first commit
This commit is contained in:
1963
media/vendor/codemirror/js/codemirror-autocomplete.js
vendored
Normal file
1963
media/vendor/codemirror/js/codemirror-autocomplete.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
media/vendor/codemirror/js/codemirror-autocomplete.min.js
vendored
Normal file
1
media/vendor/codemirror/js/codemirror-autocomplete.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
BIN
media/vendor/codemirror/js/codemirror-autocomplete.min.js.gz
vendored
Normal file
BIN
media/vendor/codemirror/js/codemirror-autocomplete.min.js.gz
vendored
Normal file
Binary file not shown.
1610
media/vendor/codemirror/js/codemirror-commands.js
vendored
Normal file
1610
media/vendor/codemirror/js/codemirror-commands.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
media/vendor/codemirror/js/codemirror-commands.min.js
vendored
Normal file
1
media/vendor/codemirror/js/codemirror-commands.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
BIN
media/vendor/codemirror/js/codemirror-commands.min.js.gz
vendored
Normal file
BIN
media/vendor/codemirror/js/codemirror-commands.min.js.gz
vendored
Normal file
Binary file not shown.
257
media/vendor/codemirror/js/codemirror-lang-css.js
vendored
Normal file
257
media/vendor/codemirror/js/codemirror-lang-css.js
vendored
Normal file
@ -0,0 +1,257 @@
|
||||
import { parser } from '@lezer/css';
|
||||
import { syntaxTree, LRLanguage, indentNodeProp, continuedIndent, foldNodeProp, foldInside, LanguageSupport } from '@codemirror/language';
|
||||
import { IterMode, NodeWeakMap } from '@lezer/common';
|
||||
|
||||
let _properties = null;
|
||||
function properties() {
|
||||
if (!_properties && typeof document == "object" && document.body) {
|
||||
let { style } = document.body, names = [], seen = new Set;
|
||||
for (let prop in style)
|
||||
if (prop != "cssText" && prop != "cssFloat") {
|
||||
if (typeof style[prop] == "string") {
|
||||
if (/[A-Z]/.test(prop))
|
||||
prop = prop.replace(/[A-Z]/g, ch => "-" + ch.toLowerCase());
|
||||
if (!seen.has(prop)) {
|
||||
names.push(prop);
|
||||
seen.add(prop);
|
||||
}
|
||||
}
|
||||
}
|
||||
_properties = names.sort().map(name => ({ type: "property", label: name }));
|
||||
}
|
||||
return _properties || [];
|
||||
}
|
||||
const pseudoClasses = /*@__PURE__*/[
|
||||
"active", "after", "any-link", "autofill", "backdrop", "before",
|
||||
"checked", "cue", "default", "defined", "disabled", "empty",
|
||||
"enabled", "file-selector-button", "first", "first-child",
|
||||
"first-letter", "first-line", "first-of-type", "focus",
|
||||
"focus-visible", "focus-within", "fullscreen", "has", "host",
|
||||
"host-context", "hover", "in-range", "indeterminate", "invalid",
|
||||
"is", "lang", "last-child", "last-of-type", "left", "link", "marker",
|
||||
"modal", "not", "nth-child", "nth-last-child", "nth-last-of-type",
|
||||
"nth-of-type", "only-child", "only-of-type", "optional", "out-of-range",
|
||||
"part", "placeholder", "placeholder-shown", "read-only", "read-write",
|
||||
"required", "right", "root", "scope", "selection", "slotted", "target",
|
||||
"target-text", "valid", "visited", "where"
|
||||
].map(name => ({ type: "class", label: name }));
|
||||
const values = /*@__PURE__*/[
|
||||
"above", "absolute", "activeborder", "additive", "activecaption", "after-white-space",
|
||||
"ahead", "alias", "all", "all-scroll", "alphabetic", "alternate", "always",
|
||||
"antialiased", "appworkspace", "asterisks", "attr", "auto", "auto-flow", "avoid", "avoid-column",
|
||||
"avoid-page", "avoid-region", "axis-pan", "background", "backwards", "baseline", "below",
|
||||
"bidi-override", "blink", "block", "block-axis", "bold", "bolder", "border", "border-box",
|
||||
"both", "bottom", "break", "break-all", "break-word", "bullets", "button", "button-bevel",
|
||||
"buttonface", "buttonhighlight", "buttonshadow", "buttontext", "calc", "capitalize",
|
||||
"caps-lock-indicator", "caption", "captiontext", "caret", "cell", "center", "checkbox", "circle",
|
||||
"cjk-decimal", "clear", "clip", "close-quote", "col-resize", "collapse", "color", "color-burn",
|
||||
"color-dodge", "column", "column-reverse", "compact", "condensed", "contain", "content",
|
||||
"contents", "content-box", "context-menu", "continuous", "copy", "counter", "counters", "cover",
|
||||
"crop", "cross", "crosshair", "currentcolor", "cursive", "cyclic", "darken", "dashed", "decimal",
|
||||
"decimal-leading-zero", "default", "default-button", "dense", "destination-atop", "destination-in",
|
||||
"destination-out", "destination-over", "difference", "disc", "discard", "disclosure-closed",
|
||||
"disclosure-open", "document", "dot-dash", "dot-dot-dash", "dotted", "double", "down", "e-resize",
|
||||
"ease", "ease-in", "ease-in-out", "ease-out", "element", "ellipse", "ellipsis", "embed", "end",
|
||||
"ethiopic-abegede-gez", "ethiopic-halehame-aa-er", "ethiopic-halehame-gez", "ew-resize", "exclusion",
|
||||
"expanded", "extends", "extra-condensed", "extra-expanded", "fantasy", "fast", "fill", "fill-box",
|
||||
"fixed", "flat", "flex", "flex-end", "flex-start", "footnotes", "forwards", "from",
|
||||
"geometricPrecision", "graytext", "grid", "groove", "hand", "hard-light", "help", "hidden", "hide",
|
||||
"higher", "highlight", "highlighttext", "horizontal", "hsl", "hsla", "hue", "icon", "ignore",
|
||||
"inactiveborder", "inactivecaption", "inactivecaptiontext", "infinite", "infobackground", "infotext",
|
||||
"inherit", "initial", "inline", "inline-axis", "inline-block", "inline-flex", "inline-grid",
|
||||
"inline-table", "inset", "inside", "intrinsic", "invert", "italic", "justify", "keep-all",
|
||||
"landscape", "large", "larger", "left", "level", "lighter", "lighten", "line-through", "linear",
|
||||
"linear-gradient", "lines", "list-item", "listbox", "listitem", "local", "logical", "loud", "lower",
|
||||
"lower-hexadecimal", "lower-latin", "lower-norwegian", "lowercase", "ltr", "luminosity", "manipulation",
|
||||
"match", "matrix", "matrix3d", "medium", "menu", "menutext", "message-box", "middle", "min-intrinsic",
|
||||
"mix", "monospace", "move", "multiple", "multiple_mask_images", "multiply", "n-resize", "narrower",
|
||||
"ne-resize", "nesw-resize", "no-close-quote", "no-drop", "no-open-quote", "no-repeat", "none",
|
||||
"normal", "not-allowed", "nowrap", "ns-resize", "numbers", "numeric", "nw-resize", "nwse-resize",
|
||||
"oblique", "opacity", "open-quote", "optimizeLegibility", "optimizeSpeed", "outset", "outside",
|
||||
"outside-shape", "overlay", "overline", "padding", "padding-box", "painted", "page", "paused",
|
||||
"perspective", "pinch-zoom", "plus-darker", "plus-lighter", "pointer", "polygon", "portrait",
|
||||
"pre", "pre-line", "pre-wrap", "preserve-3d", "progress", "push-button", "radial-gradient", "radio",
|
||||
"read-only", "read-write", "read-write-plaintext-only", "rectangle", "region", "relative", "repeat",
|
||||
"repeating-linear-gradient", "repeating-radial-gradient", "repeat-x", "repeat-y", "reset", "reverse",
|
||||
"rgb", "rgba", "ridge", "right", "rotate", "rotate3d", "rotateX", "rotateY", "rotateZ", "round",
|
||||
"row", "row-resize", "row-reverse", "rtl", "run-in", "running", "s-resize", "sans-serif", "saturation",
|
||||
"scale", "scale3d", "scaleX", "scaleY", "scaleZ", "screen", "scroll", "scrollbar", "scroll-position",
|
||||
"se-resize", "self-start", "self-end", "semi-condensed", "semi-expanded", "separate", "serif", "show",
|
||||
"single", "skew", "skewX", "skewY", "skip-white-space", "slide", "slider-horizontal",
|
||||
"slider-vertical", "sliderthumb-horizontal", "sliderthumb-vertical", "slow", "small", "small-caps",
|
||||
"small-caption", "smaller", "soft-light", "solid", "source-atop", "source-in", "source-out",
|
||||
"source-over", "space", "space-around", "space-between", "space-evenly", "spell-out", "square", "start",
|
||||
"static", "status-bar", "stretch", "stroke", "stroke-box", "sub", "subpixel-antialiased", "svg_masks",
|
||||
"super", "sw-resize", "symbolic", "symbols", "system-ui", "table", "table-caption", "table-cell",
|
||||
"table-column", "table-column-group", "table-footer-group", "table-header-group", "table-row",
|
||||
"table-row-group", "text", "text-bottom", "text-top", "textarea", "textfield", "thick", "thin",
|
||||
"threeddarkshadow", "threedface", "threedhighlight", "threedlightshadow", "threedshadow", "to", "top",
|
||||
"transform", "translate", "translate3d", "translateX", "translateY", "translateZ", "transparent",
|
||||
"ultra-condensed", "ultra-expanded", "underline", "unidirectional-pan", "unset", "up", "upper-latin",
|
||||
"uppercase", "url", "var", "vertical", "vertical-text", "view-box", "visible", "visibleFill",
|
||||
"visiblePainted", "visibleStroke", "visual", "w-resize", "wait", "wave", "wider", "window", "windowframe",
|
||||
"windowtext", "words", "wrap", "wrap-reverse", "x-large", "x-small", "xor", "xx-large", "xx-small"
|
||||
].map(name => ({ type: "keyword", label: name })).concat(/*@__PURE__*/[
|
||||
"aliceblue", "antiquewhite", "aqua", "aquamarine", "azure", "beige",
|
||||
"bisque", "black", "blanchedalmond", "blue", "blueviolet", "brown",
|
||||
"burlywood", "cadetblue", "chartreuse", "chocolate", "coral", "cornflowerblue",
|
||||
"cornsilk", "crimson", "cyan", "darkblue", "darkcyan", "darkgoldenrod",
|
||||
"darkgray", "darkgreen", "darkkhaki", "darkmagenta", "darkolivegreen",
|
||||
"darkorange", "darkorchid", "darkred", "darksalmon", "darkseagreen",
|
||||
"darkslateblue", "darkslategray", "darkturquoise", "darkviolet",
|
||||
"deeppink", "deepskyblue", "dimgray", "dodgerblue", "firebrick",
|
||||
"floralwhite", "forestgreen", "fuchsia", "gainsboro", "ghostwhite",
|
||||
"gold", "goldenrod", "gray", "grey", "green", "greenyellow", "honeydew",
|
||||
"hotpink", "indianred", "indigo", "ivory", "khaki", "lavender",
|
||||
"lavenderblush", "lawngreen", "lemonchiffon", "lightblue", "lightcoral",
|
||||
"lightcyan", "lightgoldenrodyellow", "lightgray", "lightgreen", "lightpink",
|
||||
"lightsalmon", "lightseagreen", "lightskyblue", "lightslategray",
|
||||
"lightsteelblue", "lightyellow", "lime", "limegreen", "linen", "magenta",
|
||||
"maroon", "mediumaquamarine", "mediumblue", "mediumorchid", "mediumpurple",
|
||||
"mediumseagreen", "mediumslateblue", "mediumspringgreen", "mediumturquoise",
|
||||
"mediumvioletred", "midnightblue", "mintcream", "mistyrose", "moccasin",
|
||||
"navajowhite", "navy", "oldlace", "olive", "olivedrab", "orange", "orangered",
|
||||
"orchid", "palegoldenrod", "palegreen", "paleturquoise", "palevioletred",
|
||||
"papayawhip", "peachpuff", "peru", "pink", "plum", "powderblue",
|
||||
"purple", "rebeccapurple", "red", "rosybrown", "royalblue", "saddlebrown",
|
||||
"salmon", "sandybrown", "seagreen", "seashell", "sienna", "silver", "skyblue",
|
||||
"slateblue", "slategray", "snow", "springgreen", "steelblue", "tan",
|
||||
"teal", "thistle", "tomato", "turquoise", "violet", "wheat", "white",
|
||||
"whitesmoke", "yellow", "yellowgreen"
|
||||
].map(name => ({ type: "constant", label: name })));
|
||||
const tags = /*@__PURE__*/[
|
||||
"a", "abbr", "address", "article", "aside", "b", "bdi", "bdo", "blockquote", "body",
|
||||
"br", "button", "canvas", "caption", "cite", "code", "col", "colgroup", "dd", "del",
|
||||
"details", "dfn", "dialog", "div", "dl", "dt", "em", "figcaption", "figure", "footer",
|
||||
"form", "header", "hgroup", "h1", "h2", "h3", "h4", "h5", "h6", "hr", "html", "i", "iframe",
|
||||
"img", "input", "ins", "kbd", "label", "legend", "li", "main", "meter", "nav", "ol", "output",
|
||||
"p", "pre", "ruby", "section", "select", "small", "source", "span", "strong", "sub", "summary",
|
||||
"sup", "table", "tbody", "td", "template", "textarea", "tfoot", "th", "thead", "tr", "u", "ul"
|
||||
].map(name => ({ type: "type", label: name }));
|
||||
const identifier = /^(\w[\w-]*|-\w[\w-]*|)$/, variable = /^-(-[\w-]*)?$/;
|
||||
function isVarArg(node, doc) {
|
||||
var _a;
|
||||
if (node.name == "(" || node.type.isError)
|
||||
node = node.parent || node;
|
||||
if (node.name != "ArgList")
|
||||
return false;
|
||||
let callee = (_a = node.parent) === null || _a === void 0 ? void 0 : _a.firstChild;
|
||||
if ((callee === null || callee === void 0 ? void 0 : callee.name) != "Callee")
|
||||
return false;
|
||||
return doc.sliceString(callee.from, callee.to) == "var";
|
||||
}
|
||||
const VariablesByNode = /*@__PURE__*/new NodeWeakMap();
|
||||
const declSelector = ["Declaration"];
|
||||
function astTop(node) {
|
||||
for (let cur = node;;) {
|
||||
if (cur.type.isTop)
|
||||
return cur;
|
||||
if (!(cur = cur.parent))
|
||||
return node;
|
||||
}
|
||||
}
|
||||
function variableNames(doc, node, isVariable) {
|
||||
if (node.to - node.from > 4096) {
|
||||
let known = VariablesByNode.get(node);
|
||||
if (known)
|
||||
return known;
|
||||
let result = [], seen = new Set, cursor = node.cursor(IterMode.IncludeAnonymous);
|
||||
if (cursor.firstChild())
|
||||
do {
|
||||
for (let option of variableNames(doc, cursor.node, isVariable))
|
||||
if (!seen.has(option.label)) {
|
||||
seen.add(option.label);
|
||||
result.push(option);
|
||||
}
|
||||
} while (cursor.nextSibling());
|
||||
VariablesByNode.set(node, result);
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
let result = [], seen = new Set;
|
||||
node.cursor().iterate(node => {
|
||||
var _a;
|
||||
if (isVariable(node) && node.matchContext(declSelector) && ((_a = node.node.nextSibling) === null || _a === void 0 ? void 0 : _a.name) == ":") {
|
||||
let name = doc.sliceString(node.from, node.to);
|
||||
if (!seen.has(name)) {
|
||||
seen.add(name);
|
||||
result.push({ label: name, type: "variable" });
|
||||
}
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
}
|
||||
/**
|
||||
Create a completion source for a CSS dialect, providing a
|
||||
predicate for determining what kind of syntax node can act as a
|
||||
completable variable. This is used by language modes like Sass and
|
||||
Less to reuse this package's completion logic.
|
||||
*/
|
||||
const defineCSSCompletionSource = (isVariable) => context => {
|
||||
let { state, pos } = context, node = syntaxTree(state).resolveInner(pos, -1);
|
||||
let isDash = node.type.isError && node.from == node.to - 1 && state.doc.sliceString(node.from, node.to) == "-";
|
||||
if (node.name == "PropertyName" ||
|
||||
(isDash || node.name == "TagName") && /^(Block|Styles)$/.test(node.resolve(node.to).name))
|
||||
return { from: node.from, options: properties(), validFor: identifier };
|
||||
if (node.name == "ValueName")
|
||||
return { from: node.from, options: values, validFor: identifier };
|
||||
if (node.name == "PseudoClassName")
|
||||
return { from: node.from, options: pseudoClasses, validFor: identifier };
|
||||
if (isVariable(node) || (context.explicit || isDash) && isVarArg(node, state.doc))
|
||||
return { from: isVariable(node) || isDash ? node.from : pos,
|
||||
options: variableNames(state.doc, astTop(node), isVariable),
|
||||
validFor: variable };
|
||||
if (node.name == "TagName") {
|
||||
for (let { parent } = node; parent; parent = parent.parent)
|
||||
if (parent.name == "Block")
|
||||
return { from: node.from, options: properties(), validFor: identifier };
|
||||
return { from: node.from, options: tags, validFor: identifier };
|
||||
}
|
||||
if (!context.explicit)
|
||||
return null;
|
||||
let above = node.resolve(pos), before = above.childBefore(pos);
|
||||
if (before && before.name == ":" && above.name == "PseudoClassSelector")
|
||||
return { from: pos, options: pseudoClasses, validFor: identifier };
|
||||
if (before && before.name == ":" && above.name == "Declaration" || above.name == "ArgList")
|
||||
return { from: pos, options: values, validFor: identifier };
|
||||
if (above.name == "Block" || above.name == "Styles")
|
||||
return { from: pos, options: properties(), validFor: identifier };
|
||||
return null;
|
||||
};
|
||||
/**
|
||||
CSS property, variable, and value keyword completion source.
|
||||
*/
|
||||
const cssCompletionSource = /*@__PURE__*/defineCSSCompletionSource(n => n.name == "VariableName");
|
||||
|
||||
/**
|
||||
A language provider based on the [Lezer CSS
|
||||
parser](https://github.com/lezer-parser/css), extended with
|
||||
highlighting and indentation information.
|
||||
*/
|
||||
const cssLanguage = /*@__PURE__*/LRLanguage.define({
|
||||
name: "css",
|
||||
parser: /*@__PURE__*/parser.configure({
|
||||
props: [
|
||||
/*@__PURE__*/indentNodeProp.add({
|
||||
Declaration: /*@__PURE__*/continuedIndent()
|
||||
}),
|
||||
/*@__PURE__*/foldNodeProp.add({
|
||||
"Block KeyframeList": foldInside
|
||||
})
|
||||
]
|
||||
}),
|
||||
languageData: {
|
||||
commentTokens: { block: { open: "/*", close: "*/" } },
|
||||
indentOnInput: /^\s*\}$/,
|
||||
wordChars: "-"
|
||||
}
|
||||
});
|
||||
/**
|
||||
Language support for CSS.
|
||||
*/
|
||||
function css() {
|
||||
return new LanguageSupport(cssLanguage, cssLanguage.data.of({ autocomplete: cssCompletionSource }));
|
||||
}
|
||||
|
||||
export { css, cssCompletionSource, cssLanguage, defineCSSCompletionSource };
|
||||
1
media/vendor/codemirror/js/codemirror-lang-css.min.js
vendored
Normal file
1
media/vendor/codemirror/js/codemirror-lang-css.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
BIN
media/vendor/codemirror/js/codemirror-lang-css.min.js.gz
vendored
Normal file
BIN
media/vendor/codemirror/js/codemirror-lang-css.min.js.gz
vendored
Normal file
Binary file not shown.
666
media/vendor/codemirror/js/codemirror-lang-html.js
vendored
Normal file
666
media/vendor/codemirror/js/codemirror-lang-html.js
vendored
Normal file
@ -0,0 +1,666 @@
|
||||
import { parser, configureNesting } from '@lezer/html';
|
||||
import { cssLanguage, css } from '@codemirror/lang-css';
|
||||
import { typescriptLanguage, jsxLanguage, tsxLanguage, javascriptLanguage, javascript } from '@codemirror/lang-javascript';
|
||||
import { EditorView } from '@codemirror/view';
|
||||
import { EditorSelection } from '@codemirror/state';
|
||||
import { LRLanguage, indentNodeProp, foldNodeProp, bracketMatchingHandle, LanguageSupport, syntaxTree } from '@codemirror/language';
|
||||
|
||||
const Targets = ["_blank", "_self", "_top", "_parent"];
|
||||
const Charsets = ["ascii", "utf-8", "utf-16", "latin1", "latin1"];
|
||||
const Methods = ["get", "post", "put", "delete"];
|
||||
const Encs = ["application/x-www-form-urlencoded", "multipart/form-data", "text/plain"];
|
||||
const Bool = ["true", "false"];
|
||||
const S = {}; // Empty tag spec
|
||||
const Tags = {
|
||||
a: {
|
||||
attrs: {
|
||||
href: null, ping: null, type: null,
|
||||
media: null,
|
||||
target: Targets,
|
||||
hreflang: null
|
||||
}
|
||||
},
|
||||
abbr: S,
|
||||
address: S,
|
||||
area: {
|
||||
attrs: {
|
||||
alt: null, coords: null, href: null, target: null, ping: null,
|
||||
media: null, hreflang: null, type: null,
|
||||
shape: ["default", "rect", "circle", "poly"]
|
||||
}
|
||||
},
|
||||
article: S,
|
||||
aside: S,
|
||||
audio: {
|
||||
attrs: {
|
||||
src: null, mediagroup: null,
|
||||
crossorigin: ["anonymous", "use-credentials"],
|
||||
preload: ["none", "metadata", "auto"],
|
||||
autoplay: ["autoplay"],
|
||||
loop: ["loop"],
|
||||
controls: ["controls"]
|
||||
}
|
||||
},
|
||||
b: S,
|
||||
base: { attrs: { href: null, target: Targets } },
|
||||
bdi: S,
|
||||
bdo: S,
|
||||
blockquote: { attrs: { cite: null } },
|
||||
body: S,
|
||||
br: S,
|
||||
button: {
|
||||
attrs: {
|
||||
form: null, formaction: null, name: null, value: null,
|
||||
autofocus: ["autofocus"],
|
||||
disabled: ["autofocus"],
|
||||
formenctype: Encs,
|
||||
formmethod: Methods,
|
||||
formnovalidate: ["novalidate"],
|
||||
formtarget: Targets,
|
||||
type: ["submit", "reset", "button"]
|
||||
}
|
||||
},
|
||||
canvas: { attrs: { width: null, height: null } },
|
||||
caption: S,
|
||||
center: S,
|
||||
cite: S,
|
||||
code: S,
|
||||
col: { attrs: { span: null } },
|
||||
colgroup: { attrs: { span: null } },
|
||||
command: {
|
||||
attrs: {
|
||||
type: ["command", "checkbox", "radio"],
|
||||
label: null, icon: null, radiogroup: null, command: null, title: null,
|
||||
disabled: ["disabled"],
|
||||
checked: ["checked"]
|
||||
}
|
||||
},
|
||||
data: { attrs: { value: null } },
|
||||
datagrid: { attrs: { disabled: ["disabled"], multiple: ["multiple"] } },
|
||||
datalist: { attrs: { data: null } },
|
||||
dd: S,
|
||||
del: { attrs: { cite: null, datetime: null } },
|
||||
details: { attrs: { open: ["open"] } },
|
||||
dfn: S,
|
||||
div: S,
|
||||
dl: S,
|
||||
dt: S,
|
||||
em: S,
|
||||
embed: { attrs: { src: null, type: null, width: null, height: null } },
|
||||
eventsource: { attrs: { src: null } },
|
||||
fieldset: { attrs: { disabled: ["disabled"], form: null, name: null } },
|
||||
figcaption: S,
|
||||
figure: S,
|
||||
footer: S,
|
||||
form: {
|
||||
attrs: {
|
||||
action: null, name: null,
|
||||
"accept-charset": Charsets,
|
||||
autocomplete: ["on", "off"],
|
||||
enctype: Encs,
|
||||
method: Methods,
|
||||
novalidate: ["novalidate"],
|
||||
target: Targets
|
||||
}
|
||||
},
|
||||
h1: S, h2: S, h3: S, h4: S, h5: S, h6: S,
|
||||
head: {
|
||||
children: ["title", "base", "link", "style", "meta", "script", "noscript", "command"]
|
||||
},
|
||||
header: S,
|
||||
hgroup: S,
|
||||
hr: S,
|
||||
html: {
|
||||
attrs: { manifest: null }
|
||||
},
|
||||
i: S,
|
||||
iframe: {
|
||||
attrs: {
|
||||
src: null, srcdoc: null, name: null, width: null, height: null,
|
||||
sandbox: ["allow-top-navigation", "allow-same-origin", "allow-forms", "allow-scripts"],
|
||||
seamless: ["seamless"]
|
||||
}
|
||||
},
|
||||
img: {
|
||||
attrs: {
|
||||
alt: null, src: null, ismap: null, usemap: null, width: null, height: null,
|
||||
crossorigin: ["anonymous", "use-credentials"]
|
||||
}
|
||||
},
|
||||
input: {
|
||||
attrs: {
|
||||
alt: null, dirname: null, form: null, formaction: null,
|
||||
height: null, list: null, max: null, maxlength: null, min: null,
|
||||
name: null, pattern: null, placeholder: null, size: null, src: null,
|
||||
step: null, value: null, width: null,
|
||||
accept: ["audio/*", "video/*", "image/*"],
|
||||
autocomplete: ["on", "off"],
|
||||
autofocus: ["autofocus"],
|
||||
checked: ["checked"],
|
||||
disabled: ["disabled"],
|
||||
formenctype: Encs,
|
||||
formmethod: Methods,
|
||||
formnovalidate: ["novalidate"],
|
||||
formtarget: Targets,
|
||||
multiple: ["multiple"],
|
||||
readonly: ["readonly"],
|
||||
required: ["required"],
|
||||
type: ["hidden", "text", "search", "tel", "url", "email", "password", "datetime", "date", "month",
|
||||
"week", "time", "datetime-local", "number", "range", "color", "checkbox", "radio",
|
||||
"file", "submit", "image", "reset", "button"]
|
||||
}
|
||||
},
|
||||
ins: { attrs: { cite: null, datetime: null } },
|
||||
kbd: S,
|
||||
keygen: {
|
||||
attrs: {
|
||||
challenge: null, form: null, name: null,
|
||||
autofocus: ["autofocus"],
|
||||
disabled: ["disabled"],
|
||||
keytype: ["RSA"]
|
||||
}
|
||||
},
|
||||
label: { attrs: { for: null, form: null } },
|
||||
legend: S,
|
||||
li: { attrs: { value: null } },
|
||||
link: {
|
||||
attrs: {
|
||||
href: null, type: null,
|
||||
hreflang: null,
|
||||
media: null,
|
||||
sizes: ["all", "16x16", "16x16 32x32", "16x16 32x32 64x64"]
|
||||
}
|
||||
},
|
||||
map: { attrs: { name: null } },
|
||||
mark: S,
|
||||
menu: { attrs: { label: null, type: ["list", "context", "toolbar"] } },
|
||||
meta: {
|
||||
attrs: {
|
||||
content: null,
|
||||
charset: Charsets,
|
||||
name: ["viewport", "application-name", "author", "description", "generator", "keywords"],
|
||||
"http-equiv": ["content-language", "content-type", "default-style", "refresh"]
|
||||
}
|
||||
},
|
||||
meter: { attrs: { value: null, min: null, low: null, high: null, max: null, optimum: null } },
|
||||
nav: S,
|
||||
noscript: S,
|
||||
object: {
|
||||
attrs: {
|
||||
data: null, type: null, name: null, usemap: null, form: null, width: null, height: null,
|
||||
typemustmatch: ["typemustmatch"]
|
||||
}
|
||||
},
|
||||
ol: { attrs: { reversed: ["reversed"], start: null, type: ["1", "a", "A", "i", "I"] },
|
||||
children: ["li", "script", "template", "ul", "ol"] },
|
||||
optgroup: { attrs: { disabled: ["disabled"], label: null } },
|
||||
option: { attrs: { disabled: ["disabled"], label: null, selected: ["selected"], value: null } },
|
||||
output: { attrs: { for: null, form: null, name: null } },
|
||||
p: S,
|
||||
param: { attrs: { name: null, value: null } },
|
||||
pre: S,
|
||||
progress: { attrs: { value: null, max: null } },
|
||||
q: { attrs: { cite: null } },
|
||||
rp: S,
|
||||
rt: S,
|
||||
ruby: S,
|
||||
samp: S,
|
||||
script: {
|
||||
attrs: {
|
||||
type: ["text/javascript"],
|
||||
src: null,
|
||||
async: ["async"],
|
||||
defer: ["defer"],
|
||||
charset: Charsets
|
||||
}
|
||||
},
|
||||
section: S,
|
||||
select: {
|
||||
attrs: {
|
||||
form: null, name: null, size: null,
|
||||
autofocus: ["autofocus"],
|
||||
disabled: ["disabled"],
|
||||
multiple: ["multiple"]
|
||||
}
|
||||
},
|
||||
slot: { attrs: { name: null } },
|
||||
small: S,
|
||||
source: { attrs: { src: null, type: null, media: null } },
|
||||
span: S,
|
||||
strong: S,
|
||||
style: {
|
||||
attrs: {
|
||||
type: ["text/css"],
|
||||
media: null,
|
||||
scoped: null
|
||||
}
|
||||
},
|
||||
sub: S,
|
||||
summary: S,
|
||||
sup: S,
|
||||
table: S,
|
||||
tbody: S,
|
||||
td: { attrs: { colspan: null, rowspan: null, headers: null } },
|
||||
template: S,
|
||||
textarea: {
|
||||
attrs: {
|
||||
dirname: null, form: null, maxlength: null, name: null, placeholder: null,
|
||||
rows: null, cols: null,
|
||||
autofocus: ["autofocus"],
|
||||
disabled: ["disabled"],
|
||||
readonly: ["readonly"],
|
||||
required: ["required"],
|
||||
wrap: ["soft", "hard"]
|
||||
}
|
||||
},
|
||||
tfoot: S,
|
||||
th: { attrs: { colspan: null, rowspan: null, headers: null, scope: ["row", "col", "rowgroup", "colgroup"] } },
|
||||
thead: S,
|
||||
time: { attrs: { datetime: null } },
|
||||
title: S,
|
||||
tr: S,
|
||||
track: {
|
||||
attrs: {
|
||||
src: null, label: null, default: null,
|
||||
kind: ["subtitles", "captions", "descriptions", "chapters", "metadata"],
|
||||
srclang: null
|
||||
}
|
||||
},
|
||||
ul: { children: ["li", "script", "template", "ul", "ol"] },
|
||||
var: S,
|
||||
video: {
|
||||
attrs: {
|
||||
src: null, poster: null, width: null, height: null,
|
||||
crossorigin: ["anonymous", "use-credentials"],
|
||||
preload: ["auto", "metadata", "none"],
|
||||
autoplay: ["autoplay"],
|
||||
mediagroup: ["movie"],
|
||||
muted: ["muted"],
|
||||
controls: ["controls"]
|
||||
}
|
||||
},
|
||||
wbr: S
|
||||
};
|
||||
const GlobalAttrs = {
|
||||
accesskey: null,
|
||||
class: null,
|
||||
contenteditable: Bool,
|
||||
contextmenu: null,
|
||||
dir: ["ltr", "rtl", "auto"],
|
||||
draggable: ["true", "false", "auto"],
|
||||
dropzone: ["copy", "move", "link", "string:", "file:"],
|
||||
hidden: ["hidden"],
|
||||
id: null,
|
||||
inert: ["inert"],
|
||||
itemid: null,
|
||||
itemprop: null,
|
||||
itemref: null,
|
||||
itemscope: ["itemscope"],
|
||||
itemtype: null,
|
||||
lang: ["ar", "bn", "de", "en-GB", "en-US", "es", "fr", "hi", "id", "ja", "pa", "pt", "ru", "tr", "zh"],
|
||||
spellcheck: Bool,
|
||||
autocorrect: Bool,
|
||||
autocapitalize: Bool,
|
||||
style: null,
|
||||
tabindex: null,
|
||||
title: null,
|
||||
translate: ["yes", "no"],
|
||||
rel: ["stylesheet", "alternate", "author", "bookmark", "help", "license", "next", "nofollow", "noreferrer", "prefetch", "prev", "search", "tag"],
|
||||
role: /*@__PURE__*/"alert application article banner button cell checkbox complementary contentinfo dialog document feed figure form grid gridcell heading img list listbox listitem main navigation region row rowgroup search switch tab table tabpanel textbox timer".split(" "),
|
||||
"aria-activedescendant": null,
|
||||
"aria-atomic": Bool,
|
||||
"aria-autocomplete": ["inline", "list", "both", "none"],
|
||||
"aria-busy": Bool,
|
||||
"aria-checked": ["true", "false", "mixed", "undefined"],
|
||||
"aria-controls": null,
|
||||
"aria-describedby": null,
|
||||
"aria-disabled": Bool,
|
||||
"aria-dropeffect": null,
|
||||
"aria-expanded": ["true", "false", "undefined"],
|
||||
"aria-flowto": null,
|
||||
"aria-grabbed": ["true", "false", "undefined"],
|
||||
"aria-haspopup": Bool,
|
||||
"aria-hidden": Bool,
|
||||
"aria-invalid": ["true", "false", "grammar", "spelling"],
|
||||
"aria-label": null,
|
||||
"aria-labelledby": null,
|
||||
"aria-level": null,
|
||||
"aria-live": ["off", "polite", "assertive"],
|
||||
"aria-multiline": Bool,
|
||||
"aria-multiselectable": Bool,
|
||||
"aria-owns": null,
|
||||
"aria-posinset": null,
|
||||
"aria-pressed": ["true", "false", "mixed", "undefined"],
|
||||
"aria-readonly": Bool,
|
||||
"aria-relevant": null,
|
||||
"aria-required": Bool,
|
||||
"aria-selected": ["true", "false", "undefined"],
|
||||
"aria-setsize": null,
|
||||
"aria-sort": ["ascending", "descending", "none", "other"],
|
||||
"aria-valuemax": null,
|
||||
"aria-valuemin": null,
|
||||
"aria-valuenow": null,
|
||||
"aria-valuetext": null
|
||||
};
|
||||
const eventAttributes = /*@__PURE__*/("beforeunload copy cut dragstart dragover dragleave dragenter dragend " +
|
||||
"drag paste focus blur change click load mousedown mouseenter mouseleave " +
|
||||
"mouseup keydown keyup resize scroll unload").split(" ").map(n => "on" + n);
|
||||
for (let a of eventAttributes)
|
||||
GlobalAttrs[a] = null;
|
||||
class Schema {
|
||||
constructor(extraTags, extraAttrs) {
|
||||
this.tags = Object.assign(Object.assign({}, Tags), extraTags);
|
||||
this.globalAttrs = Object.assign(Object.assign({}, GlobalAttrs), extraAttrs);
|
||||
this.allTags = Object.keys(this.tags);
|
||||
this.globalAttrNames = Object.keys(this.globalAttrs);
|
||||
}
|
||||
}
|
||||
Schema.default = /*@__PURE__*/new Schema;
|
||||
function elementName(doc, tree, max = doc.length) {
|
||||
if (!tree)
|
||||
return "";
|
||||
let tag = tree.firstChild;
|
||||
let name = tag && tag.getChild("TagName");
|
||||
return name ? doc.sliceString(name.from, Math.min(name.to, max)) : "";
|
||||
}
|
||||
function findParentElement(tree, skip = false) {
|
||||
for (; tree; tree = tree.parent)
|
||||
if (tree.name == "Element") {
|
||||
if (skip)
|
||||
skip = false;
|
||||
else
|
||||
return tree;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
function allowedChildren(doc, tree, schema) {
|
||||
let parentInfo = schema.tags[elementName(doc, findParentElement(tree))];
|
||||
return (parentInfo === null || parentInfo === void 0 ? void 0 : parentInfo.children) || schema.allTags;
|
||||
}
|
||||
function openTags(doc, tree) {
|
||||
let open = [];
|
||||
for (let parent = findParentElement(tree); parent && !parent.type.isTop; parent = findParentElement(parent.parent)) {
|
||||
let tagName = elementName(doc, parent);
|
||||
if (tagName && parent.lastChild.name == "CloseTag")
|
||||
break;
|
||||
if (tagName && open.indexOf(tagName) < 0 && (tree.name == "EndTag" || tree.from >= parent.firstChild.to))
|
||||
open.push(tagName);
|
||||
}
|
||||
return open;
|
||||
}
|
||||
const identifier = /^[:\-\.\w\u00b7-\uffff]*$/;
|
||||
function completeTag(state, schema, tree, from, to) {
|
||||
let end = /\s*>/.test(state.sliceDoc(to, to + 5)) ? "" : ">";
|
||||
let parent = findParentElement(tree, true);
|
||||
return { from, to,
|
||||
options: allowedChildren(state.doc, parent, schema).map(tagName => ({ label: tagName, type: "type" })).concat(openTags(state.doc, tree).map((tag, i) => ({ label: "/" + tag, apply: "/" + tag + end,
|
||||
type: "type", boost: 99 - i }))),
|
||||
validFor: /^\/?[:\-\.\w\u00b7-\uffff]*$/ };
|
||||
}
|
||||
function completeCloseTag(state, tree, from, to) {
|
||||
let end = /\s*>/.test(state.sliceDoc(to, to + 5)) ? "" : ">";
|
||||
return { from, to,
|
||||
options: openTags(state.doc, tree).map((tag, i) => ({ label: tag, apply: tag + end, type: "type", boost: 99 - i })),
|
||||
validFor: identifier };
|
||||
}
|
||||
function completeStartTag(state, schema, tree, pos) {
|
||||
let options = [], level = 0;
|
||||
for (let tagName of allowedChildren(state.doc, tree, schema))
|
||||
options.push({ label: "<" + tagName, type: "type" });
|
||||
for (let open of openTags(state.doc, tree))
|
||||
options.push({ label: "</" + open + ">", type: "type", boost: 99 - level++ });
|
||||
return { from: pos, to: pos, options, validFor: /^<\/?[:\-\.\w\u00b7-\uffff]*$/ };
|
||||
}
|
||||
function completeAttrName(state, schema, tree, from, to) {
|
||||
let elt = findParentElement(tree), info = elt ? schema.tags[elementName(state.doc, elt)] : null;
|
||||
let localAttrs = info && info.attrs ? Object.keys(info.attrs) : [];
|
||||
let names = info && info.globalAttrs === false ? localAttrs
|
||||
: localAttrs.length ? localAttrs.concat(schema.globalAttrNames) : schema.globalAttrNames;
|
||||
return { from, to,
|
||||
options: names.map(attrName => ({ label: attrName, type: "property" })),
|
||||
validFor: identifier };
|
||||
}
|
||||
function completeAttrValue(state, schema, tree, from, to) {
|
||||
var _a;
|
||||
let nameNode = (_a = tree.parent) === null || _a === void 0 ? void 0 : _a.getChild("AttributeName");
|
||||
let options = [], token = undefined;
|
||||
if (nameNode) {
|
||||
let attrName = state.sliceDoc(nameNode.from, nameNode.to);
|
||||
let attrs = schema.globalAttrs[attrName];
|
||||
if (!attrs) {
|
||||
let elt = findParentElement(tree), info = elt ? schema.tags[elementName(state.doc, elt)] : null;
|
||||
attrs = (info === null || info === void 0 ? void 0 : info.attrs) && info.attrs[attrName];
|
||||
}
|
||||
if (attrs) {
|
||||
let base = state.sliceDoc(from, to).toLowerCase(), quoteStart = '"', quoteEnd = '"';
|
||||
if (/^['"]/.test(base)) {
|
||||
token = base[0] == '"' ? /^[^"]*$/ : /^[^']*$/;
|
||||
quoteStart = "";
|
||||
quoteEnd = state.sliceDoc(to, to + 1) == base[0] ? "" : base[0];
|
||||
base = base.slice(1);
|
||||
from++;
|
||||
}
|
||||
else {
|
||||
token = /^[^\s<>='"]*$/;
|
||||
}
|
||||
for (let value of attrs)
|
||||
options.push({ label: value, apply: quoteStart + value + quoteEnd, type: "constant" });
|
||||
}
|
||||
}
|
||||
return { from, to, options, validFor: token };
|
||||
}
|
||||
function htmlCompletionFor(schema, context) {
|
||||
let { state, pos } = context, tree = syntaxTree(state).resolveInner(pos, -1), around = tree.resolve(pos);
|
||||
for (let scan = pos, before; around == tree && (before = tree.childBefore(scan));) {
|
||||
let last = before.lastChild;
|
||||
if (!last || !last.type.isError || last.from < last.to)
|
||||
break;
|
||||
around = tree = before;
|
||||
scan = last.from;
|
||||
}
|
||||
if (tree.name == "TagName") {
|
||||
return tree.parent && /CloseTag$/.test(tree.parent.name) ? completeCloseTag(state, tree, tree.from, pos)
|
||||
: completeTag(state, schema, tree, tree.from, pos);
|
||||
}
|
||||
else if (tree.name == "StartTag") {
|
||||
return completeTag(state, schema, tree, pos, pos);
|
||||
}
|
||||
else if (tree.name == "StartCloseTag" || tree.name == "IncompleteCloseTag") {
|
||||
return completeCloseTag(state, tree, pos, pos);
|
||||
}
|
||||
else if (context.explicit && (tree.name == "OpenTag" || tree.name == "SelfClosingTag") || tree.name == "AttributeName") {
|
||||
return completeAttrName(state, schema, tree, tree.name == "AttributeName" ? tree.from : pos, pos);
|
||||
}
|
||||
else if (tree.name == "Is" || tree.name == "AttributeValue" || tree.name == "UnquotedAttributeValue") {
|
||||
return completeAttrValue(state, schema, tree, tree.name == "Is" ? pos : tree.from, pos);
|
||||
}
|
||||
else if (context.explicit && (around.name == "Element" || around.name == "Text" || around.name == "Document")) {
|
||||
return completeStartTag(state, schema, tree, pos);
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
/**
|
||||
HTML tag completion. Opens and closes tags and attributes in a
|
||||
context-aware way.
|
||||
*/
|
||||
function htmlCompletionSource(context) {
|
||||
return htmlCompletionFor(Schema.default, context);
|
||||
}
|
||||
/**
|
||||
Create a completion source for HTML extended with additional tags
|
||||
or attributes.
|
||||
*/
|
||||
function htmlCompletionSourceWith(config) {
|
||||
let { extraTags, extraGlobalAttributes: extraAttrs } = config;
|
||||
let schema = extraAttrs || extraTags ? new Schema(extraTags, extraAttrs) : Schema.default;
|
||||
return (context) => htmlCompletionFor(schema, context);
|
||||
}
|
||||
|
||||
const jsonParser = /*@__PURE__*/javascriptLanguage.parser.configure({ top: "SingleExpression" });
|
||||
const defaultNesting = [
|
||||
{ tag: "script",
|
||||
attrs: attrs => attrs.type == "text/typescript" || attrs.lang == "ts",
|
||||
parser: typescriptLanguage.parser },
|
||||
{ tag: "script",
|
||||
attrs: attrs => attrs.type == "text/babel" || attrs.type == "text/jsx",
|
||||
parser: jsxLanguage.parser },
|
||||
{ tag: "script",
|
||||
attrs: attrs => attrs.type == "text/typescript-jsx",
|
||||
parser: tsxLanguage.parser },
|
||||
{ tag: "script",
|
||||
attrs: attrs => attrs.type == "importmap" || attrs.type == "speculationrules",
|
||||
parser: jsonParser },
|
||||
{ tag: "script",
|
||||
attrs(attrs) {
|
||||
return !attrs.type || /^(?:text|application)\/(?:x-)?(?:java|ecma)script$|^module$|^$/i.test(attrs.type);
|
||||
},
|
||||
parser: javascriptLanguage.parser },
|
||||
{ tag: "style",
|
||||
attrs(attrs) {
|
||||
return (!attrs.lang || attrs.lang == "css") && (!attrs.type || /^(text\/)?(x-)?(stylesheet|css)$/i.test(attrs.type));
|
||||
},
|
||||
parser: cssLanguage.parser }
|
||||
];
|
||||
const defaultAttrs = /*@__PURE__*/[
|
||||
{ name: "style",
|
||||
parser: /*@__PURE__*/cssLanguage.parser.configure({ top: "Styles" }) }
|
||||
].concat(/*@__PURE__*/eventAttributes.map(name => ({ name, parser: javascriptLanguage.parser })));
|
||||
/**
|
||||
A language provider based on the [Lezer HTML
|
||||
parser](https://github.com/lezer-parser/html), extended with the
|
||||
JavaScript and CSS parsers to parse the content of `<script>` and
|
||||
`<style>` tags.
|
||||
*/
|
||||
const htmlPlain = /*@__PURE__*/LRLanguage.define({
|
||||
name: "html",
|
||||
parser: /*@__PURE__*/parser.configure({
|
||||
props: [
|
||||
/*@__PURE__*/indentNodeProp.add({
|
||||
Element(context) {
|
||||
let after = /^(\s*)(<\/)?/.exec(context.textAfter);
|
||||
if (context.node.to <= context.pos + after[0].length)
|
||||
return context.continue();
|
||||
return context.lineIndent(context.node.from) + (after[2] ? 0 : context.unit);
|
||||
},
|
||||
"OpenTag CloseTag SelfClosingTag"(context) {
|
||||
return context.column(context.node.from) + context.unit;
|
||||
},
|
||||
Document(context) {
|
||||
if (context.pos + /\s*/.exec(context.textAfter)[0].length < context.node.to)
|
||||
return context.continue();
|
||||
let endElt = null, close;
|
||||
for (let cur = context.node;;) {
|
||||
let last = cur.lastChild;
|
||||
if (!last || last.name != "Element" || last.to != cur.to)
|
||||
break;
|
||||
endElt = cur = last;
|
||||
}
|
||||
if (endElt && !((close = endElt.lastChild) && (close.name == "CloseTag" || close.name == "SelfClosingTag")))
|
||||
return context.lineIndent(endElt.from) + context.unit;
|
||||
return null;
|
||||
}
|
||||
}),
|
||||
/*@__PURE__*/foldNodeProp.add({
|
||||
Element(node) {
|
||||
let first = node.firstChild, last = node.lastChild;
|
||||
if (!first || first.name != "OpenTag")
|
||||
return null;
|
||||
return { from: first.to, to: last.name == "CloseTag" ? last.from : node.to };
|
||||
}
|
||||
}),
|
||||
/*@__PURE__*/bracketMatchingHandle.add({
|
||||
"OpenTag CloseTag": node => node.getChild("TagName")
|
||||
})
|
||||
]
|
||||
}),
|
||||
languageData: {
|
||||
commentTokens: { block: { open: "<!--", close: "-->" } },
|
||||
indentOnInput: /^\s*<\/\w+\W$/,
|
||||
wordChars: "-._"
|
||||
}
|
||||
});
|
||||
/**
|
||||
A language provider based on the [Lezer HTML
|
||||
parser](https://github.com/lezer-parser/html), extended with the
|
||||
JavaScript and CSS parsers to parse the content of `<script>` and
|
||||
`<style>` tags.
|
||||
*/
|
||||
const htmlLanguage = /*@__PURE__*/htmlPlain.configure({
|
||||
wrap: /*@__PURE__*/configureNesting(defaultNesting, defaultAttrs)
|
||||
});
|
||||
/**
|
||||
Language support for HTML, including
|
||||
[`htmlCompletion`](https://codemirror.net/6/docs/ref/#lang-html.htmlCompletion) and JavaScript and
|
||||
CSS support extensions.
|
||||
*/
|
||||
function html(config = {}) {
|
||||
let dialect = "", wrap;
|
||||
if (config.matchClosingTags === false)
|
||||
dialect = "noMatch";
|
||||
if (config.selfClosingTags === true)
|
||||
dialect = (dialect ? dialect + " " : "") + "selfClosing";
|
||||
if (config.nestedLanguages && config.nestedLanguages.length ||
|
||||
config.nestedAttributes && config.nestedAttributes.length)
|
||||
wrap = configureNesting((config.nestedLanguages || []).concat(defaultNesting), (config.nestedAttributes || []).concat(defaultAttrs));
|
||||
let lang = wrap ? htmlPlain.configure({ wrap, dialect }) : dialect ? htmlLanguage.configure({ dialect }) : htmlLanguage;
|
||||
return new LanguageSupport(lang, [
|
||||
htmlLanguage.data.of({ autocomplete: htmlCompletionSourceWith(config) }),
|
||||
config.autoCloseTags !== false ? autoCloseTags : [],
|
||||
javascript().support,
|
||||
css().support
|
||||
]);
|
||||
}
|
||||
const selfClosers = /*@__PURE__*/new Set(/*@__PURE__*/"area base br col command embed frame hr img input keygen link meta param source track wbr menuitem".split(" "));
|
||||
/**
|
||||
Extension that will automatically insert close tags when a `>` or
|
||||
`/` is typed.
|
||||
*/
|
||||
const autoCloseTags = /*@__PURE__*/EditorView.inputHandler.of((view, from, to, text, insertTransaction) => {
|
||||
if (view.composing || view.state.readOnly || from != to || (text != ">" && text != "/") ||
|
||||
!htmlLanguage.isActiveAt(view.state, from, -1))
|
||||
return false;
|
||||
let base = insertTransaction(), { state } = base;
|
||||
let closeTags = state.changeByRange(range => {
|
||||
var _a, _b, _c;
|
||||
let didType = state.doc.sliceString(range.from - 1, range.to) == text;
|
||||
let { head } = range, around = syntaxTree(state).resolveInner(head - 1, -1), name;
|
||||
if (around.name == "TagName" || around.name == "StartTag")
|
||||
around = around.parent;
|
||||
if (didType && text == ">" && around.name == "OpenTag") {
|
||||
if (((_b = (_a = around.parent) === null || _a === void 0 ? void 0 : _a.lastChild) === null || _b === void 0 ? void 0 : _b.name) != "CloseTag" &&
|
||||
(name = elementName(state.doc, around.parent, head)) &&
|
||||
!selfClosers.has(name)) {
|
||||
let to = head + (state.doc.sliceString(head, head + 1) === ">" ? 1 : 0);
|
||||
let insert = `</${name}>`;
|
||||
return { range, changes: { from: head, to, insert } };
|
||||
}
|
||||
}
|
||||
else if (didType && text == "/" && around.name == "IncompleteCloseTag") {
|
||||
let base = around.parent;
|
||||
if (around.from == head - 2 && ((_c = base.lastChild) === null || _c === void 0 ? void 0 : _c.name) != "CloseTag" &&
|
||||
(name = elementName(state.doc, base, head)) && !selfClosers.has(name)) {
|
||||
let to = head + (state.doc.sliceString(head, head + 1) === ">" ? 1 : 0);
|
||||
let insert = `${name}>`;
|
||||
return {
|
||||
range: EditorSelection.cursor(head + insert.length, -1),
|
||||
changes: { from: head, to, insert }
|
||||
};
|
||||
}
|
||||
}
|
||||
return { range };
|
||||
});
|
||||
if (closeTags.changes.empty)
|
||||
return false;
|
||||
view.dispatch([
|
||||
base,
|
||||
state.update(closeTags, {
|
||||
userEvent: "input.complete",
|
||||
scrollIntoView: true
|
||||
})
|
||||
]);
|
||||
return true;
|
||||
});
|
||||
|
||||
export { autoCloseTags, html, htmlCompletionSource, htmlCompletionSourceWith, htmlLanguage, htmlPlain };
|
||||
1
media/vendor/codemirror/js/codemirror-lang-html.min.js
vendored
Normal file
1
media/vendor/codemirror/js/codemirror-lang-html.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
BIN
media/vendor/codemirror/js/codemirror-lang-html.min.js.gz
vendored
Normal file
BIN
media/vendor/codemirror/js/codemirror-lang-html.min.js.gz
vendored
Normal file
Binary file not shown.
496
media/vendor/codemirror/js/codemirror-lang-javascript.js
vendored
Normal file
496
media/vendor/codemirror/js/codemirror-lang-javascript.js
vendored
Normal file
@ -0,0 +1,496 @@
|
||||
import { parser } from '@lezer/javascript';
|
||||
import { syntaxTree, LRLanguage, indentNodeProp, continuedIndent, flatIndent, delimitedIndent, foldNodeProp, foldInside, sublanguageProp, LanguageSupport, defineLanguageFacet } from '@codemirror/language';
|
||||
import { EditorSelection } from '@codemirror/state';
|
||||
import { EditorView } from '@codemirror/view';
|
||||
import { snippetCompletion, ifNotIn, completeFromList } from '@codemirror/autocomplete';
|
||||
import { IterMode, NodeWeakMap } from '@lezer/common';
|
||||
|
||||
/**
|
||||
A collection of JavaScript-related
|
||||
[snippets](https://codemirror.net/6/docs/ref/#autocomplete.snippet).
|
||||
*/
|
||||
const snippets = [
|
||||
/*@__PURE__*/snippetCompletion("function ${name}(${params}) {\n\t${}\n}", {
|
||||
label: "function",
|
||||
detail: "definition",
|
||||
type: "keyword"
|
||||
}),
|
||||
/*@__PURE__*/snippetCompletion("for (let ${index} = 0; ${index} < ${bound}; ${index}++) {\n\t${}\n}", {
|
||||
label: "for",
|
||||
detail: "loop",
|
||||
type: "keyword"
|
||||
}),
|
||||
/*@__PURE__*/snippetCompletion("for (let ${name} of ${collection}) {\n\t${}\n}", {
|
||||
label: "for",
|
||||
detail: "of loop",
|
||||
type: "keyword"
|
||||
}),
|
||||
/*@__PURE__*/snippetCompletion("do {\n\t${}\n} while (${})", {
|
||||
label: "do",
|
||||
detail: "loop",
|
||||
type: "keyword"
|
||||
}),
|
||||
/*@__PURE__*/snippetCompletion("while (${}) {\n\t${}\n}", {
|
||||
label: "while",
|
||||
detail: "loop",
|
||||
type: "keyword"
|
||||
}),
|
||||
/*@__PURE__*/snippetCompletion("try {\n\t${}\n} catch (${error}) {\n\t${}\n}", {
|
||||
label: "try",
|
||||
detail: "/ catch block",
|
||||
type: "keyword"
|
||||
}),
|
||||
/*@__PURE__*/snippetCompletion("if (${}) {\n\t${}\n}", {
|
||||
label: "if",
|
||||
detail: "block",
|
||||
type: "keyword"
|
||||
}),
|
||||
/*@__PURE__*/snippetCompletion("if (${}) {\n\t${}\n} else {\n\t${}\n}", {
|
||||
label: "if",
|
||||
detail: "/ else block",
|
||||
type: "keyword"
|
||||
}),
|
||||
/*@__PURE__*/snippetCompletion("class ${name} {\n\tconstructor(${params}) {\n\t\t${}\n\t}\n}", {
|
||||
label: "class",
|
||||
detail: "definition",
|
||||
type: "keyword"
|
||||
}),
|
||||
/*@__PURE__*/snippetCompletion("import {${names}} from \"${module}\"\n${}", {
|
||||
label: "import",
|
||||
detail: "named",
|
||||
type: "keyword"
|
||||
}),
|
||||
/*@__PURE__*/snippetCompletion("import ${name} from \"${module}\"\n${}", {
|
||||
label: "import",
|
||||
detail: "default",
|
||||
type: "keyword"
|
||||
})
|
||||
];
|
||||
/**
|
||||
A collection of snippet completions for TypeScript. Includes the
|
||||
JavaScript [snippets](https://codemirror.net/6/docs/ref/#lang-javascript.snippets).
|
||||
*/
|
||||
const typescriptSnippets = /*@__PURE__*/snippets.concat([
|
||||
/*@__PURE__*/snippetCompletion("interface ${name} {\n\t${}\n}", {
|
||||
label: "interface",
|
||||
detail: "definition",
|
||||
type: "keyword"
|
||||
}),
|
||||
/*@__PURE__*/snippetCompletion("type ${name} = ${type}", {
|
||||
label: "type",
|
||||
detail: "definition",
|
||||
type: "keyword"
|
||||
}),
|
||||
/*@__PURE__*/snippetCompletion("enum ${name} {\n\t${}\n}", {
|
||||
label: "enum",
|
||||
detail: "definition",
|
||||
type: "keyword"
|
||||
})
|
||||
]);
|
||||
|
||||
const cache = /*@__PURE__*/new NodeWeakMap();
|
||||
const ScopeNodes = /*@__PURE__*/new Set([
|
||||
"Script", "Block",
|
||||
"FunctionExpression", "FunctionDeclaration", "ArrowFunction", "MethodDeclaration",
|
||||
"ForStatement"
|
||||
]);
|
||||
function defID(type) {
|
||||
return (node, def) => {
|
||||
let id = node.node.getChild("VariableDefinition");
|
||||
if (id)
|
||||
def(id, type);
|
||||
return true;
|
||||
};
|
||||
}
|
||||
const functionContext = ["FunctionDeclaration"];
|
||||
const gatherCompletions = {
|
||||
FunctionDeclaration: /*@__PURE__*/defID("function"),
|
||||
ClassDeclaration: /*@__PURE__*/defID("class"),
|
||||
ClassExpression: () => true,
|
||||
EnumDeclaration: /*@__PURE__*/defID("constant"),
|
||||
TypeAliasDeclaration: /*@__PURE__*/defID("type"),
|
||||
NamespaceDeclaration: /*@__PURE__*/defID("namespace"),
|
||||
VariableDefinition(node, def) { if (!node.matchContext(functionContext))
|
||||
def(node, "variable"); },
|
||||
TypeDefinition(node, def) { def(node, "type"); },
|
||||
__proto__: null
|
||||
};
|
||||
function getScope(doc, node) {
|
||||
let cached = cache.get(node);
|
||||
if (cached)
|
||||
return cached;
|
||||
let completions = [], top = true;
|
||||
function def(node, type) {
|
||||
let name = doc.sliceString(node.from, node.to);
|
||||
completions.push({ label: name, type });
|
||||
}
|
||||
node.cursor(IterMode.IncludeAnonymous).iterate(node => {
|
||||
if (top) {
|
||||
top = false;
|
||||
}
|
||||
else if (node.name) {
|
||||
let gather = gatherCompletions[node.name];
|
||||
if (gather && gather(node, def) || ScopeNodes.has(node.name))
|
||||
return false;
|
||||
}
|
||||
else if (node.to - node.from > 8192) {
|
||||
// Allow caching for bigger internal nodes
|
||||
for (let c of getScope(doc, node.node))
|
||||
completions.push(c);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
cache.set(node, completions);
|
||||
return completions;
|
||||
}
|
||||
const Identifier = /^[\w$\xa1-\uffff][\w$\d\xa1-\uffff]*$/;
|
||||
const dontComplete = [
|
||||
"TemplateString", "String", "RegExp",
|
||||
"LineComment", "BlockComment",
|
||||
"VariableDefinition", "TypeDefinition", "Label",
|
||||
"PropertyDefinition", "PropertyName",
|
||||
"PrivatePropertyDefinition", "PrivatePropertyName",
|
||||
".", "?."
|
||||
];
|
||||
/**
|
||||
Completion source that looks up locally defined names in
|
||||
JavaScript code.
|
||||
*/
|
||||
function localCompletionSource(context) {
|
||||
let inner = syntaxTree(context.state).resolveInner(context.pos, -1);
|
||||
if (dontComplete.indexOf(inner.name) > -1)
|
||||
return null;
|
||||
let isWord = inner.name == "VariableName" ||
|
||||
inner.to - inner.from < 20 && Identifier.test(context.state.sliceDoc(inner.from, inner.to));
|
||||
if (!isWord && !context.explicit)
|
||||
return null;
|
||||
let options = [];
|
||||
for (let pos = inner; pos; pos = pos.parent) {
|
||||
if (ScopeNodes.has(pos.name))
|
||||
options = options.concat(getScope(context.state.doc, pos));
|
||||
}
|
||||
return {
|
||||
options,
|
||||
from: isWord ? inner.from : context.pos,
|
||||
validFor: Identifier
|
||||
};
|
||||
}
|
||||
function pathFor(read, member, name) {
|
||||
var _a;
|
||||
let path = [];
|
||||
for (;;) {
|
||||
let obj = member.firstChild, prop;
|
||||
if ((obj === null || obj === void 0 ? void 0 : obj.name) == "VariableName") {
|
||||
path.push(read(obj));
|
||||
return { path: path.reverse(), name };
|
||||
}
|
||||
else if ((obj === null || obj === void 0 ? void 0 : obj.name) == "MemberExpression" && ((_a = (prop = obj.lastChild)) === null || _a === void 0 ? void 0 : _a.name) == "PropertyName") {
|
||||
path.push(read(prop));
|
||||
member = obj;
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
Helper function for defining JavaScript completion sources. It
|
||||
returns the completable name and object path for a completion
|
||||
context, or null if no name/property completion should happen at
|
||||
that position. For example, when completing after `a.b.c` it will
|
||||
return `{path: ["a", "b"], name: "c"}`. When completing after `x`
|
||||
it will return `{path: [], name: "x"}`. When not in a property or
|
||||
name, it will return null if `context.explicit` is false, and
|
||||
`{path: [], name: ""}` otherwise.
|
||||
*/
|
||||
function completionPath(context) {
|
||||
let read = (node) => context.state.doc.sliceString(node.from, node.to);
|
||||
let inner = syntaxTree(context.state).resolveInner(context.pos, -1);
|
||||
if (inner.name == "PropertyName") {
|
||||
return pathFor(read, inner.parent, read(inner));
|
||||
}
|
||||
else if ((inner.name == "." || inner.name == "?.") && inner.parent.name == "MemberExpression") {
|
||||
return pathFor(read, inner.parent, "");
|
||||
}
|
||||
else if (dontComplete.indexOf(inner.name) > -1) {
|
||||
return null;
|
||||
}
|
||||
else if (inner.name == "VariableName" || inner.to - inner.from < 20 && Identifier.test(read(inner))) {
|
||||
return { path: [], name: read(inner) };
|
||||
}
|
||||
else if (inner.name == "MemberExpression") {
|
||||
return pathFor(read, inner, "");
|
||||
}
|
||||
else {
|
||||
return context.explicit ? { path: [], name: "" } : null;
|
||||
}
|
||||
}
|
||||
function enumeratePropertyCompletions(obj, top) {
|
||||
let options = [], seen = new Set;
|
||||
for (let depth = 0;; depth++) {
|
||||
for (let name of (Object.getOwnPropertyNames || Object.keys)(obj)) {
|
||||
if (!/^[a-zA-Z_$\xaa-\uffdc][\w$\xaa-\uffdc]*$/.test(name) || seen.has(name))
|
||||
continue;
|
||||
seen.add(name);
|
||||
let value;
|
||||
try {
|
||||
value = obj[name];
|
||||
}
|
||||
catch (_) {
|
||||
continue;
|
||||
}
|
||||
options.push({
|
||||
label: name,
|
||||
type: typeof value == "function" ? (/^[A-Z]/.test(name) ? "class" : top ? "function" : "method")
|
||||
: top ? "variable" : "property",
|
||||
boost: -depth
|
||||
});
|
||||
}
|
||||
let next = Object.getPrototypeOf(obj);
|
||||
if (!next)
|
||||
return options;
|
||||
obj = next;
|
||||
}
|
||||
}
|
||||
/**
|
||||
Defines a [completion source](https://codemirror.net/6/docs/ref/#autocomplete.CompletionSource) that
|
||||
completes from the given scope object (for example `globalThis`).
|
||||
Will enter properties of the object when completing properties on
|
||||
a directly-named path.
|
||||
*/
|
||||
function scopeCompletionSource(scope) {
|
||||
let cache = new Map;
|
||||
return (context) => {
|
||||
let path = completionPath(context);
|
||||
if (!path)
|
||||
return null;
|
||||
let target = scope;
|
||||
for (let step of path.path) {
|
||||
target = target[step];
|
||||
if (!target)
|
||||
return null;
|
||||
}
|
||||
let options = cache.get(target);
|
||||
if (!options)
|
||||
cache.set(target, options = enumeratePropertyCompletions(target, !path.path.length));
|
||||
return {
|
||||
from: context.pos - path.name.length,
|
||||
options,
|
||||
validFor: Identifier
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
A language provider based on the [Lezer JavaScript
|
||||
parser](https://github.com/lezer-parser/javascript), extended with
|
||||
highlighting and indentation information.
|
||||
*/
|
||||
const javascriptLanguage = /*@__PURE__*/LRLanguage.define({
|
||||
name: "javascript",
|
||||
parser: /*@__PURE__*/parser.configure({
|
||||
props: [
|
||||
/*@__PURE__*/indentNodeProp.add({
|
||||
IfStatement: /*@__PURE__*/continuedIndent({ except: /^\s*({|else\b)/ }),
|
||||
TryStatement: /*@__PURE__*/continuedIndent({ except: /^\s*({|catch\b|finally\b)/ }),
|
||||
LabeledStatement: flatIndent,
|
||||
SwitchBody: context => {
|
||||
let after = context.textAfter, closed = /^\s*\}/.test(after), isCase = /^\s*(case|default)\b/.test(after);
|
||||
return context.baseIndent + (closed ? 0 : isCase ? 1 : 2) * context.unit;
|
||||
},
|
||||
Block: /*@__PURE__*/delimitedIndent({ closing: "}" }),
|
||||
ArrowFunction: cx => cx.baseIndent + cx.unit,
|
||||
"TemplateString BlockComment": () => null,
|
||||
"Statement Property": /*@__PURE__*/continuedIndent({ except: /^{/ }),
|
||||
JSXElement(context) {
|
||||
let closed = /^\s*<\//.test(context.textAfter);
|
||||
return context.lineIndent(context.node.from) + (closed ? 0 : context.unit);
|
||||
},
|
||||
JSXEscape(context) {
|
||||
let closed = /\s*\}/.test(context.textAfter);
|
||||
return context.lineIndent(context.node.from) + (closed ? 0 : context.unit);
|
||||
},
|
||||
"JSXOpenTag JSXSelfClosingTag"(context) {
|
||||
return context.column(context.node.from) + context.unit;
|
||||
}
|
||||
}),
|
||||
/*@__PURE__*/foldNodeProp.add({
|
||||
"Block ClassBody SwitchBody EnumBody ObjectExpression ArrayExpression ObjectType": foldInside,
|
||||
BlockComment(tree) { return { from: tree.from + 2, to: tree.to - 2 }; }
|
||||
})
|
||||
]
|
||||
}),
|
||||
languageData: {
|
||||
closeBrackets: { brackets: ["(", "[", "{", "'", '"', "`"] },
|
||||
commentTokens: { line: "//", block: { open: "/*", close: "*/" } },
|
||||
indentOnInput: /^\s*(?:case |default:|\{|\}|<\/)$/,
|
||||
wordChars: "$"
|
||||
}
|
||||
});
|
||||
const jsxSublanguage = {
|
||||
test: node => /^JSX/.test(node.name),
|
||||
facet: /*@__PURE__*/defineLanguageFacet({ commentTokens: { block: { open: "{/*", close: "*/}" } } })
|
||||
};
|
||||
/**
|
||||
A language provider for TypeScript.
|
||||
*/
|
||||
const typescriptLanguage = /*@__PURE__*/javascriptLanguage.configure({ dialect: "ts" }, "typescript");
|
||||
/**
|
||||
Language provider for JSX.
|
||||
*/
|
||||
const jsxLanguage = /*@__PURE__*/javascriptLanguage.configure({
|
||||
dialect: "jsx",
|
||||
props: [/*@__PURE__*/sublanguageProp.add(n => n.isTop ? [jsxSublanguage] : undefined)]
|
||||
});
|
||||
/**
|
||||
Language provider for JSX + TypeScript.
|
||||
*/
|
||||
const tsxLanguage = /*@__PURE__*/javascriptLanguage.configure({
|
||||
dialect: "jsx ts",
|
||||
props: [/*@__PURE__*/sublanguageProp.add(n => n.isTop ? [jsxSublanguage] : undefined)]
|
||||
}, "typescript");
|
||||
let kwCompletion = (name) => ({ label: name, type: "keyword" });
|
||||
const keywords = /*@__PURE__*/"break case const continue default delete export extends false finally in instanceof let new return static super switch this throw true typeof var yield".split(" ").map(kwCompletion);
|
||||
const typescriptKeywords = /*@__PURE__*/keywords.concat(/*@__PURE__*/["declare", "implements", "private", "protected", "public"].map(kwCompletion));
|
||||
/**
|
||||
JavaScript support. Includes [snippet](https://codemirror.net/6/docs/ref/#lang-javascript.snippets)
|
||||
completion.
|
||||
*/
|
||||
function javascript(config = {}) {
|
||||
let lang = config.jsx ? (config.typescript ? tsxLanguage : jsxLanguage)
|
||||
: config.typescript ? typescriptLanguage : javascriptLanguage;
|
||||
let completions = config.typescript ? typescriptSnippets.concat(typescriptKeywords) : snippets.concat(keywords);
|
||||
return new LanguageSupport(lang, [
|
||||
javascriptLanguage.data.of({
|
||||
autocomplete: ifNotIn(dontComplete, completeFromList(completions))
|
||||
}),
|
||||
javascriptLanguage.data.of({
|
||||
autocomplete: localCompletionSource
|
||||
}),
|
||||
config.jsx ? autoCloseTags : [],
|
||||
]);
|
||||
}
|
||||
function findOpenTag(node) {
|
||||
for (;;) {
|
||||
if (node.name == "JSXOpenTag" || node.name == "JSXSelfClosingTag" || node.name == "JSXFragmentTag")
|
||||
return node;
|
||||
if (node.name == "JSXEscape" || !node.parent)
|
||||
return null;
|
||||
node = node.parent;
|
||||
}
|
||||
}
|
||||
function elementName(doc, tree, max = doc.length) {
|
||||
for (let ch = tree === null || tree === void 0 ? void 0 : tree.firstChild; ch; ch = ch.nextSibling) {
|
||||
if (ch.name == "JSXIdentifier" || ch.name == "JSXBuiltin" || ch.name == "JSXNamespacedName" ||
|
||||
ch.name == "JSXMemberExpression")
|
||||
return doc.sliceString(ch.from, Math.min(ch.to, max));
|
||||
}
|
||||
return "";
|
||||
}
|
||||
const android = typeof navigator == "object" && /*@__PURE__*//Android\b/.test(navigator.userAgent);
|
||||
/**
|
||||
Extension that will automatically insert JSX close tags when a `>` or
|
||||
`/` is typed.
|
||||
*/
|
||||
const autoCloseTags = /*@__PURE__*/EditorView.inputHandler.of((view, from, to, text, defaultInsert) => {
|
||||
if ((android ? view.composing : view.compositionStarted) || view.state.readOnly ||
|
||||
from != to || (text != ">" && text != "/") ||
|
||||
!javascriptLanguage.isActiveAt(view.state, from, -1))
|
||||
return false;
|
||||
let base = defaultInsert(), { state } = base;
|
||||
let closeTags = state.changeByRange(range => {
|
||||
var _a;
|
||||
let { head } = range, around = syntaxTree(state).resolveInner(head - 1, -1), name;
|
||||
if (around.name == "JSXStartTag")
|
||||
around = around.parent;
|
||||
if (state.doc.sliceString(head - 1, head) != text || around.name == "JSXAttributeValue" && around.to > head) ;
|
||||
else if (text == ">" && around.name == "JSXFragmentTag") {
|
||||
return { range, changes: { from: head, insert: `</>` } };
|
||||
}
|
||||
else if (text == "/" && around.name == "JSXStartCloseTag") {
|
||||
let empty = around.parent, base = empty.parent;
|
||||
if (base && empty.from == head - 2 &&
|
||||
((name = elementName(state.doc, base.firstChild, head)) || ((_a = base.firstChild) === null || _a === void 0 ? void 0 : _a.name) == "JSXFragmentTag")) {
|
||||
let insert = `${name}>`;
|
||||
return { range: EditorSelection.cursor(head + insert.length, -1), changes: { from: head, insert } };
|
||||
}
|
||||
}
|
||||
else if (text == ">") {
|
||||
let openTag = findOpenTag(around);
|
||||
if (openTag &&
|
||||
!/^\/?>|^<\//.test(state.doc.sliceString(head, head + 2)) &&
|
||||
(name = elementName(state.doc, openTag, head)))
|
||||
return { range, changes: { from: head, insert: `</${name}>` } };
|
||||
}
|
||||
return { range };
|
||||
});
|
||||
if (closeTags.changes.empty)
|
||||
return false;
|
||||
view.dispatch([
|
||||
base,
|
||||
state.update(closeTags, { userEvent: "input.complete", scrollIntoView: true })
|
||||
]);
|
||||
return true;
|
||||
});
|
||||
|
||||
/**
|
||||
Connects an [ESLint](https://eslint.org/) linter to CodeMirror's
|
||||
[lint](https://codemirror.net/6/docs/ref/#lint) integration. `eslint` should be an instance of the
|
||||
[`Linter`](https://eslint.org/docs/developer-guide/nodejs-api#linter)
|
||||
class, and `config` an optional ESLint configuration. The return
|
||||
value of this function can be passed to [`linter`](https://codemirror.net/6/docs/ref/#lint.linter)
|
||||
to create a JavaScript linting extension.
|
||||
|
||||
Note that ESLint targets node, and is tricky to run in the
|
||||
browser. The
|
||||
[eslint-linter-browserify](https://github.com/UziTech/eslint-linter-browserify)
|
||||
package may help with that (see
|
||||
[example](https://github.com/UziTech/eslint-linter-browserify/blob/master/example/script.js)).
|
||||
*/
|
||||
function esLint(eslint, config) {
|
||||
if (!config) {
|
||||
config = {
|
||||
parserOptions: { ecmaVersion: 2019, sourceType: "module" },
|
||||
env: { browser: true, node: true, es6: true, es2015: true, es2017: true, es2020: true },
|
||||
rules: {}
|
||||
};
|
||||
eslint.getRules().forEach((desc, name) => {
|
||||
if (desc.meta.docs.recommended)
|
||||
config.rules[name] = 2;
|
||||
});
|
||||
}
|
||||
return (view) => {
|
||||
let { state } = view, found = [];
|
||||
for (let { from, to } of javascriptLanguage.findRegions(state)) {
|
||||
let fromLine = state.doc.lineAt(from), offset = { line: fromLine.number - 1, col: from - fromLine.from, pos: from };
|
||||
for (let d of eslint.verify(state.sliceDoc(from, to), config))
|
||||
found.push(translateDiagnostic(d, state.doc, offset));
|
||||
}
|
||||
return found;
|
||||
};
|
||||
}
|
||||
function mapPos(line, col, doc, offset) {
|
||||
return doc.line(line + offset.line).from + col + (line == 1 ? offset.col - 1 : -1);
|
||||
}
|
||||
function translateDiagnostic(input, doc, offset) {
|
||||
let start = mapPos(input.line, input.column, doc, offset);
|
||||
let result = {
|
||||
from: start,
|
||||
to: input.endLine != null && input.endColumn != 1 ? mapPos(input.endLine, input.endColumn, doc, offset) : start,
|
||||
message: input.message,
|
||||
source: input.ruleId ? "eslint:" + input.ruleId : "eslint",
|
||||
severity: input.severity == 1 ? "warning" : "error",
|
||||
};
|
||||
if (input.fix) {
|
||||
let { range, text } = input.fix, from = range[0] + offset.pos - start, to = range[1] + offset.pos - start;
|
||||
result.actions = [{
|
||||
name: "fix",
|
||||
apply(view, start) {
|
||||
view.dispatch({ changes: { from: start + from, to: start + to, insert: text }, scrollIntoView: true });
|
||||
}
|
||||
}];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export { autoCloseTags, completionPath, esLint, javascript, javascriptLanguage, jsxLanguage, localCompletionSource, scopeCompletionSource, snippets, tsxLanguage, typescriptLanguage, typescriptSnippets };
|
||||
1
media/vendor/codemirror/js/codemirror-lang-javascript.min.js
vendored
Normal file
1
media/vendor/codemirror/js/codemirror-lang-javascript.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
BIN
media/vendor/codemirror/js/codemirror-lang-javascript.min.js.gz
vendored
Normal file
BIN
media/vendor/codemirror/js/codemirror-lang-javascript.min.js.gz
vendored
Normal file
Binary file not shown.
64
media/vendor/codemirror/js/codemirror-lang-json.js
vendored
Normal file
64
media/vendor/codemirror/js/codemirror-lang-json.js
vendored
Normal file
@ -0,0 +1,64 @@
|
||||
import { parser } from '@lezer/json';
|
||||
import { LRLanguage, indentNodeProp, continuedIndent, foldNodeProp, foldInside, LanguageSupport } from '@codemirror/language';
|
||||
|
||||
/**
|
||||
Calls
|
||||
[`JSON.parse`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse)
|
||||
on the document and, if that throws an error, reports it as a
|
||||
single diagnostic.
|
||||
*/
|
||||
const jsonParseLinter = () => (view) => {
|
||||
try {
|
||||
JSON.parse(view.state.doc.toString());
|
||||
}
|
||||
catch (e) {
|
||||
if (!(e instanceof SyntaxError))
|
||||
throw e;
|
||||
const pos = getErrorPosition(e, view.state.doc);
|
||||
return [{
|
||||
from: pos,
|
||||
message: e.message,
|
||||
severity: 'error',
|
||||
to: pos
|
||||
}];
|
||||
}
|
||||
return [];
|
||||
};
|
||||
function getErrorPosition(error, doc) {
|
||||
let m;
|
||||
if (m = error.message.match(/at position (\d+)/))
|
||||
return Math.min(+m[1], doc.length);
|
||||
if (m = error.message.match(/at line (\d+) column (\d+)/))
|
||||
return Math.min(doc.line(+m[1]).from + (+m[2]) - 1, doc.length);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
A language provider that provides JSON parsing.
|
||||
*/
|
||||
const jsonLanguage = /*@__PURE__*/LRLanguage.define({
|
||||
name: "json",
|
||||
parser: /*@__PURE__*/parser.configure({
|
||||
props: [
|
||||
/*@__PURE__*/indentNodeProp.add({
|
||||
Object: /*@__PURE__*/continuedIndent({ except: /^\s*\}/ }),
|
||||
Array: /*@__PURE__*/continuedIndent({ except: /^\s*\]/ })
|
||||
}),
|
||||
/*@__PURE__*/foldNodeProp.add({
|
||||
"Object Array": foldInside
|
||||
})
|
||||
]
|
||||
}),
|
||||
languageData: {
|
||||
closeBrackets: { brackets: ["[", "{", '"'] },
|
||||
indentOnInput: /^\s*[\}\]]$/
|
||||
}
|
||||
});
|
||||
/**
|
||||
JSON language support.
|
||||
*/
|
||||
function json() {
|
||||
return new LanguageSupport(jsonLanguage);
|
||||
}
|
||||
|
||||
export { json, jsonLanguage, jsonParseLinter };
|
||||
1
media/vendor/codemirror/js/codemirror-lang-json.min.js
vendored
Normal file
1
media/vendor/codemirror/js/codemirror-lang-json.min.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
import{parser}from"@lezer/json";import{LRLanguage,indentNodeProp,continuedIndent,foldNodeProp,foldInside,LanguageSupport}from"@codemirror/language";const jsonParseLinter=()=>e=>{try{JSON.parse(e.state.doc.toString())}catch(n){if(!(n instanceof SyntaxError))throw n;const o=getErrorPosition(n,e.state.doc);return[{from:o,message:n.message,severity:"error",to:o}]}return[]};function getErrorPosition(e,n){let o;return(o=e.message.match(/at position (\d+)/))?Math.min(+o[1],n.length):(o=e.message.match(/at line (\d+) column (\d+)/))?Math.min(n.line(+o[1]).from+ +o[2]-1,n.length):0}const jsonLanguage=LRLanguage.define({name:"json",parser:parser.configure({props:[indentNodeProp.add({Object:continuedIndent({except:/^\s*\}/}),Array:continuedIndent({except:/^\s*\]/})}),foldNodeProp.add({"Object Array":foldInside})]}),languageData:{closeBrackets:{brackets:["[","{",'"']},indentOnInput:/^\s*[\}\]]$/}});function json(){return new LanguageSupport(jsonLanguage)}export{json,jsonLanguage,jsonParseLinter};
|
||||
BIN
media/vendor/codemirror/js/codemirror-lang-json.min.js.gz
vendored
Normal file
BIN
media/vendor/codemirror/js/codemirror-lang-json.min.js.gz
vendored
Normal file
Binary file not shown.
395
media/vendor/codemirror/js/codemirror-lang-markdown.js
vendored
Normal file
395
media/vendor/codemirror/js/codemirror-lang-markdown.js
vendored
Normal file
@ -0,0 +1,395 @@
|
||||
import { EditorSelection, Prec, EditorState } from '@codemirror/state';
|
||||
import { keymap } from '@codemirror/view';
|
||||
import { syntaxTree, LanguageSupport, Language, defineLanguageFacet, foldNodeProp, indentNodeProp, languageDataProp, foldService, LanguageDescription, ParseContext } from '@codemirror/language';
|
||||
import { CompletionContext } from '@codemirror/autocomplete';
|
||||
import { MarkdownParser, parseCode, parser, GFM, Subscript, Superscript, Emoji } from '@lezer/markdown';
|
||||
import { htmlCompletionSource, html } from '@codemirror/lang-html';
|
||||
import { NodeProp } from '@lezer/common';
|
||||
|
||||
const data = /*@__PURE__*/defineLanguageFacet({ commentTokens: { block: { open: "<!--", close: "-->" } } });
|
||||
const headingProp = /*@__PURE__*/new NodeProp();
|
||||
const commonmark = /*@__PURE__*/parser.configure({
|
||||
props: [
|
||||
/*@__PURE__*/foldNodeProp.add(type => {
|
||||
return !type.is("Block") || type.is("Document") || isHeading(type) != null ? undefined
|
||||
: (tree, state) => ({ from: state.doc.lineAt(tree.from).to, to: tree.to });
|
||||
}),
|
||||
/*@__PURE__*/headingProp.add(isHeading),
|
||||
/*@__PURE__*/indentNodeProp.add({
|
||||
Document: () => null
|
||||
}),
|
||||
/*@__PURE__*/languageDataProp.add({
|
||||
Document: data
|
||||
})
|
||||
]
|
||||
});
|
||||
function isHeading(type) {
|
||||
let match = /^(?:ATX|Setext)Heading(\d)$/.exec(type.name);
|
||||
return match ? +match[1] : undefined;
|
||||
}
|
||||
function findSectionEnd(headerNode, level) {
|
||||
let last = headerNode;
|
||||
for (;;) {
|
||||
let next = last.nextSibling, heading;
|
||||
if (!next || (heading = isHeading(next.type)) != null && heading <= level)
|
||||
break;
|
||||
last = next;
|
||||
}
|
||||
return last.to;
|
||||
}
|
||||
const headerIndent = /*@__PURE__*/foldService.of((state, start, end) => {
|
||||
for (let node = syntaxTree(state).resolveInner(end, -1); node; node = node.parent) {
|
||||
if (node.from < start)
|
||||
break;
|
||||
let heading = node.type.prop(headingProp);
|
||||
if (heading == null)
|
||||
continue;
|
||||
let upto = findSectionEnd(node, heading);
|
||||
if (upto > end)
|
||||
return { from: end, to: upto };
|
||||
}
|
||||
return null;
|
||||
});
|
||||
function mkLang(parser) {
|
||||
return new Language(data, parser, [headerIndent], "markdown");
|
||||
}
|
||||
/**
|
||||
Language support for strict CommonMark.
|
||||
*/
|
||||
const commonmarkLanguage = /*@__PURE__*/mkLang(commonmark);
|
||||
const extended = /*@__PURE__*/commonmark.configure([GFM, Subscript, Superscript, Emoji]);
|
||||
/**
|
||||
Language support for [GFM](https://github.github.com/gfm/) plus
|
||||
subscript, superscript, and emoji syntax.
|
||||
*/
|
||||
const markdownLanguage = /*@__PURE__*/mkLang(extended);
|
||||
function getCodeParser(languages, defaultLanguage) {
|
||||
return (info) => {
|
||||
if (info && languages) {
|
||||
let found = null;
|
||||
// Strip anything after whitespace
|
||||
info = /\S*/.exec(info)[0];
|
||||
if (typeof languages == "function")
|
||||
found = languages(info);
|
||||
else
|
||||
found = LanguageDescription.matchLanguageName(languages, info, true);
|
||||
if (found instanceof LanguageDescription)
|
||||
return found.support ? found.support.language.parser : ParseContext.getSkippingParser(found.load());
|
||||
else if (found)
|
||||
return found.parser;
|
||||
}
|
||||
return defaultLanguage ? defaultLanguage.parser : null;
|
||||
};
|
||||
}
|
||||
|
||||
class Context {
|
||||
constructor(node, from, to, spaceBefore, spaceAfter, type, item) {
|
||||
this.node = node;
|
||||
this.from = from;
|
||||
this.to = to;
|
||||
this.spaceBefore = spaceBefore;
|
||||
this.spaceAfter = spaceAfter;
|
||||
this.type = type;
|
||||
this.item = item;
|
||||
}
|
||||
blank(maxWidth, trailing = true) {
|
||||
let result = this.spaceBefore + (this.node.name == "Blockquote" ? ">" : "");
|
||||
if (maxWidth != null) {
|
||||
while (result.length < maxWidth)
|
||||
result += " ";
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
for (let i = this.to - this.from - result.length - this.spaceAfter.length; i > 0; i--)
|
||||
result += " ";
|
||||
return result + (trailing ? this.spaceAfter : "");
|
||||
}
|
||||
}
|
||||
marker(doc, add) {
|
||||
let number = this.node.name == "OrderedList" ? String((+itemNumber(this.item, doc)[2] + add)) : "";
|
||||
return this.spaceBefore + number + this.type + this.spaceAfter;
|
||||
}
|
||||
}
|
||||
function getContext(node, doc) {
|
||||
let nodes = [];
|
||||
for (let cur = node; cur && cur.name != "Document"; cur = cur.parent) {
|
||||
if (cur.name == "ListItem" || cur.name == "Blockquote" || cur.name == "FencedCode")
|
||||
nodes.push(cur);
|
||||
}
|
||||
let context = [];
|
||||
for (let i = nodes.length - 1; i >= 0; i--) {
|
||||
let node = nodes[i], match;
|
||||
let line = doc.lineAt(node.from), startPos = node.from - line.from;
|
||||
if (node.name == "FencedCode") {
|
||||
context.push(new Context(node, startPos, startPos, "", "", "", null));
|
||||
}
|
||||
else if (node.name == "Blockquote" && (match = /^[ \t]*>( ?)/.exec(line.text.slice(startPos)))) {
|
||||
context.push(new Context(node, startPos, startPos + match[0].length, "", match[1], ">", null));
|
||||
}
|
||||
else if (node.name == "ListItem" && node.parent.name == "OrderedList" &&
|
||||
(match = /^([ \t]*)\d+([.)])([ \t]*)/.exec(line.text.slice(startPos)))) {
|
||||
let after = match[3], len = match[0].length;
|
||||
if (after.length >= 4) {
|
||||
after = after.slice(0, after.length - 4);
|
||||
len -= 4;
|
||||
}
|
||||
context.push(new Context(node.parent, startPos, startPos + len, match[1], after, match[2], node));
|
||||
}
|
||||
else if (node.name == "ListItem" && node.parent.name == "BulletList" &&
|
||||
(match = /^([ \t]*)([-+*])([ \t]{1,4}\[[ xX]\])?([ \t]+)/.exec(line.text.slice(startPos)))) {
|
||||
let after = match[4], len = match[0].length;
|
||||
if (after.length > 4) {
|
||||
after = after.slice(0, after.length - 4);
|
||||
len -= 4;
|
||||
}
|
||||
let type = match[2];
|
||||
if (match[3])
|
||||
type += match[3].replace(/[xX]/, ' ');
|
||||
context.push(new Context(node.parent, startPos, startPos + len, match[1], after, type, node));
|
||||
}
|
||||
}
|
||||
return context;
|
||||
}
|
||||
function itemNumber(item, doc) {
|
||||
return /^(\s*)(\d+)(?=[.)])/.exec(doc.sliceString(item.from, item.from + 10));
|
||||
}
|
||||
function renumberList(after, doc, changes, offset = 0) {
|
||||
for (let prev = -1, node = after;;) {
|
||||
if (node.name == "ListItem") {
|
||||
let m = itemNumber(node, doc);
|
||||
let number = +m[2];
|
||||
if (prev >= 0) {
|
||||
if (number != prev + 1)
|
||||
return;
|
||||
changes.push({ from: node.from + m[1].length, to: node.from + m[0].length, insert: String(prev + 2 + offset) });
|
||||
}
|
||||
prev = number;
|
||||
}
|
||||
let next = node.nextSibling;
|
||||
if (!next)
|
||||
break;
|
||||
node = next;
|
||||
}
|
||||
}
|
||||
/**
|
||||
This command, when invoked in Markdown context with cursor
|
||||
selection(s), will create a new line with the markup for
|
||||
blockquotes and lists that were active on the old line. If the
|
||||
cursor was directly after the end of the markup for the old line,
|
||||
trailing whitespace and list markers are removed from that line.
|
||||
|
||||
The command does nothing in non-Markdown context, so it should
|
||||
not be used as the only binding for Enter (even in a Markdown
|
||||
document, HTML and code regions might use a different language).
|
||||
*/
|
||||
const insertNewlineContinueMarkup = ({ state, dispatch }) => {
|
||||
let tree = syntaxTree(state), { doc } = state;
|
||||
let dont = null, changes = state.changeByRange(range => {
|
||||
if (!range.empty || !markdownLanguage.isActiveAt(state, range.from))
|
||||
return dont = { range };
|
||||
let pos = range.from, line = doc.lineAt(pos);
|
||||
let context = getContext(tree.resolveInner(pos, -1), doc);
|
||||
while (context.length && context[context.length - 1].from > pos - line.from)
|
||||
context.pop();
|
||||
if (!context.length)
|
||||
return dont = { range };
|
||||
let inner = context[context.length - 1];
|
||||
if (inner.to - inner.spaceAfter.length > pos - line.from)
|
||||
return dont = { range };
|
||||
let emptyLine = pos >= (inner.to - inner.spaceAfter.length) && !/\S/.test(line.text.slice(inner.to));
|
||||
// Empty line in list
|
||||
if (inner.item && emptyLine) {
|
||||
// First list item or blank line before: delete a level of markup
|
||||
if (inner.node.firstChild.to >= pos ||
|
||||
line.from > 0 && !/[^\s>]/.test(doc.lineAt(line.from - 1).text)) {
|
||||
let next = context.length > 1 ? context[context.length - 2] : null;
|
||||
let delTo, insert = "";
|
||||
if (next && next.item) { // Re-add marker for the list at the next level
|
||||
delTo = line.from + next.from;
|
||||
insert = next.marker(doc, 1);
|
||||
}
|
||||
else {
|
||||
delTo = line.from + (next ? next.to : 0);
|
||||
}
|
||||
let changes = [{ from: delTo, to: pos, insert }];
|
||||
if (inner.node.name == "OrderedList")
|
||||
renumberList(inner.item, doc, changes, -2);
|
||||
if (next && next.node.name == "OrderedList")
|
||||
renumberList(next.item, doc, changes);
|
||||
return { range: EditorSelection.cursor(delTo + insert.length), changes };
|
||||
}
|
||||
else { // Move this line down
|
||||
let insert = "";
|
||||
for (let i = 0, e = context.length - 2; i <= e; i++) {
|
||||
insert += context[i].blank(i < e ? context[i + 1].from - insert.length : null, i < e);
|
||||
}
|
||||
insert += state.lineBreak;
|
||||
return { range: EditorSelection.cursor(pos + insert.length), changes: { from: line.from, insert } };
|
||||
}
|
||||
}
|
||||
if (inner.node.name == "Blockquote" && emptyLine && line.from) {
|
||||
let prevLine = doc.lineAt(line.from - 1), quoted = />\s*$/.exec(prevLine.text);
|
||||
// Two aligned empty quoted lines in a row
|
||||
if (quoted && quoted.index == inner.from) {
|
||||
let changes = state.changes([{ from: prevLine.from + quoted.index, to: prevLine.to },
|
||||
{ from: line.from + inner.from, to: line.to }]);
|
||||
return { range: range.map(changes), changes };
|
||||
}
|
||||
}
|
||||
let changes = [];
|
||||
if (inner.node.name == "OrderedList")
|
||||
renumberList(inner.item, doc, changes);
|
||||
let continued = inner.item && inner.item.from < line.from;
|
||||
let insert = "";
|
||||
// If not dedented
|
||||
if (!continued || /^[\s\d.)\-+*>]*/.exec(line.text)[0].length >= inner.to) {
|
||||
for (let i = 0, e = context.length - 1; i <= e; i++) {
|
||||
insert += i == e && !continued ? context[i].marker(doc, 1)
|
||||
: context[i].blank(i < e ? context[i + 1].from - insert.length : null);
|
||||
}
|
||||
}
|
||||
let from = pos;
|
||||
while (from > line.from && /\s/.test(line.text.charAt(from - line.from - 1)))
|
||||
from--;
|
||||
insert = state.lineBreak + insert;
|
||||
changes.push({ from, to: pos, insert });
|
||||
return { range: EditorSelection.cursor(from + insert.length), changes };
|
||||
});
|
||||
if (dont)
|
||||
return false;
|
||||
dispatch(state.update(changes, { scrollIntoView: true, userEvent: "input" }));
|
||||
return true;
|
||||
};
|
||||
function isMark(node) {
|
||||
return node.name == "QuoteMark" || node.name == "ListMark";
|
||||
}
|
||||
function contextNodeForDelete(tree, pos) {
|
||||
let node = tree.resolveInner(pos, -1), scan = pos;
|
||||
if (isMark(node)) {
|
||||
scan = node.from;
|
||||
node = node.parent;
|
||||
}
|
||||
for (let prev; prev = node.childBefore(scan);) {
|
||||
if (isMark(prev)) {
|
||||
scan = prev.from;
|
||||
}
|
||||
else if (prev.name == "OrderedList" || prev.name == "BulletList") {
|
||||
node = prev.lastChild;
|
||||
scan = node.to;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return node;
|
||||
}
|
||||
/**
|
||||
This command will, when invoked in a Markdown context with the
|
||||
cursor directly after list or blockquote markup, delete one level
|
||||
of markup. When the markup is for a list, it will be replaced by
|
||||
spaces on the first invocation (a further invocation will delete
|
||||
the spaces), to make it easy to continue a list.
|
||||
|
||||
When not after Markdown block markup, this command will return
|
||||
false, so it is intended to be bound alongside other deletion
|
||||
commands, with a higher precedence than the more generic commands.
|
||||
*/
|
||||
const deleteMarkupBackward = ({ state, dispatch }) => {
|
||||
let tree = syntaxTree(state);
|
||||
let dont = null, changes = state.changeByRange(range => {
|
||||
let pos = range.from, { doc } = state;
|
||||
if (range.empty && markdownLanguage.isActiveAt(state, range.from)) {
|
||||
let line = doc.lineAt(pos);
|
||||
let context = getContext(contextNodeForDelete(tree, pos), doc);
|
||||
if (context.length) {
|
||||
let inner = context[context.length - 1];
|
||||
let spaceEnd = inner.to - inner.spaceAfter.length + (inner.spaceAfter ? 1 : 0);
|
||||
// Delete extra trailing space after markup
|
||||
if (pos - line.from > spaceEnd && !/\S/.test(line.text.slice(spaceEnd, pos - line.from)))
|
||||
return { range: EditorSelection.cursor(line.from + spaceEnd),
|
||||
changes: { from: line.from + spaceEnd, to: pos } };
|
||||
if (pos - line.from == spaceEnd &&
|
||||
// Only apply this if we're on the line that has the
|
||||
// construct's syntax, or there's only indentation in the
|
||||
// target range
|
||||
(!inner.item || line.from <= inner.item.from || !/\S/.test(line.text.slice(0, inner.to)))) {
|
||||
let start = line.from + inner.from;
|
||||
// Replace a list item marker with blank space
|
||||
if (inner.item && inner.node.from < inner.item.from && /\S/.test(line.text.slice(inner.from, inner.to)))
|
||||
return { range, changes: { from: start, to: line.from + inner.to, insert: inner.blank(inner.to - inner.from) } };
|
||||
// Delete one level of indentation
|
||||
if (start < pos)
|
||||
return { range: EditorSelection.cursor(start), changes: { from: start, to: pos } };
|
||||
}
|
||||
}
|
||||
}
|
||||
return dont = { range };
|
||||
});
|
||||
if (dont)
|
||||
return false;
|
||||
dispatch(state.update(changes, { scrollIntoView: true, userEvent: "delete" }));
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
A small keymap with Markdown-specific bindings. Binds Enter to
|
||||
[`insertNewlineContinueMarkup`](https://codemirror.net/6/docs/ref/#lang-markdown.insertNewlineContinueMarkup)
|
||||
and Backspace to
|
||||
[`deleteMarkupBackward`](https://codemirror.net/6/docs/ref/#lang-markdown.deleteMarkupBackward).
|
||||
*/
|
||||
const markdownKeymap = [
|
||||
{ key: "Enter", run: insertNewlineContinueMarkup },
|
||||
{ key: "Backspace", run: deleteMarkupBackward }
|
||||
];
|
||||
const htmlNoMatch = /*@__PURE__*/html({ matchClosingTags: false });
|
||||
/**
|
||||
Markdown language support.
|
||||
*/
|
||||
function markdown(config = {}) {
|
||||
let { codeLanguages, defaultCodeLanguage, addKeymap = true, base: { parser } = commonmarkLanguage, completeHTMLTags = true } = config;
|
||||
if (!(parser instanceof MarkdownParser))
|
||||
throw new RangeError("Base parser provided to `markdown` should be a Markdown parser");
|
||||
let extensions = config.extensions ? [config.extensions] : [];
|
||||
let support = [htmlNoMatch.support], defaultCode;
|
||||
if (defaultCodeLanguage instanceof LanguageSupport) {
|
||||
support.push(defaultCodeLanguage.support);
|
||||
defaultCode = defaultCodeLanguage.language;
|
||||
}
|
||||
else if (defaultCodeLanguage) {
|
||||
defaultCode = defaultCodeLanguage;
|
||||
}
|
||||
let codeParser = codeLanguages || defaultCode ? getCodeParser(codeLanguages, defaultCode) : undefined;
|
||||
extensions.push(parseCode({ codeParser, htmlParser: htmlNoMatch.language.parser }));
|
||||
if (addKeymap)
|
||||
support.push(Prec.high(keymap.of(markdownKeymap)));
|
||||
let lang = mkLang(parser.configure(extensions));
|
||||
if (completeHTMLTags)
|
||||
support.push(lang.data.of({ autocomplete: htmlTagCompletion }));
|
||||
return new LanguageSupport(lang, support);
|
||||
}
|
||||
function htmlTagCompletion(context) {
|
||||
let { state, pos } = context, m = /<[:\-\.\w\u00b7-\uffff]*$/.exec(state.sliceDoc(pos - 25, pos));
|
||||
if (!m)
|
||||
return null;
|
||||
let tree = syntaxTree(state).resolveInner(pos, -1);
|
||||
while (tree && !tree.type.isTop) {
|
||||
if (tree.name == "CodeBlock" || tree.name == "FencedCode" || tree.name == "ProcessingInstructionBlock" ||
|
||||
tree.name == "CommentBlock" || tree.name == "Link" || tree.name == "Image")
|
||||
return null;
|
||||
tree = tree.parent;
|
||||
}
|
||||
return {
|
||||
from: pos - m[0].length, to: pos,
|
||||
options: htmlTagCompletions(),
|
||||
validFor: /^<[:\-\.\w\u00b7-\uffff]*$/
|
||||
};
|
||||
}
|
||||
let _tagCompletions = null;
|
||||
function htmlTagCompletions() {
|
||||
if (_tagCompletions)
|
||||
return _tagCompletions;
|
||||
let result = htmlCompletionSource(new CompletionContext(EditorState.create({ extensions: htmlNoMatch }), 0, true));
|
||||
return _tagCompletions = result ? result.options : [];
|
||||
}
|
||||
|
||||
export { commonmarkLanguage, deleteMarkupBackward, insertNewlineContinueMarkup, markdown, markdownKeymap, markdownLanguage };
|
||||
1
media/vendor/codemirror/js/codemirror-lang-markdown.min.js
vendored
Normal file
1
media/vendor/codemirror/js/codemirror-lang-markdown.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
BIN
media/vendor/codemirror/js/codemirror-lang-markdown.min.js.gz
vendored
Normal file
BIN
media/vendor/codemirror/js/codemirror-lang-markdown.min.js.gz
vendored
Normal file
Binary file not shown.
69
media/vendor/codemirror/js/codemirror-lang-php.js
vendored
Normal file
69
media/vendor/codemirror/js/codemirror-lang-php.js
vendored
Normal file
@ -0,0 +1,69 @@
|
||||
import { parser } from '@lezer/php';
|
||||
import { parseMixed } from '@lezer/common';
|
||||
import { html } from '@codemirror/lang-html';
|
||||
import { LRLanguage, indentNodeProp, continuedIndent, delimitedIndent, foldNodeProp, foldInside, LanguageSupport } from '@codemirror/language';
|
||||
|
||||
/**
|
||||
A language provider based on the [Lezer PHP
|
||||
parser](https://github.com/lezer-parser/php), extended with
|
||||
highlighting and indentation information.
|
||||
*/
|
||||
const phpLanguage = /*@__PURE__*/LRLanguage.define({
|
||||
name: "php",
|
||||
parser: /*@__PURE__*/parser.configure({
|
||||
props: [
|
||||
/*@__PURE__*/indentNodeProp.add({
|
||||
IfStatement: /*@__PURE__*/continuedIndent({ except: /^\s*({|else\b|elseif\b|endif\b)/ }),
|
||||
TryStatement: /*@__PURE__*/continuedIndent({ except: /^\s*({|catch\b|finally\b)/ }),
|
||||
SwitchBody: context => {
|
||||
let after = context.textAfter, closed = /^\s*\}/.test(after), isCase = /^\s*(case|default)\b/.test(after);
|
||||
return context.baseIndent + (closed ? 0 : isCase ? 1 : 2) * context.unit;
|
||||
},
|
||||
ColonBlock: cx => cx.baseIndent + cx.unit,
|
||||
"Block EnumBody DeclarationList": /*@__PURE__*/delimitedIndent({ closing: "}" }),
|
||||
ArrowFunction: cx => cx.baseIndent + cx.unit,
|
||||
"String BlockComment": () => null,
|
||||
Statement: /*@__PURE__*/continuedIndent({ except: /^({|end(for|foreach|switch|while)\b)/ })
|
||||
}),
|
||||
/*@__PURE__*/foldNodeProp.add({
|
||||
"Block EnumBody DeclarationList SwitchBody ArrayExpression ValueList": foldInside,
|
||||
ColonBlock(tree) { return { from: tree.from + 1, to: tree.to }; },
|
||||
BlockComment(tree) { return { from: tree.from + 2, to: tree.to - 2 }; }
|
||||
})
|
||||
]
|
||||
}),
|
||||
languageData: {
|
||||
commentTokens: { block: { open: "/*", close: "*/" }, line: "//" },
|
||||
indentOnInput: /^\s*(?:case |default:|end(?:if|for(?:each)?|switch|while)|else(?:if)?|\{|\})$/,
|
||||
wordChars: "$",
|
||||
closeBrackets: { stringPrefixes: ["b", "B"] }
|
||||
}
|
||||
});
|
||||
/**
|
||||
PHP language support.
|
||||
*/
|
||||
function php(config = {}) {
|
||||
let support = [], base;
|
||||
if (config.baseLanguage === null) ;
|
||||
else if (config.baseLanguage) {
|
||||
base = config.baseLanguage;
|
||||
}
|
||||
else {
|
||||
let htmlSupport = html({ matchClosingTags: false });
|
||||
support.push(htmlSupport.support);
|
||||
base = htmlSupport.language;
|
||||
}
|
||||
return new LanguageSupport(phpLanguage.configure({
|
||||
wrap: base && parseMixed(node => {
|
||||
if (!node.type.isTop)
|
||||
return null;
|
||||
return {
|
||||
parser: base.parser,
|
||||
overlay: node => node.name == "Text"
|
||||
};
|
||||
}),
|
||||
top: config.plain ? "Program" : "Template"
|
||||
}), support);
|
||||
}
|
||||
|
||||
export { php, phpLanguage };
|
||||
1
media/vendor/codemirror/js/codemirror-lang-php.min.js
vendored
Normal file
1
media/vendor/codemirror/js/codemirror-lang-php.min.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
import{parser}from"@lezer/php";import{parseMixed}from"@lezer/common";import{html}from"@codemirror/lang-html";import{LRLanguage,indentNodeProp,continuedIndent,delimitedIndent,foldNodeProp,foldInside,LanguageSupport}from"@codemirror/language";const phpLanguage=LRLanguage.define({name:"php",parser:parser.configure({props:[indentNodeProp.add({IfStatement:continuedIndent({except:/^\s*({|else\b|elseif\b|endif\b)/}),TryStatement:continuedIndent({except:/^\s*({|catch\b|finally\b)/}),SwitchBody:e=>{let n=e.textAfter,t=/^\s*\}/.test(n),o=/^\s*(case|default)\b/.test(n);return e.baseIndent+(t?0:o?1:2)*e.unit},ColonBlock:e=>e.baseIndent+e.unit,"Block EnumBody DeclarationList":delimitedIndent({closing:"}"}),ArrowFunction:e=>e.baseIndent+e.unit,"String BlockComment":()=>null,Statement:continuedIndent({except:/^({|end(for|foreach|switch|while)\b)/})}),foldNodeProp.add({"Block EnumBody DeclarationList SwitchBody ArrayExpression ValueList":foldInside,ColonBlock:e=>({from:e.from+1,to:e.to}),BlockComment:e=>({from:e.from+2,to:e.to-2})})]}),languageData:{commentTokens:{block:{open:"/*",close:"*/"},line:"//"},indentOnInput:/^\s*(?:case |default:|end(?:if|for(?:each)?|switch|while)|else(?:if)?|\{|\})$/,wordChars:"$",closeBrackets:{stringPrefixes:["b","B"]}}});function php(e={}){let n,t=[];if(null===e.baseLanguage);else if(e.baseLanguage)n=e.baseLanguage;else{let e=html({matchClosingTags:!1});t.push(e.support),n=e.language}return new LanguageSupport(phpLanguage.configure({wrap:n&&parseMixed((e=>e.type.isTop?{parser:n.parser,overlay:e=>"Text"==e.name}:null)),top:e.plain?"Program":"Template"}),t)}export{php,phpLanguage};
|
||||
BIN
media/vendor/codemirror/js/codemirror-lang-php.min.js.gz
vendored
Normal file
BIN
media/vendor/codemirror/js/codemirror-lang-php.min.js.gz
vendored
Normal file
Binary file not shown.
249
media/vendor/codemirror/js/codemirror-lang-xml.js
vendored
Normal file
249
media/vendor/codemirror/js/codemirror-lang-xml.js
vendored
Normal file
@ -0,0 +1,249 @@
|
||||
import { parser } from '@lezer/xml';
|
||||
import { LRLanguage, indentNodeProp, foldNodeProp, bracketMatchingHandle, LanguageSupport, syntaxTree } from '@codemirror/language';
|
||||
|
||||
function tagName(doc, tag) {
|
||||
let name = tag && tag.getChild("TagName");
|
||||
return name ? doc.sliceString(name.from, name.to) : "";
|
||||
}
|
||||
function elementName(doc, tree) {
|
||||
let tag = tree && tree.firstChild;
|
||||
return !tag || tag.name != "OpenTag" ? "" : tagName(doc, tag);
|
||||
}
|
||||
function attrName(doc, tag, pos) {
|
||||
let attr = tag && tag.getChildren("Attribute").find(a => a.from <= pos && a.to >= pos);
|
||||
let name = attr && attr.getChild("AttributeName");
|
||||
return name ? doc.sliceString(name.from, name.to) : "";
|
||||
}
|
||||
function findParentElement(tree) {
|
||||
for (let cur = tree && tree.parent; cur; cur = cur.parent)
|
||||
if (cur.name == "Element")
|
||||
return cur;
|
||||
return null;
|
||||
}
|
||||
function findLocation(state, pos) {
|
||||
var _a;
|
||||
let at = syntaxTree(state).resolveInner(pos, -1), inTag = null;
|
||||
for (let cur = at; !inTag && cur.parent; cur = cur.parent)
|
||||
if (cur.name == "OpenTag" || cur.name == "CloseTag" || cur.name == "SelfClosingTag" || cur.name == "MismatchedCloseTag")
|
||||
inTag = cur;
|
||||
if (inTag && (inTag.to > pos || inTag.lastChild.type.isError)) {
|
||||
let elt = inTag.parent;
|
||||
if (at.name == "TagName")
|
||||
return inTag.name == "CloseTag" || inTag.name == "MismatchedCloseTag"
|
||||
? { type: "closeTag", from: at.from, context: elt }
|
||||
: { type: "openTag", from: at.from, context: findParentElement(elt) };
|
||||
if (at.name == "AttributeName")
|
||||
return { type: "attrName", from: at.from, context: inTag };
|
||||
if (at.name == "AttributeValue")
|
||||
return { type: "attrValue", from: at.from, context: inTag };
|
||||
let before = at == inTag || at.name == "Attribute" ? at.childBefore(pos) : at;
|
||||
if ((before === null || before === void 0 ? void 0 : before.name) == "StartTag")
|
||||
return { type: "openTag", from: pos, context: findParentElement(elt) };
|
||||
if ((before === null || before === void 0 ? void 0 : before.name) == "StartCloseTag" && before.to <= pos)
|
||||
return { type: "closeTag", from: pos, context: elt };
|
||||
if ((before === null || before === void 0 ? void 0 : before.name) == "Is")
|
||||
return { type: "attrValue", from: pos, context: inTag };
|
||||
if (before)
|
||||
return { type: "attrName", from: pos, context: inTag };
|
||||
return null;
|
||||
}
|
||||
else if (at.name == "StartCloseTag") {
|
||||
return { type: "closeTag", from: pos, context: at.parent };
|
||||
}
|
||||
while (at.parent && at.to == pos && !((_a = at.lastChild) === null || _a === void 0 ? void 0 : _a.type.isError))
|
||||
at = at.parent;
|
||||
if (at.name == "Element" || at.name == "Text" || at.name == "Document")
|
||||
return { type: "tag", from: pos, context: at.name == "Element" ? at : findParentElement(at) };
|
||||
return null;
|
||||
}
|
||||
class Element {
|
||||
constructor(spec, attrs, attrValues) {
|
||||
this.attrs = attrs;
|
||||
this.attrValues = attrValues;
|
||||
this.children = [];
|
||||
this.name = spec.name;
|
||||
this.completion = Object.assign(Object.assign({ type: "type" }, spec.completion || {}), { label: this.name });
|
||||
this.openCompletion = Object.assign(Object.assign({}, this.completion), { label: "<" + this.name });
|
||||
this.closeCompletion = Object.assign(Object.assign({}, this.completion), { label: "</" + this.name + ">", boost: 2 });
|
||||
this.closeNameCompletion = Object.assign(Object.assign({}, this.completion), { label: this.name + ">" });
|
||||
this.text = spec.textContent ? spec.textContent.map(s => ({ label: s, type: "text" })) : [];
|
||||
}
|
||||
}
|
||||
const Identifier = /^[:\-\.\w\u00b7-\uffff]*$/;
|
||||
function attrCompletion(spec) {
|
||||
return Object.assign(Object.assign({ type: "property" }, spec.completion || {}), { label: spec.name });
|
||||
}
|
||||
function valueCompletion(spec) {
|
||||
return typeof spec == "string" ? { label: `"${spec}"`, type: "constant" }
|
||||
: /^"/.test(spec.label) ? spec
|
||||
: Object.assign(Object.assign({}, spec), { label: `"${spec.label}"` });
|
||||
}
|
||||
/**
|
||||
Create a completion source for the given schema.
|
||||
*/
|
||||
function completeFromSchema(eltSpecs, attrSpecs) {
|
||||
let allAttrs = [], globalAttrs = [];
|
||||
let attrValues = Object.create(null);
|
||||
for (let s of attrSpecs) {
|
||||
let completion = attrCompletion(s);
|
||||
allAttrs.push(completion);
|
||||
if (s.global)
|
||||
globalAttrs.push(completion);
|
||||
if (s.values)
|
||||
attrValues[s.name] = s.values.map(valueCompletion);
|
||||
}
|
||||
let allElements = [], topElements = [];
|
||||
let byName = Object.create(null);
|
||||
for (let s of eltSpecs) {
|
||||
let attrs = globalAttrs, attrVals = attrValues;
|
||||
if (s.attributes)
|
||||
attrs = attrs.concat(s.attributes.map(s => {
|
||||
if (typeof s == "string")
|
||||
return allAttrs.find(a => a.label == s) || { label: s, type: "property" };
|
||||
if (s.values) {
|
||||
if (attrVals == attrValues)
|
||||
attrVals = Object.create(attrVals);
|
||||
attrVals[s.name] = s.values.map(valueCompletion);
|
||||
}
|
||||
return attrCompletion(s);
|
||||
}));
|
||||
let elt = new Element(s, attrs, attrVals);
|
||||
byName[elt.name] = elt;
|
||||
allElements.push(elt);
|
||||
if (s.top)
|
||||
topElements.push(elt);
|
||||
}
|
||||
if (!topElements.length)
|
||||
topElements = allElements;
|
||||
for (let i = 0; i < allElements.length; i++) {
|
||||
let s = eltSpecs[i], elt = allElements[i];
|
||||
if (s.children) {
|
||||
for (let ch of s.children)
|
||||
if (byName[ch])
|
||||
elt.children.push(byName[ch]);
|
||||
}
|
||||
else {
|
||||
elt.children = allElements;
|
||||
}
|
||||
}
|
||||
return cx => {
|
||||
var _a;
|
||||
let { doc } = cx.state, loc = findLocation(cx.state, cx.pos);
|
||||
if (!loc || (loc.type == "tag" && !cx.explicit))
|
||||
return null;
|
||||
let { type, from, context } = loc;
|
||||
if (type == "openTag") {
|
||||
let children = topElements;
|
||||
let parentName = elementName(doc, context);
|
||||
if (parentName) {
|
||||
let parent = byName[parentName];
|
||||
children = (parent === null || parent === void 0 ? void 0 : parent.children) || allElements;
|
||||
}
|
||||
return {
|
||||
from,
|
||||
options: children.map(ch => ch.completion),
|
||||
validFor: Identifier
|
||||
};
|
||||
}
|
||||
else if (type == "closeTag") {
|
||||
let parentName = elementName(doc, context);
|
||||
return parentName ? {
|
||||
from,
|
||||
to: cx.pos + (doc.sliceString(cx.pos, cx.pos + 1) == ">" ? 1 : 0),
|
||||
options: [((_a = byName[parentName]) === null || _a === void 0 ? void 0 : _a.closeNameCompletion) || { label: parentName + ">", type: "type" }],
|
||||
validFor: Identifier
|
||||
} : null;
|
||||
}
|
||||
else if (type == "attrName") {
|
||||
let parent = byName[tagName(doc, context)];
|
||||
return {
|
||||
from,
|
||||
options: (parent === null || parent === void 0 ? void 0 : parent.attrs) || globalAttrs,
|
||||
validFor: Identifier
|
||||
};
|
||||
}
|
||||
else if (type == "attrValue") {
|
||||
let attr = attrName(doc, context, from);
|
||||
if (!attr)
|
||||
return null;
|
||||
let parent = byName[tagName(doc, context)];
|
||||
let values = ((parent === null || parent === void 0 ? void 0 : parent.attrValues) || attrValues)[attr];
|
||||
if (!values || !values.length)
|
||||
return null;
|
||||
return {
|
||||
from,
|
||||
to: cx.pos + (doc.sliceString(cx.pos, cx.pos + 1) == '"' ? 1 : 0),
|
||||
options: values,
|
||||
validFor: /^"[^"]*"?$/
|
||||
};
|
||||
}
|
||||
else if (type == "tag") {
|
||||
let parentName = elementName(doc, context), parent = byName[parentName];
|
||||
let closing = [], last = context && context.lastChild;
|
||||
if (parentName && (!last || last.name != "CloseTag" || tagName(doc, last) != parentName))
|
||||
closing.push(parent ? parent.closeCompletion : { label: "</" + parentName + ">", type: "type", boost: 2 });
|
||||
let options = closing.concat(((parent === null || parent === void 0 ? void 0 : parent.children) || (context ? allElements : topElements)).map(e => e.openCompletion));
|
||||
if (context && (parent === null || parent === void 0 ? void 0 : parent.text.length)) {
|
||||
let openTag = context.firstChild;
|
||||
if (openTag.to > cx.pos - 20 && !/\S/.test(cx.state.sliceDoc(openTag.to, cx.pos)))
|
||||
options = options.concat(parent.text);
|
||||
}
|
||||
return {
|
||||
from,
|
||||
options,
|
||||
validFor: /^<\/?[:\-\.\w\u00b7-\uffff]*$/
|
||||
};
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
A language provider based on the [Lezer XML
|
||||
parser](https://github.com/lezer-parser/xml), extended with
|
||||
highlighting and indentation information.
|
||||
*/
|
||||
const xmlLanguage = /*@__PURE__*/LRLanguage.define({
|
||||
name: "xml",
|
||||
parser: /*@__PURE__*/parser.configure({
|
||||
props: [
|
||||
/*@__PURE__*/indentNodeProp.add({
|
||||
Element(context) {
|
||||
let closed = /^\s*<\//.test(context.textAfter);
|
||||
return context.lineIndent(context.node.from) + (closed ? 0 : context.unit);
|
||||
},
|
||||
"OpenTag CloseTag SelfClosingTag"(context) {
|
||||
return context.column(context.node.from) + context.unit;
|
||||
}
|
||||
}),
|
||||
/*@__PURE__*/foldNodeProp.add({
|
||||
Element(subtree) {
|
||||
let first = subtree.firstChild, last = subtree.lastChild;
|
||||
if (!first || first.name != "OpenTag")
|
||||
return null;
|
||||
return { from: first.to, to: last.name == "CloseTag" ? last.from : subtree.to };
|
||||
}
|
||||
}),
|
||||
/*@__PURE__*/bracketMatchingHandle.add({
|
||||
"OpenTag CloseTag": node => node.getChild("TagName")
|
||||
})
|
||||
]
|
||||
}),
|
||||
languageData: {
|
||||
commentTokens: { block: { open: "<!--", close: "-->" } },
|
||||
indentOnInput: /^\s*<\/$/
|
||||
}
|
||||
});
|
||||
/**
|
||||
XML language support. Includes schema-based autocompletion when
|
||||
configured.
|
||||
*/
|
||||
function xml(conf = {}) {
|
||||
return new LanguageSupport(xmlLanguage, xmlLanguage.data.of({
|
||||
autocomplete: completeFromSchema(conf.elements || [], conf.attributes || [])
|
||||
}));
|
||||
}
|
||||
|
||||
export { completeFromSchema, xml, xmlLanguage };
|
||||
1
media/vendor/codemirror/js/codemirror-lang-xml.min.js
vendored
Normal file
1
media/vendor/codemirror/js/codemirror-lang-xml.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
BIN
media/vendor/codemirror/js/codemirror-lang-xml.min.js.gz
vendored
Normal file
BIN
media/vendor/codemirror/js/codemirror-lang-xml.min.js.gz
vendored
Normal file
Binary file not shown.
2680
media/vendor/codemirror/js/codemirror-language.js
vendored
Normal file
2680
media/vendor/codemirror/js/codemirror-language.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
media/vendor/codemirror/js/codemirror-language.min.js
vendored
Normal file
1
media/vendor/codemirror/js/codemirror-language.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
BIN
media/vendor/codemirror/js/codemirror-language.min.js.gz
vendored
Normal file
BIN
media/vendor/codemirror/js/codemirror-language.min.js.gz
vendored
Normal file
Binary file not shown.
814
media/vendor/codemirror/js/codemirror-lint.js
vendored
Normal file
814
media/vendor/codemirror/js/codemirror-lint.js
vendored
Normal file
@ -0,0 +1,814 @@
|
||||
import { getPanel, EditorView, Decoration, hoverTooltip, showPanel, ViewPlugin, logException, gutter, showTooltip, WidgetType, GutterMarker } from '@codemirror/view';
|
||||
import { StateEffect, RangeSet, StateField, Facet, combineConfig } from '@codemirror/state';
|
||||
|
||||
function crelt() {
|
||||
var elt = arguments[0];
|
||||
if (typeof elt == "string") elt = document.createElement(elt);
|
||||
var i = 1, next = arguments[1];
|
||||
if (next && typeof next == "object" && next.nodeType == null && !Array.isArray(next)) {
|
||||
for (var name in next) if (Object.prototype.hasOwnProperty.call(next, name)) {
|
||||
var value = next[name];
|
||||
if (typeof value == "string") elt.setAttribute(name, value);
|
||||
else if (value != null) elt[name] = value;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
for (; i < arguments.length; i++) add(elt, arguments[i]);
|
||||
return elt
|
||||
}
|
||||
|
||||
function add(elt, child) {
|
||||
if (typeof child == "string") {
|
||||
elt.appendChild(document.createTextNode(child));
|
||||
} else if (child == null) ; else if (child.nodeType != null) {
|
||||
elt.appendChild(child);
|
||||
} else if (Array.isArray(child)) {
|
||||
for (var i = 0; i < child.length; i++) add(elt, child[i]);
|
||||
} else {
|
||||
throw new RangeError("Unsupported child node: " + child)
|
||||
}
|
||||
}
|
||||
|
||||
class SelectedDiagnostic {
|
||||
constructor(from, to, diagnostic) {
|
||||
this.from = from;
|
||||
this.to = to;
|
||||
this.diagnostic = diagnostic;
|
||||
}
|
||||
}
|
||||
class LintState {
|
||||
constructor(diagnostics, panel, selected) {
|
||||
this.diagnostics = diagnostics;
|
||||
this.panel = panel;
|
||||
this.selected = selected;
|
||||
}
|
||||
static init(diagnostics, panel, state) {
|
||||
// Filter the list of diagnostics for which to create markers
|
||||
let markedDiagnostics = diagnostics;
|
||||
let diagnosticFilter = state.facet(lintConfig).markerFilter;
|
||||
if (diagnosticFilter)
|
||||
markedDiagnostics = diagnosticFilter(markedDiagnostics);
|
||||
let ranges = Decoration.set(markedDiagnostics.map((d) => {
|
||||
// For zero-length ranges or ranges covering only a line break, create a widget
|
||||
return d.from == d.to || (d.from == d.to - 1 && state.doc.lineAt(d.from).to == d.from)
|
||||
? Decoration.widget({
|
||||
widget: new DiagnosticWidget(d),
|
||||
diagnostic: d
|
||||
}).range(d.from)
|
||||
: Decoration.mark({
|
||||
attributes: { class: "cm-lintRange cm-lintRange-" + d.severity + (d.markClass ? " " + d.markClass : "") },
|
||||
diagnostic: d
|
||||
}).range(d.from, d.to);
|
||||
}), true);
|
||||
return new LintState(ranges, panel, findDiagnostic(ranges));
|
||||
}
|
||||
}
|
||||
function findDiagnostic(diagnostics, diagnostic = null, after = 0) {
|
||||
let found = null;
|
||||
diagnostics.between(after, 1e9, (from, to, { spec }) => {
|
||||
if (diagnostic && spec.diagnostic != diagnostic)
|
||||
return;
|
||||
found = new SelectedDiagnostic(from, to, spec.diagnostic);
|
||||
return false;
|
||||
});
|
||||
return found;
|
||||
}
|
||||
function hideTooltip(tr, tooltip) {
|
||||
let line = tr.startState.doc.lineAt(tooltip.pos);
|
||||
return !!(tr.effects.some(e => e.is(setDiagnosticsEffect)) || tr.changes.touchesRange(line.from, line.to));
|
||||
}
|
||||
function maybeEnableLint(state, effects) {
|
||||
return state.field(lintState, false) ? effects : effects.concat(StateEffect.appendConfig.of(lintExtensions));
|
||||
}
|
||||
/**
|
||||
Returns a transaction spec which updates the current set of
|
||||
diagnostics, and enables the lint extension if if wasn't already
|
||||
active.
|
||||
*/
|
||||
function setDiagnostics(state, diagnostics) {
|
||||
return {
|
||||
effects: maybeEnableLint(state, [setDiagnosticsEffect.of(diagnostics)])
|
||||
};
|
||||
}
|
||||
/**
|
||||
The state effect that updates the set of active diagnostics. Can
|
||||
be useful when writing an extension that needs to track these.
|
||||
*/
|
||||
const setDiagnosticsEffect = /*@__PURE__*/StateEffect.define();
|
||||
const togglePanel = /*@__PURE__*/StateEffect.define();
|
||||
const movePanelSelection = /*@__PURE__*/StateEffect.define();
|
||||
const lintState = /*@__PURE__*/StateField.define({
|
||||
create() {
|
||||
return new LintState(Decoration.none, null, null);
|
||||
},
|
||||
update(value, tr) {
|
||||
if (tr.docChanged) {
|
||||
let mapped = value.diagnostics.map(tr.changes), selected = null;
|
||||
if (value.selected) {
|
||||
let selPos = tr.changes.mapPos(value.selected.from, 1);
|
||||
selected = findDiagnostic(mapped, value.selected.diagnostic, selPos) || findDiagnostic(mapped, null, selPos);
|
||||
}
|
||||
value = new LintState(mapped, value.panel, selected);
|
||||
}
|
||||
for (let effect of tr.effects) {
|
||||
if (effect.is(setDiagnosticsEffect)) {
|
||||
value = LintState.init(effect.value, value.panel, tr.state);
|
||||
}
|
||||
else if (effect.is(togglePanel)) {
|
||||
value = new LintState(value.diagnostics, effect.value ? LintPanel.open : null, value.selected);
|
||||
}
|
||||
else if (effect.is(movePanelSelection)) {
|
||||
value = new LintState(value.diagnostics, value.panel, effect.value);
|
||||
}
|
||||
}
|
||||
return value;
|
||||
},
|
||||
provide: f => [showPanel.from(f, val => val.panel),
|
||||
EditorView.decorations.from(f, s => s.diagnostics)]
|
||||
});
|
||||
/**
|
||||
Returns the number of active lint diagnostics in the given state.
|
||||
*/
|
||||
function diagnosticCount(state) {
|
||||
let lint = state.field(lintState, false);
|
||||
return lint ? lint.diagnostics.size : 0;
|
||||
}
|
||||
const activeMark = /*@__PURE__*/Decoration.mark({ class: "cm-lintRange cm-lintRange-active" });
|
||||
function lintTooltip(view, pos, side) {
|
||||
let { diagnostics } = view.state.field(lintState);
|
||||
let found = [], stackStart = 2e8, stackEnd = 0;
|
||||
diagnostics.between(pos - (side < 0 ? 1 : 0), pos + (side > 0 ? 1 : 0), (from, to, { spec }) => {
|
||||
if (pos >= from && pos <= to &&
|
||||
(from == to || ((pos > from || side > 0) && (pos < to || side < 0)))) {
|
||||
found.push(spec.diagnostic);
|
||||
stackStart = Math.min(from, stackStart);
|
||||
stackEnd = Math.max(to, stackEnd);
|
||||
}
|
||||
});
|
||||
let diagnosticFilter = view.state.facet(lintConfig).tooltipFilter;
|
||||
if (diagnosticFilter)
|
||||
found = diagnosticFilter(found);
|
||||
if (!found.length)
|
||||
return null;
|
||||
return {
|
||||
pos: stackStart,
|
||||
end: stackEnd,
|
||||
above: view.state.doc.lineAt(stackStart).to < stackEnd,
|
||||
create() {
|
||||
return { dom: diagnosticsTooltip(view, found) };
|
||||
}
|
||||
};
|
||||
}
|
||||
function diagnosticsTooltip(view, diagnostics) {
|
||||
return crelt("ul", { class: "cm-tooltip-lint" }, diagnostics.map(d => renderDiagnostic(view, d, false)));
|
||||
}
|
||||
/**
|
||||
Command to open and focus the lint panel.
|
||||
*/
|
||||
const openLintPanel = (view) => {
|
||||
let field = view.state.field(lintState, false);
|
||||
if (!field || !field.panel)
|
||||
view.dispatch({ effects: maybeEnableLint(view.state, [togglePanel.of(true)]) });
|
||||
let panel = getPanel(view, LintPanel.open);
|
||||
if (panel)
|
||||
panel.dom.querySelector(".cm-panel-lint ul").focus();
|
||||
return true;
|
||||
};
|
||||
/**
|
||||
Command to close the lint panel, when open.
|
||||
*/
|
||||
const closeLintPanel = (view) => {
|
||||
let field = view.state.field(lintState, false);
|
||||
if (!field || !field.panel)
|
||||
return false;
|
||||
view.dispatch({ effects: togglePanel.of(false) });
|
||||
return true;
|
||||
};
|
||||
/**
|
||||
Move the selection to the next diagnostic.
|
||||
*/
|
||||
const nextDiagnostic = (view) => {
|
||||
let field = view.state.field(lintState, false);
|
||||
if (!field)
|
||||
return false;
|
||||
let sel = view.state.selection.main, next = field.diagnostics.iter(sel.to + 1);
|
||||
if (!next.value) {
|
||||
next = field.diagnostics.iter(0);
|
||||
if (!next.value || next.from == sel.from && next.to == sel.to)
|
||||
return false;
|
||||
}
|
||||
view.dispatch({ selection: { anchor: next.from, head: next.to }, scrollIntoView: true });
|
||||
return true;
|
||||
};
|
||||
/**
|
||||
Move the selection to the previous diagnostic.
|
||||
*/
|
||||
const previousDiagnostic = (view) => {
|
||||
let { state } = view, field = state.field(lintState, false);
|
||||
if (!field)
|
||||
return false;
|
||||
let sel = state.selection.main;
|
||||
let prevFrom, prevTo, lastFrom, lastTo;
|
||||
field.diagnostics.between(0, state.doc.length, (from, to) => {
|
||||
if (to < sel.to && (prevFrom == null || prevFrom < from)) {
|
||||
prevFrom = from;
|
||||
prevTo = to;
|
||||
}
|
||||
if (lastFrom == null || from > lastFrom) {
|
||||
lastFrom = from;
|
||||
lastTo = to;
|
||||
}
|
||||
});
|
||||
if (lastFrom == null || prevFrom == null && lastFrom == sel.from)
|
||||
return false;
|
||||
view.dispatch({ selection: { anchor: prevFrom !== null && prevFrom !== void 0 ? prevFrom : lastFrom, head: prevTo !== null && prevTo !== void 0 ? prevTo : lastTo }, scrollIntoView: true });
|
||||
return true;
|
||||
};
|
||||
/**
|
||||
A set of default key bindings for the lint functionality.
|
||||
|
||||
- Ctrl-Shift-m (Cmd-Shift-m on macOS): [`openLintPanel`](https://codemirror.net/6/docs/ref/#lint.openLintPanel)
|
||||
- F8: [`nextDiagnostic`](https://codemirror.net/6/docs/ref/#lint.nextDiagnostic)
|
||||
*/
|
||||
const lintKeymap = [
|
||||
{ key: "Mod-Shift-m", run: openLintPanel, preventDefault: true },
|
||||
{ key: "F8", run: nextDiagnostic }
|
||||
];
|
||||
const lintPlugin = /*@__PURE__*/ViewPlugin.fromClass(class {
|
||||
constructor(view) {
|
||||
this.view = view;
|
||||
this.timeout = -1;
|
||||
this.set = true;
|
||||
let { delay } = view.state.facet(lintConfig);
|
||||
this.lintTime = Date.now() + delay;
|
||||
this.run = this.run.bind(this);
|
||||
this.timeout = setTimeout(this.run, delay);
|
||||
}
|
||||
run() {
|
||||
let now = Date.now();
|
||||
if (now < this.lintTime - 10) {
|
||||
this.timeout = setTimeout(this.run, this.lintTime - now);
|
||||
}
|
||||
else {
|
||||
this.set = false;
|
||||
let { state } = this.view, { sources } = state.facet(lintConfig);
|
||||
Promise.all(sources.map(source => Promise.resolve(source(this.view)))).then(annotations => {
|
||||
let all = annotations.reduce((a, b) => a.concat(b));
|
||||
if (this.view.state.doc == state.doc)
|
||||
this.view.dispatch(setDiagnostics(this.view.state, all));
|
||||
}, error => { logException(this.view.state, error); });
|
||||
}
|
||||
}
|
||||
update(update) {
|
||||
let config = update.state.facet(lintConfig);
|
||||
if (update.docChanged || config != update.startState.facet(lintConfig) ||
|
||||
config.needsRefresh && config.needsRefresh(update)) {
|
||||
this.lintTime = Date.now() + config.delay;
|
||||
if (!this.set) {
|
||||
this.set = true;
|
||||
this.timeout = setTimeout(this.run, config.delay);
|
||||
}
|
||||
}
|
||||
}
|
||||
force() {
|
||||
if (this.set) {
|
||||
this.lintTime = Date.now();
|
||||
this.run();
|
||||
}
|
||||
}
|
||||
destroy() {
|
||||
clearTimeout(this.timeout);
|
||||
}
|
||||
});
|
||||
const lintConfig = /*@__PURE__*/Facet.define({
|
||||
combine(input) {
|
||||
return Object.assign({ sources: input.map(i => i.source) }, combineConfig(input.map(i => i.config), {
|
||||
delay: 750,
|
||||
markerFilter: null,
|
||||
tooltipFilter: null,
|
||||
needsRefresh: null
|
||||
}, {
|
||||
needsRefresh: (a, b) => !a ? b : !b ? a : u => a(u) || b(u)
|
||||
}));
|
||||
}
|
||||
});
|
||||
/**
|
||||
Given a diagnostic source, this function returns an extension that
|
||||
enables linting with that source. It will be called whenever the
|
||||
editor is idle (after its content changed).
|
||||
*/
|
||||
function linter(source, config = {}) {
|
||||
return [
|
||||
lintConfig.of({ source, config }),
|
||||
lintPlugin,
|
||||
lintExtensions
|
||||
];
|
||||
}
|
||||
/**
|
||||
Forces any linters [configured](https://codemirror.net/6/docs/ref/#lint.linter) to run when the
|
||||
editor is idle to run right away.
|
||||
*/
|
||||
function forceLinting(view) {
|
||||
let plugin = view.plugin(lintPlugin);
|
||||
if (plugin)
|
||||
plugin.force();
|
||||
}
|
||||
function assignKeys(actions) {
|
||||
let assigned = [];
|
||||
if (actions)
|
||||
actions: for (let { name } of actions) {
|
||||
for (let i = 0; i < name.length; i++) {
|
||||
let ch = name[i];
|
||||
if (/[a-zA-Z]/.test(ch) && !assigned.some(c => c.toLowerCase() == ch.toLowerCase())) {
|
||||
assigned.push(ch);
|
||||
continue actions;
|
||||
}
|
||||
}
|
||||
assigned.push("");
|
||||
}
|
||||
return assigned;
|
||||
}
|
||||
function renderDiagnostic(view, diagnostic, inPanel) {
|
||||
var _a;
|
||||
let keys = inPanel ? assignKeys(diagnostic.actions) : [];
|
||||
return crelt("li", { class: "cm-diagnostic cm-diagnostic-" + diagnostic.severity }, crelt("span", { class: "cm-diagnosticText" }, diagnostic.renderMessage ? diagnostic.renderMessage() : diagnostic.message), (_a = diagnostic.actions) === null || _a === void 0 ? void 0 : _a.map((action, i) => {
|
||||
let fired = false, click = (e) => {
|
||||
e.preventDefault();
|
||||
if (fired)
|
||||
return;
|
||||
fired = true;
|
||||
let found = findDiagnostic(view.state.field(lintState).diagnostics, diagnostic);
|
||||
if (found)
|
||||
action.apply(view, found.from, found.to);
|
||||
};
|
||||
let { name } = action, keyIndex = keys[i] ? name.indexOf(keys[i]) : -1;
|
||||
let nameElt = keyIndex < 0 ? name : [name.slice(0, keyIndex),
|
||||
crelt("u", name.slice(keyIndex, keyIndex + 1)),
|
||||
name.slice(keyIndex + 1)];
|
||||
return crelt("button", {
|
||||
type: "button",
|
||||
class: "cm-diagnosticAction",
|
||||
onclick: click,
|
||||
onmousedown: click,
|
||||
"aria-label": ` Action: ${name}${keyIndex < 0 ? "" : ` (access key "${keys[i]})"`}.`
|
||||
}, nameElt);
|
||||
}), diagnostic.source && crelt("div", { class: "cm-diagnosticSource" }, diagnostic.source));
|
||||
}
|
||||
class DiagnosticWidget extends WidgetType {
|
||||
constructor(diagnostic) {
|
||||
super();
|
||||
this.diagnostic = diagnostic;
|
||||
}
|
||||
eq(other) { return other.diagnostic == this.diagnostic; }
|
||||
toDOM() {
|
||||
return crelt("span", { class: "cm-lintPoint cm-lintPoint-" + this.diagnostic.severity });
|
||||
}
|
||||
}
|
||||
class PanelItem {
|
||||
constructor(view, diagnostic) {
|
||||
this.diagnostic = diagnostic;
|
||||
this.id = "item_" + Math.floor(Math.random() * 0xffffffff).toString(16);
|
||||
this.dom = renderDiagnostic(view, diagnostic, true);
|
||||
this.dom.id = this.id;
|
||||
this.dom.setAttribute("role", "option");
|
||||
}
|
||||
}
|
||||
class LintPanel {
|
||||
constructor(view) {
|
||||
this.view = view;
|
||||
this.items = [];
|
||||
let onkeydown = (event) => {
|
||||
if (event.keyCode == 27) { // Escape
|
||||
closeLintPanel(this.view);
|
||||
this.view.focus();
|
||||
}
|
||||
else if (event.keyCode == 38 || event.keyCode == 33) { // ArrowUp, PageUp
|
||||
this.moveSelection((this.selectedIndex - 1 + this.items.length) % this.items.length);
|
||||
}
|
||||
else if (event.keyCode == 40 || event.keyCode == 34) { // ArrowDown, PageDown
|
||||
this.moveSelection((this.selectedIndex + 1) % this.items.length);
|
||||
}
|
||||
else if (event.keyCode == 36) { // Home
|
||||
this.moveSelection(0);
|
||||
}
|
||||
else if (event.keyCode == 35) { // End
|
||||
this.moveSelection(this.items.length - 1);
|
||||
}
|
||||
else if (event.keyCode == 13) { // Enter
|
||||
this.view.focus();
|
||||
}
|
||||
else if (event.keyCode >= 65 && event.keyCode <= 90 && this.selectedIndex >= 0) { // A-Z
|
||||
let { diagnostic } = this.items[this.selectedIndex], keys = assignKeys(diagnostic.actions);
|
||||
for (let i = 0; i < keys.length; i++)
|
||||
if (keys[i].toUpperCase().charCodeAt(0) == event.keyCode) {
|
||||
let found = findDiagnostic(this.view.state.field(lintState).diagnostics, diagnostic);
|
||||
if (found)
|
||||
diagnostic.actions[i].apply(view, found.from, found.to);
|
||||
}
|
||||
}
|
||||
else {
|
||||
return;
|
||||
}
|
||||
event.preventDefault();
|
||||
};
|
||||
let onclick = (event) => {
|
||||
for (let i = 0; i < this.items.length; i++) {
|
||||
if (this.items[i].dom.contains(event.target))
|
||||
this.moveSelection(i);
|
||||
}
|
||||
};
|
||||
this.list = crelt("ul", {
|
||||
tabIndex: 0,
|
||||
role: "listbox",
|
||||
"aria-label": this.view.state.phrase("Diagnostics"),
|
||||
onkeydown,
|
||||
onclick
|
||||
});
|
||||
this.dom = crelt("div", { class: "cm-panel-lint" }, this.list, crelt("button", {
|
||||
type: "button",
|
||||
name: "close",
|
||||
"aria-label": this.view.state.phrase("close"),
|
||||
onclick: () => closeLintPanel(this.view)
|
||||
}, "×"));
|
||||
this.update();
|
||||
}
|
||||
get selectedIndex() {
|
||||
let selected = this.view.state.field(lintState).selected;
|
||||
if (!selected)
|
||||
return -1;
|
||||
for (let i = 0; i < this.items.length; i++)
|
||||
if (this.items[i].diagnostic == selected.diagnostic)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
update() {
|
||||
let { diagnostics, selected } = this.view.state.field(lintState);
|
||||
let i = 0, needsSync = false, newSelectedItem = null;
|
||||
diagnostics.between(0, this.view.state.doc.length, (_start, _end, { spec }) => {
|
||||
let found = -1, item;
|
||||
for (let j = i; j < this.items.length; j++)
|
||||
if (this.items[j].diagnostic == spec.diagnostic) {
|
||||
found = j;
|
||||
break;
|
||||
}
|
||||
if (found < 0) {
|
||||
item = new PanelItem(this.view, spec.diagnostic);
|
||||
this.items.splice(i, 0, item);
|
||||
needsSync = true;
|
||||
}
|
||||
else {
|
||||
item = this.items[found];
|
||||
if (found > i) {
|
||||
this.items.splice(i, found - i);
|
||||
needsSync = true;
|
||||
}
|
||||
}
|
||||
if (selected && item.diagnostic == selected.diagnostic) {
|
||||
if (!item.dom.hasAttribute("aria-selected")) {
|
||||
item.dom.setAttribute("aria-selected", "true");
|
||||
newSelectedItem = item;
|
||||
}
|
||||
}
|
||||
else if (item.dom.hasAttribute("aria-selected")) {
|
||||
item.dom.removeAttribute("aria-selected");
|
||||
}
|
||||
i++;
|
||||
});
|
||||
while (i < this.items.length && !(this.items.length == 1 && this.items[0].diagnostic.from < 0)) {
|
||||
needsSync = true;
|
||||
this.items.pop();
|
||||
}
|
||||
if (this.items.length == 0) {
|
||||
this.items.push(new PanelItem(this.view, {
|
||||
from: -1, to: -1,
|
||||
severity: "info",
|
||||
message: this.view.state.phrase("No diagnostics")
|
||||
}));
|
||||
needsSync = true;
|
||||
}
|
||||
if (newSelectedItem) {
|
||||
this.list.setAttribute("aria-activedescendant", newSelectedItem.id);
|
||||
this.view.requestMeasure({
|
||||
key: this,
|
||||
read: () => ({ sel: newSelectedItem.dom.getBoundingClientRect(), panel: this.list.getBoundingClientRect() }),
|
||||
write: ({ sel, panel }) => {
|
||||
if (sel.top < panel.top)
|
||||
this.list.scrollTop -= panel.top - sel.top;
|
||||
else if (sel.bottom > panel.bottom)
|
||||
this.list.scrollTop += sel.bottom - panel.bottom;
|
||||
}
|
||||
});
|
||||
}
|
||||
else if (this.selectedIndex < 0) {
|
||||
this.list.removeAttribute("aria-activedescendant");
|
||||
}
|
||||
if (needsSync)
|
||||
this.sync();
|
||||
}
|
||||
sync() {
|
||||
let domPos = this.list.firstChild;
|
||||
function rm() {
|
||||
let prev = domPos;
|
||||
domPos = prev.nextSibling;
|
||||
prev.remove();
|
||||
}
|
||||
for (let item of this.items) {
|
||||
if (item.dom.parentNode == this.list) {
|
||||
while (domPos != item.dom)
|
||||
rm();
|
||||
domPos = item.dom.nextSibling;
|
||||
}
|
||||
else {
|
||||
this.list.insertBefore(item.dom, domPos);
|
||||
}
|
||||
}
|
||||
while (domPos)
|
||||
rm();
|
||||
}
|
||||
moveSelection(selectedIndex) {
|
||||
if (this.selectedIndex < 0)
|
||||
return;
|
||||
let field = this.view.state.field(lintState);
|
||||
let selection = findDiagnostic(field.diagnostics, this.items[selectedIndex].diagnostic);
|
||||
if (!selection)
|
||||
return;
|
||||
this.view.dispatch({
|
||||
selection: { anchor: selection.from, head: selection.to },
|
||||
scrollIntoView: true,
|
||||
effects: movePanelSelection.of(selection)
|
||||
});
|
||||
}
|
||||
static open(view) { return new LintPanel(view); }
|
||||
}
|
||||
function svg(content, attrs = `viewBox="0 0 40 40"`) {
|
||||
return `url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" ${attrs}>${encodeURIComponent(content)}</svg>')`;
|
||||
}
|
||||
function underline(color) {
|
||||
return svg(`<path d="m0 2.5 l2 -1.5 l1 0 l2 1.5 l1 0" stroke="${color}" fill="none" stroke-width=".7"/>`, `width="6" height="3"`);
|
||||
}
|
||||
const baseTheme = /*@__PURE__*/EditorView.baseTheme({
|
||||
".cm-diagnostic": {
|
||||
padding: "3px 6px 3px 8px",
|
||||
marginLeft: "-1px",
|
||||
display: "block",
|
||||
whiteSpace: "pre-wrap"
|
||||
},
|
||||
".cm-diagnostic-error": { borderLeft: "5px solid #d11" },
|
||||
".cm-diagnostic-warning": { borderLeft: "5px solid orange" },
|
||||
".cm-diagnostic-info": { borderLeft: "5px solid #999" },
|
||||
".cm-diagnostic-hint": { borderLeft: "5px solid #66d" },
|
||||
".cm-diagnosticAction": {
|
||||
font: "inherit",
|
||||
border: "none",
|
||||
padding: "2px 4px",
|
||||
backgroundColor: "#444",
|
||||
color: "white",
|
||||
borderRadius: "3px",
|
||||
marginLeft: "8px",
|
||||
cursor: "pointer"
|
||||
},
|
||||
".cm-diagnosticSource": {
|
||||
fontSize: "70%",
|
||||
opacity: .7
|
||||
},
|
||||
".cm-lintRange": {
|
||||
backgroundPosition: "left bottom",
|
||||
backgroundRepeat: "repeat-x",
|
||||
paddingBottom: "0.7px",
|
||||
},
|
||||
".cm-lintRange-error": { backgroundImage: /*@__PURE__*/underline("#d11") },
|
||||
".cm-lintRange-warning": { backgroundImage: /*@__PURE__*/underline("orange") },
|
||||
".cm-lintRange-info": { backgroundImage: /*@__PURE__*/underline("#999") },
|
||||
".cm-lintRange-hint": { backgroundImage: /*@__PURE__*/underline("#66d") },
|
||||
".cm-lintRange-active": { backgroundColor: "#ffdd9980" },
|
||||
".cm-tooltip-lint": {
|
||||
padding: 0,
|
||||
margin: 0
|
||||
},
|
||||
".cm-lintPoint": {
|
||||
position: "relative",
|
||||
"&:after": {
|
||||
content: '""',
|
||||
position: "absolute",
|
||||
bottom: 0,
|
||||
left: "-2px",
|
||||
borderLeft: "3px solid transparent",
|
||||
borderRight: "3px solid transparent",
|
||||
borderBottom: "4px solid #d11"
|
||||
}
|
||||
},
|
||||
".cm-lintPoint-warning": {
|
||||
"&:after": { borderBottomColor: "orange" }
|
||||
},
|
||||
".cm-lintPoint-info": {
|
||||
"&:after": { borderBottomColor: "#999" }
|
||||
},
|
||||
".cm-lintPoint-hint": {
|
||||
"&:after": { borderBottomColor: "#66d" }
|
||||
},
|
||||
".cm-panel.cm-panel-lint": {
|
||||
position: "relative",
|
||||
"& ul": {
|
||||
maxHeight: "100px",
|
||||
overflowY: "auto",
|
||||
"& [aria-selected]": {
|
||||
backgroundColor: "#ddd",
|
||||
"& u": { textDecoration: "underline" }
|
||||
},
|
||||
"&:focus [aria-selected]": {
|
||||
background_fallback: "#bdf",
|
||||
backgroundColor: "Highlight",
|
||||
color_fallback: "white",
|
||||
color: "HighlightText"
|
||||
},
|
||||
"& u": { textDecoration: "none" },
|
||||
padding: 0,
|
||||
margin: 0
|
||||
},
|
||||
"& [name=close]": {
|
||||
position: "absolute",
|
||||
top: "0",
|
||||
right: "2px",
|
||||
background: "inherit",
|
||||
border: "none",
|
||||
font: "inherit",
|
||||
padding: 0,
|
||||
margin: 0
|
||||
}
|
||||
}
|
||||
});
|
||||
function severityWeight(sev) {
|
||||
return sev == "error" ? 4 : sev == "warning" ? 3 : sev == "info" ? 2 : 1;
|
||||
}
|
||||
class LintGutterMarker extends GutterMarker {
|
||||
constructor(diagnostics) {
|
||||
super();
|
||||
this.diagnostics = diagnostics;
|
||||
this.severity = diagnostics.reduce((max, d) => severityWeight(max) < severityWeight(d.severity) ? d.severity : max, "hint");
|
||||
}
|
||||
toDOM(view) {
|
||||
let elt = document.createElement("div");
|
||||
elt.className = "cm-lint-marker cm-lint-marker-" + this.severity;
|
||||
let diagnostics = this.diagnostics;
|
||||
let diagnosticsFilter = view.state.facet(lintGutterConfig).tooltipFilter;
|
||||
if (diagnosticsFilter)
|
||||
diagnostics = diagnosticsFilter(diagnostics);
|
||||
if (diagnostics.length)
|
||||
elt.onmouseover = () => gutterMarkerMouseOver(view, elt, diagnostics);
|
||||
return elt;
|
||||
}
|
||||
}
|
||||
function trackHoverOn(view, marker) {
|
||||
let mousemove = (event) => {
|
||||
let rect = marker.getBoundingClientRect();
|
||||
if (event.clientX > rect.left - 10 /* Hover.Margin */ && event.clientX < rect.right + 10 /* Hover.Margin */ &&
|
||||
event.clientY > rect.top - 10 /* Hover.Margin */ && event.clientY < rect.bottom + 10 /* Hover.Margin */)
|
||||
return;
|
||||
for (let target = event.target; target; target = target.parentNode) {
|
||||
if (target.nodeType == 1 && target.classList.contains("cm-tooltip-lint"))
|
||||
return;
|
||||
}
|
||||
window.removeEventListener("mousemove", mousemove);
|
||||
if (view.state.field(lintGutterTooltip))
|
||||
view.dispatch({ effects: setLintGutterTooltip.of(null) });
|
||||
};
|
||||
window.addEventListener("mousemove", mousemove);
|
||||
}
|
||||
function gutterMarkerMouseOver(view, marker, diagnostics) {
|
||||
function hovered() {
|
||||
let line = view.elementAtHeight(marker.getBoundingClientRect().top + 5 - view.documentTop);
|
||||
const linePos = view.coordsAtPos(line.from);
|
||||
if (linePos) {
|
||||
view.dispatch({ effects: setLintGutterTooltip.of({
|
||||
pos: line.from,
|
||||
above: false,
|
||||
create() {
|
||||
return {
|
||||
dom: diagnosticsTooltip(view, diagnostics),
|
||||
getCoords: () => marker.getBoundingClientRect()
|
||||
};
|
||||
}
|
||||
}) });
|
||||
}
|
||||
marker.onmouseout = marker.onmousemove = null;
|
||||
trackHoverOn(view, marker);
|
||||
}
|
||||
let { hoverTime } = view.state.facet(lintGutterConfig);
|
||||
let hoverTimeout = setTimeout(hovered, hoverTime);
|
||||
marker.onmouseout = () => {
|
||||
clearTimeout(hoverTimeout);
|
||||
marker.onmouseout = marker.onmousemove = null;
|
||||
};
|
||||
marker.onmousemove = () => {
|
||||
clearTimeout(hoverTimeout);
|
||||
hoverTimeout = setTimeout(hovered, hoverTime);
|
||||
};
|
||||
}
|
||||
function markersForDiagnostics(doc, diagnostics) {
|
||||
let byLine = Object.create(null);
|
||||
for (let diagnostic of diagnostics) {
|
||||
let line = doc.lineAt(diagnostic.from);
|
||||
(byLine[line.from] || (byLine[line.from] = [])).push(diagnostic);
|
||||
}
|
||||
let markers = [];
|
||||
for (let line in byLine) {
|
||||
markers.push(new LintGutterMarker(byLine[line]).range(+line));
|
||||
}
|
||||
return RangeSet.of(markers, true);
|
||||
}
|
||||
const lintGutterExtension = /*@__PURE__*/gutter({
|
||||
class: "cm-gutter-lint",
|
||||
markers: view => view.state.field(lintGutterMarkers),
|
||||
});
|
||||
const lintGutterMarkers = /*@__PURE__*/StateField.define({
|
||||
create() {
|
||||
return RangeSet.empty;
|
||||
},
|
||||
update(markers, tr) {
|
||||
markers = markers.map(tr.changes);
|
||||
let diagnosticFilter = tr.state.facet(lintGutterConfig).markerFilter;
|
||||
for (let effect of tr.effects) {
|
||||
if (effect.is(setDiagnosticsEffect)) {
|
||||
let diagnostics = effect.value;
|
||||
if (diagnosticFilter)
|
||||
diagnostics = diagnosticFilter(diagnostics || []);
|
||||
markers = markersForDiagnostics(tr.state.doc, diagnostics.slice(0));
|
||||
}
|
||||
}
|
||||
return markers;
|
||||
}
|
||||
});
|
||||
const setLintGutterTooltip = /*@__PURE__*/StateEffect.define();
|
||||
const lintGutterTooltip = /*@__PURE__*/StateField.define({
|
||||
create() { return null; },
|
||||
update(tooltip, tr) {
|
||||
if (tooltip && tr.docChanged)
|
||||
tooltip = hideTooltip(tr, tooltip) ? null : Object.assign(Object.assign({}, tooltip), { pos: tr.changes.mapPos(tooltip.pos) });
|
||||
return tr.effects.reduce((t, e) => e.is(setLintGutterTooltip) ? e.value : t, tooltip);
|
||||
},
|
||||
provide: field => showTooltip.from(field)
|
||||
});
|
||||
const lintGutterTheme = /*@__PURE__*/EditorView.baseTheme({
|
||||
".cm-gutter-lint": {
|
||||
width: "1.4em",
|
||||
"& .cm-gutterElement": {
|
||||
padding: ".2em"
|
||||
}
|
||||
},
|
||||
".cm-lint-marker": {
|
||||
width: "1em",
|
||||
height: "1em"
|
||||
},
|
||||
".cm-lint-marker-info": {
|
||||
content: /*@__PURE__*/svg(`<path fill="#aaf" stroke="#77e" stroke-width="6" stroke-linejoin="round" d="M5 5L35 5L35 35L5 35Z"/>`)
|
||||
},
|
||||
".cm-lint-marker-warning": {
|
||||
content: /*@__PURE__*/svg(`<path fill="#fe8" stroke="#fd7" stroke-width="6" stroke-linejoin="round" d="M20 6L37 35L3 35Z"/>`),
|
||||
},
|
||||
".cm-lint-marker-error": {
|
||||
content: /*@__PURE__*/svg(`<circle cx="20" cy="20" r="15" fill="#f87" stroke="#f43" stroke-width="6"/>`)
|
||||
},
|
||||
});
|
||||
const lintExtensions = [
|
||||
lintState,
|
||||
/*@__PURE__*/EditorView.decorations.compute([lintState], state => {
|
||||
let { selected, panel } = state.field(lintState);
|
||||
return !selected || !panel || selected.from == selected.to ? Decoration.none : Decoration.set([
|
||||
activeMark.range(selected.from, selected.to)
|
||||
]);
|
||||
}),
|
||||
/*@__PURE__*/hoverTooltip(lintTooltip, { hideOn: hideTooltip }),
|
||||
baseTheme
|
||||
];
|
||||
const lintGutterConfig = /*@__PURE__*/Facet.define({
|
||||
combine(configs) {
|
||||
return combineConfig(configs, {
|
||||
hoverTime: 300 /* Hover.Time */,
|
||||
markerFilter: null,
|
||||
tooltipFilter: null
|
||||
});
|
||||
}
|
||||
});
|
||||
/**
|
||||
Returns an extension that installs a gutter showing markers for
|
||||
each line that has diagnostics, which can be hovered over to see
|
||||
the diagnostics.
|
||||
*/
|
||||
function lintGutter(config = {}) {
|
||||
return [lintGutterConfig.of(config), lintGutterMarkers, lintGutterExtension, lintGutterTheme, lintGutterTooltip];
|
||||
}
|
||||
/**
|
||||
Iterate over the marked diagnostics for the given editor state,
|
||||
calling `f` for each of them. Note that, if the document changed
|
||||
since the diagnostics were created, the `Diagnostic` object will
|
||||
hold the original outdated position, whereas the `to` and `from`
|
||||
arguments hold the diagnostic's current position.
|
||||
*/
|
||||
function forEachDiagnostic(state, f) {
|
||||
let lState = state.field(lintState, false);
|
||||
if (lState && lState.diagnostics.size)
|
||||
for (let iter = RangeSet.iter([lState.diagnostics]); iter.value; iter.next())
|
||||
f(iter.value.spec.diagnostic, iter.from, iter.to);
|
||||
}
|
||||
|
||||
export { closeLintPanel, diagnosticCount, forEachDiagnostic, forceLinting, lintGutter, lintKeymap, linter, nextDiagnostic, openLintPanel, previousDiagnostic, setDiagnostics, setDiagnosticsEffect };
|
||||
1
media/vendor/codemirror/js/codemirror-lint.min.js
vendored
Normal file
1
media/vendor/codemirror/js/codemirror-lint.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
BIN
media/vendor/codemirror/js/codemirror-lint.min.js.gz
vendored
Normal file
BIN
media/vendor/codemirror/js/codemirror-lint.min.js.gz
vendored
Normal file
Binary file not shown.
1245
media/vendor/codemirror/js/codemirror-search.js
vendored
Normal file
1245
media/vendor/codemirror/js/codemirror-search.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
media/vendor/codemirror/js/codemirror-search.min.js
vendored
Normal file
1
media/vendor/codemirror/js/codemirror-search.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
BIN
media/vendor/codemirror/js/codemirror-search.min.js.gz
vendored
Normal file
BIN
media/vendor/codemirror/js/codemirror-search.min.js.gz
vendored
Normal file
Binary file not shown.
3886
media/vendor/codemirror/js/codemirror-state.js
vendored
Normal file
3886
media/vendor/codemirror/js/codemirror-state.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
media/vendor/codemirror/js/codemirror-state.min.js
vendored
Normal file
1
media/vendor/codemirror/js/codemirror-state.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
BIN
media/vendor/codemirror/js/codemirror-state.min.js.gz
vendored
Normal file
BIN
media/vendor/codemirror/js/codemirror-state.min.js.gz
vendored
Normal file
Binary file not shown.
10485
media/vendor/codemirror/js/codemirror-view.js
vendored
Normal file
10485
media/vendor/codemirror/js/codemirror-view.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
media/vendor/codemirror/js/codemirror-view.min.js
vendored
Normal file
1
media/vendor/codemirror/js/codemirror-view.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
BIN
media/vendor/codemirror/js/codemirror-view.min.js.gz
vendored
Normal file
BIN
media/vendor/codemirror/js/codemirror-view.min.js.gz
vendored
Normal file
Binary file not shown.
2049
media/vendor/codemirror/js/lezer-common.js
vendored
Normal file
2049
media/vendor/codemirror/js/lezer-common.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
media/vendor/codemirror/js/lezer-common.min.js
vendored
Normal file
1
media/vendor/codemirror/js/lezer-common.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
BIN
media/vendor/codemirror/js/lezer-common.min.js.gz
vendored
Normal file
BIN
media/vendor/codemirror/js/lezer-common.min.js.gz
vendored
Normal file
Binary file not shown.
118
media/vendor/codemirror/js/lezer-css.js
vendored
Normal file
118
media/vendor/codemirror/js/lezer-css.js
vendored
Normal file
@ -0,0 +1,118 @@
|
||||
import { ExternalTokenizer, LRParser, LocalTokenGroup } from '@lezer/lr';
|
||||
import { styleTags, tags } from '@lezer/highlight';
|
||||
|
||||
// This file was generated by lezer-generator. You probably shouldn't edit it.
|
||||
const descendantOp = 96,
|
||||
Unit = 1,
|
||||
callee = 97,
|
||||
identifier = 98,
|
||||
VariableName = 2;
|
||||
|
||||
/* Hand-written tokenizers for CSS tokens that can't be
|
||||
expressed by Lezer's built-in tokenizer. */
|
||||
|
||||
const space = [9, 10, 11, 12, 13, 32, 133, 160, 5760, 8192, 8193, 8194, 8195, 8196, 8197,
|
||||
8198, 8199, 8200, 8201, 8202, 8232, 8233, 8239, 8287, 12288];
|
||||
const colon = 58, parenL = 40, underscore = 95, bracketL = 91, dash = 45, period = 46,
|
||||
hash = 35, percent = 37;
|
||||
|
||||
function isAlpha(ch) { return ch >= 65 && ch <= 90 || ch >= 97 && ch <= 122 || ch >= 161 }
|
||||
|
||||
function isDigit(ch) { return ch >= 48 && ch <= 57 }
|
||||
|
||||
const identifiers = new ExternalTokenizer((input, stack) => {
|
||||
for (let inside = false, dashes = 0, i = 0;; i++) {
|
||||
let {next} = input;
|
||||
if (isAlpha(next) || next == dash || next == underscore || (inside && isDigit(next))) {
|
||||
if (!inside && (next != dash || i > 0)) inside = true;
|
||||
if (dashes === i && next == dash) dashes++;
|
||||
input.advance();
|
||||
} else {
|
||||
if (inside)
|
||||
input.acceptToken(next == parenL ? callee : dashes == 2 && stack.canShift(VariableName) ? VariableName : identifier);
|
||||
break
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const descendant = new ExternalTokenizer(input => {
|
||||
if (space.includes(input.peek(-1))) {
|
||||
let {next} = input;
|
||||
if (isAlpha(next) || next == underscore || next == hash || next == period ||
|
||||
next == bracketL || next == colon || next == dash)
|
||||
input.acceptToken(descendantOp);
|
||||
}
|
||||
});
|
||||
|
||||
const unitToken = new ExternalTokenizer(input => {
|
||||
if (!space.includes(input.peek(-1))) {
|
||||
let {next} = input;
|
||||
if (next == percent) { input.advance(); input.acceptToken(Unit); }
|
||||
if (isAlpha(next)) {
|
||||
do { input.advance(); } while (isAlpha(input.next))
|
||||
input.acceptToken(Unit);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const cssHighlighting = styleTags({
|
||||
"AtKeyword import charset namespace keyframes media supports": tags.definitionKeyword,
|
||||
"from to selector": tags.keyword,
|
||||
NamespaceName: tags.namespace,
|
||||
KeyframeName: tags.labelName,
|
||||
KeyframeRangeName: tags.operatorKeyword,
|
||||
TagName: tags.tagName,
|
||||
ClassName: tags.className,
|
||||
PseudoClassName: tags.constant(tags.className),
|
||||
IdName: tags.labelName,
|
||||
"FeatureName PropertyName": tags.propertyName,
|
||||
AttributeName: tags.attributeName,
|
||||
NumberLiteral: tags.number,
|
||||
KeywordQuery: tags.keyword,
|
||||
UnaryQueryOp: tags.operatorKeyword,
|
||||
"CallTag ValueName": tags.atom,
|
||||
VariableName: tags.variableName,
|
||||
Callee: tags.operatorKeyword,
|
||||
Unit: tags.unit,
|
||||
"UniversalSelector NestingSelector": tags.definitionOperator,
|
||||
MatchOp: tags.compareOperator,
|
||||
"ChildOp SiblingOp, LogicOp": tags.logicOperator,
|
||||
BinOp: tags.arithmeticOperator,
|
||||
Important: tags.modifier,
|
||||
Comment: tags.blockComment,
|
||||
ColorLiteral: tags.color,
|
||||
"ParenthesizedContent StringLiteral": tags.string,
|
||||
":": tags.punctuation,
|
||||
"PseudoOp #": tags.derefOperator,
|
||||
"; ,": tags.separator,
|
||||
"( )": tags.paren,
|
||||
"[ ]": tags.squareBracket,
|
||||
"{ }": tags.brace
|
||||
});
|
||||
|
||||
// This file was generated by lezer-generator. You probably shouldn't edit it.
|
||||
const spec_callee = {__proto__:null,lang:32, "nth-child":32, "nth-last-child":32, "nth-of-type":32, "nth-last-of-type":32, dir:32, "host-context":32, url:60, "url-prefix":60, domain:60, regexp:60, selector:134};
|
||||
const spec_AtKeyword = {__proto__:null,"@import":114, "@media":138, "@charset":142, "@namespace":146, "@keyframes":152, "@supports":164};
|
||||
const spec_identifier = {__proto__:null,not:128, only:128};
|
||||
const parser = LRParser.deserialize({
|
||||
version: 14,
|
||||
states: "9bQYQ[OOO#_Q[OOP#fOWOOOOQP'#Cd'#CdOOQP'#Cc'#CcO#kQ[O'#CfO$_QXO'#CaO$fQ[O'#ChO$qQ[O'#DPO$vQ[O'#DTOOQP'#Ej'#EjO${QdO'#DeO%gQ[O'#DrO${QdO'#DtO%xQ[O'#DvO&TQ[O'#DyO&]Q[O'#EPO&kQ[O'#EROOQS'#Ei'#EiOOQS'#EU'#EUQYQ[OOO&rQXO'#CdO'gQWO'#DaO'lQWO'#EpO'wQ[O'#EpQOQWOOP(RO#tO'#C_POOO)C@X)C@XOOQP'#Cg'#CgOOQP,59Q,59QO#kQ[O,59QO(^Q[O'#EXO(xQWO,58{O)QQ[O,59SO$qQ[O,59kO$vQ[O,59oO(^Q[O,59sO(^Q[O,59uO(^Q[O,59vO)]Q[O'#D`OOQS,58{,58{OOQP'#Ck'#CkOOQO'#C}'#C}OOQP,59S,59SO)dQWO,59SO)iQWO,59SOOQP'#DR'#DROOQP,59k,59kOOQO'#DV'#DVO)nQ`O,59oOOQS'#Cp'#CpO${QdO'#CqO)vQvO'#CsO+TQtO,5:POOQO'#Cx'#CxO)iQWO'#CwO+iQWO'#CyOOQS'#Em'#EmOOQO'#Dh'#DhO+nQ[O'#DoO+|QWO'#EqO&]Q[O'#DmO,[QWO'#DpOOQO'#Er'#ErO({QWO,5:^O,aQpO,5:`OOQS'#Dx'#DxO,iQWO,5:bO,nQ[O,5:bOOQO'#D{'#D{O,vQWO,5:eO,{QWO,5:kO-TQWO,5:mOOQS-E8S-E8SO${QdO,59{O-]Q[O'#EZO-jQWO,5;[O-jQWO,5;[POOO'#ET'#ETP-uO#tO,58yPOOO,58y,58yOOQP1G.l1G.lO.lQXO,5:sOOQO-E8V-E8VOOQS1G.g1G.gOOQP1G.n1G.nO)dQWO1G.nO)iQWO1G.nOOQP1G/V1G/VO.yQ`O1G/ZO/dQXO1G/_O/zQXO1G/aO0bQXO1G/bO0xQWO,59zO0}Q[O'#DOO1UQdO'#CoOOQP1G/Z1G/ZO${QdO1G/ZO1]QpO,59]OOQS,59_,59_O${QdO,59aO1eQWO1G/kOOQS,59c,59cO1jQ!bO,59eO1rQWO'#DhO1}QWO,5:TO2SQWO,5:ZO&]Q[O,5:VO&]Q[O'#E[O2[QWO,5;]O2gQWO,5:XO(^Q[O,5:[OOQS1G/x1G/xOOQS1G/z1G/zOOQS1G/|1G/|O2xQWO1G/|O2}QdO'#D|OOQS1G0P1G0POOQS1G0V1G0VOOQS1G0X1G0XO3YQtO1G/gOOQO,5:u,5:uO3pQ[O,5:uOOQO-E8X-E8XO3}QWO1G0vPOOO-E8R-E8RPOOO1G.e1G.eOOQP7+$Y7+$YOOQP7+$u7+$uO${QdO7+$uOOQS1G/f1G/fO4YQXO'#EoO4aQWO,59jO4fQtO'#EVO5ZQdO'#ElO5eQWO,59ZO5jQpO7+$uOOQS1G.w1G.wOOQS1G.{1G.{OOQS7+%V7+%VO5rQWO1G/PO${QdO1G/oOOQO1G/u1G/uOOQO1G/q1G/qO5wQWO,5:vOOQO-E8Y-E8YO6VQXO1G/vOOQS7+%h7+%hO6^QYO'#CsOOQO'#EO'#EOO6iQ`O'#D}OOQO'#D}'#D}O6tQWO'#E]O6|QdO,5:hOOQS,5:h,5:hO7XQtO'#EYO${QdO'#EYO8VQdO7+%ROOQO7+%R7+%ROOQO1G0a1G0aO8jQpO<<HaO8rQWO,5;ZOOQP1G/U1G/UOOQS-E8T-E8TO${QdO'#EWO8zQWO,5;WOOQT1G.u1G.uOOQP<<Ha<<HaOOQS7+$k7+$kO9SQdO7+%ZOOQO7+%b7+%bOOQO,5:i,5:iO3QQdO'#E^O6tQWO,5:wOOQS,5:w,5:wOOQS-E8Z-E8ZOOQS1G0S1G0SO9ZQtO,5:tOOQS-E8W-E8WOOQO<<Hm<<HmOOQPAN={AN={O:XQdO,5:rOOQO-E8U-E8UOOQO<<Hu<<HuOOQO,5:x,5:xOOQO-E8[-E8[OOQS1G0c1G0c",
|
||||
stateData: ":k~O#WOS#XQQ~OUYOXYO]VO^VOtWOxXO!YaO!ZZO!g[O!i]O!k^O!n_O!t`O#URO#_TO~OQfOUYOXYO]VO^VOtWOxXO!YaO!ZZO!g[O!i]O!k^O!n_O!t`O#UeO#_TO~O#R#dP~P!ZO#XjO~O#UlO~O]qO^qOpoOtrOxsO|tO!PvO#SuO#_nO~O!RwO~P#pO`}O#TzO#UyO~O#U!OO~O#U!QO~OQ!ZOb!TOf!ZOh!ZOn!YO#T!WO#U!SO#b!UO~Ob!]O!b!_O!e!`O#U![O!R#eP~Oh!eOn!YO#U!dO~Oh!gO#U!gO~Ob!]O!b!_O!e!`O#U![O~O!W#eP~P%gO]WX]!UX^WXpWXtWXxWX|WX!PWX!RWX#SWX#_WX~O]!lO~O!W!mO#R#dX!Q#dX~O#R#dX!Q#dX~P!ZO#Y!pO#Z!pO#[!rO~OUYOXYO]VO^VOtWOxXO#URO#_TO~OpoO!RwO~O`!yO#TzO#UyO~O!Q#dP~P!ZOb#QO~Ob#RO~Ov#SOz#TO~OP#VObgXjgX!WgX!bgX!egX#UgXagXQgXfgXhgXngXpgX!VgX#RgX#TgX#bgXvgX!QgX~Ob!]Oj#WO!b!_O!e!`O#U![O!W#eP~Ob#ZO~Ob!]O!b!_O!e!`O#U#[O~Op#`O!`#_O!R#eX!W#eX~Ob#cO~Oj#WO!W#eO~O!W#fO~Oh#gOn!YO~O!R#hO~O!RwO!`#_O~O!RwO!W#kO~O!W!}X#R!}X!Q!}X~P!ZO!W!mO#R#da!Q#da~O#Y!pO#Z!pO#[#rO~O]qO^qOtrOxsO|tO!PvO#SuO#_nO~Op!{a!R!{aa!{a~P.QOv#tOz#uO~O]qO^qOtrOxsO#_nO~Op{i|{i!P{i!R{i#S{ia{i~P/ROp}i|}i!P}i!R}i#S}ia}i~P/ROp!Oi|!Oi!P!Oi!R!Oi#S!Oia!Oi~P/RO!Q#vO~Oa#cP~P(^Oa#`P~P${Oa#}Oj#WO~O!W$PO~Oh$QOo$QO~O]!^Xa![X!`![X~O]$RO~Oa$SO!`#_O~Op#`O!R#ea!W#ea~O!`#_Op!aa!R!aa!W!aaa!aa~O!W$XO~O!Q$`O#U$ZO#b$YO~Oj#WOp$bO!V$dO!W!Ti#R!Ti!Q!Ti~P${O!W!}a#R!}a!Q!}a~P!ZO!W!mO#R#di!Q#di~Oa#cX~P#pOa$hO~Oj#WOQ!yXa!yXb!yXf!yXh!yXn!yXp!yX#T!yX#U!yX#b!yX~Op$jOa#`X~P${Oa$lO~Oj#WOv$mO~Oa$nO~O!`#_Op#Oa!R#Oa!W#Oa~Oa$pO~P.QOP#VOpgX!RgX~O#b$YOp!qX!R!qX~Op$rO!RwO~O!Q$vO#U$ZO#b$YO~Oj#WOQ!|Xb!|Xf!|Xh!|Xn!|Xp!|X!V!|X!W!|X#R!|X#T!|X#U!|X#b!|X!Q!|X~Op$bO!V$yO!W!Tq#R!Tq!Q!Tq~P${Oj#WOv$zO~OpoOa#ca~Op$jOa#`a~Oa$}O~P${Oj#WOQ!|ab!|af!|ah!|an!|ap!|a!V!|a!W!|a#R!|a#T!|a#U!|a#b!|a!Q!|a~Oa!zap!za~P${O#Wo#X#bj!P#b~",
|
||||
goto: "-Y#gPPP#hP#kP#t$TP#t$d#tPP$jPPP$p$y$yP%]P$yP$y%w&ZPPP&s&y#tP'PP#tP'VP#tP#t#tPPP']'r(PPP#kPP(W(W(b(WP(WP(W(WP#kP#kP#kP(e#kP(h(k(n(u#kP#kP(z)Q)a)o)u*P*V*a*g*mPPPPPPPPPP*s*|P+i+lP,b,e,k,tRkQ_bOPdhw!m#nkYOPdhotuvw!m#Q#c#nkSOPdhotuvw!m#Q#c#nQmTR!snQ{VR!wqQ!w}Q#Y!XR#s!yq!ZZ]!T!l#R#T#W#l#u#z$R$b$c$j$o${p!ZZ]!T!l#R#T#W#l#u#z$R$b$c$j$o${U$]#h$_$rR$q$[q!XZ]!T!l#R#T#W#l#u#z$R$b$c$j$o${p!ZZ]!T!l#R#T#W#l#u#z$R$b$c$j$o${Q!e^R#g!fQ|VR!xqQ!w|R#s!xQ!PWR!zrQ!RXR!{sQxUQ!vpQ#d!bQ#j!iQ#k!jQ$t$^R%Q$sSgPwQ!ohQ#m!mR$e#nZfPhw!m#na!a[`a!V!]!_#_#`R#]!]R!f^R!h_R#i!hS$^#h$_R%O$rV$[#h$_$rQ!qjR#q!qQdOShPwU!kdh#nR#n!mQ#z#RU$i#z$o${Q$o$RR${$jQ$k#zR$|$kQpUS!up$gR$g#wQ$c#lR$x$cQ!ngS#o!n#pR#p!oQ#a!^R$V#aQ$_#hR$u$_Q$s$^R%P$s_cOPdhw!m#n^UOPdhw!m#nQ!toQ!|tQ!}uQ#OvQ#w#QR$W#cR#{#RQ!VZQ!c]Q#U!TQ#l!l[#y#R#z$R$j$o${Q#|#TQ$O#WS$a#l$cQ$f#uR$w$bR#x#QQiPR#PwQ!b[Q!jaR#X!VU!^[a!VQ!i`Q#^!]Q#b!_Q$T#_R$U#`",
|
||||
nodeNames: "⚠ Unit VariableName Comment StyleSheet RuleSet UniversalSelector TagSelector TagName NestingSelector ClassSelector ClassName PseudoClassSelector : :: PseudoClassName PseudoClassName ) ( ArgList ValueName ParenthesizedValue ColorLiteral NumberLiteral StringLiteral BinaryExpression BinOp CallExpression Callee CallLiteral CallTag ParenthesizedContent , PseudoClassName ArgList IdSelector # IdName ] AttributeSelector [ AttributeName MatchOp ChildSelector ChildOp DescendantSelector SiblingSelector SiblingOp } { Block Declaration PropertyName Important ; ImportStatement AtKeyword import KeywordQuery FeatureQuery FeatureName BinaryQuery LogicOp UnaryQuery UnaryQueryOp ParenthesizedQuery SelectorQuery selector MediaStatement media CharsetStatement charset NamespaceStatement namespace NamespaceName KeyframesStatement keyframes KeyframeName KeyframeList KeyframeSelector KeyframeRangeName SupportsStatement supports AtRule Styles",
|
||||
maxTerm: 114,
|
||||
nodeProps: [
|
||||
["openedBy", 17,"(",48,"{"],
|
||||
["closedBy", 18,")",49,"}"]
|
||||
],
|
||||
propSources: [cssHighlighting],
|
||||
skippedNodes: [0,3,85],
|
||||
repeatNodeCount: 10,
|
||||
tokenData: "J^~R!^OX$}X^%u^p$}pq%uqr)Xrs.Rst/utu6duv$}vw7^wx7oxy9^yz9oz{9t{|:_|}?Q}!O?c!O!P@Q!P!Q@i!Q![Ab![!]B]!]!^CX!^!_$}!_!`Cj!`!aC{!a!b$}!b!cDw!c!}$}!}#OFa#O#P$}#P#QFr#Q#R6d#R#T$}#T#UGT#U#c$}#c#dHf#d#o$}#o#pH{#p#q6d#q#rI^#r#sIo#s#y$}#y#z%u#z$f$}$f$g%u$g#BY$}#BY#BZ%u#BZ$IS$}$IS$I_%u$I_$I|$}$I|$JO%u$JO$JT$}$JT$JU%u$JU$KV$}$KV$KW%u$KW&FU$}&FU&FV%u&FV;'S$};'S;=`JW<%lO$}`%QSOy%^z;'S%^;'S;=`%o<%lO%^`%cSo`Oy%^z;'S%^;'S;=`%o<%lO%^`%rP;=`<%l%^~%zh#W~OX%^X^'f^p%^pq'fqy%^z#y%^#y#z'f#z$f%^$f$g'f$g#BY%^#BY#BZ'f#BZ$IS%^$IS$I_'f$I_$I|%^$I|$JO'f$JO$JT%^$JT$JU'f$JU$KV%^$KV$KW'f$KW&FU%^&FU&FV'f&FV;'S%^;'S;=`%o<%lO%^~'mh#W~o`OX%^X^'f^p%^pq'fqy%^z#y%^#y#z'f#z$f%^$f$g'f$g#BY%^#BY#BZ'f#BZ$IS%^$IS$I_'f$I_$I|%^$I|$JO'f$JO$JT%^$JT$JU'f$JU$KV%^$KV$KW'f$KW&FU%^&FU&FV'f&FV;'S%^;'S;=`%o<%lO%^l)[UOy%^z#]%^#]#^)n#^;'S%^;'S;=`%o<%lO%^l)sUo`Oy%^z#a%^#a#b*V#b;'S%^;'S;=`%o<%lO%^l*[Uo`Oy%^z#d%^#d#e*n#e;'S%^;'S;=`%o<%lO%^l*sUo`Oy%^z#c%^#c#d+V#d;'S%^;'S;=`%o<%lO%^l+[Uo`Oy%^z#f%^#f#g+n#g;'S%^;'S;=`%o<%lO%^l+sUo`Oy%^z#h%^#h#i,V#i;'S%^;'S;=`%o<%lO%^l,[Uo`Oy%^z#T%^#T#U,n#U;'S%^;'S;=`%o<%lO%^l,sUo`Oy%^z#b%^#b#c-V#c;'S%^;'S;=`%o<%lO%^l-[Uo`Oy%^z#h%^#h#i-n#i;'S%^;'S;=`%o<%lO%^l-uS!V[o`Oy%^z;'S%^;'S;=`%o<%lO%^~.UWOY.RZr.Rrs.ns#O.R#O#P.s#P;'S.R;'S;=`/o<%lO.R~.sOh~~.vRO;'S.R;'S;=`/P;=`O.R~/SXOY.RZr.Rrs.ns#O.R#O#P.s#P;'S.R;'S;=`/o;=`<%l.R<%lO.R~/rP;=`<%l.Rn/zYtQOy%^z!Q%^!Q![0j![!c%^!c!i0j!i#T%^#T#Z0j#Z;'S%^;'S;=`%o<%lO%^l0oYo`Oy%^z!Q%^!Q![1_![!c%^!c!i1_!i#T%^#T#Z1_#Z;'S%^;'S;=`%o<%lO%^l1dYo`Oy%^z!Q%^!Q![2S![!c%^!c!i2S!i#T%^#T#Z2S#Z;'S%^;'S;=`%o<%lO%^l2ZYf[o`Oy%^z!Q%^!Q![2y![!c%^!c!i2y!i#T%^#T#Z2y#Z;'S%^;'S;=`%o<%lO%^l3QYf[o`Oy%^z!Q%^!Q![3p![!c%^!c!i3p!i#T%^#T#Z3p#Z;'S%^;'S;=`%o<%lO%^l3uYo`Oy%^z!Q%^!Q![4e![!c%^!c!i4e!i#T%^#T#Z4e#Z;'S%^;'S;=`%o<%lO%^l4lYf[o`Oy%^z!Q%^!Q![5[![!c%^!c!i5[!i#T%^#T#Z5[#Z;'S%^;'S;=`%o<%lO%^l5aYo`Oy%^z!Q%^!Q![6P![!c%^!c!i6P!i#T%^#T#Z6P#Z;'S%^;'S;=`%o<%lO%^l6WSf[o`Oy%^z;'S%^;'S;=`%o<%lO%^d6gUOy%^z!_%^!_!`6y!`;'S%^;'S;=`%o<%lO%^d7QSzSo`Oy%^z;'S%^;'S;=`%o<%lO%^b7cSXQOy%^z;'S%^;'S;=`%o<%lO%^~7rWOY7oZw7owx.nx#O7o#O#P8[#P;'S7o;'S;=`9W<%lO7o~8_RO;'S7o;'S;=`8h;=`O7o~8kXOY7oZw7owx.nx#O7o#O#P8[#P;'S7o;'S;=`9W;=`<%l7o<%lO7o~9ZP;=`<%l7on9cSb^Oy%^z;'S%^;'S;=`%o<%lO%^~9tOa~n9{UUQjWOy%^z!_%^!_!`6y!`;'S%^;'S;=`%o<%lO%^n:fWjW!PQOy%^z!O%^!O!P;O!P!Q%^!Q![>T![;'S%^;'S;=`%o<%lO%^l;TUo`Oy%^z!Q%^!Q![;g![;'S%^;'S;=`%o<%lO%^l;nYo`#b[Oy%^z!Q%^!Q![;g![!g%^!g!h<^!h#X%^#X#Y<^#Y;'S%^;'S;=`%o<%lO%^l<cYo`Oy%^z{%^{|=R|}%^}!O=R!O!Q%^!Q![=j![;'S%^;'S;=`%o<%lO%^l=WUo`Oy%^z!Q%^!Q![=j![;'S%^;'S;=`%o<%lO%^l=qUo`#b[Oy%^z!Q%^!Q![=j![;'S%^;'S;=`%o<%lO%^l>[[o`#b[Oy%^z!O%^!O!P;g!P!Q%^!Q![>T![!g%^!g!h<^!h#X%^#X#Y<^#Y;'S%^;'S;=`%o<%lO%^n?VSp^Oy%^z;'S%^;'S;=`%o<%lO%^l?hWjWOy%^z!O%^!O!P;O!P!Q%^!Q![>T![;'S%^;'S;=`%o<%lO%^n@VU#_QOy%^z!Q%^!Q![;g![;'S%^;'S;=`%o<%lO%^~@nTjWOy%^z{@}{;'S%^;'S;=`%o<%lO%^~AUSo`#X~Oy%^z;'S%^;'S;=`%o<%lO%^lAg[#b[Oy%^z!O%^!O!P;g!P!Q%^!Q![>T![!g%^!g!h<^!h#X%^#X#Y<^#Y;'S%^;'S;=`%o<%lO%^bBbU]QOy%^z![%^![!]Bt!];'S%^;'S;=`%o<%lO%^bB{S^Qo`Oy%^z;'S%^;'S;=`%o<%lO%^nC^S!W^Oy%^z;'S%^;'S;=`%o<%lO%^dCoSzSOy%^z;'S%^;'S;=`%o<%lO%^bDQU|QOy%^z!`%^!`!aDd!a;'S%^;'S;=`%o<%lO%^bDkS|Qo`Oy%^z;'S%^;'S;=`%o<%lO%^bDzWOy%^z!c%^!c!}Ed!}#T%^#T#oEd#o;'S%^;'S;=`%o<%lO%^bEk[!YQo`Oy%^z}%^}!OEd!O!Q%^!Q![Ed![!c%^!c!}Ed!}#T%^#T#oEd#o;'S%^;'S;=`%o<%lO%^bFfSxQOy%^z;'S%^;'S;=`%o<%lO%^lFwSv[Oy%^z;'S%^;'S;=`%o<%lO%^bGWUOy%^z#b%^#b#cGj#c;'S%^;'S;=`%o<%lO%^bGoUo`Oy%^z#W%^#W#XHR#X;'S%^;'S;=`%o<%lO%^bHYS!`Qo`Oy%^z;'S%^;'S;=`%o<%lO%^bHiUOy%^z#f%^#f#gHR#g;'S%^;'S;=`%o<%lO%^fIQS!RUOy%^z;'S%^;'S;=`%o<%lO%^nIcS!Q^Oy%^z;'S%^;'S;=`%o<%lO%^fItU!PQOy%^z!_%^!_!`6y!`;'S%^;'S;=`%o<%lO%^`JZP;=`<%l$}",
|
||||
tokenizers: [descendant, unitToken, identifiers, 1, 2, 3, 4, new LocalTokenGroup("m~RRYZ[z{a~~g~aO#Z~~dP!P!Qg~lO#[~~", 28, 102)],
|
||||
topRules: {"StyleSheet":[0,4],"Styles":[1,84]},
|
||||
specialized: [{term: 97, get: value => spec_callee[value] || -1},{term: 56, get: value => spec_AtKeyword[value] || -1},{term: 98, get: value => spec_identifier[value] || -1}],
|
||||
tokenPrec: 1169
|
||||
});
|
||||
|
||||
export { parser };
|
||||
1
media/vendor/codemirror/js/lezer-css.min.js
vendored
Normal file
1
media/vendor/codemirror/js/lezer-css.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
BIN
media/vendor/codemirror/js/lezer-css.min.js.gz
vendored
Normal file
BIN
media/vendor/codemirror/js/lezer-css.min.js.gz
vendored
Normal file
Binary file not shown.
859
media/vendor/codemirror/js/lezer-highlight.js
vendored
Normal file
859
media/vendor/codemirror/js/lezer-highlight.js
vendored
Normal file
@ -0,0 +1,859 @@
|
||||
import { NodeProp } from '@lezer/common';
|
||||
|
||||
let nextTagID = 0;
|
||||
/**
|
||||
Highlighting tags are markers that denote a highlighting category.
|
||||
They are [associated](#highlight.styleTags) with parts of a syntax
|
||||
tree by a language mode, and then mapped to an actual CSS style by
|
||||
a [highlighter](#highlight.Highlighter).
|
||||
|
||||
Because syntax tree node types and highlight styles have to be
|
||||
able to talk the same language, CodeMirror uses a mostly _closed_
|
||||
[vocabulary](#highlight.tags) of syntax tags (as opposed to
|
||||
traditional open string-based systems, which make it hard for
|
||||
highlighting themes to cover all the tokens produced by the
|
||||
various languages).
|
||||
|
||||
It _is_ possible to [define](#highlight.Tag^define) your own
|
||||
highlighting tags for system-internal use (where you control both
|
||||
the language package and the highlighter), but such tags will not
|
||||
be picked up by regular highlighters (though you can derive them
|
||||
from standard tags to allow highlighters to fall back to those).
|
||||
*/
|
||||
class Tag {
|
||||
/**
|
||||
@internal
|
||||
*/
|
||||
constructor(
|
||||
/**
|
||||
The set of this tag and all its parent tags, starting with
|
||||
this one itself and sorted in order of decreasing specificity.
|
||||
*/
|
||||
set,
|
||||
/**
|
||||
The base unmodified tag that this one is based on, if it's
|
||||
modified @internal
|
||||
*/
|
||||
base,
|
||||
/**
|
||||
The modifiers applied to this.base @internal
|
||||
*/
|
||||
modified) {
|
||||
this.set = set;
|
||||
this.base = base;
|
||||
this.modified = modified;
|
||||
/**
|
||||
@internal
|
||||
*/
|
||||
this.id = nextTagID++;
|
||||
}
|
||||
/**
|
||||
Define a new tag. If `parent` is given, the tag is treated as a
|
||||
sub-tag of that parent, and
|
||||
[highlighters](#highlight.tagHighlighter) that don't mention
|
||||
this tag will try to fall back to the parent tag (or grandparent
|
||||
tag, etc).
|
||||
*/
|
||||
static define(parent) {
|
||||
if (parent === null || parent === void 0 ? void 0 : parent.base)
|
||||
throw new Error("Can not derive from a modified tag");
|
||||
let tag = new Tag([], null, []);
|
||||
tag.set.push(tag);
|
||||
if (parent)
|
||||
for (let t of parent.set)
|
||||
tag.set.push(t);
|
||||
return tag;
|
||||
}
|
||||
/**
|
||||
Define a tag _modifier_, which is a function that, given a tag,
|
||||
will return a tag that is a subtag of the original. Applying the
|
||||
same modifier to a twice tag will return the same value (`m1(t1)
|
||||
== m1(t1)`) and applying multiple modifiers will, regardless or
|
||||
order, produce the same tag (`m1(m2(t1)) == m2(m1(t1))`).
|
||||
|
||||
When multiple modifiers are applied to a given base tag, each
|
||||
smaller set of modifiers is registered as a parent, so that for
|
||||
example `m1(m2(m3(t1)))` is a subtype of `m1(m2(t1))`,
|
||||
`m1(m3(t1)`, and so on.
|
||||
*/
|
||||
static defineModifier() {
|
||||
let mod = new Modifier;
|
||||
return (tag) => {
|
||||
if (tag.modified.indexOf(mod) > -1)
|
||||
return tag;
|
||||
return Modifier.get(tag.base || tag, tag.modified.concat(mod).sort((a, b) => a.id - b.id));
|
||||
};
|
||||
}
|
||||
}
|
||||
let nextModifierID = 0;
|
||||
class Modifier {
|
||||
constructor() {
|
||||
this.instances = [];
|
||||
this.id = nextModifierID++;
|
||||
}
|
||||
static get(base, mods) {
|
||||
if (!mods.length)
|
||||
return base;
|
||||
let exists = mods[0].instances.find(t => t.base == base && sameArray(mods, t.modified));
|
||||
if (exists)
|
||||
return exists;
|
||||
let set = [], tag = new Tag(set, base, mods);
|
||||
for (let m of mods)
|
||||
m.instances.push(tag);
|
||||
let configs = powerSet(mods);
|
||||
for (let parent of base.set)
|
||||
if (!parent.modified.length)
|
||||
for (let config of configs)
|
||||
set.push(Modifier.get(parent, config));
|
||||
return tag;
|
||||
}
|
||||
}
|
||||
function sameArray(a, b) {
|
||||
return a.length == b.length && a.every((x, i) => x == b[i]);
|
||||
}
|
||||
function powerSet(array) {
|
||||
let sets = [[]];
|
||||
for (let i = 0; i < array.length; i++) {
|
||||
for (let j = 0, e = sets.length; j < e; j++) {
|
||||
sets.push(sets[j].concat(array[i]));
|
||||
}
|
||||
}
|
||||
return sets.sort((a, b) => b.length - a.length);
|
||||
}
|
||||
/**
|
||||
This function is used to add a set of tags to a language syntax
|
||||
via [`NodeSet.extend`](#common.NodeSet.extend) or
|
||||
[`LRParser.configure`](#lr.LRParser.configure).
|
||||
|
||||
The argument object maps node selectors to [highlighting
|
||||
tags](#highlight.Tag) or arrays of tags.
|
||||
|
||||
Node selectors may hold one or more (space-separated) node paths.
|
||||
Such a path can be a [node name](#common.NodeType.name), or
|
||||
multiple node names (or `*` wildcards) separated by slash
|
||||
characters, as in `"Block/Declaration/VariableName"`. Such a path
|
||||
matches the final node but only if its direct parent nodes are the
|
||||
other nodes mentioned. A `*` in such a path matches any parent,
|
||||
but only a single level—wildcards that match multiple parents
|
||||
aren't supported, both for efficiency reasons and because Lezer
|
||||
trees make it rather hard to reason about what they would match.)
|
||||
|
||||
A path can be ended with `/...` to indicate that the tag assigned
|
||||
to the node should also apply to all child nodes, even if they
|
||||
match their own style (by default, only the innermost style is
|
||||
used).
|
||||
|
||||
When a path ends in `!`, as in `Attribute!`, no further matching
|
||||
happens for the node's child nodes, and the entire node gets the
|
||||
given style.
|
||||
|
||||
In this notation, node names that contain `/`, `!`, `*`, or `...`
|
||||
must be quoted as JSON strings.
|
||||
|
||||
For example:
|
||||
|
||||
```javascript
|
||||
parser.withProps(
|
||||
styleTags({
|
||||
// Style Number and BigNumber nodes
|
||||
"Number BigNumber": tags.number,
|
||||
// Style Escape nodes whose parent is String
|
||||
"String/Escape": tags.escape,
|
||||
// Style anything inside Attributes nodes
|
||||
"Attributes!": tags.meta,
|
||||
// Add a style to all content inside Italic nodes
|
||||
"Italic/...": tags.emphasis,
|
||||
// Style InvalidString nodes as both `string` and `invalid`
|
||||
"InvalidString": [tags.string, tags.invalid],
|
||||
// Style the node named "/" as punctuation
|
||||
'"/"': tags.punctuation
|
||||
})
|
||||
)
|
||||
```
|
||||
*/
|
||||
function styleTags(spec) {
|
||||
let byName = Object.create(null);
|
||||
for (let prop in spec) {
|
||||
let tags = spec[prop];
|
||||
if (!Array.isArray(tags))
|
||||
tags = [tags];
|
||||
for (let part of prop.split(" "))
|
||||
if (part) {
|
||||
let pieces = [], mode = 2 /* Normal */, rest = part;
|
||||
for (let pos = 0;;) {
|
||||
if (rest == "..." && pos > 0 && pos + 3 == part.length) {
|
||||
mode = 1 /* Inherit */;
|
||||
break;
|
||||
}
|
||||
let m = /^"(?:[^"\\]|\\.)*?"|[^\/!]+/.exec(rest);
|
||||
if (!m)
|
||||
throw new RangeError("Invalid path: " + part);
|
||||
pieces.push(m[0] == "*" ? "" : m[0][0] == '"' ? JSON.parse(m[0]) : m[0]);
|
||||
pos += m[0].length;
|
||||
if (pos == part.length)
|
||||
break;
|
||||
let next = part[pos++];
|
||||
if (pos == part.length && next == "!") {
|
||||
mode = 0 /* Opaque */;
|
||||
break;
|
||||
}
|
||||
if (next != "/")
|
||||
throw new RangeError("Invalid path: " + part);
|
||||
rest = part.slice(pos);
|
||||
}
|
||||
let last = pieces.length - 1, inner = pieces[last];
|
||||
if (!inner)
|
||||
throw new RangeError("Invalid path: " + part);
|
||||
let rule = new Rule(tags, mode, last > 0 ? pieces.slice(0, last) : null);
|
||||
byName[inner] = rule.sort(byName[inner]);
|
||||
}
|
||||
}
|
||||
return ruleNodeProp.add(byName);
|
||||
}
|
||||
const ruleNodeProp = new NodeProp();
|
||||
class Rule {
|
||||
constructor(tags, mode, context, next) {
|
||||
this.tags = tags;
|
||||
this.mode = mode;
|
||||
this.context = context;
|
||||
this.next = next;
|
||||
}
|
||||
get opaque() { return this.mode == 0 /* Opaque */; }
|
||||
get inherit() { return this.mode == 1 /* Inherit */; }
|
||||
sort(other) {
|
||||
if (!other || other.depth < this.depth) {
|
||||
this.next = other;
|
||||
return this;
|
||||
}
|
||||
other.next = this.sort(other.next);
|
||||
return other;
|
||||
}
|
||||
get depth() { return this.context ? this.context.length : 0; }
|
||||
}
|
||||
Rule.empty = new Rule([], 2 /* Normal */, null);
|
||||
/**
|
||||
Define a [highlighter](#highlight.Highlighter) from an array of
|
||||
tag/class pairs. Classes associated with more specific tags will
|
||||
take precedence.
|
||||
*/
|
||||
function tagHighlighter(tags, options) {
|
||||
let map = Object.create(null);
|
||||
for (let style of tags) {
|
||||
if (!Array.isArray(style.tag))
|
||||
map[style.tag.id] = style.class;
|
||||
else
|
||||
for (let tag of style.tag)
|
||||
map[tag.id] = style.class;
|
||||
}
|
||||
let { scope, all = null } = options || {};
|
||||
return {
|
||||
style: (tags) => {
|
||||
let cls = all;
|
||||
for (let tag of tags) {
|
||||
for (let sub of tag.set) {
|
||||
let tagClass = map[sub.id];
|
||||
if (tagClass) {
|
||||
cls = cls ? cls + " " + tagClass : tagClass;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return cls;
|
||||
},
|
||||
scope
|
||||
};
|
||||
}
|
||||
function highlightTags(highlighters, tags) {
|
||||
let result = null;
|
||||
for (let highlighter of highlighters) {
|
||||
let value = highlighter.style(tags);
|
||||
if (value)
|
||||
result = result ? result + " " + value : value;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
/**
|
||||
Highlight the given [tree](#common.Tree) with the given
|
||||
[highlighter](#highlight.Highlighter).
|
||||
*/
|
||||
function highlightTree(tree, highlighter,
|
||||
/**
|
||||
Assign styling to a region of the text. Will be called, in order
|
||||
of position, for any ranges where more than zero classes apply.
|
||||
`classes` is a space separated string of CSS classes.
|
||||
*/
|
||||
putStyle,
|
||||
/**
|
||||
The start of the range to highlight.
|
||||
*/
|
||||
from = 0,
|
||||
/**
|
||||
The end of the range.
|
||||
*/
|
||||
to = tree.length) {
|
||||
let builder = new HighlightBuilder(from, Array.isArray(highlighter) ? highlighter : [highlighter], putStyle);
|
||||
builder.highlightRange(tree.cursor(), from, to, "", builder.highlighters);
|
||||
builder.flush(to);
|
||||
}
|
||||
class HighlightBuilder {
|
||||
constructor(at, highlighters, span) {
|
||||
this.at = at;
|
||||
this.highlighters = highlighters;
|
||||
this.span = span;
|
||||
this.class = "";
|
||||
}
|
||||
startSpan(at, cls) {
|
||||
if (cls != this.class) {
|
||||
this.flush(at);
|
||||
if (at > this.at)
|
||||
this.at = at;
|
||||
this.class = cls;
|
||||
}
|
||||
}
|
||||
flush(to) {
|
||||
if (to > this.at && this.class)
|
||||
this.span(this.at, to, this.class);
|
||||
}
|
||||
highlightRange(cursor, from, to, inheritedClass, highlighters) {
|
||||
let { type, from: start, to: end } = cursor;
|
||||
if (start >= to || end <= from)
|
||||
return;
|
||||
if (type.isTop)
|
||||
highlighters = this.highlighters.filter(h => !h.scope || h.scope(type));
|
||||
let cls = inheritedClass;
|
||||
let rule = getStyleTags(cursor) || Rule.empty;
|
||||
let tagCls = highlightTags(highlighters, rule.tags);
|
||||
if (tagCls) {
|
||||
if (cls)
|
||||
cls += " ";
|
||||
cls += tagCls;
|
||||
if (rule.mode == 1 /* Inherit */)
|
||||
inheritedClass += (inheritedClass ? " " : "") + tagCls;
|
||||
}
|
||||
this.startSpan(Math.max(from, start), cls);
|
||||
if (rule.opaque)
|
||||
return;
|
||||
let mounted = cursor.tree && cursor.tree.prop(NodeProp.mounted);
|
||||
if (mounted && mounted.overlay) {
|
||||
let inner = cursor.node.enter(mounted.overlay[0].from + start, 1);
|
||||
let innerHighlighters = this.highlighters.filter(h => !h.scope || h.scope(mounted.tree.type));
|
||||
let hasChild = cursor.firstChild();
|
||||
for (let i = 0, pos = start;; i++) {
|
||||
let next = i < mounted.overlay.length ? mounted.overlay[i] : null;
|
||||
let nextPos = next ? next.from + start : end;
|
||||
let rangeFrom = Math.max(from, pos), rangeTo = Math.min(to, nextPos);
|
||||
if (rangeFrom < rangeTo && hasChild) {
|
||||
while (cursor.from < rangeTo) {
|
||||
this.highlightRange(cursor, rangeFrom, rangeTo, inheritedClass, highlighters);
|
||||
this.startSpan(Math.min(rangeTo, cursor.to), cls);
|
||||
if (cursor.to >= nextPos || !cursor.nextSibling())
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!next || nextPos > to)
|
||||
break;
|
||||
pos = next.to + start;
|
||||
if (pos > from) {
|
||||
this.highlightRange(inner.cursor(), Math.max(from, next.from + start), Math.min(to, pos), "", innerHighlighters);
|
||||
this.startSpan(Math.min(to, pos), cls);
|
||||
}
|
||||
}
|
||||
if (hasChild)
|
||||
cursor.parent();
|
||||
}
|
||||
else if (cursor.firstChild()) {
|
||||
if (mounted)
|
||||
inheritedClass = "";
|
||||
do {
|
||||
if (cursor.to <= from)
|
||||
continue;
|
||||
if (cursor.from >= to)
|
||||
break;
|
||||
this.highlightRange(cursor, from, to, inheritedClass, highlighters);
|
||||
this.startSpan(Math.min(to, cursor.to), cls);
|
||||
} while (cursor.nextSibling());
|
||||
cursor.parent();
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
Match a syntax node's [highlight rules](#highlight.styleTags). If
|
||||
there's a match, return its set of tags, and whether it is
|
||||
opaque (uses a `!`) or applies to all child nodes (`/...`).
|
||||
*/
|
||||
function getStyleTags(node) {
|
||||
let rule = node.type.prop(ruleNodeProp);
|
||||
while (rule && rule.context && !node.matchContext(rule.context))
|
||||
rule = rule.next;
|
||||
return rule || null;
|
||||
}
|
||||
const t = Tag.define;
|
||||
const comment = t(), name = t(), typeName = t(name), propertyName = t(name), literal = t(), string = t(literal), number = t(literal), content = t(), heading = t(content), keyword = t(), operator = t(), punctuation = t(), bracket = t(punctuation), meta = t();
|
||||
/**
|
||||
The default set of highlighting [tags](#highlight.Tag).
|
||||
|
||||
This collection is heavily biased towards programming languages,
|
||||
and necessarily incomplete. A full ontology of syntactic
|
||||
constructs would fill a stack of books, and be impractical to
|
||||
write themes for. So try to make do with this set. If all else
|
||||
fails, [open an
|
||||
issue](https://github.com/codemirror/codemirror.next) to propose a
|
||||
new tag, or [define](#highlight.Tag^define) a local custom tag for
|
||||
your use case.
|
||||
|
||||
Note that it is not obligatory to always attach the most specific
|
||||
tag possible to an element—if your grammar can't easily
|
||||
distinguish a certain type of element (such as a local variable),
|
||||
it is okay to style it as its more general variant (a variable).
|
||||
|
||||
For tags that extend some parent tag, the documentation links to
|
||||
the parent.
|
||||
*/
|
||||
const tags = {
|
||||
/**
|
||||
A comment.
|
||||
*/
|
||||
comment,
|
||||
/**
|
||||
A line [comment](#highlight.tags.comment).
|
||||
*/
|
||||
lineComment: t(comment),
|
||||
/**
|
||||
A block [comment](#highlight.tags.comment).
|
||||
*/
|
||||
blockComment: t(comment),
|
||||
/**
|
||||
A documentation [comment](#highlight.tags.comment).
|
||||
*/
|
||||
docComment: t(comment),
|
||||
/**
|
||||
Any kind of identifier.
|
||||
*/
|
||||
name,
|
||||
/**
|
||||
The [name](#highlight.tags.name) of a variable.
|
||||
*/
|
||||
variableName: t(name),
|
||||
/**
|
||||
A type [name](#highlight.tags.name).
|
||||
*/
|
||||
typeName: typeName,
|
||||
/**
|
||||
A tag name (subtag of [`typeName`](#highlight.tags.typeName)).
|
||||
*/
|
||||
tagName: t(typeName),
|
||||
/**
|
||||
A property or field [name](#highlight.tags.name).
|
||||
*/
|
||||
propertyName: propertyName,
|
||||
/**
|
||||
An attribute name (subtag of [`propertyName`](#highlight.tags.propertyName)).
|
||||
*/
|
||||
attributeName: t(propertyName),
|
||||
/**
|
||||
The [name](#highlight.tags.name) of a class.
|
||||
*/
|
||||
className: t(name),
|
||||
/**
|
||||
A label [name](#highlight.tags.name).
|
||||
*/
|
||||
labelName: t(name),
|
||||
/**
|
||||
A namespace [name](#highlight.tags.name).
|
||||
*/
|
||||
namespace: t(name),
|
||||
/**
|
||||
The [name](#highlight.tags.name) of a macro.
|
||||
*/
|
||||
macroName: t(name),
|
||||
/**
|
||||
A literal value.
|
||||
*/
|
||||
literal,
|
||||
/**
|
||||
A string [literal](#highlight.tags.literal).
|
||||
*/
|
||||
string,
|
||||
/**
|
||||
A documentation [string](#highlight.tags.string).
|
||||
*/
|
||||
docString: t(string),
|
||||
/**
|
||||
A character literal (subtag of [string](#highlight.tags.string)).
|
||||
*/
|
||||
character: t(string),
|
||||
/**
|
||||
An attribute value (subtag of [string](#highlight.tags.string)).
|
||||
*/
|
||||
attributeValue: t(string),
|
||||
/**
|
||||
A number [literal](#highlight.tags.literal).
|
||||
*/
|
||||
number,
|
||||
/**
|
||||
An integer [number](#highlight.tags.number) literal.
|
||||
*/
|
||||
integer: t(number),
|
||||
/**
|
||||
A floating-point [number](#highlight.tags.number) literal.
|
||||
*/
|
||||
float: t(number),
|
||||
/**
|
||||
A boolean [literal](#highlight.tags.literal).
|
||||
*/
|
||||
bool: t(literal),
|
||||
/**
|
||||
Regular expression [literal](#highlight.tags.literal).
|
||||
*/
|
||||
regexp: t(literal),
|
||||
/**
|
||||
An escape [literal](#highlight.tags.literal), for example a
|
||||
backslash escape in a string.
|
||||
*/
|
||||
escape: t(literal),
|
||||
/**
|
||||
A color [literal](#highlight.tags.literal).
|
||||
*/
|
||||
color: t(literal),
|
||||
/**
|
||||
A URL [literal](#highlight.tags.literal).
|
||||
*/
|
||||
url: t(literal),
|
||||
/**
|
||||
A language keyword.
|
||||
*/
|
||||
keyword,
|
||||
/**
|
||||
The [keyword](#highlight.tags.keyword) for the self or this
|
||||
object.
|
||||
*/
|
||||
self: t(keyword),
|
||||
/**
|
||||
The [keyword](#highlight.tags.keyword) for null.
|
||||
*/
|
||||
null: t(keyword),
|
||||
/**
|
||||
A [keyword](#highlight.tags.keyword) denoting some atomic value.
|
||||
*/
|
||||
atom: t(keyword),
|
||||
/**
|
||||
A [keyword](#highlight.tags.keyword) that represents a unit.
|
||||
*/
|
||||
unit: t(keyword),
|
||||
/**
|
||||
A modifier [keyword](#highlight.tags.keyword).
|
||||
*/
|
||||
modifier: t(keyword),
|
||||
/**
|
||||
A [keyword](#highlight.tags.keyword) that acts as an operator.
|
||||
*/
|
||||
operatorKeyword: t(keyword),
|
||||
/**
|
||||
A control-flow related [keyword](#highlight.tags.keyword).
|
||||
*/
|
||||
controlKeyword: t(keyword),
|
||||
/**
|
||||
A [keyword](#highlight.tags.keyword) that defines something.
|
||||
*/
|
||||
definitionKeyword: t(keyword),
|
||||
/**
|
||||
A [keyword](#highlight.tags.keyword) related to defining or
|
||||
interfacing with modules.
|
||||
*/
|
||||
moduleKeyword: t(keyword),
|
||||
/**
|
||||
An operator.
|
||||
*/
|
||||
operator,
|
||||
/**
|
||||
An [operator](#highlight.tags.operator) that dereferences something.
|
||||
*/
|
||||
derefOperator: t(operator),
|
||||
/**
|
||||
Arithmetic-related [operator](#highlight.tags.operator).
|
||||
*/
|
||||
arithmeticOperator: t(operator),
|
||||
/**
|
||||
Logical [operator](#highlight.tags.operator).
|
||||
*/
|
||||
logicOperator: t(operator),
|
||||
/**
|
||||
Bit [operator](#highlight.tags.operator).
|
||||
*/
|
||||
bitwiseOperator: t(operator),
|
||||
/**
|
||||
Comparison [operator](#highlight.tags.operator).
|
||||
*/
|
||||
compareOperator: t(operator),
|
||||
/**
|
||||
[Operator](#highlight.tags.operator) that updates its operand.
|
||||
*/
|
||||
updateOperator: t(operator),
|
||||
/**
|
||||
[Operator](#highlight.tags.operator) that defines something.
|
||||
*/
|
||||
definitionOperator: t(operator),
|
||||
/**
|
||||
Type-related [operator](#highlight.tags.operator).
|
||||
*/
|
||||
typeOperator: t(operator),
|
||||
/**
|
||||
Control-flow [operator](#highlight.tags.operator).
|
||||
*/
|
||||
controlOperator: t(operator),
|
||||
/**
|
||||
Program or markup punctuation.
|
||||
*/
|
||||
punctuation,
|
||||
/**
|
||||
[Punctuation](#highlight.tags.punctuation) that separates
|
||||
things.
|
||||
*/
|
||||
separator: t(punctuation),
|
||||
/**
|
||||
Bracket-style [punctuation](#highlight.tags.punctuation).
|
||||
*/
|
||||
bracket,
|
||||
/**
|
||||
Angle [brackets](#highlight.tags.bracket) (usually `<` and `>`
|
||||
tokens).
|
||||
*/
|
||||
angleBracket: t(bracket),
|
||||
/**
|
||||
Square [brackets](#highlight.tags.bracket) (usually `[` and `]`
|
||||
tokens).
|
||||
*/
|
||||
squareBracket: t(bracket),
|
||||
/**
|
||||
Parentheses (usually `(` and `)` tokens). Subtag of
|
||||
[bracket](#highlight.tags.bracket).
|
||||
*/
|
||||
paren: t(bracket),
|
||||
/**
|
||||
Braces (usually `{` and `}` tokens). Subtag of
|
||||
[bracket](#highlight.tags.bracket).
|
||||
*/
|
||||
brace: t(bracket),
|
||||
/**
|
||||
Content, for example plain text in XML or markup documents.
|
||||
*/
|
||||
content,
|
||||
/**
|
||||
[Content](#highlight.tags.content) that represents a heading.
|
||||
*/
|
||||
heading,
|
||||
/**
|
||||
A level 1 [heading](#highlight.tags.heading).
|
||||
*/
|
||||
heading1: t(heading),
|
||||
/**
|
||||
A level 2 [heading](#highlight.tags.heading).
|
||||
*/
|
||||
heading2: t(heading),
|
||||
/**
|
||||
A level 3 [heading](#highlight.tags.heading).
|
||||
*/
|
||||
heading3: t(heading),
|
||||
/**
|
||||
A level 4 [heading](#highlight.tags.heading).
|
||||
*/
|
||||
heading4: t(heading),
|
||||
/**
|
||||
A level 5 [heading](#highlight.tags.heading).
|
||||
*/
|
||||
heading5: t(heading),
|
||||
/**
|
||||
A level 6 [heading](#highlight.tags.heading).
|
||||
*/
|
||||
heading6: t(heading),
|
||||
/**
|
||||
A prose separator (such as a horizontal rule).
|
||||
*/
|
||||
contentSeparator: t(content),
|
||||
/**
|
||||
[Content](#highlight.tags.content) that represents a list.
|
||||
*/
|
||||
list: t(content),
|
||||
/**
|
||||
[Content](#highlight.tags.content) that represents a quote.
|
||||
*/
|
||||
quote: t(content),
|
||||
/**
|
||||
[Content](#highlight.tags.content) that is emphasized.
|
||||
*/
|
||||
emphasis: t(content),
|
||||
/**
|
||||
[Content](#highlight.tags.content) that is styled strong.
|
||||
*/
|
||||
strong: t(content),
|
||||
/**
|
||||
[Content](#highlight.tags.content) that is part of a link.
|
||||
*/
|
||||
link: t(content),
|
||||
/**
|
||||
[Content](#highlight.tags.content) that is styled as code or
|
||||
monospace.
|
||||
*/
|
||||
monospace: t(content),
|
||||
/**
|
||||
[Content](#highlight.tags.content) that has a strike-through
|
||||
style.
|
||||
*/
|
||||
strikethrough: t(content),
|
||||
/**
|
||||
Inserted text in a change-tracking format.
|
||||
*/
|
||||
inserted: t(),
|
||||
/**
|
||||
Deleted text.
|
||||
*/
|
||||
deleted: t(),
|
||||
/**
|
||||
Changed text.
|
||||
*/
|
||||
changed: t(),
|
||||
/**
|
||||
An invalid or unsyntactic element.
|
||||
*/
|
||||
invalid: t(),
|
||||
/**
|
||||
Metadata or meta-instruction.
|
||||
*/
|
||||
meta,
|
||||
/**
|
||||
[Metadata](#highlight.tags.meta) that applies to the entire
|
||||
document.
|
||||
*/
|
||||
documentMeta: t(meta),
|
||||
/**
|
||||
[Metadata](#highlight.tags.meta) that annotates or adds
|
||||
attributes to a given syntactic element.
|
||||
*/
|
||||
annotation: t(meta),
|
||||
/**
|
||||
Processing instruction or preprocessor directive. Subtag of
|
||||
[meta](#highlight.tags.meta).
|
||||
*/
|
||||
processingInstruction: t(meta),
|
||||
/**
|
||||
[Modifier](#highlight.Tag^defineModifier) that indicates that a
|
||||
given element is being defined. Expected to be used with the
|
||||
various [name](#highlight.tags.name) tags.
|
||||
*/
|
||||
definition: Tag.defineModifier(),
|
||||
/**
|
||||
[Modifier](#highlight.Tag^defineModifier) that indicates that
|
||||
something is constant. Mostly expected to be used with
|
||||
[variable names](#highlight.tags.variableName).
|
||||
*/
|
||||
constant: Tag.defineModifier(),
|
||||
/**
|
||||
[Modifier](#highlight.Tag^defineModifier) used to indicate that
|
||||
a [variable](#highlight.tags.variableName) or [property
|
||||
name](#highlight.tags.propertyName) is being called or defined
|
||||
as a function.
|
||||
*/
|
||||
function: Tag.defineModifier(),
|
||||
/**
|
||||
[Modifier](#highlight.Tag^defineModifier) that can be applied to
|
||||
[names](#highlight.tags.name) to indicate that they belong to
|
||||
the language's standard environment.
|
||||
*/
|
||||
standard: Tag.defineModifier(),
|
||||
/**
|
||||
[Modifier](#highlight.Tag^defineModifier) that indicates a given
|
||||
[names](#highlight.tags.name) is local to some scope.
|
||||
*/
|
||||
local: Tag.defineModifier(),
|
||||
/**
|
||||
A generic variant [modifier](#highlight.Tag^defineModifier) that
|
||||
can be used to tag language-specific alternative variants of
|
||||
some common tag. It is recommended for themes to define special
|
||||
forms of at least the [string](#highlight.tags.string) and
|
||||
[variable name](#highlight.tags.variableName) tags, since those
|
||||
come up a lot.
|
||||
*/
|
||||
special: Tag.defineModifier()
|
||||
};
|
||||
/**
|
||||
This is a highlighter that adds stable, predictable classes to
|
||||
tokens, for styling with external CSS.
|
||||
|
||||
The following tags are mapped to their name prefixed with `"tok-"`
|
||||
(for example `"tok-comment"`):
|
||||
|
||||
* [`link`](#highlight.tags.link)
|
||||
* [`heading`](#highlight.tags.heading)
|
||||
* [`emphasis`](#highlight.tags.emphasis)
|
||||
* [`strong`](#highlight.tags.strong)
|
||||
* [`keyword`](#highlight.tags.keyword)
|
||||
* [`atom`](#highlight.tags.atom)
|
||||
* [`bool`](#highlight.tags.bool)
|
||||
* [`url`](#highlight.tags.url)
|
||||
* [`labelName`](#highlight.tags.labelName)
|
||||
* [`inserted`](#highlight.tags.inserted)
|
||||
* [`deleted`](#highlight.tags.deleted)
|
||||
* [`literal`](#highlight.tags.literal)
|
||||
* [`string`](#highlight.tags.string)
|
||||
* [`number`](#highlight.tags.number)
|
||||
* [`variableName`](#highlight.tags.variableName)
|
||||
* [`typeName`](#highlight.tags.typeName)
|
||||
* [`namespace`](#highlight.tags.namespace)
|
||||
* [`className`](#highlight.tags.className)
|
||||
* [`macroName`](#highlight.tags.macroName)
|
||||
* [`propertyName`](#highlight.tags.propertyName)
|
||||
* [`operator`](#highlight.tags.operator)
|
||||
* [`comment`](#highlight.tags.comment)
|
||||
* [`meta`](#highlight.tags.meta)
|
||||
* [`punctuation`](#highlight.tags.punctuation)
|
||||
* [`invalid`](#highlight.tags.invalid)
|
||||
|
||||
In addition, these mappings are provided:
|
||||
|
||||
* [`regexp`](#highlight.tags.regexp),
|
||||
[`escape`](#highlight.tags.escape), and
|
||||
[`special`](#highlight.tags.special)[`(string)`](#highlight.tags.string)
|
||||
are mapped to `"tok-string2"`
|
||||
* [`special`](#highlight.tags.special)[`(variableName)`](#highlight.tags.variableName)
|
||||
to `"tok-variableName2"`
|
||||
* [`local`](#highlight.tags.local)[`(variableName)`](#highlight.tags.variableName)
|
||||
to `"tok-variableName tok-local"`
|
||||
* [`definition`](#highlight.tags.definition)[`(variableName)`](#highlight.tags.variableName)
|
||||
to `"tok-variableName tok-definition"`
|
||||
* [`definition`](#highlight.tags.definition)[`(propertyName)`](#highlight.tags.propertyName)
|
||||
to `"tok-propertyName tok-definition"`
|
||||
*/
|
||||
const classHighlighter = tagHighlighter([
|
||||
{ tag: tags.link, class: "tok-link" },
|
||||
{ tag: tags.heading, class: "tok-heading" },
|
||||
{ tag: tags.emphasis, class: "tok-emphasis" },
|
||||
{ tag: tags.strong, class: "tok-strong" },
|
||||
{ tag: tags.keyword, class: "tok-keyword" },
|
||||
{ tag: tags.atom, class: "tok-atom" },
|
||||
{ tag: tags.bool, class: "tok-bool" },
|
||||
{ tag: tags.url, class: "tok-url" },
|
||||
{ tag: tags.labelName, class: "tok-labelName" },
|
||||
{ tag: tags.inserted, class: "tok-inserted" },
|
||||
{ tag: tags.deleted, class: "tok-deleted" },
|
||||
{ tag: tags.literal, class: "tok-literal" },
|
||||
{ tag: tags.string, class: "tok-string" },
|
||||
{ tag: tags.number, class: "tok-number" },
|
||||
{ tag: [tags.regexp, tags.escape, tags.special(tags.string)], class: "tok-string2" },
|
||||
{ tag: tags.variableName, class: "tok-variableName" },
|
||||
{ tag: tags.local(tags.variableName), class: "tok-variableName tok-local" },
|
||||
{ tag: tags.definition(tags.variableName), class: "tok-variableName tok-definition" },
|
||||
{ tag: tags.special(tags.variableName), class: "tok-variableName2" },
|
||||
{ tag: tags.definition(tags.propertyName), class: "tok-propertyName tok-definition" },
|
||||
{ tag: tags.typeName, class: "tok-typeName" },
|
||||
{ tag: tags.namespace, class: "tok-namespace" },
|
||||
{ tag: tags.className, class: "tok-className" },
|
||||
{ tag: tags.macroName, class: "tok-macroName" },
|
||||
{ tag: tags.propertyName, class: "tok-propertyName" },
|
||||
{ tag: tags.operator, class: "tok-operator" },
|
||||
{ tag: tags.comment, class: "tok-comment" },
|
||||
{ tag: tags.meta, class: "tok-meta" },
|
||||
{ tag: tags.invalid, class: "tok-invalid" },
|
||||
{ tag: tags.punctuation, class: "tok-punctuation" }
|
||||
]);
|
||||
|
||||
export { Tag, classHighlighter, getStyleTags, highlightTree, styleTags, tagHighlighter, tags };
|
||||
1
media/vendor/codemirror/js/lezer-highlight.min.js
vendored
Normal file
1
media/vendor/codemirror/js/lezer-highlight.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
BIN
media/vendor/codemirror/js/lezer-highlight.min.js.gz
vendored
Normal file
BIN
media/vendor/codemirror/js/lezer-highlight.min.js.gz
vendored
Normal file
Binary file not shown.
356
media/vendor/codemirror/js/lezer-html.js
vendored
Normal file
356
media/vendor/codemirror/js/lezer-html.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
media/vendor/codemirror/js/lezer-html.min.js
vendored
Normal file
1
media/vendor/codemirror/js/lezer-html.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
BIN
media/vendor/codemirror/js/lezer-html.min.js.gz
vendored
Normal file
BIN
media/vendor/codemirror/js/lezer-html.min.js.gz
vendored
Normal file
Binary file not shown.
145
media/vendor/codemirror/js/lezer-javascript.js
vendored
Normal file
145
media/vendor/codemirror/js/lezer-javascript.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
media/vendor/codemirror/js/lezer-javascript.min.js
vendored
Normal file
1
media/vendor/codemirror/js/lezer-javascript.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
BIN
media/vendor/codemirror/js/lezer-javascript.min.js.gz
vendored
Normal file
BIN
media/vendor/codemirror/js/lezer-javascript.min.js.gz
vendored
Normal file
Binary file not shown.
36
media/vendor/codemirror/js/lezer-json.js
vendored
Normal file
36
media/vendor/codemirror/js/lezer-json.js
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
import { LRParser } from '@lezer/lr';
|
||||
import { styleTags, tags } from '@lezer/highlight';
|
||||
|
||||
const jsonHighlighting = styleTags({
|
||||
String: tags.string,
|
||||
Number: tags.number,
|
||||
"True False": tags.bool,
|
||||
PropertyName: tags.propertyName,
|
||||
Null: tags.null,
|
||||
",": tags.separator,
|
||||
"[ ]": tags.squareBracket,
|
||||
"{ }": tags.brace
|
||||
});
|
||||
|
||||
// This file was generated by lezer-generator. You probably shouldn't edit it.
|
||||
const parser = LRParser.deserialize({
|
||||
version: 14,
|
||||
states: "$bOVQPOOOOQO'#Cb'#CbOnQPO'#CeOvQPO'#CjOOQO'#Cp'#CpQOQPOOOOQO'#Cg'#CgO}QPO'#CfO!SQPO'#CrOOQO,59P,59PO![QPO,59PO!aQPO'#CuOOQO,59U,59UO!iQPO,59UOVQPO,59QOqQPO'#CkO!nQPO,59^OOQO1G.k1G.kOVQPO'#ClO!vQPO,59aOOQO1G.p1G.pOOQO1G.l1G.lOOQO,59V,59VOOQO-E6i-E6iOOQO,59W,59WOOQO-E6j-E6j",
|
||||
stateData: "#O~OcOS~OQSORSOSSOTSOWQO]ROePO~OVXOeUO~O[[O~PVOg^O~Oh_OVfX~OVaO~OhbO[iX~O[dO~Oh_OVfa~OhbO[ia~O",
|
||||
goto: "!kjPPPPPPkPPkqwPPk{!RPPP!XP!ePP!hXSOR^bQWQRf_TVQ_Q`WRg`QcZRicQTOQZRQe^RhbRYQR]R",
|
||||
nodeNames: "⚠ JsonText True False Null Number String } { Object Property PropertyName ] [ Array",
|
||||
maxTerm: 25,
|
||||
nodeProps: [
|
||||
["openedBy", 7,"{",12,"["],
|
||||
["closedBy", 8,"}",13,"]"]
|
||||
],
|
||||
propSources: [jsonHighlighting],
|
||||
skippedNodes: [0],
|
||||
repeatNodeCount: 2,
|
||||
tokenData: "(|~RaXY!WYZ!W]^!Wpq!Wrs!]|}$u}!O$z!Q!R%T!R![&c![!]&t!}#O&y#P#Q'O#Y#Z'T#b#c'r#h#i(Z#o#p(r#q#r(w~!]Oc~~!`Wpq!]qr!]rs!xs#O!]#O#P!}#P;'S!];'S;=`$o<%lO!]~!}Oe~~#QXrs!]!P!Q!]#O#P!]#U#V!]#Y#Z!]#b#c!]#f#g!]#h#i!]#i#j#m~#pR!Q![#y!c!i#y#T#Z#y~#|R!Q![$V!c!i$V#T#Z$V~$YR!Q![$c!c!i$c#T#Z$c~$fR!Q![!]!c!i!]#T#Z!]~$rP;=`<%l!]~$zOh~~$}Q!Q!R%T!R![&c~%YRT~!O!P%c!g!h%w#X#Y%w~%fP!Q![%i~%nRT~!Q![%i!g!h%w#X#Y%w~%zR{|&T}!O&T!Q![&Z~&WP!Q![&Z~&`PT~!Q![&Z~&hST~!O!P%c!Q![&c!g!h%w#X#Y%w~&yOg~~'OO]~~'TO[~~'WP#T#U'Z~'^P#`#a'a~'dP#g#h'g~'jP#X#Y'm~'rOR~~'uP#i#j'x~'{P#`#a(O~(RP#`#a(U~(ZOS~~(^P#f#g(a~(dP#i#j(g~(jP#X#Y(m~(rOQ~~(wOW~~(|OV~",
|
||||
tokenizers: [0],
|
||||
topRules: {"JsonText":[0,1]},
|
||||
tokenPrec: 0
|
||||
});
|
||||
|
||||
export { parser };
|
||||
1
media/vendor/codemirror/js/lezer-json.min.js
vendored
Normal file
1
media/vendor/codemirror/js/lezer-json.min.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
import{LRParser}from"@lezer/lr";import{styleTags,tags}from"@lezer/highlight";const jsonHighlighting=styleTags({String:tags.string,Number:tags.number,"True False":tags.bool,PropertyName:tags.propertyName,Null:tags.null,",":tags.separator,"[ ]":tags.squareBracket,"{ }":tags.brace}),parser=LRParser.deserialize({version:14,states:"$bOVQPOOOOQO'#Cb'#CbOnQPO'#CeOvQPO'#CjOOQO'#Cp'#CpQOQPOOOOQO'#Cg'#CgO}QPO'#CfO!SQPO'#CrOOQO,59P,59PO![QPO,59PO!aQPO'#CuOOQO,59U,59UO!iQPO,59UOVQPO,59QOqQPO'#CkO!nQPO,59^OOQO1G.k1G.kOVQPO'#ClO!vQPO,59aOOQO1G.p1G.pOOQO1G.l1G.lOOQO,59V,59VOOQO-E6i-E6iOOQO,59W,59WOOQO-E6j-E6j",stateData:"#O~OcOS~OQSORSOSSOTSOWQO]ROePO~OVXOeUO~O[[O~PVOg^O~Oh_OVfX~OVaO~OhbO[iX~O[dO~Oh_OVfa~OhbO[ia~O",goto:"!kjPPPPPPkPPkqwPPk{!RPPP!XP!ePP!hXSOR^bQWQRf_TVQ_Q`WRg`QcZRicQTOQZRQe^RhbRYQR]R",nodeNames:"⚠ JsonText True False Null Number String } { Object Property PropertyName ] [ Array",maxTerm:25,nodeProps:[["openedBy",7,"{",12,"["],["closedBy",8,"}",13,"]"]],propSources:[jsonHighlighting],skippedNodes:[0],repeatNodeCount:2,tokenData:"(|~RaXY!WYZ!W]^!Wpq!Wrs!]|}$u}!O$z!Q!R%T!R![&c![!]&t!}#O&y#P#Q'O#Y#Z'T#b#c'r#h#i(Z#o#p(r#q#r(w~!]Oc~~!`Wpq!]qr!]rs!xs#O!]#O#P!}#P;'S!];'S;=`$o<%lO!]~!}Oe~~#QXrs!]!P!Q!]#O#P!]#U#V!]#Y#Z!]#b#c!]#f#g!]#h#i!]#i#j#m~#pR!Q![#y!c!i#y#T#Z#y~#|R!Q![$V!c!i$V#T#Z$V~$YR!Q![$c!c!i$c#T#Z$c~$fR!Q![!]!c!i!]#T#Z!]~$rP;=`<%l!]~$zOh~~$}Q!Q!R%T!R![&c~%YRT~!O!P%c!g!h%w#X#Y%w~%fP!Q![%i~%nRT~!Q![%i!g!h%w#X#Y%w~%zR{|&T}!O&T!Q![&Z~&WP!Q![&Z~&`PT~!Q![&Z~&hST~!O!P%c!Q![&c!g!h%w#X#Y%w~&yOg~~'OO]~~'TO[~~'WP#T#U'Z~'^P#`#a'a~'dP#g#h'g~'jP#X#Y'm~'rOR~~'uP#i#j'x~'{P#`#a(O~(RP#`#a(U~(ZOS~~(^P#f#g(a~(dP#i#j(g~(jP#X#Y(m~(rOQ~~(wOW~~(|OV~",tokenizers:[0],topRules:{JsonText:[0,1]},tokenPrec:0});export{parser};
|
||||
BIN
media/vendor/codemirror/js/lezer-json.min.js.gz
vendored
Normal file
BIN
media/vendor/codemirror/js/lezer-json.min.js.gz
vendored
Normal file
Binary file not shown.
1862
media/vendor/codemirror/js/lezer-lr.js
vendored
Normal file
1862
media/vendor/codemirror/js/lezer-lr.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
media/vendor/codemirror/js/lezer-lr.min.js
vendored
Normal file
1
media/vendor/codemirror/js/lezer-lr.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
BIN
media/vendor/codemirror/js/lezer-lr.min.js.gz
vendored
Normal file
BIN
media/vendor/codemirror/js/lezer-lr.min.js.gz
vendored
Normal file
Binary file not shown.
2067
media/vendor/codemirror/js/lezer-markdown.js
vendored
Normal file
2067
media/vendor/codemirror/js/lezer-markdown.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
media/vendor/codemirror/js/lezer-markdown.min.js
vendored
Normal file
1
media/vendor/codemirror/js/lezer-markdown.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
BIN
media/vendor/codemirror/js/lezer-markdown.min.js.gz
vendored
Normal file
BIN
media/vendor/codemirror/js/lezer-markdown.min.js.gz
vendored
Normal file
Binary file not shown.
355
media/vendor/codemirror/js/lezer-php.js
vendored
Normal file
355
media/vendor/codemirror/js/lezer-php.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
media/vendor/codemirror/js/lezer-php.min.js
vendored
Normal file
1
media/vendor/codemirror/js/lezer-php.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
BIN
media/vendor/codemirror/js/lezer-php.min.js.gz
vendored
Normal file
BIN
media/vendor/codemirror/js/lezer-php.min.js.gz
vendored
Normal file
Binary file not shown.
143
media/vendor/codemirror/js/lezer-xml.js
vendored
Normal file
143
media/vendor/codemirror/js/lezer-xml.js
vendored
Normal file
@ -0,0 +1,143 @@
|
||||
import { ContextTracker, ExternalTokenizer, LRParser } from '@lezer/lr';
|
||||
import { styleTags, tags } from '@lezer/highlight';
|
||||
|
||||
// This file was generated by lezer-generator. You probably shouldn't edit it.
|
||||
const StartTag = 1,
|
||||
StartCloseTag = 2,
|
||||
MissingCloseTag = 3,
|
||||
mismatchedStartCloseTag = 4,
|
||||
incompleteStartCloseTag = 5,
|
||||
commentContent$1 = 35,
|
||||
piContent$1 = 36,
|
||||
cdataContent$1 = 37,
|
||||
Element = 11,
|
||||
OpenTag = 13;
|
||||
|
||||
/* Hand-written tokenizer for XML tag matching. */
|
||||
|
||||
function nameChar(ch) {
|
||||
return ch == 45 || ch == 46 || ch == 58 || ch >= 65 && ch <= 90 || ch == 95 || ch >= 97 && ch <= 122 || ch >= 161
|
||||
}
|
||||
|
||||
function isSpace(ch) {
|
||||
return ch == 9 || ch == 10 || ch == 13 || ch == 32
|
||||
}
|
||||
|
||||
let cachedName = null, cachedInput = null, cachedPos = 0;
|
||||
function tagNameAfter(input, offset) {
|
||||
let pos = input.pos + offset;
|
||||
if (cachedInput == input && cachedPos == pos) return cachedName
|
||||
while (isSpace(input.peek(offset))) offset++;
|
||||
let name = "";
|
||||
for (;;) {
|
||||
let next = input.peek(offset);
|
||||
if (!nameChar(next)) break
|
||||
name += String.fromCharCode(next);
|
||||
offset++;
|
||||
}
|
||||
cachedInput = input; cachedPos = pos;
|
||||
return cachedName = name || null
|
||||
}
|
||||
|
||||
function ElementContext(name, parent) {
|
||||
this.name = name;
|
||||
this.parent = parent;
|
||||
this.hash = parent ? parent.hash : 0;
|
||||
for (let i = 0; i < name.length; i++) this.hash += (this.hash << 4) + name.charCodeAt(i) + (name.charCodeAt(i) << 8);
|
||||
}
|
||||
|
||||
const elementContext = new ContextTracker({
|
||||
start: null,
|
||||
shift(context, term, stack, input) {
|
||||
return term == StartTag ? new ElementContext(tagNameAfter(input, 1) || "", context) : context
|
||||
},
|
||||
reduce(context, term) {
|
||||
return term == Element && context ? context.parent : context
|
||||
},
|
||||
reuse(context, node, _stack, input) {
|
||||
let type = node.type.id;
|
||||
return type == StartTag || type == OpenTag
|
||||
? new ElementContext(tagNameAfter(input, 1) || "", context) : context
|
||||
},
|
||||
hash(context) { return context ? context.hash : 0 },
|
||||
strict: false
|
||||
});
|
||||
|
||||
const startTag = new ExternalTokenizer((input, stack) => {
|
||||
if (input.next != 60 /* '<' */) return
|
||||
input.advance();
|
||||
if (input.next == 47 /* '/' */) {
|
||||
input.advance();
|
||||
let name = tagNameAfter(input, 0);
|
||||
if (!name) return input.acceptToken(incompleteStartCloseTag)
|
||||
if (stack.context && name == stack.context.name) return input.acceptToken(StartCloseTag)
|
||||
for (let cx = stack.context; cx; cx = cx.parent) if (cx.name == name) return input.acceptToken(MissingCloseTag, -2)
|
||||
input.acceptToken(mismatchedStartCloseTag);
|
||||
} else if (input.next != 33 /* '!' */ && input.next != 63 /* '?' */) {
|
||||
return input.acceptToken(StartTag)
|
||||
}
|
||||
}, {contextual: true});
|
||||
|
||||
function scanTo(type, end) {
|
||||
return new ExternalTokenizer(input => {
|
||||
for (let endPos = 0, len = 0;; len++) {
|
||||
if (input.next < 0) {
|
||||
if (len) input.acceptToken(type);
|
||||
break
|
||||
}
|
||||
if (input.next == end.charCodeAt(endPos)) {
|
||||
endPos++;
|
||||
if (endPos == end.length) {
|
||||
if (len >= end.length) input.acceptToken(type, 1 - end.length);
|
||||
break
|
||||
}
|
||||
} else {
|
||||
endPos = input.next == end.charCodeAt(0) ? 1 : 0;
|
||||
}
|
||||
input.advance();
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const commentContent = scanTo(commentContent$1, "-->");
|
||||
const piContent = scanTo(piContent$1, "?>");
|
||||
const cdataContent = scanTo(cdataContent$1, "]]>");
|
||||
|
||||
const xmlHighlighting = styleTags({
|
||||
Text: tags.content,
|
||||
"StartTag StartCloseTag EndTag SelfCloseEndTag": tags.angleBracket,
|
||||
TagName: tags.tagName,
|
||||
"MismatchedCloseTag/Tagname": [tags.tagName, tags.invalid],
|
||||
AttributeName: tags.attributeName,
|
||||
AttributeValue: tags.attributeValue,
|
||||
Is: tags.definitionOperator,
|
||||
"EntityReference CharacterReference": tags.character,
|
||||
Comment: tags.blockComment,
|
||||
ProcessingInst: tags.processingInstruction,
|
||||
DoctypeDecl: tags.documentMeta,
|
||||
Cdata: tags.special(tags.string)
|
||||
});
|
||||
|
||||
// This file was generated by lezer-generator. You probably shouldn't edit it.
|
||||
const parser = LRParser.deserialize({
|
||||
version: 14,
|
||||
states: ",SOQOaOOOrOxO'#CfOzOpO'#CiO!tOaO'#CgOOOP'#Cg'#CgO!{OrO'#CrO#TOtO'#CsO#]OpO'#CtOOOP'#DS'#DSOOOP'#Cv'#CvQQOaOOOOOW'#Cw'#CwO#eOxO,59QOOOP,59Q,59QOOOO'#Cx'#CxO#mOpO,59TO#uO!bO,59TOOOP'#C{'#C{O$TOaO,59RO$[OpO'#CoOOOP,59R,59ROOOQ'#C|'#C|O$dOrO,59^OOOP,59^,59^OOOS'#C}'#C}O$lOtO,59_OOOP,59_,59_O$tOpO,59`O$|OpO,59`OOOP-E6t-E6tOOOW-E6u-E6uOOOP1G.l1G.lOOOO-E6v-E6vO%UO!bO1G.oO%UO!bO1G.oO%dOpO'#CkO%lO!bO'#CyO%zO!bO1G.oOOOP1G.o1G.oOOOP1G.w1G.wOOOP-E6y-E6yOOOP1G.m1G.mO&VOpO,59ZO&_OpO,59ZOOOQ-E6z-E6zOOOP1G.x1G.xOOOS-E6{-E6{OOOP1G.y1G.yO&gOpO1G.zO&gOpO1G.zOOOP1G.z1G.zO&oO!bO7+$ZO&}O!bO7+$ZOOOP7+$Z7+$ZOOOP7+$c7+$cO'YOpO,59VO'bOpO,59VO'jO!bO,59eOOOO-E6w-E6wO'xOpO1G.uO'xOpO1G.uOOOP1G.u1G.uO(QOpO7+$fOOOP7+$f7+$fO(YO!bO<<GuOOOP<<Gu<<GuOOOP<<G}<<G}O'bOpO1G.qO'bOpO1G.qO(eO#tO'#CnOOOO1G.q1G.qO(sOpO7+$aOOOP7+$a7+$aOOOP<<HQ<<HQOOOPAN=aAN=aOOOPAN=iAN=iO'bOpO7+$]OOOO7+$]7+$]OOOO'#Cz'#CzO({O#tO,59YOOOO,59Y,59YOOOP<<G{<<G{OOOO<<Gw<<GwOOOO-E6x-E6xOOOO1G.t1G.t",
|
||||
stateData: ")Z~OPQOSVOTWOVWOWWOXWOiXOxPO}TO!PUO~OuZOw]O~O^`Oy^O~OPQOQcOSVOTWOVWOWWOXWOxPO}TO!PUO~ORdO~P!SOseO|gO~OthO!OjO~O^lOy^O~OuZOwoO~O^qOy^O~O[vO`sOdwOy^O~ORyO~P!SO^{Oy^O~OseO|}O~OthO!O!PO~O^!QOy^O~O[!SOy^O~O[!VO`sOd!WOy^O~Oa!YOy^O~Oy^O[mX`mXdmX~O[!VO`sOd!WO~O^!]Oy^O~O[!_Oy^O~O[!aOy^O~O[!cO`sOd!dOy^O~O[!cO`sOd!dO~Oa!eOy^O~Oy^Oz!gO~Oy^O[ma`madma~O[!jOy^O~O[!kOy^O~O[!lO`sOd!mO~OW!pOX!pOz!rO{!pO~O[!sOy^O~OW!pOX!pOz!vO{!pO~O",
|
||||
goto: "%[wPPPPPPPPPPxxP!OP!UPP!_!iP!oxxxP!u!{#R$Z$j$p$v$|PPPP%SXWORYbXRORYb_t`qru!T!U!bQ!h!YS!o!e!fR!t!nQdRRybXSORYbQYORmYQ[PRn[Q_QQkVjp_krz!R!T!X!Z!^!`!f!i!nQr`QzcQ!RlQ!TqQ!XsQ!ZtQ!^{Q!`!QQ!f!YQ!i!]R!n!eQu`S!UqrU![u!U!bR!b!TQ!q!gR!u!qQbRRxbQfTR|fQiUR!OiSXOYTaRb",
|
||||
nodeNames: "⚠ StartTag StartCloseTag MissingCloseTag StartCloseTag StartCloseTag Document Text EntityReference CharacterReference Cdata Element EndTag OpenTag TagName Attribute AttributeName Is AttributeValue CloseTag SelfCloseEndTag SelfClosingTag Comment ProcessingInst MismatchedCloseTag DoctypeDecl",
|
||||
maxTerm: 47,
|
||||
context: elementContext,
|
||||
nodeProps: [
|
||||
["closedBy", 1,"SelfCloseEndTag EndTag",13,"CloseTag MissingCloseTag"],
|
||||
["openedBy", 12,"StartTag StartCloseTag",19,"OpenTag",20,"StartTag"]
|
||||
],
|
||||
propSources: [xmlHighlighting],
|
||||
skippedNodes: [0],
|
||||
repeatNodeCount: 8,
|
||||
tokenData: "IX~R!XOX$nXY&kYZ&kZ]$n]^&k^p$npq&kqr$nrs'ssv$nvw(Zw}$n}!O*l!O!P$n!P!Q,{!Q![$n![!].e!]!^$n!^!_1v!_!`Cz!`!aDm!a!bE`!b!c$n!c!}.e!}#P$n#P#QFx#Q#R$n#R#S.e#S#T$n#T#o.e#o%W$n%W%o.e%o%p$n%p&a.e&a&b$n&b1p.e1p4U$n4U4d.e4d4e$n4e$IS.e$IS$I`$n$I`$Ib.e$Ib$Kh$n$Kh%#t.e%#t&/x$n&/x&Et.e&Et&FV$n&FV;'S.e;'S;:j1p;:j;=`&e<%l?&r$n?&r?Ah.e?Ah?BY$n?BY?Mn.e?MnO$nX$uWVP{WOr$nrs%_sv$nw!^$n!^!_%y!_;'S$n;'S;=`&e<%lO$nP%dTVPOv%_w!^%_!_;'S%_;'S;=`%s<%lO%_P%vP;=`<%l%_W&OT{WOr%ysv%yw;'S%y;'S;=`&_<%lO%yW&bP;=`<%l%yX&hP;=`<%l$n_&t_VP{WyUOX$nXY&kYZ&kZ]$n]^&k^p$npq&kqr$nrs%_sv$nw!^$n!^!_%y!_;'S$n;'S;=`&e<%lO$nZ'zTzYVPOv%_w!^%_!_;'S%_;'S;=`%s<%lO%_~(^VOp(sqs(sst)ht!](s!^;'S(s;'S;=`)b<%lO(s~(vVOp(sqs(st!](s!]!^)]!^;'S(s;'S;=`)b<%lO(s~)bOW~~)eP;=`<%l(s~)kTOp)zq!])z!^;'S)z;'S;=`*f<%lO)z~)}UOp)zq!])z!]!^*a!^;'S)z;'S;=`*f<%lO)z~*fOX~~*iP;=`<%l)zZ*sYVP{WOr$nrs%_sv$nw}$n}!O+c!O!^$n!^!_%y!_;'S$n;'S;=`&e<%lO$nZ+jYVP{WOr$nrs%_sv$nw!^$n!^!_%y!_!`$n!`!a,Y!a;'S$n;'S;=`&e<%lO$nZ,cW|QVP{WOr$nrs%_sv$nw!^$n!^!_%y!_;'S$n;'S;=`&e<%lO$n]-SYVP{WOr$nrs%_sv$nw!^$n!^!_%y!_!`$n!`!a-r!a;'S$n;'S;=`&e<%lO$n]-{WdSVP{WOr$nrs%_sv$nw!^$n!^!_%y!_;'S$n;'S;=`&e<%lO$n_.p!O`S^QVP{WOr$nrs%_sv$nw}$n}!O.e!O!P.e!P!Q$n!Q![.e![!].e!]!^$n!^!_%y!_!c$n!c!}.e!}#R$n#R#S.e#S#T$n#T#o.e#o$}$n$}%O.e%O%W$n%W%o.e%o%p$n%p&a.e&a&b$n&b1p.e1p4U.e4U4d.e4d4e$n4e$IS.e$IS$I`$n$I`$Ib.e$Ib$Je$n$Je$Jg.e$Jg$Kh$n$Kh%#t.e%#t&/x$n&/x&Et.e&Et&FV$n&FV;'S.e;'S;:j1p;:j;=`&e<%l?&r$n?&r?Ah.e?Ah?BY$n?BY?Mn.e?MnO$n_1sP;=`<%l.eX1{W{WOq%yqr2esv%yw!a%y!a!bCd!b;'S%y;'S;=`&_<%lO%yX2j]{WOr%ysv%yw}%y}!O3c!O!f%y!f!g4e!g!}%y!}#O9t#O#W%y#W#X@Q#X;'S%y;'S;=`&_<%lO%yX3hV{WOr%ysv%yw}%y}!O3}!O;'S%y;'S;=`&_<%lO%yX4UT}P{WOr%ysv%yw;'S%y;'S;=`&_<%lO%yX4jV{WOr%ysv%yw!q%y!q!r5P!r;'S%y;'S;=`&_<%lO%yX5UV{WOr%ysv%yw!e%y!e!f5k!f;'S%y;'S;=`&_<%lO%yX5pV{WOr%ysv%yw!v%y!v!w6V!w;'S%y;'S;=`&_<%lO%yX6[V{WOr%ysv%yw!{%y!{!|6q!|;'S%y;'S;=`&_<%lO%yX6vV{WOr%ysv%yw!r%y!r!s7]!s;'S%y;'S;=`&_<%lO%yX7bV{WOr%ysv%yw!g%y!g!h7w!h;'S%y;'S;=`&_<%lO%yX7|X{WOr7wrs8isv7wvw8iw!`7w!`!a9W!a;'S7w;'S;=`9n<%lO7wP8lTO!`8i!`!a8{!a;'S8i;'S;=`9Q<%lO8iP9QOiPP9TP;=`<%l8iX9_TiP{WOr%ysv%yw;'S%y;'S;=`&_<%lO%yX9qP;=`<%l7wX9yX{WOr%ysv%yw!e%y!e!f:f!f#V%y#V#W=t#W;'S%y;'S;=`&_<%lO%yX:kV{WOr%ysv%yw!f%y!f!g;Q!g;'S%y;'S;=`&_<%lO%yX;VV{WOr%ysv%yw!c%y!c!d;l!d;'S%y;'S;=`&_<%lO%yX;qV{WOr%ysv%yw!v%y!v!w<W!w;'S%y;'S;=`&_<%lO%yX<]V{WOr%ysv%yw!c%y!c!d<r!d;'S%y;'S;=`&_<%lO%yX<wV{WOr%ysv%yw!}%y!}#O=^#O;'S%y;'S;=`&_<%lO%yX=eT{WxPOr%ysv%yw;'S%y;'S;=`&_<%lO%yX=yV{WOr%ysv%yw#W%y#W#X>`#X;'S%y;'S;=`&_<%lO%yX>eV{WOr%ysv%yw#T%y#T#U>z#U;'S%y;'S;=`&_<%lO%yX?PV{WOr%ysv%yw#h%y#h#i?f#i;'S%y;'S;=`&_<%lO%yX?kV{WOr%ysv%yw#T%y#T#U<r#U;'S%y;'S;=`&_<%lO%yX@VV{WOr%ysv%yw#c%y#c#d@l#d;'S%y;'S;=`&_<%lO%yX@qV{WOr%ysv%yw#V%y#V#WAW#W;'S%y;'S;=`&_<%lO%yXA]V{WOr%ysv%yw#h%y#h#iAr#i;'S%y;'S;=`&_<%lO%yXAwV{WOr%ysv%yw#m%y#m#nB^#n;'S%y;'S;=`&_<%lO%yXBcV{WOr%ysv%yw#d%y#d#eBx#e;'S%y;'S;=`&_<%lO%yXB}V{WOr%ysv%yw#X%y#X#Y7w#Y;'S%y;'S;=`&_<%lO%yXCkT!PP{WOr%ysv%yw;'S%y;'S;=`&_<%lO%yZDTWaQVP{WOr$nrs%_sv$nw!^$n!^!_%y!_;'S$n;'S;=`&e<%lO$n_DvW[UVP{WOr$nrs%_sv$nw!^$n!^!_%y!_;'S$n;'S;=`&e<%lO$nZEgYVP{WOr$nrs%_sv$nw!^$n!^!_%y!_!`$n!`!aFV!a;'S$n;'S;=`&e<%lO$nZF`W!OQVP{WOr$nrs%_sv$nw!^$n!^!_%y!_;'S$n;'S;=`&e<%lO$nZGPYVP{WOr$nrs%_sv$nw!^$n!^!_%y!_#P$n#P#QGo#Q;'S$n;'S;=`&e<%lO$nZGvYVP{WOr$nrs%_sv$nw!^$n!^!_%y!_!`$n!`!aHf!a;'S$n;'S;=`&e<%lO$nZHoWwQVP{WOr$nrs%_sv$nw!^$n!^!_%y!_;'S$n;'S;=`&e<%lO$n",
|
||||
tokenizers: [startTag, commentContent, piContent, cdataContent, 0, 1, 2, 3],
|
||||
topRules: {"Document":[0,6]},
|
||||
tokenPrec: 0
|
||||
});
|
||||
|
||||
export { parser };
|
||||
1
media/vendor/codemirror/js/lezer-xml.min.js
vendored
Normal file
1
media/vendor/codemirror/js/lezer-xml.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
BIN
media/vendor/codemirror/js/lezer-xml.min.js.gz
vendored
Normal file
BIN
media/vendor/codemirror/js/lezer-xml.min.js.gz
vendored
Normal file
Binary file not shown.
Reference in New Issue
Block a user