UNPKG

3.01 kBJavaScriptView Raw
1'use strict';
2
3Object.defineProperty(exports, '__esModule', {
4 value: true,
5});
6exports.stripIgnoredCharacters = stripIgnoredCharacters;
7
8var _blockString = require('../language/blockString.js');
9
10var _lexer = require('../language/lexer.js');
11
12var _source = require('../language/source.js');
13
14var _tokenKind = require('../language/tokenKind.js');
15
16/**
17 * Strips characters that are not significant to the validity or execution
18 * of a GraphQL document:
19 * - UnicodeBOM
20 * - WhiteSpace
21 * - LineTerminator
22 * - Comment
23 * - Comma
24 * - BlockString indentation
25 *
26 * Note: It is required to have a delimiter character between neighboring
27 * non-punctuator tokens and this function always uses single space as delimiter.
28 *
29 * It is guaranteed that both input and output documents if parsed would result
30 * in the exact same AST except for nodes location.
31 *
32 * Warning: It is guaranteed that this function will always produce stable results.
33 * However, it's not guaranteed that it will stay the same between different
34 * releases due to bugfixes or changes in the GraphQL specification.
35 *
36 * Query example:
37 *
38 * ```graphql
39 * query SomeQuery($foo: String!, $bar: String) {
40 * someField(foo: $foo, bar: $bar) {
41 * a
42 * b {
43 * c
44 * d
45 * }
46 * }
47 * }
48 * ```
49 *
50 * Becomes:
51 *
52 * ```graphql
53 * query SomeQuery($foo:String!$bar:String){someField(foo:$foo bar:$bar){a b{c d}}}
54 * ```
55 *
56 * SDL example:
57 *
58 * ```graphql
59 * """
60 * Type description
61 * """
62 * type Foo {
63 * """
64 * Field description
65 * """
66 * bar: String
67 * }
68 * ```
69 *
70 * Becomes:
71 *
72 * ```graphql
73 * """Type description""" type Foo{"""Field description""" bar:String}
74 * ```
75 */
76function stripIgnoredCharacters(source) {
77 const sourceObj = (0, _source.isSource)(source)
78 ? source
79 : new _source.Source(source);
80 const body = sourceObj.body;
81 const lexer = new _lexer.Lexer(sourceObj);
82 let strippedBody = '';
83 let wasLastAddedTokenNonPunctuator = false;
84
85 while (lexer.advance().kind !== _tokenKind.TokenKind.EOF) {
86 const currentToken = lexer.token;
87 const tokenKind = currentToken.kind;
88 /**
89 * Every two non-punctuator tokens should have space between them.
90 * Also prevent case of non-punctuator token following by spread resulting
91 * in invalid token (e.g. `1...` is invalid Float token).
92 */
93
94 const isNonPunctuator = !(0, _lexer.isPunctuatorTokenKind)(
95 currentToken.kind,
96 );
97
98 if (wasLastAddedTokenNonPunctuator) {
99 if (
100 isNonPunctuator ||
101 currentToken.kind === _tokenKind.TokenKind.SPREAD
102 ) {
103 strippedBody += ' ';
104 }
105 }
106
107 const tokenBody = body.slice(currentToken.start, currentToken.end);
108
109 if (tokenKind === _tokenKind.TokenKind.BLOCK_STRING) {
110 strippedBody += (0, _blockString.printBlockString)(currentToken.value, {
111 minimize: true,
112 });
113 } else {
114 strippedBody += tokenBody;
115 }
116
117 wasLastAddedTokenNonPunctuator = isNonPunctuator;
118 }
119
120 return strippedBody;
121}