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