[ Index ]

PHP Cross Reference of Joomla 4.2.2 documentation

title

Body

[close]

/media/vendor/codemirror/mode/slim/ -> slim.js (source)

   1  // CodeMirror, copyright (c) by Marijn Haverbeke and others
   2  // Distributed under an MIT license: https://codemirror.net/5/LICENSE
   3  
   4  // Slim Highlighting for CodeMirror copyright (c) HicknHack Software Gmbh
   5  
   6  (function(mod) {
   7    if (typeof exports == "object" && typeof module == "object") // CommonJS
   8      mod(require("../../lib/codemirror"), require("../htmlmixed/htmlmixed"), require("../ruby/ruby"));
   9    else if (typeof define == "function" && define.amd) // AMD
  10      define(["../../lib/codemirror", "../htmlmixed/htmlmixed", "../ruby/ruby"], mod);
  11    else // Plain browser env
  12      mod(CodeMirror);
  13  })(function(CodeMirror) {
  14  "use strict";
  15  
  16    CodeMirror.defineMode("slim", function(config) {
  17      var htmlMode = CodeMirror.getMode(config, {name: "htmlmixed"});
  18      var rubyMode = CodeMirror.getMode(config, "ruby");
  19      var modes = { html: htmlMode, ruby: rubyMode };
  20      var embedded = {
  21        ruby: "ruby",
  22        javascript: "javascript",
  23        css: "text/css",
  24        sass: "text/x-sass",
  25        scss: "text/x-scss",
  26        less: "text/x-less",
  27        styl: "text/x-styl", // no highlighting so far
  28        coffee: "coffeescript",
  29        asciidoc: "text/x-asciidoc",
  30        markdown: "text/x-markdown",
  31        textile: "text/x-textile", // no highlighting so far
  32        creole: "text/x-creole", // no highlighting so far
  33        wiki: "text/x-wiki", // no highlighting so far
  34        mediawiki: "text/x-mediawiki", // no highlighting so far
  35        rdoc: "text/x-rdoc", // no highlighting so far
  36        builder: "text/x-builder", // no highlighting so far
  37        nokogiri: "text/x-nokogiri", // no highlighting so far
  38        erb: "application/x-erb"
  39      };
  40      var embeddedRegexp = function(map){
  41        var arr = [];
  42        for(var key in map) arr.push(key);
  43        return new RegExp("^("+arr.join('|')+"):");
  44      }(embedded);
  45  
  46      var styleMap = {
  47        "commentLine": "comment",
  48        "slimSwitch": "operator special",
  49        "slimTag": "tag",
  50        "slimId": "attribute def",
  51        "slimClass": "attribute qualifier",
  52        "slimAttribute": "attribute",
  53        "slimSubmode": "keyword special",
  54        "closeAttributeTag": null,
  55        "slimDoctype": null,
  56        "lineContinuation": null
  57      };
  58      var closing = {
  59        "{": "}",
  60        "[": "]",
  61        "(": ")"
  62      };
  63  
  64      var nameStartChar = "_a-zA-Z\xC0-\xD6\xD8-\xF6\xF8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD";
  65      var nameChar = nameStartChar + "\\-0-9\xB7\u0300-\u036F\u203F-\u2040";
  66      var nameRegexp = new RegExp("^[:"+nameStartChar+"](?::["+nameChar+"]|["+nameChar+"]*)");
  67      var attributeNameRegexp = new RegExp("^[:"+nameStartChar+"][:\\."+nameChar+"]*(?=\\s*=)");
  68      var wrappedAttributeNameRegexp = new RegExp("^[:"+nameStartChar+"][:\\."+nameChar+"]*");
  69      var classNameRegexp = /^\.-?[_a-zA-Z]+[\w\-]*/;
  70      var classIdRegexp = /^#[_a-zA-Z]+[\w\-]*/;
  71  
  72      function backup(pos, tokenize, style) {
  73        var restore = function(stream, state) {
  74          state.tokenize = tokenize;
  75          if (stream.pos < pos) {
  76            stream.pos = pos;
  77            return style;
  78          }
  79          return state.tokenize(stream, state);
  80        };
  81        return function(stream, state) {
  82          state.tokenize = restore;
  83          return tokenize(stream, state);
  84        };
  85      }
  86  
  87      function maybeBackup(stream, state, pat, offset, style) {
  88        var cur = stream.current();
  89        var idx = cur.search(pat);
  90        if (idx > -1) {
  91          state.tokenize = backup(stream.pos, state.tokenize, style);
  92          stream.backUp(cur.length - idx - offset);
  93        }
  94        return style;
  95      }
  96  
  97      function continueLine(state, column) {
  98        state.stack = {
  99          parent: state.stack,
 100          style: "continuation",
 101          indented: column,
 102          tokenize: state.line
 103        };
 104        state.line = state.tokenize;
 105      }
 106      function finishContinue(state) {
 107        if (state.line == state.tokenize) {
 108          state.line = state.stack.tokenize;
 109          state.stack = state.stack.parent;
 110        }
 111      }
 112  
 113      function lineContinuable(column, tokenize) {
 114        return function(stream, state) {
 115          finishContinue(state);
 116          if (stream.match(/^\\$/)) {
 117            continueLine(state, column);
 118            return "lineContinuation";
 119          }
 120          var style = tokenize(stream, state);
 121          if (stream.eol() && stream.current().match(/(?:^|[^\\])(?:\\\\)*\\$/)) {
 122            stream.backUp(1);
 123          }
 124          return style;
 125        };
 126      }
 127      function commaContinuable(column, tokenize) {
 128        return function(stream, state) {
 129          finishContinue(state);
 130          var style = tokenize(stream, state);
 131          if (stream.eol() && stream.current().match(/,$/)) {
 132            continueLine(state, column);
 133          }
 134          return style;
 135        };
 136      }
 137  
 138      function rubyInQuote(endQuote, tokenize) {
 139        // TODO: add multi line support
 140        return function(stream, state) {
 141          var ch = stream.peek();
 142          if (ch == endQuote && state.rubyState.tokenize.length == 1) {
 143            // step out of ruby context as it seems to complete processing all the braces
 144            stream.next();
 145            state.tokenize = tokenize;
 146            return "closeAttributeTag";
 147          } else {
 148            return ruby(stream, state);
 149          }
 150        };
 151      }
 152      function startRubySplat(tokenize) {
 153        var rubyState;
 154        var runSplat = function(stream, state) {
 155          if (state.rubyState.tokenize.length == 1 && !state.rubyState.context.prev) {
 156            stream.backUp(1);
 157            if (stream.eatSpace()) {
 158              state.rubyState = rubyState;
 159              state.tokenize = tokenize;
 160              return tokenize(stream, state);
 161            }
 162            stream.next();
 163          }
 164          return ruby(stream, state);
 165        };
 166        return function(stream, state) {
 167          rubyState = state.rubyState;
 168          state.rubyState = CodeMirror.startState(rubyMode);
 169          state.tokenize = runSplat;
 170          return ruby(stream, state);
 171        };
 172      }
 173  
 174      function ruby(stream, state) {
 175        return rubyMode.token(stream, state.rubyState);
 176      }
 177  
 178      function htmlLine(stream, state) {
 179        if (stream.match(/^\\$/)) {
 180          return "lineContinuation";
 181        }
 182        return html(stream, state);
 183      }
 184      function html(stream, state) {
 185        if (stream.match(/^#\{/)) {
 186          state.tokenize = rubyInQuote("}", state.tokenize);
 187          return null;
 188        }
 189        return maybeBackup(stream, state, /[^\\]#\{/, 1, htmlMode.token(stream, state.htmlState));
 190      }
 191  
 192      function startHtmlLine(lastTokenize) {
 193        return function(stream, state) {
 194          var style = htmlLine(stream, state);
 195          if (stream.eol()) state.tokenize = lastTokenize;
 196          return style;
 197        };
 198      }
 199  
 200      function startHtmlMode(stream, state, offset) {
 201        state.stack = {
 202          parent: state.stack,
 203          style: "html",
 204          indented: stream.column() + offset, // pipe + space
 205          tokenize: state.line
 206        };
 207        state.line = state.tokenize = html;
 208        return null;
 209      }
 210  
 211      function comment(stream, state) {
 212        stream.skipToEnd();
 213        return state.stack.style;
 214      }
 215  
 216      function commentMode(stream, state) {
 217        state.stack = {
 218          parent: state.stack,
 219          style: "comment",
 220          indented: state.indented + 1,
 221          tokenize: state.line
 222        };
 223        state.line = comment;
 224        return comment(stream, state);
 225      }
 226  
 227      function attributeWrapper(stream, state) {
 228        if (stream.eat(state.stack.endQuote)) {
 229          state.line = state.stack.line;
 230          state.tokenize = state.stack.tokenize;
 231          state.stack = state.stack.parent;
 232          return null;
 233        }
 234        if (stream.match(wrappedAttributeNameRegexp)) {
 235          state.tokenize = attributeWrapperAssign;
 236          return "slimAttribute";
 237        }
 238        stream.next();
 239        return null;
 240      }
 241      function attributeWrapperAssign(stream, state) {
 242        if (stream.match(/^==?/)) {
 243          state.tokenize = attributeWrapperValue;
 244          return null;
 245        }
 246        return attributeWrapper(stream, state);
 247      }
 248      function attributeWrapperValue(stream, state) {
 249        var ch = stream.peek();
 250        if (ch == '"' || ch == "\'") {
 251          state.tokenize = readQuoted(ch, "string", true, false, attributeWrapper);
 252          stream.next();
 253          return state.tokenize(stream, state);
 254        }
 255        if (ch == '[') {
 256          return startRubySplat(attributeWrapper)(stream, state);
 257        }
 258        if (stream.match(/^(true|false|nil)\b/)) {
 259          state.tokenize = attributeWrapper;
 260          return "keyword";
 261        }
 262        return startRubySplat(attributeWrapper)(stream, state);
 263      }
 264  
 265      function startAttributeWrapperMode(state, endQuote, tokenize) {
 266        state.stack = {
 267          parent: state.stack,
 268          style: "wrapper",
 269          indented: state.indented + 1,
 270          tokenize: tokenize,
 271          line: state.line,
 272          endQuote: endQuote
 273        };
 274        state.line = state.tokenize = attributeWrapper;
 275        return null;
 276      }
 277  
 278      function sub(stream, state) {
 279        if (stream.match(/^#\{/)) {
 280          state.tokenize = rubyInQuote("}", state.tokenize);
 281          return null;
 282        }
 283        var subStream = new CodeMirror.StringStream(stream.string.slice(state.stack.indented), stream.tabSize);
 284        subStream.pos = stream.pos - state.stack.indented;
 285        subStream.start = stream.start - state.stack.indented;
 286        subStream.lastColumnPos = stream.lastColumnPos - state.stack.indented;
 287        subStream.lastColumnValue = stream.lastColumnValue - state.stack.indented;
 288        var style = state.subMode.token(subStream, state.subState);
 289        stream.pos = subStream.pos + state.stack.indented;
 290        return style;
 291      }
 292      function firstSub(stream, state) {
 293        state.stack.indented = stream.column();
 294        state.line = state.tokenize = sub;
 295        return state.tokenize(stream, state);
 296      }
 297  
 298      function createMode(mode) {
 299        var query = embedded[mode];
 300        var spec = CodeMirror.mimeModes[query];
 301        if (spec) {
 302          return CodeMirror.getMode(config, spec);
 303        }
 304        var factory = CodeMirror.modes[query];
 305        if (factory) {
 306          return factory(config, {name: query});
 307        }
 308        return CodeMirror.getMode(config, "null");
 309      }
 310  
 311      function getMode(mode) {
 312        if (!modes.hasOwnProperty(mode)) {
 313          return modes[mode] = createMode(mode);
 314        }
 315        return modes[mode];
 316      }
 317  
 318      function startSubMode(mode, state) {
 319        var subMode = getMode(mode);
 320        var subState = CodeMirror.startState(subMode);
 321  
 322        state.subMode = subMode;
 323        state.subState = subState;
 324  
 325        state.stack = {
 326          parent: state.stack,
 327          style: "sub",
 328          indented: state.indented + 1,
 329          tokenize: state.line
 330        };
 331        state.line = state.tokenize = firstSub;
 332        return "slimSubmode";
 333      }
 334  
 335      function doctypeLine(stream, _state) {
 336        stream.skipToEnd();
 337        return "slimDoctype";
 338      }
 339  
 340      function startLine(stream, state) {
 341        var ch = stream.peek();
 342        if (ch == '<') {
 343          return (state.tokenize = startHtmlLine(state.tokenize))(stream, state);
 344        }
 345        if (stream.match(/^[|']/)) {
 346          return startHtmlMode(stream, state, 1);
 347        }
 348        if (stream.match(/^\/(!|\[\w+])?/)) {
 349          return commentMode(stream, state);
 350        }
 351        if (stream.match(/^(-|==?[<>]?)/)) {
 352          state.tokenize = lineContinuable(stream.column(), commaContinuable(stream.column(), ruby));
 353          return "slimSwitch";
 354        }
 355        if (stream.match(/^doctype\b/)) {
 356          state.tokenize = doctypeLine;
 357          return "keyword";
 358        }
 359  
 360        var m = stream.match(embeddedRegexp);
 361        if (m) {
 362          return startSubMode(m[1], state);
 363        }
 364  
 365        return slimTag(stream, state);
 366      }
 367  
 368      function slim(stream, state) {
 369        if (state.startOfLine) {
 370          return startLine(stream, state);
 371        }
 372        return slimTag(stream, state);
 373      }
 374  
 375      function slimTag(stream, state) {
 376        if (stream.eat('*')) {
 377          state.tokenize = startRubySplat(slimTagExtras);
 378          return null;
 379        }
 380        if (stream.match(nameRegexp)) {
 381          state.tokenize = slimTagExtras;
 382          return "slimTag";
 383        }
 384        return slimClass(stream, state);
 385      }
 386      function slimTagExtras(stream, state) {
 387        if (stream.match(/^(<>?|><?)/)) {
 388          state.tokenize = slimClass;
 389          return null;
 390        }
 391        return slimClass(stream, state);
 392      }
 393      function slimClass(stream, state) {
 394        if (stream.match(classIdRegexp)) {
 395          state.tokenize = slimClass;
 396          return "slimId";
 397        }
 398        if (stream.match(classNameRegexp)) {
 399          state.tokenize = slimClass;
 400          return "slimClass";
 401        }
 402        return slimAttribute(stream, state);
 403      }
 404      function slimAttribute(stream, state) {
 405        if (stream.match(/^([\[\{\(])/)) {
 406          return startAttributeWrapperMode(state, closing[RegExp.$1], slimAttribute);
 407        }
 408        if (stream.match(attributeNameRegexp)) {
 409          state.tokenize = slimAttributeAssign;
 410          return "slimAttribute";
 411        }
 412        if (stream.peek() == '*') {
 413          stream.next();
 414          state.tokenize = startRubySplat(slimContent);
 415          return null;
 416        }
 417        return slimContent(stream, state);
 418      }
 419      function slimAttributeAssign(stream, state) {
 420        if (stream.match(/^==?/)) {
 421          state.tokenize = slimAttributeValue;
 422          return null;
 423        }
 424        // should never happen, because of forward lookup
 425        return slimAttribute(stream, state);
 426      }
 427  
 428      function slimAttributeValue(stream, state) {
 429        var ch = stream.peek();
 430        if (ch == '"' || ch == "\'") {
 431          state.tokenize = readQuoted(ch, "string", true, false, slimAttribute);
 432          stream.next();
 433          return state.tokenize(stream, state);
 434        }
 435        if (ch == '[') {
 436          return startRubySplat(slimAttribute)(stream, state);
 437        }
 438        if (ch == ':') {
 439          return startRubySplat(slimAttributeSymbols)(stream, state);
 440        }
 441        if (stream.match(/^(true|false|nil)\b/)) {
 442          state.tokenize = slimAttribute;
 443          return "keyword";
 444        }
 445        return startRubySplat(slimAttribute)(stream, state);
 446      }
 447      function slimAttributeSymbols(stream, state) {
 448        stream.backUp(1);
 449        if (stream.match(/^[^\s],(?=:)/)) {
 450          state.tokenize = startRubySplat(slimAttributeSymbols);
 451          return null;
 452        }
 453        stream.next();
 454        return slimAttribute(stream, state);
 455      }
 456      function readQuoted(quote, style, embed, unescaped, nextTokenize) {
 457        return function(stream, state) {
 458          finishContinue(state);
 459          var fresh = stream.current().length == 0;
 460          if (stream.match(/^\\$/, fresh)) {
 461            if (!fresh) return style;
 462            continueLine(state, state.indented);
 463            return "lineContinuation";
 464          }
 465          if (stream.match(/^#\{/, fresh)) {
 466            if (!fresh) return style;
 467            state.tokenize = rubyInQuote("}", state.tokenize);
 468            return null;
 469          }
 470          var escaped = false, ch;
 471          while ((ch = stream.next()) != null) {
 472            if (ch == quote && (unescaped || !escaped)) {
 473              state.tokenize = nextTokenize;
 474              break;
 475            }
 476            if (embed && ch == "#" && !escaped) {
 477              if (stream.eat("{")) {
 478                stream.backUp(2);
 479                break;
 480              }
 481            }
 482            escaped = !escaped && ch == "\\";
 483          }
 484          if (stream.eol() && escaped) {
 485            stream.backUp(1);
 486          }
 487          return style;
 488        };
 489      }
 490      function slimContent(stream, state) {
 491        if (stream.match(/^==?/)) {
 492          state.tokenize = ruby;
 493          return "slimSwitch";
 494        }
 495        if (stream.match(/^\/$/)) { // tag close hint
 496          state.tokenize = slim;
 497          return null;
 498        }
 499        if (stream.match(/^:/)) { // inline tag
 500          state.tokenize = slimTag;
 501          return "slimSwitch";
 502        }
 503        startHtmlMode(stream, state, 0);
 504        return state.tokenize(stream, state);
 505      }
 506  
 507      var mode = {
 508        // default to html mode
 509        startState: function() {
 510          var htmlState = CodeMirror.startState(htmlMode);
 511          var rubyState = CodeMirror.startState(rubyMode);
 512          return {
 513            htmlState: htmlState,
 514            rubyState: rubyState,
 515            stack: null,
 516            last: null,
 517            tokenize: slim,
 518            line: slim,
 519            indented: 0
 520          };
 521        },
 522  
 523        copyState: function(state) {
 524          return {
 525            htmlState : CodeMirror.copyState(htmlMode, state.htmlState),
 526            rubyState: CodeMirror.copyState(rubyMode, state.rubyState),
 527            subMode: state.subMode,
 528            subState: state.subMode && CodeMirror.copyState(state.subMode, state.subState),
 529            stack: state.stack,
 530            last: state.last,
 531            tokenize: state.tokenize,
 532            line: state.line
 533          };
 534        },
 535  
 536        token: function(stream, state) {
 537          if (stream.sol()) {
 538            state.indented = stream.indentation();
 539            state.startOfLine = true;
 540            state.tokenize = state.line;
 541            while (state.stack && state.stack.indented > state.indented && state.last != "slimSubmode") {
 542              state.line = state.tokenize = state.stack.tokenize;
 543              state.stack = state.stack.parent;
 544              state.subMode = null;
 545              state.subState = null;
 546            }
 547          }
 548          if (stream.eatSpace()) return null;
 549          var style = state.tokenize(stream, state);
 550          state.startOfLine = false;
 551          if (style) state.last = style;
 552          return styleMap.hasOwnProperty(style) ? styleMap[style] : style;
 553        },
 554  
 555        blankLine: function(state) {
 556          if (state.subMode && state.subMode.blankLine) {
 557            return state.subMode.blankLine(state.subState);
 558          }
 559        },
 560  
 561        innerMode: function(state) {
 562          if (state.subMode) return {state: state.subState, mode: state.subMode};
 563          return {state: state, mode: mode};
 564        }
 565  
 566        //indent: function(state) {
 567        //  return state.indented;
 568        //}
 569      };
 570      return mode;
 571    }, "htmlmixed", "ruby");
 572  
 573    CodeMirror.defineMIME("text/x-slim", "slim");
 574    CodeMirror.defineMIME("application/x-slim", "slim");
 575  });


Generated: Wed Sep 7 05:41:13 2022 Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer