blockstring.go

 1package lexer
 2
 3import (
 4	"math"
 5	"strings"
 6)
 7
 8// blockStringValue produces the value of a block string from its parsed raw value, similar to
 9// Coffeescript's block string, Python's docstring trim or Ruby's strip_heredoc.
10//
11// This implements the GraphQL spec's BlockStringValue() static algorithm.
12func blockStringValue(raw string) string {
13	lines := strings.Split(raw, "\n")
14
15	commonIndent := math.MaxInt32
16	for _, line := range lines {
17		indent := leadingWhitespace(line)
18		if indent < len(line) && indent < commonIndent {
19			commonIndent = indent
20			if commonIndent == 0 {
21				break
22			}
23		}
24	}
25
26	if commonIndent != math.MaxInt32 && len(lines) > 0 {
27		for i := 1; i < len(lines); i++ {
28			if len(lines[i]) < commonIndent {
29				lines[i] = ""
30			} else {
31				lines[i] = lines[i][commonIndent:]
32			}
33		}
34	}
35
36	start := 0
37	end := len(lines)
38
39	for start < end && leadingWhitespace(lines[start]) == math.MaxInt32 {
40		start++
41	}
42
43	for start < end && leadingWhitespace(lines[end-1]) == math.MaxInt32 {
44		end--
45	}
46
47	return strings.Join(lines[start:end], "\n")
48}
49
50func leadingWhitespace(str string) int {
51	for i, r := range str {
52		if r != ' ' && r != '\t' {
53			return i
54		}
55	}
56	// this line is made up entirely of whitespace, its leading whitespace doesnt count.
57	return math.MaxInt32
58}