@tiptap/extension-code-block-lowlight 2.0.0-beta.9 → 2.0.0-rc.2

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