blob: dca0c32f0f0ffe9ee3fc443c65cb07a9b5115c08 [file] [log] [blame]
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.stripIgnoredCharacters = stripIgnoredCharacters;
var _inspect = _interopRequireDefault(require("../jsutils/inspect"));
var _source = require("../language/source");
var _tokenKind = require("../language/tokenKind");
var _lexer = require("../language/lexer");
var _blockString = require("../language/blockString");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* Strips characters that are not significant to the validity or execution
* of a GraphQL document:
* - UnicodeBOM
* - WhiteSpace
* - LineTerminator
* - Comment
* - Comma
* - BlockString indentation
*
* Note: It is required to have a delimiter character between neighboring
* non-punctuator tokens and this function always uses single space as delimiter.
*
* It is guaranteed that both input and output documents if parsed would result
* in the exact same AST except for nodes location.
*
* Warning: It is guaranteed that this function will always produce stable results.
* However, it's not guaranteed that it will stay the same between different
* releases due to bugfixes or changes in the GraphQL specification.
*
* Query example:
*
* query SomeQuery($foo: String!, $bar: String) {
* someField(foo: $foo, bar: $bar) {
* a
* b {
* c
* d
* }
* }
* }
*
* Becomes:
*
* query SomeQuery($foo:String!$bar:String){someField(foo:$foo bar:$bar){a b{c d}}}
*
* SDL example:
*
* """
* Type description
* """
* type Foo {
* """
* Field description
* """
* bar: String
* }
*
* Becomes:
*
* """Type description""" type Foo{"""Field description""" bar:String}
*/
function stripIgnoredCharacters(source) {
var sourceObj = typeof source === 'string' ? new _source.Source(source) : source;
if (!(sourceObj instanceof _source.Source)) {
throw new TypeError("Must provide string or Source. Received: ".concat((0, _inspect.default)(sourceObj), "."));
}
var body = sourceObj.body;
var lexer = new _lexer.Lexer(sourceObj);
var strippedBody = '';
var wasLastAddedTokenNonPunctuator = false;
while (lexer.advance().kind !== _tokenKind.TokenKind.EOF) {
var currentToken = lexer.token;
var tokenKind = currentToken.kind;
/**
* Every two non-punctuator tokens should have space between them.
* Also prevent case of non-punctuator token following by spread resulting
* in invalid token (e.g. `1...` is invalid Float token).
*/
var isNonPunctuator = !(0, _lexer.isPunctuatorTokenKind)(currentToken.kind);
if (wasLastAddedTokenNonPunctuator) {
if (isNonPunctuator || currentToken.kind === _tokenKind.TokenKind.SPREAD) {
strippedBody += ' ';
}
}
var tokenBody = body.slice(currentToken.start, currentToken.end);
if (tokenKind === _tokenKind.TokenKind.BLOCK_STRING) {
strippedBody += dedentBlockString(tokenBody);
} else {
strippedBody += tokenBody;
}
wasLastAddedTokenNonPunctuator = isNonPunctuator;
}
return strippedBody;
}
function dedentBlockString(blockStr) {
// skip leading and trailing triple quotations
var rawStr = blockStr.slice(3, -3);
var body = (0, _blockString.dedentBlockStringValue)(rawStr);
var lines = body.split(/\r\n|[\n\r]/g);
if ((0, _blockString.getBlockStringIndentation)(lines) > 0) {
body = '\n' + body;
}
var lastChar = body[body.length - 1];
var hasTrailingQuote = lastChar === '"' && body.slice(-4) !== '\\"""';
if (hasTrailingQuote || lastChar === '\\') {
body += '\n';
}
return '"""' + body + '"""';
}