@tiptap/extension-code-block-lowlight 2.0.0-beta.2 → 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 +2 -2
- package/dist/packages/extension-code-block-lowlight/src/code-block-lowlight.d.ts +6 -1
- package/dist/packages/extension-code-block-lowlight/src/lowlight-plugin.d.ts +4 -2
- package/dist/tiptap-extension-code-block-lowlight.cjs.js +676 -935
- package/dist/tiptap-extension-code-block-lowlight.cjs.js.map +1 -1
- package/dist/tiptap-extension-code-block-lowlight.esm.js +672 -932
- package/dist/tiptap-extension-code-block-lowlight.esm.js.map +1 -1
- package/dist/tiptap-extension-code-block-lowlight.umd.js +680 -939
- package/dist/tiptap-extension-code-block-lowlight.umd.js.map +1 -1
- package/package.json +11 -10
- package/src/code-block-lowlight.ts +22 -3
- package/src/lowlight-plugin.ts +50 -16
- package/CHANGELOG.md +0 -16
- package/LICENSE.md +0 -21
- package/dist/tiptap-extension-code-block-lowlight.bundle.umd.min.js +0 -2
- package/dist/tiptap-extension-code-block-lowlight.bundle.umd.min.js.map +0 -1
|
@@ -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,280 +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
|
|
1571
|
+
var version = "11.6.0";
|
|
1244
1572
|
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
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:
|
|
1396
|
-
|
|
1397
|
-
if (event1 == 'start' && event2 == 'start')
|
|
1398
|
-
return original;
|
|
1399
|
-
if (event1 == 'start' && event2 == 'stop')
|
|
1400
|
-
return highlighted;
|
|
1401
|
-
if (event1 == 'stop' && event2 == 'start')
|
|
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) + '>';
|
|
1573
|
+
class HTMLInjectionError extends Error {
|
|
1574
|
+
constructor(reason, html) {
|
|
1575
|
+
super(reason);
|
|
1576
|
+
this.name = "HTMLInjectionError";
|
|
1577
|
+
this.html = html;
|
|
1428
1578
|
}
|
|
1429
|
-
|
|
1430
|
-
/**
|
|
1431
|
-
* @param {Event} event
|
|
1432
|
-
*/
|
|
1433
|
-
function render(event) {
|
|
1434
|
-
(event.event === 'start' ? open : close)(event.node);
|
|
1435
|
-
}
|
|
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
|
-
const deprecated = (version, message) => {
|
|
1493
|
-
console.log(`Deprecated as of ${version}. ${message}`);
|
|
1494
|
-
};
|
|
1495
|
-
|
|
1496
|
-
/*
|
|
1497
|
-
Syntax highlighting with language autodetection.
|
|
1498
|
-
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
|
|
1499
1605
|
*/
|
|
1500
1606
|
|
|
1501
|
-
|
|
1502
|
-
const
|
|
1607
|
+
|
|
1608
|
+
const escape = escapeHTML;
|
|
1609
|
+
const inherit = inherit$1;
|
|
1503
1610
|
const NO_MATCH = Symbol("nomatch");
|
|
1611
|
+
const MAX_KEYWORD_HITS = 7;
|
|
1504
1612
|
|
|
1505
1613
|
/**
|
|
1506
1614
|
* @param {any} hljs - object that is extended (legacy)
|
|
@@ -1518,7 +1626,6 @@
|
|
|
1518
1626
|
// safe/production mode - swallows more errors, tries to keep running
|
|
1519
1627
|
// even if a single syntax or parse hits a fatal error
|
|
1520
1628
|
let SAFE_MODE = true;
|
|
1521
|
-
const fixMarkupRe = /(^(<[^>]+>|\t|)+|\n)/gm;
|
|
1522
1629
|
const LANGUAGE_NOT_FOUND = "Could not find the language '{}', did you forget to load/include a language module?";
|
|
1523
1630
|
/** @type {Language} */
|
|
1524
1631
|
const PLAINTEXT_LANGUAGE = { disableAutodetect: true, name: 'Plain text', contains: [] };
|
|
@@ -1527,11 +1634,12 @@
|
|
|
1527
1634
|
// calling the `hljs.configure` function.
|
|
1528
1635
|
/** @type HLJSOptions */
|
|
1529
1636
|
let options = {
|
|
1637
|
+
ignoreUnescapedHTML: false,
|
|
1638
|
+
throwUnescapedHTML: false,
|
|
1530
1639
|
noHighlightRe: /^(no-?highlight)$/i,
|
|
1531
1640
|
languageDetectRe: /\blang(?:uage)?-([\w-]+)\b/i,
|
|
1532
1641
|
classPrefix: 'hljs-',
|
|
1533
|
-
|
|
1534
|
-
useBR: false,
|
|
1642
|
+
cssSelector: 'pre code',
|
|
1535
1643
|
languages: null,
|
|
1536
1644
|
// beta configuration options, subject to change, welcome to discuss
|
|
1537
1645
|
// https://github.com/highlightjs/highlight.js/issues/1086
|
|
@@ -1581,10 +1689,9 @@
|
|
|
1581
1689
|
* NEW API
|
|
1582
1690
|
* highlight(code, {lang, ignoreIllegals})
|
|
1583
1691
|
*
|
|
1584
|
-
* @param {string}
|
|
1692
|
+
* @param {string} codeOrLanguageName - the language to use for highlighting
|
|
1585
1693
|
* @param {string | HighlightOptions} optionsOrCode - the code to highlight
|
|
1586
1694
|
* @param {boolean} [ignoreIllegals] - whether to ignore illegal matches, default is to bail
|
|
1587
|
-
* @param {CompiledMode} [continuation] - current continuation mode, if any
|
|
1588
1695
|
*
|
|
1589
1696
|
* @returns {HighlightResult} Result - an object that represents the result
|
|
1590
1697
|
* @property {string} language - the language name
|
|
@@ -1594,24 +1701,25 @@
|
|
|
1594
1701
|
* @property {CompiledMode} top - top of the current mode stack
|
|
1595
1702
|
* @property {boolean} illegal - indicates whether any illegal matches were found
|
|
1596
1703
|
*/
|
|
1597
|
-
function highlight(
|
|
1704
|
+
function highlight(codeOrLanguageName, optionsOrCode, ignoreIllegals) {
|
|
1598
1705
|
let code = "";
|
|
1599
1706
|
let languageName = "";
|
|
1600
1707
|
if (typeof optionsOrCode === "object") {
|
|
1601
|
-
code =
|
|
1708
|
+
code = codeOrLanguageName;
|
|
1602
1709
|
ignoreIllegals = optionsOrCode.ignoreIllegals;
|
|
1603
1710
|
languageName = optionsOrCode.language;
|
|
1604
|
-
// continuation not supported at all via the new API
|
|
1605
|
-
// eslint-disable-next-line no-undefined
|
|
1606
|
-
continuation = undefined;
|
|
1607
1711
|
} else {
|
|
1608
1712
|
// old API
|
|
1609
1713
|
deprecated("10.7.0", "highlight(lang, code, ...args) has been deprecated.");
|
|
1610
1714
|
deprecated("10.7.0", "Please use highlight(code, options) instead.\nhttps://github.com/highlightjs/highlight.js/issues/2277");
|
|
1611
|
-
languageName =
|
|
1715
|
+
languageName = codeOrLanguageName;
|
|
1612
1716
|
code = optionsOrCode;
|
|
1613
1717
|
}
|
|
1614
1718
|
|
|
1719
|
+
// https://github.com/highlightjs/highlight.js/issues/3149
|
|
1720
|
+
// eslint-disable-next-line no-undefined
|
|
1721
|
+
if (ignoreIllegals === undefined) { ignoreIllegals = true; }
|
|
1722
|
+
|
|
1615
1723
|
/** @type {BeforeHighlightContext} */
|
|
1616
1724
|
const context = {
|
|
1617
1725
|
code,
|
|
@@ -1625,7 +1733,7 @@
|
|
|
1625
1733
|
// in which case we don't even need to call highlight
|
|
1626
1734
|
const result = context.result
|
|
1627
1735
|
? context.result
|
|
1628
|
-
: _highlight(context.language, context.code, ignoreIllegals
|
|
1736
|
+
: _highlight(context.language, context.code, ignoreIllegals);
|
|
1629
1737
|
|
|
1630
1738
|
result.code = context.code;
|
|
1631
1739
|
// the plugin can change anything in result to suite it
|
|
@@ -1644,15 +1752,16 @@
|
|
|
1644
1752
|
* @returns {HighlightResult} - result of the highlight operation
|
|
1645
1753
|
*/
|
|
1646
1754
|
function _highlight(languageName, codeToHighlight, ignoreIllegals, continuation) {
|
|
1755
|
+
const keywordHits = Object.create(null);
|
|
1756
|
+
|
|
1647
1757
|
/**
|
|
1648
1758
|
* Return keyword data if a match is a keyword
|
|
1649
1759
|
* @param {CompiledMode} mode - current mode
|
|
1650
|
-
* @param {
|
|
1760
|
+
* @param {string} matchText - the textual match
|
|
1651
1761
|
* @returns {KeywordData | false}
|
|
1652
1762
|
*/
|
|
1653
|
-
function keywordData(mode,
|
|
1654
|
-
|
|
1655
|
-
return Object.prototype.hasOwnProperty.call(mode.keywords, matchText) && mode.keywords[matchText];
|
|
1763
|
+
function keywordData(mode, matchText) {
|
|
1764
|
+
return mode.keywords[matchText];
|
|
1656
1765
|
}
|
|
1657
1766
|
|
|
1658
1767
|
function processKeywords() {
|
|
@@ -1668,13 +1777,15 @@
|
|
|
1668
1777
|
|
|
1669
1778
|
while (match) {
|
|
1670
1779
|
buf += modeBuffer.substring(lastIndex, match.index);
|
|
1671
|
-
const
|
|
1780
|
+
const word = language.case_insensitive ? match[0].toLowerCase() : match[0];
|
|
1781
|
+
const data = keywordData(top, word);
|
|
1672
1782
|
if (data) {
|
|
1673
1783
|
const [kind, keywordRelevance] = data;
|
|
1674
1784
|
emitter.addText(buf);
|
|
1675
1785
|
buf = "";
|
|
1676
1786
|
|
|
1677
|
-
|
|
1787
|
+
keywordHits[word] = (keywordHits[word] || 0) + 1;
|
|
1788
|
+
if (keywordHits[word] <= MAX_KEYWORD_HITS) relevance += keywordRelevance;
|
|
1678
1789
|
if (kind.startsWith("_")) {
|
|
1679
1790
|
// _ implied for relevance only, do not highlight
|
|
1680
1791
|
// by applying a class name
|
|
@@ -1689,7 +1800,7 @@
|
|
|
1689
1800
|
lastIndex = top.keywordPatternRe.lastIndex;
|
|
1690
1801
|
match = top.keywordPatternRe.exec(modeBuffer);
|
|
1691
1802
|
}
|
|
1692
|
-
buf += modeBuffer.
|
|
1803
|
+
buf += modeBuffer.substring(lastIndex);
|
|
1693
1804
|
emitter.addText(buf);
|
|
1694
1805
|
}
|
|
1695
1806
|
|
|
@@ -1704,7 +1815,7 @@
|
|
|
1704
1815
|
return;
|
|
1705
1816
|
}
|
|
1706
1817
|
result = _highlight(top.subLanguage, modeBuffer, true, continuations[top.subLanguage]);
|
|
1707
|
-
continuations[top.subLanguage] = /** @type {CompiledMode} */ (result.
|
|
1818
|
+
continuations[top.subLanguage] = /** @type {CompiledMode} */ (result._top);
|
|
1708
1819
|
} else {
|
|
1709
1820
|
result = highlightAuto(modeBuffer, top.subLanguage.length ? top.subLanguage : null);
|
|
1710
1821
|
}
|
|
@@ -1716,7 +1827,7 @@
|
|
|
1716
1827
|
if (top.relevance > 0) {
|
|
1717
1828
|
relevance += result.relevance;
|
|
1718
1829
|
}
|
|
1719
|
-
emitter.addSublanguage(result.
|
|
1830
|
+
emitter.addSublanguage(result._emitter, result.language);
|
|
1720
1831
|
}
|
|
1721
1832
|
|
|
1722
1833
|
function processBuffer() {
|
|
@@ -1729,12 +1840,47 @@
|
|
|
1729
1840
|
}
|
|
1730
1841
|
|
|
1731
1842
|
/**
|
|
1732
|
-
* @param {
|
|
1843
|
+
* @param {CompiledScope} scope
|
|
1844
|
+
* @param {RegExpMatchArray} match
|
|
1733
1845
|
*/
|
|
1734
|
-
function
|
|
1735
|
-
|
|
1736
|
-
|
|
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++;
|
|
1737
1861
|
}
|
|
1862
|
+
}
|
|
1863
|
+
|
|
1864
|
+
/**
|
|
1865
|
+
* @param {CompiledMode} mode - new mode to start
|
|
1866
|
+
* @param {RegExpMatchArray} match
|
|
1867
|
+
*/
|
|
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
|
+
}
|
|
1882
|
+
}
|
|
1883
|
+
|
|
1738
1884
|
top = Object.create(mode, { parent: { value: top } });
|
|
1739
1885
|
return top;
|
|
1740
1886
|
}
|
|
@@ -1776,7 +1922,7 @@
|
|
|
1776
1922
|
*/
|
|
1777
1923
|
function doIgnore(lexeme) {
|
|
1778
1924
|
if (top.matcher.regexIndex === 0) {
|
|
1779
|
-
// no more
|
|
1925
|
+
// no more regexes to potentially match here, so we move the cursor forward one
|
|
1780
1926
|
// space
|
|
1781
1927
|
modeBuffer += lexeme[0];
|
|
1782
1928
|
return 1;
|
|
@@ -1807,10 +1953,6 @@
|
|
|
1807
1953
|
if (resp.isMatchIgnored) return doIgnore(lexeme);
|
|
1808
1954
|
}
|
|
1809
1955
|
|
|
1810
|
-
if (newMode && newMode.endSameAsBegin) {
|
|
1811
|
-
newMode.endRe = escape(lexeme);
|
|
1812
|
-
}
|
|
1813
|
-
|
|
1814
1956
|
if (newMode.skip) {
|
|
1815
1957
|
modeBuffer += lexeme;
|
|
1816
1958
|
} else {
|
|
@@ -1822,11 +1964,7 @@
|
|
|
1822
1964
|
modeBuffer = lexeme;
|
|
1823
1965
|
}
|
|
1824
1966
|
}
|
|
1825
|
-
startNewMode(newMode);
|
|
1826
|
-
// if (mode["after:begin"]) {
|
|
1827
|
-
// let resp = new Response(mode);
|
|
1828
|
-
// mode["after:begin"](match, resp);
|
|
1829
|
-
// }
|
|
1967
|
+
startNewMode(newMode, match);
|
|
1830
1968
|
return newMode.returnBegin ? 0 : lexeme.length;
|
|
1831
1969
|
}
|
|
1832
1970
|
|
|
@@ -1837,13 +1975,19 @@
|
|
|
1837
1975
|
*/
|
|
1838
1976
|
function doEndMatch(match) {
|
|
1839
1977
|
const lexeme = match[0];
|
|
1840
|
-
const matchPlusRemainder = codeToHighlight.
|
|
1978
|
+
const matchPlusRemainder = codeToHighlight.substring(match.index);
|
|
1841
1979
|
|
|
1842
1980
|
const endMode = endOfMode(top, match, matchPlusRemainder);
|
|
1843
1981
|
if (!endMode) { return NO_MATCH; }
|
|
1844
1982
|
|
|
1845
1983
|
const origin = top;
|
|
1846
|
-
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) {
|
|
1847
1991
|
modeBuffer += lexeme;
|
|
1848
1992
|
} else {
|
|
1849
1993
|
if (!(origin.returnEnd || origin.excludeEnd)) {
|
|
@@ -1855,7 +1999,7 @@
|
|
|
1855
1999
|
}
|
|
1856
2000
|
}
|
|
1857
2001
|
do {
|
|
1858
|
-
if (top.
|
|
2002
|
+
if (top.scope) {
|
|
1859
2003
|
emitter.closeNode();
|
|
1860
2004
|
}
|
|
1861
2005
|
if (!top.skip && !top.subLanguage) {
|
|
@@ -1864,10 +2008,7 @@
|
|
|
1864
2008
|
top = top.parent;
|
|
1865
2009
|
} while (top !== endMode.parent);
|
|
1866
2010
|
if (endMode.starts) {
|
|
1867
|
-
|
|
1868
|
-
endMode.starts.endRe = endMode.endRe;
|
|
1869
|
-
}
|
|
1870
|
-
startNewMode(endMode.starts);
|
|
2011
|
+
startNewMode(endMode.starts, match);
|
|
1871
2012
|
}
|
|
1872
2013
|
return origin.returnEnd ? 0 : lexeme.length;
|
|
1873
2014
|
}
|
|
@@ -1875,8 +2016,8 @@
|
|
|
1875
2016
|
function processContinuations() {
|
|
1876
2017
|
const list = [];
|
|
1877
2018
|
for (let current = top; current !== language; current = current.parent) {
|
|
1878
|
-
if (current.
|
|
1879
|
-
list.unshift(current.
|
|
2019
|
+
if (current.scope) {
|
|
2020
|
+
list.unshift(current.scope);
|
|
1880
2021
|
}
|
|
1881
2022
|
}
|
|
1882
2023
|
list.forEach(item => emitter.openNode(item));
|
|
@@ -1888,7 +2029,7 @@
|
|
|
1888
2029
|
/**
|
|
1889
2030
|
* Process an individual match
|
|
1890
2031
|
*
|
|
1891
|
-
* @param {string} textBeforeMatch - text
|
|
2032
|
+
* @param {string} textBeforeMatch - text preceding the match (since the last match)
|
|
1892
2033
|
* @param {EnhancedMatch} [match] - the match itself
|
|
1893
2034
|
*/
|
|
1894
2035
|
function processLexeme(textBeforeMatch, match) {
|
|
@@ -1911,7 +2052,7 @@
|
|
|
1911
2052
|
modeBuffer += codeToHighlight.slice(match.index, match.index + 1);
|
|
1912
2053
|
if (!SAFE_MODE) {
|
|
1913
2054
|
/** @type {AnnotatedError} */
|
|
1914
|
-
const err = new Error(
|
|
2055
|
+
const err = new Error(`0 width match regex (${languageName})`);
|
|
1915
2056
|
err.languageName = languageName;
|
|
1916
2057
|
err.badRule = lastMatch.rule;
|
|
1917
2058
|
throw err;
|
|
@@ -1925,7 +2066,7 @@
|
|
|
1925
2066
|
} else if (match.type === "illegal" && !ignoreIllegals) {
|
|
1926
2067
|
// illegal match, we do not continue processing
|
|
1927
2068
|
/** @type {AnnotatedError} */
|
|
1928
|
-
const err = new Error('Illegal lexeme "' + lexeme + '" for mode "' + (top.
|
|
2069
|
+
const err = new Error('Illegal lexeme "' + lexeme + '" for mode "' + (top.scope || '<unnamed>') + '"');
|
|
1929
2070
|
err.mode = top;
|
|
1930
2071
|
throw err;
|
|
1931
2072
|
} else if (match.type === "end") {
|
|
@@ -1953,13 +2094,9 @@
|
|
|
1953
2094
|
}
|
|
1954
2095
|
|
|
1955
2096
|
/*
|
|
1956
|
-
Why might be find ourselves here?
|
|
1957
|
-
triggered but could not be completed.
|
|
1958
|
-
|
|
1959
|
-
being used to scan the text isn't recompiled that means that any match that LOOKS like
|
|
1960
|
-
the end (but is not, because it is not an exact match to the beginning) will
|
|
1961
|
-
end up here. A definite end match, but when `doEndMatch` tries to "reapply"
|
|
1962
|
-
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)
|
|
1963
2100
|
|
|
1964
2101
|
This causes no real harm other than stopping a few times too many.
|
|
1965
2102
|
*/
|
|
@@ -1974,7 +2111,7 @@
|
|
|
1974
2111
|
throw new Error('Unknown language: "' + languageName + '"');
|
|
1975
2112
|
}
|
|
1976
2113
|
|
|
1977
|
-
const md = compileLanguage(language
|
|
2114
|
+
const md = compileLanguage(language);
|
|
1978
2115
|
let result = '';
|
|
1979
2116
|
/** @type {CompiledMode} */
|
|
1980
2117
|
let top = continuation || md;
|
|
@@ -2011,44 +2148,44 @@
|
|
|
2011
2148
|
const processedCount = processLexeme(beforeMatch, match);
|
|
2012
2149
|
index = match.index + processedCount;
|
|
2013
2150
|
}
|
|
2014
|
-
processLexeme(codeToHighlight.
|
|
2151
|
+
processLexeme(codeToHighlight.substring(index));
|
|
2015
2152
|
emitter.closeAllNodes();
|
|
2016
2153
|
emitter.finalize();
|
|
2017
2154
|
result = emitter.toHTML();
|
|
2018
2155
|
|
|
2019
2156
|
return {
|
|
2020
|
-
// avoid possible breakage with v10 clients expecting
|
|
2021
|
-
// this to always be an integer
|
|
2022
|
-
relevance: Math.floor(relevance),
|
|
2023
|
-
value: result,
|
|
2024
2157
|
language: languageName,
|
|
2158
|
+
value: result,
|
|
2159
|
+
relevance: relevance,
|
|
2025
2160
|
illegal: false,
|
|
2026
|
-
|
|
2027
|
-
|
|
2161
|
+
_emitter: emitter,
|
|
2162
|
+
_top: top
|
|
2028
2163
|
};
|
|
2029
2164
|
} catch (err) {
|
|
2030
2165
|
if (err.message && err.message.includes('Illegal')) {
|
|
2031
2166
|
return {
|
|
2167
|
+
language: languageName,
|
|
2168
|
+
value: escape(codeToHighlight),
|
|
2032
2169
|
illegal: true,
|
|
2033
|
-
|
|
2034
|
-
|
|
2170
|
+
relevance: 0,
|
|
2171
|
+
_illegalBy: {
|
|
2172
|
+
message: err.message,
|
|
2173
|
+
index: index,
|
|
2035
2174
|
context: codeToHighlight.slice(index - 100, index + 100),
|
|
2036
|
-
mode: err.mode
|
|
2175
|
+
mode: err.mode,
|
|
2176
|
+
resultSoFar: result
|
|
2037
2177
|
},
|
|
2038
|
-
|
|
2039
|
-
relevance: 0,
|
|
2040
|
-
value: escape$1(codeToHighlight),
|
|
2041
|
-
emitter: emitter
|
|
2178
|
+
_emitter: emitter
|
|
2042
2179
|
};
|
|
2043
2180
|
} else if (SAFE_MODE) {
|
|
2044
2181
|
return {
|
|
2182
|
+
language: languageName,
|
|
2183
|
+
value: escape(codeToHighlight),
|
|
2045
2184
|
illegal: false,
|
|
2046
2185
|
relevance: 0,
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
top: top,
|
|
2051
|
-
errorRaised: err
|
|
2186
|
+
errorRaised: err,
|
|
2187
|
+
_emitter: emitter,
|
|
2188
|
+
_top: top
|
|
2052
2189
|
};
|
|
2053
2190
|
} else {
|
|
2054
2191
|
throw err;
|
|
@@ -2065,13 +2202,13 @@
|
|
|
2065
2202
|
*/
|
|
2066
2203
|
function justTextHighlightResult(code) {
|
|
2067
2204
|
const result = {
|
|
2068
|
-
|
|
2069
|
-
emitter: new options.__emitter(options),
|
|
2070
|
-
value: escape$1(code),
|
|
2205
|
+
value: escape(code),
|
|
2071
2206
|
illegal: false,
|
|
2072
|
-
|
|
2207
|
+
relevance: 0,
|
|
2208
|
+
_top: PLAINTEXT_LANGUAGE,
|
|
2209
|
+
_emitter: new options.__emitter(options)
|
|
2073
2210
|
};
|
|
2074
|
-
result.
|
|
2211
|
+
result._emitter.addText(code);
|
|
2075
2212
|
return result;
|
|
2076
2213
|
}
|
|
2077
2214
|
|
|
@@ -2082,7 +2219,7 @@
|
|
|
2082
2219
|
- language (detected language)
|
|
2083
2220
|
- relevance (int)
|
|
2084
2221
|
- value (an HTML string with highlighting markup)
|
|
2085
|
-
-
|
|
2222
|
+
- secondBest (object with the same structure for second-best heuristically
|
|
2086
2223
|
detected language, may be absent)
|
|
2087
2224
|
|
|
2088
2225
|
@param {string} code
|
|
@@ -2123,35 +2260,11 @@
|
|
|
2123
2260
|
|
|
2124
2261
|
/** @type {AutoHighlightResult} */
|
|
2125
2262
|
const result = best;
|
|
2126
|
-
result.
|
|
2263
|
+
result.secondBest = secondBest;
|
|
2127
2264
|
|
|
2128
2265
|
return result;
|
|
2129
2266
|
}
|
|
2130
2267
|
|
|
2131
|
-
/**
|
|
2132
|
-
Post-processing of the highlighted markup:
|
|
2133
|
-
|
|
2134
|
-
- replace TABs with something more useful
|
|
2135
|
-
- replace real line-breaks with '<br>' for non-pre containers
|
|
2136
|
-
|
|
2137
|
-
@param {string} html
|
|
2138
|
-
@returns {string}
|
|
2139
|
-
*/
|
|
2140
|
-
function fixMarkup(html) {
|
|
2141
|
-
if (!(options.tabReplace || options.useBR)) {
|
|
2142
|
-
return html;
|
|
2143
|
-
}
|
|
2144
|
-
|
|
2145
|
-
return html.replace(fixMarkupRe, match => {
|
|
2146
|
-
if (match === '\n') {
|
|
2147
|
-
return options.useBR ? '<br>' : match;
|
|
2148
|
-
} else if (options.tabReplace) {
|
|
2149
|
-
return match.replace(/\t/g, options.tabReplace);
|
|
2150
|
-
}
|
|
2151
|
-
return match;
|
|
2152
|
-
});
|
|
2153
|
-
}
|
|
2154
|
-
|
|
2155
2268
|
/**
|
|
2156
2269
|
* Builds new class name for block given the language name
|
|
2157
2270
|
*
|
|
@@ -2160,41 +2273,14 @@
|
|
|
2160
2273
|
* @param {string} [resultLang]
|
|
2161
2274
|
*/
|
|
2162
2275
|
function updateClassName(element, currentLang, resultLang) {
|
|
2163
|
-
const language = currentLang
|
|
2276
|
+
const language = (currentLang && aliases[currentLang]) || resultLang;
|
|
2164
2277
|
|
|
2165
2278
|
element.classList.add("hljs");
|
|
2166
|
-
|
|
2279
|
+
element.classList.add(`language-${language}`);
|
|
2167
2280
|
}
|
|
2168
2281
|
|
|
2169
|
-
/** @type {HLJSPlugin} */
|
|
2170
|
-
const brPlugin = {
|
|
2171
|
-
"before:highlightElement": ({ el }) => {
|
|
2172
|
-
if (options.useBR) {
|
|
2173
|
-
el.innerHTML = el.innerHTML.replace(/\n/g, '').replace(/<br[ /]*>/g, '\n');
|
|
2174
|
-
}
|
|
2175
|
-
},
|
|
2176
|
-
"after:highlightElement": ({ result }) => {
|
|
2177
|
-
if (options.useBR) {
|
|
2178
|
-
result.value = result.value.replace(/\n/g, "<br>");
|
|
2179
|
-
}
|
|
2180
|
-
}
|
|
2181
|
-
};
|
|
2182
|
-
|
|
2183
|
-
const TAB_REPLACE_RE = /^(<[^>]+>|\t)+/gm;
|
|
2184
|
-
/** @type {HLJSPlugin} */
|
|
2185
|
-
const tabReplacePlugin = {
|
|
2186
|
-
"after:highlightElement": ({ result }) => {
|
|
2187
|
-
if (options.tabReplace) {
|
|
2188
|
-
result.value = result.value.replace(TAB_REPLACE_RE, (m) =>
|
|
2189
|
-
m.replace(/\t/g, options.tabReplace)
|
|
2190
|
-
);
|
|
2191
|
-
}
|
|
2192
|
-
}
|
|
2193
|
-
};
|
|
2194
|
-
|
|
2195
2282
|
/**
|
|
2196
|
-
* Applies highlighting to a DOM node containing code.
|
|
2197
|
-
* two optional parameters for fixMarkup.
|
|
2283
|
+
* Applies highlighting to a DOM node containing code.
|
|
2198
2284
|
*
|
|
2199
2285
|
* @param {HighlightedHTMLElement} element - the HTML element to highlight
|
|
2200
2286
|
*/
|
|
@@ -2205,33 +2291,50 @@
|
|
|
2205
2291
|
|
|
2206
2292
|
if (shouldNotHighlight(language)) return;
|
|
2207
2293
|
|
|
2208
|
-
// support for v10 API
|
|
2209
2294
|
fire("before:highlightElement",
|
|
2210
2295
|
{ el: element, language: language });
|
|
2211
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
|
+
|
|
2212
2318
|
node = element;
|
|
2213
2319
|
const text = node.textContent;
|
|
2214
2320
|
const result = language ? highlight(text, { language, ignoreIllegals: true }) : highlightAuto(text);
|
|
2215
2321
|
|
|
2216
|
-
// support for v10 API
|
|
2217
|
-
fire("after:highlightElement", { el: element, result, text });
|
|
2218
|
-
|
|
2219
2322
|
element.innerHTML = result.value;
|
|
2220
2323
|
updateClassName(element, language, result.language);
|
|
2221
2324
|
element.result = {
|
|
2222
2325
|
language: result.language,
|
|
2223
2326
|
// TODO: remove with version 11.0
|
|
2224
2327
|
re: result.relevance,
|
|
2225
|
-
|
|
2328
|
+
relevance: result.relevance
|
|
2226
2329
|
};
|
|
2227
|
-
if (result.
|
|
2228
|
-
element.
|
|
2229
|
-
language: result.
|
|
2230
|
-
|
|
2231
|
-
re: result.second_best.relevance,
|
|
2232
|
-
relavance: result.second_best.relevance
|
|
2330
|
+
if (result.secondBest) {
|
|
2331
|
+
element.secondBest = {
|
|
2332
|
+
language: result.secondBest.language,
|
|
2333
|
+
relevance: result.secondBest.relevance
|
|
2233
2334
|
};
|
|
2234
2335
|
}
|
|
2336
|
+
|
|
2337
|
+
fire("after:highlightElement", { el: element, result, text });
|
|
2235
2338
|
}
|
|
2236
2339
|
|
|
2237
2340
|
/**
|
|
@@ -2240,34 +2343,19 @@
|
|
|
2240
2343
|
* @param {Partial<HLJSOptions>} userOptions
|
|
2241
2344
|
*/
|
|
2242
2345
|
function configure(userOptions) {
|
|
2243
|
-
|
|
2244
|
-
deprecated("10.3.0", "'useBR' will be removed entirely in v11.0");
|
|
2245
|
-
deprecated("10.3.0", "Please see https://github.com/highlightjs/highlight.js/issues/2559");
|
|
2246
|
-
}
|
|
2247
|
-
options = inherit$1(options, userOptions);
|
|
2346
|
+
options = inherit(options, userOptions);
|
|
2248
2347
|
}
|
|
2249
2348
|
|
|
2250
|
-
/**
|
|
2251
|
-
* Highlights to all <pre><code> blocks on a page
|
|
2252
|
-
*
|
|
2253
|
-
* @type {Function & {called?: boolean}}
|
|
2254
|
-
*/
|
|
2255
2349
|
// TODO: remove v12, deprecated
|
|
2256
2350
|
const initHighlighting = () => {
|
|
2257
|
-
|
|
2258
|
-
initHighlighting.
|
|
2259
|
-
|
|
2260
|
-
deprecated("10.6.0", "initHighlighting() is deprecated. Use highlightAll() instead.");
|
|
2261
|
-
|
|
2262
|
-
const blocks = document.querySelectorAll('pre code');
|
|
2263
|
-
blocks.forEach(highlightElement);
|
|
2351
|
+
highlightAll();
|
|
2352
|
+
deprecated("10.6.0", "initHighlighting() deprecated. Use highlightAll() now.");
|
|
2264
2353
|
};
|
|
2265
2354
|
|
|
2266
|
-
// Higlights all when DOMContentLoaded fires
|
|
2267
2355
|
// TODO: remove v12, deprecated
|
|
2268
2356
|
function initHighlightingOnLoad() {
|
|
2269
|
-
|
|
2270
|
-
|
|
2357
|
+
highlightAll();
|
|
2358
|
+
deprecated("10.6.0", "initHighlightingOnLoad() deprecated. Use highlightAll() now.");
|
|
2271
2359
|
}
|
|
2272
2360
|
|
|
2273
2361
|
let wantsHighlight = false;
|
|
@@ -2282,7 +2370,7 @@
|
|
|
2282
2370
|
return;
|
|
2283
2371
|
}
|
|
2284
2372
|
|
|
2285
|
-
const blocks = document.querySelectorAll(
|
|
2373
|
+
const blocks = document.querySelectorAll(options.cssSelector);
|
|
2286
2374
|
blocks.forEach(highlightElement);
|
|
2287
2375
|
}
|
|
2288
2376
|
|
|
@@ -2347,26 +2435,6 @@
|
|
|
2347
2435
|
return Object.keys(languages);
|
|
2348
2436
|
}
|
|
2349
2437
|
|
|
2350
|
-
/**
|
|
2351
|
-
intended usage: When one language truly requires another
|
|
2352
|
-
|
|
2353
|
-
Unlike `getLanguage`, this will throw when the requested language
|
|
2354
|
-
is not available.
|
|
2355
|
-
|
|
2356
|
-
@param {string} name - name of the language to fetch/require
|
|
2357
|
-
@returns {Language | never}
|
|
2358
|
-
*/
|
|
2359
|
-
function requireLanguage(name) {
|
|
2360
|
-
deprecated("10.4.0", "requireLanguage will be removed entirely in v11.");
|
|
2361
|
-
deprecated("10.4.0", "Please see https://github.com/highlightjs/highlight.js/pull/2844");
|
|
2362
|
-
|
|
2363
|
-
const lang = getLanguage(name);
|
|
2364
|
-
if (lang) { return lang; }
|
|
2365
|
-
|
|
2366
|
-
const err = new Error('The \'{}\' language is required, but not loaded.'.replace('{}', name));
|
|
2367
|
-
throw err;
|
|
2368
|
-
}
|
|
2369
|
-
|
|
2370
2438
|
/**
|
|
2371
2439
|
* @param {string} name - name of the language to retrieve
|
|
2372
2440
|
* @returns {Language | undefined}
|
|
@@ -2443,20 +2511,7 @@
|
|
|
2443
2511
|
}
|
|
2444
2512
|
|
|
2445
2513
|
/**
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
@param {string} arg
|
|
2449
|
-
@returns {string}
|
|
2450
|
-
*/
|
|
2451
|
-
function deprecateFixMarkup(arg) {
|
|
2452
|
-
deprecated("10.2.0", "fixMarkup will be removed entirely in v11.0");
|
|
2453
|
-
deprecated("10.2.0", "Please see https://github.com/highlightjs/highlight.js/issues/2534");
|
|
2454
|
-
|
|
2455
|
-
return fixMarkup(arg);
|
|
2456
|
-
}
|
|
2457
|
-
|
|
2458
|
-
/**
|
|
2459
|
-
*
|
|
2514
|
+
* DEPRECATED
|
|
2460
2515
|
* @param {HighlightedHTMLElement} el
|
|
2461
2516
|
*/
|
|
2462
2517
|
function deprecateHighlightBlock(el) {
|
|
@@ -2471,7 +2526,6 @@
|
|
|
2471
2526
|
highlight,
|
|
2472
2527
|
highlightAuto,
|
|
2473
2528
|
highlightAll,
|
|
2474
|
-
fixMarkup: deprecateFixMarkup,
|
|
2475
2529
|
highlightElement,
|
|
2476
2530
|
// TODO: Remove with v12 API
|
|
2477
2531
|
highlightBlock: deprecateHighlightBlock,
|
|
@@ -2483,394 +2537,45 @@
|
|
|
2483
2537
|
listLanguages,
|
|
2484
2538
|
getLanguage,
|
|
2485
2539
|
registerAliases,
|
|
2486
|
-
requireLanguage,
|
|
2487
2540
|
autoDetection,
|
|
2488
|
-
inherit
|
|
2489
|
-
addPlugin
|
|
2490
|
-
// plugins for frameworks
|
|
2491
|
-
vuePlugin: BuildVuePlugin(hljs).VuePlugin
|
|
2541
|
+
inherit,
|
|
2542
|
+
addPlugin
|
|
2492
2543
|
});
|
|
2493
2544
|
|
|
2494
2545
|
hljs.debugMode = function() { SAFE_MODE = false; };
|
|
2495
2546
|
hljs.safeMode = function() { SAFE_MODE = true; };
|
|
2496
2547
|
hljs.versionString = version;
|
|
2497
2548
|
|
|
2549
|
+
hljs.regex = {
|
|
2550
|
+
concat: concat,
|
|
2551
|
+
lookahead: lookahead,
|
|
2552
|
+
either: either,
|
|
2553
|
+
optional: optional,
|
|
2554
|
+
anyNumberOfTimes: anyNumberOfTimes
|
|
2555
|
+
};
|
|
2556
|
+
|
|
2498
2557
|
for (const key in MODES) {
|
|
2499
2558
|
// @ts-ignore
|
|
2500
2559
|
if (typeof MODES[key] === "object") {
|
|
2501
2560
|
// @ts-ignore
|
|
2502
|
-
deepFreezeEs6(MODES[key]);
|
|
2561
|
+
deepFreezeEs6.exports(MODES[key]);
|
|
2503
2562
|
}
|
|
2504
2563
|
}
|
|
2505
2564
|
|
|
2506
|
-
// merge all the modes/
|
|
2565
|
+
// merge all the modes/regexes into our main object
|
|
2507
2566
|
Object.assign(hljs, MODES);
|
|
2508
2567
|
|
|
2509
|
-
// built-in plugins, likely to be moved out of core in the future
|
|
2510
|
-
hljs.addPlugin(brPlugin); // slated to be removed in v11
|
|
2511
|
-
hljs.addPlugin(mergeHTMLPlugin);
|
|
2512
|
-
hljs.addPlugin(tabReplacePlugin);
|
|
2513
2568
|
return hljs;
|
|
2514
2569
|
};
|
|
2515
2570
|
|
|
2516
2571
|
// export an "instance" of the highlighter
|
|
2517
|
-
var highlight
|
|
2518
|
-
|
|
2519
|
-
var core$1 = highlight$1;
|
|
2572
|
+
var highlight = HLJS({});
|
|
2520
2573
|
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
}
|
|
2525
|
-
|
|
2526
|
-
var format = createCommonjsModule(function (module) {
|
|
2527
|
-
(function() {
|
|
2528
|
-
|
|
2529
|
-
//// Export the API
|
|
2530
|
-
var namespace;
|
|
2531
|
-
|
|
2532
|
-
// CommonJS / Node module
|
|
2533
|
-
{
|
|
2534
|
-
namespace = module.exports = format;
|
|
2535
|
-
}
|
|
2536
|
-
|
|
2537
|
-
namespace.format = format;
|
|
2538
|
-
namespace.vsprintf = vsprintf;
|
|
2539
|
-
|
|
2540
|
-
if (typeof console !== 'undefined' && typeof console.log === 'function') {
|
|
2541
|
-
namespace.printf = printf;
|
|
2542
|
-
}
|
|
2543
|
-
|
|
2544
|
-
function printf(/* ... */) {
|
|
2545
|
-
console.log(format.apply(null, arguments));
|
|
2546
|
-
}
|
|
2547
|
-
|
|
2548
|
-
function vsprintf(fmt, replacements) {
|
|
2549
|
-
return format.apply(null, [fmt].concat(replacements));
|
|
2550
|
-
}
|
|
2551
|
-
|
|
2552
|
-
function format(fmt) {
|
|
2553
|
-
var argIndex = 1 // skip initial format argument
|
|
2554
|
-
, args = [].slice.call(arguments)
|
|
2555
|
-
, i = 0
|
|
2556
|
-
, n = fmt.length
|
|
2557
|
-
, result = ''
|
|
2558
|
-
, c
|
|
2559
|
-
, escaped = false
|
|
2560
|
-
, arg
|
|
2561
|
-
, tmp
|
|
2562
|
-
, leadingZero = false
|
|
2563
|
-
, precision
|
|
2564
|
-
, nextArg = function() { return args[argIndex++]; }
|
|
2565
|
-
, slurpNumber = function() {
|
|
2566
|
-
var digits = '';
|
|
2567
|
-
while (/\d/.test(fmt[i])) {
|
|
2568
|
-
digits += fmt[i++];
|
|
2569
|
-
c = fmt[i];
|
|
2570
|
-
}
|
|
2571
|
-
return digits.length > 0 ? parseInt(digits) : null;
|
|
2572
|
-
}
|
|
2573
|
-
;
|
|
2574
|
-
for (; i < n; ++i) {
|
|
2575
|
-
c = fmt[i];
|
|
2576
|
-
if (escaped) {
|
|
2577
|
-
escaped = false;
|
|
2578
|
-
if (c == '.') {
|
|
2579
|
-
leadingZero = false;
|
|
2580
|
-
c = fmt[++i];
|
|
2581
|
-
}
|
|
2582
|
-
else if (c == '0' && fmt[i + 1] == '.') {
|
|
2583
|
-
leadingZero = true;
|
|
2584
|
-
i += 2;
|
|
2585
|
-
c = fmt[i];
|
|
2586
|
-
}
|
|
2587
|
-
else {
|
|
2588
|
-
leadingZero = true;
|
|
2589
|
-
}
|
|
2590
|
-
precision = slurpNumber();
|
|
2591
|
-
switch (c) {
|
|
2592
|
-
case 'b': // number in binary
|
|
2593
|
-
result += parseInt(nextArg(), 10).toString(2);
|
|
2594
|
-
break;
|
|
2595
|
-
case 'c': // character
|
|
2596
|
-
arg = nextArg();
|
|
2597
|
-
if (typeof arg === 'string' || arg instanceof String)
|
|
2598
|
-
result += arg;
|
|
2599
|
-
else
|
|
2600
|
-
result += String.fromCharCode(parseInt(arg, 10));
|
|
2601
|
-
break;
|
|
2602
|
-
case 'd': // number in decimal
|
|
2603
|
-
result += parseInt(nextArg(), 10);
|
|
2604
|
-
break;
|
|
2605
|
-
case 'f': // floating point number
|
|
2606
|
-
tmp = String(parseFloat(nextArg()).toFixed(precision || 6));
|
|
2607
|
-
result += leadingZero ? tmp : tmp.replace(/^0/, '');
|
|
2608
|
-
break;
|
|
2609
|
-
case 'j': // JSON
|
|
2610
|
-
result += JSON.stringify(nextArg());
|
|
2611
|
-
break;
|
|
2612
|
-
case 'o': // number in octal
|
|
2613
|
-
result += '0' + parseInt(nextArg(), 10).toString(8);
|
|
2614
|
-
break;
|
|
2615
|
-
case 's': // string
|
|
2616
|
-
result += nextArg();
|
|
2617
|
-
break;
|
|
2618
|
-
case 'x': // lowercase hexadecimal
|
|
2619
|
-
result += '0x' + parseInt(nextArg(), 10).toString(16);
|
|
2620
|
-
break;
|
|
2621
|
-
case 'X': // uppercase hexadecimal
|
|
2622
|
-
result += '0x' + parseInt(nextArg(), 10).toString(16).toUpperCase();
|
|
2623
|
-
break;
|
|
2624
|
-
default:
|
|
2625
|
-
result += c;
|
|
2626
|
-
break;
|
|
2627
|
-
}
|
|
2628
|
-
} else if (c === '%') {
|
|
2629
|
-
escaped = true;
|
|
2630
|
-
} else {
|
|
2631
|
-
result += c;
|
|
2632
|
-
}
|
|
2633
|
-
}
|
|
2634
|
-
return result;
|
|
2635
|
-
}
|
|
2636
|
-
|
|
2637
|
-
}());
|
|
2638
|
-
});
|
|
2639
|
-
|
|
2640
|
-
var fault = create(Error);
|
|
2641
|
-
|
|
2642
|
-
var fault_1 = fault;
|
|
2643
|
-
|
|
2644
|
-
fault.eval = create(EvalError);
|
|
2645
|
-
fault.range = create(RangeError);
|
|
2646
|
-
fault.reference = create(ReferenceError);
|
|
2647
|
-
fault.syntax = create(SyntaxError);
|
|
2648
|
-
fault.type = create(TypeError);
|
|
2649
|
-
fault.uri = create(URIError);
|
|
2574
|
+
var core = highlight;
|
|
2575
|
+
highlight.HighlightJS = highlight;
|
|
2576
|
+
highlight.default = highlight;
|
|
2650
2577
|
|
|
2651
|
-
|
|
2652
|
-
|
|
2653
|
-
// Create a new `EConstructor`, with the formatted `format` as a first argument.
|
|
2654
|
-
function create(EConstructor) {
|
|
2655
|
-
FormattedError.displayName = EConstructor.displayName || EConstructor.name;
|
|
2656
|
-
|
|
2657
|
-
return FormattedError
|
|
2658
|
-
|
|
2659
|
-
function FormattedError(format$1) {
|
|
2660
|
-
if (format$1) {
|
|
2661
|
-
format$1 = format.apply(null, arguments);
|
|
2662
|
-
}
|
|
2663
|
-
|
|
2664
|
-
return new EConstructor(format$1)
|
|
2665
|
-
}
|
|
2666
|
-
}
|
|
2667
|
-
|
|
2668
|
-
var highlight_1 = highlight;
|
|
2669
|
-
var highlightAuto_1 = highlightAuto;
|
|
2670
|
-
var registerLanguage_1 = registerLanguage;
|
|
2671
|
-
var listLanguages_1 = listLanguages;
|
|
2672
|
-
var registerAlias_1 = registerAlias;
|
|
2673
|
-
|
|
2674
|
-
Emitter.prototype.addText = text;
|
|
2675
|
-
Emitter.prototype.addKeyword = addKeyword;
|
|
2676
|
-
Emitter.prototype.addSublanguage = addSublanguage;
|
|
2677
|
-
Emitter.prototype.openNode = open;
|
|
2678
|
-
Emitter.prototype.closeNode = close;
|
|
2679
|
-
Emitter.prototype.closeAllNodes = noop;
|
|
2680
|
-
Emitter.prototype.finalize = noop;
|
|
2681
|
-
Emitter.prototype.toHTML = toHtmlNoop;
|
|
2682
|
-
|
|
2683
|
-
var defaultPrefix = 'hljs-';
|
|
2684
|
-
|
|
2685
|
-
// Highlighting `value` in the language `name`.
|
|
2686
|
-
function highlight(name, value, options) {
|
|
2687
|
-
var before = core$1.configure({});
|
|
2688
|
-
var settings = options || {};
|
|
2689
|
-
var prefix = settings.prefix;
|
|
2690
|
-
var result;
|
|
2691
|
-
|
|
2692
|
-
if (typeof name !== 'string') {
|
|
2693
|
-
throw fault_1('Expected `string` for name, got `%s`', name)
|
|
2694
|
-
}
|
|
2695
|
-
|
|
2696
|
-
if (!core$1.getLanguage(name)) {
|
|
2697
|
-
throw fault_1('Unknown language: `%s` is not registered', name)
|
|
2698
|
-
}
|
|
2699
|
-
|
|
2700
|
-
if (typeof value !== 'string') {
|
|
2701
|
-
throw fault_1('Expected `string` for value, got `%s`', value)
|
|
2702
|
-
}
|
|
2703
|
-
|
|
2704
|
-
if (prefix === null || prefix === undefined) {
|
|
2705
|
-
prefix = defaultPrefix;
|
|
2706
|
-
}
|
|
2707
|
-
|
|
2708
|
-
core$1.configure({__emitter: Emitter, classPrefix: prefix});
|
|
2709
|
-
|
|
2710
|
-
result = core$1.highlight(value, {language: name, ignoreIllegals: true});
|
|
2711
|
-
|
|
2712
|
-
core$1.configure(before || {});
|
|
2713
|
-
|
|
2714
|
-
/* istanbul ignore if - Highlight.js seems to use this (currently) for broken
|
|
2715
|
-
* grammars, so let’s keep it in there just to be sure. */
|
|
2716
|
-
if (result.errorRaised) {
|
|
2717
|
-
throw result.errorRaised
|
|
2718
|
-
}
|
|
2719
|
-
|
|
2720
|
-
return {
|
|
2721
|
-
relevance: result.relevance,
|
|
2722
|
-
language: result.language,
|
|
2723
|
-
value: result.emitter.rootNode.children
|
|
2724
|
-
}
|
|
2725
|
-
}
|
|
2726
|
-
|
|
2727
|
-
function highlightAuto(value, options) {
|
|
2728
|
-
var settings = options || {};
|
|
2729
|
-
var subset = settings.subset || core$1.listLanguages();
|
|
2730
|
-
settings.prefix;
|
|
2731
|
-
var length = subset.length;
|
|
2732
|
-
var index = -1;
|
|
2733
|
-
var result;
|
|
2734
|
-
var secondBest;
|
|
2735
|
-
var current;
|
|
2736
|
-
var name;
|
|
2737
|
-
|
|
2738
|
-
if (typeof value !== 'string') {
|
|
2739
|
-
throw fault_1('Expected `string` for value, got `%s`', value)
|
|
2740
|
-
}
|
|
2741
|
-
|
|
2742
|
-
secondBest = {relevance: 0, language: null, value: []};
|
|
2743
|
-
result = {relevance: 0, language: null, value: []};
|
|
2744
|
-
|
|
2745
|
-
while (++index < length) {
|
|
2746
|
-
name = subset[index];
|
|
2747
|
-
|
|
2748
|
-
if (!core$1.getLanguage(name)) {
|
|
2749
|
-
continue
|
|
2750
|
-
}
|
|
2751
|
-
|
|
2752
|
-
current = highlight(name, value, options);
|
|
2753
|
-
current.language = name;
|
|
2754
|
-
|
|
2755
|
-
if (current.relevance > secondBest.relevance) {
|
|
2756
|
-
secondBest = current;
|
|
2757
|
-
}
|
|
2758
|
-
|
|
2759
|
-
if (current.relevance > result.relevance) {
|
|
2760
|
-
secondBest = result;
|
|
2761
|
-
result = current;
|
|
2762
|
-
}
|
|
2763
|
-
}
|
|
2764
|
-
|
|
2765
|
-
if (secondBest.language) {
|
|
2766
|
-
result.secondBest = secondBest;
|
|
2767
|
-
}
|
|
2768
|
-
|
|
2769
|
-
return result
|
|
2770
|
-
}
|
|
2771
|
-
|
|
2772
|
-
// Register a language.
|
|
2773
|
-
function registerLanguage(name, syntax) {
|
|
2774
|
-
core$1.registerLanguage(name, syntax);
|
|
2775
|
-
}
|
|
2776
|
-
|
|
2777
|
-
// Get a list of all registered languages.
|
|
2778
|
-
function listLanguages() {
|
|
2779
|
-
return core$1.listLanguages()
|
|
2780
|
-
}
|
|
2781
|
-
|
|
2782
|
-
// Register more aliases for an already registered language.
|
|
2783
|
-
function registerAlias(name, alias) {
|
|
2784
|
-
var map = name;
|
|
2785
|
-
var key;
|
|
2786
|
-
|
|
2787
|
-
if (alias) {
|
|
2788
|
-
map = {};
|
|
2789
|
-
map[name] = alias;
|
|
2790
|
-
}
|
|
2791
|
-
|
|
2792
|
-
for (key in map) {
|
|
2793
|
-
core$1.registerAliases(map[key], {languageName: key});
|
|
2794
|
-
}
|
|
2795
|
-
}
|
|
2796
|
-
|
|
2797
|
-
function Emitter(options) {
|
|
2798
|
-
this.options = options;
|
|
2799
|
-
this.rootNode = {children: []};
|
|
2800
|
-
this.stack = [this.rootNode];
|
|
2801
|
-
}
|
|
2802
|
-
|
|
2803
|
-
function addKeyword(value, name) {
|
|
2804
|
-
this.openNode(name);
|
|
2805
|
-
this.addText(value);
|
|
2806
|
-
this.closeNode();
|
|
2807
|
-
}
|
|
2808
|
-
|
|
2809
|
-
function addSublanguage(other, name) {
|
|
2810
|
-
var stack = this.stack;
|
|
2811
|
-
var current = stack[stack.length - 1];
|
|
2812
|
-
var results = other.rootNode.children;
|
|
2813
|
-
var node = name
|
|
2814
|
-
? {
|
|
2815
|
-
type: 'element',
|
|
2816
|
-
tagName: 'span',
|
|
2817
|
-
properties: {className: [name]},
|
|
2818
|
-
children: results
|
|
2819
|
-
}
|
|
2820
|
-
: results;
|
|
2821
|
-
|
|
2822
|
-
current.children = current.children.concat(node);
|
|
2823
|
-
}
|
|
2824
|
-
|
|
2825
|
-
function text(value) {
|
|
2826
|
-
var stack = this.stack;
|
|
2827
|
-
var current;
|
|
2828
|
-
var tail;
|
|
2829
|
-
|
|
2830
|
-
if (value === '') return
|
|
2831
|
-
|
|
2832
|
-
current = stack[stack.length - 1];
|
|
2833
|
-
tail = current.children[current.children.length - 1];
|
|
2834
|
-
|
|
2835
|
-
if (tail && tail.type === 'text') {
|
|
2836
|
-
tail.value += value;
|
|
2837
|
-
} else {
|
|
2838
|
-
current.children.push({type: 'text', value: value});
|
|
2839
|
-
}
|
|
2840
|
-
}
|
|
2841
|
-
|
|
2842
|
-
function open(name) {
|
|
2843
|
-
var stack = this.stack;
|
|
2844
|
-
var className = this.options.classPrefix + name;
|
|
2845
|
-
var current = stack[stack.length - 1];
|
|
2846
|
-
var child = {
|
|
2847
|
-
type: 'element',
|
|
2848
|
-
tagName: 'span',
|
|
2849
|
-
properties: {className: [className]},
|
|
2850
|
-
children: []
|
|
2851
|
-
};
|
|
2852
|
-
|
|
2853
|
-
current.children.push(child);
|
|
2854
|
-
stack.push(child);
|
|
2855
|
-
}
|
|
2856
|
-
|
|
2857
|
-
function close() {
|
|
2858
|
-
this.stack.pop();
|
|
2859
|
-
}
|
|
2860
|
-
|
|
2861
|
-
function toHtmlNoop() {
|
|
2862
|
-
return ''
|
|
2863
|
-
}
|
|
2864
|
-
|
|
2865
|
-
function noop() {}
|
|
2866
|
-
|
|
2867
|
-
var core = {
|
|
2868
|
-
highlight: highlight_1,
|
|
2869
|
-
highlightAuto: highlightAuto_1,
|
|
2870
|
-
registerLanguage: registerLanguage_1,
|
|
2871
|
-
listLanguages: listLanguages_1,
|
|
2872
|
-
registerAlias: registerAlias_1
|
|
2873
|
-
};
|
|
2578
|
+
var HighlightJS = core;
|
|
2874
2579
|
|
|
2875
2580
|
function parseNodes(nodes, className = []) {
|
|
2876
2581
|
return nodes
|
|
@@ -2891,18 +2596,23 @@
|
|
|
2891
2596
|
})
|
|
2892
2597
|
.flat();
|
|
2893
2598
|
}
|
|
2894
|
-
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, }) {
|
|
2895
2607
|
const decorations = [];
|
|
2896
|
-
core$
|
|
2608
|
+
core$1.findChildren(doc, node => node.type.name === name)
|
|
2897
2609
|
.forEach(block => {
|
|
2898
2610
|
let from = block.pos + 1;
|
|
2899
|
-
const
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
? core.highlight(language, block.node.textContent).value
|
|
2905
|
-
: core.highlightAuto(block.node.textContent).value;
|
|
2611
|
+
const language = block.node.attrs.language || defaultLanguage;
|
|
2612
|
+
const languages = lowlight.listLanguages();
|
|
2613
|
+
const nodes = language && (languages.includes(language) || registered(language))
|
|
2614
|
+
? getHighlightNodes(lowlight.highlight(language, block.node.textContent))
|
|
2615
|
+
: getHighlightNodes(lowlight.highlightAuto(block.node.textContent));
|
|
2906
2616
|
parseNodes(nodes).forEach(node => {
|
|
2907
2617
|
const to = from + node.text.length;
|
|
2908
2618
|
if (node.classes.length) {
|
|
@@ -2916,16 +2626,27 @@
|
|
|
2916
2626
|
});
|
|
2917
2627
|
return prosemirrorView.DecorationSet.create(doc, decorations);
|
|
2918
2628
|
}
|
|
2919
|
-
function
|
|
2920
|
-
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({
|
|
2921
2637
|
key: new prosemirrorState.PluginKey('lowlight'),
|
|
2922
2638
|
state: {
|
|
2923
|
-
init: (_, { doc }) => getDecorations({
|
|
2639
|
+
init: (_, { doc }) => getDecorations({
|
|
2640
|
+
doc,
|
|
2641
|
+
name,
|
|
2642
|
+
lowlight,
|
|
2643
|
+
defaultLanguage,
|
|
2644
|
+
}),
|
|
2924
2645
|
apply: (transaction, decorationSet, oldState, newState) => {
|
|
2925
2646
|
const oldNodeName = oldState.selection.$head.parent.type.name;
|
|
2926
2647
|
const newNodeName = newState.selection.$head.parent.type.name;
|
|
2927
|
-
const oldNodes = core$
|
|
2928
|
-
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);
|
|
2929
2650
|
if (transaction.docChanged
|
|
2930
2651
|
// Apply decorations if:
|
|
2931
2652
|
&& (
|
|
@@ -2948,31 +2669,51 @@
|
|
|
2948
2669
|
&& node.pos + node.node.nodeSize <= step.to;
|
|
2949
2670
|
});
|
|
2950
2671
|
}))) {
|
|
2951
|
-
return getDecorations({
|
|
2672
|
+
return getDecorations({
|
|
2673
|
+
doc: transaction.doc,
|
|
2674
|
+
name,
|
|
2675
|
+
lowlight,
|
|
2676
|
+
defaultLanguage,
|
|
2677
|
+
});
|
|
2952
2678
|
}
|
|
2953
2679
|
return decorationSet.map(transaction.mapping, transaction.doc);
|
|
2954
2680
|
},
|
|
2955
2681
|
},
|
|
2956
2682
|
props: {
|
|
2957
2683
|
decorations(state) {
|
|
2958
|
-
return
|
|
2684
|
+
return lowlightPlugin.getState(state);
|
|
2959
2685
|
},
|
|
2960
2686
|
},
|
|
2961
2687
|
});
|
|
2688
|
+
return lowlightPlugin;
|
|
2962
2689
|
}
|
|
2963
2690
|
|
|
2964
|
-
const CodeBlockLowlight = CodeBlock__default[
|
|
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
|
+
};
|
|
2699
|
+
},
|
|
2965
2700
|
addProseMirrorPlugins() {
|
|
2701
|
+
var _a;
|
|
2966
2702
|
return [
|
|
2967
|
-
|
|
2703
|
+
...((_a = this.parent) === null || _a === void 0 ? void 0 : _a.call(this)) || [],
|
|
2704
|
+
LowlightPlugin({
|
|
2705
|
+
name: this.name,
|
|
2706
|
+
lowlight: this.options.lowlight,
|
|
2707
|
+
defaultLanguage: this.options.defaultLanguage,
|
|
2708
|
+
}),
|
|
2968
2709
|
];
|
|
2969
2710
|
},
|
|
2970
2711
|
});
|
|
2971
2712
|
|
|
2972
2713
|
exports.CodeBlockLowlight = CodeBlockLowlight;
|
|
2973
|
-
exports
|
|
2714
|
+
exports["default"] = CodeBlockLowlight;
|
|
2974
2715
|
|
|
2975
2716
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
2976
2717
|
|
|
2977
|
-
}))
|
|
2718
|
+
}));
|
|
2978
2719
|
//# sourceMappingURL=tiptap-extension-code-block-lowlight.umd.js.map
|