Skip to content

Commit

Permalink
RFC: Block String (#327)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
leebyron committed Nov 30, 2017
1 parent 92b41db commit 361cb40
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 10 deletions.
11 changes: 9 additions & 2 deletions spec/Appendix B -- Grammar Summary.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,8 @@ ExponentIndicator :: one of `e` `E`
Sign :: one of + -

StringValue ::
- `""`
- `"` StringCharacter+ `"`
- `"` StringCharacter* `"`
- `"""` BlockStringCharacter* `"""`

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

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

BlockStringCharacter ::
- SourceCharacter but not `"""` or `\"""`
- `\"""`

Note: Block string values are interpretted to exclude blank initial and trailing
lines and uniform indentation with {BlockStringValue()}.


## Query Document

Expand Down
97 changes: 89 additions & 8 deletions spec/Section 2 -- Language.md
Original file line number Diff line number Diff line change
Expand Up @@ -694,8 +694,8 @@ The two keywords `true` and `false` represent the two boolean values.
### String Value

StringValue ::
- `""`
- `"` StringCharacter+ `"`
- `"` StringCharacter* `"`
- `"""` BlockStringCharacter* `"""`

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

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

BlockStringCharacter ::
- SourceCharacter but not `"""` or `\"""`
- `\"""`

Strings are sequences of characters wrapped in double-quotes (`"`). (ex.
`"Hello World"`). White space and other otherwise-ignored characters are
significant within a string value.

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

**Semantics**
**Block Strings**

Block strings are sequences of characters wrapped in triple-quotes (`"""`).
White space, line terminators, quote, and backslash characters may all be
used unescaped to enable verbatim text. Characters must all be valid
{SourceCharacter}.

Since block strings represent freeform text often used in indented
positions, the string value semantics of a block string excludes uniform
indentation and blank initial and trailing lines via {BlockStringValue()}.

For example, the following operation containing a block string:

```graphql
mutation {
sendEmail(message: """
Hello,
World!
Yours,
GraphQL.
""")
}
```

Is identical to the standard quoted string:

StringValue :: `""`
```graphql
mutation {
sendEmail(message: "Hello,\n World!\n\nYours,\n GraphQL.")
}
```

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

StringValue :: `"` StringCharacter+ `"`
**Semantics**

StringValue :: `"` StringCharacter* `"`

* Return the Unicode character sequence of all {StringCharacter}
Unicode character values.
Unicode character values (which may be an empty sequence).

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

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

StringValue :: `"""` BlockStringCharacter* `"""`

* Let {rawValue} be the Unicode character sequence of all
{BlockStringCharacter} Unicode character values (which may be an empty
sequence).
* Return the result of {BlockStringValue(rawValue)}.

BlockStringCharacter :: SourceCharacter but not `"""` or `\"""`

* Return the character value of {SourceCharacter}.

BlockStringCharacter :: `\"""`

* Return the character sequence `"""`.

BlockStringValue(rawValue):

* Let {lines} be the result of splitting {rawValue} by {LineTerminator}.
* Let {commonIndent} be {null}.
* For each {line} in {lines}:
* If {line} is the first item in {lines}, continue to the next line.
* Let {length} be the number of characters in {line}.
* Let {indent} be the number of leading consecutive {WhiteSpace} characters
in {line}.
* If {indent} is less than {length}:
* If {commonIndent} is {null} or {indent} is less than {commonIndent}:
* Let {commonIndent} be {indent}.
* If {commonIndent} is not {null}:
* For each {line} in {lines}:
* If {line} is the first item in {lines}, continue to the next line.
* Remove {commonIndent} characters from the beginning of {line}.
* While the first item {line} in {lines} contains only {WhiteSpace}:
* Remove the first item from {lines}.
* While the last item {line} in {lines} contains only {WhiteSpace}:
* Remove the last item from {lines}.
* Let {formatted} be the empty character sequence.
* For each {line} in {lines}:
* If {line} is the first item in {lines}:
* Append {formatted} with {line}.
* Otherwise:
* Append {formatted} with a line feed character (U+000A).
* Append {formatted} with {line}.
* Return {formatted}.


### Null Value

Expand Down

0 comments on commit 361cb40

Please sign in to comment.