123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658 |
- // CodeMirror, copyright (c) by Marijn Haverbeke and others
- // Distributed under an MIT license: https://codemirror.net/LICENSE
- ;(function (mod) {
- if (typeof exports == 'object' && typeof module == 'object')
- // CommonJS
- mod(require('../../lib/codemirror'))
- else if (typeof define == 'function' && define.amd)
- // AMD
- define(['../../lib/codemirror'], mod)
- // Plain browser env
- else mod(CodeMirror)
- })(function (CodeMirror) {
- 'use strict'
- CodeMirror.defineMode('xquery', function () {
- // The keywords object is set to the result of this self executing
- // function. Each keyword is a property of the keywords object whose
- // value is {type: atype, style: astyle}
- var keywords = (function () {
- // convenience functions used to build keywords object
- function kw(type) {
- return { type: type, style: 'keyword' }
- }
- var operator = kw('operator'),
- atom = { type: 'atom', style: 'atom' },
- punctuation = { type: 'punctuation', style: null },
- qualifier = { type: 'axis_specifier', style: 'qualifier' }
- // kwObj is what is return from this function at the end
- var kwObj = {
- ',': punctuation,
- }
- // a list of 'basic' keywords. For each add a property to kwObj with the value of
- // {type: basic[i], style: "keyword"} e.g. 'after' --> {type: "after", style: "keyword"}
- var basic = [
- 'after',
- 'all',
- 'allowing',
- 'ancestor',
- 'ancestor-or-self',
- 'any',
- 'array',
- 'as',
- 'ascending',
- 'at',
- 'attribute',
- 'base-uri',
- 'before',
- 'boundary-space',
- 'by',
- 'case',
- 'cast',
- 'castable',
- 'catch',
- 'child',
- 'collation',
- 'comment',
- 'construction',
- 'contains',
- 'content',
- 'context',
- 'copy',
- 'copy-namespaces',
- 'count',
- 'decimal-format',
- 'declare',
- 'default',
- 'delete',
- 'descendant',
- 'descendant-or-self',
- 'descending',
- 'diacritics',
- 'different',
- 'distance',
- 'document',
- 'document-node',
- 'element',
- 'else',
- 'empty',
- 'empty-sequence',
- 'encoding',
- 'end',
- 'entire',
- 'every',
- 'exactly',
- 'except',
- 'external',
- 'first',
- 'following',
- 'following-sibling',
- 'for',
- 'from',
- 'ftand',
- 'ftnot',
- 'ft-option',
- 'ftor',
- 'function',
- 'fuzzy',
- 'greatest',
- 'group',
- 'if',
- 'import',
- 'in',
- 'inherit',
- 'insensitive',
- 'insert',
- 'instance',
- 'intersect',
- 'into',
- 'invoke',
- 'is',
- 'item',
- 'language',
- 'last',
- 'lax',
- 'least',
- 'let',
- 'levels',
- 'lowercase',
- 'map',
- 'modify',
- 'module',
- 'most',
- 'namespace',
- 'next',
- 'no',
- 'node',
- 'nodes',
- 'no-inherit',
- 'no-preserve',
- 'not',
- 'occurs',
- 'of',
- 'only',
- 'option',
- 'order',
- 'ordered',
- 'ordering',
- 'paragraph',
- 'paragraphs',
- 'parent',
- 'phrase',
- 'preceding',
- 'preceding-sibling',
- 'preserve',
- 'previous',
- 'processing-instruction',
- 'relationship',
- 'rename',
- 'replace',
- 'return',
- 'revalidation',
- 'same',
- 'satisfies',
- 'schema',
- 'schema-attribute',
- 'schema-element',
- 'score',
- 'self',
- 'sensitive',
- 'sentence',
- 'sentences',
- 'sequence',
- 'skip',
- 'sliding',
- 'some',
- 'stable',
- 'start',
- 'stemming',
- 'stop',
- 'strict',
- 'strip',
- 'switch',
- 'text',
- 'then',
- 'thesaurus',
- 'times',
- 'to',
- 'transform',
- 'treat',
- 'try',
- 'tumbling',
- 'type',
- 'typeswitch',
- 'union',
- 'unordered',
- 'update',
- 'updating',
- 'uppercase',
- 'using',
- 'validate',
- 'value',
- 'variable',
- 'version',
- 'weight',
- 'when',
- 'where',
- 'wildcards',
- 'window',
- 'with',
- 'without',
- 'word',
- 'words',
- 'xquery',
- ]
- for (var i = 0, l = basic.length; i < l; i++) {
- kwObj[basic[i]] = kw(basic[i])
- }
- // a list of types. For each add a property to kwObj with the value of
- // {type: "atom", style: "atom"}
- var types = [
- 'xs:anyAtomicType',
- 'xs:anySimpleType',
- 'xs:anyType',
- 'xs:anyURI',
- 'xs:base64Binary',
- 'xs:boolean',
- 'xs:byte',
- 'xs:date',
- 'xs:dateTime',
- 'xs:dateTimeStamp',
- 'xs:dayTimeDuration',
- 'xs:decimal',
- 'xs:double',
- 'xs:duration',
- 'xs:ENTITIES',
- 'xs:ENTITY',
- 'xs:float',
- 'xs:gDay',
- 'xs:gMonth',
- 'xs:gMonthDay',
- 'xs:gYear',
- 'xs:gYearMonth',
- 'xs:hexBinary',
- 'xs:ID',
- 'xs:IDREF',
- 'xs:IDREFS',
- 'xs:int',
- 'xs:integer',
- 'xs:item',
- 'xs:java',
- 'xs:language',
- 'xs:long',
- 'xs:Name',
- 'xs:NCName',
- 'xs:negativeInteger',
- 'xs:NMTOKEN',
- 'xs:NMTOKENS',
- 'xs:nonNegativeInteger',
- 'xs:nonPositiveInteger',
- 'xs:normalizedString',
- 'xs:NOTATION',
- 'xs:numeric',
- 'xs:positiveInteger',
- 'xs:precisionDecimal',
- 'xs:QName',
- 'xs:short',
- 'xs:string',
- 'xs:time',
- 'xs:token',
- 'xs:unsignedByte',
- 'xs:unsignedInt',
- 'xs:unsignedLong',
- 'xs:unsignedShort',
- 'xs:untyped',
- 'xs:untypedAtomic',
- 'xs:yearMonthDuration',
- ]
- for (var i = 0, l = types.length; i < l; i++) {
- kwObj[types[i]] = atom
- }
- // each operator will add a property to kwObj with value of {type: "operator", style: "keyword"}
- var operators = ['eq', 'ne', 'lt', 'le', 'gt', 'ge', ':=', '=', '>', '>=', '<', '<=', '.', '|', '?', 'and', 'or', 'div', 'idiv', 'mod', '*', '/', '+', '-']
- for (var i = 0, l = operators.length; i < l; i++) {
- kwObj[operators[i]] = operator
- }
- // each axis_specifiers will add a property to kwObj with value of {type: "axis_specifier", style: "qualifier"}
- var axis_specifiers = [
- 'self::',
- 'attribute::',
- 'child::',
- 'descendant::',
- 'descendant-or-self::',
- 'parent::',
- 'ancestor::',
- 'ancestor-or-self::',
- 'following::',
- 'preceding::',
- 'following-sibling::',
- 'preceding-sibling::',
- ]
- for (var i = 0, l = axis_specifiers.length; i < l; i++) {
- kwObj[axis_specifiers[i]] = qualifier
- }
- return kwObj
- })()
- function chain(stream, state, f) {
- state.tokenize = f
- return f(stream, state)
- }
- // the primary mode tokenizer
- function tokenBase(stream, state) {
- var ch = stream.next(),
- mightBeFunction = false,
- isEQName = isEQNameAhead(stream)
- // an XML tag (if not in some sub, chained tokenizer)
- if (ch == '<') {
- if (stream.match('!--', true)) return chain(stream, state, tokenXMLComment)
- if (stream.match('![CDATA', false)) {
- state.tokenize = tokenCDATA
- return 'tag'
- }
- if (stream.match('?', false)) {
- return chain(stream, state, tokenPreProcessing)
- }
- var isclose = stream.eat('/')
- stream.eatSpace()
- var tagName = '',
- c
- while ((c = stream.eat(/[^\s\u00a0=<>\"\'\/?]/))) tagName += c
- return chain(stream, state, tokenTag(tagName, isclose))
- }
- // start code block
- else if (ch == '{') {
- pushStateStack(state, { type: 'codeblock' })
- return null
- }
- // end code block
- else if (ch == '}') {
- popStateStack(state)
- return null
- }
- // if we're in an XML block
- else if (isInXmlBlock(state)) {
- if (ch == '>') return 'tag'
- else if (ch == '/' && stream.eat('>')) {
- popStateStack(state)
- return 'tag'
- } else return 'variable'
- }
- // if a number
- else if (/\d/.test(ch)) {
- stream.match(/^\d*(?:\.\d*)?(?:E[+\-]?\d+)?/)
- return 'atom'
- }
- // comment start
- else if (ch === '(' && stream.eat(':')) {
- pushStateStack(state, { type: 'comment' })
- return chain(stream, state, tokenComment)
- }
- // quoted string
- else if (!isEQName && (ch === '"' || ch === "'")) return chain(stream, state, tokenString(ch))
- // variable
- else if (ch === '$') {
- return chain(stream, state, tokenVariable)
- }
- // assignment
- else if (ch === ':' && stream.eat('=')) {
- return 'keyword'
- }
- // open paren
- else if (ch === '(') {
- pushStateStack(state, { type: 'paren' })
- return null
- }
- // close paren
- else if (ch === ')') {
- popStateStack(state)
- return null
- }
- // open paren
- else if (ch === '[') {
- pushStateStack(state, { type: 'bracket' })
- return null
- }
- // close paren
- else if (ch === ']') {
- popStateStack(state)
- return null
- } else {
- var known = keywords.propertyIsEnumerable(ch) && keywords[ch]
- // if there's a EQName ahead, consume the rest of the string portion, it's likely a function
- if (isEQName && ch === '"') while (stream.next() !== '"') {}
- if (isEQName && ch === "'") while (stream.next() !== "'") {}
- // gobble up a word if the character is not known
- if (!known) stream.eatWhile(/[\w\$_-]/)
- // gobble a colon in the case that is a lib func type call fn:doc
- var foundColon = stream.eat(':')
- // if there's not a second colon, gobble another word. Otherwise, it's probably an axis specifier
- // which should get matched as a keyword
- if (!stream.eat(':') && foundColon) {
- stream.eatWhile(/[\w\$_-]/)
- }
- // if the next non whitespace character is an open paren, this is probably a function (if not a keyword of other sort)
- if (stream.match(/^[ \t]*\(/, false)) {
- mightBeFunction = true
- }
- // is the word a keyword?
- var word = stream.current()
- known = keywords.propertyIsEnumerable(word) && keywords[word]
- // if we think it's a function call but not yet known,
- // set style to variable for now for lack of something better
- if (mightBeFunction && !known) known = { type: 'function_call', style: 'variable def' }
- // if the previous word was element, attribute, axis specifier, this word should be the name of that
- if (isInXmlConstructor(state)) {
- popStateStack(state)
- return 'variable'
- }
- // as previously checked, if the word is element,attribute, axis specifier, call it an "xmlconstructor" and
- // push the stack so we know to look for it on the next word
- if (word == 'element' || word == 'attribute' || known.type == 'axis_specifier') pushStateStack(state, { type: 'xmlconstructor' })
- // if the word is known, return the details of that else just call this a generic 'word'
- return known ? known.style : 'variable'
- }
- }
- // handle comments, including nested
- function tokenComment(stream, state) {
- var maybeEnd = false,
- maybeNested = false,
- nestedCount = 0,
- ch
- while ((ch = stream.next())) {
- if (ch == ')' && maybeEnd) {
- if (nestedCount > 0) nestedCount--
- else {
- popStateStack(state)
- break
- }
- } else if (ch == ':' && maybeNested) {
- nestedCount++
- }
- maybeEnd = ch == ':'
- maybeNested = ch == '('
- }
- return 'comment'
- }
- // tokenizer for string literals
- // optionally pass a tokenizer function to set state.tokenize back to when finished
- function tokenString(quote, f) {
- return function (stream, state) {
- var ch
- if (isInString(state) && stream.current() == quote) {
- popStateStack(state)
- if (f) state.tokenize = f
- return 'string'
- }
- pushStateStack(state, { type: 'string', name: quote, tokenize: tokenString(quote, f) })
- // if we're in a string and in an XML block, allow an embedded code block
- if (stream.match('{', false) && isInXmlAttributeBlock(state)) {
- state.tokenize = tokenBase
- return 'string'
- }
- while ((ch = stream.next())) {
- if (ch == quote) {
- popStateStack(state)
- if (f) state.tokenize = f
- break
- } else {
- // if we're in a string and in an XML block, allow an embedded code block in an attribute
- if (stream.match('{', false) && isInXmlAttributeBlock(state)) {
- state.tokenize = tokenBase
- return 'string'
- }
- }
- }
- return 'string'
- }
- }
- // tokenizer for variables
- function tokenVariable(stream, state) {
- var isVariableChar = /[\w\$_-]/
- // a variable may start with a quoted EQName so if the next character is quote, consume to the next quote
- if (stream.eat('"')) {
- while (stream.next() !== '"') {}
- stream.eat(':')
- } else {
- stream.eatWhile(isVariableChar)
- if (!stream.match(':=', false)) stream.eat(':')
- }
- stream.eatWhile(isVariableChar)
- state.tokenize = tokenBase
- return 'variable'
- }
- // tokenizer for XML tags
- function tokenTag(name, isclose) {
- return function (stream, state) {
- stream.eatSpace()
- if (isclose && stream.eat('>')) {
- popStateStack(state)
- state.tokenize = tokenBase
- return 'tag'
- }
- // self closing tag without attributes?
- if (!stream.eat('/')) pushStateStack(state, { type: 'tag', name: name, tokenize: tokenBase })
- if (!stream.eat('>')) {
- state.tokenize = tokenAttribute
- return 'tag'
- } else {
- state.tokenize = tokenBase
- }
- return 'tag'
- }
- }
- // tokenizer for XML attributes
- function tokenAttribute(stream, state) {
- var ch = stream.next()
- if (ch == '/' && stream.eat('>')) {
- if (isInXmlAttributeBlock(state)) popStateStack(state)
- if (isInXmlBlock(state)) popStateStack(state)
- return 'tag'
- }
- if (ch == '>') {
- if (isInXmlAttributeBlock(state)) popStateStack(state)
- return 'tag'
- }
- if (ch == '=') return null
- // quoted string
- if (ch == '"' || ch == "'") return chain(stream, state, tokenString(ch, tokenAttribute))
- if (!isInXmlAttributeBlock(state)) pushStateStack(state, { type: 'attribute', tokenize: tokenAttribute })
- stream.eat(/[a-zA-Z_:]/)
- stream.eatWhile(/[-a-zA-Z0-9_:.]/)
- stream.eatSpace()
- // the case where the attribute has not value and the tag was closed
- if (stream.match('>', false) || stream.match('/', false)) {
- popStateStack(state)
- state.tokenize = tokenBase
- }
- return 'attribute'
- }
- // handle comments, including nested
- function tokenXMLComment(stream, state) {
- var ch
- while ((ch = stream.next())) {
- if (ch == '-' && stream.match('->', true)) {
- state.tokenize = tokenBase
- return 'comment'
- }
- }
- }
- // handle CDATA
- function tokenCDATA(stream, state) {
- var ch
- while ((ch = stream.next())) {
- if (ch == ']' && stream.match(']', true)) {
- state.tokenize = tokenBase
- return 'comment'
- }
- }
- }
- // handle preprocessing instructions
- function tokenPreProcessing(stream, state) {
- var ch
- while ((ch = stream.next())) {
- if (ch == '?' && stream.match('>', true)) {
- state.tokenize = tokenBase
- return 'comment meta'
- }
- }
- }
- // functions to test the current context of the state
- function isInXmlBlock(state) {
- return isIn(state, 'tag')
- }
- function isInXmlAttributeBlock(state) {
- return isIn(state, 'attribute')
- }
- function isInXmlConstructor(state) {
- return isIn(state, 'xmlconstructor')
- }
- function isInString(state) {
- return isIn(state, 'string')
- }
- function isEQNameAhead(stream) {
- // assume we've already eaten a quote (")
- if (stream.current() === '"') return stream.match(/^[^\"]+\"\:/, false)
- else if (stream.current() === "'") return stream.match(/^[^\"]+\'\:/, false)
- else return false
- }
- function isIn(state, type) {
- return state.stack.length && state.stack[state.stack.length - 1].type == type
- }
- function pushStateStack(state, newState) {
- state.stack.push(newState)
- }
- function popStateStack(state) {
- state.stack.pop()
- var reinstateTokenize = state.stack.length && state.stack[state.stack.length - 1].tokenize
- state.tokenize = reinstateTokenize || tokenBase
- }
- // the interface for the mode API
- return {
- startState: function () {
- return {
- tokenize: tokenBase,
- cc: [],
- stack: [],
- }
- },
- token: function (stream, state) {
- if (stream.eatSpace()) return null
- var style = state.tokenize(stream, state)
- return style
- },
- blockCommentStart: '(:',
- blockCommentEnd: ':)',
- }
- })
- CodeMirror.defineMIME('application/xquery', 'xquery')
- })
|