diff .cms/lib/codemirror/mode/pug/pug.js @ 0:78edf6b517a0 draft

24.10
author Coffee CMS <info@coffee-cms.ru>
date Fri, 11 Oct 2024 22:40:23 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.cms/lib/codemirror/mode/pug/pug.js	Fri Oct 11 22:40:23 2024 +0000
@@ -0,0 +1,591 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: https://codemirror.net/5/LICENSE
+
+(function(mod) {
+  if (typeof exports == "object" && typeof module == "object") // CommonJS
+    mod(require("../../lib/codemirror"), require("../javascript/javascript"), require("../css/css"), require("../htmlmixed/htmlmixed"));
+  else if (typeof define == "function" && define.amd) // AMD
+    define(["../../lib/codemirror", "../javascript/javascript", "../css/css", "../htmlmixed/htmlmixed"], mod);
+  else // Plain browser env
+    mod(CodeMirror);
+})(function(CodeMirror) {
+"use strict";
+
+CodeMirror.defineMode("pug", function (config) {
+  // token types
+  var KEYWORD = 'keyword';
+  var DOCTYPE = 'meta';
+  var ID = 'builtin';
+  var CLASS = 'qualifier';
+
+  var ATTRS_NEST = {
+    '{': '}',
+    '(': ')',
+    '[': ']'
+  };
+
+  var jsMode = CodeMirror.getMode(config, 'javascript');
+
+  function State() {
+    this.javaScriptLine = false;
+    this.javaScriptLineExcludesColon = false;
+
+    this.javaScriptArguments = false;
+    this.javaScriptArgumentsDepth = 0;
+
+    this.isInterpolating = false;
+    this.interpolationNesting = 0;
+
+    this.jsState = CodeMirror.startState(jsMode);
+
+    this.restOfLine = '';
+
+    this.isIncludeFiltered = false;
+    this.isEach = false;
+
+    this.lastTag = '';
+    this.scriptType = '';
+
+    // Attributes Mode
+    this.isAttrs = false;
+    this.attrsNest = [];
+    this.inAttributeName = true;
+    this.attributeIsType = false;
+    this.attrValue = '';
+
+    // Indented Mode
+    this.indentOf = Infinity;
+    this.indentToken = '';
+
+    this.innerMode = null;
+    this.innerState = null;
+
+    this.innerModeForLine = false;
+  }
+  /**
+   * Safely copy a state
+   *
+   * @return {State}
+   */
+  State.prototype.copy = function () {
+    var res = new State();
+    res.javaScriptLine = this.javaScriptLine;
+    res.javaScriptLineExcludesColon = this.javaScriptLineExcludesColon;
+    res.javaScriptArguments = this.javaScriptArguments;
+    res.javaScriptArgumentsDepth = this.javaScriptArgumentsDepth;
+    res.isInterpolating = this.isInterpolating;
+    res.interpolationNesting = this.interpolationNesting;
+
+    res.jsState = CodeMirror.copyState(jsMode, this.jsState);
+
+    res.innerMode = this.innerMode;
+    if (this.innerMode && this.innerState) {
+      res.innerState = CodeMirror.copyState(this.innerMode, this.innerState);
+    }
+
+    res.restOfLine = this.restOfLine;
+
+    res.isIncludeFiltered = this.isIncludeFiltered;
+    res.isEach = this.isEach;
+    res.lastTag = this.lastTag;
+    res.scriptType = this.scriptType;
+    res.isAttrs = this.isAttrs;
+    res.attrsNest = this.attrsNest.slice();
+    res.inAttributeName = this.inAttributeName;
+    res.attributeIsType = this.attributeIsType;
+    res.attrValue = this.attrValue;
+    res.indentOf = this.indentOf;
+    res.indentToken = this.indentToken;
+
+    res.innerModeForLine = this.innerModeForLine;
+
+    return res;
+  };
+
+  function javaScript(stream, state) {
+    if (stream.sol()) {
+      // if javaScriptLine was set at end of line, ignore it
+      state.javaScriptLine = false;
+      state.javaScriptLineExcludesColon = false;
+    }
+    if (state.javaScriptLine) {
+      if (state.javaScriptLineExcludesColon && stream.peek() === ':') {
+        state.javaScriptLine = false;
+        state.javaScriptLineExcludesColon = false;
+        return;
+      }
+      var tok = jsMode.token(stream, state.jsState);
+      if (stream.eol()) state.javaScriptLine = false;
+      return tok || true;
+    }
+  }
+  function javaScriptArguments(stream, state) {
+    if (state.javaScriptArguments) {
+      if (state.javaScriptArgumentsDepth === 0 && stream.peek() !== '(') {
+        state.javaScriptArguments = false;
+        return;
+      }
+      if (stream.peek() === '(') {
+        state.javaScriptArgumentsDepth++;
+      } else if (stream.peek() === ')') {
+        state.javaScriptArgumentsDepth--;
+      }
+      if (state.javaScriptArgumentsDepth === 0) {
+        state.javaScriptArguments = false;
+        return;
+      }
+
+      var tok = jsMode.token(stream, state.jsState);
+      return tok || true;
+    }
+  }
+
+  function yieldStatement(stream) {
+    if (stream.match(/^yield\b/)) {
+        return 'keyword';
+    }
+  }
+
+  function doctype(stream) {
+    if (stream.match(/^(?:doctype) *([^\n]+)?/)) {
+        return DOCTYPE;
+    }
+  }
+
+  function interpolation(stream, state) {
+    if (stream.match('#{')) {
+      state.isInterpolating = true;
+      state.interpolationNesting = 0;
+      return 'punctuation';
+    }
+  }
+
+  function interpolationContinued(stream, state) {
+    if (state.isInterpolating) {
+      if (stream.peek() === '}') {
+        state.interpolationNesting--;
+        if (state.interpolationNesting < 0) {
+          stream.next();
+          state.isInterpolating = false;
+          return 'punctuation';
+        }
+      } else if (stream.peek() === '{') {
+        state.interpolationNesting++;
+      }
+      return jsMode.token(stream, state.jsState) || true;
+    }
+  }
+
+  function caseStatement(stream, state) {
+    if (stream.match(/^case\b/)) {
+      state.javaScriptLine = true;
+      return KEYWORD;
+    }
+  }
+
+  function when(stream, state) {
+    if (stream.match(/^when\b/)) {
+      state.javaScriptLine = true;
+      state.javaScriptLineExcludesColon = true;
+      return KEYWORD;
+    }
+  }
+
+  function defaultStatement(stream) {
+    if (stream.match(/^default\b/)) {
+      return KEYWORD;
+    }
+  }
+
+  function extendsStatement(stream, state) {
+    if (stream.match(/^extends?\b/)) {
+      state.restOfLine = 'string';
+      return KEYWORD;
+    }
+  }
+
+  function append(stream, state) {
+    if (stream.match(/^append\b/)) {
+      state.restOfLine = 'variable';
+      return KEYWORD;
+    }
+  }
+  function prepend(stream, state) {
+    if (stream.match(/^prepend\b/)) {
+      state.restOfLine = 'variable';
+      return KEYWORD;
+    }
+  }
+  function block(stream, state) {
+    if (stream.match(/^block\b *(?:(prepend|append)\b)?/)) {
+      state.restOfLine = 'variable';
+      return KEYWORD;
+    }
+  }
+
+  function include(stream, state) {
+    if (stream.match(/^include\b/)) {
+      state.restOfLine = 'string';
+      return KEYWORD;
+    }
+  }
+
+  function includeFiltered(stream, state) {
+    if (stream.match(/^include:([a-zA-Z0-9\-]+)/, false) && stream.match('include')) {
+      state.isIncludeFiltered = true;
+      return KEYWORD;
+    }
+  }
+
+  function includeFilteredContinued(stream, state) {
+    if (state.isIncludeFiltered) {
+      var tok = filter(stream, state);
+      state.isIncludeFiltered = false;
+      state.restOfLine = 'string';
+      return tok;
+    }
+  }
+
+  function mixin(stream, state) {
+    if (stream.match(/^mixin\b/)) {
+      state.javaScriptLine = true;
+      return KEYWORD;
+    }
+  }
+
+  function call(stream, state) {
+    if (stream.match(/^\+([-\w]+)/)) {
+      if (!stream.match(/^\( *[-\w]+ *=/, false)) {
+        state.javaScriptArguments = true;
+        state.javaScriptArgumentsDepth = 0;
+      }
+      return 'variable';
+    }
+    if (stream.match('+#{', false)) {
+      stream.next();
+      state.mixinCallAfter = true;
+      return interpolation(stream, state);
+    }
+  }
+  function callArguments(stream, state) {
+    if (state.mixinCallAfter) {
+      state.mixinCallAfter = false;
+      if (!stream.match(/^\( *[-\w]+ *=/, false)) {
+        state.javaScriptArguments = true;
+        state.javaScriptArgumentsDepth = 0;
+      }
+      return true;
+    }
+  }
+
+  function conditional(stream, state) {
+    if (stream.match(/^(if|unless|else if|else)\b/)) {
+      state.javaScriptLine = true;
+      return KEYWORD;
+    }
+  }
+
+  function each(stream, state) {
+    if (stream.match(/^(- *)?(each|for)\b/)) {
+      state.isEach = true;
+      return KEYWORD;
+    }
+  }
+  function eachContinued(stream, state) {
+    if (state.isEach) {
+      if (stream.match(/^ in\b/)) {
+        state.javaScriptLine = true;
+        state.isEach = false;
+        return KEYWORD;
+      } else if (stream.sol() || stream.eol()) {
+        state.isEach = false;
+      } else if (stream.next()) {
+        while (!stream.match(/^ in\b/, false) && stream.next());
+        return 'variable';
+      }
+    }
+  }
+
+  function whileStatement(stream, state) {
+    if (stream.match(/^while\b/)) {
+      state.javaScriptLine = true;
+      return KEYWORD;
+    }
+  }
+
+  function tag(stream, state) {
+    var captures;
+    if (captures = stream.match(/^(\w(?:[-:\w]*\w)?)\/?/)) {
+      state.lastTag = captures[1].toLowerCase();
+      if (state.lastTag === 'script') {
+        state.scriptType = 'application/javascript';
+      }
+      return 'tag';
+    }
+  }
+
+  function filter(stream, state) {
+    if (stream.match(/^:([\w\-]+)/)) {
+      var innerMode;
+      if (config && config.innerModes) {
+        innerMode = config.innerModes(stream.current().substring(1));
+      }
+      if (!innerMode) {
+        innerMode = stream.current().substring(1);
+      }
+      if (typeof innerMode === 'string') {
+        innerMode = CodeMirror.getMode(config, innerMode);
+      }
+      setInnerMode(stream, state, innerMode);
+      return 'atom';
+    }
+  }
+
+  function code(stream, state) {
+    if (stream.match(/^(!?=|-)/)) {
+      state.javaScriptLine = true;
+      return 'punctuation';
+    }
+  }
+
+  function id(stream) {
+    if (stream.match(/^#([\w-]+)/)) {
+      return ID;
+    }
+  }
+
+  function className(stream) {
+    if (stream.match(/^\.([\w-]+)/)) {
+      return CLASS;
+    }
+  }
+
+  function attrs(stream, state) {
+    if (stream.peek() == '(') {
+      stream.next();
+      state.isAttrs = true;
+      state.attrsNest = [];
+      state.inAttributeName = true;
+      state.attrValue = '';
+      state.attributeIsType = false;
+      return 'punctuation';
+    }
+  }
+
+  function attrsContinued(stream, state) {
+    if (state.isAttrs) {
+      if (ATTRS_NEST[stream.peek()]) {
+        state.attrsNest.push(ATTRS_NEST[stream.peek()]);
+      }
+      if (state.attrsNest[state.attrsNest.length - 1] === stream.peek()) {
+        state.attrsNest.pop();
+      } else  if (stream.eat(')')) {
+        state.isAttrs = false;
+        return 'punctuation';
+      }
+      if (state.inAttributeName && stream.match(/^[^=,\)!]+/)) {
+        if (stream.peek() === '=' || stream.peek() === '!') {
+          state.inAttributeName = false;
+          state.jsState = CodeMirror.startState(jsMode);
+          if (state.lastTag === 'script' && stream.current().trim().toLowerCase() === 'type') {
+            state.attributeIsType = true;
+          } else {
+            state.attributeIsType = false;
+          }
+        }
+        return 'attribute';
+      }
+
+      var tok = jsMode.token(stream, state.jsState);
+      if (state.attributeIsType && tok === 'string') {
+        state.scriptType = stream.current().toString();
+      }
+      if (state.attrsNest.length === 0 && (tok === 'string' || tok === 'variable' || tok === 'keyword')) {
+        try {
+          Function('', 'var x ' + state.attrValue.replace(/,\s*$/, '').replace(/^!/, ''));
+          state.inAttributeName = true;
+          state.attrValue = '';
+          stream.backUp(stream.current().length);
+          return attrsContinued(stream, state);
+        } catch (ex) {
+          //not the end of an attribute
+        }
+      }
+      state.attrValue += stream.current();
+      return tok || true;
+    }
+  }
+
+  function attributesBlock(stream, state) {
+    if (stream.match(/^&attributes\b/)) {
+      state.javaScriptArguments = true;
+      state.javaScriptArgumentsDepth = 0;
+      return 'keyword';
+    }
+  }
+
+  function indent(stream) {
+    if (stream.sol() && stream.eatSpace()) {
+      return 'indent';
+    }
+  }
+
+  function comment(stream, state) {
+    if (stream.match(/^ *\/\/(-)?([^\n]*)/)) {
+      state.indentOf = stream.indentation();
+      state.indentToken = 'comment';
+      return 'comment';
+    }
+  }
+
+  function colon(stream) {
+    if (stream.match(/^: */)) {
+      return 'colon';
+    }
+  }
+
+  function text(stream, state) {
+    if (stream.match(/^(?:\| ?| )([^\n]+)/)) {
+      return 'string';
+    }
+    if (stream.match(/^(<[^\n]*)/, false)) {
+      // html string
+      setInnerMode(stream, state, 'htmlmixed');
+      state.innerModeForLine = true;
+      return innerMode(stream, state, true);
+    }
+  }
+
+  function dot(stream, state) {
+    if (stream.eat('.')) {
+      var innerMode = null;
+      if (state.lastTag === 'script' && state.scriptType.toLowerCase().indexOf('javascript') != -1) {
+        innerMode = state.scriptType.toLowerCase().replace(/"|'/g, '');
+      } else if (state.lastTag === 'style') {
+        innerMode = 'css';
+      }
+      setInnerMode(stream, state, innerMode);
+      return 'dot';
+    }
+  }
+
+  function fail(stream) {
+    stream.next();
+    return null;
+  }
+
+
+  function setInnerMode(stream, state, mode) {
+    mode = CodeMirror.mimeModes[mode] || mode;
+    mode = config.innerModes ? config.innerModes(mode) || mode : mode;
+    mode = CodeMirror.mimeModes[mode] || mode;
+    mode = CodeMirror.getMode(config, mode);
+    state.indentOf = stream.indentation();
+
+    if (mode && mode.name !== 'null') {
+      state.innerMode = mode;
+    } else {
+      state.indentToken = 'string';
+    }
+  }
+  function innerMode(stream, state, force) {
+    if (stream.indentation() > state.indentOf || (state.innerModeForLine && !stream.sol()) || force) {
+      if (state.innerMode) {
+        if (!state.innerState) {
+          state.innerState = state.innerMode.startState ? CodeMirror.startState(state.innerMode, stream.indentation()) : {};
+        }
+        return stream.hideFirstChars(state.indentOf + 2, function () {
+          return state.innerMode.token(stream, state.innerState) || true;
+        });
+      } else {
+        stream.skipToEnd();
+        return state.indentToken;
+      }
+    } else if (stream.sol()) {
+      state.indentOf = Infinity;
+      state.indentToken = null;
+      state.innerMode = null;
+      state.innerState = null;
+    }
+  }
+  function restOfLine(stream, state) {
+    if (stream.sol()) {
+      // if restOfLine was set at end of line, ignore it
+      state.restOfLine = '';
+    }
+    if (state.restOfLine) {
+      stream.skipToEnd();
+      var tok = state.restOfLine;
+      state.restOfLine = '';
+      return tok;
+    }
+  }
+
+
+  function startState() {
+    return new State();
+  }
+  function copyState(state) {
+    return state.copy();
+  }
+  /**
+   * Get the next token in the stream
+   *
+   * @param {Stream} stream
+   * @param {State} state
+   */
+  function nextToken(stream, state) {
+    var tok = innerMode(stream, state)
+      || restOfLine(stream, state)
+      || interpolationContinued(stream, state)
+      || includeFilteredContinued(stream, state)
+      || eachContinued(stream, state)
+      || attrsContinued(stream, state)
+      || javaScript(stream, state)
+      || javaScriptArguments(stream, state)
+      || callArguments(stream, state)
+
+      || yieldStatement(stream)
+      || doctype(stream)
+      || interpolation(stream, state)
+      || caseStatement(stream, state)
+      || when(stream, state)
+      || defaultStatement(stream)
+      || extendsStatement(stream, state)
+      || append(stream, state)
+      || prepend(stream, state)
+      || block(stream, state)
+      || include(stream, state)
+      || includeFiltered(stream, state)
+      || mixin(stream, state)
+      || call(stream, state)
+      || conditional(stream, state)
+      || each(stream, state)
+      || whileStatement(stream, state)
+      || tag(stream, state)
+      || filter(stream, state)
+      || code(stream, state)
+      || id(stream)
+      || className(stream)
+      || attrs(stream, state)
+      || attributesBlock(stream, state)
+      || indent(stream)
+      || text(stream, state)
+      || comment(stream, state)
+      || colon(stream)
+      || dot(stream, state)
+      || fail(stream);
+
+    return tok === true ? null : tok;
+  }
+  return {
+    startState: startState,
+    copyState: copyState,
+    token: nextToken
+  };
+}, 'javascript', 'css', 'htmlmixed');
+
+CodeMirror.defineMIME('text/x-pug', 'pug');
+CodeMirror.defineMIME('text/x-jade', 'pug');
+
+});