codemirror-graphql
Advanced tools
Comparing version 0.5.0 to 0.5.1
364
hint.js
@@ -18,16 +18,6 @@ /** | ||
var _graphql = require('graphql'); | ||
var _utilsGetHintsAtPosition = require('./utils/getHintsAtPosition'); | ||
var _graphqlTypeIntrospection = require('graphql/type/introspection'); | ||
var _utilsGetHintsAtPosition2 = _interopRequireDefault(_utilsGetHintsAtPosition); | ||
var _utilsForEachState = require('./utils/forEachState'); | ||
var _utilsForEachState2 = _interopRequireDefault(_utilsForEachState); | ||
var _utilsHintList = require('./utils/hintList'); | ||
var _utilsHintList2 = _interopRequireDefault(_utilsHintList); | ||
require('./mode'); | ||
/** | ||
@@ -58,346 +48,10 @@ * Registers a "hint" helper for CodeMirror. | ||
var token = editor.getTokenAt(cur); | ||
var typeInfo = getTypeInfo(schema, token.state); | ||
var state = token.state; | ||
var kind = state.kind; | ||
var step = state.step; | ||
if (token.type === 'comment') { | ||
return; | ||
var results = _utilsGetHintsAtPosition2['default'](schema, editor.getValue(), cur, token); | ||
if (results.list && results.list.length > 0) { | ||
results.from = _codemirror2['default'].Pos(results.from.line, results.from.column); | ||
results.to = _codemirror2['default'].Pos(results.to.line, results.to.column); | ||
_codemirror2['default'].signal(editor, 'hasCompletion', editor, results, token); | ||
} | ||
// Definition kinds | ||
if (kind === 'Document') { | ||
return _utilsHintList2['default'](editor, options, cur, token, [{ text: 'query' }, { text: 'mutation' }, { text: 'subscription' }, { text: 'fragment' }, { text: '{' }]); | ||
} | ||
// Field names | ||
if (kind === 'SelectionSet' || kind === 'Field' || kind === 'AliasedField') { | ||
if (typeInfo.parentType) { | ||
var fields; | ||
if (typeInfo.parentType.getFields) { | ||
var fieldObj = typeInfo.parentType.getFields(); | ||
fields = Object.keys(fieldObj).map(function (fieldName) { | ||
return fieldObj[fieldName]; | ||
}); | ||
} else { | ||
fields = []; | ||
} | ||
if (_graphql.isAbstractType(typeInfo.parentType)) { | ||
fields.push(_graphqlTypeIntrospection.TypeNameMetaFieldDef); | ||
} | ||
if (typeInfo.parentType === schema.getQueryType()) { | ||
fields.push(_graphqlTypeIntrospection.SchemaMetaFieldDef, _graphqlTypeIntrospection.TypeMetaFieldDef); | ||
} | ||
return _utilsHintList2['default'](editor, options, cur, token, fields.map(function (field) { | ||
return { | ||
text: field.name, | ||
type: field.type, | ||
description: field.description | ||
}; | ||
})); | ||
} | ||
} | ||
// Argument names | ||
if (kind === 'Arguments' || kind === 'Argument' && step === 0) { | ||
var argDefs = typeInfo.argDefs; | ||
if (argDefs) { | ||
return _utilsHintList2['default'](editor, options, cur, token, argDefs.map(function (argDef) { | ||
return { | ||
text: argDef.name, | ||
type: argDef.type, | ||
description: argDef.description | ||
}; | ||
})); | ||
} | ||
} | ||
// Input Object fields | ||
if (kind === 'ObjectValue' || kind === 'ObjectField' && step === 0) { | ||
if (typeInfo.objectFieldDefs) { | ||
var objectFields = Object.keys(typeInfo.objectFieldDefs).map(function (fieldName) { | ||
return typeInfo.objectFieldDefs[fieldName]; | ||
}); | ||
return _utilsHintList2['default'](editor, options, cur, token, objectFields.map(function (field) { | ||
return { | ||
text: field.name, | ||
type: field.type, | ||
description: field.description | ||
}; | ||
})); | ||
} | ||
} | ||
// Input values: Enum and Boolean | ||
if (kind === 'EnumValue' || kind === 'ListValue' && step === 1 || kind === 'ObjectField' && step === 2 || kind === 'Argument' && step === 2) { | ||
var namedInputType = _graphql.getNamedType(typeInfo.inputType); | ||
if (namedInputType instanceof _graphql.GraphQLEnumType) { | ||
var valueMap = namedInputType.getValues(); | ||
var values = Object.keys(valueMap).map(function (valueName) { | ||
return valueMap[valueName]; | ||
}); | ||
return _utilsHintList2['default'](editor, options, cur, token, values.map(function (value) { | ||
return { | ||
text: value.name, | ||
type: namedInputType, | ||
description: value.description | ||
}; | ||
})); | ||
} else if (namedInputType === _graphql.GraphQLBoolean) { | ||
return _utilsHintList2['default'](editor, options, cur, token, [{ text: 'true', type: _graphql.GraphQLBoolean, description: 'Not false.' }, { text: 'false', type: _graphql.GraphQLBoolean, description: 'Not true.' }]); | ||
} | ||
} | ||
// Fragment type conditions | ||
if (kind === 'TypeCondition' && step === 1 || kind === 'NamedType' && state.prevState.kind === 'TypeCondition') { | ||
var possibleTypes; | ||
if (typeInfo.parentType) { | ||
possibleTypes = _graphql.isAbstractType(typeInfo.parentType) ? schema.getPossibleTypes(typeInfo.parentType) : [typeInfo.parentType]; | ||
} else { | ||
(function () { | ||
var typeMap = schema.getTypeMap(); | ||
possibleTypes = Object.keys(typeMap).map(function (typeName) { | ||
return typeMap[typeName]; | ||
}).filter(_graphql.isCompositeType); | ||
})(); | ||
} | ||
return _utilsHintList2['default'](editor, options, cur, token, possibleTypes.map(function (type) { | ||
return { | ||
text: type.name, | ||
description: type.description | ||
}; | ||
})); | ||
} | ||
// Fragment spread names | ||
if (kind === 'FragmentSpread' && step === 1) { | ||
var _ret2 = (function () { | ||
var typeMap = schema.getTypeMap(); | ||
var defState = getDefinitionState(token.state); | ||
var fragments = getFragmentDefinitions(editor); | ||
// Filter down to only the fragments which may exist here. | ||
var relevantFrags = fragments.filter(function (frag) { | ||
return( | ||
// Only include fragments with known types. | ||
typeMap[frag.typeCondition.name.value] && | ||
// Only include fragments which are not cyclic. | ||
!(defState && defState.kind === 'FragmentDefinition' && defState.name === frag.name.value) && | ||
// Only include fragments which could possibly be spread here. | ||
_graphql.doTypesOverlap(schema, typeInfo.parentType, typeMap[frag.typeCondition.name.value]) | ||
); | ||
}); | ||
return { | ||
v: _utilsHintList2['default'](editor, options, cur, token, relevantFrags.map(function (frag) { | ||
return { | ||
text: frag.name.value, | ||
type: typeMap[frag.typeCondition.name.value], | ||
description: 'fragment ' + frag.name.value + ' on ' + frag.typeCondition.name.value | ||
}; | ||
})) | ||
}; | ||
})(); | ||
if (typeof _ret2 === 'object') return _ret2.v; | ||
} | ||
// Variable definition types | ||
if (kind === 'VariableDefinition' && step === 2 || kind === 'ListType' && step === 1 || kind === 'NamedType' && (state.prevState.kind === 'VariableDefinition' || state.prevState.kind === 'ListType')) { | ||
var inputTypeMap = schema.getTypeMap(); | ||
var inputTypes = Object.keys(inputTypeMap).map(function (typeName) { | ||
return inputTypeMap[typeName]; | ||
}).filter(_graphql.isInputType); | ||
return _utilsHintList2['default'](editor, options, cur, token, inputTypes.map(function (type) { | ||
return { | ||
text: type.name, | ||
description: type.description | ||
}; | ||
})); | ||
} | ||
// Directive names | ||
if (kind === 'Directive') { | ||
var directives = schema.getDirectives().filter(function (directive) { | ||
return canUseDirective(state.prevState.kind, directive); | ||
}); | ||
return _utilsHintList2['default'](editor, options, cur, token, directives.map(function (directive) { | ||
return { | ||
text: directive.name, | ||
description: directive.description | ||
}; | ||
})); | ||
} | ||
}); | ||
function canUseDirective(kind, directive) { | ||
var locations = directive.locations; | ||
switch (kind) { | ||
case 'Query': | ||
return locations.indexOf('QUERY') !== -1; | ||
case 'Mutation': | ||
return locations.indexOf('MUTATION') !== -1; | ||
case 'Subscription': | ||
return locations.indexOf('SUBSCRIPTION') !== -1; | ||
case 'Field': | ||
return locations.indexOf('FIELD') !== -1; | ||
case 'FragmentDefinition': | ||
return locations.indexOf('FRAGMENT_DEFINITION') !== -1; | ||
case 'FragmentSpread': | ||
return locations.indexOf('FRAGMENT_SPREAD') !== -1; | ||
case 'InlineFragment': | ||
return locations.indexOf('INLINE_FRAGMENT') !== -1; | ||
} | ||
return false; | ||
} | ||
// Utility for collecting rich type information given any token's state | ||
// from the graphql-mode parser. | ||
function getTypeInfo(schema, tokenState) { | ||
var info = { | ||
type: null, | ||
parentType: null, | ||
inputType: null, | ||
directiveDef: null, | ||
fieldDef: null, | ||
argDef: null, | ||
argDefs: null, | ||
objectFieldDefs: null | ||
}; | ||
_utilsForEachState2['default'](tokenState, function (state) { | ||
switch (state.kind) { | ||
case 'Query': | ||
case 'ShortQuery': | ||
info.type = schema.getQueryType(); | ||
break; | ||
case 'Mutation': | ||
info.type = schema.getMutationType(); | ||
break; | ||
case 'Subscription': | ||
info.type = schema.getSubscriptionType(); | ||
break; | ||
case 'InlineFragment': | ||
case 'FragmentDefinition': | ||
if (state.type) { | ||
info.type = schema.getType(state.type); | ||
} | ||
break; | ||
case 'Field': | ||
info.fieldDef = info.type && state.name ? getFieldDef(schema, info.parentType, state.name) : null; | ||
info.type = info.fieldDef && info.fieldDef.type; | ||
break; | ||
case 'SelectionSet': | ||
info.parentType = _graphql.getNamedType(info.type); | ||
break; | ||
case 'Directive': | ||
info.directiveDef = state.name && schema.getDirective(state.name); | ||
break; | ||
case 'Arguments': | ||
info.argDefs = state.prevState.kind === 'Field' ? info.fieldDef && info.fieldDef.args : state.prevState.kind === 'Directive' ? info.directiveDef && info.directiveDef.args : null; | ||
break; | ||
case 'Argument': | ||
info.argDef = null; | ||
if (info.argDefs) { | ||
for (var i = 0; i < info.argDefs.length; i++) { | ||
if (info.argDefs[i].name === state.name) { | ||
info.argDef = info.argDefs[i]; | ||
break; | ||
} | ||
} | ||
} | ||
info.inputType = info.argDef && info.argDef.type; | ||
break; | ||
case 'ListValue': | ||
var nullableType = _graphql.getNullableType(info.inputType); | ||
info.inputType = nullableType instanceof _graphql.GraphQLList ? nullableType.ofType : null; | ||
break; | ||
case 'ObjectValue': | ||
var objectType = _graphql.getNamedType(info.inputType); | ||
info.objectFieldDefs = objectType instanceof _graphql.GraphQLInputObjectType ? objectType.getFields() : null; | ||
break; | ||
case 'ObjectField': | ||
var objectField = state.name && info.objectFieldDefs ? info.objectFieldDefs[state.name] : null; | ||
info.inputType = objectField && objectField.type; | ||
break; | ||
} | ||
}); | ||
return info; | ||
} | ||
// Utility for returning the state representing the Definition this token state | ||
// is within, if any. | ||
function getDefinitionState(tokenState) { | ||
var definitionState = undefined; | ||
_utilsForEachState2['default'](tokenState, function (state) { | ||
switch (state.kind) { | ||
case 'Query': | ||
case 'ShortQuery': | ||
case 'Mutation': | ||
case 'Subscription': | ||
case 'FragmentDefinition': | ||
definitionState = state; | ||
break; | ||
} | ||
}); | ||
return definitionState; | ||
} | ||
// Finds all fragment definition ASTs in a source. | ||
function getFragmentDefinitions(editor) { | ||
var fragmentDefs = []; | ||
runMode(editor, 'graphql', function (state) { | ||
if (state.kind === 'FragmentDefinition' && state.name && state.type) { | ||
fragmentDefs.push({ | ||
kind: 'FragmentDefinition', | ||
name: { | ||
kind: 'Name', | ||
value: state.name | ||
}, | ||
typeCondition: { | ||
kind: 'NamedType', | ||
name: { | ||
kind: 'Name', | ||
value: state.type | ||
} | ||
} | ||
}); | ||
} | ||
}); | ||
return fragmentDefs; | ||
} | ||
// Utility for efficiently running a codemirror mode over an editor's current | ||
// state, calling an iterFn function on each token. | ||
function runMode(editor, modeSpec, iterFn) { | ||
var mode = _codemirror2['default'].getMode(_codemirror2['default'].defaults, modeSpec); | ||
var state = _codemirror2['default'].startState(mode); | ||
editor.eachLine(function (line) { | ||
var stream = new _codemirror2['default'].StringStream(line.text); | ||
while (!stream.eol()) { | ||
var style = mode.token(stream, state); | ||
iterFn(state, style, stream); | ||
stream.start = stream.pos; | ||
} | ||
}); | ||
} | ||
// Gets the field definition given a type and field name | ||
function getFieldDef(schema, type, fieldName) { | ||
if (fieldName === _graphqlTypeIntrospection.SchemaMetaFieldDef.name && schema.getQueryType() === type) { | ||
return _graphqlTypeIntrospection.SchemaMetaFieldDef; | ||
} | ||
if (fieldName === _graphqlTypeIntrospection.TypeMetaFieldDef.name && schema.getQueryType() === type) { | ||
return _graphqlTypeIntrospection.TypeMetaFieldDef; | ||
} | ||
if (fieldName === _graphqlTypeIntrospection.TypeNameMetaFieldDef.name && _graphql.isCompositeType(type)) { | ||
return _graphqlTypeIntrospection.TypeNameMetaFieldDef; | ||
} | ||
if (type.getFields) { | ||
return type.getFields()[fieldName]; | ||
} | ||
} | ||
return results; | ||
}); |
152
mode.js
@@ -22,2 +22,4 @@ /** | ||
var _utilsRules = require('./utils/Rules'); | ||
/** | ||
@@ -46,6 +48,7 @@ * The GraphQL mode is defined as a tokenizer along with a list of rules, each | ||
eatWhitespace: function eatWhitespace(stream) { | ||
return stream.eatWhile(isIgnored); | ||
return stream.eatWhile(_utilsRules.isIgnored); | ||
}, | ||
LexRules: LexRules, | ||
ParseRules: ParseRules | ||
LexRules: _utilsRules.LexRules, | ||
ParseRules: _utilsRules.ParseRules, | ||
editorConfig: { tabSize: config.tabSize } | ||
}); | ||
@@ -56,3 +59,3 @@ | ||
startState: parser.startState, | ||
token: parser.getToken, | ||
token: parser.token, | ||
indent: indent, | ||
@@ -69,6 +72,2 @@ electricInput: /^\s*[})\]]/, | ||
var isIgnored = function isIgnored(ch) { | ||
return ch === ' ' || ch === '\t' || ch === ',' || ch === '\n' || ch === '\r' || ch === ''; | ||
}; | ||
function indent(state, textAfter) { | ||
@@ -80,139 +79,2 @@ var levels = state.levels; | ||
return level * this.config.indentUnit; | ||
} | ||
/** | ||
* The lexer rules. These are exactly as described by the spec. | ||
*/ | ||
var LexRules = { | ||
// The Name token. | ||
Name: /^[_A-Za-z][_0-9A-Za-z]*/, | ||
// All Punctuation used in GraphQL | ||
Punctuation: /^(?:!|\$|\(|\)|\.\.\.|:|=|@|\[|\]|\{|\})/, | ||
// Combines the IntValue and FloatValue tokens. | ||
Number: /^-?(?:0|(?:[1-9][0-9]*))(?:\.[0-9]*)?(?:[eE][+-]?[0-9]+)?/, | ||
// Note the closing quote is made optional as an IDE experience improvment. | ||
String: /^"(?:[^"\\]|\\(?:"|\/|\\|b|f|n|r|t|u[0-9a-fA-F]{4}))*"?/ | ||
}; | ||
/** | ||
* The parser rules. These are very close to, but not exactly the same as the | ||
* spec. Minor deviations allow for a simpler implementation. The resulting | ||
* parser can parse everything the spec declares possible. | ||
*/ | ||
var ParseRules = { | ||
Document: [_utilsOnlineParser.list('Definition')], | ||
Definition: function Definition(token) { | ||
switch (token.value) { | ||
case 'query': | ||
return 'Query'; | ||
case 'mutation': | ||
return 'Mutation'; | ||
case 'subscription': | ||
return 'Subscription'; | ||
case 'fragment': | ||
return 'FragmentDefinition'; | ||
case '{': | ||
return 'ShortQuery'; | ||
} | ||
}, | ||
// Note: instead of "Operation", these rules have been separated out. | ||
Query: [word('query'), _utilsOnlineParser.opt(name('def')), _utilsOnlineParser.opt('VariableDefinitions'), _utilsOnlineParser.list('Directive'), 'SelectionSet'], | ||
ShortQuery: ['SelectionSet'], | ||
Mutation: [word('mutation'), _utilsOnlineParser.opt(name('def')), _utilsOnlineParser.opt('VariableDefinitions'), _utilsOnlineParser.list('Directive'), 'SelectionSet'], | ||
Subscription: [word('subscription'), _utilsOnlineParser.opt(name('def')), _utilsOnlineParser.opt('VariableDefinitions'), _utilsOnlineParser.list('Directive'), 'SelectionSet'], | ||
VariableDefinitions: [_utilsOnlineParser.p('('), _utilsOnlineParser.list('VariableDefinition'), _utilsOnlineParser.p(')')], | ||
VariableDefinition: ['Variable', _utilsOnlineParser.p(':'), 'Type', _utilsOnlineParser.opt('DefaultValue')], | ||
Variable: [_utilsOnlineParser.p('$', 'variable'), name('variable')], | ||
DefaultValue: [_utilsOnlineParser.p('='), 'Value'], | ||
SelectionSet: [_utilsOnlineParser.p('{'), _utilsOnlineParser.list('Selection'), _utilsOnlineParser.p('}')], | ||
Selection: function Selection(token, stream) { | ||
return token.value === '...' ? stream.match(/[\s\u00a0,]*(on\b|@|{)/, false) ? 'InlineFragment' : 'FragmentSpread' : stream.match(/[\s\u00a0,]*:/, false) ? 'AliasedField' : 'Field'; | ||
}, | ||
// Note: this minor deviation of "AliasedField" simplifies the lookahead. | ||
AliasedField: [name('qualifier'), _utilsOnlineParser.p(':'), 'Field'], | ||
Field: [name('property'), _utilsOnlineParser.opt('Arguments'), _utilsOnlineParser.list('Directive'), _utilsOnlineParser.opt('SelectionSet')], | ||
Arguments: [_utilsOnlineParser.p('('), _utilsOnlineParser.list('Argument'), _utilsOnlineParser.p(')')], | ||
Argument: [name('attribute'), _utilsOnlineParser.p(':'), 'Value'], | ||
FragmentSpread: [_utilsOnlineParser.p('...'), name('def'), _utilsOnlineParser.list('Directive')], | ||
InlineFragment: [_utilsOnlineParser.p('...'), _utilsOnlineParser.opt('TypeCondition'), _utilsOnlineParser.list('Directive'), 'SelectionSet'], | ||
FragmentDefinition: [word('fragment'), _utilsOnlineParser.opt(_utilsOnlineParser.butNot(name('def'), [word('on')])), 'TypeCondition', _utilsOnlineParser.list('Directive'), 'SelectionSet'], | ||
TypeCondition: [word('on'), type('atom')], | ||
// Variables could be parsed in cases where only Const is expected by spec. | ||
Value: function Value(token) { | ||
switch (token.kind) { | ||
case 'Number': | ||
return 'NumberValue'; | ||
case 'String': | ||
return 'StringValue'; | ||
case 'Punctuation': | ||
switch (token.value) { | ||
case '[': | ||
return 'ListValue'; | ||
case '{': | ||
return 'ObjectValue'; | ||
case '$': | ||
return 'Variable'; | ||
} | ||
return null; | ||
case 'Name': | ||
switch (token.value) { | ||
case 'true':case 'false': | ||
return 'BooleanValue'; | ||
} | ||
return 'EnumValue'; | ||
} | ||
}, | ||
NumberValue: [_utilsOnlineParser.t('Number', 'number')], | ||
StringValue: [_utilsOnlineParser.t('String', 'string')], | ||
BooleanValue: [_utilsOnlineParser.t('Name', 'builtin')], | ||
EnumValue: [name('string-2')], | ||
ListValue: [_utilsOnlineParser.p('['), _utilsOnlineParser.list('Value'), _utilsOnlineParser.p(']')], | ||
ObjectValue: [_utilsOnlineParser.p('{'), _utilsOnlineParser.list('ObjectField'), _utilsOnlineParser.p('}')], | ||
ObjectField: [name('attribute'), _utilsOnlineParser.p(':'), 'Value'], | ||
Type: function Type(token) { | ||
return token.value === '[' ? 'ListType' : 'NamedType'; | ||
}, | ||
// NonNullType has been merged into ListType and NamedType to simplify. | ||
ListType: [_utilsOnlineParser.p('['), 'NamedType', _utilsOnlineParser.p(']'), _utilsOnlineParser.opt(_utilsOnlineParser.p('!'))], | ||
NamedType: [name('atom'), _utilsOnlineParser.opt(_utilsOnlineParser.p('!'))], | ||
Directive: [_utilsOnlineParser.p('@', 'meta'), name('meta'), _utilsOnlineParser.opt('Arguments')] | ||
}; | ||
// A keyword Token. | ||
function word(value) { | ||
return { | ||
style: 'keyword', | ||
match: function match(token) { | ||
return token.kind === 'Name' && token.value === value; | ||
} | ||
}; | ||
} | ||
// A Name Token which will decorate the state with a `name`. | ||
function name(style) { | ||
return { | ||
style: style, | ||
match: function match(token) { | ||
return token.kind === 'Name'; | ||
}, | ||
update: function update(state, token) { | ||
state.name = token.value; | ||
} | ||
}; | ||
} | ||
// A Name Token which will decorate the previous state with a `type`. | ||
function type(style) { | ||
return { | ||
style: style, | ||
match: function match(token) { | ||
return token.kind === 'Name'; | ||
}, | ||
update: function update(state, token) { | ||
state.prevState.type = token.value; | ||
} | ||
}; | ||
} |
{ | ||
"name": "codemirror-graphql", | ||
"version": "0.5.0", | ||
"version": "0.5.1", | ||
"description": "GraphQL mode and helpers for CodeMirror.", | ||
@@ -51,3 +51,3 @@ "contributors": [ | ||
"peerDependencies": { | ||
"graphql": "^0.5.0", | ||
"graphql": "^0.6.0", | ||
"codemirror": "^5.6.0" | ||
@@ -54,0 +54,0 @@ }, |
@@ -10,2 +10,3 @@ /** | ||
// Create the expected hint response given a possible list and a token | ||
'use strict'; | ||
@@ -16,11 +17,3 @@ | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } | ||
var _codemirror = require('codemirror'); | ||
var _codemirror2 = _interopRequireDefault(_codemirror); | ||
// Create the expected hint response given a possible list and a token | ||
function hintList(editor, options, cursor, token, list) { | ||
function hintList(cursor, token, list) { | ||
var hints = filterAndSortList(list, normalizeText(token.string)); | ||
@@ -35,8 +28,6 @@ if (!hints) { | ||
list: hints, | ||
from: _codemirror2['default'].Pos(cursor.line, tokenStart), | ||
to: _codemirror2['default'].Pos(cursor.line, token.end) | ||
from: { line: cursor.line, column: tokenStart }, | ||
to: { line: cursor.line, column: token.end } | ||
}; | ||
_codemirror2['default'].signal(editor, 'hasCompletion', editor, results, token); | ||
return results; | ||
@@ -43,0 +34,0 @@ } |
@@ -217,3 +217,2 @@ /** | ||
while (code !== 34 && code > 31) { | ||
ch(); | ||
if (code === 92) { | ||
@@ -247,2 +246,4 @@ // \ | ||
throw syntaxError('Unterminated string.'); | ||
} else { | ||
ch(); | ||
} | ||
@@ -249,0 +250,0 @@ } |
@@ -16,2 +16,7 @@ /** | ||
* | ||
* eatWhitespace: ( | ||
* stream: Stream | CodeMirror.StringStream | CharacterStream | ||
* ) => boolean | ||
* Use CodeMirror API. | ||
* | ||
* LexRules: { [name: string]: RegExp }, Includes `Punctuation`. | ||
@@ -21,5 +26,7 @@ * | ||
* | ||
* eatWhitespace: (stream: CodeMirrorStream) => boolean, Use CodeMirror API. | ||
* editorConfig: { [name: string]: mixed }, Provides an editor-specific | ||
* configurations set. | ||
* | ||
*/ | ||
'use strict'; | ||
@@ -29,81 +36,22 @@ | ||
exports['default'] = onlineParser; | ||
exports.opt = opt; | ||
exports.list = list; | ||
exports.butNot = butNot; | ||
exports.t = t; | ||
exports.p = p; | ||
function onlineParser(options) { | ||
var eatWhitespace = options.eatWhitespace; | ||
var LexRules = options.LexRules; | ||
var ParseRules = options.ParseRules; | ||
return { | ||
startState: function startState() { | ||
var initialState = { level: 0 }; | ||
pushRule(ParseRules, initialState, 'Document'); | ||
pushRule(options.ParseRules, initialState, 'Document'); | ||
return initialState; | ||
}, | ||
getToken: (function (_getToken) { | ||
function getToken(_x, _x2) { | ||
return _getToken.apply(this, arguments); | ||
} | ||
getToken.toString = function () { | ||
return _getToken.toString(); | ||
}; | ||
return getToken; | ||
})(function (stream, state) { | ||
return getToken(eatWhitespace, LexRules, ParseRules, this, stream, state); | ||
}) | ||
token: function token(stream, state) { | ||
return getToken(stream, state, options); | ||
} | ||
}; | ||
} | ||
// These functions help build matching rules for ParseRules. | ||
function getToken(stream, state, options) { | ||
var LexRules = options.LexRules; | ||
var ParseRules = options.ParseRules; | ||
var eatWhitespace = options.eatWhitespace; | ||
var editorConfig = options.editorConfig; | ||
// An optional rule. | ||
function opt(ofRule) { | ||
return { ofRule: ofRule }; | ||
} | ||
// A list of another rule. | ||
function list(ofRule, separator) { | ||
return { ofRule: ofRule, isList: true, separator: separator }; | ||
} | ||
// An constraint described as `but not` in the GraphQL spec. | ||
function butNot(rule, exclusions) { | ||
var ruleMatch = rule.match; | ||
rule.match = function (token) { | ||
return ruleMatch(token) && exclusions.every(function (exclusion) { | ||
return !exclusion.match(token); | ||
}); | ||
}; | ||
return rule; | ||
} | ||
// Token of a kind | ||
function t(kind, style) { | ||
return { style: style, match: function match(token) { | ||
return token.kind === kind; | ||
} }; | ||
} | ||
// Punctuator | ||
function p(value, style) { | ||
return { | ||
style: style || 'punctuation', | ||
match: function match(token) { | ||
return token.kind === 'Punctuation' && token.value === value; | ||
} | ||
}; | ||
} | ||
function getToken(eatWhitespace, LexRules, ParseRules, editor, stream, state) { | ||
if (state.needsAdvance) { | ||
@@ -116,3 +64,4 @@ state.needsAdvance = false; | ||
if (stream.sol()) { | ||
state.indentLevel = Math.floor(stream.indentation() / editor.config.tabSize); | ||
var tabSize = editorConfig && editorConfig.tabSize || 2; | ||
state.indentLevel = Math.floor(stream.indentation() / tabSize); | ||
} | ||
@@ -125,4 +74,4 @@ | ||
// Tokenize line comment | ||
if (editor.lineComment && stream.match(editor.lineComment)) { | ||
// Peek a character forward and skip the entire line if it's a comment line | ||
if (stream.peek() === '#') { | ||
stream.skipToEnd(); | ||
@@ -132,3 +81,3 @@ return 'comment'; | ||
// Lex a token from the stream | ||
// Get a matched token from the stream, using lex | ||
var token = lex(LexRules, stream); | ||
@@ -321,2 +270,3 @@ | ||
} | ||
} | ||
} | ||
module.exports = exports['default']; |
@@ -28,4 +28,2 @@ /** | ||
require('./mode'); | ||
/** | ||
@@ -51,2 +49,14 @@ * Registers a "hint" helper for CodeMirror. | ||
var token = editor.getTokenAt(cur); | ||
var results = getVariablesHint(cur, token, options); | ||
if (results.list && results.list.length > 0) { | ||
results.from = _codemirror2['default'].Pos(results.from.line, results.from.column); | ||
results.to = _codemirror2['default'].Pos(results.to.line, results.to.column); | ||
_codemirror2['default'].signal(editor, 'hasCompletion', editor, results, token); | ||
} | ||
return results; | ||
}); | ||
function getVariablesHint(cur, token, options) { | ||
var state = token.state; | ||
@@ -58,3 +68,3 @@ var kind = state.kind; | ||
if (kind === 'Document' && step === 0) { | ||
return _utilsHintList2['default'](editor, options, cur, token, [{ text: '{' }]); | ||
return _utilsHintList2['default'](cur, token, [{ text: '{' }]); | ||
} | ||
@@ -72,3 +82,3 @@ | ||
var variableNames = Object.keys(variableToType); | ||
return _utilsHintList2['default'](editor, options, cur, token, variableNames.map(function (name) { | ||
return _utilsHintList2['default'](cur, token, variableNames.map(function (name) { | ||
return { | ||
@@ -87,3 +97,3 @@ text: '"' + name + '": ', | ||
}); | ||
return _utilsHintList2['default'](editor, options, cur, token, inputFields.map(function (field) { | ||
return _utilsHintList2['default'](cur, token, inputFields.map(function (field) { | ||
return { | ||
@@ -104,3 +114,3 @@ text: '"' + field.name + '": ', | ||
return { | ||
v: _utilsHintList2['default'](editor, options, cur, token, [{ text: '{' }]) | ||
v: _utilsHintList2['default'](cur, token, [{ text: '{' }]) | ||
}; | ||
@@ -115,3 +125,3 @@ } else if (namedInputType instanceof _graphql.GraphQLEnumType) { | ||
v: { | ||
v: _utilsHintList2['default'](editor, options, cur, token, values.map(function (value) { | ||
v: _utilsHintList2['default'](cur, token, values.map(function (value) { | ||
return { | ||
@@ -130,3 +140,3 @@ text: '"' + value.name + '"', | ||
return { | ||
v: _utilsHintList2['default'](editor, options, cur, token, [{ text: 'true', type: _graphql.GraphQLBoolean, description: 'Not false.' }, { text: 'false', type: _graphql.GraphQLBoolean, description: 'Not true.' }]) | ||
v: _utilsHintList2['default'](cur, token, [{ text: 'true', type: _graphql.GraphQLBoolean, description: 'Not false.' }, { text: 'false', type: _graphql.GraphQLBoolean, description: 'Not true.' }]) | ||
}; | ||
@@ -138,3 +148,3 @@ } | ||
} | ||
}); | ||
} | ||
@@ -141,0 +151,0 @@ // Utility for collecting rich type information given any token's state |
@@ -22,2 +22,4 @@ /** | ||
var _utilsRuleHelpers = require('../utils/RuleHelpers'); | ||
/** | ||
@@ -33,3 +35,4 @@ * This mode defines JSON, but provides a data-laden parser state to enable | ||
LexRules: LexRules, | ||
ParseRules: ParseRules | ||
ParseRules: ParseRules, | ||
editorConfig: { tabSize: config.tabSize } | ||
}); | ||
@@ -40,3 +43,3 @@ | ||
startState: parser.startState, | ||
token: parser.getToken, | ||
token: parser.token, | ||
indent: indent, | ||
@@ -81,4 +84,4 @@ electricInput: /^\s*[}\]]/, | ||
var ParseRules = { | ||
Document: [_utilsOnlineParser.p('{'), _utilsOnlineParser.list('Variable', _utilsOnlineParser.p(',')), _utilsOnlineParser.p('}')], | ||
Variable: [namedKey('variable'), _utilsOnlineParser.p(':'), 'Value'], | ||
Document: [_utilsRuleHelpers.p('{'), _utilsRuleHelpers.list('Variable', _utilsRuleHelpers.p(',')), _utilsRuleHelpers.p('}')], | ||
Variable: [namedKey('variable'), _utilsRuleHelpers.p(':'), 'Value'], | ||
Value: function Value(token) { | ||
@@ -108,9 +111,9 @@ switch (token.kind) { | ||
}, | ||
NumberValue: [_utilsOnlineParser.t('Number', 'number')], | ||
StringValue: [_utilsOnlineParser.t('String', 'string')], | ||
BooleanValue: [_utilsOnlineParser.t('Keyword', 'builtin')], | ||
NullValue: [_utilsOnlineParser.t('Keyword', 'keyword')], | ||
ListValue: [_utilsOnlineParser.p('['), _utilsOnlineParser.list('Value', _utilsOnlineParser.p(',')), _utilsOnlineParser.p(']')], | ||
ObjectValue: [_utilsOnlineParser.p('{'), _utilsOnlineParser.list('ObjectField', _utilsOnlineParser.p(',')), _utilsOnlineParser.p('}')], | ||
ObjectField: [namedKey('attribute'), _utilsOnlineParser.p(':'), 'Value'] | ||
NumberValue: [_utilsRuleHelpers.t('Number', 'number')], | ||
StringValue: [_utilsRuleHelpers.t('String', 'string')], | ||
BooleanValue: [_utilsRuleHelpers.t('Keyword', 'builtin')], | ||
NullValue: [_utilsRuleHelpers.t('Keyword', 'keyword')], | ||
ListValue: [_utilsRuleHelpers.p('['), _utilsRuleHelpers.list('Value', _utilsRuleHelpers.p(',')), _utilsRuleHelpers.p(']')], | ||
ObjectValue: [_utilsRuleHelpers.p('{'), _utilsRuleHelpers.list('ObjectField', _utilsRuleHelpers.p(',')), _utilsRuleHelpers.p('}')], | ||
ObjectField: [namedKey('attribute'), _utilsRuleHelpers.p(':'), 'Value'] | ||
}; | ||
@@ -117,0 +120,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No README
QualityPackage does not have a README. This may indicate a failed publish or a low quality package.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
73671
20
2025
1
0