// CodeMirror, copyright (c) by Marijn Haverbeke and others // Distributed under an MIT license: https://codemirror.net/LICENSE /* DTD mode Ported to CodeMirror by Peter Kroon Report bugs/issues here: https://github.com/codemirror/CodeMirror/issues GitHub: @peterkroon */ ;(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('dtd', function (config) { var indentUnit = config.indentUnit, type function ret(style, tp) { type = tp return style } function tokenBase(stream, state) { var ch = stream.next() if (ch == '<' && stream.eat('!')) { if (stream.eatWhile(/[\-]/)) { state.tokenize = tokenSGMLComment return tokenSGMLComment(stream, state) } else if (stream.eatWhile(/[\w]/)) return ret('keyword', 'doindent') } else if (ch == '<' && stream.eat('?')) { //xml declaration state.tokenize = inBlock('meta', '?>') return ret('meta', ch) } else if (ch == '#' && stream.eatWhile(/[\w]/)) return ret('atom', 'tag') else if (ch == '|') return ret('keyword', 'separator') else if (ch.match(/[\(\)\[\]\-\.,\+\?>]/)) return ret(null, ch) //if(ch === ">") return ret(null, "endtag"); else else if (ch.match(/[\[\]]/)) return ret('rule', ch) else if (ch == '"' || ch == "'") { state.tokenize = tokenString(ch) return state.tokenize(stream, state) } else if (stream.eatWhile(/[a-zA-Z\?\+\d]/)) { var sc = stream.current() if (sc.substr(sc.length - 1, sc.length).match(/\?|\+/) !== null) stream.backUp(1) return ret('tag', 'tag') } else if (ch == '%' || ch == '*') return ret('number', 'number') else { stream.eatWhile(/[\w\\\-_%.{,]/) return ret(null, null) } } function tokenSGMLComment(stream, state) { var dashes = 0, ch while ((ch = stream.next()) != null) { if (dashes >= 2 && ch == '>') { state.tokenize = tokenBase break } dashes = ch == '-' ? dashes + 1 : 0 } return ret('comment', 'comment') } function tokenString(quote) { return function (stream, state) { var escaped = false, ch while ((ch = stream.next()) != null) { if (ch == quote && !escaped) { state.tokenize = tokenBase break } escaped = !escaped && ch == '\\' } return ret('string', 'tag') } } function inBlock(style, terminator) { return function (stream, state) { while (!stream.eol()) { if (stream.match(terminator)) { state.tokenize = tokenBase break } stream.next() } return style } } return { startState: function (base) { return { tokenize: tokenBase, baseIndent: base || 0, stack: [] } }, token: function (stream, state) { if (stream.eatSpace()) return null var style = state.tokenize(stream, state) var context = state.stack[state.stack.length - 1] if (stream.current() == '[' || type === 'doindent' || type == '[') state.stack.push('rule') else if (type === 'endtag') state.stack[state.stack.length - 1] = 'endtag' else if (stream.current() == ']' || type == ']' || (type == '>' && context == 'rule')) state.stack.pop() else if (type == '[') state.stack.push('[') return style }, indent: function (state, textAfter) { var n = state.stack.length if (textAfter.charAt(0) === ']') n-- else if (textAfter.substr(textAfter.length - 1, textAfter.length) === '>') { if (textAfter.substr(0, 1) === '<') { } else if (type == 'doindent' && textAfter.length > 1) { } else if (type == 'doindent') n-- else if (type == '>' && textAfter.length > 1) { } else if (type == 'tag' && textAfter !== '>') { } else if (type == 'tag' && state.stack[state.stack.length - 1] == 'rule') n-- else if (type == 'tag') n++ else if (textAfter === '>' && state.stack[state.stack.length - 1] == 'rule' && type === '>') n-- else if (textAfter === '>' && state.stack[state.stack.length - 1] == 'rule') { } else if (textAfter.substr(0, 1) !== '<' && textAfter.substr(0, 1) === '>') n = n - 1 else if (textAfter === '>') { } else n = n - 1 //over rule them all if (type == null || type == ']') n-- } return state.baseIndent + n * indentUnit }, electricChars: ']>', } }) CodeMirror.defineMIME('application/xml-dtd', 'dtd') })