update codemirror to 5.39.2

This commit is contained in:
azivner 2018-08-15 11:25:30 +02:00
parent 510704a074
commit 3204291463
35 changed files with 1001 additions and 265 deletions

View file

@ -137,12 +137,14 @@
CodeMirror.registerHelper("fold", "xml", function(cm, start) {
var iter = new Iter(cm, start.line, 0);
for (;;) {
var openTag = toNextTag(iter), end;
if (!openTag || !(end = toTagEnd(iter)) || iter.line != start.line) return;
var openTag = toNextTag(iter)
if (!openTag || iter.line != start.line) return
var end = toTagEnd(iter)
if (!end) return
if (!openTag[1] && end != "selfClose") {
var startPos = Pos(iter.line, iter.ch);
var endPos = findMatchingClose(iter, openTag[2]);
return endPos && {from: startPos, to: endPos.from};
return endPos && cmp(endPos.from, startPos) > 0 ? {from: startPos, to: endPos.from} : null
}
}
});

View file

@ -90,7 +90,7 @@
var state = cm.state.matchHighlighter;
cm.addOverlay(state.overlay = makeOverlay(query, hasBoundary, style));
if (state.options.annotateScrollbar && cm.showMatchesOnScrollbar) {
var searchFor = hasBoundary ? new RegExp("\\b" + query.replace(/[\\\[+*?(){|^$]/g, "\\$&") + "\\b") : query;
var searchFor = hasBoundary ? new RegExp("\\b" + query.replace(/[\\\[.+*?(){|^$]/g, "\\$&") + "\\b") : query;
state.matchesonscroll = cm.showMatchesOnScrollbar(searchFor, false,
{className: "CodeMirror-selection-highlight-scrollbar"});
}

View file

@ -746,6 +746,16 @@ function collapsedSpanAtSide(line, start) {
function collapsedSpanAtStart(line) { return collapsedSpanAtSide(line, true) }
function collapsedSpanAtEnd(line) { return collapsedSpanAtSide(line, false) }
function collapsedSpanAround(line, ch) {
var sps = sawCollapsedSpans && line.markedSpans, found
if (sps) { for (var i = 0; i < sps.length; ++i) {
var sp = sps[i]
if (sp.marker.collapsed && (sp.from == null || sp.from < ch) && (sp.to == null || sp.to > ch) &&
(!found || compareCollapsedMarkers(found, sp.marker) < 0)) { found = sp.marker }
} }
return found
}
// Test whether there exists a collapsed span that partially
// overlaps (covers the start or end, but not both) of a new span.
// Such overlap is not allowed.
@ -2778,12 +2788,11 @@ function coordsChar(cm, x, y) {
var lineObj = getLine(doc, lineN)
for (;;) {
var found = coordsCharInner(cm, lineObj, lineN, x, y)
var merged = collapsedSpanAtEnd(lineObj)
var mergedPos = merged && merged.find(0, true)
if (merged && (found.ch > mergedPos.from.ch || found.ch == mergedPos.from.ch && found.xRel > 0))
{ lineN = lineNo(lineObj = mergedPos.to.line) }
else
{ return found }
var collapsed = collapsedSpanAround(lineObj, found.ch + (found.xRel > 0 ? 1 : 0))
if (!collapsed) { return found }
var rangeEnd = collapsed.find(1)
if (rangeEnd.line == lineN) { return rangeEnd }
lineObj = getLine(doc, lineN = rangeEnd.line)
}
}
@ -3543,6 +3552,7 @@ var NativeScrollbars = function(place, scroll, cm) {
this.cm = cm
var vert = this.vert = elt("div", [elt("div", null, null, "min-width: 1px")], "CodeMirror-vscrollbar")
var horiz = this.horiz = elt("div", [elt("div", null, null, "height: 100%; min-height: 1px")], "CodeMirror-hscrollbar")
vert.tabIndex = horiz.tabIndex = -1
place(vert); place(horiz)
on(vert, "scroll", function () {
@ -4783,7 +4793,7 @@ function addChangeToHistory(doc, change, selAfter, opId) {
if ((hist.lastOp == opId ||
hist.lastOrigin == change.origin && change.origin &&
((change.origin.charAt(0) == "+" && doc.cm && hist.lastModTime > time - doc.cm.options.historyEventDelay) ||
((change.origin.charAt(0) == "+" && hist.lastModTime > time - (doc.cm ? doc.cm.options.historyEventDelay : 500)) ||
change.origin.charAt(0) == "*")) &&
(cur = lastChangeEvent(hist, hist.lastOp == opId))) {
// Merge this change into the last event
@ -5684,7 +5694,7 @@ LineWidget.prototype.changed = function () {
this.height = null
var diff = widgetHeight(this) - oldH
if (!diff) { return }
updateLineHeight(line, line.height + diff)
if (!lineIsHidden(this.doc, line)) { updateLineHeight(line, line.height + diff) }
if (cm) {
runInOp(cm, function () {
cm.curOp.forceUpdate = true
@ -6567,8 +6577,6 @@ function registerGlobalHandlers() {
// Called when the window resizes
function onResize(cm) {
var d = cm.display
if (d.lastWrapHeight == d.wrapper.clientHeight && d.lastWrapWidth == d.wrapper.clientWidth)
{ return }
// Might be a text scaling operation, clear size caches.
d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null
d.scrollbarsClipped = false
@ -6614,7 +6622,7 @@ keyMap.pcDefault = {
"Ctrl-G": "findNext", "Shift-Ctrl-G": "findPrev", "Shift-Ctrl-F": "replace", "Shift-Ctrl-R": "replaceAll",
"Ctrl-[": "indentLess", "Ctrl-]": "indentMore",
"Ctrl-U": "undoSelection", "Shift-Ctrl-U": "redoSelection", "Alt-U": "redoSelection",
fallthrough: "basic"
"fallthrough": "basic"
}
// Very basic readline/emacs-style bindings, which are standard on Mac.
keyMap.emacsy = {
@ -6632,7 +6640,7 @@ keyMap.macDefault = {
"Cmd-G": "findNext", "Shift-Cmd-G": "findPrev", "Cmd-Alt-F": "replace", "Shift-Cmd-Alt-F": "replaceAll",
"Cmd-[": "indentLess", "Cmd-]": "indentMore", "Cmd-Backspace": "delWrappedLineLeft", "Cmd-Delete": "delWrappedLineRight",
"Cmd-U": "undoSelection", "Shift-Cmd-U": "redoSelection", "Ctrl-Up": "goDocStart", "Ctrl-Down": "goDocEnd",
fallthrough: ["basic", "emacsy"]
"fallthrough": ["basic", "emacsy"]
}
keyMap["default"] = mac ? keyMap.macDefault : keyMap.pcDefault
@ -7312,8 +7320,8 @@ function leftButtonStartDrag(cm, event, pos, behavior) {
var dragEnd = operation(cm, function (e) {
if (webkit) { display.scroller.draggable = false }
cm.state.draggingText = false
off(document, "mouseup", dragEnd)
off(document, "mousemove", mouseMove)
off(display.wrapper.ownerDocument, "mouseup", dragEnd)
off(display.wrapper.ownerDocument, "mousemove", mouseMove)
off(display.scroller, "dragstart", dragStart)
off(display.scroller, "drop", dragEnd)
if (!moved) {
@ -7322,7 +7330,7 @@ function leftButtonStartDrag(cm, event, pos, behavior) {
{ extendSelection(cm.doc, pos, null, null, behavior.extend) }
// Work around unexplainable focus problem in IE9 (#2127) and Chrome (#3081)
if (webkit || ie && ie_version == 9)
{ setTimeout(function () {document.body.focus(); display.input.focus()}, 20) }
{ setTimeout(function () {display.wrapper.ownerDocument.body.focus(); display.input.focus()}, 20) }
else
{ display.input.focus() }
}
@ -7337,8 +7345,8 @@ function leftButtonStartDrag(cm, event, pos, behavior) {
dragEnd.copy = !behavior.moveOnDrag
// IE's approach to draggable
if (display.scroller.dragDrop) { display.scroller.dragDrop() }
on(document, "mouseup", dragEnd)
on(document, "mousemove", mouseMove)
on(display.wrapper.ownerDocument, "mouseup", dragEnd)
on(display.wrapper.ownerDocument, "mousemove", mouseMove)
on(display.scroller, "dragstart", dragStart)
on(display.scroller, "drop", dragEnd)
@ -7470,19 +7478,19 @@ function leftButtonSelect(cm, event, start, behavior) {
counter = Infinity
e_preventDefault(e)
display.input.focus()
off(document, "mousemove", move)
off(document, "mouseup", up)
off(display.wrapper.ownerDocument, "mousemove", move)
off(display.wrapper.ownerDocument, "mouseup", up)
doc.history.lastSelOrigin = null
}
var move = operation(cm, function (e) {
if (!e_button(e)) { done(e) }
if (e.buttons === 0 || !e_button(e)) { done(e) }
else { extend(e) }
})
var up = operation(cm, done)
cm.state.selectingText = up
on(document, "mousemove", move)
on(document, "mouseup", up)
on(display.wrapper.ownerDocument, "mousemove", move)
on(display.wrapper.ownerDocument, "mouseup", up)
}
// Used when mouse-selecting to adjust the anchor to the proper side
@ -7765,6 +7773,7 @@ function CodeMirror(place, options) {
var doc = options.value
if (typeof doc == "string") { doc = new Doc(doc, options.mode, null, options.lineSeparator, options.direction) }
else if (options.mode) { doc.modeOption = options.mode }
this.doc = doc
var input = new CodeMirror.inputStyles[options.inputStyle](this)
@ -8755,8 +8764,12 @@ ContentEditableInput.prototype.showSelection = function (info, takeFocus) {
this.showMultipleSelections(info)
};
ContentEditableInput.prototype.getSelection = function () {
return this.cm.display.wrapper.ownerDocument.getSelection()
};
ContentEditableInput.prototype.showPrimarySelection = function () {
var sel = window.getSelection(), cm = this.cm, prim = cm.doc.sel.primary()
var sel = this.getSelection(), cm = this.cm, prim = cm.doc.sel.primary()
var from = prim.from(), to = prim.to()
if (cm.display.viewTo == cm.display.viewFrom || from.line >= cm.display.viewTo || to.line < cm.display.viewFrom) {
@ -8823,13 +8836,13 @@ ContentEditableInput.prototype.showMultipleSelections = function (info) {
};
ContentEditableInput.prototype.rememberSelection = function () {
var sel = window.getSelection()
var sel = this.getSelection()
this.lastAnchorNode = sel.anchorNode; this.lastAnchorOffset = sel.anchorOffset
this.lastFocusNode = sel.focusNode; this.lastFocusOffset = sel.focusOffset
};
ContentEditableInput.prototype.selectionInEditor = function () {
var sel = window.getSelection()
var sel = this.getSelection()
if (!sel.rangeCount) { return false }
var node = sel.getRangeAt(0).commonAncestorContainer
return contains(this.div, node)
@ -8864,14 +8877,14 @@ ContentEditableInput.prototype.receivedFocus = function () {
};
ContentEditableInput.prototype.selectionChanged = function () {
var sel = window.getSelection()
var sel = this.getSelection()
return sel.anchorNode != this.lastAnchorNode || sel.anchorOffset != this.lastAnchorOffset ||
sel.focusNode != this.lastFocusNode || sel.focusOffset != this.lastFocusOffset
};
ContentEditableInput.prototype.pollSelection = function () {
if (this.readDOMTimeout != null || this.gracePeriod || !this.selectionChanged()) { return }
var sel = window.getSelection(), cm = this.cm
var sel = this.getSelection(), cm = this.cm
// On Android Chrome (version 56, at least), backspacing into an
// uneditable block element will put the cursor in that element,
// and then, because it's not editable, hide the virtual keyboard.
@ -9005,7 +9018,7 @@ ContentEditableInput.prototype.setUneditable = function (node) {
};
ContentEditableInput.prototype.onKeyPress = function (e) {
if (e.charCode == 0) { return }
if (e.charCode == 0 || this.composing) { return }
e.preventDefault()
if (!this.cm.isReadOnly())
{ operation(this.cm, applyTextInput)(this.cm, String.fromCharCode(e.charCode == null ? e.keyCode : e.charCode), 0) }
@ -9045,12 +9058,13 @@ function isInGutter(node) {
function badPos(pos, bad) { if (bad) { pos.bad = true; } return pos }
function domTextBetween(cm, from, to, fromLine, toLine) {
var text = "", closing = false, lineSep = cm.doc.lineSeparator()
var text = "", closing = false, lineSep = cm.doc.lineSeparator(), extraLinebreak = false
function recognizeMarker(id) { return function (marker) { return marker.id == id; } }
function close() {
if (closing) {
text += lineSep
closing = false
if (extraLinebreak) { text += lineSep }
closing = extraLinebreak = false
}
}
function addText(str) {
@ -9062,8 +9076,8 @@ function domTextBetween(cm, from, to, fromLine, toLine) {
function walk(node) {
if (node.nodeType == 1) {
var cmText = node.getAttribute("cm-text")
if (cmText != null) {
addText(cmText || node.textContent.replace(/\u200b/g, ""))
if (cmText) {
addText(cmText)
return
}
var markerID = node.getAttribute("cm-marker"), range
@ -9074,19 +9088,24 @@ function domTextBetween(cm, from, to, fromLine, toLine) {
return
}
if (node.getAttribute("contenteditable") == "false") { return }
var isBlock = /^(pre|div|p)$/i.test(node.nodeName)
var isBlock = /^(pre|div|p|li|table|br)$/i.test(node.nodeName)
if (!/^br$/i.test(node.nodeName) && node.textContent.length == 0) { return }
if (isBlock) { close() }
for (var i = 0; i < node.childNodes.length; i++)
{ walk(node.childNodes[i]) }
if (/^(pre|p)$/i.test(node.nodeName)) { extraLinebreak = true }
if (isBlock) { closing = true }
} else if (node.nodeType == 3) {
addText(node.nodeValue)
addText(node.nodeValue.replace(/\u200b/g, "").replace(/\u00a0/g, " "))
}
}
for (;;) {
walk(from)
if (from == to) { break }
from = from.nextSibling
extraLinebreak = false
}
return text
}
@ -9187,13 +9206,10 @@ TextareaInput.prototype.init = function (display) {
var this$1 = this;
var input = this, cm = this.cm
this.createField(display)
var te = this.textarea
// Wraps and hides input textarea
var div = this.wrapper = hiddenTextarea()
// The semihidden textarea that is focused when the editor is
// focused, and receives input.
var te = this.textarea = div.firstChild
display.wrapper.insertBefore(div, display.wrapper.firstChild)
display.wrapper.insertBefore(this.wrapper, display.wrapper.firstChild)
// Needed to hide big blue blinking cursor on Mobile Safari (doesn't seem to work in iOS 8 anymore)
if (ios) { te.style.width = "0px" }
@ -9260,6 +9276,14 @@ TextareaInput.prototype.init = function (display) {
})
};
TextareaInput.prototype.createField = function (_display) {
// Wraps and hides input textarea
this.wrapper = hiddenTextarea()
// The semihidden textarea that is focused when the editor is
// focused, and receives input.
this.textarea = this.wrapper.firstChild
};
TextareaInput.prototype.prepareSelection = function () {
// Redraw the selection and/or cursor
var cm = this.cm, display = cm.display, doc = cm.doc
@ -9653,7 +9677,7 @@ CodeMirror.fromTextArea = fromTextArea
addLegacyProps(CodeMirror)
CodeMirror.version = "5.35.0"
CodeMirror.version = "5.39.2"
return CodeMirror;

View file

@ -216,15 +216,15 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
indent: function(state, textAfter) {
if (state.tokenize != tokenBase && state.tokenize != null || state.typeAtEndOfLine) return CodeMirror.Pass;
var ctx = state.context, firstChar = textAfter && textAfter.charAt(0);
var closing = firstChar == ctx.type;
if (ctx.type == "statement" && firstChar == "}") ctx = ctx.prev;
if (parserConfig.dontIndentStatements)
while (ctx.type == "statement" && parserConfig.dontIndentStatements.test(ctx.info))
ctx = ctx.prev
if (hooks.indent) {
var hook = hooks.indent(state, ctx, textAfter);
var hook = hooks.indent(state, ctx, textAfter, indentUnit);
if (typeof hook == "number") return hook
}
var closing = firstChar == ctx.type;
var switchBlock = ctx.prev && ctx.prev.info == "switch";
if (parserConfig.allmanIndentation && /[{(]/.test(firstChar)) {
while (ctx.type != "top" && ctx.type != "}") ctx = ctx.prev
@ -374,7 +374,7 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
blockKeywords: words("case do else for if switch while struct"),
defKeywords: words("struct"),
typeFirstDefinitions: true,
atoms: words("null true false"),
atoms: words("NULL true false"),
hooks: {"#": cppHook, "*": pointerHook},
modeProps: {fold: ["brace", "include"]}
});
@ -390,7 +390,7 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
blockKeywords: words("catch class do else finally for if struct switch try while"),
defKeywords: words("class namespace struct enum union"),
typeFirstDefinitions: true,
atoms: words("true false null"),
atoms: words("true false NULL"),
dontIndentStatements: /^template$/,
isIdentifierChar: /[\w\$_~\xa1-\uffff]/,
hooks: {
@ -597,34 +597,51 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
name: "clike",
keywords: words(
/*keywords*/
"package as typealias class interface this super val " +
"var fun for is in This throw return " +
"package as typealias class interface this super val operator " +
"var fun for is in This throw return annotation " +
"break continue object if else while do try when !in !is as? " +
/*soft keywords*/
"file import where by get set abstract enum open inner override private public internal " +
"protected catch finally out final vararg reified dynamic companion constructor init " +
"sealed field property receiver param sparam lateinit data inline noinline tailrec " +
"external annotation crossinline const operator infix suspend actual expect"
"external annotation crossinline const operator infix suspend actual expect setparam"
),
types: words(
/* package java.lang */
"Boolean Byte Character CharSequence Class ClassLoader Cloneable Comparable " +
"Compiler Double Exception Float Integer Long Math Number Object Package Pair Process " +
"Runtime Runnable SecurityManager Short StackTraceElement StrictMath String " +
"StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void"
"StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void Annotation Any BooleanArray " +
"ByteArray Char CharArray DeprecationLevel DoubleArray Enum FloatArray Function Int IntArray Lazy " +
"LazyThreadSafetyMode LongArray Nothing ShortArray Unit"
),
intendSwitch: false,
indentStatements: false,
multiLineStrings: true,
number: /^(?:0x[a-f\d_]+|0b[01_]+|(?:[\d_]+\.?\d*|\.\d+)(?:e[-+]?[\d_]+)?)(u|ll?|l|f)?/i,
number: /^(?:0x[a-f\d_]+|0b[01_]+|(?:[\d_]+(\.\d+)?|\.\d+)(?:e[-+]?[\d_]+)?)(u|ll?|l|f)?/i,
blockKeywords: words("catch class do else finally for if where try while enum"),
defKeywords: words("class val var object interface fun"),
atoms: words("true false null this"),
hooks: {
"@": function(stream) {
stream.eatWhile(/[\w\$_]/);
return "meta";
},
'"': function(stream, state) {
state.tokenize = tokenKotlinString(stream.match('""'));
return state.tokenize(stream, state);
},
indent: function(state, ctx, textAfter, indentUnit) {
var firstChar = textAfter && textAfter.charAt(0);
if ((state.prevToken == "}" || state.prevToken == ")") && textAfter == "")
return state.indented;
if (state.prevToken == "operator" && textAfter != "}" ||
state.prevToken == "variable" && firstChar == "." ||
(state.prevToken == "}" || state.prevToken == ")") && firstChar == ".")
return indentUnit * 2 + ctx.indented;
if (ctx.align && ctx.type == "}")
return ctx.indented + (state.context.type == (textAfter || "").charAt(0) ? 0 : indentUnit);
}
},
modeProps: {closeBrackets: {triples: '"'}}

View file

@ -11,30 +11,64 @@
})(function(CodeMirror) {
"use strict";
var from = "from";
var fromRegex = new RegExp("^(\\s*)\\b(" + from + ")\\b", "i");
var shells = ["run", "cmd", "entrypoint", "shell"];
var shellsAsArrayRegex = new RegExp("^(\\s*)(" + shells.join('|') + ")(\\s+\\[)", "i");
var expose = "expose";
var exposeRegex = new RegExp("^(\\s*)(" + expose + ")(\\s+)", "i");
var others = [
"arg", "from", "maintainer", "label", "env",
"add", "copy", "volume", "user",
"workdir", "onbuild", "stopsignal", "healthcheck", "shell"
];
// Collect all Dockerfile directives
var instructions = ["from", "maintainer", "run", "cmd", "expose", "env",
"add", "copy", "entrypoint", "volume", "user",
"workdir", "onbuild"],
var instructions = [from, expose].concat(shells).concat(others),
instructionRegex = "(" + instructions.join('|') + ")",
instructionOnlyLine = new RegExp(instructionRegex + "\\s*$", "i"),
instructionWithArguments = new RegExp(instructionRegex + "(\\s+)", "i");
instructionOnlyLine = new RegExp("^(\\s*)" + instructionRegex + "(\\s*)(#.*)?$", "i"),
instructionWithArguments = new RegExp("^(\\s*)" + instructionRegex + "(\\s+)", "i");
CodeMirror.defineSimpleMode("dockerfile", {
start: [
// Block comment: This is a line starting with a comment
{
regex: /#.*$/,
regex: /^\s*#.*$/,
sol: true,
token: "comment"
},
{
regex: fromRegex,
token: [null, "keyword"],
sol: true,
next: "from"
},
// Highlight an instruction without any arguments (for convenience)
{
regex: instructionOnlyLine,
token: "variable-2"
token: [null, "keyword", null, "error"],
sol: true
},
{
regex: shellsAsArrayRegex,
token: [null, "keyword", null],
sol: true,
next: "array"
},
{
regex: exposeRegex,
token: [null, "keyword", null],
sol: true,
next: "expose"
},
// Highlight an instruction followed by arguments
{
regex: instructionWithArguments,
token: ["variable-2", null],
token: [null, "keyword", null],
sol: true,
next: "arguments"
},
{
@ -42,26 +76,21 @@
token: null
}
],
arguments: [
from: [
{
regex: /\s*$/,
token: null,
next: "start"
},
{
// Line comment without instruction arguments is an error
regex: /#.*$/,
token: "error",
regex: /(\s*)(#.*)$/,
token: [null, "error"],
next: "start"
},
{
regex: /[^#]+\\$/,
token: null
},
{
// Match everything except for the inline comment
regex: /[^#]+/,
token: null,
next: "start"
},
{
regex: /$/,
token: null,
regex: /(\s*\S+\s+)(as)/i,
token: [null, "keyword"],
next: "start"
},
// Fail safe return to start
@ -70,9 +99,112 @@
next: "start"
}
],
meta: {
lineComment: "#"
single: [
{
regex: /(?:[^\\']|\\.)/,
token: "string"
},
{
regex: /'/,
token: "string",
pop: true
}
],
double: [
{
regex: /(?:[^\\"]|\\.)/,
token: "string"
},
{
regex: /"/,
token: "string",
pop: true
}
],
array: [
{
regex: /\]/,
token: null,
next: "start"
},
{
regex: /"(?:[^\\"]|\\.)*"?/,
token: "string"
}
],
expose: [
{
regex: /\d+$/,
token: "number",
next: "start"
},
{
regex: /[^\d]+$/,
token: null,
next: "start"
},
{
regex: /\d+/,
token: "number"
},
{
regex: /[^\d]+/,
token: null
},
// Fail safe return to start
{
token: null,
next: "start"
}
],
arguments: [
{
regex: /^\s*#.*$/,
sol: true,
token: "comment"
},
{
regex: /"(?:[^\\"]|\\.)*"?$/,
token: "string",
next: "start"
},
{
regex: /"/,
token: "string",
push: "double"
},
{
regex: /'(?:[^\\']|\\.)*'?$/,
token: "string",
next: "start"
},
{
regex: /'/,
token: "string",
push: "single"
},
{
regex: /[^#"']+[\\`]$/,
token: null
},
{
regex: /[^#"']+$/,
token: null,
next: "start"
},
{
regex: /[^#"']+/,
token: null
},
// Fail safe return to start
{
token: null,
next: "start"
}
],
meta: {
lineComment: "#"
}
});
CodeMirror.defineMIME("text/x-dockerfile", "dockerfile");

View file

@ -0,0 +1,128 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function() {
var mode = CodeMirror.getMode({indentUnit: 2}, "text/x-dockerfile");
function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }
MT("simple_nodejs_dockerfile",
"[keyword FROM] node:carbon",
"[comment # Create app directory]",
"[keyword WORKDIR] /usr/src/app",
"[comment # Install app dependencies]",
"[comment # A wildcard is used to ensure both package.json AND package-lock.json are copied]",
"[comment # where available (npm@5+)]",
"[keyword COPY] package*.json ./",
"[keyword RUN] npm install",
"[keyword COPY] . .",
"[keyword EXPOSE] [number 8080] [number 3000]",
"[keyword ENV] NODE_ENV development",
"[keyword CMD] [[ [string \"npm\"], [string \"start\"] ]]");
// Ideally the last space should not be highlighted.
MT("instruction_without_args_1",
"[keyword CMD] ");
MT("instruction_without_args_2",
"[comment # An instruction without args...]",
"[keyword ARG] [error #...is an error]");
MT("multiline",
"[keyword RUN] apt-get update && apt-get install -y \\",
" mercurial \\",
" subversion \\",
" && apt-get clean \\",
" && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*");
MT("from_comment",
" [keyword FROM] debian:stretch # I tend to use stable as that is more stable",
" [keyword FROM] debian:stretch [keyword AS] stable # I am even more stable",
" [keyword FROM] [error # this is an error]");
MT("from_as",
"[keyword FROM] golang:1.9.2-alpine3.6 [keyword AS] build",
"[keyword COPY] --from=build /bin/project /bin/project",
"[keyword ENTRYPOINT] [[ [string \"/bin/project\"] ]]",
"[keyword CMD] [[ [string \"--help\"] ]]");
MT("arg",
"[keyword ARG] VERSION=latest",
"[keyword FROM] busybox:$VERSION",
"[keyword ARG] VERSION",
"[keyword RUN] echo $VERSION > image_version");
MT("label",
"[keyword LABEL] com.example.label-with-value=[string \"foo\"]");
MT("label_multiline",
"[keyword LABEL] description=[string \"This text illustrates ]\\",
"[string that label-values can span multiple lines.\"]");
MT("maintainer",
"[keyword MAINTAINER] Foo Bar [string \"foo@bar.com\"] ",
"[keyword MAINTAINER] Bar Baz <bar@baz.com>");
MT("env",
"[keyword ENV] BUNDLE_PATH=[string \"$GEM_HOME\"] \\",
" BUNDLE_APP_CONFIG=[string \"$GEM_HOME\"]");
MT("verify_keyword",
"[keyword RUN] add-apt-repository ppa:chris-lea/node.js");
MT("scripts",
"[comment # Set an entrypoint, to automatically install node modules]",
"[keyword ENTRYPOINT] [[ [string \"/bin/bash\"], [string \"-c\"], [string \"if [[ ! -d node_modules ]]; then npm install; fi; exec \\\"${@:0}\\\";\"] ]]",
"[keyword CMD] npm start",
"[keyword RUN] npm run build && \\",
"[comment # a comment between the shell commands]",
" npm run test");
MT("strings_single",
"[keyword FROM] buildpack-deps:stretch",
"[keyword RUN] { \\",
" echo [string 'install: --no-document']; \\",
" echo [string 'update: --no-document']; \\",
" } >> /usr/local/etc/gemrc");
MT("strings_single_multiline",
"[keyword RUN] set -ex \\",
" \\",
" && buildDeps=[string ' ]\\",
"[string bison ]\\",
"[string dpkg-dev ]\\",
"[string libgdbm-dev ]\\",
"[string ruby ]\\",
"[string '] \\",
" && apt-get update");
MT("strings_single_multiline_2",
"[keyword RUN] echo [string 'say \\' ]\\",
"[string it works'] ");
MT("strings_double",
"[keyword RUN] apt-get install -y --no-install-recommends $buildDeps \\",
" \\",
" && wget -O ruby.tar.xz [string \"https://cache.ruby-lang.org/pub/ruby/${RUBY_MAJOR%-rc}/ruby-$RUBY_VERSION.tar.xz\"] \\",
" && echo [string \"$RUBY_DOWNLOAD_SHA256 *ruby.tar.xz\"] | sha256sum -c - ");
MT("strings_double_multiline",
"[keyword RUN] echo [string \"say \\\" ]\\",
"[string it works\"] ");
MT("escape",
"[comment # escape=`]",
"[keyword FROM] microsoft/windowsservercore",
"[keyword RUN] powershell.exe -Command `",
" $ErrorActionPreference = [string 'Stop']; `",
" wget https://www.python.org/ftp/python/3.5.1/python-3.5.1.exe -OutFile c:\python-3.5.1.exe ; `",
" Start-Process c:\python-3.5.1.exe -ArgumentList [string '/quiet InstallAllUsers=1 PrependPath=1'] -Wait ; `",
" Remove-Item c:\python-3.5.1.exe -Force)");
MT("escape_strings",
"[comment # escape=`]",
"[keyword FROM] python:3.6-windowsservercore [keyword AS] python",
"[keyword RUN] $env:PATH = [string 'C:\\Python;C:\\Python\\Scripts;{0}'] -f $env:PATH ; `",
// It should not consider \' as escaped.
// " Set-ItemProperty -Path [string 'HKLM:\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment\\'] -Name Path -Value $env:PATH ;");
" Set-ItemProperty -Path [string 'HKLM:\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment\\' -Name Path -Value $env:PATH ;]");
})();

View file

@ -46,7 +46,11 @@
comment: [
{ regex: /\}\}/, pop: true, token: "comment" },
{ regex: /./, token: "comment" }
]
],
meta: {
blockCommentStart: "{{--",
blockCommentEnd: "--}}"
}
});
CodeMirror.defineMode("handlebars", function(config, parserConfig) {

View file

@ -197,13 +197,14 @@ CodeMirror.defineMode("haskell", function(_config, modeConfig) {
"\.\.", ":", "::", "=", "\\", "<-", "->", "@", "~", "=>");
setType("builtin")(
"!!", "$!", "$", "&&", "+", "++", "-", ".", "/", "/=", "<", "<=", "=<<",
"==", ">", ">=", ">>", ">>=", "^", "^^", "||", "*", "**");
"!!", "$!", "$", "&&", "+", "++", "-", ".", "/", "/=", "<", "<*", "<=",
"<$>", "<*>", "=<<", "==", ">", ">=", ">>", ">>=", "^", "^^", "||", "*",
"*>", "**");
setType("builtin")(
"Bool", "Bounded", "Char", "Double", "EQ", "Either", "Enum", "Eq",
"False", "FilePath", "Float", "Floating", "Fractional", "Functor", "GT",
"IO", "IOError", "Int", "Integer", "Integral", "Just", "LT", "Left",
"Applicative", "Bool", "Bounded", "Char", "Double", "EQ", "Either", "Enum",
"Eq", "False", "FilePath", "Float", "Floating", "Fractional", "Functor",
"GT", "IO", "IOError", "Int", "Integer", "Integral", "Just", "LT", "Left",
"Maybe", "Monad", "Nothing", "Num", "Ord", "Ordering", "Rational", "Read",
"ReadS", "Real", "RealFloat", "RealFrac", "Right", "Show", "ShowS",
"String", "True");
@ -223,7 +224,7 @@ CodeMirror.defineMode("haskell", function(_config, modeConfig) {
"lcm", "length", "lex", "lines", "log", "logBase", "lookup", "map",
"mapM", "mapM_", "max", "maxBound", "maximum", "maybe", "min", "minBound",
"minimum", "mod", "negate", "not", "notElem", "null", "odd", "or",
"otherwise", "pi", "pred", "print", "product", "properFraction",
"otherwise", "pi", "pred", "print", "product", "properFraction", "pure",
"putChar", "putStr", "putStrLn", "quot", "quotRem", "read", "readFile",
"readIO", "readList", "readLn", "readParen", "reads", "readsPrec",
"realToFrac", "recip", "rem", "repeat", "replicate", "return", "reverse",

View file

@ -80,7 +80,7 @@ option.</p>
<li><a href="javascript/index.html">JavaScript</a> (<a href="jsx/index.html">JSX</a>)</li>
<li><a href="jinja2/index.html">Jinja2</a></li>
<li><a href="julia/index.html">Julia</a></li>
<li><a href="kotlin/index.html">Kotlin</a></li>
<li><a href="clike/index.html">Kotlin</a></li>
<li><a href="css/less.html">LESS</a></li>
<li><a href="livescript/index.html">LiveScript</a></li>
<li><a href="lua/index.html">Lua</a></li>

View file

@ -75,17 +75,10 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
return ret(ch);
} else if (ch == "=" && stream.eat(">")) {
return ret("=>", "operator");
} else if (ch == "0" && stream.eat(/x/i)) {
stream.eatWhile(/[\da-f]/i);
return ret("number", "number");
} else if (ch == "0" && stream.eat(/o/i)) {
stream.eatWhile(/[0-7]/i);
return ret("number", "number");
} else if (ch == "0" && stream.eat(/b/i)) {
stream.eatWhile(/[01]/i);
} else if (ch == "0" && stream.match(/^(?:x[\da-f]+|o[0-7]+|b[01]+)n?/i)) {
return ret("number", "number");
} else if (/\d/.test(ch)) {
stream.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/);
stream.match(/^\d*(?:n|(?:\.\d*)?(?:[eE][+\-]?\d+)?)?/);
return ret("number", "number");
} else if (ch == "/") {
if (stream.eat("*")) {
@ -96,7 +89,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
return ret("comment", "comment");
} else if (expressionAllowed(stream, state, 1)) {
readRegexp(stream);
stream.match(/^\b(([gimyu])(?![gimyu]*\2))+\b/);
stream.match(/^\b(([gimyus])(?![gimyus]*\2))+\b/);
return ret("regexp", "string-2");
} else {
stream.eat("=");
@ -126,7 +119,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
var kw = keywords[word]
return ret(kw.type, kw.style, word)
}
if (word == "async" && stream.match(/^(\s|\/\*.*?\*\/)*[\(\w]/, false))
if (word == "async" && stream.match(/^(\s|\/\*.*?\*\/)*[\[\(\w]/, false))
return ret("async", "keyword", word)
}
return ret("variable", "variable", word)
@ -265,21 +258,42 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
pass.apply(null, arguments);
return true;
}
function inList(name, list) {
for (var v = list; v; v = v.next) if (v.name == name) return true
return false;
}
function register(varname) {
function inList(list) {
for (var v = list; v; v = v.next)
if (v.name == varname) return true;
return false;
}
var state = cx.state;
cx.marked = "def";
if (state.context) {
if (inList(state.localVars)) return;
state.localVars = {name: varname, next: state.localVars};
if (state.lexical.info == "var" && state.context && state.context.block) {
// FIXME function decls are also not block scoped
var newContext = registerVarScoped(varname, state.context)
if (newContext != null) {
state.context = newContext
return
}
} else if (!inList(varname, state.localVars)) {
state.localVars = new Var(varname, state.localVars)
return
}
}
// Fall through means this is global
if (parserConfig.globalVars && !inList(varname, state.globalVars))
state.globalVars = new Var(varname, state.globalVars)
}
function registerVarScoped(varname, context) {
if (!context) {
return null
} else if (context.block) {
var inner = registerVarScoped(varname, context.prev)
if (!inner) return null
if (inner == context.prev) return context
return new Context(inner, context.vars, true)
} else if (inList(varname, context.vars)) {
return context
} else {
if (inList(state.globalVars)) return;
if (parserConfig.globalVars)
state.globalVars = {name: varname, next: state.globalVars};
return new Context(context.prev, new Var(varname, context.vars), false)
}
}
@ -289,15 +303,23 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
// Combinators
var defaultVars = {name: "this", next: {name: "arguments"}};
function Context(prev, vars, block) { this.prev = prev; this.vars = vars; this.block = block }
function Var(name, next) { this.name = name; this.next = next }
var defaultVars = new Var("this", new Var("arguments", null))
function pushcontext() {
cx.state.context = {prev: cx.state.context, vars: cx.state.localVars};
cx.state.localVars = defaultVars;
cx.state.context = new Context(cx.state.context, cx.state.localVars, false)
cx.state.localVars = defaultVars
}
function pushblockcontext() {
cx.state.context = new Context(cx.state.context, cx.state.localVars, true)
cx.state.localVars = null
}
function popcontext() {
cx.state.localVars = cx.state.context.vars;
cx.state.context = cx.state.context.prev;
cx.state.localVars = cx.state.context.vars
cx.state.context = cx.state.context.prev
}
popcontext.lex = true
function pushlex(type, info) {
var result = function() {
var state = cx.state, indent = state.indented;
@ -322,19 +344,19 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
function expect(wanted) {
function exp(type) {
if (type == wanted) return cont();
else if (wanted == ";") return pass();
else if (wanted == ";" || type == "}" || type == ")" || type == "]") return pass();
else return cont(exp);
};
return exp;
}
function statement(type, value) {
if (type == "var") return cont(pushlex("vardef", value.length), vardef, expect(";"), poplex);
if (type == "var") return cont(pushlex("vardef", value), vardef, expect(";"), poplex);
if (type == "keyword a") return cont(pushlex("form"), parenExpr, statement, poplex);
if (type == "keyword b") return cont(pushlex("form"), statement, poplex);
if (type == "keyword d") return cx.stream.match(/^\s*$/, false) ? cont() : cont(pushlex("stat"), maybeexpression, expect(";"), poplex);
if (type == "debugger") return cont(expect(";"));
if (type == "{") return cont(pushlex("}"), block, poplex);
if (type == "{") return cont(pushlex("}"), pushblockcontext, block, poplex, popcontext);
if (type == ";") return cont();
if (type == "if") {
if (cx.state.lexical.info == "else" && cx.state.cc[cx.state.cc.length - 1] == poplex)
@ -345,34 +367,38 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
if (type == "for") return cont(pushlex("form"), forspec, statement, poplex);
if (type == "class" || (isTS && value == "interface")) { cx.marked = "keyword"; return cont(pushlex("form"), className, poplex); }
if (type == "variable") {
if (isTS && value == "type") {
cx.marked = "keyword"
return cont(typeexpr, expect("operator"), typeexpr, expect(";"));
} else if (isTS && value == "declare") {
if (isTS && value == "declare") {
cx.marked = "keyword"
return cont(statement)
} else if (isTS && (value == "module" || value == "enum") && cx.stream.match(/^\s*\w/, false)) {
} else if (isTS && (value == "module" || value == "enum" || value == "type") && cx.stream.match(/^\s*\w/, false)) {
cx.marked = "keyword"
return cont(pushlex("form"), pattern, expect("{"), pushlex("}"), block, poplex, poplex)
if (value == "enum") return cont(enumdef);
else if (value == "type") return cont(typeexpr, expect("operator"), typeexpr, expect(";"));
else return cont(pushlex("form"), pattern, expect("{"), pushlex("}"), block, poplex, poplex)
} else if (isTS && value == "namespace") {
cx.marked = "keyword"
return cont(pushlex("form"), expression, block, poplex)
} else if (isTS && value == "abstract") {
cx.marked = "keyword"
return cont(statement)
} else {
return cont(pushlex("stat"), maybelabel);
}
}
if (type == "switch") return cont(pushlex("form"), parenExpr, expect("{"), pushlex("}", "switch"),
block, poplex, poplex);
if (type == "switch") return cont(pushlex("form"), parenExpr, expect("{"), pushlex("}", "switch"), pushblockcontext,
block, poplex, poplex, popcontext);
if (type == "case") return cont(expression, expect(":"));
if (type == "default") return cont(expect(":"));
if (type == "catch") return cont(pushlex("form"), pushcontext, expect("("), funarg, expect(")"),
statement, poplex, popcontext);
if (type == "catch") return cont(pushlex("form"), pushcontext, maybeCatchBinding, statement, poplex, popcontext);
if (type == "export") return cont(pushlex("stat"), afterExport, poplex);
if (type == "import") return cont(pushlex("stat"), afterImport, poplex);
if (type == "async") return cont(statement)
if (value == "@") return cont(expression, statement)
return pass(pushlex("stat"), expression, expect(";"), poplex);
}
function maybeCatchBinding(type) {
if (type == "(") return cont(funarg, expect(")"))
}
function expression(type, value) {
return expressionInner(type, value, false);
}
@ -401,6 +427,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
if (type == "{") return contCommasep(objprop, "}", null, maybeop);
if (type == "quasi") return pass(quasi, maybeop);
if (type == "new") return cont(maybeTarget(noComma));
if (type == "import") return cont(expression);
return cont();
}
function maybeexpression(type) {
@ -560,19 +587,19 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
}
}
function typeexpr(type, value) {
if (value == "keyof" || value == "typeof") {
cx.marked = "keyword"
return cont(value == "keyof" ? typeexpr : expressionNoComma)
}
if (type == "variable" || value == "void") {
if (value == "keyof") {
cx.marked = "keyword"
return cont(typeexpr)
} else {
cx.marked = "type"
return cont(afterType)
}
cx.marked = "type"
return cont(afterType)
}
if (type == "string" || type == "number" || type == "atom") return cont(afterType);
if (type == "[") return cont(pushlex("]"), commasep(typeexpr, "]", ","), poplex, afterType)
if (type == "{") return cont(pushlex("}"), commasep(typeprop, "}", ",;"), poplex, afterType)
if (type == "(") return cont(commasep(typearg, ")"), maybeReturnType)
if (type == "<") return cont(commasep(typeexpr, ">"), typeexpr)
}
function maybeReturnType(type) {
if (type == "=>") return cont(typeexpr)
@ -589,13 +616,14 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
return cont(expression, maybetype, expect("]"), typeprop)
}
}
function typearg(type) {
if (type == "variable") return cont(typearg)
else if (type == ":") return cont(typeexpr)
function typearg(type, value) {
if (type == "variable" && cx.stream.match(/^\s*[?:]/, false) || value == "?") return cont(typearg)
if (type == ":") return cont(typeexpr)
return pass(typeexpr)
}
function afterType(type, value) {
if (value == "<") return cont(pushlex(">"), commasep(typeexpr, ">"), poplex, afterType)
if (value == "|" || type == ".") return cont(typeexpr)
if (value == "|" || type == "." || value == "&") return cont(typeexpr)
if (type == "[") return cont(expect("]"), afterType)
if (value == "extends" || value == "implements") { cx.marked = "keyword"; return cont(typeexpr) }
}
@ -608,7 +636,8 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
function maybeTypeDefault(_, value) {
if (value == "=") return cont(typeexpr)
}
function vardef() {
function vardef(_, value) {
if (value == "enum") {cx.marked = "keyword"; return cont(enumdef)}
return pass(pattern, maybetype, maybeAssign, vardefCont);
}
function pattern(type, value) {
@ -637,7 +666,8 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
function maybeelse(type, value) {
if (type == "keyword b" && value == "else") return cont(pushlex("form", "else"), statement, poplex);
}
function forspec(type) {
function forspec(type, value) {
if (value == "await") return cont(forspec);
if (type == "(") return cont(pushlex(")"), forspec1, expect(")"), poplex);
}
function forspec1(type) {
@ -680,8 +710,10 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
}
function classNameAfter(type, value) {
if (value == "<") return cont(pushlex(">"), commasep(typeparam, ">"), poplex, classNameAfter)
if (value == "extends" || value == "implements" || (isTS && type == ","))
if (value == "extends" || value == "implements" || (isTS && type == ",")) {
if (value == "implements") cx.marked = "keyword";
return cont(isTS ? typeexpr : expression, classNameAfter);
}
if (type == "{") return cont(pushlex("}"), classBody, poplex);
}
function classBody(type, value) {
@ -724,6 +756,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
}
function afterImport(type) {
if (type == "string") return cont();
if (type == "(") return pass(expression);
return pass(importSpec, maybeMoreImports, maybeFrom);
}
function importSpec(type, value) {
@ -745,6 +778,12 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
if (type == "]") return cont();
return pass(commasep(expressionNoComma, "]"));
}
function enumdef() {
return pass(pushlex("form"), pattern, expect("{"), pushlex("}"), commasep(enummember, "}"), poplex, poplex)
}
function enummember() {
return pass(pattern, maybeAssign);
}
function isContinuedStatement(state, textAfter) {
return state.lastType == "operator" || state.lastType == "," ||
@ -768,7 +807,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
cc: [],
lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false),
localVars: parserConfig.localVars,
context: parserConfig.localVars && {vars: parserConfig.localVars},
context: parserConfig.localVars && new Context(null, null, false),
indented: basecolumn || 0
};
if (parserConfig.globalVars && typeof parserConfig.globalVars == "object")
@ -809,7 +848,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
lexical = lexical.prev;
var type = lexical.type, closing = firstChar == type;
if (type == "vardef") return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? lexical.info + 1 : 0);
if (type == "vardef") return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? lexical.info.length + 1 : 0);
else if (type == "form" && firstChar == "{") return lexical.indented;
else if (type == "form") return lexical.indented + indentUnit;
else if (type == "stat")

View file

@ -63,6 +63,12 @@
MT("import_trailing_comma",
"[keyword import] {[def foo], [def bar],} [keyword from] [string 'baz']")
MT("import_dynamic",
"[keyword import]([string 'baz']).[property then]")
MT("import_dynamic",
"[keyword const] [def t] [operator =] [keyword import]([string 'baz']).[property then]")
MT("const",
"[keyword function] [def f]() {",
" [keyword const] [[ [def a], [def b] ]] [operator =] [[ [number 1], [number 2] ]];",
@ -71,12 +77,44 @@
MT("for/of",
"[keyword for]([keyword let] [def of] [keyword of] [variable something]) {}");
MT("for await",
"[keyword for] [keyword await]([keyword let] [def of] [keyword of] [variable something]) {}");
MT("generator",
"[keyword function*] [def repeat]([def n]) {",
" [keyword for]([keyword var] [def i] [operator =] [number 0]; [variable-2 i] [operator <] [variable-2 n]; [operator ++][variable-2 i])",
" [keyword yield] [variable-2 i];",
"}");
MT("let_scoping",
"[keyword function] [def scoped]([def n]) {",
" { [keyword var] [def i]; } [variable-2 i];",
" { [keyword let] [def j]; [variable-2 j]; } [variable j];",
" [keyword if] ([atom true]) { [keyword const] [def k]; [variable-2 k]; } [variable k];",
"}");
MT("switch_scoping",
"[keyword switch] ([variable x]) {",
" [keyword default]:",
" [keyword let] [def j];",
" [keyword return] [variable-2 j]",
"}",
"[variable j];")
MT("leaving_scope",
"[keyword function] [def a]() {",
" {",
" [keyword const] [def x] [operator =] [number 1]",
" [keyword if] ([atom true]) {",
" [keyword let] [def y] [operator =] [number 2]",
" [keyword var] [def z] [operator =] [number 3]",
" [variable console].[property log]([variable-2 x], [variable-2 y], [variable-2 z])",
" }",
" [variable console].[property log]([variable-2 x], [variable y], [variable-2 z])",
" }",
" [variable console].[property log]([variable x], [variable y], [variable-2 z])",
"}")
MT("quotedStringAddition",
"[keyword let] [def f] [operator =] [variable a] [operator +] [string 'fatarrow'] [operator +] [variable c];");
@ -230,6 +268,8 @@
"[keyword const] [def async] [operator =] {[property a]: [number 1]};",
"[keyword const] [def foo] [operator =] [string-2 `bar ${][variable async].[property a][string-2 }`];")
MT("bigint", "[number 1n] [operator +] [number 0x1afn] [operator +] [number 0o064n] [operator +] [number 0b100n];")
MT("async_comment",
"[keyword async] [comment /**/] [keyword function] [def foo]([def args]) { [keyword return] [atom true]; }");
@ -383,6 +423,25 @@
" }",
"}")
TS("type as variable",
"[variable type] [operator =] [variable x] [keyword as] [type Bar];");
TS("enum body",
"[keyword export] [keyword const] [keyword enum] [def CodeInspectionResultType] {",
" [def ERROR] [operator =] [string 'problem_type_error'],",
" [def WARNING] [operator =] [string 'problem_type_warning'],",
" [def META],",
"}")
TS("parenthesized type",
"[keyword class] [def Foo] {",
" [property x] [operator =] [keyword new] [variable A][operator <][type B], [type string][operator |](() [operator =>] [type void])[operator >]();",
" [keyword private] [property bar]();",
"}")
TS("abstract class",
"[keyword export] [keyword abstract] [keyword class] [def Foo] {}")
var jsonld_mode = CodeMirror.getMode(
{indentUnit: 2},
{name: "javascript", jsonld: true}

View file

@ -54,11 +54,13 @@ CodeMirror.defineMode("julia", function(config, parserConf) {
return inGenerator(state, '[')
}
function inGenerator(state, bracket) {
var curr = currentScope(state),
prev = currentScope(state, 1);
function inGenerator(state, bracket, depth) {
if (typeof(bracket) === "undefined") { bracket = '('; }
if (curr === bracket || (prev === bracket && curr === "for")) {
if (typeof(depth) === "undefined") { depth = 0; }
var scope = currentScope(state, depth);
if ((depth == 0 && scope === "if" && inGenerator(state, bracket, depth + 1)) ||
(scope === "for" && inGenerator(state, bracket, depth + 1)) ||
(scope === bracket)) {
return true;
}
return false;
@ -119,16 +121,16 @@ CodeMirror.defineMode("julia", function(config, parserConf) {
state.scopes.push('(');
}
var scope = currentScope(state);
if (inArray(state) && ch === ']') {
if (scope === "for") { state.scopes.pop(); }
if (currentScope(state) === "if") { state.scopes.pop(); }
while (currentScope(state) === "for") { state.scopes.pop(); }
state.scopes.pop();
state.leavingExpr = true;
}
if (inGenerator(state) && ch === ')') {
if (scope === "for") { state.scopes.pop(); }
if (currentScope(state) === "if") { state.scopes.pop(); }
while (currentScope(state) === "for") { state.scopes.pop(); }
state.scopes.pop();
state.leavingExpr = true;
}
@ -143,12 +145,14 @@ CodeMirror.defineMode("julia", function(config, parserConf) {
}
var match;
if (match = stream.match(openers, false)) {
if (match = stream.match(openers)) {
state.scopes.push(match[0]);
return "keyword";
}
if (stream.match(closers, false)) {
if (stream.match(closers)) {
state.scopes.pop();
return "keyword";
}
// Handle type annotations

View file

@ -90,7 +90,7 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
, setextHeaderRE = /^ *(?:\={1,}|-{1,})\s*$/
, textRE = /^[^#!\[\]*_\\<>` "'(~:]+/
, fencedCodeRE = /^(~~~+|```+)[ \t]*([\w+#-]*)[^\n`]*$/
, linkDefRE = /^\s*\[[^\]]+?\]:\s*\S+(\s*\S*\s*)?$/ // naive link-definition
, linkDefRE = /^\s*\[[^\]]+?\]:.*$/ // naive link-definition
, punctuation = /[!\"#$%&\'()*+,\-\.\/:;<=>?@\[\\\]^_`{|}~—]/
, expandedTab = " " // CommonMark specifies tab as 4 spaces
@ -113,6 +113,8 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
function blankLine(state) {
// Reset linkTitle state
state.linkTitle = false;
state.linkHref = false;
state.linkText = false;
// Reset EM state
state.em = false;
// Reset STRONG state
@ -124,8 +126,17 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
// Reset state.indentedCode
state.indentedCode = false;
if (state.f == htmlBlock) {
state.f = inlineNormal;
state.block = blockNormal;
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;
@ -151,6 +162,12 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
if (state.indentationDiff === null) {
state.indentationDiff = state.indentation;
if (prevLineIsList) {
// Reset inline styles which shouldn't propagate aross list items
state.em = false;
state.strong = false;
state.code = false;
state.strikethrough = false;
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
@ -489,6 +506,7 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
}
if (ch === '[' && !state.image) {
if (state.linkText && stream.match(/^.*?\]/)) return getType(state)
state.linkText = true;
if (modeCfg.highlightFormatting) state.formatting = "link";
return getType(state);
@ -526,7 +544,7 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
return type + tokenTypes.linkEmail;
}
if (modeCfg.xml && ch === '<' && stream.match(/^(!--|[a-z]+(?:\s+[a-z_:.\-]+(?:\s*=\s*[^ >]+)?)*\s*>)/i, false)) {
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);
@ -611,7 +629,7 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
}
if (ch === ' ') {
if (stream.match(/ +$/, false)) {
if (stream.match(/^ +$/, false)) {
state.trailingSpace++;
} else if (state.trailingSpace) {
state.trailingSpaceNewLine = true;
@ -777,6 +795,7 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
formatting: false,
linkText: s.linkText,
linkTitle: s.linkTitle,
linkHref: s.linkHref,
code: s.code,
em: s.em,
strong: s.strong,
@ -856,6 +875,8 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
return mode;
}, "xml");
CodeMirror.defineMIME("text/markdown", "markdown");
CodeMirror.defineMIME("text/x-markdown", "markdown");
});

View file

@ -1283,6 +1283,25 @@
"[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>");

View file

@ -71,12 +71,12 @@ CodeMirror.defineMode('mathematica', function(_config, _parserConfig) {
}
// usage
if (stream.match(/([a-zA-Z\$]+(?:`?[a-zA-Z0-9\$])*::usage)/, true, false)) {
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-Z\$][a-zA-Z0-9\$]*):?/, true, false)) {
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';
}

View file

@ -17,7 +17,7 @@
{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"]},
{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"]},
@ -64,13 +64,13 @@
{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"], alias: ["xhtml"]},
{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/javascript;env=frontend", "application/javascript;env=backend", "application/x-javascript", "application/ecmascript"],
{name: "JavaScript", mimes: ["text/javascript", "text/ecmascript", "application/javascript", "application/x-javascript", "application/ecmascript", "application/javascript;env=frontend", "application/javascript;env=backend"],
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"]},
@ -101,7 +101,7 @@
{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", mime: ["application/x-httpd-php", "text/x-php"], mode: "php", ext: ["php", "php3", "php4", "php5", "php7", "phtml"]},
{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"]},
@ -128,6 +128,7 @@
{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"]},
@ -137,7 +138,7 @@
{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"], alias: ["tex"]},
{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"]},

View file

@ -13,31 +13,26 @@
CodeMirror.defineMode('mllike', function(_config, parserConfig) {
var words = {
'let': 'keyword',
'rec': 'keyword',
'in': 'keyword',
'of': 'keyword',
'and': 'keyword',
'if': 'keyword',
'then': 'keyword',
'else': 'keyword',
'for': 'keyword',
'to': 'keyword',
'while': 'keyword',
'as': 'keyword',
'do': 'keyword',
'done': 'keyword',
'else': 'keyword',
'end': 'keyword',
'exception': 'keyword',
'fun': 'keyword',
'function': 'keyword',
'val': 'keyword',
'functor': 'keyword',
'if': 'keyword',
'in': 'keyword',
'include': 'keyword',
'let': 'keyword',
'of': 'keyword',
'open': 'keyword',
'rec': 'keyword',
'struct': 'keyword',
'then': 'keyword',
'type': 'keyword',
'mutable': 'keyword',
'match': 'keyword',
'with': 'keyword',
'try': 'keyword',
'open': 'builtin',
'ignore': 'builtin',
'begin': 'keyword',
'end': 'keyword'
'val': 'keyword',
'while': 'keyword',
'with': 'keyword'
};
var extraWords = parserConfig.extraWords || {};
@ -68,7 +63,7 @@ CodeMirror.defineMode('mllike', function(_config, parserConfig) {
return state.tokenize(stream, state);
}
}
if (ch === '~') {
if (ch === '~' || ch === '?') {
stream.eatWhile(/\w/);
return 'variable-2';
}
@ -98,7 +93,7 @@ CodeMirror.defineMode('mllike', function(_config, parserConfig) {
}
return 'number';
}
if ( /[+\-*&%=<>!?|@]/.test(ch)) {
if ( /[+\-*&%=<>!?|@\.~:]/.test(ch)) {
return 'operator';
}
if (/[\w\xa1-\uffff]/.test(ch)) {
@ -165,16 +160,64 @@ CodeMirror.defineMode('mllike', function(_config, parserConfig) {
CodeMirror.defineMIME('text/x-ocaml', {
name: 'mllike',
extraWords: {
'succ': 'keyword',
'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',
'true': 'atom',
'false': 'atom',
'raise': 'keyword',
'module': 'keyword',
'sig': 'keyword'
'int': 'type',
'float': 'type',
'bool': 'type',
'char': 'type',
'string': 'type',
'unit': 'type',
// Modules
'List': 'builtin'
}
});
@ -182,18 +225,21 @@ CodeMirror.defineMIME('text/x-fsharp', {
name: 'mllike',
extraWords: {
'abstract': 'keyword',
'as': 'keyword',
'assert': 'keyword',
'base': 'keyword',
'begin': 'keyword',
'class': 'keyword',
'default': 'keyword',
'delegate': 'keyword',
'do!': 'keyword',
'done': 'keyword',
'downcast': 'keyword',
'downto': 'keyword',
'elif': 'keyword',
'exception': 'keyword',
'extern': 'keyword',
'finally': 'keyword',
'for': 'keyword',
'function': 'keyword',
'global': 'keyword',
'inherit': 'keyword',
'inline': 'keyword',
@ -201,38 +247,108 @@ CodeMirror.defineMIME('text/x-fsharp', {
'internal': 'keyword',
'lazy': 'keyword',
'let!': 'keyword',
'member' : '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',
'return': 'keyword',
'select': 'keyword',
'static': 'keyword',
'struct': 'keyword',
'to': 'keyword',
'try': 'keyword',
'upcast': 'keyword',
'use': 'keyword',
'use!': 'keyword',
'val': 'keyword',
'use': 'keyword',
'void': 'keyword',
'when': 'keyword',
'yield': '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',
'raise': 'builtin',
'failwith': 'builtin',
'not': 'builtin',
'true': 'builtin',
'false': '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
});

View file

@ -1,4 +1,4 @@
<!doctype html>
<!doctype html>
<head>
<title>CodeMirror: NGINX mode</title>
<meta charset="utf-8"/>
@ -176,6 +176,6 @@ server {
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {});
</script>
<p><strong>MIME types defined:</strong> <code>text/nginx</code>.</p>
<p><strong>MIME types defined:</strong> <code>text/x-nginx-conf</code>.</p>
</article>

View file

@ -24,14 +24,14 @@ CodeMirror.defineSimpleMode("nsis",{
{ regex: /`(?:[^\\`]|\\.)*`?/, token: "string" },
// Compile Time Commands
{regex: /^\s*(?:\!(include|addincludedir|addplugindir|appendfile|cd|delfile|echo|error|execute|packhdr|pragma|finalize|getdllversion|system|tempfile|warning|verbose|define|undef|insertmacro|makensis|searchparse|searchreplace))\b/, token: "keyword"},
{regex: /^\s*(?:\!(include|addincludedir|addplugindir|appendfile|cd|delfile|echo|error|execute|packhdr|pragma|finalize|getdllversion|gettlbversion|system|tempfile|warning|verbose|define|undef|insertmacro|macro|macroend|makensis|searchparse|searchreplace))\b/, token: "keyword"},
// Conditional Compilation
{regex: /^\s*(?:\!(if(?:n?def)?|ifmacron?def|macro))\b/, token: "keyword", indent: true},
{regex: /^\s*(?:\!(else|endif|macroend))\b/, token: "keyword", dedent: true},
// Runtime Commands
{regex: /^\s*(?:Abort|AddBrandingImage|AddSize|AllowRootDirInstall|AllowSkipFiles|AutoCloseWindow|BGFont|BGGradient|BrandingText|BringToFront|Call|CallInstDLL|Caption|ChangeUI|CheckBitmap|ClearErrors|CompletedText|ComponentText|CopyFiles|CRCCheck|CreateDirectory|CreateFont|CreateShortCut|Delete|DeleteINISec|DeleteINIStr|DeleteRegKey|DeleteRegValue|DetailPrint|DetailsButtonText|DirText|DirVar|DirVerify|EnableWindow|EnumRegKey|EnumRegValue|Exch|Exec|ExecShell|ExecShellWait|ExecWait|ExpandEnvStrings|File|FileBufSize|FileClose|FileErrorText|FileOpen|FileRead|FileReadByte|FileReadUTF16LE|FileReadWord|FileWriteUTF16LE|FileSeek|FileWrite|FileWriteByte|FileWriteWord|FindClose|FindFirst|FindNext|FindWindow|FlushINI|GetCurInstType|GetCurrentAddress|GetDlgItem|GetDLLVersion|GetDLLVersionLocal|GetErrorLevel|GetFileTime|GetFileTimeLocal|GetFullPathName|GetFunctionAddress|GetInstDirError|GetLabelAddress|GetTempFileName|Goto|HideWindow|Icon|IfAbort|IfErrors|IfFileExists|IfRebootFlag|IfSilent|InitPluginsDir|InstallButtonText|InstallColors|InstallDir|InstallDirRegKey|InstProgressFlags|InstType|InstTypeGetText|InstTypeSetText|IntCmp|IntCmpU|IntFmt|IntOp|IsWindow|LangString|LicenseBkColor|LicenseData|LicenseForceSelection|LicenseLangString|LicenseText|LoadLanguageFile|LockWindow|LogSet|LogText|ManifestDPIAware|ManifestSupportedOS|MessageBox|MiscButtonText|Name|Nop|OutFile|Page|PageCallbacks|Pop|Push|Quit|ReadEnvStr|ReadINIStr|ReadRegDWORD|ReadRegStr|Reboot|RegDLL|Rename|RequestExecutionLevel|ReserveFile|Return|RMDir|SearchPath|SectionGetFlags|SectionGetInstTypes|SectionGetSize|SectionGetText|SectionIn|SectionSetFlags|SectionSetInstTypes|SectionSetSize|SectionSetText|SendMessage|SetAutoClose|SetBrandingImage|SetCompress|SetCompressor|SetCompressorDictSize|SetCtlColors|SetCurInstType|SetDatablockOptimize|SetDateSave|SetDetailsPrint|SetDetailsView|SetErrorLevel|SetErrors|SetFileAttributes|SetFont|SetOutPath|SetOverwrite|SetRebootFlag|SetRegView|SetShellVarContext|SetSilent|ShowInstDetails|ShowUninstDetails|ShowWindow|SilentInstall|SilentUnInstall|Sleep|SpaceTexts|StrCmp|StrCmpS|StrCpy|StrLen|SubCaption|Unicode|UninstallButtonText|UninstallCaption|UninstallIcon|UninstallSubCaption|UninstallText|UninstPage|UnRegDLL|Var|VIAddVersionKey|VIFileVersion|VIProductVersion|WindowIcon|WriteINIStr|WriteRegBin|WriteRegDWORD|WriteRegExpandStr|WriteRegMultiStr|WriteRegNone|WriteRegStr|WriteUninstaller|XPStyle)\b/, token: "keyword"},
{regex: /^\s*(?:Abort|AddBrandingImage|AddSize|AllowRootDirInstall|AllowSkipFiles|AutoCloseWindow|BGFont|BGGradient|BrandingText|BringToFront|Call|CallInstDLL|Caption|ChangeUI|CheckBitmap|ClearErrors|CompletedText|ComponentText|CopyFiles|CRCCheck|CreateDirectory|CreateFont|CreateShortCut|Delete|DeleteINISec|DeleteINIStr|DeleteRegKey|DeleteRegValue|DetailPrint|DetailsButtonText|DirText|DirVar|DirVerify|EnableWindow|EnumRegKey|EnumRegValue|Exch|Exec|ExecShell|ExecShellWait|ExecWait|ExpandEnvStrings|File|FileBufSize|FileClose|FileErrorText|FileOpen|FileRead|FileReadByte|FileReadUTF16LE|FileReadWord|FileWriteUTF16LE|FileSeek|FileWrite|FileWriteByte|FileWriteWord|FindClose|FindFirst|FindNext|FindWindow|FlushINI|GetCurInstType|GetCurrentAddress|GetDlgItem|GetDLLVersion|GetDLLVersionLocal|GetErrorLevel|GetFileTime|GetFileTimeLocal|GetFullPathName|GetFunctionAddress|GetInstDirError|GetLabelAddress|GetTempFileName|Goto|HideWindow|Icon|IfAbort|IfErrors|IfFileExists|IfRebootFlag|IfSilent|InitPluginsDir|InstallButtonText|InstallColors|InstallDir|InstallDirRegKey|InstProgressFlags|InstType|InstTypeGetText|InstTypeSetText|Int64Cmp|Int64CmpU|Int64Fmt|IntCmp|IntCmpU|IntFmt|IntOp|IntPtrCmp|IntPtrCmpU|IntPtrOp|IsWindow|LangString|LicenseBkColor|LicenseData|LicenseForceSelection|LicenseLangString|LicenseText|LoadLanguageFile|LockWindow|LogSet|LogText|ManifestDPIAware|ManifestSupportedOS|MessageBox|MiscButtonText|Name|Nop|OutFile|Page|PageCallbacks|PEDllCharacteristics|PESubsysVer|Pop|Push|Quit|ReadEnvStr|ReadINIStr|ReadRegDWORD|ReadRegStr|Reboot|RegDLL|Rename|RequestExecutionLevel|ReserveFile|Return|RMDir|SearchPath|SectionGetFlags|SectionGetInstTypes|SectionGetSize|SectionGetText|SectionIn|SectionSetFlags|SectionSetInstTypes|SectionSetSize|SectionSetText|SendMessage|SetAutoClose|SetBrandingImage|SetCompress|SetCompressor|SetCompressorDictSize|SetCtlColors|SetCurInstType|SetDatablockOptimize|SetDateSave|SetDetailsPrint|SetDetailsView|SetErrorLevel|SetErrors|SetFileAttributes|SetFont|SetOutPath|SetOverwrite|SetRebootFlag|SetRegView|SetShellVarContext|SetSilent|ShowInstDetails|ShowUninstDetails|ShowWindow|SilentInstall|SilentUnInstall|Sleep|SpaceTexts|StrCmp|StrCmpS|StrCpy|StrLen|SubCaption|Unicode|UninstallButtonText|UninstallCaption|UninstallIcon|UninstallSubCaption|UninstallText|UninstPage|UnRegDLL|Var|VIAddVersionKey|VIFileVersion|VIProductVersion|WindowIcon|WriteINIStr|WriteRegBin|WriteRegDWORD|WriteRegExpandStr|WriteRegMultiStr|WriteRegNone|WriteRegStr|WriteUninstaller|XPStyle)\b/, token: "keyword"},
{regex: /^\s*(?:Function|PageEx|Section(?:Group)?)\b/, token: "keyword", indent: true},
{regex: /^\s*(?:(Function|PageEx|Section(?:Group)?)End)\b/, token: "keyword", dedent: true},

View file

@ -17,9 +17,21 @@ CodeMirror.defineMode("pascal", function() {
for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
return obj;
}
var keywords = words("and array begin case const div do downto else end file for forward integer " +
"boolean char function goto if in label mod nil not of or packed procedure " +
"program record repeat set string then to type until var while with");
var keywords = words(
"absolute and array asm begin case const constructor destructor div do " +
"downto else end file for function goto if implementation in inherited " +
"inline interface label mod nil not object of operator or packed procedure " +
"program record reintroduce repeat self set shl shr string then to type " +
"unit until uses var while with xor as class dispinterface except exports " +
"finalization finally initialization inline is library on out packed " +
"property raise resourcestring threadvar try absolute abstract alias " +
"assembler bitpacked break cdecl continue cppdecl cvar default deprecated " +
"dynamic enumerator experimental export external far far16 forward generic " +
"helper implements index interrupt iocheck local message name near " +
"nodefault noreturn nostackframe oldfpccall otherwise overload override " +
"pascal platform private protected public published read register " +
"reintroduce result safecall saveregisters softfloat specialize static " +
"stdcall stored strict unaligned unimplemented varargs virtual write");
var atoms = {"null": true};
var isOperatorChar = /[+\-*&%=<>!?|\/]/;

View file

@ -126,6 +126,15 @@ class ExampleClass(ParentClass):
def __init__(self, mixin = 'Hello'):
self.mixin = mixin
# Python 3.6 f-strings (https://www.python.org/dev/peps/pep-0498/)
f'My name is {name}, my age next year is {age+1}, my anniversary is {anniversary:%A, %B %d, %Y}.'
f'He said his name is {name!r}.'
f"""He said his name is {name!r}."""
f'{"quoted string"}'
f'{{ {4*10} }}'
f'This is an error }'
f'This is ok }}'
fr'x={4*10}\n'
</textarea></div>

View file

@ -41,7 +41,7 @@
CodeMirror.defineMode("python", function(conf, parserConf) {
var ERRORCLASS = "error";
var delimiters = parserConf.delimiters || parserConf.singleDelimiters || /^[\(\)\[\]\{\}@,:`=;\.]/;
var delimiters = parserConf.delimiters || parserConf.singleDelimiters || /^[\(\)\[\]\{\}@,:`=;\.\\]/;
// (Backwards-compatiblity with old, cumbersome config system)
var operators = [parserConf.singleOperators, parserConf.doubleOperators, parserConf.doubleDelimiters, parserConf.tripleDelimiters,
parserConf.operators || /^([-+*/%\/&|^]=?|[<>=]+|\/\/=?|\*\*=?|!=|[~!@])/]
@ -62,7 +62,7 @@
var identifiers = parserConf.identifiers|| /^[_A-Za-z\u00A1-\uFFFF][_A-Za-z0-9\u00A1-\uFFFF]*/;
myKeywords = myKeywords.concat(["nonlocal", "False", "True", "None", "async", "await"]);
myBuiltins = myBuiltins.concat(["ascii", "bytes", "exec", "print"]);
var stringPrefixes = new RegExp("^(([rbuf]|(br))?('{3}|\"{3}|['\"]))", "i");
var stringPrefixes = new RegExp("^(([rbuf]|(br)|(fr))?('{3}|\"{3}|['\"]))", "i");
} else {
var identifiers = parserConf.identifiers|| /^[_A-Za-z][_A-Za-z0-9]*/;
myKeywords = myKeywords.concat(["exec", "print"]);
@ -76,9 +76,10 @@
// tokenizers
function tokenBase(stream, state) {
if (stream.sol()) state.indent = stream.indentation()
var sol = stream.sol() && state.lastToken != "\\"
if (sol) state.indent = stream.indentation()
// Handle scope changes
if (stream.sol() && top(state).type == "py") {
if (sol && top(state).type == "py") {
var scopeOffset = top(state).offset;
if (stream.eatSpace()) {
var lineOffset = stream.indentation();
@ -100,13 +101,8 @@
function tokenBaseInner(stream, state) {
if (stream.eatSpace()) return null;
var ch = stream.peek();
// Handle Comments
if (ch == "#") {
stream.skipToEnd();
return "comment";
}
if (stream.match(/^#.*/)) return "comment";
// Handle Number Literals
if (stream.match(/^[0-9\.]/, false)) {
@ -146,8 +142,14 @@
// Handle Strings
if (stream.match(stringPrefixes)) {
state.tokenize = tokenStringFactory(stream.current());
return state.tokenize(stream, state);
var isFmtString = stream.current().toLowerCase().indexOf('f') !== -1;
if (!isFmtString) {
state.tokenize = tokenStringFactory(stream.current());
return state.tokenize(stream, state);
} else {
state.tokenize = formatStringFactory(stream.current(), state.tokenize);
return state.tokenize(stream, state);
}
}
for (var i = 0; i < operators.length; i++)
@ -178,6 +180,77 @@
return ERRORCLASS;
}
function formatStringFactory(delimiter, tokenOuter) {
while ("rubf".indexOf(delimiter.charAt(0).toLowerCase()) >= 0)
delimiter = delimiter.substr(1);
var singleline = delimiter.length == 1;
var OUTCLASS = "string";
function tokenFString(stream, state) {
// inside f-str Expression
if (stream.match(delimiter)) {
// expression ends pre-maturally, but very common in editing
// Could show error to remind users to close brace here
state.tokenize = tokenString
return OUTCLASS;
} else if (stream.match('{')) {
// starting brace, if not eaten below
return "punctuation";
} else if (stream.match('}')) {
// return to regular inside string state
state.tokenize = tokenString
return "punctuation";
} else {
// use tokenBaseInner to parse the expression
return tokenBaseInner(stream, state);
}
}
function tokenString(stream, state) {
while (!stream.eol()) {
stream.eatWhile(/[^'"\{\}\\]/);
if (stream.eat("\\")) {
stream.next();
if (singleline && stream.eol())
return OUTCLASS;
} else if (stream.match(delimiter)) {
state.tokenize = tokenOuter;
return OUTCLASS;
} else if (stream.match('{{')) {
// ignore {{ in f-str
return OUTCLASS;
} else if (stream.match('{', false)) {
// switch to nested mode
state.tokenize = tokenFString
if (stream.current()) {
return OUTCLASS;
} else {
// need to return something, so eat the starting {
stream.next();
return "punctuation";
}
} else if (stream.match('}}')) {
return OUTCLASS;
} else if (stream.match('}')) {
// single } in f-string is an error
return ERRORCLASS;
} else {
stream.eat(/['"]/);
}
}
if (singleline) {
if (parserConf.singleLineStringErrors)
return ERRORCLASS;
else
state.tokenize = tokenOuter;
}
return OUTCLASS;
}
tokenString.isString = true;
return tokenString;
}
function tokenStringFactory(delimiter) {
while ("rubf".indexOf(delimiter.charAt(0).toLowerCase()) >= 0)
delimiter = delimiter.substr(1);
@ -258,14 +331,16 @@
if (current == ":" && !state.lambda && top(state).type == "py")
pushPyScope(state);
var delimiter_index = current.length == 1 ? "[({".indexOf(current) : -1;
if (delimiter_index != -1)
pushBracketScope(stream, state, "])}".slice(delimiter_index, delimiter_index+1));
if (current.length == 1 && !/string|comment/.test(style)) {
var delimiter_index = "[({".indexOf(current);
if (delimiter_index != -1)
pushBracketScope(stream, state, "])}".slice(delimiter_index, delimiter_index+1));
delimiter_index = "])}".indexOf(current);
if (delimiter_index != -1) {
if (top(state).type == current) state.indent = state.scopes.pop().offset - hangingIndent
else return ERRORCLASS;
delimiter_index = "])}".indexOf(current);
if (delimiter_index != -1) {
if (top(state).type == current) state.indent = state.scopes.pop().offset - hangingIndent
else return ERRORCLASS;
}
}
if (state.dedent > 0 && stream.eol() && top(state).type == "py") {
if (state.scopes.length > 1) state.scopes.pop();

View file

@ -30,6 +30,9 @@
MT("before_equal_sign_" + c, "[variable a] [operator " + c + "=] [variable b]");
}
MT("fValidStringPrefix", "[string f'this is a {formatted} string']");
MT("fValidStringPrefix", "[string f'this is a]{[variable formatted]}[string string']");
MT("fValidExpressioninFString", "[string f'expression ]{[number 100][operator *][number 5]}[string string']");
MT("fInvalidFString", "[error f'this is wrong}]");
MT("fNestedFString", "[string f'expression ]{[number 100] [operator +] [string f'inner]{[number 5]}[string ']}[string string']");
MT("uValidStringPrefix", "[string u'this is an unicode string']");
})();

View file

@ -84,29 +84,38 @@ CodeMirror.defineMode('shell', function() {
function tokenString(quote, style) {
var close = quote == "(" ? ")" : quote == "{" ? "}" : quote
return function(stream, state) {
var next, end = false, escaped = false;
var next, escaped = false;
while ((next = stream.next()) != null) {
if (next === close && !escaped) {
end = true;
state.tokens.shift();
break;
}
if (next === '$' && !escaped && quote !== "'") {
} else if (next === '$' && !escaped && quote !== "'" && stream.peek() != close) {
escaped = true;
stream.backUp(1);
state.tokens.unshift(tokenDollar);
break;
}
if (!escaped && next === quote && quote !== close) {
} else if (!escaped && quote !== close && next === quote) {
state.tokens.unshift(tokenString(quote, style))
return tokenize(stream, state)
} else if (!escaped && /['"]/.test(next) && !/['"]/.test(quote)) {
state.tokens.unshift(tokenStringStart(next, "string"));
stream.backUp(1);
break;
}
escaped = !escaped && next === '\\';
}
if (end) state.tokens.shift();
return style;
};
};
function tokenStringStart(quote, style) {
return function(stream, state) {
state.tokens[0] = tokenString(quote, style)
stream.next()
return tokenize(stream, state)
}
}
var tokenDollar = function(stream, state) {
if (state.tokens.length > 1) stream.eat('$');
var ch = stream.next()

View file

@ -61,4 +61,13 @@
MT("nested braces",
"[builtin echo] [def ${A[${B}]]}]")
MT("strings in parens",
"[def FOO][operator =]([quote $(<][string \"][def $MYDIR][string \"][quote /myfile grep ][string 'hello$'][quote )])")
MT ("string ending in dollar",
'[def a][operator =][string "xyz$"]; [def b][operator =][string "y"]')
MT ("quote ending in dollar",
"[quote $(echo a$)]")
})();

View file

@ -22,6 +22,7 @@
attributes: textMode,
text: textMode,
uri: textMode,
trusted_resource_uri: textMode,
css: CodeMirror.getMode(config, "text/css"),
js: CodeMirror.getMode(config, {name: "text/javascript", statementIndent: 2 * config.indentUnit})
};
@ -148,11 +149,13 @@
return "string";
}
if (stream.match(/^\/\*/)) {
state.soyState.push("comment");
return "comment";
} else if (stream.match(stream.sol() || (state.soyState.length && last(state.soyState) != "literal") ? /^\s*\/\/.*/ : /^\s+\/\/.*/)) {
return "comment";
if (!state.soyState.length || last(state.soyState) != "literal") {
if (stream.match(/^\/\*/)) {
state.soyState.push("comment");
return "comment";
} else if (stream.match(stream.sol() ? /^\s*\/\/.*/ : /^\s+\/\/.*/)) {
return "comment";
}
}
switch (last(state.soyState)) {
@ -269,7 +272,7 @@
return "keyword";
// A tag-keyword must be followed by whitespace, comment or a closing tag.
} else if (match = stream.match(/^\{([\/@\\]?\w+\??)(?=[\s\}]|\/[/*])/)) {
} else if (match = stream.match(/^\{([/@\\]?\w+\??)(?=$|[\s}]|\/[/*])/)) {
if (match[1] != "/switch")
state.indent += (/^(\/|(else|elseif|ifempty|case|fallbackmsg|default)$)/.test(match[1]) && state.tag != "switch" ? 1 : 2) * config.indentUnit;
state.tag = match[1];

View file

@ -111,4 +111,11 @@
MT('single-quote-strings',
'[keyword {][string "foo"] [string \'bar\'][keyword }]',
'');
MT('literal-comments',
'[keyword {literal}]/* comment */ // comment[keyword {/literal}]');
MT('highlight-command-at-eol',
'[keyword {msg]',
' [keyword }]');
})();

File diff suppressed because one or more lines are too long

View file

@ -103,6 +103,12 @@
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {});
</script>
<p>sTeX mode supports this option:</p>
<d1>
<dt><code>inMathMode: boolean</code></dt>
<dd>Whether to start parsing in math mode (default: <code>false</code>).</dd>
</d1>
<p><strong>MIME types defined:</strong> <code>text/x-stex</code>.</p>
<p><strong>Parsing/Highlighting Tests:</strong> <a href="../../test/index.html#stex_*">normal</a>, <a href="../../test/index.html#verbose,stex_*">verbose</a>.</p>

View file

@ -16,7 +16,7 @@
})(function(CodeMirror) {
"use strict";
CodeMirror.defineMode("stex", function() {
CodeMirror.defineMode("stex", function(_config, parserConfig) {
"use strict";
function pushCommand(state, command) {
@ -78,6 +78,14 @@
plugins["begin"] = addPluginPattern("begin", "tag", ["atom"]);
plugins["end"] = addPluginPattern("end", "tag", ["atom"]);
plugins["label" ] = addPluginPattern("label" , "tag", ["atom"]);
plugins["ref" ] = addPluginPattern("ref" , "tag", ["atom"]);
plugins["eqref" ] = addPluginPattern("eqref" , "tag", ["atom"]);
plugins["cite" ] = addPluginPattern("cite" , "tag", ["atom"]);
plugins["bibitem" ] = addPluginPattern("bibitem" , "tag", ["atom"]);
plugins["Bibitem" ] = addPluginPattern("Bibitem" , "tag", ["atom"]);
plugins["RBibitem" ] = addPluginPattern("RBibitem" , "tag", ["atom"]);
plugins["DEFAULT"] = function () {
this.name = "DEFAULT";
this.style = "tag";
@ -117,6 +125,10 @@
setState(state, function(source, state){ return inMathMode(source, state, "\\]"); });
return "keyword";
}
if (source.match("\\(")) {
setState(state, function(source, state){ return inMathMode(source, state, "\\)"); });
return "keyword";
}
if (source.match("$$")) {
setState(state, function(source, state){ return inMathMode(source, state, "$$"); });
return "keyword";
@ -161,7 +173,7 @@
if (source.eatSpace()) {
return null;
}
if (source.match(endModeSeq)) {
if (endModeSeq && source.match(endModeSeq)) {
setState(state, normal);
return "keyword";
}
@ -223,9 +235,10 @@
return {
startState: function() {
var f = parserConfig.inMathMode ? function(source, state){ return inMathMode(source, state); } : normal;
return {
cmdState: [],
f: normal
f: f
};
},
copyState: function(s) {

View file

@ -111,9 +111,18 @@
MT("inlineMath",
"[keyword $][number 3][variable-2 x][tag ^][number 2.45]-[tag \\sqrt][bracket {][tag \\$\\alpha][bracket }] = [number 2][keyword $] other text");
MT("inlineMathLatexStyle",
"[keyword \\(][number 3][variable-2 x][tag ^][number 2.45]-[tag \\sqrt][bracket {][tag \\$\\alpha][bracket }] = [number 2][keyword \\)] other text");
MT("displayMath",
"More [keyword $$]\t[variable-2 S][tag ^][variable-2 n][tag \\sum] [variable-2 i][keyword $$] other text");
MT("displayMath environment",
"[tag \\begin][bracket {][atom equation][bracket }] x [tag \\end][bracket {][atom equation][bracket }] other text");
MT("displayMath environment with label",
"[tag \\begin][bracket {][atom equation][bracket }][tag \\label][bracket {][atom eq1][bracket }] x [tag \\end][bracket {][atom equation][bracket }] other text~[tag \\ref][bracket {][atom eq1][bracket }]");
MT("mathWithComment",
"[keyword $][variable-2 x] [comment % $]",
"[variable-2 y][keyword $] other text");

View file

@ -76,7 +76,7 @@
if (ch == "#") {
stream.next();
// Hex color
if (stream.match(/^[0-9a-f]{6}|[0-9a-f]{3}/i)) {
if (stream.match(/^[0-9a-f]{3}([0-9a-f]([0-9a-f]{2}){0,2})?\b/i)) {
return ["atom", "atom"];
}
// ID selector

View file

@ -82,7 +82,7 @@ CodeMirror.defineMode("velocity", function() {
}
// variable?
else if (ch == "$") {
stream.eatWhile(/[\w\d\$_\.{}]/);
stream.eatWhile(/[\w\d\$_\.{}-]/);
// is it one of the specials?
if (specials && specials.propertyIsEnumerable(stream.current())) {
return "keyword";

View file

@ -163,8 +163,9 @@ CodeMirror.defineMode("xml", function(editorConf, config_) {
stream.next();
}
return style;
};
}
}
function doctype(depth) {
return function(stream, state) {
var ch;

View file

@ -108,7 +108,8 @@ CodeMirror.defineMode("yaml", function() {
literal: false,
escaped: false
};
}
},
lineComment: "#"
};
});