Skip to content

Commit 361cb40

Browse files
authored
RFC: Block String (#327)
This RFC adds a new form of `StringValue`, the multi-line string, similar to that found in Coffeescript, Python, and Scala. A block string starts and ends with a triple-quote: ``` """This is a triple-quoted string and it can contain multiple lines""" ``` Block strings are useful for typing literal bodies of text where new lines should be interpreted literally. In fact, the only escape sequence used is `\"""` and `\` is otherwise allowed unescaped. This is beneficial when writing documentation within strings which may reference the back-slash often: ``` """ In a block string \n and C:\ are unescaped. """ ``` The primary value of block strings are to write long-form input directly in query text, in tools like GraphiQL, and as a prerequisite to another pending RFC to allow docstring style documentation in the Schema Definition Language.
1 parent 92b41db commit 361cb40

File tree

2 files changed

+98
-10
lines changed

2 files changed

+98
-10
lines changed

spec/Appendix B -- Grammar Summary.md

+9-2
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,8 @@ ExponentIndicator :: one of `e` `E`
6969
Sign :: one of + -
7070

7171
StringValue ::
72-
- `""`
73-
- `"` StringCharacter+ `"`
72+
- `"` StringCharacter* `"`
73+
- `"""` BlockStringCharacter* `"""`
7474

7575
StringCharacter ::
7676
- SourceCharacter but not `"` or \ or LineTerminator
@@ -81,6 +81,13 @@ EscapedUnicode :: /[0-9A-Fa-f]{4}/
8181

8282
EscapedCharacter :: one of `"` \ `/` b f n r t
8383

84+
BlockStringCharacter ::
85+
- SourceCharacter but not `"""` or `\"""`
86+
- `\"""`
87+
88+
Note: Block string values are interpretted to exclude blank initial and trailing
89+
lines and uniform indentation with {BlockStringValue()}.
90+
8491

8592
## Query Document
8693

spec/Section 2 -- Language.md

+89-8
Original file line numberDiff line numberDiff line change
@@ -694,8 +694,8 @@ The two keywords `true` and `false` represent the two boolean values.
694694
### String Value
695695

696696
StringValue ::
697-
- `""`
698-
- `"` StringCharacter+ `"`
697+
- `"` StringCharacter* `"`
698+
- `"""` BlockStringCharacter* `"""`
699699

700700
StringCharacter ::
701701
- SourceCharacter but not `"` or \ or LineTerminator
@@ -706,24 +706,61 @@ EscapedUnicode :: /[0-9A-Fa-f]{4}/
706706

707707
EscapedCharacter :: one of `"` \ `/` b f n r t
708708

709+
BlockStringCharacter ::
710+
- SourceCharacter but not `"""` or `\"""`
711+
- `\"""`
712+
709713
Strings are sequences of characters wrapped in double-quotes (`"`). (ex.
710714
`"Hello World"`). White space and other otherwise-ignored characters are
711715
significant within a string value.
712716

713717
Note: Unicode characters are allowed within String value literals, however
714-
GraphQL source must not contain some ASCII control characters so escape
718+
{SourceCharacter} must not contain some ASCII control characters so escape
715719
sequences must be used to represent these characters.
716720

717-
**Semantics**
721+
**Block Strings**
722+
723+
Block strings are sequences of characters wrapped in triple-quotes (`"""`).
724+
White space, line terminators, quote, and backslash characters may all be
725+
used unescaped to enable verbatim text. Characters must all be valid
726+
{SourceCharacter}.
727+
728+
Since block strings represent freeform text often used in indented
729+
positions, the string value semantics of a block string excludes uniform
730+
indentation and blank initial and trailing lines via {BlockStringValue()}.
731+
732+
For example, the following operation containing a block string:
733+
734+
```graphql
735+
mutation {
736+
sendEmail(message: """
737+
Hello,
738+
World!
739+
740+
Yours,
741+
GraphQL.
742+
""")
743+
}
744+
```
745+
746+
Is identical to the standard quoted string:
718747

719-
StringValue :: `""`
748+
```graphql
749+
mutation {
750+
sendEmail(message: "Hello,\n World!\n\nYours,\n GraphQL.")
751+
}
752+
```
720753

721-
* Return an empty Unicode character sequence.
754+
Note: If non-printable ASCII characters are needed in a string value, a standard
755+
quoted string with appropriate escape sequences must be used instead of a
756+
block string.
722757

723-
StringValue :: `"` StringCharacter+ `"`
758+
**Semantics**
759+
760+
StringValue :: `"` StringCharacter* `"`
724761

725762
* Return the Unicode character sequence of all {StringCharacter}
726-
Unicode character values.
763+
Unicode character values (which may be an empty sequence).
727764

728765
StringCharacter :: SourceCharacter but not `"` or \ or LineTerminator
729766

@@ -749,6 +786,50 @@ StringCharacter :: \ EscapedCharacter
749786
| `r` | U+000D | carriage return |
750787
| `t` | U+0009 | horizontal tab |
751788

789+
StringValue :: `"""` BlockStringCharacter* `"""`
790+
791+
* Let {rawValue} be the Unicode character sequence of all
792+
{BlockStringCharacter} Unicode character values (which may be an empty
793+
sequence).
794+
* Return the result of {BlockStringValue(rawValue)}.
795+
796+
BlockStringCharacter :: SourceCharacter but not `"""` or `\"""`
797+
798+
* Return the character value of {SourceCharacter}.
799+
800+
BlockStringCharacter :: `\"""`
801+
802+
* Return the character sequence `"""`.
803+
804+
BlockStringValue(rawValue):
805+
806+
* Let {lines} be the result of splitting {rawValue} by {LineTerminator}.
807+
* Let {commonIndent} be {null}.
808+
* For each {line} in {lines}:
809+
* If {line} is the first item in {lines}, continue to the next line.
810+
* Let {length} be the number of characters in {line}.
811+
* Let {indent} be the number of leading consecutive {WhiteSpace} characters
812+
in {line}.
813+
* If {indent} is less than {length}:
814+
* If {commonIndent} is {null} or {indent} is less than {commonIndent}:
815+
* Let {commonIndent} be {indent}.
816+
* If {commonIndent} is not {null}:
817+
* For each {line} in {lines}:
818+
* If {line} is the first item in {lines}, continue to the next line.
819+
* Remove {commonIndent} characters from the beginning of {line}.
820+
* While the first item {line} in {lines} contains only {WhiteSpace}:
821+
* Remove the first item from {lines}.
822+
* While the last item {line} in {lines} contains only {WhiteSpace}:
823+
* Remove the last item from {lines}.
824+
* Let {formatted} be the empty character sequence.
825+
* For each {line} in {lines}:
826+
* If {line} is the first item in {lines}:
827+
* Append {formatted} with {line}.
828+
* Otherwise:
829+
* Append {formatted} with a line feed character (U+000A).
830+
* Append {formatted} with {line}.
831+
* Return {formatted}.
832+
752833

753834
### Null Value
754835

0 commit comments

Comments
 (0)