Diffdown is a real-time collaborative Markdown editor/previewer built on the AT Protocol
diffdown.com
1'use strict';
2
3var common = require('@lezer/common');
4
5let nextTagID = 0;
6/**
7Highlighting tags are markers that denote a highlighting category.
8They are [associated](#highlight.styleTags) with parts of a syntax
9tree by a language mode, and then mapped to an actual CSS style by
10a [highlighter](#highlight.Highlighter).
11
12Because syntax tree node types and highlight styles have to be
13able to talk the same language, CodeMirror uses a mostly _closed_
14[vocabulary](#highlight.tags) of syntax tags (as opposed to
15traditional open string-based systems, which make it hard for
16highlighting themes to cover all the tokens produced by the
17various languages).
18
19It _is_ possible to [define](#highlight.Tag^define) your own
20highlighting tags for system-internal use (where you control both
21the language package and the highlighter), but such tags will not
22be picked up by regular highlighters (though you can derive them
23from standard tags to allow highlighters to fall back to those).
24*/
25class Tag {
26 /**
27 @internal
28 */
29 constructor(
30 /**
31 The optional name of the base tag @internal
32 */
33 name,
34 /**
35 The set of this tag and all its parent tags, starting with
36 this one itself and sorted in order of decreasing specificity.
37 */
38 set,
39 /**
40 The base unmodified tag that this one is based on, if it's
41 modified @internal
42 */
43 base,
44 /**
45 The modifiers applied to this.base @internal
46 */
47 modified) {
48 this.name = name;
49 this.set = set;
50 this.base = base;
51 this.modified = modified;
52 /**
53 @internal
54 */
55 this.id = nextTagID++;
56 }
57 toString() {
58 let { name } = this;
59 for (let mod of this.modified)
60 if (mod.name)
61 name = `${mod.name}(${name})`;
62 return name;
63 }
64 static define(nameOrParent, parent) {
65 let name = typeof nameOrParent == "string" ? nameOrParent : "?";
66 if (nameOrParent instanceof Tag)
67 parent = nameOrParent;
68 if (parent === null || parent === void 0 ? void 0 : parent.base)
69 throw new Error("Can not derive from a modified tag");
70 let tag = new Tag(name, [], null, []);
71 tag.set.push(tag);
72 if (parent)
73 for (let t of parent.set)
74 tag.set.push(t);
75 return tag;
76 }
77 /**
78 Define a tag _modifier_, which is a function that, given a tag,
79 will return a tag that is a subtag of the original. Applying the
80 same modifier to a twice tag will return the same value (`m1(t1)
81 == m1(t1)`) and applying multiple modifiers will, regardless or
82 order, produce the same tag (`m1(m2(t1)) == m2(m1(t1))`).
83
84 When multiple modifiers are applied to a given base tag, each
85 smaller set of modifiers is registered as a parent, so that for
86 example `m1(m2(m3(t1)))` is a subtype of `m1(m2(t1))`,
87 `m1(m3(t1)`, and so on.
88 */
89 static defineModifier(name) {
90 let mod = new Modifier(name);
91 return (tag) => {
92 if (tag.modified.indexOf(mod) > -1)
93 return tag;
94 return Modifier.get(tag.base || tag, tag.modified.concat(mod).sort((a, b) => a.id - b.id));
95 };
96 }
97}
98let nextModifierID = 0;
99class Modifier {
100 constructor(name) {
101 this.name = name;
102 this.instances = [];
103 this.id = nextModifierID++;
104 }
105 static get(base, mods) {
106 if (!mods.length)
107 return base;
108 let exists = mods[0].instances.find(t => t.base == base && sameArray(mods, t.modified));
109 if (exists)
110 return exists;
111 let set = [], tag = new Tag(base.name, set, base, mods);
112 for (let m of mods)
113 m.instances.push(tag);
114 let configs = powerSet(mods);
115 for (let parent of base.set)
116 if (!parent.modified.length)
117 for (let config of configs)
118 set.push(Modifier.get(parent, config));
119 return tag;
120 }
121}
122function sameArray(a, b) {
123 return a.length == b.length && a.every((x, i) => x == b[i]);
124}
125function powerSet(array) {
126 let sets = [[]];
127 for (let i = 0; i < array.length; i++) {
128 for (let j = 0, e = sets.length; j < e; j++) {
129 sets.push(sets[j].concat(array[i]));
130 }
131 }
132 return sets.sort((a, b) => b.length - a.length);
133}
134/**
135This function is used to add a set of tags to a language syntax
136via [`NodeSet.extend`](#common.NodeSet.extend) or
137[`LRParser.configure`](#lr.LRParser.configure).
138
139The argument object maps node selectors to [highlighting
140tags](#highlight.Tag) or arrays of tags.
141
142Node selectors may hold one or more (space-separated) node paths.
143Such a path can be a [node name](#common.NodeType.name), or
144multiple node names (or `*` wildcards) separated by slash
145characters, as in `"Block/Declaration/VariableName"`. Such a path
146matches the final node but only if its direct parent nodes are the
147other nodes mentioned. A `*` in such a path matches any parent,
148but only a single level—wildcards that match multiple parents
149aren't supported, both for efficiency reasons and because Lezer
150trees make it rather hard to reason about what they would match.)
151
152A path can be ended with `/...` to indicate that the tag assigned
153to the node should also apply to all child nodes, even if they
154match their own style (by default, only the innermost style is
155used).
156
157When a path ends in `!`, as in `Attribute!`, no further matching
158happens for the node's child nodes, and the entire node gets the
159given style.
160
161In this notation, node names that contain `/`, `!`, `*`, or `...`
162must be quoted as JSON strings.
163
164For example:
165
166```javascript
167parser.configure({props: [
168 styleTags({
169 // Style Number and BigNumber nodes
170 "Number BigNumber": tags.number,
171 // Style Escape nodes whose parent is String
172 "String/Escape": tags.escape,
173 // Style anything inside Attributes nodes
174 "Attributes!": tags.meta,
175 // Add a style to all content inside Italic nodes
176 "Italic/...": tags.emphasis,
177 // Style InvalidString nodes as both `string` and `invalid`
178 "InvalidString": [tags.string, tags.invalid],
179 // Style the node named "/" as punctuation
180 '"/"': tags.punctuation
181 })
182]})
183```
184*/
185function styleTags(spec) {
186 let byName = Object.create(null);
187 for (let prop in spec) {
188 let tags = spec[prop];
189 if (!Array.isArray(tags))
190 tags = [tags];
191 for (let part of prop.split(" "))
192 if (part) {
193 let pieces = [], mode = 2 /* Mode.Normal */, rest = part;
194 for (let pos = 0;;) {
195 if (rest == "..." && pos > 0 && pos + 3 == part.length) {
196 mode = 1 /* Mode.Inherit */;
197 break;
198 }
199 let m = /^"(?:[^"\\]|\\.)*?"|[^\/!]+/.exec(rest);
200 if (!m)
201 throw new RangeError("Invalid path: " + part);
202 pieces.push(m[0] == "*" ? "" : m[0][0] == '"' ? JSON.parse(m[0]) : m[0]);
203 pos += m[0].length;
204 if (pos == part.length)
205 break;
206 let next = part[pos++];
207 if (pos == part.length && next == "!") {
208 mode = 0 /* Mode.Opaque */;
209 break;
210 }
211 if (next != "/")
212 throw new RangeError("Invalid path: " + part);
213 rest = part.slice(pos);
214 }
215 let last = pieces.length - 1, inner = pieces[last];
216 if (!inner)
217 throw new RangeError("Invalid path: " + part);
218 let rule = new Rule(tags, mode, last > 0 ? pieces.slice(0, last) : null);
219 byName[inner] = rule.sort(byName[inner]);
220 }
221 }
222 return ruleNodeProp.add(byName);
223}
224const ruleNodeProp = new common.NodeProp({
225 combine(a, b) {
226 let cur, root, take;
227 while (a || b) {
228 if (!a || b && a.depth >= b.depth) {
229 take = b;
230 b = b.next;
231 }
232 else {
233 take = a;
234 a = a.next;
235 }
236 if (cur && cur.mode == take.mode && !take.context && !cur.context)
237 continue;
238 let copy = new Rule(take.tags, take.mode, take.context);
239 if (cur)
240 cur.next = copy;
241 else
242 root = copy;
243 cur = copy;
244 }
245 return root;
246 }
247});
248class Rule {
249 constructor(tags, mode, context, next) {
250 this.tags = tags;
251 this.mode = mode;
252 this.context = context;
253 this.next = next;
254 }
255 get opaque() { return this.mode == 0 /* Mode.Opaque */; }
256 get inherit() { return this.mode == 1 /* Mode.Inherit */; }
257 sort(other) {
258 if (!other || other.depth < this.depth) {
259 this.next = other;
260 return this;
261 }
262 other.next = this.sort(other.next);
263 return other;
264 }
265 get depth() { return this.context ? this.context.length : 0; }
266}
267Rule.empty = new Rule([], 2 /* Mode.Normal */, null);
268/**
269Define a [highlighter](#highlight.Highlighter) from an array of
270tag/class pairs. Classes associated with more specific tags will
271take precedence.
272*/
273function tagHighlighter(tags, options) {
274 let map = Object.create(null);
275 for (let style of tags) {
276 if (!Array.isArray(style.tag))
277 map[style.tag.id] = style.class;
278 else
279 for (let tag of style.tag)
280 map[tag.id] = style.class;
281 }
282 let { scope, all = null } = options || {};
283 return {
284 style: (tags) => {
285 let cls = all;
286 for (let tag of tags) {
287 for (let sub of tag.set) {
288 let tagClass = map[sub.id];
289 if (tagClass) {
290 cls = cls ? cls + " " + tagClass : tagClass;
291 break;
292 }
293 }
294 }
295 return cls;
296 },
297 scope
298 };
299}
300function highlightTags(highlighters, tags) {
301 let result = null;
302 for (let highlighter of highlighters) {
303 let value = highlighter.style(tags);
304 if (value)
305 result = result ? result + " " + value : value;
306 }
307 return result;
308}
309/**
310Highlight the given [tree](#common.Tree) with the given
311[highlighter](#highlight.Highlighter). Often, the higher-level
312[`highlightCode`](#highlight.highlightCode) function is easier to
313use.
314*/
315function highlightTree(tree, highlighter,
316/**
317Assign styling to a region of the text. Will be called, in order
318of position, for any ranges where more than zero classes apply.
319`classes` is a space separated string of CSS classes.
320*/
321putStyle,
322/**
323The start of the range to highlight.
324*/
325from = 0,
326/**
327The end of the range.
328*/
329to = tree.length) {
330 let builder = new HighlightBuilder(from, Array.isArray(highlighter) ? highlighter : [highlighter], putStyle);
331 builder.highlightRange(tree.cursor(), from, to, "", builder.highlighters);
332 builder.flush(to);
333}
334/**
335Highlight the given tree with the given highlighter, calling
336`putText` for every piece of text, either with a set of classes or
337with the empty string when unstyled, and `putBreak` for every line
338break.
339*/
340function highlightCode(code, tree, highlighter, putText, putBreak, from = 0, to = code.length) {
341 let pos = from;
342 function writeTo(p, classes) {
343 if (p <= pos)
344 return;
345 for (let text = code.slice(pos, p), i = 0;;) {
346 let nextBreak = text.indexOf("\n", i);
347 let upto = nextBreak < 0 ? text.length : nextBreak;
348 if (upto > i)
349 putText(text.slice(i, upto), classes);
350 if (nextBreak < 0)
351 break;
352 putBreak();
353 i = nextBreak + 1;
354 }
355 pos = p;
356 }
357 highlightTree(tree, highlighter, (from, to, classes) => {
358 writeTo(from, "");
359 writeTo(to, classes);
360 }, from, to);
361 writeTo(to, "");
362}
363class HighlightBuilder {
364 constructor(at, highlighters, span) {
365 this.at = at;
366 this.highlighters = highlighters;
367 this.span = span;
368 this.class = "";
369 }
370 startSpan(at, cls) {
371 if (cls != this.class) {
372 this.flush(at);
373 if (at > this.at)
374 this.at = at;
375 this.class = cls;
376 }
377 }
378 flush(to) {
379 if (to > this.at && this.class)
380 this.span(this.at, to, this.class);
381 }
382 highlightRange(cursor, from, to, inheritedClass, highlighters) {
383 let { type, from: start, to: end } = cursor;
384 if (start >= to || end <= from)
385 return;
386 if (type.isTop)
387 highlighters = this.highlighters.filter(h => !h.scope || h.scope(type));
388 let cls = inheritedClass;
389 let rule = getStyleTags(cursor) || Rule.empty;
390 let tagCls = highlightTags(highlighters, rule.tags);
391 if (tagCls) {
392 if (cls)
393 cls += " ";
394 cls += tagCls;
395 if (rule.mode == 1 /* Mode.Inherit */)
396 inheritedClass += (inheritedClass ? " " : "") + tagCls;
397 }
398 this.startSpan(Math.max(from, start), cls);
399 if (rule.opaque)
400 return;
401 let mounted = cursor.tree && cursor.tree.prop(common.NodeProp.mounted);
402 if (mounted && mounted.overlay) {
403 let inner = cursor.node.enter(mounted.overlay[0].from + start, 1);
404 let innerHighlighters = this.highlighters.filter(h => !h.scope || h.scope(mounted.tree.type));
405 let hasChild = cursor.firstChild();
406 for (let i = 0, pos = start;; i++) {
407 let next = i < mounted.overlay.length ? mounted.overlay[i] : null;
408 let nextPos = next ? next.from + start : end;
409 let rangeFrom = Math.max(from, pos), rangeTo = Math.min(to, nextPos);
410 if (rangeFrom < rangeTo && hasChild) {
411 while (cursor.from < rangeTo) {
412 this.highlightRange(cursor, rangeFrom, rangeTo, inheritedClass, highlighters);
413 this.startSpan(Math.min(rangeTo, cursor.to), cls);
414 if (cursor.to >= nextPos || !cursor.nextSibling())
415 break;
416 }
417 }
418 if (!next || nextPos > to)
419 break;
420 pos = next.to + start;
421 if (pos > from) {
422 this.highlightRange(inner.cursor(), Math.max(from, next.from + start), Math.min(to, pos), "", innerHighlighters);
423 this.startSpan(Math.min(to, pos), cls);
424 }
425 }
426 if (hasChild)
427 cursor.parent();
428 }
429 else if (cursor.firstChild()) {
430 if (mounted)
431 inheritedClass = "";
432 do {
433 if (cursor.to <= from)
434 continue;
435 if (cursor.from >= to)
436 break;
437 this.highlightRange(cursor, from, to, inheritedClass, highlighters);
438 this.startSpan(Math.min(to, cursor.to), cls);
439 } while (cursor.nextSibling());
440 cursor.parent();
441 }
442 }
443}
444/**
445Match a syntax node's [highlight rules](#highlight.styleTags). If
446there's a match, return its set of tags, and whether it is
447opaque (uses a `!`) or applies to all child nodes (`/...`).
448*/
449function getStyleTags(node) {
450 let rule = node.type.prop(ruleNodeProp);
451 while (rule && rule.context && !node.matchContext(rule.context))
452 rule = rule.next;
453 return rule || null;
454}
455const t = Tag.define;
456const 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();
457/**
458The default set of highlighting [tags](#highlight.Tag).
459
460This collection is heavily biased towards programming languages,
461and necessarily incomplete. A full ontology of syntactic
462constructs would fill a stack of books, and be impractical to
463write themes for. So try to make do with this set. If all else
464fails, [open an
465issue](https://github.com/codemirror/codemirror.next) to propose a
466new tag, or [define](#highlight.Tag^define) a local custom tag for
467your use case.
468
469Note that it is not obligatory to always attach the most specific
470tag possible to an element—if your grammar can't easily
471distinguish a certain type of element (such as a local variable),
472it is okay to style it as its more general variant (a variable).
473
474For tags that extend some parent tag, the documentation links to
475the parent.
476*/
477const tags = {
478 /**
479 A comment.
480 */
481 comment,
482 /**
483 A line [comment](#highlight.tags.comment).
484 */
485 lineComment: t(comment),
486 /**
487 A block [comment](#highlight.tags.comment).
488 */
489 blockComment: t(comment),
490 /**
491 A documentation [comment](#highlight.tags.comment).
492 */
493 docComment: t(comment),
494 /**
495 Any kind of identifier.
496 */
497 name,
498 /**
499 The [name](#highlight.tags.name) of a variable.
500 */
501 variableName: t(name),
502 /**
503 A type [name](#highlight.tags.name).
504 */
505 typeName: typeName,
506 /**
507 A tag name (subtag of [`typeName`](#highlight.tags.typeName)).
508 */
509 tagName: t(typeName),
510 /**
511 A property or field [name](#highlight.tags.name).
512 */
513 propertyName: propertyName,
514 /**
515 An attribute name (subtag of [`propertyName`](#highlight.tags.propertyName)).
516 */
517 attributeName: t(propertyName),
518 /**
519 The [name](#highlight.tags.name) of a class.
520 */
521 className: t(name),
522 /**
523 A label [name](#highlight.tags.name).
524 */
525 labelName: t(name),
526 /**
527 A namespace [name](#highlight.tags.name).
528 */
529 namespace: t(name),
530 /**
531 The [name](#highlight.tags.name) of a macro.
532 */
533 macroName: t(name),
534 /**
535 A literal value.
536 */
537 literal,
538 /**
539 A string [literal](#highlight.tags.literal).
540 */
541 string,
542 /**
543 A documentation [string](#highlight.tags.string).
544 */
545 docString: t(string),
546 /**
547 A character literal (subtag of [string](#highlight.tags.string)).
548 */
549 character: t(string),
550 /**
551 An attribute value (subtag of [string](#highlight.tags.string)).
552 */
553 attributeValue: t(string),
554 /**
555 A number [literal](#highlight.tags.literal).
556 */
557 number,
558 /**
559 An integer [number](#highlight.tags.number) literal.
560 */
561 integer: t(number),
562 /**
563 A floating-point [number](#highlight.tags.number) literal.
564 */
565 float: t(number),
566 /**
567 A boolean [literal](#highlight.tags.literal).
568 */
569 bool: t(literal),
570 /**
571 Regular expression [literal](#highlight.tags.literal).
572 */
573 regexp: t(literal),
574 /**
575 An escape [literal](#highlight.tags.literal), for example a
576 backslash escape in a string.
577 */
578 escape: t(literal),
579 /**
580 A color [literal](#highlight.tags.literal).
581 */
582 color: t(literal),
583 /**
584 A URL [literal](#highlight.tags.literal).
585 */
586 url: t(literal),
587 /**
588 A language keyword.
589 */
590 keyword,
591 /**
592 The [keyword](#highlight.tags.keyword) for the self or this
593 object.
594 */
595 self: t(keyword),
596 /**
597 The [keyword](#highlight.tags.keyword) for null.
598 */
599 null: t(keyword),
600 /**
601 A [keyword](#highlight.tags.keyword) denoting some atomic value.
602 */
603 atom: t(keyword),
604 /**
605 A [keyword](#highlight.tags.keyword) that represents a unit.
606 */
607 unit: t(keyword),
608 /**
609 A modifier [keyword](#highlight.tags.keyword).
610 */
611 modifier: t(keyword),
612 /**
613 A [keyword](#highlight.tags.keyword) that acts as an operator.
614 */
615 operatorKeyword: t(keyword),
616 /**
617 A control-flow related [keyword](#highlight.tags.keyword).
618 */
619 controlKeyword: t(keyword),
620 /**
621 A [keyword](#highlight.tags.keyword) that defines something.
622 */
623 definitionKeyword: t(keyword),
624 /**
625 A [keyword](#highlight.tags.keyword) related to defining or
626 interfacing with modules.
627 */
628 moduleKeyword: t(keyword),
629 /**
630 An operator.
631 */
632 operator,
633 /**
634 An [operator](#highlight.tags.operator) that dereferences something.
635 */
636 derefOperator: t(operator),
637 /**
638 Arithmetic-related [operator](#highlight.tags.operator).
639 */
640 arithmeticOperator: t(operator),
641 /**
642 Logical [operator](#highlight.tags.operator).
643 */
644 logicOperator: t(operator),
645 /**
646 Bit [operator](#highlight.tags.operator).
647 */
648 bitwiseOperator: t(operator),
649 /**
650 Comparison [operator](#highlight.tags.operator).
651 */
652 compareOperator: t(operator),
653 /**
654 [Operator](#highlight.tags.operator) that updates its operand.
655 */
656 updateOperator: t(operator),
657 /**
658 [Operator](#highlight.tags.operator) that defines something.
659 */
660 definitionOperator: t(operator),
661 /**
662 Type-related [operator](#highlight.tags.operator).
663 */
664 typeOperator: t(operator),
665 /**
666 Control-flow [operator](#highlight.tags.operator).
667 */
668 controlOperator: t(operator),
669 /**
670 Program or markup punctuation.
671 */
672 punctuation,
673 /**
674 [Punctuation](#highlight.tags.punctuation) that separates
675 things.
676 */
677 separator: t(punctuation),
678 /**
679 Bracket-style [punctuation](#highlight.tags.punctuation).
680 */
681 bracket,
682 /**
683 Angle [brackets](#highlight.tags.bracket) (usually `<` and `>`
684 tokens).
685 */
686 angleBracket: t(bracket),
687 /**
688 Square [brackets](#highlight.tags.bracket) (usually `[` and `]`
689 tokens).
690 */
691 squareBracket: t(bracket),
692 /**
693 Parentheses (usually `(` and `)` tokens). Subtag of
694 [bracket](#highlight.tags.bracket).
695 */
696 paren: t(bracket),
697 /**
698 Braces (usually `{` and `}` tokens). Subtag of
699 [bracket](#highlight.tags.bracket).
700 */
701 brace: t(bracket),
702 /**
703 Content, for example plain text in XML or markup documents.
704 */
705 content,
706 /**
707 [Content](#highlight.tags.content) that represents a heading.
708 */
709 heading,
710 /**
711 A level 1 [heading](#highlight.tags.heading).
712 */
713 heading1: t(heading),
714 /**
715 A level 2 [heading](#highlight.tags.heading).
716 */
717 heading2: t(heading),
718 /**
719 A level 3 [heading](#highlight.tags.heading).
720 */
721 heading3: t(heading),
722 /**
723 A level 4 [heading](#highlight.tags.heading).
724 */
725 heading4: t(heading),
726 /**
727 A level 5 [heading](#highlight.tags.heading).
728 */
729 heading5: t(heading),
730 /**
731 A level 6 [heading](#highlight.tags.heading).
732 */
733 heading6: t(heading),
734 /**
735 A prose [content](#highlight.tags.content) separator (such as a horizontal rule).
736 */
737 contentSeparator: t(content),
738 /**
739 [Content](#highlight.tags.content) that represents a list.
740 */
741 list: t(content),
742 /**
743 [Content](#highlight.tags.content) that represents a quote.
744 */
745 quote: t(content),
746 /**
747 [Content](#highlight.tags.content) that is emphasized.
748 */
749 emphasis: t(content),
750 /**
751 [Content](#highlight.tags.content) that is styled strong.
752 */
753 strong: t(content),
754 /**
755 [Content](#highlight.tags.content) that is part of a link.
756 */
757 link: t(content),
758 /**
759 [Content](#highlight.tags.content) that is styled as code or
760 monospace.
761 */
762 monospace: t(content),
763 /**
764 [Content](#highlight.tags.content) that has a strike-through
765 style.
766 */
767 strikethrough: t(content),
768 /**
769 Inserted text in a change-tracking format.
770 */
771 inserted: t(),
772 /**
773 Deleted text.
774 */
775 deleted: t(),
776 /**
777 Changed text.
778 */
779 changed: t(),
780 /**
781 An invalid or unsyntactic element.
782 */
783 invalid: t(),
784 /**
785 Metadata or meta-instruction.
786 */
787 meta,
788 /**
789 [Metadata](#highlight.tags.meta) that applies to the entire
790 document.
791 */
792 documentMeta: t(meta),
793 /**
794 [Metadata](#highlight.tags.meta) that annotates or adds
795 attributes to a given syntactic element.
796 */
797 annotation: t(meta),
798 /**
799 Processing instruction or preprocessor directive. Subtag of
800 [meta](#highlight.tags.meta).
801 */
802 processingInstruction: t(meta),
803 /**
804 [Modifier](#highlight.Tag^defineModifier) that indicates that a
805 given element is being defined. Expected to be used with the
806 various [name](#highlight.tags.name) tags.
807 */
808 definition: Tag.defineModifier("definition"),
809 /**
810 [Modifier](#highlight.Tag^defineModifier) that indicates that
811 something is constant. Mostly expected to be used with
812 [variable names](#highlight.tags.variableName).
813 */
814 constant: Tag.defineModifier("constant"),
815 /**
816 [Modifier](#highlight.Tag^defineModifier) used to indicate that
817 a [variable](#highlight.tags.variableName) or [property
818 name](#highlight.tags.propertyName) is being called or defined
819 as a function.
820 */
821 function: Tag.defineModifier("function"),
822 /**
823 [Modifier](#highlight.Tag^defineModifier) that can be applied to
824 [names](#highlight.tags.name) to indicate that they belong to
825 the language's standard environment.
826 */
827 standard: Tag.defineModifier("standard"),
828 /**
829 [Modifier](#highlight.Tag^defineModifier) that indicates a given
830 [names](#highlight.tags.name) is local to some scope.
831 */
832 local: Tag.defineModifier("local"),
833 /**
834 A generic variant [modifier](#highlight.Tag^defineModifier) that
835 can be used to tag language-specific alternative variants of
836 some common tag. It is recommended for themes to define special
837 forms of at least the [string](#highlight.tags.string) and
838 [variable name](#highlight.tags.variableName) tags, since those
839 come up a lot.
840 */
841 special: Tag.defineModifier("special")
842};
843for (let name in tags) {
844 let val = tags[name];
845 if (val instanceof Tag)
846 val.name = name;
847}
848/**
849This is a highlighter that adds stable, predictable classes to
850tokens, for styling with external CSS.
851
852The following tags are mapped to their name prefixed with `"tok-"`
853(for example `"tok-comment"`):
854
855* [`link`](#highlight.tags.link)
856* [`heading`](#highlight.tags.heading)
857* [`emphasis`](#highlight.tags.emphasis)
858* [`strong`](#highlight.tags.strong)
859* [`keyword`](#highlight.tags.keyword)
860* [`atom`](#highlight.tags.atom)
861* [`bool`](#highlight.tags.bool)
862* [`url`](#highlight.tags.url)
863* [`labelName`](#highlight.tags.labelName)
864* [`inserted`](#highlight.tags.inserted)
865* [`deleted`](#highlight.tags.deleted)
866* [`literal`](#highlight.tags.literal)
867* [`string`](#highlight.tags.string)
868* [`number`](#highlight.tags.number)
869* [`variableName`](#highlight.tags.variableName)
870* [`typeName`](#highlight.tags.typeName)
871* [`namespace`](#highlight.tags.namespace)
872* [`className`](#highlight.tags.className)
873* [`macroName`](#highlight.tags.macroName)
874* [`propertyName`](#highlight.tags.propertyName)
875* [`operator`](#highlight.tags.operator)
876* [`comment`](#highlight.tags.comment)
877* [`meta`](#highlight.tags.meta)
878* [`punctuation`](#highlight.tags.punctuation)
879* [`invalid`](#highlight.tags.invalid)
880
881In addition, these mappings are provided:
882
883* [`regexp`](#highlight.tags.regexp),
884 [`escape`](#highlight.tags.escape), and
885 [`special`](#highlight.tags.special)[`(string)`](#highlight.tags.string)
886 are mapped to `"tok-string2"`
887* [`special`](#highlight.tags.special)[`(variableName)`](#highlight.tags.variableName)
888 to `"tok-variableName2"`
889* [`local`](#highlight.tags.local)[`(variableName)`](#highlight.tags.variableName)
890 to `"tok-variableName tok-local"`
891* [`definition`](#highlight.tags.definition)[`(variableName)`](#highlight.tags.variableName)
892 to `"tok-variableName tok-definition"`
893* [`definition`](#highlight.tags.definition)[`(propertyName)`](#highlight.tags.propertyName)
894 to `"tok-propertyName tok-definition"`
895*/
896const classHighlighter = tagHighlighter([
897 { tag: tags.link, class: "tok-link" },
898 { tag: tags.heading, class: "tok-heading" },
899 { tag: tags.emphasis, class: "tok-emphasis" },
900 { tag: tags.strong, class: "tok-strong" },
901 { tag: tags.keyword, class: "tok-keyword" },
902 { tag: tags.atom, class: "tok-atom" },
903 { tag: tags.bool, class: "tok-bool" },
904 { tag: tags.url, class: "tok-url" },
905 { tag: tags.labelName, class: "tok-labelName" },
906 { tag: tags.inserted, class: "tok-inserted" },
907 { tag: tags.deleted, class: "tok-deleted" },
908 { tag: tags.literal, class: "tok-literal" },
909 { tag: tags.string, class: "tok-string" },
910 { tag: tags.number, class: "tok-number" },
911 { tag: [tags.regexp, tags.escape, tags.special(tags.string)], class: "tok-string2" },
912 { tag: tags.variableName, class: "tok-variableName" },
913 { tag: tags.local(tags.variableName), class: "tok-variableName tok-local" },
914 { tag: tags.definition(tags.variableName), class: "tok-variableName tok-definition" },
915 { tag: tags.special(tags.variableName), class: "tok-variableName2" },
916 { tag: tags.definition(tags.propertyName), class: "tok-propertyName tok-definition" },
917 { tag: tags.typeName, class: "tok-typeName" },
918 { tag: tags.namespace, class: "tok-namespace" },
919 { tag: tags.className, class: "tok-className" },
920 { tag: tags.macroName, class: "tok-macroName" },
921 { tag: tags.propertyName, class: "tok-propertyName" },
922 { tag: tags.operator, class: "tok-operator" },
923 { tag: tags.comment, class: "tok-comment" },
924 { tag: tags.meta, class: "tok-meta" },
925 { tag: tags.invalid, class: "tok-invalid" },
926 { tag: tags.punctuation, class: "tok-punctuation" }
927]);
928
929exports.Tag = Tag;
930exports.classHighlighter = classHighlighter;
931exports.getStyleTags = getStyleTags;
932exports.highlightCode = highlightCode;
933exports.highlightTree = highlightTree;
934exports.styleTags = styleTags;
935exports.tagHighlighter = tagHighlighter;
936exports.tags = tags;