UNPKG

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