Skip to content

Commit 90e98c1

Browse files
committed
Include language to remove common indentation from multi-line strings
1 parent 6a39d7f commit 90e98c1

File tree

2 files changed

+62
-2
lines changed

2 files changed

+62
-2
lines changed

spec/Appendix B -- Grammar Summary.md

+3
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,9 @@ EscapedUnicode :: /[0-9A-Fa-f]{4}/
8585

8686
EscapedCharacter :: one of `"` \ `/` b f n r t
8787

88+
Note: Multi-line string values have common indentation removed with
89+
{RemoveIndentation()} when a document is interpretted.
90+
8891

8992
## Query Document
9093

spec/Section 2 -- Language.md

+59-2
Original file line numberDiff line numberDiff line change
@@ -727,6 +727,62 @@ used unescaped, enabling freeform text. Characters must all be valid
727727
characters need to be used, escape sequences must be used within standard
728728
double-quote strings.
729729

730+
Since multi-line strings are often used in indented positions, the common
731+
indentation within a multi-line string is removed along with empty initial and
732+
trailing lines.
733+
734+
For example, the following operation containing a multi-line string:
735+
736+
```graphql
737+
mutation {
738+
sendEmail(message: """
739+
Hello,
740+
World!
741+
742+
Yours,
743+
GraphQL.
744+
""")
745+
}
746+
```
747+
748+
Is identical to the escaped string:
749+
750+
```graphql
751+
mutation {
752+
sendEmail(message: "Hello,\n World!\n\nYours,\n GraphQL.")
753+
}
754+
```
755+
756+
This common indentation is removed when a document is interpretted.
757+
758+
RemoveIndentation(rawValue):
759+
760+
* Let {lines} be the result of splitting {rawValue} by {LineTerminator}.
761+
* Let {minIndent} be Infinity.
762+
* For each {line} in {lines}:
763+
* If {line} is the first item in {lines}, continue to the next line.
764+
* Let {length} be the number of characters in {line}.
765+
* Let {indent} be the number of leading consecutive {WhiteSpace} characters
766+
in {line}.
767+
* If {indent} is less than {length} and {indent} is less than {minIndent}:
768+
* Let {minIndent} be {indent}.
769+
* If {minIndent} is not Infinity:
770+
* For each {line} in {lines}:
771+
* If {line} is the first item in {lines}, continue to the next line.
772+
* Remove {minIndent} characters from the beginning of {line}.
773+
* While the first {line} in {lines} contains no characters:
774+
* Remove the first {line} from {lines}.
775+
* While the last {line} in {lines} contains no characters:
776+
* Remove the last {line} from {lines}.
777+
* Let {formatted} be the empty character sequence.
778+
* For each {line} in {lines}:
779+
* If {line} is the first item in {lines}:
780+
* Append {formatted} with {line}.
781+
* Otherwise:
782+
* Append {formatted} with a new line character (U+000A).
783+
* Append {formatted} with {line}.
784+
* Return {formatted}.
785+
730786
**Semantics**
731787

732788
StringValue :: `"` StringCharacter* `"`
@@ -736,8 +792,9 @@ StringValue :: `"` StringCharacter* `"`
736792

737793
StringValue :: `"""` MultiLineStringCharacter* `"""`
738794

739-
* Return the Unicode character sequence of all {MultiLineStringCharacter}
740-
Unicode character values (which may be empty).
795+
* Let {rawValue} be the Unicode character sequence of all
796+
{MultiLineStringCharacter} Unicode character values (which may be empty).
797+
* Return the result of {RemoveIndentation(rawValue)}.
741798

742799
MultiLineStringCharacter :: SourceCharacter but not `"""` or `\"""`
743800

0 commit comments

Comments
 (0)