diff options
Diffstat (limited to 'public/vendor/codemirror/mode/slim')
-rwxr-xr-x | public/vendor/codemirror/mode/slim/index.html | 96 | ||||
-rwxr-xr-x | public/vendor/codemirror/mode/slim/slim.js | 575 | ||||
-rwxr-xr-x | public/vendor/codemirror/mode/slim/test.js | 96 |
3 files changed, 767 insertions, 0 deletions
diff --git a/public/vendor/codemirror/mode/slim/index.html b/public/vendor/codemirror/mode/slim/index.html new file mode 100755 index 00000000..7fa4e50d --- /dev/null +++ b/public/vendor/codemirror/mode/slim/index.html @@ -0,0 +1,96 @@ +<!doctype html> + +<title>CodeMirror: SLIM mode</title> +<meta charset="utf-8"/> +<link rel=stylesheet href="../../doc/docs.css"> + +<link rel="stylesheet" href="../../lib/codemirror.css"> +<link rel="stylesheet" href="../../theme/ambiance.css"> +<script src="https://code.jquery.com/jquery-1.11.1.min.js"></script> +<script src="https://code.jquery.com/ui/1.11.0/jquery-ui.min.js"></script> +<link rel="stylesheet" href="https://code.jquery.com/ui/1.11.0/themes/smoothness/jquery-ui.css"> +<script src="../../lib/codemirror.js"></script> +<script src="../xml/xml.js"></script> +<script src="../htmlembedded/htmlembedded.js"></script> +<script src="../htmlmixed/htmlmixed.js"></script> +<script src="../coffeescript/coffeescript.js"></script> +<script src="../javascript/javascript.js"></script> +<script src="../ruby/ruby.js"></script> +<script src="../markdown/markdown.js"></script> +<script src="slim.js"></script> +<style>.CodeMirror {background: #f8f8f8;}</style> +<div id=nav> + <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a> + + <ul> + <li><a href="../../index.html">Home</a> + <li><a href="../../doc/manual.html">Manual</a> + <li><a href="https://github.com/codemirror/codemirror">Code</a> + </ul> + <ul> + <li><a href="../index.html">Language modes</a> + <li><a class=active href="#">SLIM</a> + </ul> +</div> + +<article> + <h2>SLIM mode</h2> + <form><textarea id="code" name="code"> +body + table + - for user in users + td id="user_#{user.id}" class=user.role + a href=user_action(user, :edit) Edit #{user.name} + a href=(path_to_user user) = user.name +body + h1(id="logo") = page_logo + h2[id="tagline" class="small tagline"] = page_tagline + +h2[id="tagline" + class="small tagline"] = page_tagline + +h1 id = "logo" = page_logo +h2 [ id = "tagline" ] = page_tagline + +/ comment + second line +/! html comment + second line +<!-- html comment --> +<a href="#{'hello' if set}">link</a> +a.slim href="work" disabled=false running==:atom Text <b>bold</b> +.clazz data-id="test" == 'hello' unless quark + | Text mode #{12} + Second line += x ||= :ruby_atom +#menu.left + - @env.each do |x| + li: a = x +*@dyntag attr="val" +.first *{:class => [:second, :third]} Text +.second class=["text","more"] +.third class=:text,:symbol + + </textarea></form> + <script> + var editor = CodeMirror.fromTextArea(document.getElementById("code"), { + lineNumbers: true, + theme: "ambiance", + mode: "application/x-slim" + }); + $('.CodeMirror').resizable({ + resize: function() { + editor.setSize($(this).width(), $(this).height()); + //editor.refresh(); + } + }); + </script> + + <p><strong>MIME types defined:</strong> <code>application/x-slim</code>.</p> + + <p> + <strong>Parsing/Highlighting Tests:</strong> + <a href="../../test/index.html#slim_*">normal</a>, + <a href="../../test/index.html#verbose,slim_*">verbose</a>. + </p> +</article> diff --git a/public/vendor/codemirror/mode/slim/slim.js b/public/vendor/codemirror/mode/slim/slim.js new file mode 100755 index 00000000..164464d0 --- /dev/null +++ b/public/vendor/codemirror/mode/slim/slim.js @@ -0,0 +1,575 @@ +// CodeMirror, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + +// Slim Highlighting for CodeMirror copyright (c) HicknHack Software Gmbh + +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror"), require("../htmlmixed/htmlmixed"), require("../ruby/ruby")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror", "../htmlmixed/htmlmixed", "../ruby/ruby"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { +"use strict"; + + CodeMirror.defineMode("slim", function(config) { + var htmlMode = CodeMirror.getMode(config, {name: "htmlmixed"}); + var rubyMode = CodeMirror.getMode(config, "ruby"); + var modes = { html: htmlMode, ruby: rubyMode }; + var embedded = { + ruby: "ruby", + javascript: "javascript", + css: "text/css", + sass: "text/x-sass", + scss: "text/x-scss", + less: "text/x-less", + styl: "text/x-styl", // no highlighting so far + coffee: "coffeescript", + asciidoc: "text/x-asciidoc", + markdown: "text/x-markdown", + textile: "text/x-textile", // no highlighting so far + creole: "text/x-creole", // no highlighting so far + wiki: "text/x-wiki", // no highlighting so far + mediawiki: "text/x-mediawiki", // no highlighting so far + rdoc: "text/x-rdoc", // no highlighting so far + builder: "text/x-builder", // no highlighting so far + nokogiri: "text/x-nokogiri", // no highlighting so far + erb: "application/x-erb" + }; + var embeddedRegexp = function(map){ + var arr = []; + for(var key in map) arr.push(key); + return new RegExp("^("+arr.join('|')+"):"); + }(embedded); + + var styleMap = { + "commentLine": "comment", + "slimSwitch": "operator special", + "slimTag": "tag", + "slimId": "attribute def", + "slimClass": "attribute qualifier", + "slimAttribute": "attribute", + "slimSubmode": "keyword special", + "closeAttributeTag": null, + "slimDoctype": null, + "lineContinuation": null + }; + var closing = { + "{": "}", + "[": "]", + "(": ")" + }; + + 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"; + var nameChar = nameStartChar + "\\-0-9\xB7\u0300-\u036F\u203F-\u2040"; + var nameRegexp = new RegExp("^[:"+nameStartChar+"](?::["+nameChar+"]|["+nameChar+"]*)"); + var attributeNameRegexp = new RegExp("^[:"+nameStartChar+"][:\\."+nameChar+"]*(?=\\s*=)"); + var wrappedAttributeNameRegexp = new RegExp("^[:"+nameStartChar+"][:\\."+nameChar+"]*"); + var classNameRegexp = /^\.-?[_a-zA-Z]+[\w\-]*/; + var classIdRegexp = /^#[_a-zA-Z]+[\w\-]*/; + + function backup(pos, tokenize, style) { + var restore = function(stream, state) { + state.tokenize = tokenize; + if (stream.pos < pos) { + stream.pos = pos; + return style; + } + return state.tokenize(stream, state); + }; + return function(stream, state) { + state.tokenize = restore; + return tokenize(stream, state); + }; + } + + function maybeBackup(stream, state, pat, offset, style) { + var cur = stream.current(); + var idx = cur.search(pat); + if (idx > -1) { + state.tokenize = backup(stream.pos, state.tokenize, style); + stream.backUp(cur.length - idx - offset); + } + return style; + } + + function continueLine(state, column) { + state.stack = { + parent: state.stack, + style: "continuation", + indented: column, + tokenize: state.line + }; + state.line = state.tokenize; + } + function finishContinue(state) { + if (state.line == state.tokenize) { + state.line = state.stack.tokenize; + state.stack = state.stack.parent; + } + } + + function lineContinuable(column, tokenize) { + return function(stream, state) { + finishContinue(state); + if (stream.match(/^\\$/)) { + continueLine(state, column); + return "lineContinuation"; + } + var style = tokenize(stream, state); + if (stream.eol() && stream.current().match(/(?:^|[^\\])(?:\\\\)*\\$/)) { + stream.backUp(1); + } + return style; + }; + } + function commaContinuable(column, tokenize) { + return function(stream, state) { + finishContinue(state); + var style = tokenize(stream, state); + if (stream.eol() && stream.current().match(/,$/)) { + continueLine(state, column); + } + return style; + }; + } + + function rubyInQuote(endQuote, tokenize) { + // TODO: add multi line support + return function(stream, state) { + var ch = stream.peek(); + if (ch == endQuote && state.rubyState.tokenize.length == 1) { + // step out of ruby context as it seems to complete processing all the braces + stream.next(); + state.tokenize = tokenize; + return "closeAttributeTag"; + } else { + return ruby(stream, state); + } + }; + } + function startRubySplat(tokenize) { + var rubyState; + var runSplat = function(stream, state) { + if (state.rubyState.tokenize.length == 1 && !state.rubyState.context.prev) { + stream.backUp(1); + if (stream.eatSpace()) { + state.rubyState = rubyState; + state.tokenize = tokenize; + return tokenize(stream, state); + } + stream.next(); + } + return ruby(stream, state); + }; + return function(stream, state) { + rubyState = state.rubyState; + state.rubyState = rubyMode.startState(); + state.tokenize = runSplat; + return ruby(stream, state); + }; + } + + function ruby(stream, state) { + return rubyMode.token(stream, state.rubyState); + } + + function htmlLine(stream, state) { + if (stream.match(/^\\$/)) { + return "lineContinuation"; + } + return html(stream, state); + } + function html(stream, state) { + if (stream.match(/^#\{/)) { + state.tokenize = rubyInQuote("}", state.tokenize); + return null; + } + return maybeBackup(stream, state, /[^\\]#\{/, 1, htmlMode.token(stream, state.htmlState)); + } + + function startHtmlLine(lastTokenize) { + return function(stream, state) { + var style = htmlLine(stream, state); + if (stream.eol()) state.tokenize = lastTokenize; + return style; + }; + } + + function startHtmlMode(stream, state, offset) { + state.stack = { + parent: state.stack, + style: "html", + indented: stream.column() + offset, // pipe + space + tokenize: state.line + }; + state.line = state.tokenize = html; + return null; + } + + function comment(stream, state) { + stream.skipToEnd(); + return state.stack.style; + } + + function commentMode(stream, state) { + state.stack = { + parent: state.stack, + style: "comment", + indented: state.indented + 1, + tokenize: state.line + }; + state.line = comment; + return comment(stream, state); + } + + function attributeWrapper(stream, state) { + if (stream.eat(state.stack.endQuote)) { + state.line = state.stack.line; + state.tokenize = state.stack.tokenize; + state.stack = state.stack.parent; + return null; + } + if (stream.match(wrappedAttributeNameRegexp)) { + state.tokenize = attributeWrapperAssign; + return "slimAttribute"; + } + stream.next(); + return null; + } + function attributeWrapperAssign(stream, state) { + if (stream.match(/^==?/)) { + state.tokenize = attributeWrapperValue; + return null; + } + return attributeWrapper(stream, state); + } + function attributeWrapperValue(stream, state) { + var ch = stream.peek(); + if (ch == '"' || ch == "\'") { + state.tokenize = readQuoted(ch, "string", true, false, attributeWrapper); + stream.next(); + return state.tokenize(stream, state); + } + if (ch == '[') { + return startRubySplat(attributeWrapper)(stream, state); + } + if (stream.match(/^(true|false|nil)\b/)) { + state.tokenize = attributeWrapper; + return "keyword"; + } + return startRubySplat(attributeWrapper)(stream, state); + } + + function startAttributeWrapperMode(state, endQuote, tokenize) { + state.stack = { + parent: state.stack, + style: "wrapper", + indented: state.indented + 1, + tokenize: tokenize, + line: state.line, + endQuote: endQuote + }; + state.line = state.tokenize = attributeWrapper; + return null; + } + + function sub(stream, state) { + if (stream.match(/^#\{/)) { + state.tokenize = rubyInQuote("}", state.tokenize); + return null; + } + var subStream = new CodeMirror.StringStream(stream.string.slice(state.stack.indented), stream.tabSize); + subStream.pos = stream.pos - state.stack.indented; + subStream.start = stream.start - state.stack.indented; + subStream.lastColumnPos = stream.lastColumnPos - state.stack.indented; + subStream.lastColumnValue = stream.lastColumnValue - state.stack.indented; + var style = state.subMode.token(subStream, state.subState); + stream.pos = subStream.pos + state.stack.indented; + return style; + } + function firstSub(stream, state) { + state.stack.indented = stream.column(); + state.line = state.tokenize = sub; + return state.tokenize(stream, state); + } + + function createMode(mode) { + var query = embedded[mode]; + var spec = CodeMirror.mimeModes[query]; + if (spec) { + return CodeMirror.getMode(config, spec); + } + var factory = CodeMirror.modes[query]; + if (factory) { + return factory(config, {name: query}); + } + return CodeMirror.getMode(config, "null"); + } + + function getMode(mode) { + if (!modes.hasOwnProperty(mode)) { + return modes[mode] = createMode(mode); + } + return modes[mode]; + } + + function startSubMode(mode, state) { + var subMode = getMode(mode); + var subState = subMode.startState && subMode.startState(); + + state.subMode = subMode; + state.subState = subState; + + state.stack = { + parent: state.stack, + style: "sub", + indented: state.indented + 1, + tokenize: state.line + }; + state.line = state.tokenize = firstSub; + return "slimSubmode"; + } + + function doctypeLine(stream, _state) { + stream.skipToEnd(); + return "slimDoctype"; + } + + function startLine(stream, state) { + var ch = stream.peek(); + if (ch == '<') { + return (state.tokenize = startHtmlLine(state.tokenize))(stream, state); + } + if (stream.match(/^[|']/)) { + return startHtmlMode(stream, state, 1); + } + if (stream.match(/^\/(!|\[\w+])?/)) { + return commentMode(stream, state); + } + if (stream.match(/^(-|==?[<>]?)/)) { + state.tokenize = lineContinuable(stream.column(), commaContinuable(stream.column(), ruby)); + return "slimSwitch"; + } + if (stream.match(/^doctype\b/)) { + state.tokenize = doctypeLine; + return "keyword"; + } + + var m = stream.match(embeddedRegexp); + if (m) { + return startSubMode(m[1], state); + } + + return slimTag(stream, state); + } + + function slim(stream, state) { + if (state.startOfLine) { + return startLine(stream, state); + } + return slimTag(stream, state); + } + + function slimTag(stream, state) { + if (stream.eat('*')) { + state.tokenize = startRubySplat(slimTagExtras); + return null; + } + if (stream.match(nameRegexp)) { + state.tokenize = slimTagExtras; + return "slimTag"; + } + return slimClass(stream, state); + } + function slimTagExtras(stream, state) { + if (stream.match(/^(<>?|><?)/)) { + state.tokenize = slimClass; + return null; + } + return slimClass(stream, state); + } + function slimClass(stream, state) { + if (stream.match(classIdRegexp)) { + state.tokenize = slimClass; + return "slimId"; + } + if (stream.match(classNameRegexp)) { + state.tokenize = slimClass; + return "slimClass"; + } + return slimAttribute(stream, state); + } + function slimAttribute(stream, state) { + if (stream.match(/^([\[\{\(])/)) { + return startAttributeWrapperMode(state, closing[RegExp.$1], slimAttribute); + } + if (stream.match(attributeNameRegexp)) { + state.tokenize = slimAttributeAssign; + return "slimAttribute"; + } + if (stream.peek() == '*') { + stream.next(); + state.tokenize = startRubySplat(slimContent); + return null; + } + return slimContent(stream, state); + } + function slimAttributeAssign(stream, state) { + if (stream.match(/^==?/)) { + state.tokenize = slimAttributeValue; + return null; + } + // should never happen, because of forward lookup + return slimAttribute(stream, state); + } + + function slimAttributeValue(stream, state) { + var ch = stream.peek(); + if (ch == '"' || ch == "\'") { + state.tokenize = readQuoted(ch, "string", true, false, slimAttribute); + stream.next(); + return state.tokenize(stream, state); + } + if (ch == '[') { + return startRubySplat(slimAttribute)(stream, state); + } + if (ch == ':') { + return startRubySplat(slimAttributeSymbols)(stream, state); + } + if (stream.match(/^(true|false|nil)\b/)) { + state.tokenize = slimAttribute; + return "keyword"; + } + return startRubySplat(slimAttribute)(stream, state); + } + function slimAttributeSymbols(stream, state) { + stream.backUp(1); + if (stream.match(/^[^\s],(?=:)/)) { + state.tokenize = startRubySplat(slimAttributeSymbols); + return null; + } + stream.next(); + return slimAttribute(stream, state); + } + function readQuoted(quote, style, embed, unescaped, nextTokenize) { + return function(stream, state) { + finishContinue(state); + var fresh = stream.current().length == 0; + if (stream.match(/^\\$/, fresh)) { + if (!fresh) return style; + continueLine(state, state.indented); + return "lineContinuation"; + } + if (stream.match(/^#\{/, fresh)) { + if (!fresh) return style; + state.tokenize = rubyInQuote("}", state.tokenize); + return null; + } + var escaped = false, ch; + while ((ch = stream.next()) != null) { + if (ch == quote && (unescaped || !escaped)) { + state.tokenize = nextTokenize; + break; + } + if (embed && ch == "#" && !escaped) { + if (stream.eat("{")) { + stream.backUp(2); + break; + } + } + escaped = !escaped && ch == "\\"; + } + if (stream.eol() && escaped) { + stream.backUp(1); + } + return style; + }; + } + function slimContent(stream, state) { + if (stream.match(/^==?/)) { + state.tokenize = ruby; + return "slimSwitch"; + } + if (stream.match(/^\/$/)) { // tag close hint + state.tokenize = slim; + return null; + } + if (stream.match(/^:/)) { // inline tag + state.tokenize = slimTag; + return "slimSwitch"; + } + startHtmlMode(stream, state, 0); + return state.tokenize(stream, state); + } + + var mode = { + // default to html mode + startState: function() { + var htmlState = htmlMode.startState(); + var rubyState = rubyMode.startState(); + return { + htmlState: htmlState, + rubyState: rubyState, + stack: null, + last: null, + tokenize: slim, + line: slim, + indented: 0 + }; + }, + + copyState: function(state) { + return { + htmlState : CodeMirror.copyState(htmlMode, state.htmlState), + rubyState: CodeMirror.copyState(rubyMode, state.rubyState), + subMode: state.subMode, + subState: state.subMode && CodeMirror.copyState(state.subMode, state.subState), + stack: state.stack, + last: state.last, + tokenize: state.tokenize, + line: state.line + }; + }, + + token: function(stream, state) { + if (stream.sol()) { + state.indented = stream.indentation(); + state.startOfLine = true; + state.tokenize = state.line; + while (state.stack && state.stack.indented > state.indented && state.last != "slimSubmode") { + state.line = state.tokenize = state.stack.tokenize; + state.stack = state.stack.parent; + state.subMode = null; + state.subState = null; + } + } + if (stream.eatSpace()) return null; + var style = state.tokenize(stream, state); + state.startOfLine = false; + if (style) state.last = style; + return styleMap.hasOwnProperty(style) ? styleMap[style] : style; + }, + + blankLine: function(state) { + if (state.subMode && state.subMode.blankLine) { + return state.subMode.blankLine(state.subState); + } + }, + + innerMode: function(state) { + if (state.subMode) return {state: state.subState, mode: state.subMode}; + return {state: state, mode: mode}; + } + + //indent: function(state) { + // return state.indented; + //} + }; + return mode; + }, "htmlmixed", "ruby"); + + CodeMirror.defineMIME("text/x-slim", "slim"); + CodeMirror.defineMIME("application/x-slim", "slim"); +}); diff --git a/public/vendor/codemirror/mode/slim/test.js b/public/vendor/codemirror/mode/slim/test.js new file mode 100755 index 00000000..be4ddacb --- /dev/null +++ b/public/vendor/codemirror/mode/slim/test.js @@ -0,0 +1,96 @@ +// CodeMirror, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + +// Slim Highlighting for CodeMirror copyright (c) HicknHack Software Gmbh + +(function() { + var mode = CodeMirror.getMode({tabSize: 4, indentUnit: 2}, "slim"); + function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); } + + // Requires at least one media query + MT("elementName", + "[tag h1] Hey There"); + + MT("oneElementPerLine", + "[tag h1] Hey There .h2"); + + MT("idShortcut", + "[attribute&def #test] Hey There"); + + MT("tagWithIdShortcuts", + "[tag h1][attribute&def #test] Hey There"); + + MT("classShortcut", + "[attribute&qualifier .hello] Hey There"); + + MT("tagWithIdAndClassShortcuts", + "[tag h1][attribute&def #test][attribute&qualifier .hello] Hey There"); + + MT("docType", + "[keyword doctype] xml"); + + MT("comment", + "[comment / Hello WORLD]"); + + MT("notComment", + "[tag h1] This is not a / comment "); + + MT("attributes", + "[tag a]([attribute title]=[string \"test\"]) [attribute href]=[string \"link\"]}"); + + MT("multiLineAttributes", + "[tag a]([attribute title]=[string \"test\"]", + " ) [attribute href]=[string \"link\"]}"); + + MT("htmlCode", + "[tag&bracket <][tag h1][tag&bracket >]Title[tag&bracket </][tag h1][tag&bracket >]"); + + MT("rubyBlock", + "[operator&special =][variable-2 @item]"); + + MT("selectorRubyBlock", + "[tag a][attribute&qualifier .test][operator&special =] [variable-2 @item]"); + + MT("nestedRubyBlock", + "[tag a]", + " [operator&special =][variable puts] [string \"test\"]"); + + MT("multilinePlaintext", + "[tag p]", + " | Hello,", + " World"); + + MT("multilineRuby", + "[tag p]", + " [comment /# this is a comment]", + " [comment and this is a comment too]", + " | Date/Time", + " [operator&special -] [variable now] [operator =] [tag DateTime][operator .][property now]", + " [tag strong][operator&special =] [variable now]", + " [operator&special -] [keyword if] [variable now] [operator >] [tag DateTime][operator .][property parse]([string \"December 31, 2006\"])", + " [operator&special =][string \"Happy\"]", + " [operator&special =][string \"Belated\"]", + " [operator&special =][string \"Birthday\"]"); + + MT("multilineComment", + "[comment /]", + " [comment Multiline]", + " [comment Comment]"); + + MT("hamlAfterRubyTag", + "[attribute&qualifier .block]", + " [tag strong][operator&special =] [variable now]", + " [attribute&qualifier .test]", + " [operator&special =][variable now]", + " [attribute&qualifier .right]"); + + MT("stretchedRuby", + "[operator&special =] [variable puts] [string \"Hello\"],", + " [string \"World\"]"); + + MT("interpolationInHashAttribute", + "[tag div]{[attribute id] = [string \"]#{[variable test]}[string _]#{[variable ting]}[string \"]} test"); + + MT("interpolationInHTMLAttribute", + "[tag div]([attribute title]=[string \"]#{[variable test]}[string _]#{[variable ting]()}[string \"]) Test"); +})(); |