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}