@tiptap/extension-code-block-lowlight 2.0.0-beta.9 → 2.0.0-rc.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/dist/{tiptap-extension-code-block-lowlight.cjs.js → index.cjs} +685 -964
- package/dist/index.cjs.map +1 -0
- package/dist/{tiptap-extension-code-block-lowlight.esm.js → index.js} +678 -958
- package/dist/index.js.map +1 -0
- package/dist/{tiptap-extension-code-block-lowlight.umd.js → index.umd.js} +687 -966
- package/dist/index.umd.js.map +1 -0
- package/dist/packages/extension-code-block-lowlight/src/code-block-lowlight.d.ts +2 -1
- package/dist/packages/extension-code-block-lowlight/src/lowlight-plugin.d.ts +4 -3
- package/package.json +29 -15
- package/src/code-block-lowlight.ts +10 -5
- package/src/lowlight-plugin.ts +93 -45
- package/CHANGELOG.md +0 -70
- package/LICENSE.md +0 -21
- package/dist/tiptap-extension-code-block-lowlight.bundle.umd.min.js +0 -2
- package/dist/tiptap-extension-code-block-lowlight.bundle.umd.min.js.map +0 -1
- package/dist/tiptap-extension-code-block-lowlight.cjs.js.map +0 -1
- package/dist/tiptap-extension-code-block-lowlight.esm.js.map +0 -1
- package/dist/tiptap-extension-code-block-lowlight.umd.js.map +0 -1
|
@@ -3,14 +3,16 @@
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
5
|
var CodeBlock = require('@tiptap/extension-code-block');
|
|
6
|
-
var
|
|
7
|
-
var
|
|
8
|
-
var
|
|
6
|
+
var core$1 = require('@tiptap/core');
|
|
7
|
+
var state = require('@tiptap/pm/state');
|
|
8
|
+
var view = require('@tiptap/pm/view');
|
|
9
9
|
|
|
10
10
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
11
11
|
|
|
12
12
|
var CodeBlock__default = /*#__PURE__*/_interopDefaultLegacy(CodeBlock);
|
|
13
13
|
|
|
14
|
+
var deepFreezeEs6 = {exports: {}};
|
|
15
|
+
|
|
14
16
|
function deepFreeze(obj) {
|
|
15
17
|
if (obj instanceof Map) {
|
|
16
18
|
obj.clear = obj.delete = obj.set = function () {
|
|
@@ -37,11 +39,13 @@ function deepFreeze(obj) {
|
|
|
37
39
|
return obj;
|
|
38
40
|
}
|
|
39
41
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
deepFreezeEs6.default = _default;
|
|
42
|
+
deepFreezeEs6.exports = deepFreeze;
|
|
43
|
+
deepFreezeEs6.exports.default = deepFreeze;
|
|
43
44
|
|
|
45
|
+
/** @typedef {import('highlight.js').CallbackResponse} CallbackResponse */
|
|
46
|
+
/** @typedef {import('highlight.js').CompiledMode} CompiledMode */
|
|
44
47
|
/** @implements CallbackResponse */
|
|
48
|
+
|
|
45
49
|
class Response {
|
|
46
50
|
/**
|
|
47
51
|
* @param {CompiledMode} mode
|
|
@@ -80,7 +84,7 @@ function escapeHTML(value) {
|
|
|
80
84
|
* @param {Record<string,any>[]} objects
|
|
81
85
|
* @returns {T} a single new object
|
|
82
86
|
*/
|
|
83
|
-
function inherit(original, ...objects) {
|
|
87
|
+
function inherit$1(original, ...objects) {
|
|
84
88
|
/** @type Record<string,any> */
|
|
85
89
|
const result = Object.create(null);
|
|
86
90
|
|
|
@@ -103,7 +107,7 @@ function inherit(original, ...objects) {
|
|
|
103
107
|
* @property {() => string} value
|
|
104
108
|
*/
|
|
105
109
|
|
|
106
|
-
/** @typedef {{
|
|
110
|
+
/** @typedef {{scope?: string, language?: string, sublanguage?: boolean}} Node */
|
|
107
111
|
/** @typedef {{walk: (r: Renderer) => void}} Tree */
|
|
108
112
|
/** */
|
|
109
113
|
|
|
@@ -114,7 +118,25 @@ const SPAN_CLOSE = '</span>';
|
|
|
114
118
|
*
|
|
115
119
|
* @param {Node} node */
|
|
116
120
|
const emitsWrappingTags = (node) => {
|
|
117
|
-
|
|
121
|
+
// rarely we can have a sublanguage where language is undefined
|
|
122
|
+
// TODO: track down why
|
|
123
|
+
return !!node.scope || (node.sublanguage && node.language);
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
*
|
|
128
|
+
* @param {string} name
|
|
129
|
+
* @param {{prefix:string}} options
|
|
130
|
+
*/
|
|
131
|
+
const scopeToCSSClass = (name, { prefix }) => {
|
|
132
|
+
if (name.includes(".")) {
|
|
133
|
+
const pieces = name.split(".");
|
|
134
|
+
return [
|
|
135
|
+
`${prefix}${pieces.shift()}`,
|
|
136
|
+
...(pieces.map((x, i) => `${x}${"_".repeat(i + 1)}`))
|
|
137
|
+
].join(" ");
|
|
138
|
+
}
|
|
139
|
+
return `${prefix}${name}`;
|
|
118
140
|
};
|
|
119
141
|
|
|
120
142
|
/** @type {Renderer} */
|
|
@@ -146,9 +168,11 @@ class HTMLRenderer {
|
|
|
146
168
|
openNode(node) {
|
|
147
169
|
if (!emitsWrappingTags(node)) return;
|
|
148
170
|
|
|
149
|
-
let className =
|
|
150
|
-
if (
|
|
151
|
-
className =
|
|
171
|
+
let className = "";
|
|
172
|
+
if (node.sublanguage) {
|
|
173
|
+
className = `language-${node.language}`;
|
|
174
|
+
} else {
|
|
175
|
+
className = scopeToCSSClass(node.scope, { prefix: this.classPrefix });
|
|
152
176
|
}
|
|
153
177
|
this.span(className);
|
|
154
178
|
}
|
|
@@ -181,14 +205,23 @@ class HTMLRenderer {
|
|
|
181
205
|
}
|
|
182
206
|
}
|
|
183
207
|
|
|
184
|
-
/** @typedef {{
|
|
185
|
-
/** @typedef {{
|
|
208
|
+
/** @typedef {{scope?: string, language?: string, sublanguage?: boolean, children: Node[]} | string} Node */
|
|
209
|
+
/** @typedef {{scope?: string, language?: string, sublanguage?: boolean, children: Node[]} } DataNode */
|
|
210
|
+
/** @typedef {import('highlight.js').Emitter} Emitter */
|
|
186
211
|
/** */
|
|
187
212
|
|
|
213
|
+
/** @returns {DataNode} */
|
|
214
|
+
const newNode = (opts = {}) => {
|
|
215
|
+
/** @type DataNode */
|
|
216
|
+
const result = { children: [] };
|
|
217
|
+
Object.assign(result, opts);
|
|
218
|
+
return result;
|
|
219
|
+
};
|
|
220
|
+
|
|
188
221
|
class TokenTree {
|
|
189
222
|
constructor() {
|
|
190
223
|
/** @type DataNode */
|
|
191
|
-
this.rootNode =
|
|
224
|
+
this.rootNode = newNode();
|
|
192
225
|
this.stack = [this.rootNode];
|
|
193
226
|
}
|
|
194
227
|
|
|
@@ -203,10 +236,10 @@ class TokenTree {
|
|
|
203
236
|
this.top.children.push(node);
|
|
204
237
|
}
|
|
205
238
|
|
|
206
|
-
/** @param {string}
|
|
207
|
-
openNode(
|
|
239
|
+
/** @param {string} scope */
|
|
240
|
+
openNode(scope) {
|
|
208
241
|
/** @type Node */
|
|
209
|
-
const node = {
|
|
242
|
+
const node = newNode({ scope });
|
|
210
243
|
this.add(node);
|
|
211
244
|
this.stack.push(node);
|
|
212
245
|
}
|
|
@@ -278,11 +311,11 @@ class TokenTree {
|
|
|
278
311
|
|
|
279
312
|
Minimal interface:
|
|
280
313
|
|
|
281
|
-
- addKeyword(text,
|
|
314
|
+
- addKeyword(text, scope)
|
|
282
315
|
- addText(text)
|
|
283
316
|
- addSublanguage(emitter, subLanguageName)
|
|
284
317
|
- finalize()
|
|
285
|
-
- openNode(
|
|
318
|
+
- openNode(scope)
|
|
286
319
|
- closeNode()
|
|
287
320
|
- closeAllNodes()
|
|
288
321
|
- toHTML()
|
|
@@ -303,12 +336,12 @@ class TokenTreeEmitter extends TokenTree {
|
|
|
303
336
|
|
|
304
337
|
/**
|
|
305
338
|
* @param {string} text
|
|
306
|
-
* @param {string}
|
|
339
|
+
* @param {string} scope
|
|
307
340
|
*/
|
|
308
|
-
addKeyword(text,
|
|
341
|
+
addKeyword(text, scope) {
|
|
309
342
|
if (text === "") { return; }
|
|
310
343
|
|
|
311
|
-
this.openNode(
|
|
344
|
+
this.openNode(scope);
|
|
312
345
|
this.addText(text);
|
|
313
346
|
this.closeNode();
|
|
314
347
|
}
|
|
@@ -329,8 +362,8 @@ class TokenTreeEmitter extends TokenTree {
|
|
|
329
362
|
addSublanguage(emitter, name) {
|
|
330
363
|
/** @type DataNode */
|
|
331
364
|
const node = emitter.root;
|
|
332
|
-
node.kind = name;
|
|
333
365
|
node.sublanguage = true;
|
|
366
|
+
node.language = name;
|
|
334
367
|
this.add(node);
|
|
335
368
|
}
|
|
336
369
|
|
|
@@ -348,9 +381,6 @@ class TokenTreeEmitter extends TokenTree {
|
|
|
348
381
|
* @param {string} value
|
|
349
382
|
* @returns {RegExp}
|
|
350
383
|
* */
|
|
351
|
-
function escape(value) {
|
|
352
|
-
return new RegExp(value.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&'), 'm');
|
|
353
|
-
}
|
|
354
384
|
|
|
355
385
|
/**
|
|
356
386
|
* @param {RegExp | string } re
|
|
@@ -363,6 +393,30 @@ function source(re) {
|
|
|
363
393
|
return re.source;
|
|
364
394
|
}
|
|
365
395
|
|
|
396
|
+
/**
|
|
397
|
+
* @param {RegExp | string } re
|
|
398
|
+
* @returns {string}
|
|
399
|
+
*/
|
|
400
|
+
function lookahead(re) {
|
|
401
|
+
return concat('(?=', re, ')');
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
/**
|
|
405
|
+
* @param {RegExp | string } re
|
|
406
|
+
* @returns {string}
|
|
407
|
+
*/
|
|
408
|
+
function anyNumberOfTimes(re) {
|
|
409
|
+
return concat('(?:', re, ')*');
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
/**
|
|
413
|
+
* @param {RegExp | string } re
|
|
414
|
+
* @returns {string}
|
|
415
|
+
*/
|
|
416
|
+
function optional(re) {
|
|
417
|
+
return concat('(?:', re, ')?');
|
|
418
|
+
}
|
|
419
|
+
|
|
366
420
|
/**
|
|
367
421
|
* @param {...(RegExp | string) } args
|
|
368
422
|
* @returns {string}
|
|
@@ -372,20 +426,41 @@ function concat(...args) {
|
|
|
372
426
|
return joined;
|
|
373
427
|
}
|
|
374
428
|
|
|
429
|
+
/**
|
|
430
|
+
* @param { Array<string | RegExp | Object> } args
|
|
431
|
+
* @returns {object}
|
|
432
|
+
*/
|
|
433
|
+
function stripOptionsFromArgs(args) {
|
|
434
|
+
const opts = args[args.length - 1];
|
|
435
|
+
|
|
436
|
+
if (typeof opts === 'object' && opts.constructor === Object) {
|
|
437
|
+
args.splice(args.length - 1, 1);
|
|
438
|
+
return opts;
|
|
439
|
+
} else {
|
|
440
|
+
return {};
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
/** @typedef { {capture?: boolean} } RegexEitherOptions */
|
|
445
|
+
|
|
375
446
|
/**
|
|
376
447
|
* Any of the passed expresssions may match
|
|
377
448
|
*
|
|
378
449
|
* Creates a huge this | this | that | that match
|
|
379
|
-
* @param {(RegExp | string)[] } args
|
|
450
|
+
* @param {(RegExp | string)[] | [...(RegExp | string)[], RegexEitherOptions]} args
|
|
380
451
|
* @returns {string}
|
|
381
452
|
*/
|
|
382
453
|
function either(...args) {
|
|
383
|
-
|
|
454
|
+
/** @type { object & {capture?: boolean} } */
|
|
455
|
+
const opts = stripOptionsFromArgs(args);
|
|
456
|
+
const joined = '('
|
|
457
|
+
+ (opts.capture ? "" : "?:")
|
|
458
|
+
+ args.map((x) => source(x)).join("|") + ")";
|
|
384
459
|
return joined;
|
|
385
460
|
}
|
|
386
461
|
|
|
387
462
|
/**
|
|
388
|
-
* @param {RegExp} re
|
|
463
|
+
* @param {RegExp | string} re
|
|
389
464
|
* @returns {number}
|
|
390
465
|
*/
|
|
391
466
|
function countMatchGroups(re) {
|
|
@@ -411,6 +486,7 @@ function startsWith(re, lexeme) {
|
|
|
411
486
|
// follow the '(' with a '?'.
|
|
412
487
|
const BACKREF_RE = /\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./;
|
|
413
488
|
|
|
489
|
+
// **INTERNAL** Not intended for outside usage
|
|
414
490
|
// join logically computes regexps.join(separator), but fixes the
|
|
415
491
|
// backreferences so they continue to match.
|
|
416
492
|
// it also places each individual regular expression into it's own
|
|
@@ -418,10 +494,10 @@ const BACKREF_RE = /\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./;
|
|
|
418
494
|
// is currently an exercise for the caller. :-)
|
|
419
495
|
/**
|
|
420
496
|
* @param {(string | RegExp)[]} regexps
|
|
421
|
-
* @param {string}
|
|
497
|
+
* @param {{joinWith: string}} opts
|
|
422
498
|
* @returns {string}
|
|
423
499
|
*/
|
|
424
|
-
function
|
|
500
|
+
function _rewriteBackreferences(regexps, { joinWith }) {
|
|
425
501
|
let numCaptures = 0;
|
|
426
502
|
|
|
427
503
|
return regexps.map((regex) => {
|
|
@@ -449,9 +525,12 @@ function join(regexps, separator = "|") {
|
|
|
449
525
|
}
|
|
450
526
|
}
|
|
451
527
|
return out;
|
|
452
|
-
}).map(re => `(${re})`).join(
|
|
528
|
+
}).map(re => `(${re})`).join(joinWith);
|
|
453
529
|
}
|
|
454
530
|
|
|
531
|
+
/** @typedef {import('highlight.js').Mode} Mode */
|
|
532
|
+
/** @typedef {import('highlight.js').ModeCallback} ModeCallback */
|
|
533
|
+
|
|
455
534
|
// Common regexps
|
|
456
535
|
const MATCH_NOTHING_RE = /\b\B/;
|
|
457
536
|
const IDENT_RE = '[a-zA-Z]\\w*';
|
|
@@ -473,8 +552,8 @@ const SHEBANG = (opts = {}) => {
|
|
|
473
552
|
opts.binary,
|
|
474
553
|
/\b.*/);
|
|
475
554
|
}
|
|
476
|
-
return inherit({
|
|
477
|
-
|
|
555
|
+
return inherit$1({
|
|
556
|
+
scope: 'meta',
|
|
478
557
|
begin: beginShebang,
|
|
479
558
|
end: /$/,
|
|
480
559
|
relevance: 0,
|
|
@@ -490,14 +569,14 @@ const BACKSLASH_ESCAPE = {
|
|
|
490
569
|
begin: '\\\\[\\s\\S]', relevance: 0
|
|
491
570
|
};
|
|
492
571
|
const APOS_STRING_MODE = {
|
|
493
|
-
|
|
572
|
+
scope: 'string',
|
|
494
573
|
begin: '\'',
|
|
495
574
|
end: '\'',
|
|
496
575
|
illegal: '\\n',
|
|
497
576
|
contains: [BACKSLASH_ESCAPE]
|
|
498
577
|
};
|
|
499
578
|
const QUOTE_STRING_MODE = {
|
|
500
|
-
|
|
579
|
+
scope: 'string',
|
|
501
580
|
begin: '"',
|
|
502
581
|
end: '"',
|
|
503
582
|
illegal: '\\n',
|
|
@@ -515,54 +594,88 @@ const PHRASAL_WORDS_MODE = {
|
|
|
515
594
|
* @returns {Partial<Mode>}
|
|
516
595
|
*/
|
|
517
596
|
const COMMENT = function(begin, end, modeOptions = {}) {
|
|
518
|
-
const mode = inherit(
|
|
597
|
+
const mode = inherit$1(
|
|
519
598
|
{
|
|
520
|
-
|
|
599
|
+
scope: 'comment',
|
|
521
600
|
begin,
|
|
522
601
|
end,
|
|
523
602
|
contains: []
|
|
524
603
|
},
|
|
525
604
|
modeOptions
|
|
526
605
|
);
|
|
527
|
-
mode.contains.push(PHRASAL_WORDS_MODE);
|
|
528
606
|
mode.contains.push({
|
|
529
|
-
|
|
530
|
-
|
|
607
|
+
scope: 'doctag',
|
|
608
|
+
// hack to avoid the space from being included. the space is necessary to
|
|
609
|
+
// match here to prevent the plain text rule below from gobbling up doctags
|
|
610
|
+
begin: '[ ]*(?=(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):)',
|
|
611
|
+
end: /(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):/,
|
|
612
|
+
excludeBegin: true,
|
|
531
613
|
relevance: 0
|
|
532
614
|
});
|
|
615
|
+
const ENGLISH_WORD = either(
|
|
616
|
+
// list of common 1 and 2 letter words in English
|
|
617
|
+
"I",
|
|
618
|
+
"a",
|
|
619
|
+
"is",
|
|
620
|
+
"so",
|
|
621
|
+
"us",
|
|
622
|
+
"to",
|
|
623
|
+
"at",
|
|
624
|
+
"if",
|
|
625
|
+
"in",
|
|
626
|
+
"it",
|
|
627
|
+
"on",
|
|
628
|
+
// note: this is not an exhaustive list of contractions, just popular ones
|
|
629
|
+
/[A-Za-z]+['](d|ve|re|ll|t|s|n)/, // contractions - can't we'd they're let's, etc
|
|
630
|
+
/[A-Za-z]+[-][a-z]+/, // `no-way`, etc.
|
|
631
|
+
/[A-Za-z][a-z]{2,}/ // allow capitalized words at beginning of sentences
|
|
632
|
+
);
|
|
633
|
+
// looking like plain text, more likely to be a comment
|
|
634
|
+
mode.contains.push(
|
|
635
|
+
{
|
|
636
|
+
// TODO: how to include ", (, ) without breaking grammars that use these for
|
|
637
|
+
// comment delimiters?
|
|
638
|
+
// begin: /[ ]+([()"]?([A-Za-z'-]{3,}|is|a|I|so|us|[tT][oO]|at|if|in|it|on)[.]?[()":]?([.][ ]|[ ]|\))){3}/
|
|
639
|
+
// ---
|
|
640
|
+
|
|
641
|
+
// this tries to find sequences of 3 english words in a row (without any
|
|
642
|
+
// "programming" type syntax) this gives us a strong signal that we've
|
|
643
|
+
// TRULY found a comment - vs perhaps scanning with the wrong language.
|
|
644
|
+
// It's possible to find something that LOOKS like the start of the
|
|
645
|
+
// comment - but then if there is no readable text - good chance it is a
|
|
646
|
+
// false match and not a comment.
|
|
647
|
+
//
|
|
648
|
+
// for a visual example please see:
|
|
649
|
+
// https://github.com/highlightjs/highlight.js/issues/2827
|
|
650
|
+
|
|
651
|
+
begin: concat(
|
|
652
|
+
/[ ]+/, // necessary to prevent us gobbling up doctags like /* @author Bob Mcgill */
|
|
653
|
+
'(',
|
|
654
|
+
ENGLISH_WORD,
|
|
655
|
+
/[.]?[:]?([.][ ]|[ ])/,
|
|
656
|
+
'){3}') // look for 3 words in a row
|
|
657
|
+
}
|
|
658
|
+
);
|
|
533
659
|
return mode;
|
|
534
660
|
};
|
|
535
661
|
const C_LINE_COMMENT_MODE = COMMENT('//', '$');
|
|
536
662
|
const C_BLOCK_COMMENT_MODE = COMMENT('/\\*', '\\*/');
|
|
537
663
|
const HASH_COMMENT_MODE = COMMENT('#', '$');
|
|
538
664
|
const NUMBER_MODE = {
|
|
539
|
-
|
|
665
|
+
scope: 'number',
|
|
540
666
|
begin: NUMBER_RE,
|
|
541
667
|
relevance: 0
|
|
542
668
|
};
|
|
543
669
|
const C_NUMBER_MODE = {
|
|
544
|
-
|
|
670
|
+
scope: 'number',
|
|
545
671
|
begin: C_NUMBER_RE,
|
|
546
672
|
relevance: 0
|
|
547
673
|
};
|
|
548
674
|
const BINARY_NUMBER_MODE = {
|
|
549
|
-
|
|
675
|
+
scope: 'number',
|
|
550
676
|
begin: BINARY_NUMBER_RE,
|
|
551
677
|
relevance: 0
|
|
552
678
|
};
|
|
553
|
-
const CSS_NUMBER_MODE = {
|
|
554
|
-
className: 'number',
|
|
555
|
-
begin: NUMBER_RE + '(' +
|
|
556
|
-
'%|em|ex|ch|rem' +
|
|
557
|
-
'|vw|vh|vmin|vmax' +
|
|
558
|
-
'|cm|mm|in|pt|pc|px' +
|
|
559
|
-
'|deg|grad|rad|turn' +
|
|
560
|
-
'|s|ms' +
|
|
561
|
-
'|Hz|kHz' +
|
|
562
|
-
'|dpi|dpcm|dppx' +
|
|
563
|
-
')?',
|
|
564
|
-
relevance: 0
|
|
565
|
-
};
|
|
566
679
|
const REGEXP_MODE = {
|
|
567
680
|
// this outer rule makes sure we actually have a WHOLE regex and not simply
|
|
568
681
|
// an expression such as:
|
|
@@ -572,7 +685,7 @@ const REGEXP_MODE = {
|
|
|
572
685
|
// (which will then blow up when regex's `illegal` sees the newline)
|
|
573
686
|
begin: /(?=\/[^/\n]*\/)/,
|
|
574
687
|
contains: [{
|
|
575
|
-
|
|
688
|
+
scope: 'regexp',
|
|
576
689
|
begin: /\//,
|
|
577
690
|
end: /\/[gimuy]*/,
|
|
578
691
|
illegal: /\n/,
|
|
@@ -588,12 +701,12 @@ const REGEXP_MODE = {
|
|
|
588
701
|
}]
|
|
589
702
|
};
|
|
590
703
|
const TITLE_MODE = {
|
|
591
|
-
|
|
704
|
+
scope: 'title',
|
|
592
705
|
begin: IDENT_RE,
|
|
593
706
|
relevance: 0
|
|
594
707
|
};
|
|
595
708
|
const UNDERSCORE_TITLE_MODE = {
|
|
596
|
-
|
|
709
|
+
scope: 'title',
|
|
597
710
|
begin: UNDERSCORE_IDENT_RE,
|
|
598
711
|
relevance: 0
|
|
599
712
|
};
|
|
@@ -641,7 +754,6 @@ var MODES = /*#__PURE__*/Object.freeze({
|
|
|
641
754
|
NUMBER_MODE: NUMBER_MODE,
|
|
642
755
|
C_NUMBER_MODE: C_NUMBER_MODE,
|
|
643
756
|
BINARY_NUMBER_MODE: BINARY_NUMBER_MODE,
|
|
644
|
-
CSS_NUMBER_MODE: CSS_NUMBER_MODE,
|
|
645
757
|
REGEXP_MODE: REGEXP_MODE,
|
|
646
758
|
TITLE_MODE: TITLE_MODE,
|
|
647
759
|
UNDERSCORE_TITLE_MODE: UNDERSCORE_TITLE_MODE,
|
|
@@ -649,6 +761,11 @@ var MODES = /*#__PURE__*/Object.freeze({
|
|
|
649
761
|
END_SAME_AS_BEGIN: END_SAME_AS_BEGIN
|
|
650
762
|
});
|
|
651
763
|
|
|
764
|
+
/**
|
|
765
|
+
@typedef {import('highlight.js').CallbackResponse} CallbackResponse
|
|
766
|
+
@typedef {import('highlight.js').CompilerExt} CompilerExt
|
|
767
|
+
*/
|
|
768
|
+
|
|
652
769
|
// Grammar extensions / plugins
|
|
653
770
|
// See: https://github.com/highlightjs/highlight.js/issues/2833
|
|
654
771
|
|
|
@@ -673,13 +790,24 @@ var MODES = /*#__PURE__*/Object.freeze({
|
|
|
673
790
|
* @param {RegExpMatchArray} match
|
|
674
791
|
* @param {CallbackResponse} response
|
|
675
792
|
*/
|
|
676
|
-
function
|
|
793
|
+
function skipIfHasPrecedingDot(match, response) {
|
|
677
794
|
const before = match.input[match.index - 1];
|
|
678
795
|
if (before === ".") {
|
|
679
796
|
response.ignoreMatch();
|
|
680
797
|
}
|
|
681
798
|
}
|
|
682
799
|
|
|
800
|
+
/**
|
|
801
|
+
*
|
|
802
|
+
* @type {CompilerExt}
|
|
803
|
+
*/
|
|
804
|
+
function scopeClassName(mode, _parent) {
|
|
805
|
+
// eslint-disable-next-line no-undefined
|
|
806
|
+
if (mode.className !== undefined) {
|
|
807
|
+
mode.scope = mode.className;
|
|
808
|
+
delete mode.className;
|
|
809
|
+
}
|
|
810
|
+
}
|
|
683
811
|
|
|
684
812
|
/**
|
|
685
813
|
* `beginKeywords` syntactic sugar
|
|
@@ -695,7 +823,7 @@ function beginKeywords(mode, parent) {
|
|
|
695
823
|
// doesn't allow spaces in keywords anyways and we still check for the boundary
|
|
696
824
|
// first
|
|
697
825
|
mode.begin = '\\b(' + mode.beginKeywords.split(' ').join('|') + ')(?!\\.)(?=\\b|\\s)';
|
|
698
|
-
mode.__beforeBegin =
|
|
826
|
+
mode.__beforeBegin = skipIfHasPrecedingDot;
|
|
699
827
|
mode.keywords = mode.keywords || mode.beginKeywords;
|
|
700
828
|
delete mode.beginKeywords;
|
|
701
829
|
|
|
@@ -736,6 +864,30 @@ function compileRelevance(mode, _parent) {
|
|
|
736
864
|
if (mode.relevance === undefined) mode.relevance = 1;
|
|
737
865
|
}
|
|
738
866
|
|
|
867
|
+
// allow beforeMatch to act as a "qualifier" for the match
|
|
868
|
+
// the full match begin must be [beforeMatch][begin]
|
|
869
|
+
const beforeMatchExt = (mode, parent) => {
|
|
870
|
+
if (!mode.beforeMatch) return;
|
|
871
|
+
// starts conflicts with endsParent which we need to make sure the child
|
|
872
|
+
// rule is not matched multiple times
|
|
873
|
+
if (mode.starts) throw new Error("beforeMatch cannot be used with starts");
|
|
874
|
+
|
|
875
|
+
const originalMode = Object.assign({}, mode);
|
|
876
|
+
Object.keys(mode).forEach((key) => { delete mode[key]; });
|
|
877
|
+
|
|
878
|
+
mode.keywords = originalMode.keywords;
|
|
879
|
+
mode.begin = concat(originalMode.beforeMatch, lookahead(originalMode.begin));
|
|
880
|
+
mode.starts = {
|
|
881
|
+
relevance: 0,
|
|
882
|
+
contains: [
|
|
883
|
+
Object.assign(originalMode, { endsParent: true })
|
|
884
|
+
]
|
|
885
|
+
};
|
|
886
|
+
mode.relevance = 0;
|
|
887
|
+
|
|
888
|
+
delete originalMode.beforeMatch;
|
|
889
|
+
};
|
|
890
|
+
|
|
739
891
|
// keywords that should have no default relevance value
|
|
740
892
|
const COMMON_KEYWORDS = [
|
|
741
893
|
'of',
|
|
@@ -751,7 +903,7 @@ const COMMON_KEYWORDS = [
|
|
|
751
903
|
'value' // common variable name
|
|
752
904
|
];
|
|
753
905
|
|
|
754
|
-
const
|
|
906
|
+
const DEFAULT_KEYWORD_SCOPE = "keyword";
|
|
755
907
|
|
|
756
908
|
/**
|
|
757
909
|
* Given raw keywords from a language definition, compile them.
|
|
@@ -759,22 +911,22 @@ const DEFAULT_KEYWORD_CLASSNAME = "keyword";
|
|
|
759
911
|
* @param {string | Record<string,string|string[]> | Array<string>} rawKeywords
|
|
760
912
|
* @param {boolean} caseInsensitive
|
|
761
913
|
*/
|
|
762
|
-
function compileKeywords(rawKeywords, caseInsensitive,
|
|
914
|
+
function compileKeywords(rawKeywords, caseInsensitive, scopeName = DEFAULT_KEYWORD_SCOPE) {
|
|
763
915
|
/** @type KeywordDict */
|
|
764
|
-
const compiledKeywords =
|
|
916
|
+
const compiledKeywords = Object.create(null);
|
|
765
917
|
|
|
766
918
|
// input can be a string of keywords, an array of keywords, or a object with
|
|
767
|
-
// named keys representing
|
|
919
|
+
// named keys representing scopeName (which can then point to a string or array)
|
|
768
920
|
if (typeof rawKeywords === 'string') {
|
|
769
|
-
compileList(
|
|
921
|
+
compileList(scopeName, rawKeywords.split(" "));
|
|
770
922
|
} else if (Array.isArray(rawKeywords)) {
|
|
771
|
-
compileList(
|
|
923
|
+
compileList(scopeName, rawKeywords);
|
|
772
924
|
} else {
|
|
773
|
-
Object.keys(rawKeywords).forEach(function(
|
|
925
|
+
Object.keys(rawKeywords).forEach(function(scopeName) {
|
|
774
926
|
// collapse all our objects back into the parent object
|
|
775
927
|
Object.assign(
|
|
776
928
|
compiledKeywords,
|
|
777
|
-
compileKeywords(rawKeywords[
|
|
929
|
+
compileKeywords(rawKeywords[scopeName], caseInsensitive, scopeName)
|
|
778
930
|
);
|
|
779
931
|
});
|
|
780
932
|
}
|
|
@@ -787,16 +939,16 @@ function compileKeywords(rawKeywords, caseInsensitive, className = DEFAULT_KEYWO
|
|
|
787
939
|
*
|
|
788
940
|
* Ex: "for if when while|5"
|
|
789
941
|
*
|
|
790
|
-
* @param {string}
|
|
942
|
+
* @param {string} scopeName
|
|
791
943
|
* @param {Array<string>} keywordList
|
|
792
944
|
*/
|
|
793
|
-
function compileList(
|
|
945
|
+
function compileList(scopeName, keywordList) {
|
|
794
946
|
if (caseInsensitive) {
|
|
795
947
|
keywordList = keywordList.map(x => x.toLowerCase());
|
|
796
948
|
}
|
|
797
949
|
keywordList.forEach(function(keyword) {
|
|
798
950
|
const pair = keyword.split('|');
|
|
799
|
-
compiledKeywords[pair[0]] = [
|
|
951
|
+
compiledKeywords[pair[0]] = [scopeName, scoreForKeyword(pair[0], pair[1])];
|
|
800
952
|
});
|
|
801
953
|
}
|
|
802
954
|
}
|
|
@@ -827,6 +979,183 @@ function commonKeyword(keyword) {
|
|
|
827
979
|
return COMMON_KEYWORDS.includes(keyword.toLowerCase());
|
|
828
980
|
}
|
|
829
981
|
|
|
982
|
+
/*
|
|
983
|
+
|
|
984
|
+
For the reasoning behind this please see:
|
|
985
|
+
https://github.com/highlightjs/highlight.js/issues/2880#issuecomment-747275419
|
|
986
|
+
|
|
987
|
+
*/
|
|
988
|
+
|
|
989
|
+
/**
|
|
990
|
+
* @type {Record<string, boolean>}
|
|
991
|
+
*/
|
|
992
|
+
const seenDeprecations = {};
|
|
993
|
+
|
|
994
|
+
/**
|
|
995
|
+
* @param {string} message
|
|
996
|
+
*/
|
|
997
|
+
const error = (message) => {
|
|
998
|
+
console.error(message);
|
|
999
|
+
};
|
|
1000
|
+
|
|
1001
|
+
/**
|
|
1002
|
+
* @param {string} message
|
|
1003
|
+
* @param {any} args
|
|
1004
|
+
*/
|
|
1005
|
+
const warn = (message, ...args) => {
|
|
1006
|
+
console.log(`WARN: ${message}`, ...args);
|
|
1007
|
+
};
|
|
1008
|
+
|
|
1009
|
+
/**
|
|
1010
|
+
* @param {string} version
|
|
1011
|
+
* @param {string} message
|
|
1012
|
+
*/
|
|
1013
|
+
const deprecated = (version, message) => {
|
|
1014
|
+
if (seenDeprecations[`${version}/${message}`]) return;
|
|
1015
|
+
|
|
1016
|
+
console.log(`Deprecated as of ${version}. ${message}`);
|
|
1017
|
+
seenDeprecations[`${version}/${message}`] = true;
|
|
1018
|
+
};
|
|
1019
|
+
|
|
1020
|
+
/* eslint-disable no-throw-literal */
|
|
1021
|
+
|
|
1022
|
+
/**
|
|
1023
|
+
@typedef {import('highlight.js').CompiledMode} CompiledMode
|
|
1024
|
+
*/
|
|
1025
|
+
|
|
1026
|
+
const MultiClassError = new Error();
|
|
1027
|
+
|
|
1028
|
+
/**
|
|
1029
|
+
* Renumbers labeled scope names to account for additional inner match
|
|
1030
|
+
* groups that otherwise would break everything.
|
|
1031
|
+
*
|
|
1032
|
+
* Lets say we 3 match scopes:
|
|
1033
|
+
*
|
|
1034
|
+
* { 1 => ..., 2 => ..., 3 => ... }
|
|
1035
|
+
*
|
|
1036
|
+
* So what we need is a clean match like this:
|
|
1037
|
+
*
|
|
1038
|
+
* (a)(b)(c) => [ "a", "b", "c" ]
|
|
1039
|
+
*
|
|
1040
|
+
* But this falls apart with inner match groups:
|
|
1041
|
+
*
|
|
1042
|
+
* (a)(((b)))(c) => ["a", "b", "b", "b", "c" ]
|
|
1043
|
+
*
|
|
1044
|
+
* Our scopes are now "out of alignment" and we're repeating `b` 3 times.
|
|
1045
|
+
* What needs to happen is the numbers are remapped:
|
|
1046
|
+
*
|
|
1047
|
+
* { 1 => ..., 2 => ..., 5 => ... }
|
|
1048
|
+
*
|
|
1049
|
+
* We also need to know that the ONLY groups that should be output
|
|
1050
|
+
* are 1, 2, and 5. This function handles this behavior.
|
|
1051
|
+
*
|
|
1052
|
+
* @param {CompiledMode} mode
|
|
1053
|
+
* @param {Array<RegExp | string>} regexes
|
|
1054
|
+
* @param {{key: "beginScope"|"endScope"}} opts
|
|
1055
|
+
*/
|
|
1056
|
+
function remapScopeNames(mode, regexes, { key }) {
|
|
1057
|
+
let offset = 0;
|
|
1058
|
+
const scopeNames = mode[key];
|
|
1059
|
+
/** @type Record<number,boolean> */
|
|
1060
|
+
const emit = {};
|
|
1061
|
+
/** @type Record<number,string> */
|
|
1062
|
+
const positions = {};
|
|
1063
|
+
|
|
1064
|
+
for (let i = 1; i <= regexes.length; i++) {
|
|
1065
|
+
positions[i + offset] = scopeNames[i];
|
|
1066
|
+
emit[i + offset] = true;
|
|
1067
|
+
offset += countMatchGroups(regexes[i - 1]);
|
|
1068
|
+
}
|
|
1069
|
+
// we use _emit to keep track of which match groups are "top-level" to avoid double
|
|
1070
|
+
// output from inside match groups
|
|
1071
|
+
mode[key] = positions;
|
|
1072
|
+
mode[key]._emit = emit;
|
|
1073
|
+
mode[key]._multi = true;
|
|
1074
|
+
}
|
|
1075
|
+
|
|
1076
|
+
/**
|
|
1077
|
+
* @param {CompiledMode} mode
|
|
1078
|
+
*/
|
|
1079
|
+
function beginMultiClass(mode) {
|
|
1080
|
+
if (!Array.isArray(mode.begin)) return;
|
|
1081
|
+
|
|
1082
|
+
if (mode.skip || mode.excludeBegin || mode.returnBegin) {
|
|
1083
|
+
error("skip, excludeBegin, returnBegin not compatible with beginScope: {}");
|
|
1084
|
+
throw MultiClassError;
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1087
|
+
if (typeof mode.beginScope !== "object" || mode.beginScope === null) {
|
|
1088
|
+
error("beginScope must be object");
|
|
1089
|
+
throw MultiClassError;
|
|
1090
|
+
}
|
|
1091
|
+
|
|
1092
|
+
remapScopeNames(mode, mode.begin, { key: "beginScope" });
|
|
1093
|
+
mode.begin = _rewriteBackreferences(mode.begin, { joinWith: "" });
|
|
1094
|
+
}
|
|
1095
|
+
|
|
1096
|
+
/**
|
|
1097
|
+
* @param {CompiledMode} mode
|
|
1098
|
+
*/
|
|
1099
|
+
function endMultiClass(mode) {
|
|
1100
|
+
if (!Array.isArray(mode.end)) return;
|
|
1101
|
+
|
|
1102
|
+
if (mode.skip || mode.excludeEnd || mode.returnEnd) {
|
|
1103
|
+
error("skip, excludeEnd, returnEnd not compatible with endScope: {}");
|
|
1104
|
+
throw MultiClassError;
|
|
1105
|
+
}
|
|
1106
|
+
|
|
1107
|
+
if (typeof mode.endScope !== "object" || mode.endScope === null) {
|
|
1108
|
+
error("endScope must be object");
|
|
1109
|
+
throw MultiClassError;
|
|
1110
|
+
}
|
|
1111
|
+
|
|
1112
|
+
remapScopeNames(mode, mode.end, { key: "endScope" });
|
|
1113
|
+
mode.end = _rewriteBackreferences(mode.end, { joinWith: "" });
|
|
1114
|
+
}
|
|
1115
|
+
|
|
1116
|
+
/**
|
|
1117
|
+
* this exists only to allow `scope: {}` to be used beside `match:`
|
|
1118
|
+
* Otherwise `beginScope` would necessary and that would look weird
|
|
1119
|
+
|
|
1120
|
+
{
|
|
1121
|
+
match: [ /def/, /\w+/ ]
|
|
1122
|
+
scope: { 1: "keyword" , 2: "title" }
|
|
1123
|
+
}
|
|
1124
|
+
|
|
1125
|
+
* @param {CompiledMode} mode
|
|
1126
|
+
*/
|
|
1127
|
+
function scopeSugar(mode) {
|
|
1128
|
+
if (mode.scope && typeof mode.scope === "object" && mode.scope !== null) {
|
|
1129
|
+
mode.beginScope = mode.scope;
|
|
1130
|
+
delete mode.scope;
|
|
1131
|
+
}
|
|
1132
|
+
}
|
|
1133
|
+
|
|
1134
|
+
/**
|
|
1135
|
+
* @param {CompiledMode} mode
|
|
1136
|
+
*/
|
|
1137
|
+
function MultiClass(mode) {
|
|
1138
|
+
scopeSugar(mode);
|
|
1139
|
+
|
|
1140
|
+
if (typeof mode.beginScope === "string") {
|
|
1141
|
+
mode.beginScope = { _wrap: mode.beginScope };
|
|
1142
|
+
}
|
|
1143
|
+
if (typeof mode.endScope === "string") {
|
|
1144
|
+
mode.endScope = { _wrap: mode.endScope };
|
|
1145
|
+
}
|
|
1146
|
+
|
|
1147
|
+
beginMultiClass(mode);
|
|
1148
|
+
endMultiClass(mode);
|
|
1149
|
+
}
|
|
1150
|
+
|
|
1151
|
+
/**
|
|
1152
|
+
@typedef {import('highlight.js').Mode} Mode
|
|
1153
|
+
@typedef {import('highlight.js').CompiledMode} CompiledMode
|
|
1154
|
+
@typedef {import('highlight.js').Language} Language
|
|
1155
|
+
@typedef {import('highlight.js').HLJSPlugin} HLJSPlugin
|
|
1156
|
+
@typedef {import('highlight.js').CompiledLanguage} CompiledLanguage
|
|
1157
|
+
*/
|
|
1158
|
+
|
|
830
1159
|
// compilation
|
|
831
1160
|
|
|
832
1161
|
/**
|
|
@@ -835,12 +1164,11 @@ function commonKeyword(keyword) {
|
|
|
835
1164
|
* Given the raw result of a language definition (Language), compiles this so
|
|
836
1165
|
* that it is ready for highlighting code.
|
|
837
1166
|
* @param {Language} language
|
|
838
|
-
* @param {{plugins: HLJSPlugin[]}} opts
|
|
839
1167
|
* @returns {CompiledLanguage}
|
|
840
1168
|
*/
|
|
841
|
-
function compileLanguage(language
|
|
1169
|
+
function compileLanguage(language) {
|
|
842
1170
|
/**
|
|
843
|
-
* Builds a regex with the case
|
|
1171
|
+
* Builds a regex with the case sensitivity of the current language
|
|
844
1172
|
*
|
|
845
1173
|
* @param {RegExp | string} value
|
|
846
1174
|
* @param {boolean} [global]
|
|
@@ -848,7 +1176,10 @@ function compileLanguage(language, { plugins }) {
|
|
|
848
1176
|
function langRe(value, global) {
|
|
849
1177
|
return new RegExp(
|
|
850
1178
|
source(value),
|
|
851
|
-
'm'
|
|
1179
|
+
'm'
|
|
1180
|
+
+ (language.case_insensitive ? 'i' : '')
|
|
1181
|
+
+ (language.unicodeRegex ? 'u' : '')
|
|
1182
|
+
+ (global ? 'g' : '')
|
|
852
1183
|
);
|
|
853
1184
|
}
|
|
854
1185
|
|
|
@@ -890,7 +1221,7 @@ function compileLanguage(language, { plugins }) {
|
|
|
890
1221
|
this.exec = () => null;
|
|
891
1222
|
}
|
|
892
1223
|
const terminators = this.regexes.map(el => el[1]);
|
|
893
|
-
this.matcherRe = langRe(
|
|
1224
|
+
this.matcherRe = langRe(_rewriteBackreferences(terminators, { joinWith: '|' }), true);
|
|
894
1225
|
this.lastIndex = 0;
|
|
895
1226
|
}
|
|
896
1227
|
|
|
@@ -1103,9 +1434,12 @@ function compileLanguage(language, { plugins }) {
|
|
|
1103
1434
|
if (mode.isCompiled) return cmode;
|
|
1104
1435
|
|
|
1105
1436
|
[
|
|
1437
|
+
scopeClassName,
|
|
1106
1438
|
// do this early so compiler extensions generally don't have to worry about
|
|
1107
1439
|
// the distinction between match/begin
|
|
1108
|
-
compileMatch
|
|
1440
|
+
compileMatch,
|
|
1441
|
+
MultiClass,
|
|
1442
|
+
beforeMatchExt
|
|
1109
1443
|
].forEach(ext => ext(mode, parent));
|
|
1110
1444
|
|
|
1111
1445
|
language.compilerExtensions.forEach(ext => ext(mode, parent));
|
|
@@ -1125,32 +1459,28 @@ function compileLanguage(language, { plugins }) {
|
|
|
1125
1459
|
mode.isCompiled = true;
|
|
1126
1460
|
|
|
1127
1461
|
let keywordPattern = null;
|
|
1128
|
-
if (typeof mode.keywords === "object") {
|
|
1462
|
+
if (typeof mode.keywords === "object" && mode.keywords.$pattern) {
|
|
1463
|
+
// we need a copy because keywords might be compiled multiple times
|
|
1464
|
+
// so we can't go deleting $pattern from the original on the first
|
|
1465
|
+
// pass
|
|
1466
|
+
mode.keywords = Object.assign({}, mode.keywords);
|
|
1129
1467
|
keywordPattern = mode.keywords.$pattern;
|
|
1130
1468
|
delete mode.keywords.$pattern;
|
|
1131
1469
|
}
|
|
1470
|
+
keywordPattern = keywordPattern || /\w+/;
|
|
1132
1471
|
|
|
1133
1472
|
if (mode.keywords) {
|
|
1134
1473
|
mode.keywords = compileKeywords(mode.keywords, language.case_insensitive);
|
|
1135
1474
|
}
|
|
1136
1475
|
|
|
1137
|
-
// both are not allowed
|
|
1138
|
-
if (mode.lexemes && keywordPattern) {
|
|
1139
|
-
throw new Error("ERR: Prefer `keywords.$pattern` to `mode.lexemes`, BOTH are not allowed. (see mode reference) ");
|
|
1140
|
-
}
|
|
1141
|
-
|
|
1142
|
-
// `mode.lexemes` was the old standard before we added and now recommend
|
|
1143
|
-
// using `keywords.$pattern` to pass the keyword pattern
|
|
1144
|
-
keywordPattern = keywordPattern || mode.lexemes || /\w+/;
|
|
1145
1476
|
cmode.keywordPatternRe = langRe(keywordPattern, true);
|
|
1146
1477
|
|
|
1147
1478
|
if (parent) {
|
|
1148
1479
|
if (!mode.begin) mode.begin = /\B|\b/;
|
|
1149
|
-
cmode.beginRe = langRe(
|
|
1150
|
-
if (mode.endSameAsBegin) mode.end = mode.begin;
|
|
1480
|
+
cmode.beginRe = langRe(cmode.begin);
|
|
1151
1481
|
if (!mode.end && !mode.endsWithParent) mode.end = /\B|\b/;
|
|
1152
|
-
if (mode.end) cmode.endRe = langRe(
|
|
1153
|
-
cmode.terminatorEnd = source(
|
|
1482
|
+
if (mode.end) cmode.endRe = langRe(cmode.end);
|
|
1483
|
+
cmode.terminatorEnd = source(cmode.end) || '';
|
|
1154
1484
|
if (mode.endsWithParent && parent.terminatorEnd) {
|
|
1155
1485
|
cmode.terminatorEnd += (mode.end ? '|' : '') + parent.terminatorEnd;
|
|
1156
1486
|
}
|
|
@@ -1179,7 +1509,7 @@ function compileLanguage(language, { plugins }) {
|
|
|
1179
1509
|
}
|
|
1180
1510
|
|
|
1181
1511
|
// we need a null object, which inherit will guarantee
|
|
1182
|
-
language.classNameAliases = inherit(language.classNameAliases || {});
|
|
1512
|
+
language.classNameAliases = inherit$1(language.classNameAliases || {});
|
|
1183
1513
|
|
|
1184
1514
|
return compileMode(/** @type Mode */ (language));
|
|
1185
1515
|
}
|
|
@@ -1214,7 +1544,7 @@ function dependencyOnParent(mode) {
|
|
|
1214
1544
|
function expandOrCloneMode(mode) {
|
|
1215
1545
|
if (mode.variants && !mode.cachedVariants) {
|
|
1216
1546
|
mode.cachedVariants = mode.variants.map(function(variant) {
|
|
1217
|
-
return inherit(mode, { variants: null }, variant);
|
|
1547
|
+
return inherit$1(mode, { variants: null }, variant);
|
|
1218
1548
|
});
|
|
1219
1549
|
}
|
|
1220
1550
|
|
|
@@ -1230,288 +1560,58 @@ function expandOrCloneMode(mode) {
|
|
|
1230
1560
|
// instance of ourselves, so we can be reused with many
|
|
1231
1561
|
// different parents without issue
|
|
1232
1562
|
if (dependencyOnParent(mode)) {
|
|
1233
|
-
return inherit(mode, { starts: mode.starts ? inherit(mode.starts) : null });
|
|
1563
|
+
return inherit$1(mode, { starts: mode.starts ? inherit$1(mode.starts) : null });
|
|
1234
1564
|
}
|
|
1235
1565
|
|
|
1236
1566
|
if (Object.isFrozen(mode)) {
|
|
1237
|
-
return inherit(mode);
|
|
1567
|
+
return inherit$1(mode);
|
|
1238
1568
|
}
|
|
1239
1569
|
|
|
1240
1570
|
// no special dependency issues, just return ourselves
|
|
1241
1571
|
return mode;
|
|
1242
1572
|
}
|
|
1243
1573
|
|
|
1244
|
-
var version = "
|
|
1245
|
-
|
|
1246
|
-
// @ts-nocheck
|
|
1247
|
-
|
|
1248
|
-
function hasValueOrEmptyAttribute(value) {
|
|
1249
|
-
return Boolean(value || value === "");
|
|
1250
|
-
}
|
|
1251
|
-
|
|
1252
|
-
function BuildVuePlugin(hljs) {
|
|
1253
|
-
const Component = {
|
|
1254
|
-
props: ["language", "code", "autodetect"],
|
|
1255
|
-
data: function() {
|
|
1256
|
-
return {
|
|
1257
|
-
detectedLanguage: "",
|
|
1258
|
-
unknownLanguage: false
|
|
1259
|
-
};
|
|
1260
|
-
},
|
|
1261
|
-
computed: {
|
|
1262
|
-
className() {
|
|
1263
|
-
if (this.unknownLanguage) return "";
|
|
1264
|
-
|
|
1265
|
-
return "hljs " + this.detectedLanguage;
|
|
1266
|
-
},
|
|
1267
|
-
highlighted() {
|
|
1268
|
-
// no idea what language to use, return raw code
|
|
1269
|
-
if (!this.autoDetect && !hljs.getLanguage(this.language)) {
|
|
1270
|
-
console.warn(`The language "${this.language}" you specified could not be found.`);
|
|
1271
|
-
this.unknownLanguage = true;
|
|
1272
|
-
return escapeHTML(this.code);
|
|
1273
|
-
}
|
|
1274
|
-
|
|
1275
|
-
let result = {};
|
|
1276
|
-
if (this.autoDetect) {
|
|
1277
|
-
result = hljs.highlightAuto(this.code);
|
|
1278
|
-
this.detectedLanguage = result.language;
|
|
1279
|
-
} else {
|
|
1280
|
-
result = hljs.highlight(this.language, this.code, this.ignoreIllegals);
|
|
1281
|
-
this.detectedLanguage = this.language;
|
|
1282
|
-
}
|
|
1283
|
-
return result.value;
|
|
1284
|
-
},
|
|
1285
|
-
autoDetect() {
|
|
1286
|
-
return !this.language || hasValueOrEmptyAttribute(this.autodetect);
|
|
1287
|
-
},
|
|
1288
|
-
ignoreIllegals() {
|
|
1289
|
-
return true;
|
|
1290
|
-
}
|
|
1291
|
-
},
|
|
1292
|
-
// this avoids needing to use a whole Vue compilation pipeline just
|
|
1293
|
-
// to build Highlight.js
|
|
1294
|
-
render(createElement) {
|
|
1295
|
-
return createElement("pre", {}, [
|
|
1296
|
-
createElement("code", {
|
|
1297
|
-
class: this.className,
|
|
1298
|
-
domProps: { innerHTML: this.highlighted }
|
|
1299
|
-
})
|
|
1300
|
-
]);
|
|
1301
|
-
}
|
|
1302
|
-
// template: `<pre><code :class="className" v-html="highlighted"></code></pre>`
|
|
1303
|
-
};
|
|
1304
|
-
|
|
1305
|
-
const VuePlugin = {
|
|
1306
|
-
install(Vue) {
|
|
1307
|
-
Vue.component('highlightjs', Component);
|
|
1308
|
-
}
|
|
1309
|
-
};
|
|
1574
|
+
var version = "11.6.0";
|
|
1310
1575
|
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
/** @type {HLJSPlugin} */
|
|
1317
|
-
const mergeHTMLPlugin = {
|
|
1318
|
-
"after:highlightElement": ({ el, result, text }) => {
|
|
1319
|
-
const originalStream = nodeStream(el);
|
|
1320
|
-
if (!originalStream.length) return;
|
|
1321
|
-
|
|
1322
|
-
const resultNode = document.createElement('div');
|
|
1323
|
-
resultNode.innerHTML = result.value;
|
|
1324
|
-
result.value = mergeStreams(originalStream, nodeStream(resultNode), text);
|
|
1325
|
-
}
|
|
1326
|
-
};
|
|
1327
|
-
|
|
1328
|
-
/* Stream merging support functions */
|
|
1329
|
-
|
|
1330
|
-
/**
|
|
1331
|
-
* @typedef Event
|
|
1332
|
-
* @property {'start'|'stop'} event
|
|
1333
|
-
* @property {number} offset
|
|
1334
|
-
* @property {Node} node
|
|
1335
|
-
*/
|
|
1336
|
-
|
|
1337
|
-
/**
|
|
1338
|
-
* @param {Node} node
|
|
1339
|
-
*/
|
|
1340
|
-
function tag(node) {
|
|
1341
|
-
return node.nodeName.toLowerCase();
|
|
1342
|
-
}
|
|
1343
|
-
|
|
1344
|
-
/**
|
|
1345
|
-
* @param {Node} node
|
|
1346
|
-
*/
|
|
1347
|
-
function nodeStream(node) {
|
|
1348
|
-
/** @type Event[] */
|
|
1349
|
-
const result = [];
|
|
1350
|
-
(function _nodeStream(node, offset) {
|
|
1351
|
-
for (let child = node.firstChild; child; child = child.nextSibling) {
|
|
1352
|
-
if (child.nodeType === 3) {
|
|
1353
|
-
offset += child.nodeValue.length;
|
|
1354
|
-
} else if (child.nodeType === 1) {
|
|
1355
|
-
result.push({
|
|
1356
|
-
event: 'start',
|
|
1357
|
-
offset: offset,
|
|
1358
|
-
node: child
|
|
1359
|
-
});
|
|
1360
|
-
offset = _nodeStream(child, offset);
|
|
1361
|
-
// Prevent void elements from having an end tag that would actually
|
|
1362
|
-
// double them in the output. There are more void elements in HTML
|
|
1363
|
-
// but we list only those realistically expected in code display.
|
|
1364
|
-
if (!tag(child).match(/br|hr|img|input/)) {
|
|
1365
|
-
result.push({
|
|
1366
|
-
event: 'stop',
|
|
1367
|
-
offset: offset,
|
|
1368
|
-
node: child
|
|
1369
|
-
});
|
|
1370
|
-
}
|
|
1371
|
-
}
|
|
1372
|
-
}
|
|
1373
|
-
return offset;
|
|
1374
|
-
})(node, 0);
|
|
1375
|
-
return result;
|
|
1376
|
-
}
|
|
1377
|
-
|
|
1378
|
-
/**
|
|
1379
|
-
* @param {any} original - the original stream
|
|
1380
|
-
* @param {any} highlighted - stream of the highlighted source
|
|
1381
|
-
* @param {string} value - the original source itself
|
|
1382
|
-
*/
|
|
1383
|
-
function mergeStreams(original, highlighted, value) {
|
|
1384
|
-
let processed = 0;
|
|
1385
|
-
let result = '';
|
|
1386
|
-
const nodeStack = [];
|
|
1387
|
-
|
|
1388
|
-
function selectStream() {
|
|
1389
|
-
if (!original.length || !highlighted.length) {
|
|
1390
|
-
return original.length ? original : highlighted;
|
|
1391
|
-
}
|
|
1392
|
-
if (original[0].offset !== highlighted[0].offset) {
|
|
1393
|
-
return (original[0].offset < highlighted[0].offset) ? original : highlighted;
|
|
1394
|
-
}
|
|
1395
|
-
|
|
1396
|
-
/*
|
|
1397
|
-
To avoid starting the stream just before it should stop the order is
|
|
1398
|
-
ensured that original always starts first and closes last:
|
|
1399
|
-
|
|
1400
|
-
if (event1 == 'start' && event2 == 'start')
|
|
1401
|
-
return original;
|
|
1402
|
-
if (event1 == 'start' && event2 == 'stop')
|
|
1403
|
-
return highlighted;
|
|
1404
|
-
if (event1 == 'stop' && event2 == 'start')
|
|
1405
|
-
return original;
|
|
1406
|
-
if (event1 == 'stop' && event2 == 'stop')
|
|
1407
|
-
return highlighted;
|
|
1408
|
-
|
|
1409
|
-
... which is collapsed to:
|
|
1410
|
-
*/
|
|
1411
|
-
return highlighted[0].event === 'start' ? original : highlighted;
|
|
1576
|
+
class HTMLInjectionError extends Error {
|
|
1577
|
+
constructor(reason, html) {
|
|
1578
|
+
super(reason);
|
|
1579
|
+
this.name = "HTMLInjectionError";
|
|
1580
|
+
this.html = html;
|
|
1412
1581
|
}
|
|
1413
|
-
|
|
1414
|
-
/**
|
|
1415
|
-
* @param {Node} node
|
|
1416
|
-
*/
|
|
1417
|
-
function open(node) {
|
|
1418
|
-
/** @param {Attr} attr */
|
|
1419
|
-
function attributeString(attr) {
|
|
1420
|
-
return ' ' + attr.nodeName + '="' + escapeHTML(attr.value) + '"';
|
|
1421
|
-
}
|
|
1422
|
-
// @ts-ignore
|
|
1423
|
-
result += '<' + tag(node) + [].map.call(node.attributes, attributeString).join('') + '>';
|
|
1424
|
-
}
|
|
1425
|
-
|
|
1426
|
-
/**
|
|
1427
|
-
* @param {Node} node
|
|
1428
|
-
*/
|
|
1429
|
-
function close(node) {
|
|
1430
|
-
result += '</' + tag(node) + '>';
|
|
1431
|
-
}
|
|
1432
|
-
|
|
1433
|
-
/**
|
|
1434
|
-
* @param {Event} event
|
|
1435
|
-
*/
|
|
1436
|
-
function render(event) {
|
|
1437
|
-
(event.event === 'start' ? open : close)(event.node);
|
|
1438
|
-
}
|
|
1439
|
-
|
|
1440
|
-
while (original.length || highlighted.length) {
|
|
1441
|
-
let stream = selectStream();
|
|
1442
|
-
result += escapeHTML(value.substring(processed, stream[0].offset));
|
|
1443
|
-
processed = stream[0].offset;
|
|
1444
|
-
if (stream === original) {
|
|
1445
|
-
/*
|
|
1446
|
-
On any opening or closing tag of the original markup we first close
|
|
1447
|
-
the entire highlighted node stack, then render the original tag along
|
|
1448
|
-
with all the following original tags at the same offset and then
|
|
1449
|
-
reopen all the tags on the highlighted stack.
|
|
1450
|
-
*/
|
|
1451
|
-
nodeStack.reverse().forEach(close);
|
|
1452
|
-
do {
|
|
1453
|
-
render(stream.splice(0, 1)[0]);
|
|
1454
|
-
stream = selectStream();
|
|
1455
|
-
} while (stream === original && stream.length && stream[0].offset === processed);
|
|
1456
|
-
nodeStack.reverse().forEach(open);
|
|
1457
|
-
} else {
|
|
1458
|
-
if (stream[0].event === 'start') {
|
|
1459
|
-
nodeStack.push(stream[0].node);
|
|
1460
|
-
} else {
|
|
1461
|
-
nodeStack.pop();
|
|
1462
|
-
}
|
|
1463
|
-
render(stream.splice(0, 1)[0]);
|
|
1464
|
-
}
|
|
1465
|
-
}
|
|
1466
|
-
return result + escapeHTML(value.substr(processed));
|
|
1467
1582
|
}
|
|
1468
1583
|
|
|
1469
1584
|
/*
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
https://github.com/highlightjs/highlight.js/issues/2880#issuecomment-747275419
|
|
1473
|
-
|
|
1585
|
+
Syntax highlighting with language autodetection.
|
|
1586
|
+
https://highlightjs.org/
|
|
1474
1587
|
*/
|
|
1475
1588
|
|
|
1476
1589
|
/**
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
}
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
}
|
|
1495
|
-
|
|
1496
|
-
/**
|
|
1497
|
-
* @param {string} version
|
|
1498
|
-
* @param {string} message
|
|
1499
|
-
*/
|
|
1500
|
-
const deprecated = (version, message) => {
|
|
1501
|
-
if (seenDeprecations[`${version}/${message}`]) return;
|
|
1502
|
-
|
|
1503
|
-
console.log(`Deprecated as of ${version}. ${message}`);
|
|
1504
|
-
seenDeprecations[`${version}/${message}`] = true;
|
|
1505
|
-
};
|
|
1506
|
-
|
|
1507
|
-
/*
|
|
1508
|
-
Syntax highlighting with language autodetection.
|
|
1509
|
-
https://highlightjs.org/
|
|
1590
|
+
@typedef {import('highlight.js').Mode} Mode
|
|
1591
|
+
@typedef {import('highlight.js').CompiledMode} CompiledMode
|
|
1592
|
+
@typedef {import('highlight.js').CompiledScope} CompiledScope
|
|
1593
|
+
@typedef {import('highlight.js').Language} Language
|
|
1594
|
+
@typedef {import('highlight.js').HLJSApi} HLJSApi
|
|
1595
|
+
@typedef {import('highlight.js').HLJSPlugin} HLJSPlugin
|
|
1596
|
+
@typedef {import('highlight.js').PluginEvent} PluginEvent
|
|
1597
|
+
@typedef {import('highlight.js').HLJSOptions} HLJSOptions
|
|
1598
|
+
@typedef {import('highlight.js').LanguageFn} LanguageFn
|
|
1599
|
+
@typedef {import('highlight.js').HighlightedHTMLElement} HighlightedHTMLElement
|
|
1600
|
+
@typedef {import('highlight.js').BeforeHighlightContext} BeforeHighlightContext
|
|
1601
|
+
@typedef {import('highlight.js/private').MatchType} MatchType
|
|
1602
|
+
@typedef {import('highlight.js/private').KeywordData} KeywordData
|
|
1603
|
+
@typedef {import('highlight.js/private').EnhancedMatch} EnhancedMatch
|
|
1604
|
+
@typedef {import('highlight.js/private').AnnotatedError} AnnotatedError
|
|
1605
|
+
@typedef {import('highlight.js').AutoHighlightResult} AutoHighlightResult
|
|
1606
|
+
@typedef {import('highlight.js').HighlightOptions} HighlightOptions
|
|
1607
|
+
@typedef {import('highlight.js').HighlightResult} HighlightResult
|
|
1510
1608
|
*/
|
|
1511
1609
|
|
|
1512
|
-
|
|
1513
|
-
const
|
|
1610
|
+
|
|
1611
|
+
const escape = escapeHTML;
|
|
1612
|
+
const inherit = inherit$1;
|
|
1514
1613
|
const NO_MATCH = Symbol("nomatch");
|
|
1614
|
+
const MAX_KEYWORD_HITS = 7;
|
|
1515
1615
|
|
|
1516
1616
|
/**
|
|
1517
1617
|
* @param {any} hljs - object that is extended (legacy)
|
|
@@ -1529,7 +1629,6 @@ const HLJS = function(hljs) {
|
|
|
1529
1629
|
// safe/production mode - swallows more errors, tries to keep running
|
|
1530
1630
|
// even if a single syntax or parse hits a fatal error
|
|
1531
1631
|
let SAFE_MODE = true;
|
|
1532
|
-
const fixMarkupRe = /(^(<[^>]+>|\t|)+|\n)/gm;
|
|
1533
1632
|
const LANGUAGE_NOT_FOUND = "Could not find the language '{}', did you forget to load/include a language module?";
|
|
1534
1633
|
/** @type {Language} */
|
|
1535
1634
|
const PLAINTEXT_LANGUAGE = { disableAutodetect: true, name: 'Plain text', contains: [] };
|
|
@@ -1538,11 +1637,12 @@ const HLJS = function(hljs) {
|
|
|
1538
1637
|
// calling the `hljs.configure` function.
|
|
1539
1638
|
/** @type HLJSOptions */
|
|
1540
1639
|
let options = {
|
|
1640
|
+
ignoreUnescapedHTML: false,
|
|
1641
|
+
throwUnescapedHTML: false,
|
|
1541
1642
|
noHighlightRe: /^(no-?highlight)$/i,
|
|
1542
1643
|
languageDetectRe: /\blang(?:uage)?-([\w-]+)\b/i,
|
|
1543
1644
|
classPrefix: 'hljs-',
|
|
1544
|
-
|
|
1545
|
-
useBR: false,
|
|
1645
|
+
cssSelector: 'pre code',
|
|
1546
1646
|
languages: null,
|
|
1547
1647
|
// beta configuration options, subject to change, welcome to discuss
|
|
1548
1648
|
// https://github.com/highlightjs/highlight.js/issues/1086
|
|
@@ -1592,10 +1692,9 @@ const HLJS = function(hljs) {
|
|
|
1592
1692
|
* NEW API
|
|
1593
1693
|
* highlight(code, {lang, ignoreIllegals})
|
|
1594
1694
|
*
|
|
1595
|
-
* @param {string}
|
|
1695
|
+
* @param {string} codeOrLanguageName - the language to use for highlighting
|
|
1596
1696
|
* @param {string | HighlightOptions} optionsOrCode - the code to highlight
|
|
1597
1697
|
* @param {boolean} [ignoreIllegals] - whether to ignore illegal matches, default is to bail
|
|
1598
|
-
* @param {CompiledMode} [continuation] - current continuation mode, if any
|
|
1599
1698
|
*
|
|
1600
1699
|
* @returns {HighlightResult} Result - an object that represents the result
|
|
1601
1700
|
* @property {string} language - the language name
|
|
@@ -1605,24 +1704,25 @@ const HLJS = function(hljs) {
|
|
|
1605
1704
|
* @property {CompiledMode} top - top of the current mode stack
|
|
1606
1705
|
* @property {boolean} illegal - indicates whether any illegal matches were found
|
|
1607
1706
|
*/
|
|
1608
|
-
function highlight(
|
|
1707
|
+
function highlight(codeOrLanguageName, optionsOrCode, ignoreIllegals) {
|
|
1609
1708
|
let code = "";
|
|
1610
1709
|
let languageName = "";
|
|
1611
1710
|
if (typeof optionsOrCode === "object") {
|
|
1612
|
-
code =
|
|
1711
|
+
code = codeOrLanguageName;
|
|
1613
1712
|
ignoreIllegals = optionsOrCode.ignoreIllegals;
|
|
1614
1713
|
languageName = optionsOrCode.language;
|
|
1615
|
-
// continuation not supported at all via the new API
|
|
1616
|
-
// eslint-disable-next-line no-undefined
|
|
1617
|
-
continuation = undefined;
|
|
1618
1714
|
} else {
|
|
1619
1715
|
// old API
|
|
1620
1716
|
deprecated("10.7.0", "highlight(lang, code, ...args) has been deprecated.");
|
|
1621
1717
|
deprecated("10.7.0", "Please use highlight(code, options) instead.\nhttps://github.com/highlightjs/highlight.js/issues/2277");
|
|
1622
|
-
languageName =
|
|
1718
|
+
languageName = codeOrLanguageName;
|
|
1623
1719
|
code = optionsOrCode;
|
|
1624
1720
|
}
|
|
1625
1721
|
|
|
1722
|
+
// https://github.com/highlightjs/highlight.js/issues/3149
|
|
1723
|
+
// eslint-disable-next-line no-undefined
|
|
1724
|
+
if (ignoreIllegals === undefined) { ignoreIllegals = true; }
|
|
1725
|
+
|
|
1626
1726
|
/** @type {BeforeHighlightContext} */
|
|
1627
1727
|
const context = {
|
|
1628
1728
|
code,
|
|
@@ -1636,7 +1736,7 @@ const HLJS = function(hljs) {
|
|
|
1636
1736
|
// in which case we don't even need to call highlight
|
|
1637
1737
|
const result = context.result
|
|
1638
1738
|
? context.result
|
|
1639
|
-
: _highlight(context.language, context.code, ignoreIllegals
|
|
1739
|
+
: _highlight(context.language, context.code, ignoreIllegals);
|
|
1640
1740
|
|
|
1641
1741
|
result.code = context.code;
|
|
1642
1742
|
// the plugin can change anything in result to suite it
|
|
@@ -1655,15 +1755,16 @@ const HLJS = function(hljs) {
|
|
|
1655
1755
|
* @returns {HighlightResult} - result of the highlight operation
|
|
1656
1756
|
*/
|
|
1657
1757
|
function _highlight(languageName, codeToHighlight, ignoreIllegals, continuation) {
|
|
1758
|
+
const keywordHits = Object.create(null);
|
|
1759
|
+
|
|
1658
1760
|
/**
|
|
1659
1761
|
* Return keyword data if a match is a keyword
|
|
1660
1762
|
* @param {CompiledMode} mode - current mode
|
|
1661
|
-
* @param {
|
|
1763
|
+
* @param {string} matchText - the textual match
|
|
1662
1764
|
* @returns {KeywordData | false}
|
|
1663
1765
|
*/
|
|
1664
|
-
function keywordData(mode,
|
|
1665
|
-
|
|
1666
|
-
return Object.prototype.hasOwnProperty.call(mode.keywords, matchText) && mode.keywords[matchText];
|
|
1766
|
+
function keywordData(mode, matchText) {
|
|
1767
|
+
return mode.keywords[matchText];
|
|
1667
1768
|
}
|
|
1668
1769
|
|
|
1669
1770
|
function processKeywords() {
|
|
@@ -1679,13 +1780,15 @@ const HLJS = function(hljs) {
|
|
|
1679
1780
|
|
|
1680
1781
|
while (match) {
|
|
1681
1782
|
buf += modeBuffer.substring(lastIndex, match.index);
|
|
1682
|
-
const
|
|
1783
|
+
const word = language.case_insensitive ? match[0].toLowerCase() : match[0];
|
|
1784
|
+
const data = keywordData(top, word);
|
|
1683
1785
|
if (data) {
|
|
1684
1786
|
const [kind, keywordRelevance] = data;
|
|
1685
1787
|
emitter.addText(buf);
|
|
1686
1788
|
buf = "";
|
|
1687
1789
|
|
|
1688
|
-
|
|
1790
|
+
keywordHits[word] = (keywordHits[word] || 0) + 1;
|
|
1791
|
+
if (keywordHits[word] <= MAX_KEYWORD_HITS) relevance += keywordRelevance;
|
|
1689
1792
|
if (kind.startsWith("_")) {
|
|
1690
1793
|
// _ implied for relevance only, do not highlight
|
|
1691
1794
|
// by applying a class name
|
|
@@ -1700,7 +1803,7 @@ const HLJS = function(hljs) {
|
|
|
1700
1803
|
lastIndex = top.keywordPatternRe.lastIndex;
|
|
1701
1804
|
match = top.keywordPatternRe.exec(modeBuffer);
|
|
1702
1805
|
}
|
|
1703
|
-
buf += modeBuffer.
|
|
1806
|
+
buf += modeBuffer.substring(lastIndex);
|
|
1704
1807
|
emitter.addText(buf);
|
|
1705
1808
|
}
|
|
1706
1809
|
|
|
@@ -1715,7 +1818,7 @@ const HLJS = function(hljs) {
|
|
|
1715
1818
|
return;
|
|
1716
1819
|
}
|
|
1717
1820
|
result = _highlight(top.subLanguage, modeBuffer, true, continuations[top.subLanguage]);
|
|
1718
|
-
continuations[top.subLanguage] = /** @type {CompiledMode} */ (result.
|
|
1821
|
+
continuations[top.subLanguage] = /** @type {CompiledMode} */ (result._top);
|
|
1719
1822
|
} else {
|
|
1720
1823
|
result = highlightAuto(modeBuffer, top.subLanguage.length ? top.subLanguage : null);
|
|
1721
1824
|
}
|
|
@@ -1727,7 +1830,7 @@ const HLJS = function(hljs) {
|
|
|
1727
1830
|
if (top.relevance > 0) {
|
|
1728
1831
|
relevance += result.relevance;
|
|
1729
1832
|
}
|
|
1730
|
-
emitter.addSublanguage(result.
|
|
1833
|
+
emitter.addSublanguage(result._emitter, result.language);
|
|
1731
1834
|
}
|
|
1732
1835
|
|
|
1733
1836
|
function processBuffer() {
|
|
@@ -1740,12 +1843,47 @@ const HLJS = function(hljs) {
|
|
|
1740
1843
|
}
|
|
1741
1844
|
|
|
1742
1845
|
/**
|
|
1743
|
-
* @param {
|
|
1846
|
+
* @param {CompiledScope} scope
|
|
1847
|
+
* @param {RegExpMatchArray} match
|
|
1848
|
+
*/
|
|
1849
|
+
function emitMultiClass(scope, match) {
|
|
1850
|
+
let i = 1;
|
|
1851
|
+
const max = match.length - 1;
|
|
1852
|
+
while (i <= max) {
|
|
1853
|
+
if (!scope._emit[i]) { i++; continue; }
|
|
1854
|
+
const klass = language.classNameAliases[scope[i]] || scope[i];
|
|
1855
|
+
const text = match[i];
|
|
1856
|
+
if (klass) {
|
|
1857
|
+
emitter.addKeyword(text, klass);
|
|
1858
|
+
} else {
|
|
1859
|
+
modeBuffer = text;
|
|
1860
|
+
processKeywords();
|
|
1861
|
+
modeBuffer = "";
|
|
1862
|
+
}
|
|
1863
|
+
i++;
|
|
1864
|
+
}
|
|
1865
|
+
}
|
|
1866
|
+
|
|
1867
|
+
/**
|
|
1868
|
+
* @param {CompiledMode} mode - new mode to start
|
|
1869
|
+
* @param {RegExpMatchArray} match
|
|
1744
1870
|
*/
|
|
1745
|
-
function startNewMode(mode) {
|
|
1746
|
-
if (mode.
|
|
1747
|
-
emitter.openNode(language.classNameAliases[mode.
|
|
1871
|
+
function startNewMode(mode, match) {
|
|
1872
|
+
if (mode.scope && typeof mode.scope === "string") {
|
|
1873
|
+
emitter.openNode(language.classNameAliases[mode.scope] || mode.scope);
|
|
1748
1874
|
}
|
|
1875
|
+
if (mode.beginScope) {
|
|
1876
|
+
// beginScope just wraps the begin match itself in a scope
|
|
1877
|
+
if (mode.beginScope._wrap) {
|
|
1878
|
+
emitter.addKeyword(modeBuffer, language.classNameAliases[mode.beginScope._wrap] || mode.beginScope._wrap);
|
|
1879
|
+
modeBuffer = "";
|
|
1880
|
+
} else if (mode.beginScope._multi) {
|
|
1881
|
+
// at this point modeBuffer should just be the match
|
|
1882
|
+
emitMultiClass(mode.beginScope, match);
|
|
1883
|
+
modeBuffer = "";
|
|
1884
|
+
}
|
|
1885
|
+
}
|
|
1886
|
+
|
|
1749
1887
|
top = Object.create(mode, { parent: { value: top } });
|
|
1750
1888
|
return top;
|
|
1751
1889
|
}
|
|
@@ -1787,7 +1925,7 @@ const HLJS = function(hljs) {
|
|
|
1787
1925
|
*/
|
|
1788
1926
|
function doIgnore(lexeme) {
|
|
1789
1927
|
if (top.matcher.regexIndex === 0) {
|
|
1790
|
-
// no more
|
|
1928
|
+
// no more regexes to potentially match here, so we move the cursor forward one
|
|
1791
1929
|
// space
|
|
1792
1930
|
modeBuffer += lexeme[0];
|
|
1793
1931
|
return 1;
|
|
@@ -1818,10 +1956,6 @@ const HLJS = function(hljs) {
|
|
|
1818
1956
|
if (resp.isMatchIgnored) return doIgnore(lexeme);
|
|
1819
1957
|
}
|
|
1820
1958
|
|
|
1821
|
-
if (newMode && newMode.endSameAsBegin) {
|
|
1822
|
-
newMode.endRe = escape(lexeme);
|
|
1823
|
-
}
|
|
1824
|
-
|
|
1825
1959
|
if (newMode.skip) {
|
|
1826
1960
|
modeBuffer += lexeme;
|
|
1827
1961
|
} else {
|
|
@@ -1833,11 +1967,7 @@ const HLJS = function(hljs) {
|
|
|
1833
1967
|
modeBuffer = lexeme;
|
|
1834
1968
|
}
|
|
1835
1969
|
}
|
|
1836
|
-
startNewMode(newMode);
|
|
1837
|
-
// if (mode["after:begin"]) {
|
|
1838
|
-
// let resp = new Response(mode);
|
|
1839
|
-
// mode["after:begin"](match, resp);
|
|
1840
|
-
// }
|
|
1970
|
+
startNewMode(newMode, match);
|
|
1841
1971
|
return newMode.returnBegin ? 0 : lexeme.length;
|
|
1842
1972
|
}
|
|
1843
1973
|
|
|
@@ -1848,13 +1978,19 @@ const HLJS = function(hljs) {
|
|
|
1848
1978
|
*/
|
|
1849
1979
|
function doEndMatch(match) {
|
|
1850
1980
|
const lexeme = match[0];
|
|
1851
|
-
const matchPlusRemainder = codeToHighlight.
|
|
1981
|
+
const matchPlusRemainder = codeToHighlight.substring(match.index);
|
|
1852
1982
|
|
|
1853
1983
|
const endMode = endOfMode(top, match, matchPlusRemainder);
|
|
1854
1984
|
if (!endMode) { return NO_MATCH; }
|
|
1855
1985
|
|
|
1856
1986
|
const origin = top;
|
|
1857
|
-
if (
|
|
1987
|
+
if (top.endScope && top.endScope._wrap) {
|
|
1988
|
+
processBuffer();
|
|
1989
|
+
emitter.addKeyword(lexeme, top.endScope._wrap);
|
|
1990
|
+
} else if (top.endScope && top.endScope._multi) {
|
|
1991
|
+
processBuffer();
|
|
1992
|
+
emitMultiClass(top.endScope, match);
|
|
1993
|
+
} else if (origin.skip) {
|
|
1858
1994
|
modeBuffer += lexeme;
|
|
1859
1995
|
} else {
|
|
1860
1996
|
if (!(origin.returnEnd || origin.excludeEnd)) {
|
|
@@ -1866,7 +2002,7 @@ const HLJS = function(hljs) {
|
|
|
1866
2002
|
}
|
|
1867
2003
|
}
|
|
1868
2004
|
do {
|
|
1869
|
-
if (top.
|
|
2005
|
+
if (top.scope) {
|
|
1870
2006
|
emitter.closeNode();
|
|
1871
2007
|
}
|
|
1872
2008
|
if (!top.skip && !top.subLanguage) {
|
|
@@ -1875,10 +2011,7 @@ const HLJS = function(hljs) {
|
|
|
1875
2011
|
top = top.parent;
|
|
1876
2012
|
} while (top !== endMode.parent);
|
|
1877
2013
|
if (endMode.starts) {
|
|
1878
|
-
|
|
1879
|
-
endMode.starts.endRe = endMode.endRe;
|
|
1880
|
-
}
|
|
1881
|
-
startNewMode(endMode.starts);
|
|
2014
|
+
startNewMode(endMode.starts, match);
|
|
1882
2015
|
}
|
|
1883
2016
|
return origin.returnEnd ? 0 : lexeme.length;
|
|
1884
2017
|
}
|
|
@@ -1886,8 +2019,8 @@ const HLJS = function(hljs) {
|
|
|
1886
2019
|
function processContinuations() {
|
|
1887
2020
|
const list = [];
|
|
1888
2021
|
for (let current = top; current !== language; current = current.parent) {
|
|
1889
|
-
if (current.
|
|
1890
|
-
list.unshift(current.
|
|
2022
|
+
if (current.scope) {
|
|
2023
|
+
list.unshift(current.scope);
|
|
1891
2024
|
}
|
|
1892
2025
|
}
|
|
1893
2026
|
list.forEach(item => emitter.openNode(item));
|
|
@@ -1899,7 +2032,7 @@ const HLJS = function(hljs) {
|
|
|
1899
2032
|
/**
|
|
1900
2033
|
* Process an individual match
|
|
1901
2034
|
*
|
|
1902
|
-
* @param {string} textBeforeMatch - text
|
|
2035
|
+
* @param {string} textBeforeMatch - text preceding the match (since the last match)
|
|
1903
2036
|
* @param {EnhancedMatch} [match] - the match itself
|
|
1904
2037
|
*/
|
|
1905
2038
|
function processLexeme(textBeforeMatch, match) {
|
|
@@ -1922,7 +2055,7 @@ const HLJS = function(hljs) {
|
|
|
1922
2055
|
modeBuffer += codeToHighlight.slice(match.index, match.index + 1);
|
|
1923
2056
|
if (!SAFE_MODE) {
|
|
1924
2057
|
/** @type {AnnotatedError} */
|
|
1925
|
-
const err = new Error(
|
|
2058
|
+
const err = new Error(`0 width match regex (${languageName})`);
|
|
1926
2059
|
err.languageName = languageName;
|
|
1927
2060
|
err.badRule = lastMatch.rule;
|
|
1928
2061
|
throw err;
|
|
@@ -1936,7 +2069,7 @@ const HLJS = function(hljs) {
|
|
|
1936
2069
|
} else if (match.type === "illegal" && !ignoreIllegals) {
|
|
1937
2070
|
// illegal match, we do not continue processing
|
|
1938
2071
|
/** @type {AnnotatedError} */
|
|
1939
|
-
const err = new Error('Illegal lexeme "' + lexeme + '" for mode "' + (top.
|
|
2072
|
+
const err = new Error('Illegal lexeme "' + lexeme + '" for mode "' + (top.scope || '<unnamed>') + '"');
|
|
1940
2073
|
err.mode = top;
|
|
1941
2074
|
throw err;
|
|
1942
2075
|
} else if (match.type === "end") {
|
|
@@ -1964,13 +2097,9 @@ const HLJS = function(hljs) {
|
|
|
1964
2097
|
}
|
|
1965
2098
|
|
|
1966
2099
|
/*
|
|
1967
|
-
Why might be find ourselves here?
|
|
1968
|
-
triggered but could not be completed.
|
|
1969
|
-
|
|
1970
|
-
being used to scan the text isn't recompiled that means that any match that LOOKS like
|
|
1971
|
-
the end (but is not, because it is not an exact match to the beginning) will
|
|
1972
|
-
end up here. A definite end match, but when `doEndMatch` tries to "reapply"
|
|
1973
|
-
the end rule and fails to match, we wind up here, and just silently ignore the end.
|
|
2100
|
+
Why might be find ourselves here? An potential end match that was
|
|
2101
|
+
triggered but could not be completed. IE, `doEndMatch` returned NO_MATCH.
|
|
2102
|
+
(this could be because a callback requests the match be ignored, etc)
|
|
1974
2103
|
|
|
1975
2104
|
This causes no real harm other than stopping a few times too many.
|
|
1976
2105
|
*/
|
|
@@ -1985,7 +2114,7 @@ const HLJS = function(hljs) {
|
|
|
1985
2114
|
throw new Error('Unknown language: "' + languageName + '"');
|
|
1986
2115
|
}
|
|
1987
2116
|
|
|
1988
|
-
const md = compileLanguage(language
|
|
2117
|
+
const md = compileLanguage(language);
|
|
1989
2118
|
let result = '';
|
|
1990
2119
|
/** @type {CompiledMode} */
|
|
1991
2120
|
let top = continuation || md;
|
|
@@ -2022,44 +2151,44 @@ const HLJS = function(hljs) {
|
|
|
2022
2151
|
const processedCount = processLexeme(beforeMatch, match);
|
|
2023
2152
|
index = match.index + processedCount;
|
|
2024
2153
|
}
|
|
2025
|
-
processLexeme(codeToHighlight.
|
|
2154
|
+
processLexeme(codeToHighlight.substring(index));
|
|
2026
2155
|
emitter.closeAllNodes();
|
|
2027
2156
|
emitter.finalize();
|
|
2028
2157
|
result = emitter.toHTML();
|
|
2029
2158
|
|
|
2030
2159
|
return {
|
|
2031
|
-
// avoid possible breakage with v10 clients expecting
|
|
2032
|
-
// this to always be an integer
|
|
2033
|
-
relevance: Math.floor(relevance),
|
|
2034
|
-
value: result,
|
|
2035
2160
|
language: languageName,
|
|
2161
|
+
value: result,
|
|
2162
|
+
relevance: relevance,
|
|
2036
2163
|
illegal: false,
|
|
2037
|
-
|
|
2038
|
-
|
|
2164
|
+
_emitter: emitter,
|
|
2165
|
+
_top: top
|
|
2039
2166
|
};
|
|
2040
2167
|
} catch (err) {
|
|
2041
2168
|
if (err.message && err.message.includes('Illegal')) {
|
|
2042
2169
|
return {
|
|
2170
|
+
language: languageName,
|
|
2171
|
+
value: escape(codeToHighlight),
|
|
2043
2172
|
illegal: true,
|
|
2044
|
-
|
|
2045
|
-
|
|
2173
|
+
relevance: 0,
|
|
2174
|
+
_illegalBy: {
|
|
2175
|
+
message: err.message,
|
|
2176
|
+
index: index,
|
|
2046
2177
|
context: codeToHighlight.slice(index - 100, index + 100),
|
|
2047
|
-
mode: err.mode
|
|
2178
|
+
mode: err.mode,
|
|
2179
|
+
resultSoFar: result
|
|
2048
2180
|
},
|
|
2049
|
-
|
|
2050
|
-
relevance: 0,
|
|
2051
|
-
value: escape$1(codeToHighlight),
|
|
2052
|
-
emitter: emitter
|
|
2181
|
+
_emitter: emitter
|
|
2053
2182
|
};
|
|
2054
2183
|
} else if (SAFE_MODE) {
|
|
2055
2184
|
return {
|
|
2185
|
+
language: languageName,
|
|
2186
|
+
value: escape(codeToHighlight),
|
|
2056
2187
|
illegal: false,
|
|
2057
2188
|
relevance: 0,
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
top: top,
|
|
2062
|
-
errorRaised: err
|
|
2189
|
+
errorRaised: err,
|
|
2190
|
+
_emitter: emitter,
|
|
2191
|
+
_top: top
|
|
2063
2192
|
};
|
|
2064
2193
|
} else {
|
|
2065
2194
|
throw err;
|
|
@@ -2076,13 +2205,13 @@ const HLJS = function(hljs) {
|
|
|
2076
2205
|
*/
|
|
2077
2206
|
function justTextHighlightResult(code) {
|
|
2078
2207
|
const result = {
|
|
2079
|
-
|
|
2080
|
-
emitter: new options.__emitter(options),
|
|
2081
|
-
value: escape$1(code),
|
|
2208
|
+
value: escape(code),
|
|
2082
2209
|
illegal: false,
|
|
2083
|
-
|
|
2210
|
+
relevance: 0,
|
|
2211
|
+
_top: PLAINTEXT_LANGUAGE,
|
|
2212
|
+
_emitter: new options.__emitter(options)
|
|
2084
2213
|
};
|
|
2085
|
-
result.
|
|
2214
|
+
result._emitter.addText(code);
|
|
2086
2215
|
return result;
|
|
2087
2216
|
}
|
|
2088
2217
|
|
|
@@ -2093,7 +2222,7 @@ const HLJS = function(hljs) {
|
|
|
2093
2222
|
- language (detected language)
|
|
2094
2223
|
- relevance (int)
|
|
2095
2224
|
- value (an HTML string with highlighting markup)
|
|
2096
|
-
-
|
|
2225
|
+
- secondBest (object with the same structure for second-best heuristically
|
|
2097
2226
|
detected language, may be absent)
|
|
2098
2227
|
|
|
2099
2228
|
@param {string} code
|
|
@@ -2134,35 +2263,11 @@ const HLJS = function(hljs) {
|
|
|
2134
2263
|
|
|
2135
2264
|
/** @type {AutoHighlightResult} */
|
|
2136
2265
|
const result = best;
|
|
2137
|
-
result.
|
|
2266
|
+
result.secondBest = secondBest;
|
|
2138
2267
|
|
|
2139
2268
|
return result;
|
|
2140
2269
|
}
|
|
2141
2270
|
|
|
2142
|
-
/**
|
|
2143
|
-
Post-processing of the highlighted markup:
|
|
2144
|
-
|
|
2145
|
-
- replace TABs with something more useful
|
|
2146
|
-
- replace real line-breaks with '<br>' for non-pre containers
|
|
2147
|
-
|
|
2148
|
-
@param {string} html
|
|
2149
|
-
@returns {string}
|
|
2150
|
-
*/
|
|
2151
|
-
function fixMarkup(html) {
|
|
2152
|
-
if (!(options.tabReplace || options.useBR)) {
|
|
2153
|
-
return html;
|
|
2154
|
-
}
|
|
2155
|
-
|
|
2156
|
-
return html.replace(fixMarkupRe, match => {
|
|
2157
|
-
if (match === '\n') {
|
|
2158
|
-
return options.useBR ? '<br>' : match;
|
|
2159
|
-
} else if (options.tabReplace) {
|
|
2160
|
-
return match.replace(/\t/g, options.tabReplace);
|
|
2161
|
-
}
|
|
2162
|
-
return match;
|
|
2163
|
-
});
|
|
2164
|
-
}
|
|
2165
|
-
|
|
2166
2271
|
/**
|
|
2167
2272
|
* Builds new class name for block given the language name
|
|
2168
2273
|
*
|
|
@@ -2171,41 +2276,14 @@ const HLJS = function(hljs) {
|
|
|
2171
2276
|
* @param {string} [resultLang]
|
|
2172
2277
|
*/
|
|
2173
2278
|
function updateClassName(element, currentLang, resultLang) {
|
|
2174
|
-
const language = currentLang
|
|
2279
|
+
const language = (currentLang && aliases[currentLang]) || resultLang;
|
|
2175
2280
|
|
|
2176
2281
|
element.classList.add("hljs");
|
|
2177
|
-
|
|
2282
|
+
element.classList.add(`language-${language}`);
|
|
2178
2283
|
}
|
|
2179
2284
|
|
|
2180
|
-
/** @type {HLJSPlugin} */
|
|
2181
|
-
const brPlugin = {
|
|
2182
|
-
"before:highlightElement": ({ el }) => {
|
|
2183
|
-
if (options.useBR) {
|
|
2184
|
-
el.innerHTML = el.innerHTML.replace(/\n/g, '').replace(/<br[ /]*>/g, '\n');
|
|
2185
|
-
}
|
|
2186
|
-
},
|
|
2187
|
-
"after:highlightElement": ({ result }) => {
|
|
2188
|
-
if (options.useBR) {
|
|
2189
|
-
result.value = result.value.replace(/\n/g, "<br>");
|
|
2190
|
-
}
|
|
2191
|
-
}
|
|
2192
|
-
};
|
|
2193
|
-
|
|
2194
|
-
const TAB_REPLACE_RE = /^(<[^>]+>|\t)+/gm;
|
|
2195
|
-
/** @type {HLJSPlugin} */
|
|
2196
|
-
const tabReplacePlugin = {
|
|
2197
|
-
"after:highlightElement": ({ result }) => {
|
|
2198
|
-
if (options.tabReplace) {
|
|
2199
|
-
result.value = result.value.replace(TAB_REPLACE_RE, (m) =>
|
|
2200
|
-
m.replace(/\t/g, options.tabReplace)
|
|
2201
|
-
);
|
|
2202
|
-
}
|
|
2203
|
-
}
|
|
2204
|
-
};
|
|
2205
|
-
|
|
2206
2285
|
/**
|
|
2207
|
-
* Applies highlighting to a DOM node containing code.
|
|
2208
|
-
* two optional parameters for fixMarkup.
|
|
2286
|
+
* Applies highlighting to a DOM node containing code.
|
|
2209
2287
|
*
|
|
2210
2288
|
* @param {HighlightedHTMLElement} element - the HTML element to highlight
|
|
2211
2289
|
*/
|
|
@@ -2216,33 +2294,50 @@ const HLJS = function(hljs) {
|
|
|
2216
2294
|
|
|
2217
2295
|
if (shouldNotHighlight(language)) return;
|
|
2218
2296
|
|
|
2219
|
-
// support for v10 API
|
|
2220
2297
|
fire("before:highlightElement",
|
|
2221
2298
|
{ el: element, language: language });
|
|
2222
2299
|
|
|
2300
|
+
// we should be all text, no child nodes (unescaped HTML) - this is possibly
|
|
2301
|
+
// an HTML injection attack - it's likely too late if this is already in
|
|
2302
|
+
// production (the code has likely already done its damage by the time
|
|
2303
|
+
// we're seeing it)... but we yell loudly about this so that hopefully it's
|
|
2304
|
+
// more likely to be caught in development before making it to production
|
|
2305
|
+
if (element.children.length > 0) {
|
|
2306
|
+
if (!options.ignoreUnescapedHTML) {
|
|
2307
|
+
console.warn("One of your code blocks includes unescaped HTML. This is a potentially serious security risk.");
|
|
2308
|
+
console.warn("https://github.com/highlightjs/highlight.js/wiki/security");
|
|
2309
|
+
console.warn("The element with unescaped HTML:");
|
|
2310
|
+
console.warn(element);
|
|
2311
|
+
}
|
|
2312
|
+
if (options.throwUnescapedHTML) {
|
|
2313
|
+
const err = new HTMLInjectionError(
|
|
2314
|
+
"One of your code blocks includes unescaped HTML.",
|
|
2315
|
+
element.innerHTML
|
|
2316
|
+
);
|
|
2317
|
+
throw err;
|
|
2318
|
+
}
|
|
2319
|
+
}
|
|
2320
|
+
|
|
2223
2321
|
node = element;
|
|
2224
2322
|
const text = node.textContent;
|
|
2225
2323
|
const result = language ? highlight(text, { language, ignoreIllegals: true }) : highlightAuto(text);
|
|
2226
2324
|
|
|
2227
|
-
// support for v10 API
|
|
2228
|
-
fire("after:highlightElement", { el: element, result, text });
|
|
2229
|
-
|
|
2230
2325
|
element.innerHTML = result.value;
|
|
2231
2326
|
updateClassName(element, language, result.language);
|
|
2232
2327
|
element.result = {
|
|
2233
2328
|
language: result.language,
|
|
2234
2329
|
// TODO: remove with version 11.0
|
|
2235
2330
|
re: result.relevance,
|
|
2236
|
-
|
|
2331
|
+
relevance: result.relevance
|
|
2237
2332
|
};
|
|
2238
|
-
if (result.
|
|
2239
|
-
element.
|
|
2240
|
-
language: result.
|
|
2241
|
-
|
|
2242
|
-
re: result.second_best.relevance,
|
|
2243
|
-
relavance: result.second_best.relevance
|
|
2333
|
+
if (result.secondBest) {
|
|
2334
|
+
element.secondBest = {
|
|
2335
|
+
language: result.secondBest.language,
|
|
2336
|
+
relevance: result.secondBest.relevance
|
|
2244
2337
|
};
|
|
2245
2338
|
}
|
|
2339
|
+
|
|
2340
|
+
fire("after:highlightElement", { el: element, result, text });
|
|
2246
2341
|
}
|
|
2247
2342
|
|
|
2248
2343
|
/**
|
|
@@ -2251,34 +2346,19 @@ const HLJS = function(hljs) {
|
|
|
2251
2346
|
* @param {Partial<HLJSOptions>} userOptions
|
|
2252
2347
|
*/
|
|
2253
2348
|
function configure(userOptions) {
|
|
2254
|
-
|
|
2255
|
-
deprecated("10.3.0", "'useBR' will be removed entirely in v11.0");
|
|
2256
|
-
deprecated("10.3.0", "Please see https://github.com/highlightjs/highlight.js/issues/2559");
|
|
2257
|
-
}
|
|
2258
|
-
options = inherit$1(options, userOptions);
|
|
2349
|
+
options = inherit(options, userOptions);
|
|
2259
2350
|
}
|
|
2260
2351
|
|
|
2261
|
-
/**
|
|
2262
|
-
* Highlights to all <pre><code> blocks on a page
|
|
2263
|
-
*
|
|
2264
|
-
* @type {Function & {called?: boolean}}
|
|
2265
|
-
*/
|
|
2266
2352
|
// TODO: remove v12, deprecated
|
|
2267
2353
|
const initHighlighting = () => {
|
|
2268
|
-
|
|
2269
|
-
initHighlighting.
|
|
2270
|
-
|
|
2271
|
-
deprecated("10.6.0", "initHighlighting() is deprecated. Use highlightAll() instead.");
|
|
2272
|
-
|
|
2273
|
-
const blocks = document.querySelectorAll('pre code');
|
|
2274
|
-
blocks.forEach(highlightElement);
|
|
2354
|
+
highlightAll();
|
|
2355
|
+
deprecated("10.6.0", "initHighlighting() deprecated. Use highlightAll() now.");
|
|
2275
2356
|
};
|
|
2276
2357
|
|
|
2277
|
-
// Higlights all when DOMContentLoaded fires
|
|
2278
2358
|
// TODO: remove v12, deprecated
|
|
2279
2359
|
function initHighlightingOnLoad() {
|
|
2280
|
-
|
|
2281
|
-
|
|
2360
|
+
highlightAll();
|
|
2361
|
+
deprecated("10.6.0", "initHighlightingOnLoad() deprecated. Use highlightAll() now.");
|
|
2282
2362
|
}
|
|
2283
2363
|
|
|
2284
2364
|
let wantsHighlight = false;
|
|
@@ -2293,7 +2373,7 @@ const HLJS = function(hljs) {
|
|
|
2293
2373
|
return;
|
|
2294
2374
|
}
|
|
2295
2375
|
|
|
2296
|
-
const blocks = document.querySelectorAll(
|
|
2376
|
+
const blocks = document.querySelectorAll(options.cssSelector);
|
|
2297
2377
|
blocks.forEach(highlightElement);
|
|
2298
2378
|
}
|
|
2299
2379
|
|
|
@@ -2358,26 +2438,6 @@ const HLJS = function(hljs) {
|
|
|
2358
2438
|
return Object.keys(languages);
|
|
2359
2439
|
}
|
|
2360
2440
|
|
|
2361
|
-
/**
|
|
2362
|
-
intended usage: When one language truly requires another
|
|
2363
|
-
|
|
2364
|
-
Unlike `getLanguage`, this will throw when the requested language
|
|
2365
|
-
is not available.
|
|
2366
|
-
|
|
2367
|
-
@param {string} name - name of the language to fetch/require
|
|
2368
|
-
@returns {Language | never}
|
|
2369
|
-
*/
|
|
2370
|
-
function requireLanguage(name) {
|
|
2371
|
-
deprecated("10.4.0", "requireLanguage will be removed entirely in v11.");
|
|
2372
|
-
deprecated("10.4.0", "Please see https://github.com/highlightjs/highlight.js/pull/2844");
|
|
2373
|
-
|
|
2374
|
-
const lang = getLanguage(name);
|
|
2375
|
-
if (lang) { return lang; }
|
|
2376
|
-
|
|
2377
|
-
const err = new Error('The \'{}\' language is required, but not loaded.'.replace('{}', name));
|
|
2378
|
-
throw err;
|
|
2379
|
-
}
|
|
2380
|
-
|
|
2381
2441
|
/**
|
|
2382
2442
|
* @param {string} name - name of the language to retrieve
|
|
2383
2443
|
* @returns {Language | undefined}
|
|
@@ -2454,20 +2514,7 @@ const HLJS = function(hljs) {
|
|
|
2454
2514
|
}
|
|
2455
2515
|
|
|
2456
2516
|
/**
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
@param {string} arg
|
|
2460
|
-
@returns {string}
|
|
2461
|
-
*/
|
|
2462
|
-
function deprecateFixMarkup(arg) {
|
|
2463
|
-
deprecated("10.2.0", "fixMarkup will be removed entirely in v11.0");
|
|
2464
|
-
deprecated("10.2.0", "Please see https://github.com/highlightjs/highlight.js/issues/2534");
|
|
2465
|
-
|
|
2466
|
-
return fixMarkup(arg);
|
|
2467
|
-
}
|
|
2468
|
-
|
|
2469
|
-
/**
|
|
2470
|
-
*
|
|
2517
|
+
* DEPRECATED
|
|
2471
2518
|
* @param {HighlightedHTMLElement} el
|
|
2472
2519
|
*/
|
|
2473
2520
|
function deprecateHighlightBlock(el) {
|
|
@@ -2482,7 +2529,6 @@ const HLJS = function(hljs) {
|
|
|
2482
2529
|
highlight,
|
|
2483
2530
|
highlightAuto,
|
|
2484
2531
|
highlightAll,
|
|
2485
|
-
fixMarkup: deprecateFixMarkup,
|
|
2486
2532
|
highlightElement,
|
|
2487
2533
|
// TODO: Remove with v12 API
|
|
2488
2534
|
highlightBlock: deprecateHighlightBlock,
|
|
@@ -2494,404 +2540,50 @@ const HLJS = function(hljs) {
|
|
|
2494
2540
|
listLanguages,
|
|
2495
2541
|
getLanguage,
|
|
2496
2542
|
registerAliases,
|
|
2497
|
-
requireLanguage,
|
|
2498
2543
|
autoDetection,
|
|
2499
|
-
inherit
|
|
2500
|
-
addPlugin
|
|
2501
|
-
// plugins for frameworks
|
|
2502
|
-
vuePlugin: BuildVuePlugin(hljs).VuePlugin
|
|
2544
|
+
inherit,
|
|
2545
|
+
addPlugin
|
|
2503
2546
|
});
|
|
2504
2547
|
|
|
2505
2548
|
hljs.debugMode = function() { SAFE_MODE = false; };
|
|
2506
2549
|
hljs.safeMode = function() { SAFE_MODE = true; };
|
|
2507
2550
|
hljs.versionString = version;
|
|
2508
2551
|
|
|
2552
|
+
hljs.regex = {
|
|
2553
|
+
concat: concat,
|
|
2554
|
+
lookahead: lookahead,
|
|
2555
|
+
either: either,
|
|
2556
|
+
optional: optional,
|
|
2557
|
+
anyNumberOfTimes: anyNumberOfTimes
|
|
2558
|
+
};
|
|
2559
|
+
|
|
2509
2560
|
for (const key in MODES) {
|
|
2510
2561
|
// @ts-ignore
|
|
2511
2562
|
if (typeof MODES[key] === "object") {
|
|
2512
2563
|
// @ts-ignore
|
|
2513
|
-
deepFreezeEs6(MODES[key]);
|
|
2564
|
+
deepFreezeEs6.exports(MODES[key]);
|
|
2514
2565
|
}
|
|
2515
2566
|
}
|
|
2516
2567
|
|
|
2517
|
-
// merge all the modes/
|
|
2568
|
+
// merge all the modes/regexes into our main object
|
|
2518
2569
|
Object.assign(hljs, MODES);
|
|
2519
2570
|
|
|
2520
|
-
// built-in plugins, likely to be moved out of core in the future
|
|
2521
|
-
hljs.addPlugin(brPlugin); // slated to be removed in v11
|
|
2522
|
-
hljs.addPlugin(mergeHTMLPlugin);
|
|
2523
|
-
hljs.addPlugin(tabReplacePlugin);
|
|
2524
2571
|
return hljs;
|
|
2525
2572
|
};
|
|
2526
2573
|
|
|
2527
2574
|
// export an "instance" of the highlighter
|
|
2528
|
-
var highlight
|
|
2529
|
-
|
|
2530
|
-
var core$1 = highlight$1;
|
|
2575
|
+
var highlight = HLJS({});
|
|
2531
2576
|
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
}
|
|
2536
|
-
|
|
2537
|
-
var format = createCommonjsModule(function (module) {
|
|
2538
|
-
(function() {
|
|
2539
|
-
|
|
2540
|
-
//// Export the API
|
|
2541
|
-
var namespace;
|
|
2542
|
-
|
|
2543
|
-
// CommonJS / Node module
|
|
2544
|
-
{
|
|
2545
|
-
namespace = module.exports = format;
|
|
2546
|
-
}
|
|
2547
|
-
|
|
2548
|
-
namespace.format = format;
|
|
2549
|
-
namespace.vsprintf = vsprintf;
|
|
2550
|
-
|
|
2551
|
-
if (typeof console !== 'undefined' && typeof console.log === 'function') {
|
|
2552
|
-
namespace.printf = printf;
|
|
2553
|
-
}
|
|
2554
|
-
|
|
2555
|
-
function printf(/* ... */) {
|
|
2556
|
-
console.log(format.apply(null, arguments));
|
|
2557
|
-
}
|
|
2558
|
-
|
|
2559
|
-
function vsprintf(fmt, replacements) {
|
|
2560
|
-
return format.apply(null, [fmt].concat(replacements));
|
|
2561
|
-
}
|
|
2562
|
-
|
|
2563
|
-
function format(fmt) {
|
|
2564
|
-
var argIndex = 1 // skip initial format argument
|
|
2565
|
-
, args = [].slice.call(arguments)
|
|
2566
|
-
, i = 0
|
|
2567
|
-
, n = fmt.length
|
|
2568
|
-
, result = ''
|
|
2569
|
-
, c
|
|
2570
|
-
, escaped = false
|
|
2571
|
-
, arg
|
|
2572
|
-
, tmp
|
|
2573
|
-
, leadingZero = false
|
|
2574
|
-
, precision
|
|
2575
|
-
, nextArg = function() { return args[argIndex++]; }
|
|
2576
|
-
, slurpNumber = function() {
|
|
2577
|
-
var digits = '';
|
|
2578
|
-
while (/\d/.test(fmt[i])) {
|
|
2579
|
-
digits += fmt[i++];
|
|
2580
|
-
c = fmt[i];
|
|
2581
|
-
}
|
|
2582
|
-
return digits.length > 0 ? parseInt(digits) : null;
|
|
2583
|
-
}
|
|
2584
|
-
;
|
|
2585
|
-
for (; i < n; ++i) {
|
|
2586
|
-
c = fmt[i];
|
|
2587
|
-
if (escaped) {
|
|
2588
|
-
escaped = false;
|
|
2589
|
-
if (c == '.') {
|
|
2590
|
-
leadingZero = false;
|
|
2591
|
-
c = fmt[++i];
|
|
2592
|
-
}
|
|
2593
|
-
else if (c == '0' && fmt[i + 1] == '.') {
|
|
2594
|
-
leadingZero = true;
|
|
2595
|
-
i += 2;
|
|
2596
|
-
c = fmt[i];
|
|
2597
|
-
}
|
|
2598
|
-
else {
|
|
2599
|
-
leadingZero = true;
|
|
2600
|
-
}
|
|
2601
|
-
precision = slurpNumber();
|
|
2602
|
-
switch (c) {
|
|
2603
|
-
case 'b': // number in binary
|
|
2604
|
-
result += parseInt(nextArg(), 10).toString(2);
|
|
2605
|
-
break;
|
|
2606
|
-
case 'c': // character
|
|
2607
|
-
arg = nextArg();
|
|
2608
|
-
if (typeof arg === 'string' || arg instanceof String)
|
|
2609
|
-
result += arg;
|
|
2610
|
-
else
|
|
2611
|
-
result += String.fromCharCode(parseInt(arg, 10));
|
|
2612
|
-
break;
|
|
2613
|
-
case 'd': // number in decimal
|
|
2614
|
-
result += parseInt(nextArg(), 10);
|
|
2615
|
-
break;
|
|
2616
|
-
case 'f': // floating point number
|
|
2617
|
-
tmp = String(parseFloat(nextArg()).toFixed(precision || 6));
|
|
2618
|
-
result += leadingZero ? tmp : tmp.replace(/^0/, '');
|
|
2619
|
-
break;
|
|
2620
|
-
case 'j': // JSON
|
|
2621
|
-
result += JSON.stringify(nextArg());
|
|
2622
|
-
break;
|
|
2623
|
-
case 'o': // number in octal
|
|
2624
|
-
result += '0' + parseInt(nextArg(), 10).toString(8);
|
|
2625
|
-
break;
|
|
2626
|
-
case 's': // string
|
|
2627
|
-
result += nextArg();
|
|
2628
|
-
break;
|
|
2629
|
-
case 'x': // lowercase hexadecimal
|
|
2630
|
-
result += '0x' + parseInt(nextArg(), 10).toString(16);
|
|
2631
|
-
break;
|
|
2632
|
-
case 'X': // uppercase hexadecimal
|
|
2633
|
-
result += '0x' + parseInt(nextArg(), 10).toString(16).toUpperCase();
|
|
2634
|
-
break;
|
|
2635
|
-
default:
|
|
2636
|
-
result += c;
|
|
2637
|
-
break;
|
|
2638
|
-
}
|
|
2639
|
-
} else if (c === '%') {
|
|
2640
|
-
escaped = true;
|
|
2641
|
-
} else {
|
|
2642
|
-
result += c;
|
|
2643
|
-
}
|
|
2644
|
-
}
|
|
2645
|
-
return result;
|
|
2646
|
-
}
|
|
2647
|
-
|
|
2648
|
-
}());
|
|
2649
|
-
});
|
|
2650
|
-
|
|
2651
|
-
var fault = create(Error);
|
|
2652
|
-
|
|
2653
|
-
var fault_1 = fault;
|
|
2654
|
-
|
|
2655
|
-
fault.eval = create(EvalError);
|
|
2656
|
-
fault.range = create(RangeError);
|
|
2657
|
-
fault.reference = create(ReferenceError);
|
|
2658
|
-
fault.syntax = create(SyntaxError);
|
|
2659
|
-
fault.type = create(TypeError);
|
|
2660
|
-
fault.uri = create(URIError);
|
|
2661
|
-
|
|
2662
|
-
fault.create = create;
|
|
2663
|
-
|
|
2664
|
-
// Create a new `EConstructor`, with the formatted `format` as a first argument.
|
|
2665
|
-
function create(EConstructor) {
|
|
2666
|
-
FormattedError.displayName = EConstructor.displayName || EConstructor.name;
|
|
2667
|
-
|
|
2668
|
-
return FormattedError
|
|
2669
|
-
|
|
2670
|
-
function FormattedError(format$1) {
|
|
2671
|
-
if (format$1) {
|
|
2672
|
-
format$1 = format.apply(null, arguments);
|
|
2673
|
-
}
|
|
2674
|
-
|
|
2675
|
-
return new EConstructor(format$1)
|
|
2676
|
-
}
|
|
2677
|
-
}
|
|
2678
|
-
|
|
2679
|
-
var highlight_1 = highlight;
|
|
2680
|
-
var highlightAuto_1 = highlightAuto;
|
|
2681
|
-
var registerLanguage_1 = registerLanguage;
|
|
2682
|
-
var listLanguages_1 = listLanguages;
|
|
2683
|
-
var registerAlias_1 = registerAlias;
|
|
2684
|
-
|
|
2685
|
-
Emitter.prototype.addText = text;
|
|
2686
|
-
Emitter.prototype.addKeyword = addKeyword;
|
|
2687
|
-
Emitter.prototype.addSublanguage = addSublanguage;
|
|
2688
|
-
Emitter.prototype.openNode = open;
|
|
2689
|
-
Emitter.prototype.closeNode = close;
|
|
2690
|
-
Emitter.prototype.closeAllNodes = noop;
|
|
2691
|
-
Emitter.prototype.finalize = noop;
|
|
2692
|
-
Emitter.prototype.toHTML = toHtmlNoop;
|
|
2693
|
-
|
|
2694
|
-
var defaultPrefix = 'hljs-';
|
|
2695
|
-
|
|
2696
|
-
// Highlighting `value` in the language `name`.
|
|
2697
|
-
function highlight(name, value, options) {
|
|
2698
|
-
var before = core$1.configure({});
|
|
2699
|
-
var settings = options || {};
|
|
2700
|
-
var prefix = settings.prefix;
|
|
2701
|
-
var result;
|
|
2702
|
-
|
|
2703
|
-
if (typeof name !== 'string') {
|
|
2704
|
-
throw fault_1('Expected `string` for name, got `%s`', name)
|
|
2705
|
-
}
|
|
2706
|
-
|
|
2707
|
-
if (!core$1.getLanguage(name)) {
|
|
2708
|
-
throw fault_1('Unknown language: `%s` is not registered', name)
|
|
2709
|
-
}
|
|
2710
|
-
|
|
2711
|
-
if (typeof value !== 'string') {
|
|
2712
|
-
throw fault_1('Expected `string` for value, got `%s`', value)
|
|
2713
|
-
}
|
|
2714
|
-
|
|
2715
|
-
if (prefix === null || prefix === undefined) {
|
|
2716
|
-
prefix = defaultPrefix;
|
|
2717
|
-
}
|
|
2718
|
-
|
|
2719
|
-
core$1.configure({__emitter: Emitter, classPrefix: prefix});
|
|
2720
|
-
|
|
2721
|
-
result = core$1.highlight(value, {language: name, ignoreIllegals: true});
|
|
2722
|
-
|
|
2723
|
-
core$1.configure(before || {});
|
|
2724
|
-
|
|
2725
|
-
/* istanbul ignore if - Highlight.js seems to use this (currently) for broken
|
|
2726
|
-
* grammars, so let’s keep it in there just to be sure. */
|
|
2727
|
-
if (result.errorRaised) {
|
|
2728
|
-
throw result.errorRaised
|
|
2729
|
-
}
|
|
2730
|
-
|
|
2731
|
-
return {
|
|
2732
|
-
relevance: result.relevance,
|
|
2733
|
-
language: result.language,
|
|
2734
|
-
value: result.emitter.rootNode.children
|
|
2735
|
-
}
|
|
2736
|
-
}
|
|
2737
|
-
|
|
2738
|
-
function highlightAuto(value, options) {
|
|
2739
|
-
var settings = options || {};
|
|
2740
|
-
var subset = settings.subset || core$1.listLanguages();
|
|
2741
|
-
settings.prefix;
|
|
2742
|
-
var length = subset.length;
|
|
2743
|
-
var index = -1;
|
|
2744
|
-
var result;
|
|
2745
|
-
var secondBest;
|
|
2746
|
-
var current;
|
|
2747
|
-
var name;
|
|
2748
|
-
|
|
2749
|
-
if (typeof value !== 'string') {
|
|
2750
|
-
throw fault_1('Expected `string` for value, got `%s`', value)
|
|
2751
|
-
}
|
|
2577
|
+
var core = highlight;
|
|
2578
|
+
highlight.HighlightJS = highlight;
|
|
2579
|
+
highlight.default = highlight;
|
|
2752
2580
|
|
|
2753
|
-
|
|
2754
|
-
result = {relevance: 0, language: null, value: []};
|
|
2755
|
-
|
|
2756
|
-
while (++index < length) {
|
|
2757
|
-
name = subset[index];
|
|
2758
|
-
|
|
2759
|
-
if (!core$1.getLanguage(name)) {
|
|
2760
|
-
continue
|
|
2761
|
-
}
|
|
2762
|
-
|
|
2763
|
-
current = highlight(name, value, options);
|
|
2764
|
-
current.language = name;
|
|
2765
|
-
|
|
2766
|
-
if (current.relevance > secondBest.relevance) {
|
|
2767
|
-
secondBest = current;
|
|
2768
|
-
}
|
|
2769
|
-
|
|
2770
|
-
if (current.relevance > result.relevance) {
|
|
2771
|
-
secondBest = result;
|
|
2772
|
-
result = current;
|
|
2773
|
-
}
|
|
2774
|
-
}
|
|
2775
|
-
|
|
2776
|
-
if (secondBest.language) {
|
|
2777
|
-
result.secondBest = secondBest;
|
|
2778
|
-
}
|
|
2779
|
-
|
|
2780
|
-
return result
|
|
2781
|
-
}
|
|
2782
|
-
|
|
2783
|
-
// Register a language.
|
|
2784
|
-
function registerLanguage(name, syntax) {
|
|
2785
|
-
core$1.registerLanguage(name, syntax);
|
|
2786
|
-
}
|
|
2787
|
-
|
|
2788
|
-
// Get a list of all registered languages.
|
|
2789
|
-
function listLanguages() {
|
|
2790
|
-
return core$1.listLanguages()
|
|
2791
|
-
}
|
|
2792
|
-
|
|
2793
|
-
// Register more aliases for an already registered language.
|
|
2794
|
-
function registerAlias(name, alias) {
|
|
2795
|
-
var map = name;
|
|
2796
|
-
var key;
|
|
2797
|
-
|
|
2798
|
-
if (alias) {
|
|
2799
|
-
map = {};
|
|
2800
|
-
map[name] = alias;
|
|
2801
|
-
}
|
|
2802
|
-
|
|
2803
|
-
for (key in map) {
|
|
2804
|
-
core$1.registerAliases(map[key], {languageName: key});
|
|
2805
|
-
}
|
|
2806
|
-
}
|
|
2807
|
-
|
|
2808
|
-
function Emitter(options) {
|
|
2809
|
-
this.options = options;
|
|
2810
|
-
this.rootNode = {children: []};
|
|
2811
|
-
this.stack = [this.rootNode];
|
|
2812
|
-
}
|
|
2813
|
-
|
|
2814
|
-
function addKeyword(value, name) {
|
|
2815
|
-
this.openNode(name);
|
|
2816
|
-
this.addText(value);
|
|
2817
|
-
this.closeNode();
|
|
2818
|
-
}
|
|
2819
|
-
|
|
2820
|
-
function addSublanguage(other, name) {
|
|
2821
|
-
var stack = this.stack;
|
|
2822
|
-
var current = stack[stack.length - 1];
|
|
2823
|
-
var results = other.rootNode.children;
|
|
2824
|
-
var node = name
|
|
2825
|
-
? {
|
|
2826
|
-
type: 'element',
|
|
2827
|
-
tagName: 'span',
|
|
2828
|
-
properties: {className: [name]},
|
|
2829
|
-
children: results
|
|
2830
|
-
}
|
|
2831
|
-
: results;
|
|
2832
|
-
|
|
2833
|
-
current.children = current.children.concat(node);
|
|
2834
|
-
}
|
|
2835
|
-
|
|
2836
|
-
function text(value) {
|
|
2837
|
-
var stack = this.stack;
|
|
2838
|
-
var current;
|
|
2839
|
-
var tail;
|
|
2840
|
-
|
|
2841
|
-
if (value === '') return
|
|
2842
|
-
|
|
2843
|
-
current = stack[stack.length - 1];
|
|
2844
|
-
tail = current.children[current.children.length - 1];
|
|
2845
|
-
|
|
2846
|
-
if (tail && tail.type === 'text') {
|
|
2847
|
-
tail.value += value;
|
|
2848
|
-
} else {
|
|
2849
|
-
current.children.push({type: 'text', value: value});
|
|
2850
|
-
}
|
|
2851
|
-
}
|
|
2852
|
-
|
|
2853
|
-
function open(name) {
|
|
2854
|
-
var stack = this.stack;
|
|
2855
|
-
var className = this.options.classPrefix + name;
|
|
2856
|
-
var current = stack[stack.length - 1];
|
|
2857
|
-
var child = {
|
|
2858
|
-
type: 'element',
|
|
2859
|
-
tagName: 'span',
|
|
2860
|
-
properties: {className: [className]},
|
|
2861
|
-
children: []
|
|
2862
|
-
};
|
|
2863
|
-
|
|
2864
|
-
current.children.push(child);
|
|
2865
|
-
stack.push(child);
|
|
2866
|
-
}
|
|
2867
|
-
|
|
2868
|
-
function close() {
|
|
2869
|
-
this.stack.pop();
|
|
2870
|
-
}
|
|
2871
|
-
|
|
2872
|
-
function toHtmlNoop() {
|
|
2873
|
-
return ''
|
|
2874
|
-
}
|
|
2875
|
-
|
|
2876
|
-
function noop() {}
|
|
2877
|
-
|
|
2878
|
-
var core = {
|
|
2879
|
-
highlight: highlight_1,
|
|
2880
|
-
highlightAuto: highlightAuto_1,
|
|
2881
|
-
registerLanguage: registerLanguage_1,
|
|
2882
|
-
listLanguages: listLanguages_1,
|
|
2883
|
-
registerAlias: registerAlias_1
|
|
2884
|
-
};
|
|
2581
|
+
var HighlightJS = core;
|
|
2885
2582
|
|
|
2886
2583
|
function parseNodes(nodes, className = []) {
|
|
2887
2584
|
return nodes
|
|
2888
2585
|
.map(node => {
|
|
2889
|
-
const classes = [
|
|
2890
|
-
...className,
|
|
2891
|
-
...node.properties
|
|
2892
|
-
? node.properties.className
|
|
2893
|
-
: [],
|
|
2894
|
-
];
|
|
2586
|
+
const classes = [...className, ...(node.properties ? node.properties.className : [])];
|
|
2895
2587
|
if (node.children) {
|
|
2896
2588
|
return parseNodes(node.children, classes);
|
|
2897
2589
|
}
|
|
@@ -2902,22 +2594,26 @@ function parseNodes(nodes, className = []) {
|
|
|
2902
2594
|
})
|
|
2903
2595
|
.flat();
|
|
2904
2596
|
}
|
|
2905
|
-
function
|
|
2597
|
+
function getHighlightNodes(result) {
|
|
2598
|
+
// `.value` for lowlight v1, `.children` for lowlight v2
|
|
2599
|
+
return result.value || result.children || [];
|
|
2600
|
+
}
|
|
2601
|
+
function registered(aliasOrLanguage) {
|
|
2602
|
+
return Boolean(HighlightJS.getLanguage(aliasOrLanguage));
|
|
2603
|
+
}
|
|
2604
|
+
function getDecorations({ doc, name, lowlight, defaultLanguage, }) {
|
|
2906
2605
|
const decorations = [];
|
|
2907
|
-
core$
|
|
2908
|
-
.forEach(block => {
|
|
2606
|
+
core$1.findChildren(doc, node => node.type.name === name).forEach(block => {
|
|
2909
2607
|
let from = block.pos + 1;
|
|
2910
|
-
const
|
|
2911
|
-
// TODO: add missing type for `listLanguages`
|
|
2912
|
-
// @ts-ignore
|
|
2608
|
+
const language = block.node.attrs.language || defaultLanguage;
|
|
2913
2609
|
const languages = lowlight.listLanguages();
|
|
2914
|
-
const nodes = language && languages.includes(language)
|
|
2915
|
-
? lowlight.highlight(language, block.node.textContent)
|
|
2916
|
-
: lowlight.highlightAuto(block.node.textContent)
|
|
2610
|
+
const nodes = language && (languages.includes(language) || registered(language))
|
|
2611
|
+
? getHighlightNodes(lowlight.highlight(language, block.node.textContent))
|
|
2612
|
+
: getHighlightNodes(lowlight.highlightAuto(block.node.textContent));
|
|
2917
2613
|
parseNodes(nodes).forEach(node => {
|
|
2918
2614
|
const to = from + node.text.length;
|
|
2919
2615
|
if (node.classes.length) {
|
|
2920
|
-
const decoration =
|
|
2616
|
+
const decoration = view.Decoration.inline(from, to, {
|
|
2921
2617
|
class: node.classes.join(' '),
|
|
2922
2618
|
});
|
|
2923
2619
|
decorations.push(decoration);
|
|
@@ -2925,23 +2621,33 @@ function getDecorations({ doc, name, lowlight }) {
|
|
|
2925
2621
|
from = to;
|
|
2926
2622
|
});
|
|
2927
2623
|
});
|
|
2928
|
-
return
|
|
2624
|
+
return view.DecorationSet.create(doc, decorations);
|
|
2929
2625
|
}
|
|
2930
|
-
function
|
|
2931
|
-
return
|
|
2932
|
-
|
|
2626
|
+
function isFunction(param) {
|
|
2627
|
+
return typeof param === 'function';
|
|
2628
|
+
}
|
|
2629
|
+
function LowlightPlugin({ name, lowlight, defaultLanguage, }) {
|
|
2630
|
+
if (!['highlight', 'highlightAuto', 'listLanguages'].every(api => isFunction(lowlight[api]))) {
|
|
2631
|
+
throw Error('You should provide an instance of lowlight to use the code-block-lowlight extension');
|
|
2632
|
+
}
|
|
2633
|
+
const lowlightPlugin = new state.Plugin({
|
|
2634
|
+
key: new state.PluginKey('lowlight'),
|
|
2933
2635
|
state: {
|
|
2934
|
-
init: (_, { doc }) => getDecorations({
|
|
2636
|
+
init: (_, { doc }) => getDecorations({
|
|
2637
|
+
doc,
|
|
2638
|
+
name,
|
|
2639
|
+
lowlight,
|
|
2640
|
+
defaultLanguage,
|
|
2641
|
+
}),
|
|
2935
2642
|
apply: (transaction, decorationSet, oldState, newState) => {
|
|
2936
2643
|
const oldNodeName = oldState.selection.$head.parent.type.name;
|
|
2937
2644
|
const newNodeName = newState.selection.$head.parent.type.name;
|
|
2938
|
-
const oldNodes = core$
|
|
2939
|
-
const newNodes = core$
|
|
2645
|
+
const oldNodes = core$1.findChildren(oldState.doc, node => node.type.name === name);
|
|
2646
|
+
const newNodes = core$1.findChildren(newState.doc, node => node.type.name === name);
|
|
2940
2647
|
if (transaction.docChanged
|
|
2941
2648
|
// Apply decorations if:
|
|
2942
|
-
&& (
|
|
2943
2649
|
// selection includes named node,
|
|
2944
|
-
[oldNodeName, newNodeName].includes(name)
|
|
2650
|
+
&& ([oldNodeName, newNodeName].includes(name)
|
|
2945
2651
|
// OR transaction adds/removes named node,
|
|
2946
2652
|
|| newNodes.length !== oldNodes.length
|
|
2947
2653
|
// OR transaction has changes that completely encapsulte a node
|
|
@@ -2949,46 +2655,61 @@ function LowlightPlugin({ name, lowlight }) {
|
|
|
2949
2655
|
// Such transactions can happen during collab syncing via y-prosemirror, for example.
|
|
2950
2656
|
|| transaction.steps.some(step => {
|
|
2951
2657
|
// @ts-ignore
|
|
2952
|
-
return
|
|
2658
|
+
return (
|
|
2659
|
+
// @ts-ignore
|
|
2660
|
+
step.from !== undefined
|
|
2953
2661
|
// @ts-ignore
|
|
2954
2662
|
&& step.to !== undefined
|
|
2955
2663
|
&& oldNodes.some(node => {
|
|
2956
2664
|
// @ts-ignore
|
|
2957
|
-
return
|
|
2665
|
+
return (
|
|
2666
|
+
// @ts-ignore
|
|
2667
|
+
node.pos >= step.from
|
|
2958
2668
|
// @ts-ignore
|
|
2959
|
-
&& node.pos + node.node.nodeSize <= step.to;
|
|
2960
|
-
});
|
|
2669
|
+
&& node.pos + node.node.nodeSize <= step.to);
|
|
2670
|
+
}));
|
|
2961
2671
|
}))) {
|
|
2962
|
-
return getDecorations({
|
|
2672
|
+
return getDecorations({
|
|
2673
|
+
doc: transaction.doc,
|
|
2674
|
+
name,
|
|
2675
|
+
lowlight,
|
|
2676
|
+
defaultLanguage,
|
|
2677
|
+
});
|
|
2963
2678
|
}
|
|
2964
2679
|
return decorationSet.map(transaction.mapping, transaction.doc);
|
|
2965
2680
|
},
|
|
2966
2681
|
},
|
|
2967
2682
|
props: {
|
|
2968
2683
|
decorations(state) {
|
|
2969
|
-
return
|
|
2684
|
+
return lowlightPlugin.getState(state);
|
|
2970
2685
|
},
|
|
2971
2686
|
},
|
|
2972
2687
|
});
|
|
2688
|
+
return lowlightPlugin;
|
|
2973
2689
|
}
|
|
2974
2690
|
|
|
2975
|
-
const CodeBlockLowlight = CodeBlock__default[
|
|
2976
|
-
|
|
2977
|
-
|
|
2978
|
-
|
|
2691
|
+
const CodeBlockLowlight = CodeBlock__default["default"].extend({
|
|
2692
|
+
addOptions() {
|
|
2693
|
+
var _a;
|
|
2694
|
+
return {
|
|
2695
|
+
...(_a = this.parent) === null || _a === void 0 ? void 0 : _a.call(this),
|
|
2696
|
+
lowlight: {},
|
|
2697
|
+
defaultLanguage: null,
|
|
2698
|
+
};
|
|
2979
2699
|
},
|
|
2980
2700
|
addProseMirrorPlugins() {
|
|
2981
2701
|
var _a;
|
|
2982
2702
|
return [
|
|
2983
2703
|
...((_a = this.parent) === null || _a === void 0 ? void 0 : _a.call(this)) || [],
|
|
2984
2704
|
LowlightPlugin({
|
|
2985
|
-
name:
|
|
2705
|
+
name: this.name,
|
|
2986
2706
|
lowlight: this.options.lowlight,
|
|
2707
|
+
defaultLanguage: this.options.defaultLanguage,
|
|
2987
2708
|
}),
|
|
2988
2709
|
];
|
|
2989
2710
|
},
|
|
2990
2711
|
});
|
|
2991
2712
|
|
|
2992
2713
|
exports.CodeBlockLowlight = CodeBlockLowlight;
|
|
2993
|
-
exports
|
|
2994
|
-
//# sourceMappingURL=
|
|
2714
|
+
exports["default"] = CodeBlockLowlight;
|
|
2715
|
+
//# sourceMappingURL=index.cjs.map
|