123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313 |
- // 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('tiki', function (config) {
- function inBlock(style, terminator, returnTokenizer) {
- return function (stream, state) {
- while (!stream.eol()) {
- if (stream.match(terminator)) {
- state.tokenize = inText
- break
- }
- stream.next()
- }
- if (returnTokenizer) state.tokenize = returnTokenizer
- return style
- }
- }
- function inLine(style) {
- return function (stream, state) {
- while (!stream.eol()) {
- stream.next()
- }
- state.tokenize = inText
- return style
- }
- }
- function inText(stream, state) {
- function chain(parser) {
- state.tokenize = parser
- return parser(stream, state)
- }
- var sol = stream.sol()
- var ch = stream.next()
- //non start of line
- switch (
- ch //switch is generally much faster than if, so it is used here
- ) {
- case '{': //plugin
- stream.eat('/')
- stream.eatSpace()
- stream.eatWhile(/[^\s\u00a0=\"\'\/?(}]/)
- state.tokenize = inPlugin
- return 'tag'
- case '_': //bold
- if (stream.eat('_')) return chain(inBlock('strong', '__', inText))
- break
- case "'": //italics
- if (stream.eat("'")) return chain(inBlock('em', "''", inText))
- break
- case '(': // Wiki Link
- if (stream.eat('(')) return chain(inBlock('variable-2', '))', inText))
- break
- case '[': // Weblink
- return chain(inBlock('variable-3', ']', inText))
- break
- case '|': //table
- if (stream.eat('|')) return chain(inBlock('comment', '||'))
- break
- case '-':
- if (stream.eat('=')) {
- //titleBar
- return chain(inBlock('header string', '=-', inText))
- } else if (stream.eat('-')) {
- //deleted
- return chain(inBlock('error tw-deleted', '--', inText))
- }
- break
- case '=': //underline
- if (stream.match('==')) return chain(inBlock('tw-underline', '===', inText))
- break
- case ':':
- if (stream.eat(':')) return chain(inBlock('comment', '::'))
- break
- case '^': //box
- return chain(inBlock('tw-box', '^'))
- break
- case '~': //np
- if (stream.match('np~')) return chain(inBlock('meta', '~/np~'))
- break
- }
- //start of line types
- if (sol) {
- switch (ch) {
- case '!': //header at start of line
- if (stream.match('!!!!!')) {
- return chain(inLine('header string'))
- } else if (stream.match('!!!!')) {
- return chain(inLine('header string'))
- } else if (stream.match('!!!')) {
- return chain(inLine('header string'))
- } else if (stream.match('!!')) {
- return chain(inLine('header string'))
- } else {
- return chain(inLine('header string'))
- }
- break
- case '*': //unordered list line item, or <li /> at start of line
- case '#': //ordered list line item, or <li /> at start of line
- case '+': //ordered list line item, or <li /> at start of line
- return chain(inLine('tw-listitem bracket'))
- break
- }
- }
- //stream.eatWhile(/[&{]/); was eating up plugins, turned off to act less like html and more like tiki
- return null
- }
- var indentUnit = config.indentUnit
- // Return variables for tokenizers
- var pluginName, type
- function inPlugin(stream, state) {
- var ch = stream.next()
- var peek = stream.peek()
- if (ch == '}') {
- state.tokenize = inText
- //type = ch == ")" ? "endPlugin" : "selfclosePlugin"; inPlugin
- return 'tag'
- } else if (ch == '(' || ch == ')') {
- return 'bracket'
- } else if (ch == '=') {
- type = 'equals'
- if (peek == '>') {
- stream.next()
- peek = stream.peek()
- }
- //here we detect values directly after equal character with no quotes
- if (!/[\'\"]/.test(peek)) {
- state.tokenize = inAttributeNoQuote()
- }
- //end detect values
- return 'operator'
- } else if (/[\'\"]/.test(ch)) {
- state.tokenize = inAttribute(ch)
- return state.tokenize(stream, state)
- } else {
- stream.eatWhile(/[^\s\u00a0=\"\'\/?]/)
- return 'keyword'
- }
- }
- function inAttribute(quote) {
- return function (stream, state) {
- while (!stream.eol()) {
- if (stream.next() == quote) {
- state.tokenize = inPlugin
- break
- }
- }
- return 'string'
- }
- }
- function inAttributeNoQuote() {
- return function (stream, state) {
- while (!stream.eol()) {
- var ch = stream.next()
- var peek = stream.peek()
- if (ch == ' ' || ch == ',' || /[ )}]/.test(peek)) {
- state.tokenize = inPlugin
- break
- }
- }
- return 'string'
- }
- }
- var curState, setStyle
- function pass() {
- for (var i = arguments.length - 1; i >= 0; i--) curState.cc.push(arguments[i])
- }
- function cont() {
- pass.apply(null, arguments)
- return true
- }
- function pushContext(pluginName, startOfLine) {
- var noIndent = curState.context && curState.context.noIndent
- curState.context = {
- prev: curState.context,
- pluginName: pluginName,
- indent: curState.indented,
- startOfLine: startOfLine,
- noIndent: noIndent,
- }
- }
- function popContext() {
- if (curState.context) curState.context = curState.context.prev
- }
- function element(type) {
- if (type == 'openPlugin') {
- curState.pluginName = pluginName
- return cont(attributes, endplugin(curState.startOfLine))
- } else if (type == 'closePlugin') {
- var err = false
- if (curState.context) {
- err = curState.context.pluginName != pluginName
- popContext()
- } else {
- err = true
- }
- if (err) setStyle = 'error'
- return cont(endcloseplugin(err))
- } else if (type == 'string') {
- if (!curState.context || curState.context.name != '!cdata') pushContext('!cdata')
- if (curState.tokenize == inText) popContext()
- return cont()
- } else return cont()
- }
- function endplugin(startOfLine) {
- return function (type) {
- if (type == 'selfclosePlugin' || type == 'endPlugin') return cont()
- if (type == 'endPlugin') {
- pushContext(curState.pluginName, startOfLine)
- return cont()
- }
- return cont()
- }
- }
- function endcloseplugin(err) {
- return function (type) {
- if (err) setStyle = 'error'
- if (type == 'endPlugin') return cont()
- return pass()
- }
- }
- function attributes(type) {
- if (type == 'keyword') {
- setStyle = 'attribute'
- return cont(attributes)
- }
- if (type == 'equals') return cont(attvalue, attributes)
- return pass()
- }
- function attvalue(type) {
- if (type == 'keyword') {
- setStyle = 'string'
- return cont()
- }
- if (type == 'string') return cont(attvaluemaybe)
- return pass()
- }
- function attvaluemaybe(type) {
- if (type == 'string') return cont(attvaluemaybe)
- else return pass()
- }
- return {
- startState: function () {
- return { tokenize: inText, cc: [], indented: 0, startOfLine: true, pluginName: null, context: null }
- },
- token: function (stream, state) {
- if (stream.sol()) {
- state.startOfLine = true
- state.indented = stream.indentation()
- }
- if (stream.eatSpace()) return null
- setStyle = type = pluginName = null
- var style = state.tokenize(stream, state)
- if ((style || type) && style != 'comment') {
- curState = state
- while (true) {
- var comb = state.cc.pop() || element
- if (comb(type || style)) break
- }
- }
- state.startOfLine = false
- return setStyle || style
- },
- indent: function (state, textAfter) {
- var context = state.context
- if (context && context.noIndent) return 0
- if (context && /^{\//.test(textAfter)) context = context.prev
- while (context && !context.startOfLine) context = context.prev
- if (context) return context.indent + indentUnit
- else return 0
- },
- electricChars: '/',
- }
- })
- CodeMirror.defineMIME('text/tiki', 'tiki')
- })
|