Commit 8e335a7c authored by JOE Thunyathep S's avatar JOE Thunyathep S
Browse files

up

parent 43ea69a2
Pipeline #1969 passed with stage
in 36 seconds
// 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"), require("../xml/xml"), require("../javascript/javascript"))
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror", "../xml/xml", "../javascript/javascript"], mod)
else // Plain browser env
mod(CodeMirror)
})(function(CodeMirror) {
"use strict"
// Depth means the amount of open braces in JS context, in XML
// context 0 means not in tag, 1 means in tag, and 2 means in tag
// and js block comment.
function Context(state, mode, depth, prev) {
this.state = state; this.mode = mode; this.depth = depth; this.prev = prev
}
function copyContext(context) {
return new Context(CodeMirror.copyState(context.mode, context.state),
context.mode,
context.depth,
context.prev && copyContext(context.prev))
}
CodeMirror.defineMode("jsx", function(config, modeConfig) {
var xmlMode = CodeMirror.getMode(config, {name: "xml", allowMissing: true, multilineTagIndentPastTag: false, allowMissingTagName: true})
var jsMode = CodeMirror.getMode(config, modeConfig && modeConfig.base || "javascript")
function flatXMLIndent(state) {
var tagName = state.tagName
state.tagName = null
var result = xmlMode.indent(state, "", "")
state.tagName = tagName
return result
}
function token(stream, state) {
if (state.context.mode == xmlMode)
return xmlToken(stream, state, state.context)
else
return jsToken(stream, state, state.context)
}
function xmlToken(stream, state, cx) {
if (cx.depth == 2) { // Inside a JS /* */ comment
if (stream.match(/^.*?\*\//)) cx.depth = 1
else stream.skipToEnd()
return "comment"
}
if (stream.peek() == "{") {
xmlMode.skipAttribute(cx.state)
var indent = flatXMLIndent(cx.state), xmlContext = cx.state.context
// If JS starts on same line as tag
if (xmlContext && stream.match(/^[^>]*>\s*$/, false)) {
while (xmlContext.prev && !xmlContext.startOfLine)
xmlContext = xmlContext.prev
// If tag starts the line, use XML indentation level
if (xmlContext.startOfLine) indent -= config.indentUnit
// Else use JS indentation level
else if (cx.prev.state.lexical) indent = cx.prev.state.lexical.indented
// Else if inside of tag
} else if (cx.depth == 1) {
indent += config.indentUnit
}
state.context = new Context(CodeMirror.startState(jsMode, indent),
jsMode, 0, state.context)
return null
}
if (cx.depth == 1) { // Inside of tag
if (stream.peek() == "<") { // Tag inside of tag
xmlMode.skipAttribute(cx.state)
state.context = new Context(CodeMirror.startState(xmlMode, flatXMLIndent(cx.state)),
xmlMode, 0, state.context)
return null
} else if (stream.match("//")) {
stream.skipToEnd()
return "comment"
} else if (stream.match("/*")) {
cx.depth = 2
return token(stream, state)
}
}
var style = xmlMode.token(stream, cx.state), cur = stream.current(), stop
if (/\btag\b/.test(style)) {
if (/>$/.test(cur)) {
if (cx.state.context) cx.depth = 0
else state.context = state.context.prev
} else if (/^</.test(cur)) {
cx.depth = 1
}
} else if (!style && (stop = cur.indexOf("{")) > -1) {
stream.backUp(cur.length - stop)
}
return style
}
function jsToken(stream, state, cx) {
if (stream.peek() == "<" && jsMode.expressionAllowed(stream, cx.state)) {
jsMode.skipExpression(cx.state)
state.context = new Context(CodeMirror.startState(xmlMode, jsMode.indent(cx.state, "", "")),
xmlMode, 0, state.context)
return null
}
var style = jsMode.token(stream, cx.state)
if (!style && cx.depth != null) {
var cur = stream.current()
if (cur == "{") {
cx.depth++
} else if (cur == "}") {
if (--cx.depth == 0) state.context = state.context.prev
}
}
return style
}
return {
startState: function() {
return {context: new Context(CodeMirror.startState(jsMode), jsMode)}
},
copyState: function(state) {
return {context: copyContext(state.context)}
},
token: token,
indent: function(state, textAfter, fullLine) {
return state.context.mode.indent(state.context.state, textAfter, fullLine)
},
innerMode: function(state) {
return state.context
}
}
}, "xml", "javascript")
CodeMirror.defineMIME("text/jsx", "jsx")
CodeMirror.defineMIME("text/typescript-jsx", {name: "jsx", base: {name: "javascript", typescript: true}})
});
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function() {
var mode = CodeMirror.getMode({indentUnit: 2}, "jsx")
function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)) }
MT("selfclose",
"[keyword var] [def x] [operator =] [bracket&tag <] [tag foo] [bracket&tag />] [operator +] [number 1];")
MT("openclose",
"([bracket&tag <][tag foo][bracket&tag >]hello [atom &amp;][bracket&tag </][tag foo][bracket&tag >][operator ++])")
MT("openclosefragment",
"([bracket&tag <><][tag foo][bracket&tag >]hello [atom &amp;][bracket&tag </][tag foo][bracket&tag ></>][operator ++])")
MT("attr",
"([bracket&tag <][tag foo] [attribute abc]=[string 'value'][bracket&tag >]hello [atom &amp;][bracket&tag </][tag foo][bracket&tag >][operator ++])")
MT("braced_attr",
"([bracket&tag <][tag foo] [attribute abc]={[number 10]}[bracket&tag >]hello [atom &amp;][bracket&tag </][tag foo][bracket&tag >][operator ++])")
MT("braced_text",
"([bracket&tag <][tag foo][bracket&tag >]hello {[number 10]} [atom &amp;][bracket&tag </][tag foo][bracket&tag >][operator ++])")
MT("nested_tag",
"([bracket&tag <][tag foo][bracket&tag ><][tag bar][bracket&tag ></][tag bar][bracket&tag ></][tag foo][bracket&tag >][operator ++])")
MT("nested_jsx",
"[keyword return] (",
" [bracket&tag <][tag foo][bracket&tag >]",
" say {[number 1] [operator +] [bracket&tag <][tag bar] [attribute attr]={[number 10]}[bracket&tag />]}!",
" [bracket&tag </][tag foo][bracket&tag >][operator ++]",
")")
MT("preserve_js_context",
"[variable x] [operator =] [string-2 `quasi${][bracket&tag <][tag foo][bracket&tag />][string-2 }quoted`]")
MT("string_interpolation",
"[variable x] [operator =] [string-2 `quasi<code>${] [number 10] [string-2 }</code>`]")
MT("line_comment",
"([bracket&tag <][tag foo] [comment // hello]",
" [bracket&tag ></][tag foo][bracket&tag >][operator ++])")
MT("line_comment_not_in_tag",
"([bracket&tag <][tag foo][bracket&tag >] // hello",
" [bracket&tag </][tag foo][bracket&tag >][operator ++])")
MT("block_comment",
"([bracket&tag <][tag foo] [comment /* hello]",
"[comment line 2]",
"[comment line 3 */] [bracket&tag ></][tag foo][bracket&tag >][operator ++])")
MT("block_comment_not_in_tag",
"([bracket&tag <][tag foo][bracket&tag >]/* hello",
" line 2",
" line 3 */ [bracket&tag </][tag foo][bracket&tag >][operator ++])")
MT("missing_attr",
"([bracket&tag <][tag foo] [attribute selected][bracket&tag />][operator ++])")
MT("indent_js",
"([bracket&tag <][tag foo][bracket&tag >]",
" [bracket&tag <][tag bar] [attribute baz]={[keyword function]() {",
" [keyword return] [number 10]",
" }}[bracket&tag />]",
" [bracket&tag </][tag foo][bracket&tag >])")
MT("spread",
"([bracket&tag <][tag foo] [attribute bar]={[meta ...][variable baz] [operator /][number 2]}[bracket&tag />])")
MT("tag_attribute",
"([bracket&tag <][tag foo] [attribute bar]=[bracket&tag <][tag foo][bracket&tag />/>][operator ++])")
var ts_mode = CodeMirror.getMode({indentUnit: 2}, "text/typescript-jsx")
function TS(name) { test.mode(name, ts_mode, Array.prototype.slice.call(arguments, 1)) }
TS("tsx_react_integration",
"[keyword interface] [def Props] {",
" [property foo]: [type string];",
"}",
"[keyword class] [def MyComponent] [keyword extends] [type React].[type Component] [operator <] [type Props], [type any] [operator >] {",
" [property render]() {",
" [keyword return] [bracket&tag <][tag span][bracket&tag >]{[keyword this].[property props].[property foo]}[bracket&tag </][tag span][bracket&tag >]",
" }",
"}",
"[bracket&tag <][tag MyComponent] [attribute foo]=[string \"bar\"] [bracket&tag />]; [comment //ok]",
"[bracket&tag <][tag MyComponent] [attribute foo]={[number 0]} [bracket&tag />]; [comment //error]")
})()
<!doctype html>
<title>CodeMirror: Julia mode</title>
<meta charset="utf-8"/>
<link rel=stylesheet href="../../doc/docs.css">
<link rel="stylesheet" href="../../lib/codemirror.css">
<script src="../../lib/codemirror.js"></script>
<script src="../../addon/edit/matchbrackets.js"></script>
<script src="julia.js"></script>
<style>.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
<div id=nav>
<a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png" alt=""></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="#">Julia</a>
</ul>
</div>
<article>
<h2>Julia mode</h2>
<div><textarea id="code" name="code">
#numbers
1234
1234im
.234
.234im
2.23im
2.3f3
23e2
0x234
#strings
'a'
"asdf"
r"regex"
b"bytestring"
"""
multiline string
"""
#identifiers
a
as123
function_name!
#unicode identifiers
# a = x\ddot
a⃗ = ẍ
# a = v\dot
a⃗ = v̇
#F\vec = m \cdotp a\vec
F⃗ = m·a⃗
#literal identifier multiples
3x
4[1, 2, 3]
#dicts and indexing
x=[1, 2, 3]
x[end-1]
x={"julia"=>"language of technical computing"}
#exception handling
try
f()
catch
@printf "Error"
finally
g()
end
#types
immutable Color{T<:Number}
r::T
g::T
b::T
end
#functions
function change!(x::Vector{Float64})
for i = 1:length(x)
x[i] *= 2
end
end
#function invocation
f('b', (2, 3)...)
#operators
|=
&=
^=
\-
%=
*=
+=
-=
<=
>=
!=
==
%
*
+
-
<
>
!
=
|
&
^
\
?
~
:
$
<:
.<
.>
<<
<<=
>>
>>>>
>>=
>>>=
<<=
<<<=
.<=
.>=
.==
->
//
in
...
//
:=
.//=
.*=
./=
.^=
.%=
.+=
.-=
\=
\\=
||
===
&&
|=
.|=
<:
>:
|>
<|
::
x ? y : z
#macros
@spawnat 2 1+1
@eval(:x)
#keywords and operators
if else elseif while for
begin let end do
try catch finally return break continue
global local const
export import importall using
function macro module baremodule
type immutable quote
true false enumerate
</textarea></div>
<script>
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
mode: {name: "julia",
},
lineNumbers: true,
indentUnit: 4,
matchBrackets: true
});
</script>
<p><strong>MIME types defined:</strong> <code>text/x-julia</code>.</p>
</article>
// 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);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
CodeMirror.defineMode("julia", function(config, parserConf) {
function wordRegexp(words, end) {
if (typeof end === "undefined") { end = "\\b"; }
return new RegExp("^((" + words.join(")|(") + "))" + end);
}
var octChar = "\\\\[0-7]{1,3}";
var hexChar = "\\\\x[A-Fa-f0-9]{1,2}";
var sChar = "\\\\[abefnrtv0%?'\"\\\\]";
var uChar = "([^\\u0027\\u005C\\uD800-\\uDFFF]|[\\uD800-\\uDFFF][\\uDC00-\\uDFFF])";
var operators = parserConf.operators || wordRegexp([
"[<>]:", "[<>=]=", "<<=?", ">>>?=?", "=>", "->", "\\/\\/",
"[\\\\%*+\\-<>!=\\/^|&\\u00F7\\u22BB]=?", "\\?", "\\$", "~", ":",
"\\u00D7", "\\u2208", "\\u2209", "\\u220B", "\\u220C", "\\u2218",
"\\u221A", "\\u221B", "\\u2229", "\\u222A", "\\u2260", "\\u2264",
"\\u2265", "\\u2286", "\\u2288", "\\u228A", "\\u22C5",
"\\b(in|isa)\\b(?!\.?\\()"], "");
var delimiters = parserConf.delimiters || /^[;,()[\]{}]/;
var identifiers = parserConf.identifiers ||
/^[_A-Za-z\u00A1-\u2217\u2219-\uFFFF][\w\u00A1-\u2217\u2219-\uFFFF]*!*/;
var chars = wordRegexp([octChar, hexChar, sChar, uChar], "'");
var openersList = ["begin", "function", "type", "struct", "immutable", "let",
"macro", "for", "while", "quote", "if", "else", "elseif", "try",
"finally", "catch", "do"];
var closersList = ["end", "else", "elseif", "catch", "finally"];
var keywordsList = ["if", "else", "elseif", "while", "for", "begin", "let",
"end", "do", "try", "catch", "finally", "return", "break", "continue",
"global", "local", "const", "export", "import", "importall", "using",
"function", "where", "macro", "module", "baremodule", "struct", "type",
"mutable", "immutable", "quote", "typealias", "abstract", "primitive",
"bitstype"];
var builtinsList = ["true", "false", "nothing", "NaN", "Inf"];
CodeMirror.registerHelper("hintWords", "julia", keywordsList.concat(builtinsList));
var openers = wordRegexp(openersList);
var closers = wordRegexp(closersList);
var keywords = wordRegexp(keywordsList);
var builtins = wordRegexp(builtinsList);
var macro = /^@[_A-Za-z][\w]*/;
var symbol = /^:[_A-Za-z\u00A1-\uFFFF][\w\u00A1-\uFFFF]*!*/;
var stringPrefixes = /^(`|([_A-Za-z\u00A1-\uFFFF]*"("")?))/;
function inArray(state) {
return (state.nestedArrays > 0);
}
function inGenerator(state) {
return (state.nestedGenerators > 0);
}
function currentScope(state, n) {
if (typeof(n) === "undefined") { n = 0; }
if (state.scopes.length <= n) {
return null;
}
return state.scopes[state.scopes.length - (n + 1)];
}
// tokenizers
function tokenBase(stream, state) {
// Handle multiline comments
if (stream.match(/^#=/, false)) {
state.tokenize = tokenComment;
return state.tokenize(stream, state);
}
// Handle scope changes
var leavingExpr = state.leavingExpr;
if (stream.sol()) {
leavingExpr = false;
}
state.leavingExpr = false;
if (leavingExpr) {
if (stream.match(/^'+/)) {
return "operator";
}
}
if (stream.match(/\.{4,}/)) {
return "error";
} else if (stream.match(/\.{1,3}/)) {
return "operator";
}
if (stream.eatSpace()) {
return null;
}
var ch = stream.peek();
// Handle single line comments
if (ch === '#') {
stream.skipToEnd();
return "comment";
}
if (ch === '[') {
state.scopes.push('[');
state.nestedArrays++;
}
if (ch === '(') {
state.scopes.push('(');
state.nestedGenerators++;
}
if (inArray(state) && ch === ']') {
while (currentScope(state) !== "[") { state.scopes.pop(); }
state.scopes.pop();
state.nestedArrays--;
state.leavingExpr = true;
}
if (inGenerator(state) && ch === ')') {
while (currentScope(state) !== "(") { state.scopes.pop(); }
state.scopes.pop();
state.nestedGenerators--;
state.leavingExpr = true;
}
if (inArray(state)) {
if (state.lastToken == "end" && stream.match(/^:/)) {
return "operator";
}
if (stream.match(/^end/)) {
return "number";
}
}
var match;
if (match = stream.match(openers, false)) {
state.scopes.push(match[0]);
}
if (stream.match(closers, false)) {
state.scopes.pop();
}
// Handle type annotations
if (stream.match(/^::(?![:\$])/)) {
state.tokenize = tokenAnnotation;
return state.tokenize(stream, state);
}
// Handle symbols
if (!leavingExpr && stream.match(symbol) ||
stream.match(/:([<>]:|<<=?|>>>?=?|->|\/\/|\.{2,3}|[\.\\%*+\-<>!\/^|&]=?|[~\?\$])/)) {
return "builtin";
}
// Handle parametric types
//if (stream.match(/^{[^}]*}(?=\()/)) {
// return "builtin";
//}
// Handle operators and Delimiters
if (stream.match(operators)) {
return "operator";
}
// Handle Number Literals
if (stream.match(/^\.?\d/, false)) {
var imMatcher = RegExp(/^im\b/);
var numberLiteral = false;
if (stream.match(/^0x\.[0-9a-f_]+p[\+\-]?[_\d]+/i)) { numberLiteral = true; }
// Integers
if (stream.match(/^0x[0-9a-f_]+/i)) { numberLiteral = true; } // Hex
if (stream.match(/^0b[01_]+/i)) { numberLiteral = true; } // Binary
if (stream.match(/^0o[0-7_]+/i)) { numberLiteral = true; } // Octal
// Floats
if (stream.match(/^(?:(?:\d[_\d]*)?\.(?!\.)(?:\d[_\d]*)?|\d[_\d]*\.(?!\.)(?:\d[_\d]*))?([Eef][\+\-]?[_\d]+)?/i)) { numberLiteral = true; }
if (stream.match(/^\d[_\d]*(e[\+\-]?\d+)?/i)) { numberLiteral = true; } // Decimal
if (numberLiteral) {
// Integer literals may be "long"
stream.match(imMatcher);
state.leavingExpr = true;
return "number";
}
}
// Handle Chars
if (stream.match(/^'/)) {
state.tokenize = tokenChar;
return state.tokenize(stream, state);
}
// Handle Strings
if (stream.match(stringPrefixes)) {
state.tokenize = tokenStringFactory(stream.current());
return state.tokenize(stream, state);
}
if (stream.match(macro)) {
return "meta";
}
if (stream.match(delimiters)) {
return null;
}
if (stream.match(keywords)) {
return "keyword";
}
if (stream.match(builtins)) {
return "builtin";
}
var isDefinition = state.isDefinition || state.lastToken == "function" ||
state.lastToken == "macro" || state.lastToken == "type" ||
state.lastToken == "struct" || state.lastToken == "immutable";
if (stream.match(identifiers)) {
if (isDefinition) {
if (stream.peek() === '.') {
state.isDefinition = true;
return "variable";
}
state.isDefinition = false;
return "def";
}
if (stream.match(/^({[^}]*})*\(/, false)) {
state.tokenize = tokenCallOrDef;
return state.tokenize(stream, state);
}
state.leavingExpr = true;
return "variable";
}
// Handle non-detected items
stream.next();
return "error";
}
function tokenCallOrDef(stream, state) {
var match = stream.match(/^(\(\s*)/);
if (match) {
if (state.firstParenPos < 0)
state.firstParenPos = state.scopes.length;
state.scopes.push('(');
state.charsAdvanced += match[1].length;
}
if (currentScope(state) == '(' && stream.match(/^\)/)) {
state.scopes.pop();
state.charsAdvanced += 1;
if (state.scopes.length <= state.firstParenPos) {
var isDefinition = stream.match(/^(\s*where\s+[^\s=]+)*\s*?=(?!=)/, false);
stream.backUp(state.charsAdvanced);
state.firstParenPos = -1;
state.charsAdvanced = 0;
state.tokenize = tokenBase;
if (isDefinition)
return "def";
return "builtin";
}
}
// Unfortunately javascript does not support multiline strings, so we have
// to undo anything done upto here if a function call or definition splits
// over two or more lines.
if (stream.match(/^$/g, false)) {
stream.backUp(state.charsAdvanced);
while (state.scopes.length > state.firstParenPos)
state.scopes.pop();
state.firstParenPos = -1;
state.charsAdvanced = 0;
state.tokenize = tokenBase;
return "builtin";
}
state.charsAdvanced += stream.match(/^([^()]*)/)[1].length;
return state.tokenize(stream, state);
}
function tokenAnnotation(stream, state) {
stream.match(/.*?(?=,|;|{|}|\(|\)|=|$|\s)/);
if (stream.match(/^{/)) {
state.nestedParameters++;
} else if (stream.match(/^}/) && state.nestedParameters > 0) {
state.nestedParameters--;
}
if (state.nestedParameters > 0) {
stream.match(/.*?(?={|})/) || stream.next();
} else if (state.nestedParameters == 0) {
state.tokenize = tokenBase;
}
return "builtin";
}
function tokenComment(stream, state) {
if (stream.match(/^#=/)) {
state.nestedComments++;
}
if (!stream.match(/.*?(?=(#=|=#))/)) {
stream.skipToEnd();
}
if (stream.match(/^=#/)) {
state.nestedComments--;
if (state.nestedComments == 0)
state.tokenize = tokenBase;
}
return "comment";
}
function tokenChar(stream, state) {
var isChar = false, match;
if (stream.match(chars)) {
isChar = true;
} else if (match = stream.match(/\\u([a-f0-9]{1,4})(?=')/i)) {
var value = parseInt(match[1], 16);
if (value <= 55295 || value >= 57344) { // (U+0,U+D7FF), (U+E000,U+FFFF)
isChar = true;
stream.next();
}
} else if (match = stream.match(/\\U([A-Fa-f0-9]{5,8})(?=')/)) {
var value = parseInt(match[1], 16);
if (value <= 1114111) { // U+10FFFF
isChar = true;
stream.next();
}
}
if (isChar) {
state.leavingExpr = true;
state.tokenize = tokenBase;
return "string";
}
if (!stream.match(/^[^']+(?=')/)) { stream.skipToEnd(); }
if (stream.match(/^'/)) { state.tokenize = tokenBase; }
return "error";
}
function tokenStringFactory(delimiter) {
if (delimiter.substr(-3) === '"""') {
delimiter = '"""';
} else if (delimiter.substr(-1) === '"') {
delimiter = '"';
}
function tokenString(stream, state) {
if (stream.eat('\\')) {
stream.next();
} else if (stream.match(delimiter)) {
state.tokenize = tokenBase;
state.leavingExpr = true;
return "string";
} else {
stream.eat(/[`"]/);
}
stream.eatWhile(/[^\\`"]/);
return "string";
}
return tokenString;
}
var external = {
startState: function() {
return {
tokenize: tokenBase,
scopes: [],
lastToken: null,
leavingExpr: false,
isDefinition: false,
nestedArrays: 0,
nestedComments: 0,
nestedGenerators: 0,
nestedParameters: 0,
charsAdvanced: 0,
firstParenPos: -1
};
},
token: function(stream, state) {
var style = state.tokenize(stream, state);
var current = stream.current();
if (current && style) {
state.lastToken = current;
}
return style;
},
indent: function(state, textAfter) {
var delta = 0;
if ( textAfter === ']' || textAfter === ')' || textAfter === "end" ||
textAfter === "else" || textAfter === "catch" || textAfter === "elseif" ||
textAfter === "finally" ) {
delta = -1;
}
return (state.scopes.length + delta) * config.indentUnit;
},
electricInput: /\b(end|else|catch|finally)\b/,
blockCommentStart: "#=",
blockCommentEnd: "=#",
lineComment: "#",
closeBrackets: "()[]{}\"\"",
fold: "indent"
};
return external;
});
CodeMirror.defineMIME("text/x-julia", "julia");
});
<!doctype html>
<title>CodeMirror: LiveScript 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/solarized.css">
<script src="../../lib/codemirror.js"></script>
<script src="livescript.js"></script>
<style>.CodeMirror {font-size: 80%;border-top: 1px solid silver; border-bottom: 1px solid silver;}</style>
<div id=nav>
<a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png" alt=""></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="#">LiveScript</a>
</ul>
</div>
<article>
<h2>LiveScript mode</h2>
<form><textarea id="code" name="code">
# LiveScript mode for CodeMirror
# The following script, prelude.ls, is used to
# demonstrate LiveScript mode for CodeMirror.
# https://github.com/gkz/prelude-ls
export objToFunc = objToFunc = (obj) ->
(key) -> obj[key]
export each = (f, xs) -->
if typeof! xs is \Object
for , x of xs then f x
else
for x in xs then f x
xs
export map = (f, xs) -->
f = objToFunc f if typeof! f isnt \Function
type = typeof! xs
if type is \Object
{[key, f x] for key, x of xs}
else
result = [f x for x in xs]
if type is \String then result * '' else result
export filter = (f, xs) -->
f = objToFunc f if typeof! f isnt \Function
type = typeof! xs
if type is \Object
{[key, x] for key, x of xs when f x}
else
result = [x for x in xs when f x]
if type is \String then result * '' else result
export reject = (f, xs) -->
f = objToFunc f if typeof! f isnt \Function
type = typeof! xs
if type is \Object
{[key, x] for key, x of xs when not f x}
else
result = [x for x in xs when not f x]
if type is \String then result * '' else result
export partition = (f, xs) -->
f = objToFunc f if typeof! f isnt \Function
type = typeof! xs
if type is \Object
passed = {}
failed = {}
for key, x of xs
(if f x then passed else failed)[key] = x
else
passed = []
failed = []
for x in xs
(if f x then passed else failed)push x
if type is \String
passed *= ''
failed *= ''
[passed, failed]
export find = (f, xs) -->
f = objToFunc f if typeof! f isnt \Function
if typeof! xs is \Object
for , x of xs when f x then return x
else
for x in xs when f x then return x
void
export head = export first = (xs) ->
return void if not xs.length
xs.0
export tail = (xs) ->
return void if not xs.length
xs.slice 1
export last = (xs) ->
return void if not xs.length
xs[*-1]
export initial = (xs) ->
return void if not xs.length
xs.slice 0 xs.length - 1
export empty = (xs) ->
if typeof! xs is \Object
for x of xs then return false
return yes
not xs.length
export values = (obj) ->
[x for , x of obj]
export keys = (obj) ->
[x for x of obj]
export len = (xs) ->
xs = values xs if typeof! xs is \Object
xs.length
export cons = (x, xs) -->
if typeof! xs is \String then x + xs else [x] ++ xs
export append = (xs, ys) -->
if typeof! ys is \String then xs + ys else xs ++ ys
export join = (sep, xs) -->
xs = values xs if typeof! xs is \Object
xs.join sep
export reverse = (xs) ->
if typeof! xs is \String
then (xs / '')reverse! * ''
else xs.slice!reverse!
export fold = export foldl = (f, memo, xs) -->
if typeof! xs is \Object
for , x of xs then memo = f memo, x
else
for x in xs then memo = f memo, x
memo
export fold1 = export foldl1 = (f, xs) --> fold f, xs.0, xs.slice 1
export foldr = (f, memo, xs) --> fold f, memo, xs.slice!reverse!
export foldr1 = (f, xs) -->
xs.=slice!reverse!
fold f, xs.0, xs.slice 1
export unfoldr = export unfold = (f, b) -->
if (f b)?
[that.0] ++ unfoldr f, that.1
else
[]
export andList = (xs) ->
for x in xs when not x
return false
true
export orList = (xs) ->
for x in xs when x
return true
false
export any = (f, xs) -->
f = objToFunc f if typeof! f isnt \Function
for x in xs when f x
return yes
no
export all = (f, xs) -->
f = objToFunc f if typeof! f isnt \Function
for x in xs when not f x
return no
yes
export unique = (xs) ->
result = []
if typeof! xs is \Object
for , x of xs when x not in result then result.push x
else
for x in xs when x not in result then result.push x
if typeof! xs is \String then result * '' else result
export sort = (xs) ->
xs.concat!sort (x, y) ->
| x > y => 1
| x < y => -1
| _ => 0
export sortBy = (f, xs) -->
return [] unless xs.length
xs.concat!sort f
export compare = (f, x, y) -->
| (f x) > (f y) => 1
| (f x) < (f y) => -1
| otherwise => 0
export sum = (xs) ->
result = 0
if typeof! xs is \Object
for , x of xs then result += x
else
for x in xs then result += x
result
export product = (xs) ->
result = 1
if typeof! xs is \Object
for , x of xs then result *= x
else
for x in xs then result *= x
result
export mean = export average = (xs) -> (sum xs) / len xs
export concat = (xss) -> fold append, [], xss
export concatMap = (f, xs) --> fold ((memo, x) -> append memo, f x), [], xs
export listToObj = (xs) ->
{[x.0, x.1] for x in xs}
export maximum = (xs) -> fold1 (>?), xs
export minimum = (xs) -> fold1 (<?), xs
export scan = export scanl = (f, memo, xs) -->
last = memo
if typeof! xs is \Object
then [memo] ++ [last = f last, x for , x of xs]
else [memo] ++ [last = f last, x for x in xs]
export scan1 = export scanl1 = (f, xs) --> scan f, xs.0, xs.slice 1
export scanr = (f, memo, xs) -->
xs.=slice!reverse!
scan f, memo, xs .reverse!
export scanr1 = (f, xs) -->
xs.=slice!reverse!
scan f, xs.0, xs.slice 1 .reverse!
export replicate = (n, x) -->
result = []
i = 0
while i < n, ++i then result.push x
result
export take = (n, xs) -->
| n <= 0
if typeof! xs is \String then '' else []
| not xs.length => xs
| otherwise => xs.slice 0, n
export drop = (n, xs) -->
| n <= 0 => xs
| not xs.length => xs
| otherwise => xs.slice n
export splitAt = (n, xs) --> [(take n, xs), (drop n, xs)]
export takeWhile = (p, xs) -->
return xs if not xs.length
p = objToFunc p if typeof! p isnt \Function
result = []
for x in xs
break if not p x
result.push x
if typeof! xs is \String then result * '' else result
export dropWhile = (p, xs) -->
return xs if not xs.length
p = objToFunc p if typeof! p isnt \Function
i = 0
for x in xs
break if not p x
++i
drop i, xs
export span = (p, xs) --> [(takeWhile p, xs), (dropWhile p, xs)]
export breakIt = (p, xs) --> span (not) << p, xs
export zip = (xs, ys) -->
result = []
for zs, i in [xs, ys]
for z, j in zs
result.push [] if i is 0
result[j]?push z
result
export zipWith = (f,xs, ys) -->
f = objToFunc f if typeof! f isnt \Function
if not xs.length or not ys.length
[]
else
[f.apply this, zs for zs in zip.call this, xs, ys]
export zipAll = (...xss) ->
result = []
for xs, i in xss
for x, j in xs
result.push [] if i is 0
result[j]?push x
result
export zipAllWith = (f, ...xss) ->
f = objToFunc f if typeof! f isnt \Function
if not xss.0.length or not xss.1.length
[]
else
[f.apply this, xs for xs in zipAll.apply this, xss]
export compose = (...funcs) ->
->
args = arguments
for f in funcs
args = [f.apply this, args]
args.0
export curry = (f) ->
curry$ f # using util method curry$ from livescript
export id = (x) -> x
export flip = (f, x, y) --> f y, x
export fix = (f) ->
( (g, x) -> -> f(g g) ...arguments ) do
(g, x) -> -> f(g g) ...arguments
export lines = (str) ->
return [] if not str.length
str / \\n
export unlines = (strs) -> strs * \\n
export words = (str) ->
return [] if not str.length
str / /[ ]+/
export unwords = (strs) -> strs * ' '
export max = (>?)
export min = (<?)
export negate = (x) -> -x
export abs = Math.abs
export signum = (x) ->
| x < 0 => -1
| x > 0 => 1
| otherwise => 0
export quot = (x, y) --> ~~(x / y)
export rem = (%)
export div = (x, y) --> Math.floor x / y
export mod = (%%)
export recip = (1 /)
export pi = Math.PI
export tau = pi * 2
export exp = Math.exp
export sqrt = Math.sqrt
# changed from log as log is a
# common function for logging things
export ln = Math.log
export pow = (^)
export sin = Math.sin
export tan = Math.tan
export cos = Math.cos
export asin = Math.asin
export acos = Math.acos
export atan = Math.atan
export atan2 = (x, y) --> Math.atan2 x, y
# sinh
# tanh
# cosh
# asinh
# atanh
# acosh
export truncate = (x) -> ~~x
export round = Math.round
export ceiling = Math.ceil
export floor = Math.floor
export isItNaN = (x) -> x isnt x
export even = (x) -> x % 2 == 0
export odd = (x) -> x % 2 != 0
export gcd = (x, y) -->
x = Math.abs x
y = Math.abs y
until y is 0
z = x % y
x = y
y = z
x
export lcm = (x, y) -->
Math.abs Math.floor (x / (gcd x, y) * y)
# meta
export installPrelude = !(target) ->
unless target.prelude?isInstalled
target <<< out$ # using out$ generated by livescript
target <<< target.prelude.isInstalled = true
export prelude = out$
</textarea></form>
<script>
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
theme: "solarized light",
lineNumbers: true
});
</script>
<p><strong>MIME types defined:</strong> <code>text/x-livescript</code>.</p>
<p>The LiveScript mode was written by Kenneth Bentley.</p>
</article>
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: https://codemirror.net/LICENSE
/**
* Link to the project's GitHub page:
* https://github.com/duralog/CodeMirror
*/
(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);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
CodeMirror.defineMode('livescript', function(){
var tokenBase = function(stream, state) {
var next_rule = state.next || "start";
if (next_rule) {
state.next = state.next;
var nr = Rules[next_rule];
if (nr.splice) {
for (var i$ = 0; i$ < nr.length; ++i$) {
var r = nr[i$];
if (r.regex && stream.match(r.regex)) {
state.next = r.next || state.next;
return r.token;
}
}
stream.next();
return 'error';
}
if (stream.match(r = Rules[next_rule])) {
if (r.regex && stream.match(r.regex)) {
state.next = r.next;
return r.token;
} else {
stream.next();
return 'error';
}
}
}
stream.next();
return 'error';
};
var external = {
startState: function(){
return {
next: 'start',
lastToken: {style: null, indent: 0, content: ""}
};
},
token: function(stream, state){
while (stream.pos == stream.start)
var style = tokenBase(stream, state);
state.lastToken = {
style: style,
indent: stream.indentation(),
content: stream.current()
};
return style.replace(/\./g, ' ');
},
indent: function(state){
var indentation = state.lastToken.indent;
if (state.lastToken.content.match(indenter)) {
indentation += 2;
}
return indentation;
}
};
return external;
});
var identifier = '(?![\\d\\s])[$\\w\\xAA-\\uFFDC](?:(?!\\s)[$\\w\\xAA-\\uFFDC]|-[A-Za-z])*';
var indenter = RegExp('(?:[({[=:]|[-~]>|\\b(?:e(?:lse|xport)|d(?:o|efault)|t(?:ry|hen)|finally|import(?:\\s*all)?|const|var|let|new|catch(?:\\s*' + identifier + ')?))\\s*$');
var keywordend = '(?![$\\w]|-[A-Za-z]|\\s*:(?![:=]))';
var stringfill = {
token: 'string',
regex: '.+'
};
var Rules = {
start: [
{
token: 'comment.doc',
regex: '/\\*',
next: 'comment'
}, {
token: 'comment',
regex: '#.*'
}, {
token: 'keyword',
regex: '(?:t(?:h(?:is|row|en)|ry|ypeof!?)|c(?:on(?:tinue|st)|a(?:se|tch)|lass)|i(?:n(?:stanceof)?|mp(?:ort(?:\\s+all)?|lements)|[fs])|d(?:e(?:fault|lete|bugger)|o)|f(?:or(?:\\s+own)?|inally|unction)|s(?:uper|witch)|e(?:lse|x(?:tends|port)|val)|a(?:nd|rguments)|n(?:ew|ot)|un(?:less|til)|w(?:hile|ith)|o[fr]|return|break|let|var|loop)' + keywordend
}, {
token: 'constant.language',
regex: '(?:true|false|yes|no|on|off|null|void|undefined)' + keywordend
}, {
token: 'invalid.illegal',
regex: '(?:p(?:ackage|r(?:ivate|otected)|ublic)|i(?:mplements|nterface)|enum|static|yield)' + keywordend
}, {
token: 'language.support.class',
regex: '(?:R(?:e(?:gExp|ferenceError)|angeError)|S(?:tring|yntaxError)|E(?:rror|valError)|Array|Boolean|Date|Function|Number|Object|TypeError|URIError)' + keywordend
}, {
token: 'language.support.function',
regex: '(?:is(?:NaN|Finite)|parse(?:Int|Float)|Math|JSON|(?:en|de)codeURI(?:Component)?)' + keywordend
}, {
token: 'variable.language',
regex: '(?:t(?:hat|il|o)|f(?:rom|allthrough)|it|by|e)' + keywordend
}, {
token: 'identifier',
regex: identifier + '\\s*:(?![:=])'
}, {
token: 'variable',
regex: identifier
}, {
token: 'keyword.operator',
regex: '(?:\\.{3}|\\s+\\?)'
}, {
token: 'keyword.variable',
regex: '(?:@+|::|\\.\\.)',
next: 'key'
}, {
token: 'keyword.operator',
regex: '\\.\\s*',
next: 'key'
}, {
token: 'string',
regex: '\\\\\\S[^\\s,;)}\\]]*'
}, {
token: 'string.doc',
regex: '\'\'\'',
next: 'qdoc'
}, {
token: 'string.doc',
regex: '"""',
next: 'qqdoc'
}, {
token: 'string',
regex: '\'',
next: 'qstring'
}, {
token: 'string',
regex: '"',
next: 'qqstring'
}, {
token: 'string',
regex: '`',
next: 'js'
}, {
token: 'string',
regex: '<\\[',
next: 'words'
}, {
token: 'string.regex',
regex: '//',
next: 'heregex'
}, {
token: 'string.regex',
regex: '\\/(?:[^[\\/\\n\\\\]*(?:(?:\\\\.|\\[[^\\]\\n\\\\]*(?:\\\\.[^\\]\\n\\\\]*)*\\])[^[\\/\\n\\\\]*)*)\\/[gimy$]{0,4}',
next: 'key'
}, {
token: 'constant.numeric',
regex: '(?:0x[\\da-fA-F][\\da-fA-F_]*|(?:[2-9]|[12]\\d|3[0-6])r[\\da-zA-Z][\\da-zA-Z_]*|(?:\\d[\\d_]*(?:\\.\\d[\\d_]*)?|\\.\\d[\\d_]*)(?:e[+-]?\\d[\\d_]*)?[\\w$]*)'
}, {
token: 'lparen',
regex: '[({[]'
}, {
token: 'rparen',
regex: '[)}\\]]',
next: 'key'
}, {
token: 'keyword.operator',
regex: '\\S+'
}, {
token: 'text',
regex: '\\s+'
}
],
heregex: [
{
token: 'string.regex',
regex: '.*?//[gimy$?]{0,4}',
next: 'start'
}, {
token: 'string.regex',
regex: '\\s*#{'
}, {
token: 'comment.regex',
regex: '\\s+(?:#.*)?'
}, {
token: 'string.regex',
regex: '\\S+'
}
],
key: [
{
token: 'keyword.operator',
regex: '[.?@!]+'
}, {
token: 'identifier',
regex: identifier,
next: 'start'
}, {
token: 'text',
regex: '',
next: 'start'
}
],
comment: [
{
token: 'comment.doc',
regex: '.*?\\*/',
next: 'start'
}, {
token: 'comment.doc',
regex: '.+'
}
],
qdoc: [
{
token: 'string',
regex: ".*?'''",
next: 'key'
}, stringfill
],
qqdoc: [
{
token: 'string',
regex: '.*?"""',
next: 'key'
}, stringfill
],
qstring: [
{
token: 'string',
regex: '[^\\\\\']*(?:\\\\.[^\\\\\']*)*\'',
next: 'key'
}, stringfill
],
qqstring: [
{
token: 'string',
regex: '[^\\\\"]*(?:\\\\.[^\\\\"]*)*"',
next: 'key'
}, stringfill
],
js: [
{
token: 'string',
regex: '[^\\\\`]*(?:\\\\.[^\\\\`]*)*`',
next: 'key'
}, stringfill
],
words: [
{
token: 'string',
regex: '.*?\\]>',
next: 'key'
}, stringfill
]
};
for (var idx in Rules) {
var r = Rules[idx];
if (r.splice) {
for (var i = 0, len = r.length; i < len; ++i) {
var rr = r[i];
if (typeof rr.regex === 'string') {
Rules[idx][i].regex = new RegExp('^' + rr.regex);
}
}
} else if (typeof rr.regex === 'string') {
Rules[idx].regex = new RegExp('^' + r.regex);
}
}
CodeMirror.defineMIME('text/x-livescript', 'livescript');
});
<!doctype html>
<title>CodeMirror: Lua 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/neat.css">
<script src="../../addon/edit/matchbrackets.js"></script>
<script src="../../lib/codemirror.js"></script>
<script src="lua.js"></script>
<style>.CodeMirror {border: 1px solid black;}</style>
<div id=nav>
<a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png" alt=""></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="#">Lua</a>
</ul>
</div>
<article>
<h2>Lua mode</h2>
<form><textarea id="code" name="code">
--[[
example useless code to show lua syntax highlighting
this is multiline comment
]]
function blahblahblah(x)
local table = {
"asd" = 123,
"x" = 0.34,
}
if x ~= 3 then
print( x )
elseif x == "string"
my_custom_function( 0x34 )
else
unknown_function( "some string" )
end
--single line comment
end
function blablabla3()
for k,v in ipairs( table ) do
--abcde..
y=[=[
x=[[
x is a multi line string
]]
but its definition is iside a highest level string!
]=]
print(" \"\" ")
s = math.sin( x )
end
end
</textarea></form>
<script>
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
matchBrackets: true,
theme: "neat"
});
</script>
<p>Loosely based on Franciszek
Wawrzak's <a href="https://codemirror.net/1/contrib/lua">CodeMirror
1 mode</a>. One configuration parameter is
supported, <code>specials</code>, to which you can provide an
array of strings to have those identifiers highlighted with
the <code>lua-special</code> style.</p>
<p><strong>MIME types defined:</strong> <code>text/x-lua</code>.</p>
</article>
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: https://codemirror.net/LICENSE
// LUA mode. Ported to CodeMirror 2 from Franciszek Wawrzak's
// CodeMirror 1 mode.
// highlights keywords, strings, comments (no leveling supported! ("[==[")), tokens, basic indenting
(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);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
CodeMirror.defineMode("lua", function(config, parserConfig) {
var indentUnit = config.indentUnit;
function prefixRE(words) {
return new RegExp("^(?:" + words.join("|") + ")", "i");
}
function wordRE(words) {
return new RegExp("^(?:" + words.join("|") + ")$", "i");
}
var specials = wordRE(parserConfig.specials || []);
// long list of standard functions from lua manual
var builtins = wordRE([
"_G","_VERSION","assert","collectgarbage","dofile","error","getfenv","getmetatable","ipairs","load",
"loadfile","loadstring","module","next","pairs","pcall","print","rawequal","rawget","rawset","require",
"select","setfenv","setmetatable","tonumber","tostring","type","unpack","xpcall",
"coroutine.create","coroutine.resume","coroutine.running","coroutine.status","coroutine.wrap","coroutine.yield",
"debug.debug","debug.getfenv","debug.gethook","debug.getinfo","debug.getlocal","debug.getmetatable",
"debug.getregistry","debug.getupvalue","debug.setfenv","debug.sethook","debug.setlocal","debug.setmetatable",
"debug.setupvalue","debug.traceback",
"close","flush","lines","read","seek","setvbuf","write",
"io.close","io.flush","io.input","io.lines","io.open","io.output","io.popen","io.read","io.stderr","io.stdin",
"io.stdout","io.tmpfile","io.type","io.write",
"math.abs","math.acos","math.asin","math.atan","math.atan2","math.ceil","math.cos","math.cosh","math.deg",
"math.exp","math.floor","math.fmod","math.frexp","math.huge","math.ldexp","math.log","math.log10","math.max",
"math.min","math.modf","math.pi","math.pow","math.rad","math.random","math.randomseed","math.sin","math.sinh",
"math.sqrt","math.tan","math.tanh",
"os.clock","os.date","os.difftime","os.execute","os.exit","os.getenv","os.remove","os.rename","os.setlocale",
"os.time","os.tmpname",
"package.cpath","package.loaded","package.loaders","package.loadlib","package.path","package.preload",
"package.seeall",
"string.byte","string.char","string.dump","string.find","string.format","string.gmatch","string.gsub",
"string.len","string.lower","string.match","string.rep","string.reverse","string.sub","string.upper",
"table.concat","table.insert","table.maxn","table.remove","table.sort"
]);
var keywords = wordRE(["and","break","elseif","false","nil","not","or","return",
"true","function", "end", "if", "then", "else", "do",
"while", "repeat", "until", "for", "in", "local" ]);
var indentTokens = wordRE(["function", "if","repeat","do", "\\(", "{"]);
var dedentTokens = wordRE(["end", "until", "\\)", "}"]);
var dedentPartial = prefixRE(["end", "until", "\\)", "}", "else", "elseif"]);
function readBracket(stream) {
var level = 0;
while (stream.eat("=")) ++level;
stream.eat("[");
return level;
}
function normal(stream, state) {
var ch = stream.next();
if (ch == "-" && stream.eat("-")) {
if (stream.eat("[") && stream.eat("["))
return (state.cur = bracketed(readBracket(stream), "comment"))(stream, state);
stream.skipToEnd();
return "comment";
}
if (ch == "\"" || ch == "'")
return (state.cur = string(ch))(stream, state);
if (ch == "[" && /[\[=]/.test(stream.peek()))
return (state.cur = bracketed(readBracket(stream), "string"))(stream, state);
if (/\d/.test(ch)) {
stream.eatWhile(/[\w.%]/);
return "number";
}
if (/[\w_]/.test(ch)) {
stream.eatWhile(/[\w\\\-_.]/);
return "variable";
}
return null;
}
function bracketed(level, style) {
return function(stream, state) {
var curlev = null, ch;
while ((ch = stream.next()) != null) {
if (curlev == null) {if (ch == "]") curlev = 0;}
else if (ch == "=") ++curlev;
else if (ch == "]" && curlev == level) { state.cur = normal; break; }
else curlev = null;
}
return style;
};
}
function string(quote) {
return function(stream, state) {
var escaped = false, ch;
while ((ch = stream.next()) != null) {
if (ch == quote && !escaped) break;
escaped = !escaped && ch == "\\";
}
if (!escaped) state.cur = normal;
return "string";
};
}
return {
startState: function(basecol) {
return {basecol: basecol || 0, indentDepth: 0, cur: normal};
},
token: function(stream, state) {
if (stream.eatSpace()) return null;
var style = state.cur(stream, state);
var word = stream.current();
if (style == "variable") {
if (keywords.test(word)) style = "keyword";
else if (builtins.test(word)) style = "builtin";
else if (specials.test(word)) style = "variable-2";
}
if ((style != "comment") && (style != "string")){
if (indentTokens.test(word)) ++state.indentDepth;
else if (dedentTokens.test(word)) --state.indentDepth;
}
return style;
},
indent: function(state, textAfter) {
var closing = dedentPartial.test(textAfter);
return state.basecol + indentUnit * (state.indentDepth - (closing ? 1 : 0));
},
lineComment: "--",
blockCommentStart: "--[[",
blockCommentEnd: "]]"
};
});
CodeMirror.defineMIME("text/x-lua", "lua");
});
<!doctype html>
<title>CodeMirror: Markdown mode</title>
<meta charset="utf-8"/>
<link rel=stylesheet href="../../doc/docs.css">
<link rel="stylesheet" href="../../lib/codemirror.css">
<script src="../../lib/codemirror.js"></script>
<script src="../../addon/edit/continuelist.js"></script>
<script src="../xml/xml.js"></script>
<script src="../javascript/javascript.js"></script>
<script src="markdown.js"></script>
<style>
.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
.cm-s-default .cm-trailing-space-a:before,
.cm-s-default .cm-trailing-space-b:before {position: absolute; content: "\00B7"; color: #777;}
.cm-s-default .cm-trailing-space-new-line:before {position: absolute; content: "\21B5"; color: #777;}
</style>
<div id=nav>
<a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png" alt=""></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="#">Markdown</a>
</ul>
</div>
<article>
<h2>Markdown mode</h2>
<form><textarea id="code" name="code">
Markdown: Basics
================
&lt;ul id="ProjectSubmenu"&gt;
&lt;li&gt;&lt;a href="/projects/markdown/" title="Markdown Project Page"&gt;Main&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="selected" title="Markdown Basics"&gt;Basics&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/projects/markdown/syntax" title="Markdown Syntax Documentation"&gt;Syntax&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/projects/markdown/license" title="Pricing and License Information"&gt;License&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/projects/markdown/dingus" title="Online Markdown Web Form"&gt;Dingus&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
Getting the Gist of Markdown's Formatting Syntax
------------------------------------------------
This page offers a brief overview of what it's like to use Markdown.
The [syntax page] [s] provides complete, detailed documentation for
every feature, but Markdown should be very easy to pick up simply by
looking at a few examples of it in action. The examples on this page
are written in a before/after style, showing example syntax and the
HTML output produced by Markdown.
It's also helpful to simply try Markdown out; the [Dingus] [d] is a
web application that allows you type your own Markdown-formatted text
and translate it to XHTML.
**Note:** This document is itself written using Markdown; you
can [see the source for it by adding '.text' to the URL] [src].
[s]: /projects/markdown/syntax "Markdown Syntax"
[d]: /projects/markdown/dingus "Markdown Dingus"
[src]: /projects/markdown/basics.text
## Paragraphs, Headers, Blockquotes ##
A paragraph is simply one or more consecutive lines of text, separated
by one or more blank lines. (A blank line is any line that looks like
a blank line -- a line containing nothing but spaces or tabs is
considered blank.) Normal paragraphs should not be indented with
spaces or tabs.
Markdown offers two styles of headers: *Setext* and *atx*.
Setext-style headers for `&lt;h1&gt;` and `&lt;h2&gt;` are created by
"underlining" with equal signs (`=`) and hyphens (`-`), respectively.
To create an atx-style header, you put 1-6 hash marks (`#`) at the
beginning of the line -- the number of hashes equals the resulting
HTML header level.
Blockquotes are indicated using email-style '`&gt;`' angle brackets.
Markdown:
A First Level Header
====================
A Second Level Header
---------------------
Now is the time for all good men to come to
the aid of their country. This is just a
regular paragraph.
The quick brown fox jumped over the lazy
dog's back.
### Header 3
&gt; This is a blockquote.
&gt;
&gt; This is the second paragraph in the blockquote.
&gt;
&gt; ## This is an H2 in a blockquote
Output:
&lt;h1&gt;A First Level Header&lt;/h1&gt;
&lt;h2&gt;A Second Level Header&lt;/h2&gt;
&lt;p&gt;Now is the time for all good men to come to
the aid of their country. This is just a
regular paragraph.&lt;/p&gt;
&lt;p&gt;The quick brown fox jumped over the lazy
dog's back.&lt;/p&gt;
&lt;h3&gt;Header 3&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;This is a blockquote.&lt;/p&gt;
&lt;p&gt;This is the second paragraph in the blockquote.&lt;/p&gt;
&lt;h2&gt;This is an H2 in a blockquote&lt;/h2&gt;
&lt;/blockquote&gt;
### Phrase Emphasis ###
Markdown uses asterisks and underscores to indicate spans of emphasis.
Markdown:
Some of these words *are emphasized*.
Some of these words _are emphasized also_.
Use two asterisks for **strong emphasis**.
Or, if you prefer, __use two underscores instead__.
Output:
&lt;p&gt;Some of these words &lt;em&gt;are emphasized&lt;/em&gt;.
Some of these words &lt;em&gt;are emphasized also&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Use two asterisks for &lt;strong&gt;strong emphasis&lt;/strong&gt;.
Or, if you prefer, &lt;strong&gt;use two underscores instead&lt;/strong&gt;.&lt;/p&gt;
## Lists ##
Unordered (bulleted) lists use asterisks, pluses, and hyphens (`*`,
`+`, and `-`) as list markers. These three markers are
interchangable; this:
* Candy.
* Gum.
* Booze.
this:
+ Candy.
+ Gum.
+ Booze.
and this:
- Candy.
- Gum.
- Booze.
all produce the same output:
&lt;ul&gt;
&lt;li&gt;Candy.&lt;/li&gt;
&lt;li&gt;Gum.&lt;/li&gt;
&lt;li&gt;Booze.&lt;/li&gt;
&lt;/ul&gt;
Ordered (numbered) lists use regular numbers, followed by periods, as
list markers:
1. Red
2. Green
3. Blue
Output:
&lt;ol&gt;
&lt;li&gt;Red&lt;/li&gt;
&lt;li&gt;Green&lt;/li&gt;
&lt;li&gt;Blue&lt;/li&gt;
&lt;/ol&gt;
If you put blank lines between items, you'll get `&lt;p&gt;` tags for the
list item text. You can create multi-paragraph list items by indenting
the paragraphs by 4 spaces or 1 tab:
* A list item.
With multiple paragraphs.
* Another item in the list.
Output:
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A list item.&lt;/p&gt;
&lt;p&gt;With multiple paragraphs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Another item in the list.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
### Links ###
Markdown supports two styles for creating links: *inline* and
*reference*. With both styles, you use square brackets to delimit the
text you want to turn into a link.
Inline-style links use parentheses immediately after the link text.
For example:
This is an [example link](http://example.com/).
Output:
&lt;p&gt;This is an &lt;a href="http://example.com/"&gt;
example link&lt;/a&gt;.&lt;/p&gt;
Optionally, you may include a title attribute in the parentheses:
This is an [example link](http://example.com/ "With a Title").
Output:
&lt;p&gt;This is an &lt;a href="http://example.com/" title="With a Title"&gt;
example link&lt;/a&gt;.&lt;/p&gt;
Reference-style links allow you to refer to your links by names, which
you define elsewhere in your document:
I get 10 times more traffic from [Google][1] than from
[Yahoo][2] or [MSN][3].
[1]: http://google.com/ "Google"
[2]: http://search.yahoo.com/ "Yahoo Search"
[3]: http://search.msn.com/ "MSN Search"
Output:
&lt;p&gt;I get 10 times more traffic from &lt;a href="http://google.com/"
title="Google"&gt;Google&lt;/a&gt; than from &lt;a href="http://search.yahoo.com/"
title="Yahoo Search"&gt;Yahoo&lt;/a&gt; or &lt;a href="http://search.msn.com/"
title="MSN Search"&gt;MSN&lt;/a&gt;.&lt;/p&gt;
The title attribute is optional. Link names may contain letters,
numbers and spaces, but are *not* case sensitive:
I start my morning with a cup of coffee and
[The New York Times][NY Times].
[ny times]: http://www.nytimes.com/
Output:
&lt;p&gt;I start my morning with a cup of coffee and
&lt;a href="http://www.nytimes.com/"&gt;The New York Times&lt;/a&gt;.&lt;/p&gt;
### Images ###
Image syntax is very much like link syntax.
Inline (titles are optional):
![alt text](/path/to/img.jpg "Title")
Reference-style:
![alt text][id]
[id]: /path/to/img.jpg "Title"
Both of the above examples produce the same output:
&lt;img src="/path/to/img.jpg" alt="alt text" title="Title" /&gt;
### Code ###
In a regular paragraph, you can create code span by wrapping text in
backtick quotes. Any ampersands (`&amp;`) and angle brackets (`&lt;` or
`&gt;`) will automatically be translated into HTML entities. This makes
it easy to use Markdown to write about HTML example code:
I strongly recommend against using any `&lt;blink&gt;` tags.
I wish SmartyPants used named entities like `&amp;mdash;`
instead of decimal-encoded entites like `&amp;#8212;`.
Output:
&lt;p&gt;I strongly recommend against using any
&lt;code&gt;&amp;lt;blink&amp;gt;&lt;/code&gt; tags.&lt;/p&gt;
&lt;p&gt;I wish SmartyPants used named entities like
&lt;code&gt;&amp;amp;mdash;&lt;/code&gt; instead of decimal-encoded
entites like &lt;code&gt;&amp;amp;#8212;&lt;/code&gt;.&lt;/p&gt;
To specify an entire block of pre-formatted code, indent every line of
the block by 4 spaces or 1 tab. Just like with code spans, `&amp;`, `&lt;`,
and `&gt;` characters will be escaped automatically.
Markdown:
If you want your page to validate under XHTML 1.0 Strict,
you've got to put paragraph tags in your blockquotes:
&lt;blockquote&gt;
&lt;p&gt;For example.&lt;/p&gt;
&lt;/blockquote&gt;
Output:
&lt;p&gt;If you want your page to validate under XHTML 1.0 Strict,
you've got to put paragraph tags in your blockquotes:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;blockquote&amp;gt;
&amp;lt;p&amp;gt;For example.&amp;lt;/p&amp;gt;
&amp;lt;/blockquote&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
## Fenced code blocks (and syntax highlighting)
```javascript
for (var i = 0; i < items.length; i++) {
console.log(items[i], i); // log them
}
```
</textarea></form>
<script>
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
mode: 'markdown',
lineNumbers: true,
theme: "default",
extraKeys: {"Enter": "newlineAndIndentContinueMarkdownList"}
});
</script>
<p>If you also want support <code>strikethrough</code>, <code>emoji</code> and few other goodies, check out <a href="../gfm/index.html">Github-Flavored Markdown mode</a>.</p>
<p>Optionally depends on other modes for properly highlighted code blocks,
and XML mode for properly highlighted inline XML blocks.</p>
<p>Markdown mode supports these options:</p>
<ul>
<li>
<d1>
<dt><code>highlightFormatting: boolean</code></dt>
<dd>Whether to separately highlight markdown meta characterts (<code>*[]()</code>etc.) (default: <code>false</code>).</dd>
</d1>
</li>
<li>
<d1>
<dt><code>maxBlockquoteDepth: boolean</code></dt>
<dd>Maximum allowed blockquote nesting (default: <code>0</code> - infinite nesting).</dd>
</d1>
</li>
<li>
<d1>
<dt><code>xml: boolean</code></dt>
<dd>Whether to highlight inline XML (default: <code>true</code>).</dd>
</d1>
</li>
<li>
<d1>
<dt><code>fencedCodeBlockHighlighting: boolean</code></dt>
<dd>Whether to syntax-highlight fenced code blocks, if given mode is included (default: <code>true</code>).</dd>
</d1>
</li>
<li>
<d1>
<dt><code>tokenTypeOverrides: Object</code></dt>
<dd>When you want ot override default token type names (e.g. <code>{code: "code"}</code>).</dd>
</d1>
</li>
<li>
<d1>
<dt><code>allowAtxHeaderWithoutSpace: boolean</code></dt>
<dd>Allow lazy headers without whitespace between hashtag and text (default: <code>false</code>).</dd>
</d1>
</li>
</ul>
<p><strong>MIME types defined:</strong> <code>text/x-markdown</code>.</p>
<p><strong>Parsing/Highlighting Tests:</strong> <a href="../../test/index.html#markdown_*">normal</a>, <a href="../../test/index.html#verbose,markdown_*">verbose</a>.</p>
</article>
// 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"), require("../xml/xml"), require("../meta"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror", "../xml/xml", "../meta"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
var htmlMode = CodeMirror.getMode(cmCfg, "text/html");
var htmlModeMissing = htmlMode.name == "null"
function getMode(name) {
if (CodeMirror.findModeByName) {
var found = CodeMirror.findModeByName(name);
if (found) name = found.mime || found.mimes[0];
}
var mode = CodeMirror.getMode(cmCfg, name);
return mode.name == "null" ? null : mode;
}
// Should characters that affect highlighting be highlighted separate?
// Does not include characters that will be output (such as `1.` and `-` for lists)
if (modeCfg.highlightFormatting === undefined)
modeCfg.highlightFormatting = false;
// Maximum number of nested blockquotes. Set to 0 for infinite nesting.
// Excess `>` will emit `error` token.
if (modeCfg.maxBlockquoteDepth === undefined)
modeCfg.maxBlockquoteDepth = 0;
// Turn on task lists? ("- [ ] " and "- [x] ")
if (modeCfg.taskLists === undefined) modeCfg.taskLists = false;
// Turn on strikethrough syntax
if (modeCfg.strikethrough === undefined)
modeCfg.strikethrough = false;
if (modeCfg.emoji === undefined)
modeCfg.emoji = false;
if (modeCfg.fencedCodeBlockHighlighting === undefined)
modeCfg.fencedCodeBlockHighlighting = true;
if (modeCfg.xml === undefined)
modeCfg.xml = true;
// Allow token types to be overridden by user-provided token types.
if (modeCfg.tokenTypeOverrides === undefined)
modeCfg.tokenTypeOverrides = {};
var tokenTypes = {
header: "header",
code: "comment",
quote: "quote",
list1: "variable-2",
list2: "variable-3",
list3: "keyword",
hr: "hr",
image: "image",
imageAltText: "image-alt-text",
imageMarker: "image-marker",
formatting: "formatting",
linkInline: "link",
linkEmail: "link",
linkText: "link",
linkHref: "string",
em: "em",
strong: "strong",
strikethrough: "strikethrough",
emoji: "builtin"
};
for (var tokenType in tokenTypes) {
if (tokenTypes.hasOwnProperty(tokenType) && modeCfg.tokenTypeOverrides[tokenType]) {
tokenTypes[tokenType] = modeCfg.tokenTypeOverrides[tokenType];
}
}
var hrRE = /^([*\-_])(?:\s*\1){2,}\s*$/
, listRE = /^(?:[*\-+]|^[0-9]+([.)]))\s+/
, taskListRE = /^\[(x| )\](?=\s)/i // Must follow listRE
, atxHeaderRE = modeCfg.allowAtxHeaderWithoutSpace ? /^(#+)/ : /^(#+)(?: |$)/
, setextHeaderRE = /^ *(?:\={1,}|-{1,})\s*$/
, textRE = /^[^#!\[\]*_\\<>` "'(~:]+/
, fencedCodeRE = /^(~~~+|```+)[ \t]*([\w+#-]*)[^\n`]*$/
, linkDefRE = /^\s*\[[^\]]+?\]:.*$/ // naive link-definition
, punctuation = /[!"#$%&'()*+,\-.\/:;<=>?@\[\\\]^_`{|}~\xA1\xA7\xAB\xB6\xB7\xBB\xBF\u037E\u0387\u055A-\u055F\u0589\u058A\u05BE\u05C0\u05C3\u05C6\u05F3\u05F4\u0609\u060A\u060C\u060D\u061B\u061E\u061F\u066A-\u066D\u06D4\u0700-\u070D\u07F7-\u07F9\u0830-\u083E\u085E\u0964\u0965\u0970\u0AF0\u0DF4\u0E4F\u0E5A\u0E5B\u0F04-\u0F12\u0F14\u0F3A-\u0F3D\u0F85\u0FD0-\u0FD4\u0FD9\u0FDA\u104A-\u104F\u10FB\u1360-\u1368\u1400\u166D\u166E\u169B\u169C\u16EB-\u16ED\u1735\u1736\u17D4-\u17D6\u17D8-\u17DA\u1800-\u180A\u1944\u1945\u1A1E\u1A1F\u1AA0-\u1AA6\u1AA8-\u1AAD\u1B5A-\u1B60\u1BFC-\u1BFF\u1C3B-\u1C3F\u1C7E\u1C7F\u1CC0-\u1CC7\u1CD3\u2010-\u2027\u2030-\u2043\u2045-\u2051\u2053-\u205E\u207D\u207E\u208D\u208E\u2308-\u230B\u2329\u232A\u2768-\u2775\u27C5\u27C6\u27E6-\u27EF\u2983-\u2998\u29D8-\u29DB\u29FC\u29FD\u2CF9-\u2CFC\u2CFE\u2CFF\u2D70\u2E00-\u2E2E\u2E30-\u2E42\u3001-\u3003\u3008-\u3011\u3014-\u301F\u3030\u303D\u30A0\u30FB\uA4FE\uA4FF\uA60D-\uA60F\uA673\uA67E\uA6F2-\uA6F7\uA874-\uA877\uA8CE\uA8CF\uA8F8-\uA8FA\uA8FC\uA92E\uA92F\uA95F\uA9C1-\uA9CD\uA9DE\uA9DF\uAA5C-\uAA5F\uAADE\uAADF\uAAF0\uAAF1\uABEB\uFD3E\uFD3F\uFE10-\uFE19\uFE30-\uFE52\uFE54-\uFE61\uFE63\uFE68\uFE6A\uFE6B\uFF01-\uFF03\uFF05-\uFF0A\uFF0C-\uFF0F\uFF1A\uFF1B\uFF1F\uFF20\uFF3B-\uFF3D\uFF3F\uFF5B\uFF5D\uFF5F-\uFF65]|\uD800[\uDD00-\uDD02\uDF9F\uDFD0]|\uD801\uDD6F|\uD802[\uDC57\uDD1F\uDD3F\uDE50-\uDE58\uDE7F\uDEF0-\uDEF6\uDF39-\uDF3F\uDF99-\uDF9C]|\uD804[\uDC47-\uDC4D\uDCBB\uDCBC\uDCBE-\uDCC1\uDD40-\uDD43\uDD74\uDD75\uDDC5-\uDDC9\uDDCD\uDDDB\uDDDD-\uDDDF\uDE38-\uDE3D\uDEA9]|\uD805[\uDCC6\uDDC1-\uDDD7\uDE41-\uDE43\uDF3C-\uDF3E]|\uD809[\uDC70-\uDC74]|\uD81A[\uDE6E\uDE6F\uDEF5\uDF37-\uDF3B\uDF44]|\uD82F\uDC9F|\uD836[\uDE87-\uDE8B]/
, expandedTab = " " // CommonMark specifies tab as 4 spaces
function switchInline(stream, state, f) {
state.f = state.inline = f;
return f(stream, state);
}
function switchBlock(stream, state, f) {
state.f = state.block = f;
return f(stream, state);
}
function lineIsEmpty(line) {
return !line || !/\S/.test(line.string)
}
// Blocks
function blankLine(state) {
// Reset linkTitle state
state.linkTitle = false;
state.linkHref = false;
state.linkText = false;
// Reset EM state
state.em = false;
// Reset STRONG state
state.strong = false;
// Reset strikethrough state
state.strikethrough = false;
// Reset state.quote
state.quote = 0;
// Reset state.indentedCode
state.indentedCode = false;
if (state.f == htmlBlock) {
var exit = htmlModeMissing
if (!exit) {
var inner = CodeMirror.innerMode(htmlMode, state.htmlState)
exit = inner.mode.name == "xml" && inner.state.tagStart === null &&
(!inner.state.context && inner.state.tokenize.isInText)
}
if (exit) {
state.f = inlineNormal;
state.block = blockNormal;
state.htmlState = null;
}
}
// Reset state.trailingSpace
state.trailingSpace = 0;
state.trailingSpaceNewLine = false;
// Mark this line as blank
state.prevLine = state.thisLine
state.thisLine = {stream: null}
return null;
}
function blockNormal(stream, state) {
var firstTokenOnLine = stream.column() === state.indentation;
var prevLineLineIsEmpty = lineIsEmpty(state.prevLine.stream);
var prevLineIsIndentedCode = state.indentedCode;
var prevLineIsHr = state.prevLine.hr;
var prevLineIsList = state.list !== false;
var maxNonCodeIndentation = (state.listStack[state.listStack.length - 1] || 0) + 3;
state.indentedCode = false;
var lineIndentation = state.indentation;
// compute once per line (on first token)
if (state.indentationDiff === null) {
state.indentationDiff = state.indentation;
if (prevLineIsList) {
state.list = null;
// While this list item's marker's indentation is less than the deepest
// list item's content's indentation,pop the deepest list item
// indentation off the stack, and update block indentation state
while (lineIndentation < state.listStack[state.listStack.length - 1]) {
state.listStack.pop();
if (state.listStack.length) {
state.indentation = state.listStack[state.listStack.length - 1];
// less than the first list's indent -> the line is no longer a list
} else {
state.list = false;
}
}
if (state.list !== false) {
state.indentationDiff = lineIndentation - state.listStack[state.listStack.length - 1]
}
}
}
// not comprehensive (currently only for setext detection purposes)
var allowsInlineContinuation = (
!prevLineLineIsEmpty && !prevLineIsHr && !state.prevLine.header &&
(!prevLineIsList || !prevLineIsIndentedCode) &&
!state.prevLine.fencedCodeEnd
);
var isHr = (state.list === false || prevLineIsHr || prevLineLineIsEmpty) &&
state.indentation <= maxNonCodeIndentation && stream.match(hrRE);
var match = null;
if (state.indentationDiff >= 4 && (prevLineIsIndentedCode || state.prevLine.fencedCodeEnd ||
state.prevLine.header || prevLineLineIsEmpty)) {
stream.skipToEnd();
state.indentedCode = true;
return tokenTypes.code;
} else if (stream.eatSpace()) {
return null;
} else if (firstTokenOnLine && state.indentation <= maxNonCodeIndentation && (match = stream.match(atxHeaderRE)) && match[1].length <= 6) {
state.quote = 0;
state.header = match[1].length;
state.thisLine.header = true;
if (modeCfg.highlightFormatting) state.formatting = "header";
state.f = state.inline;
return getType(state);
} else if (state.indentation <= maxNonCodeIndentation && stream.eat('>')) {
state.quote = firstTokenOnLine ? 1 : state.quote + 1;
if (modeCfg.highlightFormatting) state.formatting = "quote";
stream.eatSpace();
return getType(state);
} else if (!isHr && !state.setext && firstTokenOnLine && state.indentation <= maxNonCodeIndentation && (match = stream.match(listRE))) {
var listType = match[1] ? "ol" : "ul";
state.indentation = lineIndentation + stream.current().length;
state.list = true;
state.quote = 0;
// Add this list item's content's indentation to the stack
state.listStack.push(state.indentation);
// Reset inline styles which shouldn't propagate aross list items
state.em = false;
state.strong = false;
state.code = false;
state.strikethrough = false;
if (modeCfg.taskLists && stream.match(taskListRE, false)) {
state.taskList = true;
}
state.f = state.inline;
if (modeCfg.highlightFormatting) state.formatting = ["list", "list-" + listType];
return getType(state);
} else if (firstTokenOnLine && state.indentation <= maxNonCodeIndentation && (match = stream.match(fencedCodeRE, true))) {
state.quote = 0;
state.fencedEndRE = new RegExp(match[1] + "+ *$");
// try switching mode
state.localMode = modeCfg.fencedCodeBlockHighlighting && getMode(match[2]);
if (state.localMode) state.localState = CodeMirror.startState(state.localMode);
state.f = state.block = local;
if (modeCfg.highlightFormatting) state.formatting = "code-block";
state.code = -1
return getType(state);
// SETEXT has lowest block-scope precedence after HR, so check it after
// the others (code, blockquote, list...)
} else if (
// if setext set, indicates line after ---/===
state.setext || (
// line before ---/===
(!allowsInlineContinuation || !prevLineIsList) && !state.quote && state.list === false &&
!state.code && !isHr && !linkDefRE.test(stream.string) &&
(match = stream.lookAhead(1)) && (match = match.match(setextHeaderRE))
)
) {
if ( !state.setext ) {
state.header = match[0].charAt(0) == '=' ? 1 : 2;
state.setext = state.header;
} else {
state.header = state.setext;
// has no effect on type so we can reset it now
state.setext = 0;
stream.skipToEnd();
if (modeCfg.highlightFormatting) state.formatting = "header";
}
state.thisLine.header = true;
state.f = state.inline;
return getType(state);
} else if (isHr) {
stream.skipToEnd();
state.hr = true;
state.thisLine.hr = true;
return tokenTypes.hr;
} else if (stream.peek() === '[') {
return switchInline(stream, state, footnoteLink);
}
return switchInline(stream, state, state.inline);
}
function htmlBlock(stream, state) {
var style = htmlMode.token(stream, state.htmlState);
if (!htmlModeMissing) {
var inner = CodeMirror.innerMode(htmlMode, state.htmlState)
if ((inner.mode.name == "xml" && inner.state.tagStart === null &&
(!inner.state.context && inner.state.tokenize.isInText)) ||
(state.md_inside && stream.current().indexOf(">") > -1)) {
state.f = inlineNormal;
state.block = blockNormal;
state.htmlState = null;
}
}
return style;
}
function local(stream, state) {
var currListInd = state.listStack[state.listStack.length - 1] || 0;
var hasExitedList = state.indentation < currListInd;
var maxFencedEndInd = currListInd + 3;
if (state.fencedEndRE && state.indentation <= maxFencedEndInd && (hasExitedList || stream.match(state.fencedEndRE))) {
if (modeCfg.highlightFormatting) state.formatting = "code-block";
var returnType;
if (!hasExitedList) returnType = getType(state)
state.localMode = state.localState = null;
state.block = blockNormal;
state.f = inlineNormal;
state.fencedEndRE = null;
state.code = 0
state.thisLine.fencedCodeEnd = true;
if (hasExitedList) return switchBlock(stream, state, state.block);
return returnType;
} else if (state.localMode) {
return state.localMode.token(stream, state.localState);
} else {
stream.skipToEnd();
return tokenTypes.code;
}
}
// Inline
function getType(state) {
var styles = [];
if (state.formatting) {
styles.push(tokenTypes.formatting);
if (typeof state.formatting === "string") state.formatting = [state.formatting];
for (var i = 0; i < state.formatting.length; i++) {
styles.push(tokenTypes.formatting + "-" + state.formatting[i]);
if (state.formatting[i] === "header") {
styles.push(tokenTypes.formatting + "-" + state.formatting[i] + "-" + state.header);
}
// Add `formatting-quote` and `formatting-quote-#` for blockquotes
// Add `error` instead if the maximum blockquote nesting depth is passed
if (state.formatting[i] === "quote") {
if (!modeCfg.maxBlockquoteDepth || modeCfg.maxBlockquoteDepth >= state.quote) {
styles.push(tokenTypes.formatting + "-" + state.formatting[i] + "-" + state.quote);
} else {
styles.push("error");
}
}
}
}
if (state.taskOpen) {
styles.push("meta");
return styles.length ? styles.join(' ') : null;
}
if (state.taskClosed) {
styles.push("property");
return styles.length ? styles.join(' ') : null;
}
if (state.linkHref) {
styles.push(tokenTypes.linkHref, "url");
} else { // Only apply inline styles to non-url text
if (state.strong) { styles.push(tokenTypes.strong); }
if (state.em) { styles.push(tokenTypes.em); }
if (state.strikethrough) { styles.push(tokenTypes.strikethrough); }
if (state.emoji) { styles.push(tokenTypes.emoji); }
if (state.linkText) { styles.push(tokenTypes.linkText); }
if (state.code) { styles.push(tokenTypes.code); }
if (state.image) { styles.push(tokenTypes.image); }
if (state.imageAltText) { styles.push(tokenTypes.imageAltText, "link"); }
if (state.imageMarker) { styles.push(tokenTypes.imageMarker); }
}
if (state.header) { styles.push(tokenTypes.header, tokenTypes.header + "-" + state.header); }
if (state.quote) {
styles.push(tokenTypes.quote);
// Add `quote-#` where the maximum for `#` is modeCfg.maxBlockquoteDepth
if (!modeCfg.maxBlockquoteDepth || modeCfg.maxBlockquoteDepth >= state.quote) {
styles.push(tokenTypes.quote + "-" + state.quote);
} else {
styles.push(tokenTypes.quote + "-" + modeCfg.maxBlockquoteDepth);
}
}
if (state.list !== false) {
var listMod = (state.listStack.length - 1) % 3;
if (!listMod) {
styles.push(tokenTypes.list1);
} else if (listMod === 1) {
styles.push(tokenTypes.list2);
} else {
styles.push(tokenTypes.list3);
}
}
if (state.trailingSpaceNewLine) {
styles.push("trailing-space-new-line");
} else if (state.trailingSpace) {
styles.push("trailing-space-" + (state.trailingSpace % 2 ? "a" : "b"));
}
return styles.length ? styles.join(' ') : null;
}
function handleText(stream, state) {
if (stream.match(textRE, true)) {
return getType(state);
}
return undefined;
}
function inlineNormal(stream, state) {
var style = state.text(stream, state);
if (typeof style !== 'undefined')
return style;
if (state.list) { // List marker (*, +, -, 1., etc)
state.list = null;
return getType(state);
}
if (state.taskList) {
var taskOpen = stream.match(taskListRE, true)[1] === " ";
if (taskOpen) state.taskOpen = true;
else state.taskClosed = true;
if (modeCfg.highlightFormatting) state.formatting = "task";
state.taskList = false;
return getType(state);
}
state.taskOpen = false;
state.taskClosed = false;
if (state.header && stream.match(/^#+$/, true)) {
if (modeCfg.highlightFormatting) state.formatting = "header";
return getType(state);
}
var ch = stream.next();
// Matches link titles present on next line
if (state.linkTitle) {
state.linkTitle = false;
var matchCh = ch;
if (ch === '(') {
matchCh = ')';
}
matchCh = (matchCh+'').replace(/([.?*+^\[\]\\(){}|-])/g, "\\$1");
var regex = '^\\s*(?:[^' + matchCh + '\\\\]+|\\\\\\\\|\\\\.)' + matchCh;
if (stream.match(new RegExp(regex), true)) {
return tokenTypes.linkHref;
}
}
// If this block is changed, it may need to be updated in GFM mode
if (ch === '`') {
var previousFormatting = state.formatting;
if (modeCfg.highlightFormatting) state.formatting = "code";
stream.eatWhile('`');
var count = stream.current().length
if (state.code == 0 && (!state.quote || count == 1)) {
state.code = count
return getType(state)
} else if (count == state.code) { // Must be exact
var t = getType(state)
state.code = 0
return t
} else {
state.formatting = previousFormatting
return getType(state)
}
} else if (state.code) {
return getType(state);
}
if (ch === '\\') {
stream.next();
if (modeCfg.highlightFormatting) {
var type = getType(state);
var formattingEscape = tokenTypes.formatting + "-escape";
return type ? type + " " + formattingEscape : formattingEscape;
}
}
if (ch === '!' && stream.match(/\[[^\]]*\] ?(?:\(|\[)/, false)) {
state.imageMarker = true;
state.image = true;
if (modeCfg.highlightFormatting) state.formatting = "image";
return getType(state);
}
if (ch === '[' && state.imageMarker && stream.match(/[^\]]*\](\(.*?\)| ?\[.*?\])/, false)) {
state.imageMarker = false;
state.imageAltText = true
if (modeCfg.highlightFormatting) state.formatting = "image";
return getType(state);
}
if (ch === ']' && state.imageAltText) {
if (modeCfg.highlightFormatting) state.formatting = "image";
var type = getType(state);
state.imageAltText = false;
state.image = false;
state.inline = state.f = linkHref;
return type;
}
if (ch === '[' && !state.image) {
if (state.linkText && stream.match(/^.*?\]/)) return getType(state)
state.linkText = true;
if (modeCfg.highlightFormatting) state.formatting = "link";
return getType(state);
}
if (ch === ']' && state.linkText) {
if (modeCfg.highlightFormatting) state.formatting = "link";
var type = getType(state);
state.linkText = false;
state.inline = state.f = stream.match(/\(.*?\)| ?\[.*?\]/, false) ? linkHref : inlineNormal
return type;
}
if (ch === '<' && stream.match(/^(https?|ftps?):\/\/(?:[^\\>]|\\.)+>/, false)) {
state.f = state.inline = linkInline;
if (modeCfg.highlightFormatting) state.formatting = "link";
var type = getType(state);
if (type){
type += " ";
} else {
type = "";
}
return type + tokenTypes.linkInline;
}
if (ch === '<' && stream.match(/^[^> \\]+@(?:[^\\>]|\\.)+>/, false)) {
state.f = state.inline = linkInline;
if (modeCfg.highlightFormatting) state.formatting = "link";
var type = getType(state);
if (type){
type += " ";
} else {
type = "";
}
return type + tokenTypes.linkEmail;
}
if (modeCfg.xml && ch === '<' && stream.match(/^(!--|\?|!\[CDATA\[|[a-z][a-z0-9-]*(?:\s+[a-z_:.\-]+(?:\s*=\s*[^>]+)?)*\s*(?:>|$))/i, false)) {
var end = stream.string.indexOf(">", stream.pos);
if (end != -1) {
var atts = stream.string.substring(stream.start, end);
if (/markdown\s*=\s*('|"){0,1}1('|"){0,1}/.test(atts)) state.md_inside = true;
}
stream.backUp(1);
state.htmlState = CodeMirror.startState(htmlMode);
return switchBlock(stream, state, htmlBlock);
}
if (modeCfg.xml && ch === '<' && stream.match(/^\/\w*?>/)) {
state.md_inside = false;
return "tag";
} else if (ch === "*" || ch === "_") {
var len = 1, before = stream.pos == 1 ? " " : stream.string.charAt(stream.pos - 2)
while (len < 3 && stream.eat(ch)) len++
var after = stream.peek() || " "
// See http://spec.commonmark.org/0.27/#emphasis-and-strong-emphasis
var leftFlanking = !/\s/.test(after) && (!punctuation.test(after) || /\s/.test(before) || punctuation.test(before))
var rightFlanking = !/\s/.test(before) && (!punctuation.test(before) || /\s/.test(after) || punctuation.test(after))
var setEm = null, setStrong = null
if (len % 2) { // Em
if (!state.em && leftFlanking && (ch === "*" || !rightFlanking || punctuation.test(before)))
setEm = true
else if (state.em == ch && rightFlanking && (ch === "*" || !leftFlanking || punctuation.test(after)))
setEm = false
}
if (len > 1) { // Strong
if (!state.strong && leftFlanking && (ch === "*" || !rightFlanking || punctuation.test(before)))
setStrong = true
else if (state.strong == ch && rightFlanking && (ch === "*" || !leftFlanking || punctuation.test(after)))
setStrong = false
}
if (setStrong != null || setEm != null) {
if (modeCfg.highlightFormatting) state.formatting = setEm == null ? "strong" : setStrong == null ? "em" : "strong em"
if (setEm === true) state.em = ch
if (setStrong === true) state.strong = ch
var t = getType(state)
if (setEm === false) state.em = false
if (setStrong === false) state.strong = false
return t
}
} else if (ch === ' ') {
if (stream.eat('*') || stream.eat('_')) { // Probably surrounded by spaces
if (stream.peek() === ' ') { // Surrounded by spaces, ignore
return getType(state);
} else { // Not surrounded by spaces, back up pointer
stream.backUp(1);
}
}
}
if (modeCfg.strikethrough) {
if (ch === '~' && stream.eatWhile(ch)) {
if (state.strikethrough) {// Remove strikethrough
if (modeCfg.highlightFormatting) state.formatting = "strikethrough";
var t = getType(state);
state.strikethrough = false;
return t;
} else if (stream.match(/^[^\s]/, false)) {// Add strikethrough
state.strikethrough = true;
if (modeCfg.highlightFormatting) state.formatting = "strikethrough";
return getType(state);
}
} else if (ch === ' ') {
if (stream.match(/^~~/, true)) { // Probably surrounded by space
if (stream.peek() === ' ') { // Surrounded by spaces, ignore
return getType(state);
} else { // Not surrounded by spaces, back up pointer
stream.backUp(2);
}
}
}
}
if (modeCfg.emoji && ch === ":" && stream.match(/^(?:[a-z_\d+][a-z_\d+-]*|\-[a-z_\d+][a-z_\d+-]*):/)) {
state.emoji = true;
if (modeCfg.highlightFormatting) state.formatting = "emoji";
var retType = getType(state);
state.emoji = false;
return retType;
}
if (ch === ' ') {
if (stream.match(/^ +$/, false)) {
state.trailingSpace++;
} else if (state.trailingSpace) {
state.trailingSpaceNewLine = true;
}
}
return getType(state);
}
function linkInline(stream, state) {
var ch = stream.next();
if (ch === ">") {
state.f = state.inline = inlineNormal;
if (modeCfg.highlightFormatting) state.formatting = "link";
var type = getType(state);
if (type){
type += " ";
} else {
type = "";
}
return type + tokenTypes.linkInline;
}
stream.match(/^[^>]+/, true);
return tokenTypes.linkInline;
}
function linkHref(stream, state) {
// Check if space, and return NULL if so (to avoid marking the space)
if(stream.eatSpace()){
return null;
}
var ch = stream.next();
if (ch === '(' || ch === '[') {
state.f = state.inline = getLinkHrefInside(ch === "(" ? ")" : "]");
if (modeCfg.highlightFormatting) state.formatting = "link-string";
state.linkHref = true;
return getType(state);
}
return 'error';
}
var linkRE = {
")": /^(?:[^\\\(\)]|\\.|\((?:[^\\\(\)]|\\.)*\))*?(?=\))/,
"]": /^(?:[^\\\[\]]|\\.|\[(?:[^\\\[\]]|\\.)*\])*?(?=\])/
}
function getLinkHrefInside(endChar) {
return function(stream, state) {
var ch = stream.next();
if (ch === endChar) {
state.f = state.inline = inlineNormal;
if (modeCfg.highlightFormatting) state.formatting = "link-string";
var returnState = getType(state);
state.linkHref = false;
return returnState;
}
stream.match(linkRE[endChar])
state.linkHref = true;
return getType(state);
};
}
function footnoteLink(stream, state) {
if (stream.match(/^([^\]\\]|\\.)*\]:/, false)) {
state.f = footnoteLinkInside;
stream.next(); // Consume [
if (modeCfg.highlightFormatting) state.formatting = "link";
state.linkText = true;
return getType(state);
}
return switchInline(stream, state, inlineNormal);
}
function footnoteLinkInside(stream, state) {
if (stream.match(/^\]:/, true)) {
state.f = state.inline = footnoteUrl;
if (modeCfg.highlightFormatting) state.formatting = "link";
var returnType = getType(state);
state.linkText = false;
return returnType;
}
stream.match(/^([^\]\\]|\\.)+/, true);
return tokenTypes.linkText;
}
function footnoteUrl(stream, state) {
// Check if space, and return NULL if so (to avoid marking the space)
if(stream.eatSpace()){
return null;
}
// Match URL
stream.match(/^[^\s]+/, true);
// Check for link title
if (stream.peek() === undefined) { // End of line, set flag to check next line
state.linkTitle = true;
} else { // More content on line, check if link title
stream.match(/^(?:\s+(?:"(?:[^"\\]|\\\\|\\.)+"|'(?:[^'\\]|\\\\|\\.)+'|\((?:[^)\\]|\\\\|\\.)+\)))?/, true);
}
state.f = state.inline = inlineNormal;
return tokenTypes.linkHref + " url";
}
var mode = {
startState: function() {
return {
f: blockNormal,
prevLine: {stream: null},
thisLine: {stream: null},
block: blockNormal,
htmlState: null,
indentation: 0,
inline: inlineNormal,
text: handleText,
formatting: false,
linkText: false,
linkHref: false,
linkTitle: false,
code: 0,
em: false,
strong: false,
header: 0,
setext: 0,
hr: false,
taskList: false,
list: false,
listStack: [],
quote: 0,
trailingSpace: 0,
trailingSpaceNewLine: false,
strikethrough: false,
emoji: false,
fencedEndRE: null
};
},
copyState: function(s) {
return {
f: s.f,
prevLine: s.prevLine,
thisLine: s.thisLine,
block: s.block,
htmlState: s.htmlState && CodeMirror.copyState(htmlMode, s.htmlState),
indentation: s.indentation,
localMode: s.localMode,
localState: s.localMode ? CodeMirror.copyState(s.localMode, s.localState) : null,
inline: s.inline,
text: s.text,
formatting: false,
linkText: s.linkText,
linkTitle: s.linkTitle,
linkHref: s.linkHref,
code: s.code,
em: s.em,
strong: s.strong,
strikethrough: s.strikethrough,
emoji: s.emoji,
header: s.header,
setext: s.setext,
hr: s.hr,
taskList: s.taskList,
list: s.list,
listStack: s.listStack.slice(0),
quote: s.quote,
indentedCode: s.indentedCode,
trailingSpace: s.trailingSpace,
trailingSpaceNewLine: s.trailingSpaceNewLine,
md_inside: s.md_inside,
fencedEndRE: s.fencedEndRE
};
},
token: function(stream, state) {
// Reset state.formatting
state.formatting = false;
if (stream != state.thisLine.stream) {
state.header = 0;
state.hr = false;
if (stream.match(/^\s*$/, true)) {
blankLine(state);
return null;
}
state.prevLine = state.thisLine
state.thisLine = {stream: stream}
// Reset state.taskList
state.taskList = false;
// Reset state.trailingSpace
state.trailingSpace = 0;
state.trailingSpaceNewLine = false;
if (!state.localState) {
state.f = state.block;
if (state.f != htmlBlock) {
var indentation = stream.match(/^\s*/, true)[0].replace(/\t/g, expandedTab).length;
state.indentation = indentation;
state.indentationDiff = null;
if (indentation > 0) return null;
}
}
}
return state.f(stream, state);
},
innerMode: function(state) {
if (state.block == htmlBlock) return {state: state.htmlState, mode: htmlMode};
if (state.localState) return {state: state.localState, mode: state.localMode};
return {state: state, mode: mode};
},
indent: function(state, textAfter, line) {
if (state.block == htmlBlock && htmlMode.indent) return htmlMode.indent(state.htmlState, textAfter, line)
if (state.localState && state.localMode.indent) return state.localMode.indent(state.localState, textAfter, line)
return CodeMirror.Pass
},
blankLine: blankLine,
getType: getType,
blockCommentStart: "<!--",
blockCommentEnd: "-->",
closeBrackets: "()[]{}''\"\"``",
fold: "markdown"
};
return mode;
}, "xml");
CodeMirror.defineMIME("text/markdown", "markdown");
CodeMirror.defineMIME("text/x-markdown", "markdown");
});
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function() {
var config = {tabSize: 4, indentUnit: 2}
var mode = CodeMirror.getMode(config, "markdown");
function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }
var modeHighlightFormatting = CodeMirror.getMode(config, {name: "markdown", highlightFormatting: true});
function FT(name) { test.mode(name, modeHighlightFormatting, Array.prototype.slice.call(arguments, 1)); }
var modeMT_noXml = CodeMirror.getMode(config, {name: "markdown", xml: false});
function MT_noXml(name) { test.mode(name, modeMT_noXml, Array.prototype.slice.call(arguments, 1)); }
var modeMT_noFencedHighlight = CodeMirror.getMode(config, {name: "markdown", fencedCodeBlockHighlighting: false});
function MT_noFencedHighlight(name) { test.mode(name, modeMT_noFencedHighlight, Array.prototype.slice.call(arguments, 1)); }
var modeAtxNoSpace = CodeMirror.getMode(config, {name: "markdown", allowAtxHeaderWithoutSpace: true});
function AtxNoSpaceTest(name) { test.mode(name, modeAtxNoSpace, Array.prototype.slice.call(arguments, 1)); }
var modeOverrideClasses = CodeMirror.getMode(config, {
name: "markdown",
strikethrough: true,
emoji: true,
tokenTypeOverrides: {
"header" : "override-header",
"code" : "override-code",
"quote" : "override-quote",
"list1" : "override-list1",
"list2" : "override-list2",
"list3" : "override-list3",
"hr" : "override-hr",
"image" : "override-image",
"imageAltText": "override-image-alt-text",
"imageMarker": "override-image-marker",
"linkInline" : "override-link-inline",
"linkEmail" : "override-link-email",
"linkText" : "override-link-text",
"linkHref" : "override-link-href",
"em" : "override-em",
"strong" : "override-strong",
"strikethrough" : "override-strikethrough",
"emoji" : "override-emoji"
}});
function TokenTypeOverrideTest(name) { test.mode(name, modeOverrideClasses, Array.prototype.slice.call(arguments, 1)); }
var modeFormattingOverride = CodeMirror.getMode(config, {
name: "markdown",
highlightFormatting: true,
tokenTypeOverrides: {
"formatting" : "override-formatting"
}});
function FormatTokenTypeOverrideTest(name) { test.mode(name, modeFormattingOverride, Array.prototype.slice.call(arguments, 1)); }
var modeET = CodeMirror.getMode(config, {name: "markdown", emoji: true});
function ET(name) { test.mode(name, modeET, Array.prototype.slice.call(arguments, 1)); }
FT("formatting_emAsterisk",
"[em&formatting&formatting-em *][em foo][em&formatting&formatting-em *]");
FT("formatting_emUnderscore",
"[em&formatting&formatting-em _][em foo][em&formatting&formatting-em _]");
FT("formatting_strongAsterisk",
"[strong&formatting&formatting-strong **][strong foo][strong&formatting&formatting-strong **]");
FT("formatting_strongUnderscore",
"[strong&formatting&formatting-strong __][strong foo][strong&formatting&formatting-strong __]");
FT("formatting_codeBackticks",
"[comment&formatting&formatting-code `][comment foo][comment&formatting&formatting-code `]");
FT("formatting_doubleBackticks",
"[comment&formatting&formatting-code ``][comment foo ` bar][comment&formatting&formatting-code ``]");
FT("formatting_atxHeader",
"[header&header-1&formatting&formatting-header&formatting-header-1 # ][header&header-1 foo # bar ][header&header-1&formatting&formatting-header&formatting-header-1 #]");
FT("formatting_setextHeader",
"[header&header-1 foo]",
"[header&header-1&formatting&formatting-header&formatting-header-1 =]");
FT("formatting_blockquote",
"[quote&quote-1&formatting&formatting-quote&formatting-quote-1 > ][quote&quote-1 foo]");
FT("formatting_list",
"[variable-2&formatting&formatting-list&formatting-list-ul - ][variable-2 foo]");
FT("formatting_list",
"[variable-2&formatting&formatting-list&formatting-list-ol 1. ][variable-2 foo]");
FT("formatting_link",
"[link&formatting&formatting-link [][link foo][link&formatting&formatting-link ]]][string&formatting&formatting-link-string&url (][string&url http://example.com/][string&formatting&formatting-link-string&url )]");
FT("formatting_linkReference",
"[link&formatting&formatting-link [][link foo][link&formatting&formatting-link ]]][string&formatting&formatting-link-string&url [][string&url bar][string&formatting&formatting-link-string&url ]]]",
"[link&formatting&formatting-link [][link bar][link&formatting&formatting-link ]]:] [string&url http://example.com/]");
FT("formatting_linkWeb",
"[link&formatting&formatting-link <][link http://example.com/][link&formatting&formatting-link >]");
FT("formatting_linkEmail",
"[link&formatting&formatting-link <][link user@example.com][link&formatting&formatting-link >]");
FT("formatting_escape",
"[formatting-escape \\*]");
FT("formatting_image",
"[formatting&formatting-image&image&image-marker !][formatting&formatting-image&image&image-alt-text&link [[][image&image-alt-text&link alt text][formatting&formatting-image&image&image-alt-text&link ]]][formatting&formatting-link-string&string&url (][url&string http://link.to/image.jpg][formatting&formatting-link-string&string&url )]");
FT("codeBlock",
"[comment&formatting&formatting-code-block ```css]",
"[tag foo]",
"[comment&formatting&formatting-code-block ```]");
MT("plainText",
"foo");
// Don't style single trailing space
MT("trailingSpace1",
"foo ");
// Two or more trailing spaces should be styled with line break character
MT("trailingSpace2",
"foo[trailing-space-a ][trailing-space-new-line ]");
MT("trailingSpace3",
"foo[trailing-space-a ][trailing-space-b ][trailing-space-new-line ]");
MT("trailingSpace4",
"foo[trailing-space-a ][trailing-space-b ][trailing-space-a ][trailing-space-new-line ]");
// Code blocks using 4 spaces (regardless of CodeMirror.tabSize value)
MT("codeBlocksUsing4Spaces",
" [comment foo]");
// Code blocks using 4 spaces with internal indentation
MT("codeBlocksUsing4SpacesIndentation",
" [comment bar]",
" [comment hello]",
" [comment world]",
" [comment foo]",
"bar");
// Code blocks should end even after extra indented lines
MT("codeBlocksWithTrailingIndentedLine",
" [comment foo]",
" [comment bar]",
" [comment baz]",
" ",
"hello");
// Code blocks using 1 tab (regardless of CodeMirror.indentWithTabs value)
MT("codeBlocksUsing1Tab",
"\t[comment foo]");
// No code blocks directly after paragraph
// http://spec.commonmark.org/0.19/#example-65
MT("noCodeBlocksAfterParagraph",
"Foo",
" Bar");
MT("codeBlocksAfterATX",
"[header&header-1 # foo]",
" [comment code]");
MT("codeBlocksAfterSetext",
"[header&header-2 foo]",
"[header&header-2 ---]",
" [comment code]");
MT("codeBlocksAfterFencedCode",
"[comment ```]",
"[comment foo]",
"[comment ```]",
" [comment code]");
// Inline code using backticks
MT("inlineCodeUsingBackticks",
"foo [comment `bar`]");
// Block code using single backtick (shouldn't work)
MT("blockCodeSingleBacktick",
"[comment `]",
"[comment foo]",
"[comment `]");
// Unclosed backticks
// Instead of simply marking as CODE, it would be nice to have an
// incomplete flag for CODE, that is styled slightly different.
MT("unclosedBackticks",
"foo [comment `bar]");
// Per documentation: "To include a literal backtick character within a
// code span, you can use multiple backticks as the opening and closing
// delimiters"
MT("doubleBackticks",
"[comment ``foo ` bar``]");
// Tests based on Dingus
// http://daringfireball.net/projects/markdown/dingus
//
// Multiple backticks within an inline code block
MT("consecutiveBackticks",
"[comment `foo```bar`]");
// Multiple backticks within an inline code block with a second code block
MT("consecutiveBackticks",
"[comment `foo```bar`] hello [comment `world`]");
// Unclosed with several different groups of backticks
MT("unclosedBackticks",
"[comment ``foo ``` bar` hello]");
// Closed with several different groups of backticks
MT("closedBackticks",
"[comment ``foo ``` bar` hello``] world");
// info string cannot contain backtick, thus should result in inline code
MT("closingFencedMarksOnSameLine",
"[comment ``` code ```] foo");
// atx headers
// http://daringfireball.net/projects/markdown/syntax#header
MT("atxH1",
"[header&header-1 # foo]");
MT("atxH2",
"[header&header-2 ## foo]");
MT("atxH3",
"[header&header-3 ### foo]");
MT("atxH4",
"[header&header-4 #### foo]");
MT("atxH5",
"[header&header-5 ##### foo]");
MT("atxH6",
"[header&header-6 ###### foo]");
// http://spec.commonmark.org/0.19/#example-24
MT("noAtxH7",
"####### foo");
// http://spec.commonmark.org/0.19/#example-25
MT("noAtxH1WithoutSpace",
"#5 bolt");
// CommonMark requires a space after # but most parsers don't
AtxNoSpaceTest("atxNoSpaceAllowed_H1NoSpace",
"[header&header-1 #foo]");
AtxNoSpaceTest("atxNoSpaceAllowed_H4NoSpace",
"[header&header-4 ####foo]");
AtxNoSpaceTest("atxNoSpaceAllowed_H1Space",
"[header&header-1 # foo]");
// Inline styles should be parsed inside headers
MT("atxH1inline",
"[header&header-1 # foo ][header&header-1&em *bar*]");
MT("atxIndentedTooMuch",
"[header&header-1 # foo]",
" [comment # bar]");
// disable atx inside blockquote until we implement proper blockquote inner mode
// TODO: fix to be CommonMark-compliant
MT("atxNestedInsideBlockquote",
"[quote&quote-1 > # foo]");
MT("atxAfterBlockquote",
"[quote&quote-1 > foo]",
"[header&header-1 # bar]");
// Setext headers - H1, H2
// Per documentation, "Any number of underlining =’s or -’s will work."
// http://daringfireball.net/projects/markdown/syntax#header
// Ideally, the text would be marked as `header` as well, but this is
// not really feasible at the moment. So, instead, we're testing against
// what works today, to avoid any regressions.
//
// Check if single underlining = works
MT("setextH1",
"[header&header-1 foo]",
"[header&header-1 =]");
// Check if 3+ ='s work
MT("setextH1",
"[header&header-1 foo]",
"[header&header-1 ===]");
// Check if single underlining - works
MT("setextH2",
"[header&header-2 foo]",
"[header&header-2 -]");
// Check if 3+ -'s work
MT("setextH2",
"[header&header-2 foo]",
"[header&header-2 ---]");
// http://spec.commonmark.org/0.19/#example-45
MT("setextH2AllowSpaces",
"[header&header-2 foo]",
" [header&header-2 ---- ]");
// http://spec.commonmark.org/0.19/#example-44
MT("noSetextAfterIndentedCodeBlock",
" [comment foo]",
"[hr ---]");
MT("setextAfterFencedCode",
"[comment ```]",
"[comment foo]",
"[comment ```]",
"[header&header-2 bar]",
"[header&header-2 ---]");
MT("setextAferATX",
"[header&header-1 # foo]",
"[header&header-2 bar]",
"[header&header-2 ---]");
// http://spec.commonmark.org/0.19/#example-51
MT("noSetextAfterQuote",
"[quote&quote-1 > foo]",
"[hr ---]",
"",
"[quote&quote-1 > foo]",
"[quote&quote-1 bar]",
"[hr ---]");
MT("noSetextAfterList",
"[variable-2 - foo]",
"[hr ---]");
MT("noSetextAfterList_listContinuation",
"[variable-2 - foo]",
"bar",
"[hr ---]");
MT("setextAfterList_afterIndentedCode",
"[variable-2 - foo]",
"",
" [comment bar]",
"[header&header-2 baz]",
"[header&header-2 ---]");
MT("setextAfterList_afterFencedCodeBlocks",
"[variable-2 - foo]",
"",
" [comment ```]",
" [comment bar]",
" [comment ```]",
"[header&header-2 baz]",
"[header&header-2 ---]");
MT("setextAfterList_afterHeader",
"[variable-2 - foo]",
" [variable-2&header&header-1 # bar]",
"[header&header-2 baz]",
"[header&header-2 ---]");
MT("setextAfterList_afterHr",
"[variable-2 - foo]",
"",
" [hr ---]",
"[header&header-2 bar]",
"[header&header-2 ---]");
MT("setext_nestedInlineMarkup",
"[header&header-1 foo ][em&header&header-1 *bar*]",
"[header&header-1 =]");
MT("setext_linkDef",
"[link [[aaa]]:] [string&url http://google.com 'title']",
"[hr ---]");
// currently, looks max one line ahead, thus won't catch valid CommonMark
// markup
MT("setext_oneLineLookahead",
"foo",
"[header&header-1 bar]",
"[header&header-1 =]");
// ensure we don't regard space after dash as a list
MT("setext_emptyList",
"[header&header-2 foo]",
"[header&header-2 - ]",
"foo");
// Single-line blockquote with trailing space
MT("blockquoteSpace",
"[quote&quote-1 > foo]");
// Single-line blockquote
MT("blockquoteNoSpace",
"[quote&quote-1 >foo]");
// No blank line before blockquote
MT("blockquoteNoBlankLine",
"foo",
"[quote&quote-1 > bar]");
MT("blockquoteNested",
"[quote&quote-1 > foo]",
"[quote&quote-1 >][quote&quote-2 > foo]",
"[quote&quote-1 >][quote&quote-2 >][quote&quote-3 > foo]");
// ensure quote-level is inferred correctly even if indented
MT("blockquoteNestedIndented",
" [quote&quote-1 > foo]",
" [quote&quote-1 >][quote&quote-2 > foo]",
" [quote&quote-1 >][quote&quote-2 >][quote&quote-3 > foo]");
// ensure quote-level is inferred correctly even if indented
MT("blockquoteIndentedTooMuch",
"foo",
" > bar");
// Single-line blockquote followed by normal paragraph
MT("blockquoteThenParagraph",
"[quote&quote-1 >foo]",
"",
"bar");
// Multi-line blockquote (lazy mode)
MT("multiBlockquoteLazy",
"[quote&quote-1 >foo]",
"[quote&quote-1 bar]");
// Multi-line blockquote followed by normal paragraph (lazy mode)
MT("multiBlockquoteLazyThenParagraph",
"[quote&quote-1 >foo]",
"[quote&quote-1 bar]",
"",
"hello");
// Multi-line blockquote (non-lazy mode)
MT("multiBlockquote",
"[quote&quote-1 >foo]",
"[quote&quote-1 >bar]");
// Multi-line blockquote followed by normal paragraph (non-lazy mode)
MT("multiBlockquoteThenParagraph",
"[quote&quote-1 >foo]",
"[quote&quote-1 >bar]",
"",
"hello");
// disallow lists inside blockquote for now because it causes problems outside blockquote
// TODO: fix to be CommonMark-compliant
MT("listNestedInBlockquote",
"[quote&quote-1 > - foo]");
// disallow fenced blocks inside blockquote because it causes problems outside blockquote
// TODO: fix to be CommonMark-compliant
MT("fencedBlockNestedInBlockquote",
"[quote&quote-1 > ```]",
"[quote&quote-1 > code]",
"[quote&quote-1 > ```]",
// ensure we still allow inline code
"[quote&quote-1 > ][quote&quote-1&comment `code`]");
// Header with leading space after continued blockquote (#3287, negative indentation)
MT("headerAfterContinuedBlockquote",
"[quote&quote-1 > foo]",
"[quote&quote-1 bar]",
"",
" [header&header-1 # hello]");
// Check list types
MT("listAsterisk",
"foo",
"bar",
"",
"[variable-2 * foo]",
"[variable-2 * bar]");
MT("listPlus",
"foo",
"bar",
"",
"[variable-2 + foo]",
"[variable-2 + bar]");
MT("listDash",
"foo",
"bar",
"",
"[variable-2 - foo]",
"[variable-2 - bar]");
MT("listNumber",
"foo",
"bar",
"",
"[variable-2 1. foo]",
"[variable-2 2. bar]");
MT("listFromParagraph",
"foo",
"[variable-2 1. bar]",
"[variable-2 2. hello]");
// List after hr
MT("listAfterHr",
"[hr ---]",
"[variable-2 - bar]");
// List after header
MT("listAfterHeader",
"[header&header-1 # foo]",
"[variable-2 - bar]");
// hr after list
MT("hrAfterList",
"[variable-2 - foo]",
"[hr -----]");
MT("hrAfterFencedCode",
"[comment ```]",
"[comment code]",
"[comment ```]",
"[hr ---]");
// allow hr inside lists
// (require prev line to be empty or hr, TODO: non-CommonMark-compliant)
MT("hrInsideList",
"[variable-2 - foo]",
"",
" [hr ---]",
" [hr ---]",
"",
" [comment ---]");
MT("consecutiveHr",
"[hr ---]",
"[hr ---]",
"[hr ---]");
// Formatting in lists (*)
MT("listAsteriskFormatting",
"[variable-2 * ][variable-2&em *foo*][variable-2 bar]",
"[variable-2 * ][variable-2&strong **foo**][variable-2 bar]",
"[variable-2 * ][variable-2&em&strong ***foo***][variable-2 bar]",
"[variable-2 * ][variable-2&comment `foo`][variable-2 bar]");
// Formatting in lists (+)
MT("listPlusFormatting",
"[variable-2 + ][variable-2&em *foo*][variable-2 bar]",
"[variable-2 + ][variable-2&strong **foo**][variable-2 bar]",
"[variable-2 + ][variable-2&em&strong ***foo***][variable-2 bar]",
"[variable-2 + ][variable-2&comment `foo`][variable-2 bar]");
// Formatting in lists (-)
MT("listDashFormatting",
"[variable-2 - ][variable-2&em *foo*][variable-2 bar]",
"[variable-2 - ][variable-2&strong **foo**][variable-2 bar]",
"[variable-2 - ][variable-2&em&strong ***foo***][variable-2 bar]",
"[variable-2 - ][variable-2&comment `foo`][variable-2 bar]");
// Formatting in lists (1.)
MT("listNumberFormatting",
"[variable-2 1. ][variable-2&em *foo*][variable-2 bar]",
"[variable-2 2. ][variable-2&strong **foo**][variable-2 bar]",
"[variable-2 3. ][variable-2&em&strong ***foo***][variable-2 bar]",
"[variable-2 4. ][variable-2&comment `foo`][variable-2 bar]");
// Paragraph lists
MT("listParagraph",
"[variable-2 * foo]",
"",
"[variable-2 * bar]");
// Multi-paragraph lists
//
// 4 spaces
MT("listMultiParagraph",
"[variable-2 * foo]",
"",
"[variable-2 * bar]",
"",
" [variable-2 hello]");
// 4 spaces, extra blank lines (should still be list, per Dingus)
MT("listMultiParagraphExtra",
"[variable-2 * foo]",
"",
"[variable-2 * bar]",
"",
"",
" [variable-2 hello]");
// 4 spaces, plus 1 space (should still be list, per Dingus)
MT("listMultiParagraphExtraSpace",
"[variable-2 * foo]",
"",
"[variable-2 * bar]",
"",
" [variable-2 hello]",
"",
" [variable-2 world]");
// 1 tab
MT("listTab",
"[variable-2 * foo]",
"",
"[variable-2 * bar]",
"",
"\t[variable-2 hello]");
// No indent
MT("listNoIndent",
"[variable-2 * foo]",
"",
"[variable-2 * bar]",
"",
"hello");
MT("listCommonMarkIndentationCode",
"[variable-2 * Code blocks also affect]",
" [variable-3 * The next level starts where the contents start.]",
" [variable-3 * Anything less than that will keep the item on the same level.]",
" [variable-3 * Each list item can indent the first level further and further.]",
" [variable-3 * For the most part, this makes sense while writing a list.]",
" [keyword * This means two items with same indentation can be different levels.]",
" [keyword * Each level has an indent requirement that can change between items.]",
" [keyword * A list item that meets this will be part of the next level.]",
" [variable-3 * Otherwise, it will be part of the level where it does meet this.]",
" [variable-2 * World]");
// should handle nested and un-nested lists
MT("listCommonMark_MixedIndents",
"[variable-2 * list1]",
" [variable-2 list1]",
" [variable-2&header&header-1 # heading still part of list1]",
" [variable-2 text after heading still part of list1]",
"",
" [comment indented codeblock]",
" [variable-2 list1 after code block]",
" [variable-3 * list2]",
// amount of spaces on empty lines between lists doesn't matter
" ",
// extra empty lines irrelevant
"",
"",
" [variable-3 indented text part of list2]",
" [keyword * list3]",
"",
" [variable-3 text at level of list2]",
"",
" [variable-2 de-indented text part of list1 again]",
"",
" [variable-2&comment ```]",
" [comment code]",
" [variable-2&comment ```]",
"",
" [variable-2 text after fenced code]");
// should correctly parse numbered list content indentation
MT("listCommonMark_NumeberedListIndent",
"[variable-2 1000. list with base indent of 6]",
"",
" [variable-2 text must be indented 6 spaces at minimum]",
"",
" [variable-2 9-spaces indented text still part of list]",
"",
" [comment indented codeblock starts at 10 spaces]",
"",
" [comment text indented by 5 spaces no longer belong to list]");
// should consider tab as 4 spaces
MT("listCommonMark_TabIndented",
"[variable-2 * list]",
"\t[variable-3 * list2]",
"",
"\t\t[variable-3 part of list2]");
MT("listAfterBlockquote",
"[quote&quote-1 > foo]",
"[variable-2 - bar]");
// shouldn't create sublist if it's indented more than allowed
MT("nestedListIndentedTooMuch",
"[variable-2 - foo]",
" [variable-2 - bar]");
MT("listIndentedTooMuchAfterParagraph",
"foo",
" - bar");
// Blockquote
MT("blockquote",
"[variable-2 * foo]",
"",
"[variable-2 * bar]",
"",
" [variable-2&quote&quote-1 > hello]");
// Code block
MT("blockquoteCode",
"[variable-2 * foo]",
"",
"[variable-2 * bar]",
"",
" [comment > hello]",
"",
" [variable-2 world]");
// Code block followed by text
MT("blockquoteCodeText",
"[variable-2 * foo]",
"",
" [variable-2 bar]",
"",
" [comment hello]",
"",
" [variable-2 world]");
// Nested list
MT("listAsteriskNested",
"[variable-2 * foo]",
"",
" [variable-3 * bar]");
MT("listPlusNested",
"[variable-2 + foo]",
"",
" [variable-3 + bar]");
MT("listDashNested",
"[variable-2 - foo]",
"",
" [variable-3 - bar]");
MT("listNumberNested",
"[variable-2 1. foo]",
"",
" [variable-3 2. bar]");
MT("listMixed",
"[variable-2 * foo]",
"",
" [variable-3 + bar]",
"",
" [keyword - hello]",
"",
" [variable-2 1. world]");
MT("listBlockquote",
"[variable-2 * foo]",
"",
" [variable-3 + bar]",
"",
" [quote&quote-1&variable-3 > hello]");
MT("listCode",
"[variable-2 * foo]",
"",
" [variable-3 + bar]",
"",
" [comment hello]");
// Code with internal indentation
MT("listCodeIndentation",
"[variable-2 * foo]",
"",
" [comment bar]",
" [comment hello]",
" [comment world]",
" [comment foo]",
" [variable-2 bar]");
// List nesting edge cases
MT("listNested",
"[variable-2 * foo]",
"",
" [variable-3 * bar]",
"",
" [variable-3 hello]"
);
MT("listNested",
"[variable-2 * foo]",
"",
" [variable-3 * bar]",
"",
" [keyword * foo]"
);
// Code followed by text
MT("listCodeText",
"[variable-2 * foo]",
"",
" [comment bar]",
"",
"hello");
// Following tests directly from official Markdown documentation
// http://daringfireball.net/projects/markdown/syntax#hr
MT("hrSpace",
"[hr * * *]");
MT("hr",
"[hr ***]");
MT("hrLong",
"[hr *****]");
MT("hrSpaceDash",
"[hr - - -]");
MT("hrDashLong",
"[hr ---------------------------------------]");
//Images
MT("Images",
"[image&image-marker !][image&image-alt-text&link [[alt text]]][string&url (http://link.to/image.jpg)]")
//Images with highlight alt text
MT("imageEm",
"[image&image-marker !][image&image-alt-text&link [[][image-alt-text&em&image&link *alt text*][image&image-alt-text&link ]]][string&url (http://link.to/image.jpg)]");
MT("imageStrong",
"[image&image-marker !][image&image-alt-text&link [[][image-alt-text&strong&image&link **alt text**][image&image-alt-text&link ]]][string&url (http://link.to/image.jpg)]");
MT("imageEmStrong",
"[image&image-marker !][image&image-alt-text&link [[][image&image-alt-text&em&strong&link ***alt text***][image&image-alt-text&link ]]][string&url (http://link.to/image.jpg)]");
// Inline link with title
MT("linkTitle",
"[link [[foo]]][string&url (http://example.com/ \"bar\")] hello");
// Inline link without title
MT("linkNoTitle",
"[link [[foo]]][string&url (http://example.com/)] bar");
// Inline link with image
MT("linkImage",
"[link [[][link&image&image-marker !][link&image&image-alt-text&link [[alt text]]][string&url (http://link.to/image.jpg)][link ]]][string&url (http://example.com/)] bar");
// Inline link with Em
MT("linkEm",
"[link [[][link&em *foo*][link ]]][string&url (http://example.com/)] bar");
// Inline link with Strong
MT("linkStrong",
"[link [[][link&strong **foo**][link ]]][string&url (http://example.com/)] bar");
// Inline link with EmStrong
MT("linkEmStrong",
"[link [[][link&em&strong ***foo***][link ]]][string&url (http://example.com/)] bar");
MT("multilineLink",
"[link [[foo]",
"[link bar]]][string&url (https://foo#_a)]",
"should not be italics")
// Image with title
MT("imageTitle",
"[image&image-marker !][image&image-alt-text&link [[alt text]]][string&url (http://example.com/ \"bar\")] hello");
// Image without title
MT("imageNoTitle",
"[image&image-marker !][image&image-alt-text&link [[alt text]]][string&url (http://example.com/)] bar");
// Image with asterisks
MT("imageAsterisks",
"[image&image-marker !][image&image-alt-text&link [[ ][image&image-alt-text&em&link *alt text*][image&image-alt-text&link ]]][string&url (http://link.to/image.jpg)] bar");
// Not a link. Should be normal text due to square brackets being used
// regularly in text, especially in quoted material, and no space is allowed
// between square brackets and parentheses (per Dingus).
MT("notALink",
"[link [[foo]]] (bar)");
// Reference-style links
MT("linkReference",
"[link [[foo]]][string&url [[bar]]] hello");
// Reference-style links with Em
MT("linkReferenceEm",
"[link [[][link&em *foo*][link ]]][string&url [[bar]]] hello");
// Reference-style links with Strong
MT("linkReferenceStrong",
"[link [[][link&strong **foo**][link ]]][string&url [[bar]]] hello");
// Reference-style links with EmStrong
MT("linkReferenceEmStrong",
"[link [[][link&em&strong ***foo***][link ]]][string&url [[bar]]] hello");
// Reference-style links with optional space separator (per documentation)
// "You can optionally use a space to separate the sets of brackets"
MT("linkReferenceSpace",
"[link [[foo]]] [string&url [[bar]]] hello");
// Should only allow a single space ("...use *a* space...")
MT("linkReferenceDoubleSpace",
"[link [[foo]]] [link [[bar]]] hello");
// Reference-style links with implicit link name
MT("linkImplicit",
"[link [[foo]]][string&url [[]]] hello");
// @todo It would be nice if, at some point, the document was actually
// checked to see if the referenced link exists
// Link label, for reference-style links (taken from documentation)
MT("labelNoTitle",
"[link [[foo]]:] [string&url http://example.com/]");
MT("labelIndented",
" [link [[foo]]:] [string&url http://example.com/]");
MT("labelSpaceTitle",
"[link [[foo bar]]:] [string&url http://example.com/ \"hello\"]");
MT("labelDoubleTitle",
"[link [[foo bar]]:] [string&url http://example.com/ \"hello\"] \"world\"");
MT("labelTitleDoubleQuotes",
"[link [[foo]]:] [string&url http://example.com/ \"bar\"]");
MT("labelTitleSingleQuotes",
"[link [[foo]]:] [string&url http://example.com/ 'bar']");
MT("labelTitleParentheses",
"[link [[foo]]:] [string&url http://example.com/ (bar)]");
MT("labelTitleInvalid",
"[link [[foo]]:] [string&url http://example.com/] bar");
MT("labelLinkAngleBrackets",
"[link [[foo]]:] [string&url <http://example.com/> \"bar\"]");
MT("labelTitleNextDoubleQuotes",
"[link [[foo]]:] [string&url http://example.com/]",
"[string \"bar\"] hello");
MT("labelTitleNextSingleQuotes",
"[link [[foo]]:] [string&url http://example.com/]",
"[string 'bar'] hello");
MT("labelTitleNextParentheses",
"[link [[foo]]:] [string&url http://example.com/]",
"[string (bar)] hello");
MT("labelTitleNextMixed",
"[link [[foo]]:] [string&url http://example.com/]",
"(bar\" hello");
MT("labelEscape",
"[link [[foo \\]] ]]:] [string&url http://example.com/]");
MT("labelEscapeColon",
"[link [[foo \\]]: bar]]:] [string&url http://example.com/]");
MT("labelEscapeEnd",
"\\[[foo\\]]: http://example.com/");
MT("linkWeb",
"[link <http://example.com/>] foo");
MT("linkWebDouble",
"[link <http://example.com/>] foo [link <http://example.com/>]");
MT("linkEmail",
"[link <user@example.com>] foo");
MT("linkEmailDouble",
"[link <user@example.com>] foo [link <user@example.com>]");
MT("emAsterisk",
"[em *foo*] bar");
MT("emUnderscore",
"[em _foo_] bar");
MT("emInWordAsterisk",
"foo[em *bar*]hello");
MT("emInWordUnderscore",
"foo_bar_hello");
// Per documentation: "...surround an * or _ with spaces, it’ll be
// treated as a literal asterisk or underscore."
MT("emEscapedBySpaceIn",
"foo [em _bar _ hello_] world");
MT("emEscapedBySpaceOut",
"foo _ bar [em _hello_] world");
MT("emEscapedByNewline",
"foo",
"_ bar [em _hello_] world");
// Unclosed emphasis characters
// Instead of simply marking as EM / STRONG, it would be nice to have an
// incomplete flag for EM and STRONG, that is styled slightly different.
MT("emIncompleteAsterisk",
"foo [em *bar]");
MT("emIncompleteUnderscore",
"foo [em _bar]");
MT("strongAsterisk",
"[strong **foo**] bar");
MT("strongUnderscore",
"[strong __foo__] bar");
MT("emStrongAsterisk",
"[em *foo][em&strong **bar*][strong hello**] world");
MT("emStrongUnderscore",
"[em _foo ][em&strong __bar_][strong hello__] world");
// "...same character must be used to open and close an emphasis span.""
MT("emStrongMixed",
"[em _foo][em&strong **bar*hello__ world]");
MT("emStrongMixed",
"[em *foo ][em&strong __bar_hello** world]");
MT("linkWithNestedParens",
"[link [[foo]]][string&url (bar(baz))]")
// These characters should be escaped:
// \ backslash
// ` backtick
// * asterisk
// _ underscore
// {} curly braces
// [] square brackets
// () parentheses
// # hash mark
// + plus sign
// - minus sign (hyphen)
// . dot
// ! exclamation mark
MT("escapeBacktick",
"foo \\`bar\\`");
MT("doubleEscapeBacktick",
"foo \\\\[comment `bar\\\\`]");
MT("escapeAsterisk",
"foo \\*bar\\*");
MT("doubleEscapeAsterisk",
"foo \\\\[em *bar\\\\*]");
MT("escapeUnderscore",
"foo \\_bar\\_");
MT("doubleEscapeUnderscore",
"foo \\\\[em _bar\\\\_]");
MT("escapeHash",
"\\# foo");
MT("doubleEscapeHash",
"\\\\# foo");
MT("escapeNewline",
"\\",
"[em *foo*]");
// Class override tests
TokenTypeOverrideTest("overrideHeader1",
"[override-header&override-header-1 # Foo]");
TokenTypeOverrideTest("overrideHeader2",
"[override-header&override-header-2 ## Foo]");
TokenTypeOverrideTest("overrideHeader3",
"[override-header&override-header-3 ### Foo]");
TokenTypeOverrideTest("overrideHeader4",
"[override-header&override-header-4 #### Foo]");
TokenTypeOverrideTest("overrideHeader5",
"[override-header&override-header-5 ##### Foo]");
TokenTypeOverrideTest("overrideHeader6",
"[override-header&override-header-6 ###### Foo]");
TokenTypeOverrideTest("overrideCode",
"[override-code `foo`]");
TokenTypeOverrideTest("overrideCodeBlock",
"[override-code ```]",
"[override-code foo]",
"[override-code ```]");
TokenTypeOverrideTest("overrideQuote",
"[override-quote&override-quote-1 > foo]",
"[override-quote&override-quote-1 > bar]");
TokenTypeOverrideTest("overrideQuoteNested",
"[override-quote&override-quote-1 > foo]",
"[override-quote&override-quote-1 >][override-quote&override-quote-2 > bar]",
"[override-quote&override-quote-1 >][override-quote&override-quote-2 >][override-quote&override-quote-3 > baz]");
TokenTypeOverrideTest("overrideLists",
"[override-list1 - foo]",
"",
" [override-list2 + bar]",
"",
" [override-list3 * baz]",
"",
" [override-list1 1. qux]",
"",
" [override-list2 - quux]");
TokenTypeOverrideTest("overrideHr",
"[override-hr * * *]");
TokenTypeOverrideTest("overrideImage",
"[override-image&override-image-marker !][override-image&override-image-alt-text&link [[alt text]]][override-link-href&url (http://link.to/image.jpg)]");
TokenTypeOverrideTest("overrideLinkText",
"[override-link-text [[foo]]][override-link-href&url (http://example.com)]");
TokenTypeOverrideTest("overrideLinkEmailAndInline",
"[override-link-email <][override-link-inline foo@example.com>]");
TokenTypeOverrideTest("overrideEm",
"[override-em *foo*]");
TokenTypeOverrideTest("overrideStrong",
"[override-strong **foo**]");
TokenTypeOverrideTest("overrideStrikethrough",
"[override-strikethrough ~~foo~~]");
TokenTypeOverrideTest("overrideEmoji",
"[override-emoji :foo:]");
FormatTokenTypeOverrideTest("overrideFormatting",
"[override-formatting-escape \\*]");
// Tests to make sure GFM-specific things aren't getting through
MT("taskList",
"[variable-2 * ][link&variable-2 [[ ]]][variable-2 bar]");
MT("fencedCodeBlocks",
"[comment ```]",
"[comment foo]",
"",
"[comment bar]",
"[comment ```]",
"baz");
MT("fencedCodeBlocks_invalidClosingFence_trailingText",
"[comment ```]",
"[comment foo]",
"[comment ``` must not have trailing text]",
"[comment baz]");
MT("fencedCodeBlocks_invalidClosingFence_trailingTabs",
"[comment ```]",
"[comment foo]",
"[comment ```\t]",
"[comment baz]");
MT("fencedCodeBlocks_validClosingFence",
"[comment ```]",
"[comment foo]",
// may have trailing spaces
"[comment ``` ]",
"baz");
MT("fencedCodeBlocksInList_closingFenceIndented",
"[variable-2 - list]",
" [variable-2&comment ```]",
" [comment foo]",
" [variable-2&comment ```]",
" [variable-2 baz]");
MT("fencedCodeBlocksInList_closingFenceIndentedTooMuch",
"[variable-2 - list]",
" [variable-2&comment ```]",
" [comment foo]",
" [comment ```]",
" [comment baz]");
MT("fencedCodeBlockModeSwitching",
"[comment ```javascript]",
"[variable foo]",
"",
"[comment ```]",
"bar");
MT_noFencedHighlight("fencedCodeBlock_noHighlight",
"[comment ```javascript]",
"[comment foo]",
"[comment ```]");
MT("fencedCodeBlockModeSwitchingObjc",
"[comment ```objective-c]",
"[keyword @property] [variable NSString] [operator *] [variable foo];",
"[comment ```]",
"bar");
MT("fencedCodeBlocksMultipleChars",
"[comment `````]",
"[comment foo]",
"[comment ```]",
"[comment foo]",
"[comment `````]",
"bar");
MT("fencedCodeBlocksTildes",
"[comment ~~~]",
"[comment foo]",
"[comment ~~~]",
"bar");
MT("fencedCodeBlocksTildesMultipleChars",
"[comment ~~~~~]",
"[comment ~~~]",
"[comment foo]",
"[comment ~~~~~]",
"bar");
MT("fencedCodeBlocksMultipleChars",
"[comment `````]",
"[comment foo]",
"[comment ```]",
"[comment foo]",
"[comment `````]",
"bar");
MT("fencedCodeBlocksMixed",
"[comment ~~~]",
"[comment ```]",
"[comment foo]",
"[comment ~~~]",
"bar");
MT("fencedCodeBlocksAfterBlockquote",
"[quote&quote-1 > foo]",
"[comment ```]",
"[comment bar]",
"[comment ```]");
// fencedCode indented too much should act as simple indentedCode
// (hence has no highlight formatting)
FT("tooMuchIndentedFencedCode",
" [comment ```]",
" [comment code]",
" [comment ```]");
MT("autoTerminateFencedCodeWhenLeavingList",
"[variable-2 - list1]",
" [variable-3 - list2]",
" [variable-3&comment ```]",
" [comment code]",
" [variable-3 - list2]",
" [variable-2&comment ```]",
" [comment code]",
"[quote&quote-1 > foo]");
// Tests that require XML mode
MT("xmlMode",
"[tag&bracket <][tag div][tag&bracket >]",
" *foo*",
" [tag&bracket <][tag http://github.com][tag&bracket />]",
"[tag&bracket </][tag div][tag&bracket >]",
"[link <http://github.com/>]");
MT("xmlModeWithMarkdownInside",
"[tag&bracket <][tag div] [attribute markdown]=[string 1][tag&bracket >]",
"[em *foo*]",
"[link <http://github.com/>]",
"[tag </div>]",
"[link <http://github.com/>]",
"[tag&bracket <][tag div][tag&bracket >]",
"[tag&bracket </][tag div][tag&bracket >]");
MT("xmlModeLineBreakInTags",
"[tag&bracket <][tag div] [attribute id]=[string \"1\"]",
" [attribute class]=[string \"sth\"][tag&bracket >]xxx",
"[tag&bracket </][tag div][tag&bracket >]");
MT("xmlModeCommentWithBlankLine",
"[comment <!-- Hello]",
"",
"[comment World -->]");
MT("xmlModeCDATA",
"[atom <![CDATA[ Hello]",
"",
"[atom FooBar]",
"[atom Test ]]]]>]");
MT("xmlModePreprocessor",
"[meta <?php] [meta echo '1234'; ?>]");
MT_noXml("xmlHighlightDisabled",
"<div>foo</div>");
// Tests Emojis
ET("emojiDefault",
"[builtin :foobar:]");
ET("emojiTable",
" :--:");
})();
<!doctype html>
<title>CodeMirror: Mathematica mode</title>
<meta charset="utf-8"/>
<link rel=stylesheet href="../../doc/docs.css">
<link rel=stylesheet href=../../lib/codemirror.css>
<script src=../../lib/codemirror.js></script>
<script src=../../addon/edit/matchbrackets.js></script>
<script src=mathematica.js></script>
<style type=text/css>
.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
</style>
<div id=nav>
<a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png" alt=""></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="#">Mathematica</a>
</ul>
</div>
<article>
<h2>Mathematica mode</h2>
<textarea id="mathematicaCode">
(* example Mathematica code *)
(* Dualisiert wird anhand einer Polarität an einer
Quadrik $x^t Q x = 0$ mit regulärer Matrix $Q$ (also
mit $det(Q) \neq 0$), z.B. die Identitätsmatrix.
$p$ ist eine Liste von Polynomen - ein Ideal. *)
dualize::"singular" = "Q must be regular: found Det[Q]==0.";
dualize[ Q_, p_ ] := Block[
{ m, n, xv, lv, uv, vars, polys, dual },
If[Det[Q] == 0,
Message[dualize::"singular"],
m = Length[p];
n = Length[Q] - 1;
xv = Table[Subscript[x, i], {i, 0, n}];
lv = Table[Subscript[l, i], {i, 1, m}];
uv = Table[Subscript[u, i], {i, 0, n}];
(* Konstruiere Ideal polys. *)
If[m == 0,
polys = Q.uv,
polys = Join[p, Q.uv - Transpose[Outer[D, p, xv]].lv]
];
(* Eliminiere die ersten n + 1 + m Variablen xv und lv
aus dem Ideal polys. *)
vars = Join[xv, lv];
dual = GroebnerBasis[polys, uv, vars];
(* Ersetze u mit x im Ergebnis. *)
ReplaceAll[dual, Rule[u, x]]
]
]
</textarea>
<script>
var mathematicaEditor = CodeMirror.fromTextArea(document.getElementById('mathematicaCode'), {
mode: 'text/x-mathematica',
lineNumbers: true,
matchBrackets: true
});
</script>
<p><strong>MIME types defined:</strong> <code>text/x-mathematica</code> (Mathematica).</p>
</article>
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: https://codemirror.net/LICENSE
// Mathematica mode copyright (c) 2015 by Calin Barbat
// Based on code by Patrick Scheibe (halirutan)
// See: https://github.com/halirutan/Mathematica-Source-Highlighting/tree/master/src/lang-mma.js
(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);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
CodeMirror.defineMode('mathematica', function(_config, _parserConfig) {
// used pattern building blocks
var Identifier = '[a-zA-Z\\$][a-zA-Z0-9\\$]*';
var pBase = "(?:\\d+)";
var pFloat = "(?:\\.\\d+|\\d+\\.\\d*|\\d+)";
var pFloatBase = "(?:\\.\\w+|\\w+\\.\\w*|\\w+)";
var pPrecision = "(?:`(?:`?"+pFloat+")?)";
// regular expressions
var reBaseForm = new RegExp('(?:'+pBase+'(?:\\^\\^'+pFloatBase+pPrecision+'?(?:\\*\\^[+-]?\\d+)?))');
var reFloatForm = new RegExp('(?:' + pFloat + pPrecision + '?(?:\\*\\^[+-]?\\d+)?)');
var reIdInContext = new RegExp('(?:`?)(?:' + Identifier + ')(?:`(?:' + Identifier + '))*(?:`?)');
function tokenBase(stream, state) {
var ch;
// get next character
ch = stream.next();
// string
if (ch === '"') {
state.tokenize = tokenString;
return state.tokenize(stream, state);
}
// comment
if (ch === '(') {
if (stream.eat('*')) {
state.commentLevel++;
state.tokenize = tokenComment;
return state.tokenize(stream, state);
}
}
// go back one character
stream.backUp(1);
// look for numbers
// Numbers in a baseform
if (stream.match(reBaseForm, true, false)) {
return 'number';
}
// Mathematica numbers. Floats (1.2, .2, 1.) can have optionally a precision (`float) or an accuracy definition
// (``float). Note: while 1.2` is possible 1.2`` is not. At the end an exponent (float*^+12) can follow.
if (stream.match(reFloatForm, true, false)) {
return 'number';
}
/* In[23] and Out[34] */
if (stream.match(/(?:In|Out)\[[0-9]*\]/, true, false)) {
return 'atom';
}
// usage
if (stream.match(/([a-zA-Z\$][a-zA-Z0-9\$]*(?:`[a-zA-Z0-9\$]+)*::usage)/, true, false)) {
return 'meta';
}
// message
if (stream.match(/([a-zA-Z\$][a-zA-Z0-9\$]*(?:`[a-zA-Z0-9\$]+)*::[a-zA-Z\$][a-zA-Z0-9\$]*):?/, true, false)) {
return 'string-2';
}
// this makes a look-ahead match for something like variable:{_Integer}
// the match is then forwarded to the mma-patterns tokenizer.
if (stream.match(/([a-zA-Z\$][a-zA-Z0-9\$]*\s*:)(?:(?:[a-zA-Z\$][a-zA-Z0-9\$]*)|(?:[^:=>~@\^\&\*\)\[\]'\?,\|])).*/, true, false)) {
return 'variable-2';
}
// catch variables which are used together with Blank (_), BlankSequence (__) or BlankNullSequence (___)
// Cannot start with a number, but can have numbers at any other position. Examples
// blub__Integer, a1_, b34_Integer32
if (stream.match(/[a-zA-Z\$][a-zA-Z0-9\$]*_+[a-zA-Z\$][a-zA-Z0-9\$]*/, true, false)) {
return 'variable-2';
}
if (stream.match(/[a-zA-Z\$][a-zA-Z0-9\$]*_+/, true, false)) {
return 'variable-2';
}
if (stream.match(/_+[a-zA-Z\$][a-zA-Z0-9\$]*/, true, false)) {
return 'variable-2';
}
// Named characters in Mathematica, like \[Gamma].
if (stream.match(/\\\[[a-zA-Z\$][a-zA-Z0-9\$]*\]/, true, false)) {
return 'variable-3';
}
// Match all braces separately
if (stream.match(/(?:\[|\]|{|}|\(|\))/, true, false)) {
return 'bracket';
}
// Catch Slots (#, ##, #3, ##9 and the V10 named slots #name). I have never seen someone using more than one digit after #, so we match
// only one.
if (stream.match(/(?:#[a-zA-Z\$][a-zA-Z0-9\$]*|#+[0-9]?)/, true, false)) {
return 'variable-2';
}
// Literals like variables, keywords, functions
if (stream.match(reIdInContext, true, false)) {
return 'keyword';
}
// operators. Note that operators like @@ or /; are matched separately for each symbol.
if (stream.match(/(?:\\|\+|\-|\*|\/|,|;|\.|:|@|~|=|>|<|&|\||_|`|'|\^|\?|!|%)/, true, false)) {
return 'operator';
}
// everything else is an error
stream.next(); // advance the stream.
return 'error';
}
function tokenString(stream, state) {
var next, end = false, escaped = false;
while ((next = stream.next()) != null) {
if (next === '"' && !escaped) {
end = true;
break;
}
escaped = !escaped && next === '\\';
}
if (end && !escaped) {
state.tokenize = tokenBase;
}
return 'string';
};
function tokenComment(stream, state) {
var prev, next;
while(state.commentLevel > 0 && (next = stream.next()) != null) {
if (prev === '(' && next === '*') state.commentLevel++;
if (prev === '*' && next === ')') state.commentLevel--;
prev = next;
}
if (state.commentLevel <= 0) {
state.tokenize = tokenBase;
}
return 'comment';
}
return {
startState: function() {return {tokenize: tokenBase, commentLevel: 0};},
token: function(stream, state) {
if (stream.eatSpace()) return null;
return state.tokenize(stream, state);
},
blockCommentStart: "(*",
blockCommentEnd: "*)"
};
});
CodeMirror.defineMIME('text/x-mathematica', {
name: 'mathematica'
});
});
<!doctype html>
<title>CodeMirror: mbox mode</title>
<meta charset="utf-8"/>
<link rel=stylesheet href="../../doc/docs.css">
<link rel="stylesheet" href="../../lib/codemirror.css">
<script src="../../lib/codemirror.js"></script>
<script src="mbox.js"></script>
<style>.CodeMirror { border-top: 1px solid #ddd; border-bottom: 1px solid #ddd; }</style>
<div id=nav>
<a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png" alt=""></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="#">mbox</a>
</ul>
</div>
<article>
<h2>mbox mode</h2>
<form><textarea id="code" name="code">
From timothygu99@gmail.com Sun Apr 17 01:40:43 2016
From: Timothy Gu &lt;timothygu99@gmail.com&gt;
Date: Sat, 16 Apr 2016 18:40:43 -0700
Subject: mbox mode
Message-ID: &lt;Z8d+bTT50U/az94FZnyPkDjZmW0=@gmail.com&gt;
mbox mode is working!
Timothy
</textarea></form>
<script>
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {});
</script>
<p><strong>MIME types defined:</strong> <code>application/mbox</code>.</p>
</article>
// 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);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
var rfc2822 = [
"From", "Sender", "Reply-To", "To", "Cc", "Bcc", "Message-ID",
"In-Reply-To", "References", "Resent-From", "Resent-Sender", "Resent-To",
"Resent-Cc", "Resent-Bcc", "Resent-Message-ID", "Return-Path", "Received"
];
var rfc2822NoEmail = [
"Date", "Subject", "Comments", "Keywords", "Resent-Date"
];
CodeMirror.registerHelper("hintWords", "mbox", rfc2822.concat(rfc2822NoEmail));
var whitespace = /^[ \t]/;
var separator = /^From /; // See RFC 4155
var rfc2822Header = new RegExp("^(" + rfc2822.join("|") + "): ");
var rfc2822HeaderNoEmail = new RegExp("^(" + rfc2822NoEmail.join("|") + "): ");
var header = /^[^:]+:/; // Optional fields defined in RFC 2822
var email = /^[^ ]+@[^ ]+/;
var untilEmail = /^.*?(?=[^ ]+?@[^ ]+)/;
var bracketedEmail = /^<.*?>/;
var untilBracketedEmail = /^.*?(?=<.*>)/;
function styleForHeader(header) {
if (header === "Subject") return "header";
return "string";
}
function readToken(stream, state) {
if (stream.sol()) {
// From last line
state.inSeparator = false;
if (state.inHeader && stream.match(whitespace)) {
// Header folding
return null;
} else {
state.inHeader = false;
state.header = null;
}
if (stream.match(separator)) {
state.inHeaders = true;
state.inSeparator = true;
return "atom";
}
var match;
var emailPermitted = false;
if ((match = stream.match(rfc2822HeaderNoEmail)) ||
(emailPermitted = true) && (match = stream.match(rfc2822Header))) {
state.inHeaders = true;
state.inHeader = true;
state.emailPermitted = emailPermitted;
state.header = match[1];
return "atom";
}
// Use vim's heuristics: recognize custom headers only if the line is in a
// block of legitimate headers.
if (state.inHeaders && (match = stream.match(header))) {
state.inHeader = true;
state.emailPermitted = true;
state.header = match[1];
return "atom";
}
state.inHeaders = false;
stream.skipToEnd();
return null;
}
if (state.inSeparator) {
if (stream.match(email)) return "link";
if (stream.match(untilEmail)) return "atom";
stream.skipToEnd();
return "atom";
}
if (state.inHeader) {
var style = styleForHeader(state.header);
if (state.emailPermitted) {
if (stream.match(bracketedEmail)) return style + " link";
if (stream.match(untilBracketedEmail)) return style;
}
stream.skipToEnd();
return style;
}
stream.skipToEnd();
return null;
};
CodeMirror.defineMode("mbox", function() {
return {
startState: function() {
return {
// Is in a mbox separator
inSeparator: false,
// Is in a mail header
inHeader: false,
// If bracketed email is permitted. Only applicable when inHeader
emailPermitted: false,
// Name of current header
header: null,
// Is in a region of mail headers
inHeaders: false
};
},
token: readToken,
blankLine: function(state) {
state.inHeaders = state.inSeparator = state.inHeader = false;
}
};
});
CodeMirror.defineMIME("application/mbox", "mbox");
});
// 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);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
CodeMirror.modeInfo = [
{name: "APL", mime: "text/apl", mode: "apl", ext: ["dyalog", "apl"]},
{name: "PGP", mimes: ["application/pgp", "application/pgp-encrypted", "application/pgp-keys", "application/pgp-signature"], mode: "asciiarmor", ext: ["asc", "pgp", "sig"]},
{name: "ASN.1", mime: "text/x-ttcn-asn", mode: "asn.1", ext: ["asn", "asn1"]},
{name: "Asterisk", mime: "text/x-asterisk", mode: "asterisk", file: /^extensions\.conf$/i},
{name: "Brainfuck", mime: "text/x-brainfuck", mode: "brainfuck", ext: ["b", "bf"]},
{name: "C", mime: "text/x-csrc", mode: "clike", ext: ["c", "h", "ino"]},
{name: "C++", mime: "text/x-c++src", mode: "clike", ext: ["cpp", "c++", "cc", "cxx", "hpp", "h++", "hh", "hxx"], alias: ["cpp"]},
{name: "Cobol", mime: "text/x-cobol", mode: "cobol", ext: ["cob", "cpy"]},
{name: "C#", mime: "text/x-csharp", mode: "clike", ext: ["cs"], alias: ["csharp", "cs"]},
{name: "Clojure", mime: "text/x-clojure", mode: "clojure", ext: ["clj", "cljc", "cljx"]},
{name: "ClojureScript", mime: "text/x-clojurescript", mode: "clojure", ext: ["cljs"]},
{name: "Closure Stylesheets (GSS)", mime: "text/x-gss", mode: "css", ext: ["gss"]},
{name: "CMake", mime: "text/x-cmake", mode: "cmake", ext: ["cmake", "cmake.in"], file: /^CMakeLists.txt$/},
{name: "CoffeeScript", mimes: ["application/vnd.coffeescript", "text/coffeescript", "text/x-coffeescript"], mode: "coffeescript", ext: ["coffee"], alias: ["coffee", "coffee-script"]},
{name: "Common Lisp", mime: "text/x-common-lisp", mode: "commonlisp", ext: ["cl", "lisp", "el"], alias: ["lisp"]},
{name: "Cypher", mime: "application/x-cypher-query", mode: "cypher", ext: ["cyp", "cypher"]},
{name: "Cython", mime: "text/x-cython", mode: "python", ext: ["pyx", "pxd", "pxi"]},
{name: "Crystal", mime: "text/x-crystal", mode: "crystal", ext: ["cr"]},
{name: "CSS", mime: "text/css", mode: "css", ext: ["css"]},
{name: "CQL", mime: "text/x-cassandra", mode: "sql", ext: ["cql"]},
{name: "D", mime: "text/x-d", mode: "d", ext: ["d"]},
{name: "Dart", mimes: ["application/dart", "text/x-dart"], mode: "dart", ext: ["dart"]},
{name: "diff", mime: "text/x-diff", mode: "diff", ext: ["diff", "patch"]},
{name: "Django", mime: "text/x-django", mode: "django"},
{name: "Dockerfile", mime: "text/x-dockerfile", mode: "dockerfile", file: /^Dockerfile$/},
{name: "DTD", mime: "application/xml-dtd", mode: "dtd", ext: ["dtd"]},
{name: "Dylan", mime: "text/x-dylan", mode: "dylan", ext: ["dylan", "dyl", "intr"]},
{name: "EBNF", mime: "text/x-ebnf", mode: "ebnf"},
{name: "ECL", mime: "text/x-ecl", mode: "ecl", ext: ["ecl"]},
{name: "edn", mime: "application/edn", mode: "clojure", ext: ["edn"]},
{name: "Eiffel", mime: "text/x-eiffel", mode: "eiffel", ext: ["e"]},
{name: "Elm", mime: "text/x-elm", mode: "elm", ext: ["elm"]},
{name: "Embedded Javascript", mime: "application/x-ejs", mode: "htmlembedded", ext: ["ejs"]},
{name: "Embedded Ruby", mime: "application/x-erb", mode: "htmlembedded", ext: ["erb"]},
{name: "Erlang", mime: "text/x-erlang", mode: "erlang", ext: ["erl"]},
{name: "Esper", mime: "text/x-esper", mode: "sql"},
{name: "Factor", mime: "text/x-factor", mode: "factor", ext: ["factor"]},
{name: "FCL", mime: "text/x-fcl", mode: "fcl"},
{name: "Forth", mime: "text/x-forth", mode: "forth", ext: ["forth", "fth", "4th"]},
{name: "Fortran", mime: "text/x-fortran", mode: "fortran", ext: ["f", "for", "f77", "f90", "f95"]},
{name: "F#", mime: "text/x-fsharp", mode: "mllike", ext: ["fs"], alias: ["fsharp"]},
{name: "Gas", mime: "text/x-gas", mode: "gas", ext: ["s"]},
{name: "Gherkin", mime: "text/x-feature", mode: "gherkin", ext: ["feature"]},
{name: "GitHub Flavored Markdown", mime: "text/x-gfm", mode: "gfm", file: /^(readme|contributing|history).md$/i},
{name: "Go", mime: "text/x-go", mode: "go", ext: ["go"]},
{name: "Groovy", mime: "text/x-groovy", mode: "groovy", ext: ["groovy", "gradle"], file: /^Jenkinsfile$/},
{name: "HAML", mime: "text/x-haml", mode: "haml", ext: ["haml"]},
{name: "Haskell", mime: "text/x-haskell", mode: "haskell", ext: ["hs"]},
{name: "Haskell (Literate)", mime: "text/x-literate-haskell", mode: "haskell-literate", ext: ["lhs"]},
{name: "Haxe", mime: "text/x-haxe", mode: "haxe", ext: ["hx"]},
{name: "HXML", mime: "text/x-hxml", mode: "haxe", ext: ["hxml"]},
{name: "ASP.NET", mime: "application/x-aspx", mode: "htmlembedded", ext: ["aspx"], alias: ["asp", "aspx"]},
{name: "HTML", mime: "text/html", mode: "htmlmixed", ext: ["html", "htm", "handlebars", "hbs"], alias: ["xhtml"]},
{name: "HTTP", mime: "message/http", mode: "http"},
{name: "IDL", mime: "text/x-idl", mode: "idl", ext: ["pro"]},
{name: "Pug", mime: "text/x-pug", mode: "pug", ext: ["jade", "pug"], alias: ["jade"]},
{name: "Java", mime: "text/x-java", mode: "clike", ext: ["java"]},
{name: "Java Server Pages", mime: "application/x-jsp", mode: "htmlembedded", ext: ["jsp"], alias: ["jsp"]},
{name: "JavaScript", mimes: ["text/javascript", "text/ecmascript", "application/javascript", "application/x-javascript", "application/ecmascript"],
mode: "javascript", ext: ["js"], alias: ["ecmascript", "js", "node"]},
{name: "JSON", mimes: ["application/json", "application/x-json"], mode: "javascript", ext: ["json", "map"], alias: ["json5"]},
{name: "JSON-LD", mime: "application/ld+json", mode: "javascript", ext: ["jsonld"], alias: ["jsonld"]},
{name: "JSX", mime: "text/jsx", mode: "jsx", ext: ["jsx"]},
{name: "Jinja2", mime: "text/jinja2", mode: "jinja2", ext: ["j2", "jinja", "jinja2"]},
{name: "Julia", mime: "text/x-julia", mode: "julia", ext: ["jl"]},
{name: "Kotlin", mime: "text/x-kotlin", mode: "clike", ext: ["kt"]},
{name: "LESS", mime: "text/x-less", mode: "css", ext: ["less"]},
{name: "LiveScript", mime: "text/x-livescript", mode: "livescript", ext: ["ls"], alias: ["ls"]},
{name: "Lua", mime: "text/x-lua", mode: "lua", ext: ["lua"]},
{name: "Markdown", mime: "text/x-markdown", mode: "markdown", ext: ["markdown", "md", "mkd"]},
{name: "mIRC", mime: "text/mirc", mode: "mirc"},
{name: "MariaDB SQL", mime: "text/x-mariadb", mode: "sql"},
{name: "Mathematica", mime: "text/x-mathematica", mode: "mathematica", ext: ["m", "nb", "wl", "wls"]},
{name: "Modelica", mime: "text/x-modelica", mode: "modelica", ext: ["mo"]},
{name: "MUMPS", mime: "text/x-mumps", mode: "mumps", ext: ["mps"]},
{name: "MS SQL", mime: "text/x-mssql", mode: "sql"},
{name: "mbox", mime: "application/mbox", mode: "mbox", ext: ["mbox"]},
{name: "MySQL", mime: "text/x-mysql", mode: "sql"},
{name: "Nginx", mime: "text/x-nginx-conf", mode: "nginx", file: /nginx.*\.conf$/i},
{name: "NSIS", mime: "text/x-nsis", mode: "nsis", ext: ["nsh", "nsi"]},
{name: "NTriples", mimes: ["application/n-triples", "application/n-quads", "text/n-triples"],
mode: "ntriples", ext: ["nt", "nq"]},
{name: "Objective-C", mime: "text/x-objectivec", mode: "clike", ext: ["m"], alias: ["objective-c", "objc"]},
{name: "Objective-C++", mime: "text/x-objectivec++", mode: "clike", ext: ["mm"], alias: ["objective-c++", "objc++"]},
{name: "OCaml", mime: "text/x-ocaml", mode: "mllike", ext: ["ml", "mli", "mll", "mly"]},
{name: "Octave", mime: "text/x-octave", mode: "octave", ext: ["m"]},
{name: "Oz", mime: "text/x-oz", mode: "oz", ext: ["oz"]},
{name: "Pascal", mime: "text/x-pascal", mode: "pascal", ext: ["p", "pas"]},
{name: "PEG.js", mime: "null", mode: "pegjs", ext: ["jsonld"]},
{name: "Perl", mime: "text/x-perl", mode: "perl", ext: ["pl", "pm"]},
{name: "PHP", mimes: ["text/x-php", "application/x-httpd-php", "application/x-httpd-php-open"], mode: "php", ext: ["php", "php3", "php4", "php5", "php7", "phtml"]},
{name: "Pig", mime: "text/x-pig", mode: "pig", ext: ["pig"]},
{name: "Plain Text", mime: "text/plain", mode: "null", ext: ["txt", "text", "conf", "def", "list", "log"]},
{name: "PLSQL", mime: "text/x-plsql", mode: "sql", ext: ["pls"]},
{name: "PostgreSQL", mime: "text/x-pgsql", mode: "sql"},
{name: "PowerShell", mime: "application/x-powershell", mode: "powershell", ext: ["ps1", "psd1", "psm1"]},
{name: "Properties files", mime: "text/x-properties", mode: "properties", ext: ["properties", "ini", "in"], alias: ["ini", "properties"]},
{name: "ProtoBuf", mime: "text/x-protobuf", mode: "protobuf", ext: ["proto"]},
{name: "Python", mime: "text/x-python", mode: "python", ext: ["BUILD", "bzl", "py", "pyw"], file: /^(BUCK|BUILD)$/},
{name: "Puppet", mime: "text/x-puppet", mode: "puppet", ext: ["pp"]},
{name: "Q", mime: "text/x-q", mode: "q", ext: ["q"]},
{name: "R", mime: "text/x-rsrc", mode: "r", ext: ["r", "R"], alias: ["rscript"]},
{name: "reStructuredText", mime: "text/x-rst", mode: "rst", ext: ["rst"], alias: ["rst"]},
{name: "RPM Changes", mime: "text/x-rpm-changes", mode: "rpm"},
{name: "RPM Spec", mime: "text/x-rpm-spec", mode: "rpm", ext: ["spec"]},
{name: "Ruby", mime: "text/x-ruby", mode: "ruby", ext: ["rb"], alias: ["jruby", "macruby", "rake", "rb", "rbx"]},
{name: "Rust", mime: "text/x-rustsrc", mode: "rust", ext: ["rs"]},
{name: "SAS", mime: "text/x-sas", mode: "sas", ext: ["sas"]},
{name: "Sass", mime: "text/x-sass", mode: "sass", ext: ["sass"]},
{name: "Scala", mime: "text/x-scala", mode: "clike", ext: ["scala"]},
{name: "Scheme", mime: "text/x-scheme", mode: "scheme", ext: ["scm", "ss"]},
{name: "SCSS", mime: "text/x-scss", mode: "css", ext: ["scss"]},
{name: "Shell", mimes: ["text/x-sh", "application/x-sh"], mode: "shell", ext: ["sh", "ksh", "bash"], alias: ["bash", "sh", "zsh"], file: /^PKGBUILD$/},
{name: "Sieve", mime: "application/sieve", mode: "sieve", ext: ["siv", "sieve"]},
{name: "Slim", mimes: ["text/x-slim", "application/x-slim"], mode: "slim", ext: ["slim"]},
{name: "Smalltalk", mime: "text/x-stsrc", mode: "smalltalk", ext: ["st"]},
{name: "Smarty", mime: "text/x-smarty", mode: "smarty", ext: ["tpl"]},
{name: "Solr", mime: "text/x-solr", mode: "solr"},
{name: "SML", mime: "text/x-sml", mode: "mllike", ext: ["sml", "sig", "fun", "smackspec"]},
{name: "Soy", mime: "text/x-soy", mode: "soy", ext: ["soy"], alias: ["closure template"]},
{name: "SPARQL", mime: "application/sparql-query", mode: "sparql", ext: ["rq", "sparql"], alias: ["sparul"]},
{name: "Spreadsheet", mime: "text/x-spreadsheet", mode: "spreadsheet", alias: ["excel", "formula"]},
{name: "SQL", mime: "text/x-sql", mode: "sql", ext: ["sql"]},
{name: "SQLite", mime: "text/x-sqlite", mode: "sql"},
{name: "Squirrel", mime: "text/x-squirrel", mode: "clike", ext: ["nut"]},
{name: "Stylus", mime: "text/x-styl", mode: "stylus", ext: ["styl"]},
{name: "Swift", mime: "text/x-swift", mode: "swift", ext: ["swift"]},
{name: "sTeX", mime: "text/x-stex", mode: "stex"},
{name: "LaTeX", mime: "text/x-latex", mode: "stex", ext: ["text", "ltx", "tex"], alias: ["tex"]},
{name: "SystemVerilog", mime: "text/x-systemverilog", mode: "verilog", ext: ["v", "sv", "svh"]},
{name: "Tcl", mime: "text/x-tcl", mode: "tcl", ext: ["tcl"]},
{name: "Textile", mime: "text/x-textile", mode: "textile", ext: ["textile"]},
{name: "TiddlyWiki ", mime: "text/x-tiddlywiki", mode: "tiddlywiki"},
{name: "Tiki wiki", mime: "text/tiki", mode: "tiki"},
{name: "TOML", mime: "text/x-toml", mode: "toml", ext: ["toml"]},
{name: "Tornado", mime: "text/x-tornado", mode: "tornado"},
{name: "troff", mime: "text/troff", mode: "troff", ext: ["1", "2", "3", "4", "5", "6", "7", "8", "9"]},
{name: "TTCN", mime: "text/x-ttcn", mode: "ttcn", ext: ["ttcn", "ttcn3", "ttcnpp"]},
{name: "TTCN_CFG", mime: "text/x-ttcn-cfg", mode: "ttcn-cfg", ext: ["cfg"]},
{name: "Turtle", mime: "text/turtle", mode: "turtle", ext: ["ttl"]},
{name: "TypeScript", mime: "application/typescript", mode: "javascript", ext: ["ts"], alias: ["ts"]},
{name: "TypeScript-JSX", mime: "text/typescript-jsx", mode: "jsx", ext: ["tsx"], alias: ["tsx"]},
{name: "Twig", mime: "text/x-twig", mode: "twig"},
{name: "Web IDL", mime: "text/x-webidl", mode: "webidl", ext: ["webidl"]},
{name: "VB.NET", mime: "text/x-vb", mode: "vb", ext: ["vb"]},
{name: "VBScript", mime: "text/vbscript", mode: "vbscript", ext: ["vbs"]},
{name: "Velocity", mime: "text/velocity", mode: "velocity", ext: ["vtl"]},
{name: "Verilog", mime: "text/x-verilog", mode: "verilog", ext: ["v"]},
{name: "VHDL", mime: "text/x-vhdl", mode: "vhdl", ext: ["vhd", "vhdl"]},
{name: "Vue.js Component", mimes: ["script/x-vue", "text/x-vue"], mode: "vue", ext: ["vue"]},
{name: "XML", mimes: ["application/xml", "text/xml"], mode: "xml", ext: ["xml", "xsl", "xsd", "svg"], alias: ["rss", "wsdl", "xsd"]},
{name: "XQuery", mime: "application/xquery", mode: "xquery", ext: ["xy", "xquery"]},
{name: "Yacas", mime: "text/x-yacas", mode: "yacas", ext: ["ys"]},
{name: "YAML", mimes: ["text/x-yaml", "text/yaml"], mode: "yaml", ext: ["yaml", "yml"], alias: ["yml"]},
{name: "Z80", mime: "text/x-z80", mode: "z80", ext: ["z80"]},
{name: "mscgen", mime: "text/x-mscgen", mode: "mscgen", ext: ["mscgen", "mscin", "msc"]},
{name: "xu", mime: "text/x-xu", mode: "mscgen", ext: ["xu"]},
{name: "msgenny", mime: "text/x-msgenny", mode: "mscgen", ext: ["msgenny"]}
];
// Ensure all modes have a mime property for backwards compatibility
for (var i = 0; i < CodeMirror.modeInfo.length; i++) {
var info = CodeMirror.modeInfo[i];
if (info.mimes) info.mime = info.mimes[0];
}
CodeMirror.findModeByMIME = function(mime) {
mime = mime.toLowerCase();
for (var i = 0; i < CodeMirror.modeInfo.length; i++) {
var info = CodeMirror.modeInfo[i];
if (info.mime == mime) return info;
if (info.mimes) for (var j = 0; j < info.mimes.length; j++)
if (info.mimes[j] == mime) return info;
}
if (/\+xml$/.test(mime)) return CodeMirror.findModeByMIME("application/xml")
if (/\+json$/.test(mime)) return CodeMirror.findModeByMIME("application/json")
};
CodeMirror.findModeByExtension = function(ext) {
ext = ext.toLowerCase();
for (var i = 0; i < CodeMirror.modeInfo.length; i++) {
var info = CodeMirror.modeInfo[i];
if (info.ext) for (var j = 0; j < info.ext.length; j++)
if (info.ext[j] == ext) return info;
}
};
CodeMirror.findModeByFileName = function(filename) {
for (var i = 0; i < CodeMirror.modeInfo.length; i++) {
var info = CodeMirror.modeInfo[i];
if (info.file && info.file.test(filename)) return info;
}
var dot = filename.lastIndexOf(".");
var ext = dot > -1 && filename.substring(dot + 1, filename.length);
if (ext) return CodeMirror.findModeByExtension(ext);
};
CodeMirror.findModeByName = function(name) {
name = name.toLowerCase();
for (var i = 0; i < CodeMirror.modeInfo.length; i++) {
var info = CodeMirror.modeInfo[i];
if (info.name.toLowerCase() == name) return info;
if (info.alias) for (var j = 0; j < info.alias.length; j++)
if (info.alias[j].toLowerCase() == name) return info;
}
};
});
<!doctype html>
<title>CodeMirror: mIRC 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/twilight.css">
<script src="../../lib/codemirror.js"></script>
<script src="../../addon/edit/matchbrackets.js"></script>
<script src="mirc.js"></script>
<style>.CodeMirror {border: 1px solid black;}</style>
<div id=nav>
<a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png" alt=""></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="#">mIRC</a>
</ul>
</div>
<article>
<h2>mIRC mode</h2>
<form><textarea id="code" name="code">
;AKA Nick Tracker by Ford_Lawnmower irc.GeekShed.net #Script-Help
;*****************************************************************************;
;**Start Setup
;Change JoinDisplay, below, for On Join AKA Display. On = 1 - Off = 0
alias -l JoinDisplay { return 1 }
;Change MaxNicks, below, to the number of nicknames you want to store for each hostmask. I wouldn't go over 400 with this ;/
alias -l MaxNicks { return 20 }
;Change AKALogo, below, To the text you want displayed before each AKA result.
alias -l AKALogo { return 06 05A06K07A 06 }
;**End Setup
;*****************************************************************************;
On *:Join:#: {
if ($nick == $me) { .timer 1 1 ialupdateCheck $chan }
NickNamesAdd $nick $+($network,$wildsite)
if ($JoinDisplay) { .timerNickNames $+ $nick 1 2 NickNames.display $nick $chan $network $wildsite }
}
on *:Nick: { NickNamesAdd $newnick $+($network,$wildsite) $nick }
alias -l NickNames.display {
if ($gettok($hget(NickNames,$+($3,$4)),0,126) > 1) {
echo -g $2 $AKALogo $+(09,$1) $AKALogo 07 $mid($replace($hget(NickNames,$+($3,$4)),$chr(126),$chr(44)),2,-1)
}
}
alias -l NickNamesAdd {
if ($hget(NickNames,$2)) {
if (!$regex($hget(NickNames,$2),/~\Q $+ $replacecs($1,\E,\E\\E\Q) $+ \E~/i)) {
if ($gettok($hget(NickNames,$2),0,126) <= $MaxNicks) {
hadd NickNames $2 $+($hget(NickNames,$2),$1,~)
}
else {
hadd NickNames $2 $+($mid($hget(NickNames,$2),$pos($hget(NickNames,$2),~,2)),$1,~)
}
}
}
else {
hadd -m NickNames $2 $+(~,$1,~,$iif($3,$+($3,~)))
}
}
alias -l Fix.All.MindUser {
var %Fix.Count = $hfind(NickNames,/[^~]+[0-9]{4}~/,0,r).data
while (%Fix.Count) {
if ($Fix.MindUser($hget(NickNames,$hfind(NickNames,/[^~]+[0-9]{4}~/,%Fix.Count,r).data))) {
echo -ag Record %Fix.Count - $v1 - Was Cleaned
hadd NickNames $hfind(NickNames,/[^~]+[0-9]{4}~/,%Fix.Count,r).data $v1
}
dec %Fix.Count
}
}
alias -l Fix.MindUser { return $regsubex($1,/[^~]+[0-9]{4}~/g,$null) }
menu nicklist,query {
-
.AKA
..Check $$1: {
if ($gettok($hget(NickNames,$+($network,$address($1,2))),0,126) > 1) {
NickNames.display $1 $active $network $address($1,2)
}
else { echo -ag $AKALogo $+(09,$1) 07has not been known by any other nicknames while I have been watching. }
}
..Cleanup $$1:hadd NickNames $+($network,$address($1,2)) $fix.minduser($hget(NickNames,$+($network,$address($1,2))))
..Clear $$1:hadd NickNames $+($network,$address($1,2)) $+(~,$1,~)
..AKA Search Dialog:dialog $iif($dialog(AKA_Search),-v,-m) AKA_Search AKA_Search
-
}
menu status,channel {
-
.AKA
..AKA Search Dialog:dialog $iif($dialog(AKA_Search),-v,-m) AKA_Search AKA_Search
..Clean All Records:Fix.All.Minduser
-
}
dialog AKA_Search {
title "AKA Search Engine"
size -1 -1 206 221
option dbu
edit "", 1, 8 5 149 10, autohs
button "Search", 2, 163 4 32 12
radio "Search HostMask", 4, 61 22 55 10
radio "Search Nicknames", 5, 123 22 56 10
list 6, 8 38 190 169, sort extsel vsbar
button "Check Selected", 7, 67 206 40 12
button "Close", 8, 160 206 38 12, cancel
box "Search Type", 3, 11 17 183 18
button "Copy to Clipboard", 9, 111 206 46 12
}
On *:Dialog:Aka_Search:init:*: { did -c $dname 5 }
On *:Dialog:Aka_Search:Sclick:2,7,9: {
if ($did == 2) && ($did($dname,1)) {
did -r $dname 6
var %search $+(*,$v1,*), %type $iif($did($dname,5).state,data,item), %matches = $hfind(NickNames,%search,0,w). [ $+ [ %type ] ]
while (%matches) {
did -a $dname 6 $hfind(NickNames,%search,%matches,w). [ $+ [ %type ] ]
dec %matches
}
did -c $dname 6 1
}
elseif ($did == 7) && ($did($dname,6).seltext) { echo -ga $AKALogo 07 $mid($replace($hget(NickNames,$v1),$chr(126),$chr(44)),2,-1) }
elseif ($did == 9) && ($did($dname,6).seltext) { clipboard $mid($v1,$pos($v1,*,1)) }
}
On *:Start:{
if (!$hget(NickNames)) { hmake NickNames 10 }
if ($isfile(NickNames.hsh)) { hload NickNames NickNames.hsh }
}
On *:Exit: { if ($hget(NickNames)) { hsave NickNames NickNames.hsh } }
On *:Disconnect: { if ($hget(NickNames)) { hsave NickNames NickNames.hsh } }
On *:Unload: { hfree NickNames }
alias -l ialupdateCheck {
inc -z $+(%,ialupdateCheck,$network) $calc($nick($1,0) / 4)
;If your ial is already being updated on join .who $1 out.
;If you are using /names to update ial you will still need this line.
.who $1
}
Raw 352:*: {
if ($($+(%,ialupdateCheck,$network),2)) haltdef
NickNamesAdd $6 $+($network,$address($6,2))
}
Raw 315:*: {
if ($($+(%,ialupdateCheck,$network),2)) haltdef
}
</textarea></form>
<script>
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
theme: "twilight",
lineNumbers: true,
matchBrackets: true,
indentUnit: 4,
mode: "text/mirc"
});
</script>
<p><strong>MIME types defined:</strong> <code>text/mirc</code>.</p>
</article>
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: https://codemirror.net/LICENSE
//mIRC mode by Ford_Lawnmower :: Based on Velocity mode by Steve O'Hara
(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);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
CodeMirror.defineMIME("text/mirc", "mirc");
CodeMirror.defineMode("mirc", function() {
function parseWords(str) {
var obj = {}, words = str.split(" ");
for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
return obj;
}
var specials = parseWords("$! $$ $& $? $+ $abook $abs $active $activecid " +
"$activewid $address $addtok $agent $agentname $agentstat $agentver " +
"$alias $and $anick $ansi2mirc $aop $appactive $appstate $asc $asctime " +
"$asin $atan $avoice $away $awaymsg $awaytime $banmask $base $bfind " +
"$binoff $biton $bnick $bvar $bytes $calc $cb $cd $ceil $chan $chanmodes " +
"$chantypes $chat $chr $cid $clevel $click $cmdbox $cmdline $cnick $color " +
"$com $comcall $comchan $comerr $compact $compress $comval $cos $count " +
"$cr $crc $creq $crlf $ctime $ctimer $ctrlenter $date $day $daylight " +
"$dbuh $dbuw $dccignore $dccport $dde $ddename $debug $decode $decompress " +
"$deltok $devent $dialog $did $didreg $didtok $didwm $disk $dlevel $dll " +
"$dllcall $dname $dns $duration $ebeeps $editbox $emailaddr $encode $error " +
"$eval $event $exist $feof $ferr $fgetc $file $filename $filtered $finddir " +
"$finddirn $findfile $findfilen $findtok $fline $floor $fopen $fread $fserve " +
"$fulladdress $fulldate $fullname $fullscreen $get $getdir $getdot $gettok $gmt " +
"$group $halted $hash $height $hfind $hget $highlight $hnick $hotline " +
"$hotlinepos $ial $ialchan $ibl $idle $iel $ifmatch $ignore $iif $iil " +
"$inelipse $ini $inmidi $inpaste $inpoly $input $inrect $inroundrect " +
"$insong $instok $int $inwave $ip $isalias $isbit $isdde $isdir $isfile " +
"$isid $islower $istok $isupper $keychar $keyrpt $keyval $knick $lactive " +
"$lactivecid $lactivewid $left $len $level $lf $line $lines $link $lock " +
"$lock $locked $log $logstamp $logstampfmt $longfn $longip $lower $ltimer " +
"$maddress $mask $matchkey $matchtok $md5 $me $menu $menubar $menucontext " +
"$menutype $mid $middir $mircdir $mircexe $mircini $mklogfn $mnick $mode " +
"$modefirst $modelast $modespl $mouse $msfile $network $newnick $nick $nofile " +
"$nopath $noqt $not $notags $notify $null $numeric $numok $oline $onpoly " +
"$opnick $or $ord $os $passivedcc $pic $play $pnick $port $portable $portfree " +
"$pos $prefix $prop $protect $puttok $qt $query $rand $r $rawmsg $read $readomo " +
"$readn $regex $regml $regsub $regsubex $remove $remtok $replace $replacex " +
"$reptok $result $rgb $right $round $scid $scon $script $scriptdir $scriptline " +
"$sdir $send $server $serverip $sfile $sha1 $shortfn $show $signal $sin " +
"$site $sline $snick $snicks $snotify $sock $sockbr $sockerr $sockname " +
"$sorttok $sound $sqrt $ssl $sreq $sslready $status $strip $str $stripped " +
"$syle $submenu $switchbar $tan $target $ticks $time $timer $timestamp " +
"$timestampfmt $timezone $tip $titlebar $toolbar $treebar $trust $ulevel " +
"$ulist $upper $uptime $url $usermode $v1 $v2 $var $vcmd $vcmdstat $vcmdver " +
"$version $vnick $vol $wid $width $wildsite $wildtok $window $wrap $xor");
var keywords = parseWords("abook ajinvite alias aline ame amsg anick aop auser autojoin avoice " +
"away background ban bcopy beep bread break breplace bset btrunc bunset bwrite " +
"channel clear clearall cline clipboard close cnick color comclose comopen " +
"comreg continue copy creq ctcpreply ctcps dcc dccserver dde ddeserver " +
"debug dec describe dialog did didtok disable disconnect dlevel dline dll " +
"dns dqwindow drawcopy drawdot drawfill drawline drawpic drawrect drawreplace " +
"drawrot drawsave drawscroll drawtext ebeeps echo editbox emailaddr enable " +
"events exit fclose filter findtext finger firewall flash flist flood flush " +
"flushini font fopen fseek fsend fserve fullname fwrite ghide gload gmove " +
"gopts goto gplay gpoint gqreq groups gshow gsize gstop gtalk gunload hadd " +
"halt haltdef hdec hdel help hfree hinc hload hmake hop hsave ial ialclear " +
"ialmark identd if ignore iline inc invite iuser join kick linesep links list " +
"load loadbuf localinfo log mdi me menubar mkdir mnick mode msg nick noop notice " +
"notify omsg onotice part partall pdcc perform play playctrl pop protect pvoice " +
"qme qmsg query queryn quit raw reload remini remote remove rename renwin " +
"reseterror resetidle return rlevel rline rmdir run ruser save savebuf saveini " +
"say scid scon server set showmirc signam sline sockaccept sockclose socklist " +
"socklisten sockmark sockopen sockpause sockread sockrename sockudp sockwrite " +
"sound speak splay sreq strip switchbar timer timestamp titlebar tnick tokenize " +
"toolbar topic tray treebar ulist unload unset unsetall updatenl url uwho " +
"var vcadd vcmd vcrem vol while whois window winhelp write writeint if isalnum " +
"isalpha isaop isavoice isban ischan ishop isignore isin isincs isletter islower " +
"isnotify isnum ison isop isprotect isreg isupper isvoice iswm iswmcs " +
"elseif else goto menu nicklist status title icon size option text edit " +
"button check radio box scroll list combo link tab item");
var functions = parseWords("if elseif else and not or eq ne in ni for foreach while switch");
var isOperatorChar = /[+\-*&%=<>!?^\/\|]/;
function chain(stream, state, f) {
state.tokenize = f;
return f(stream, state);
}
function tokenBase(stream, state) {
var beforeParams = state.beforeParams;
state.beforeParams = false;
var ch = stream.next();
if (/[\[\]{}\(\),\.]/.test(ch)) {
if (ch == "(" && beforeParams) state.inParams = true;
else if (ch == ")") state.inParams = false;
return null;
}
else if (/\d/.test(ch)) {
stream.eatWhile(/[\w\.]/);
return "number";
}
else if (ch == "\\") {
stream.eat("\\");
stream.eat(/./);
return "number";
}
else if (ch == "/" && stream.eat("*")) {
return chain(stream, state, tokenComment);
}
else if (ch == ";" && stream.match(/ *\( *\(/)) {
return chain(stream, state, tokenUnparsed);
}
else if (ch == ";" && !state.inParams) {
stream.skipToEnd();
return "comment";
}
else if (ch == '"') {
stream.eat(/"/);
return "keyword";
}
else if (ch == "$") {
stream.eatWhile(/[$_a-z0-9A-Z\.:]/);
if (specials && specials.propertyIsEnumerable(stream.current().toLowerCase())) {
return "keyword";
}
else {
state.beforeParams = true;
return "builtin";
}
}
else if (ch == "%") {
stream.eatWhile(/[^,\s()]/);
state.beforeParams = true;
return "string";
}
else if (isOperatorChar.test(ch)) {
stream.eatWhile(isOperatorChar);
return "operator";
}
else {
stream.eatWhile(/[\w\$_{}]/);
var word = stream.current().toLowerCase();
if (keywords && keywords.propertyIsEnumerable(word))
return "keyword";
if (functions && functions.propertyIsEnumerable(word)) {
state.beforeParams = true;
return "keyword";
}
return null;
}
}
function tokenComment(stream, state) {
var maybeEnd = false, ch;
while (ch = stream.next()) {
if (ch == "/" && maybeEnd) {
state.tokenize = tokenBase;
break;
}
maybeEnd = (ch == "*");
}
return "comment";
}
function tokenUnparsed(stream, state) {
var maybeEnd = 0, ch;
while (ch = stream.next()) {
if (ch == ";" && maybeEnd == 2) {
state.tokenize = tokenBase;
break;
}
if (ch == ")")
maybeEnd++;
else if (ch != " ")
maybeEnd = 0;
}
return "meta";
}
return {
startState: function() {
return {
tokenize: tokenBase,
beforeParams: false,
inParams: false
};
},
token: function(stream, state) {
if (stream.eatSpace()) return null;
return state.tokenize(stream, state);
}
};
});
});
<!doctype html>
<title>CodeMirror: ML-like mode</title>
<meta charset="utf-8"/>
<link rel=stylesheet href="../../doc/docs.css">
<link rel=stylesheet href=../../lib/codemirror.css>
<script src=../../lib/codemirror.js></script>
<script src=../../addon/edit/matchbrackets.js></script>
<script src=mllike.js></script>
<style type=text/css>
.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
</style>
<div id=nav>
<a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png" alt=""></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="#">ML-like</a>
</ul>
</div>
<article>
<h2>OCaml mode</h2>
<textarea id="ocamlCode">
(* Summing a list of integers *)
let rec sum xs =
match xs with
| [] -&gt; 0
| x :: xs' -&gt; x + sum xs'
(* Quicksort *)
let rec qsort = function
| [] -&gt; []
| pivot :: rest -&gt;
let is_less x = x &lt; pivot in
let left, right = List.partition is_less rest in
qsort left @ [pivot] @ qsort right
(* Fibonacci Sequence *)
let rec fib_aux n a b =
match n with
| 0 -&gt; a
| _ -&gt; fib_aux (n - 1) (a + b) a
let fib n = fib_aux n 0 1
(* Birthday paradox *)
let year_size = 365.
let rec birthday_paradox prob people =
let prob' = (year_size -. float people) /. year_size *. prob in
if prob' &lt; 0.5 then
Printf.printf "answer = %d\n" (people+1)
else
birthday_paradox prob' (people+1) ;;
birthday_paradox 1.0 1
(* Church numerals *)
let zero f x = x
let succ n f x = f (n f x)
let one = succ zero
let two = succ (succ zero)
let add n1 n2 f x = n1 f (n2 f x)
let to_string n = n (fun k -&gt; "S" ^ k) "0"
let _ = to_string (add (succ two) two)
(* Elementary functions *)
let square x = x * x;;
let rec fact x =
if x &lt;= 1 then 1 else x * fact (x - 1);;
(* Automatic memory management *)
let l = 1 :: 2 :: 3 :: [];;
[1; 2; 3];;
5 :: l;;
(* Polymorphism: sorting lists *)
let rec sort = function
| [] -&gt; []
| x :: l -&gt; insert x (sort l)
and insert elem = function
| [] -&gt; [elem]
| x :: l -&gt;
if elem &lt; x then elem :: x :: l else x :: insert elem l;;
(* Imperative features *)
let add_polynom p1 p2 =
let n1 = Array.length p1
and n2 = Array.length p2 in
let result = Array.create (max n1 n2) 0 in
for i = 0 to n1 - 1 do result.(i) &lt;- p1.(i) done;
for i = 0 to n2 - 1 do result.(i) &lt;- result.(i) + p2.(i) done;
result;;
add_polynom [| 1; 2 |] [| 1; 2; 3 |];;
(* We may redefine fact using a reference cell and a for loop *)
let fact n =
let result = ref 1 in
for i = 2 to n do
result := i * !result
done;
!result;;
fact 5;;
(* Triangle (graphics) *)
let () =
ignore( Glut.init Sys.argv );
Glut.initDisplayMode ~double_buffer:true ();
ignore (Glut.createWindow ~title:"OpenGL Demo");
let angle t = 10. *. t *. t in
let render () =
GlClear.clear [ `color ];
GlMat.load_identity ();
GlMat.rotate ~angle: (angle (Sys.time ())) ~z:1. ();
GlDraw.begins `triangles;
List.iter GlDraw.vertex2 [-1., -1.; 0., 1.; 1., -1.];
GlDraw.ends ();
Glut.swapBuffers () in
GlMat.mode `modelview;
Glut.displayFunc ~cb:render;
Glut.idleFunc ~cb:(Some Glut.postRedisplay);
Glut.mainLoop ()
(* A Hundred Lines of Caml - http://caml.inria.fr/about/taste.en.html *)
(* OCaml page on Wikipedia - http://en.wikipedia.org/wiki/OCaml *)
module type S = sig type t end
let x = {|
this is a long string
with many lines and stuff
|}
let b = 0b00110
let h = 0x123abcd
let e = 1e-10
let i = 1.
let x = 30_000
let o = 0o1234
[1; 2; 3] (* lists *)
1 @ 2
1. +. 2.
</textarea>
<h2>F# mode</h2>
<textarea id="fsharpCode">
module CodeMirror.FSharp
let rec fib = function
| 0 -> 0
| 1 -> 1
| n -> fib (n - 1) + fib (n - 2)
type Point =
{
x : int
y : int
}
type Color =
| Red
| Green
| Blue
[0 .. 10]
|> List.map ((+) 2)
|> List.fold (fun x y -> x + y) 0
|> printf "%i"
</textarea>
<script>
var ocamlEditor = CodeMirror.fromTextArea(document.getElementById('ocamlCode'), {
mode: 'text/x-ocaml',
lineNumbers: true,
matchBrackets: true
});
var fsharpEditor = CodeMirror.fromTextArea(document.getElementById('fsharpCode'), {
mode: 'text/x-fsharp',
lineNumbers: true,
matchBrackets: true
});
</script>
<p><strong>MIME types defined:</strong> <code>text/x-ocaml</code> (OCaml) and <code>text/x-fsharp</code> (F#).</p>
</article>
// 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);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
CodeMirror.defineMode('mllike', function(_config, parserConfig) {
var words = {
'as': 'keyword',
'do': 'keyword',
'else': 'keyword',
'end': 'keyword',
'exception': 'keyword',
'fun': 'keyword',
'functor': 'keyword',
'if': 'keyword',
'in': 'keyword',
'include': 'keyword',
'let': 'keyword',
'of': 'keyword',
'open': 'keyword',
'rec': 'keyword',
'struct': 'keyword',
'then': 'keyword',
'type': 'keyword',
'val': 'keyword',
'while': 'keyword',
'with': 'keyword'
};
var extraWords = parserConfig.extraWords || {};
for (var prop in extraWords) {
if (extraWords.hasOwnProperty(prop)) {
words[prop] = parserConfig.extraWords[prop];
}
}
var hintWords = [];
for (var k in words) { hintWords.push(k); }
CodeMirror.registerHelper("hintWords", "mllike", hintWords);
function tokenBase(stream, state) {
var ch = stream.next();
if (ch === '"') {
state.tokenize = tokenString;
return state.tokenize(stream, state);
}
if (ch === '{') {
if (stream.eat('|')) {
state.longString = true;
state.tokenize = tokenLongString;
return state.tokenize(stream, state);
}
}
if (ch === '(') {
if (stream.eat('*')) {
state.commentLevel++;
state.tokenize = tokenComment;
return state.tokenize(stream, state);
}
}
if (ch === '~' || ch === '?') {
stream.eatWhile(/\w/);
return 'variable-2';
}
if (ch === '`') {
stream.eatWhile(/\w/);
return 'quote';
}
if (ch === '/' && parserConfig.slashComments && stream.eat('/')) {
stream.skipToEnd();
return 'comment';
}
if (/\d/.test(ch)) {
if (ch === '0' && stream.eat(/[bB]/)) {
stream.eatWhile(/[01]/);
} if (ch === '0' && stream.eat(/[xX]/)) {
stream.eatWhile(/[0-9a-fA-F]/)
} if (ch === '0' && stream.eat(/[oO]/)) {
stream.eatWhile(/[0-7]/);
} else {
stream.eatWhile(/[\d_]/);
if (stream.eat('.')) {
stream.eatWhile(/[\d]/);
}
if (stream.eat(/[eE]/)) {
stream.eatWhile(/[\d\-+]/);
}
}
return 'number';
}
if ( /[+\-*&%=<>!?|@\.~:]/.test(ch)) {
return 'operator';
}
if (/[\w\xa1-\uffff]/.test(ch)) {
stream.eatWhile(/[\w\xa1-\uffff]/);
var cur = stream.current();
return words.hasOwnProperty(cur) ? words[cur] : 'variable';
}
return null
}
function tokenString(stream, state) {
var next, end = false, escaped = false;
while ((next = stream.next()) != null) {
if (next === '"' && !escaped) {
end = true;
break;
}
escaped = !escaped && next === '\\';
}
if (end && !escaped) {
state.tokenize = tokenBase;
}
return 'string';
};
function tokenComment(stream, state) {
var prev, next;
while(state.commentLevel > 0 && (next = stream.next()) != null) {
if (prev === '(' && next === '*') state.commentLevel++;
if (prev === '*' && next === ')') state.commentLevel--;
prev = next;
}
if (state.commentLevel <= 0) {
state.tokenize = tokenBase;
}
return 'comment';
}
function tokenLongString(stream, state) {
var prev, next;
while (state.longString && (next = stream.next()) != null) {
if (prev === '|' && next === '}') state.longString = false;
prev = next;
}
if (!state.longString) {
state.tokenize = tokenBase;
}
return 'string';
}
return {
startState: function() {return {tokenize: tokenBase, commentLevel: 0, longString: false};},
token: function(stream, state) {
if (stream.eatSpace()) return null;
return state.tokenize(stream, state);
},
blockCommentStart: "(*",
blockCommentEnd: "*)",
lineComment: parserConfig.slashComments ? "//" : null
};
});
CodeMirror.defineMIME('text/x-ocaml', {
name: 'mllike',
extraWords: {
'and': 'keyword',
'assert': 'keyword',
'begin': 'keyword',
'class': 'keyword',
'constraint': 'keyword',
'done': 'keyword',
'downto': 'keyword',
'external': 'keyword',
'function': 'keyword',
'initializer': 'keyword',
'lazy': 'keyword',
'match': 'keyword',
'method': 'keyword',
'module': 'keyword',
'mutable': 'keyword',
'new': 'keyword',
'nonrec': 'keyword',
'object': 'keyword',
'private': 'keyword',
'sig': 'keyword',
'to': 'keyword',
'try': 'keyword',
'value': 'keyword',
'virtual': 'keyword',
'when': 'keyword',
// builtins
'raise': 'builtin',
'failwith': 'builtin',
'true': 'builtin',
'false': 'builtin',
// Pervasives builtins
'asr': 'builtin',
'land': 'builtin',
'lor': 'builtin',
'lsl': 'builtin',
'lsr': 'builtin',
'lxor': 'builtin',
'mod': 'builtin',
'or': 'builtin',
// More Pervasives
'raise_notrace': 'builtin',
'trace': 'builtin',
'exit': 'builtin',
'print_string': 'builtin',
'print_endline': 'builtin',
'int': 'type',
'float': 'type',
'bool': 'type',
'char': 'type',
'string': 'type',
'unit': 'type',
// Modules
'List': 'builtin'
}
});
CodeMirror.defineMIME('text/x-fsharp', {
name: 'mllike',
extraWords: {
'abstract': 'keyword',
'assert': 'keyword',
'base': 'keyword',
'begin': 'keyword',
'class': 'keyword',
'default': 'keyword',
'delegate': 'keyword',
'do!': 'keyword',
'done': 'keyword',
'downcast': 'keyword',
'downto': 'keyword',
'elif': 'keyword',
'extern': 'keyword',
'finally': 'keyword',
'for': 'keyword',
'function': 'keyword',
'global': 'keyword',
'inherit': 'keyword',
'inline': 'keyword',
'interface': 'keyword',
'internal': 'keyword',
'lazy': 'keyword',
'let!': 'keyword',
'match': 'keyword',
'member': 'keyword',
'module': 'keyword',
'mutable': 'keyword',
'namespace': 'keyword',
'new': 'keyword',
'null': 'keyword',
'override': 'keyword',
'private': 'keyword',
'public': 'keyword',
'return!': 'keyword',
'return': 'keyword',
'select': 'keyword',
'static': 'keyword',
'to': 'keyword',
'try': 'keyword',
'upcast': 'keyword',
'use!': 'keyword',
'use': 'keyword',
'void': 'keyword',
'when': 'keyword',
'yield!': 'keyword',
'yield': 'keyword',
// Reserved words
'atomic': 'keyword',
'break': 'keyword',
'checked': 'keyword',
'component': 'keyword',
'const': 'keyword',
'constraint': 'keyword',
'constructor': 'keyword',
'continue': 'keyword',
'eager': 'keyword',
'event': 'keyword',
'external': 'keyword',
'fixed': 'keyword',
'method': 'keyword',
'mixin': 'keyword',
'object': 'keyword',
'parallel': 'keyword',
'process': 'keyword',
'protected': 'keyword',
'pure': 'keyword',
'sealed': 'keyword',
'tailcall': 'keyword',
'trait': 'keyword',
'virtual': 'keyword',
'volatile': 'keyword',
// builtins
'List': 'builtin',
'Seq': 'builtin',
'Map': 'builtin',
'Set': 'builtin',
'Option': 'builtin',
'int': 'builtin',
'string': 'builtin',
'not': 'builtin',
'true': 'builtin',
'false': 'builtin',
'raise': 'builtin',
'failwith': 'builtin'
},
slashComments: true
});
CodeMirror.defineMIME('text/x-sml', {
name: 'mllike',
extraWords: {
'abstype': 'keyword',
'and': 'keyword',
'andalso': 'keyword',
'case': 'keyword',
'datatype': 'keyword',
'fn': 'keyword',
'handle': 'keyword',
'infix': 'keyword',
'infixr': 'keyword',
'local': 'keyword',
'nonfix': 'keyword',
'op': 'keyword',
'orelse': 'keyword',
'raise': 'keyword',
'withtype': 'keyword',
'eqtype': 'keyword',
'sharing': 'keyword',
'sig': 'keyword',
'signature': 'keyword',
'structure': 'keyword',
'where': 'keyword',
'true': 'keyword',
'false': 'keyword',
// types
'int': 'builtin',
'real': 'builtin',
'string': 'builtin',
'char': 'builtin',
'bool': 'builtin'
},
slashComments: true
});
});
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment