@bhsd/codemirror-mediawiki 2.1.9 → 2.1.10

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/mw/dist/base.js CHANGED
@@ -1,7 +1,7 @@
1
- import { CodeMirror6 } from 'https://testingcf.jsdelivr.net/npm/@bhsd/codemirror-mediawiki@2.1.9/dist/main.min.js';
1
+ import { CodeMirror6 } from 'https://testingcf.jsdelivr.net/npm/@bhsd/codemirror-mediawiki@2.1.10/dist/main.min.js';
2
2
  (() => {
3
3
  var _a;
4
- mw.loader.load('https://testingcf.jsdelivr.net/npm/@bhsd/codemirror-mediawiki@2.1.9/mediawiki.min.css', 'text/css');
4
+ mw.loader.load('https://testingcf.jsdelivr.net/npm/@bhsd/codemirror-mediawiki@2.1.10/mediawiki.min.css', 'text/css');
5
5
  mw.loader.addStyleTag('.wikiEditor-ui-toolbar{z-index:7}');
6
6
  const instances = new WeakMap();
7
7
  const getInstance = ($ele) => instances.get($ele[0]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bhsd/codemirror-mediawiki",
3
- "version": "2.1.9",
3
+ "version": "2.1.10",
4
4
  "description": "Modified CodeMirror mode based on wikimedia/mediawiki-extensions-CodeMirror",
5
5
  "keywords": [
6
6
  "mediawiki",
@@ -28,14 +28,14 @@
28
28
  "url": "git+https://github.com/bhsd-harry/codemirror-mediawiki.git"
29
29
  },
30
30
  "scripts": {
31
- "build:core": "esbuild ./src/codemirror.ts --bundle --minify --target=es2018 --format=esm --sourcemap --outfile=dist/main.min.js; tsc --emitDeclarationOnly; rm dist/gh-page.d.ts",
31
+ "build:core": "esbuild ./src/codemirror.ts --bundle --minify --target=es2018 --format=esm --sourcemap --outfile=dist/main.min.js && tsc --emitDeclarationOnly && rm dist/gh-page.d.ts",
32
32
  "build:mw": "bash build.sh mw/base.ts mw/dist/base.js",
33
33
  "build:gh-page": "bash build.sh src/gh-page.ts gh-page.js",
34
34
  "build": "npm run build:core && npm run build:mw",
35
35
  "lint:ts": "tsc --noEmit && tsc --project mw/tsconfig.json --noEmit && eslint --cache .",
36
36
  "lint:css": "stylelint *.css",
37
37
  "lint": "npm run lint:ts && npm run lint:css",
38
- "test": "http-server .. -c-1 --cors &",
38
+ "test": "npm run build:core && npm run build:gh-page && http-server .. -c-1 --cors &",
39
39
  "test:end": "pkill -x http-server"
40
40
  },
41
41
  "engines": {
package/src/mediawiki.ts CHANGED
@@ -48,6 +48,12 @@ export interface MwConfig {
48
48
  implicitlyClosedHtmlTags?: string[];
49
49
  }
50
50
 
51
+ const enum TableCell {
52
+ Td,
53
+ Th,
54
+ Caption,
55
+ }
56
+
51
57
  const copyState = (state: State): State => {
52
58
  const newState = {} as State;
53
59
  for (const [key, val] of Object.entries(state)) {
@@ -85,7 +91,7 @@ class MediaWiki {
85
91
  constructor(config: MwConfig) {
86
92
  this.config = config;
87
93
  // eslint-disable-next-line require-unicode-regexp
88
- this.urlProtocols = new RegExp(`^(?:${config.urlProtocols})`, 'i');
94
+ this.urlProtocols = new RegExp(`^(?:${config.urlProtocols})(?=[^\\s[\\]<>])`, 'i');
89
95
  this.isBold = false;
90
96
  this.wasBold = false;
91
97
  this.isItalic = false;
@@ -235,7 +241,7 @@ class MediaWiki {
235
241
  return (ground && `mw${ground}-ground `) + style;
236
242
  }
237
243
 
238
- inBlock(style: string, terminator: string, consumeLast = true): Tokenizer {
244
+ inBlock(style: string, terminator: string, consumeLast?: boolean): Tokenizer {
239
245
  return (stream, state) => {
240
246
  if (stream.skipTo(terminator)) {
241
247
  if (consumeLast) {
@@ -278,7 +284,7 @@ class MediaWiki {
278
284
  } else if (stream.match(/^<!--(?!.*?-->.*?=)/u, false)) {
279
285
  // T171074: handle trailing comments
280
286
  stream.backUp(count);
281
- state.tokenize = this.inBlock(modeConfig.tags.sectionHeader, '<!--', false);
287
+ state.tokenize = this.inBlock(modeConfig.tags.sectionHeader, '<!--');
282
288
  }
283
289
  return this.makeLocalStyle(modeConfig.tags.section, state);
284
290
  }
@@ -303,7 +309,7 @@ class MediaWiki {
303
309
  return this.makeLocalStyle(modeConfig.tags.templateVariableName, state);
304
310
  }
305
311
 
306
- inVariableDefault(isFirst: boolean): Tokenizer {
312
+ inVariableDefault(isFirst?: boolean): Tokenizer {
307
313
  const style = modeConfig.tags[isFirst ? 'templateVariable' : 'comment'];
308
314
  return (stream, state) => {
309
315
  if (stream.match(/^[^{}[<&~|]+/u)) {
@@ -312,7 +318,7 @@ class MediaWiki {
312
318
  state.tokenize = state.stack.pop()!;
313
319
  return this.makeLocalStyle(modeConfig.tags.templateVariableBracket, state);
314
320
  } else if (stream.eat('|')) {
315
- state.tokenize = this.inVariableDefault(false);
321
+ state.tokenize = this.inVariableDefault();
316
322
  return this.makeLocalStyle(modeConfig.tags.templateVariableDelimiter, state);
317
323
  }
318
324
  return this.eatWikiText(style)(stream, state);
@@ -345,7 +351,7 @@ class MediaWiki {
345
351
  return this.eatWikiText(modeConfig.tags.parserFunction)(stream, state);
346
352
  }
347
353
 
348
- inTemplatePageName(haveAte: boolean): Tokenizer {
354
+ inTemplatePageName(haveAte?: boolean): Tokenizer {
349
355
  return (stream, state) => {
350
356
  if (stream.match(/^\s*\|\s*/u)) {
351
357
  state.tokenize = this.inTemplateArgument(true);
@@ -372,11 +378,11 @@ class MediaWiki {
372
378
  };
373
379
  }
374
380
 
375
- inTemplateArgument(expectArgName: boolean): Tokenizer {
381
+ inTemplateArgument(expectArgName?: boolean): Tokenizer {
376
382
  return (stream, state) => {
377
383
  if (expectArgName && stream.eatWhile(/[^=|}{[<&~]/u)) {
378
384
  if (stream.eat('=')) {
379
- state.tokenize = this.inTemplateArgument(false);
385
+ state.tokenize = this.inTemplateArgument();
380
386
  return this.makeLocalStyle(modeConfig.tags.templateArgumentName, state);
381
387
  }
382
388
  return this.makeLocalStyle(modeConfig.tags.template, state);
@@ -531,7 +537,7 @@ class MediaWiki {
531
537
  };
532
538
  }
533
539
 
534
- eatTagName(chars: number, isCloseTag: boolean, isHtmlTag: boolean): Tokenizer {
540
+ eatTagName(chars: number, isCloseTag: boolean, isHtmlTag?: boolean): Tokenizer {
535
541
  return (stream, state) => {
536
542
  let name = '';
537
543
  for (let i = 0; i < chars; i++) {
@@ -642,7 +648,7 @@ class MediaWiki {
642
648
  return (stream, state) => {
643
649
  stream.next(); // eat <
644
650
  stream.next(); // eat /
645
- state.tokenize = this.eatTagName(name.length, true, false);
651
+ state.tokenize = this.eatTagName(name.length, true);
646
652
  return this.makeLocalStyle(modeConfig.tags.extTagBracket, state);
647
653
  };
648
654
  }
@@ -680,17 +686,6 @@ class MediaWiki {
680
686
  return this.eatWikiText(modeConfig.tags.tableDefinition)(stream, state);
681
687
  }
682
688
 
683
- inTableCaption(stream: StringStream, state: State): string {
684
- if (stream.sol() && stream.match(/^\s*(?:[|!]|\{\{\s*!\s*\}\})/u, false)) {
685
- state.tokenize = this.inTable.bind(this);
686
- return this.inTable(stream, state);
687
- } else if (stream.match(/^\s*(?:\||\{\{\s*!\s*\}\}){2}/u, false)) {
688
- state.tokenize = this.inTableRow(false, false);
689
- return '';
690
- }
691
- return this.eatWikiText(modeConfig.tags.tableCaption)(stream, state);
692
- }
693
-
694
689
  inTable(stream: StringStream, state: State): string {
695
690
  if (stream.sol()) {
696
691
  stream.eatSpace();
@@ -700,25 +695,31 @@ class MediaWiki {
700
695
  return this.makeLocalStyle(modeConfig.tags.tableDelimiter, state);
701
696
  } else if (stream.eat('+')) {
702
697
  stream.eatSpace();
703
- state.tokenize = this.inTableCaption.bind(this);
698
+ state.tokenize = this.inTableRow(true, TableCell.Caption);
704
699
  return this.makeLocalStyle(modeConfig.tags.tableDelimiter, state);
705
700
  } else if (stream.eat('}')) {
706
701
  state.tokenize = state.stack.pop()!;
707
702
  return this.makeLocalStyle(modeConfig.tags.tableBracket, state);
708
703
  }
709
704
  stream.eatSpace();
710
- state.tokenize = this.inTableRow(true, false);
705
+ state.tokenize = this.inTableRow(true, TableCell.Td);
711
706
  return this.makeLocalStyle(modeConfig.tags.tableDelimiter, state);
712
707
  } else if (stream.eat('!')) {
713
708
  stream.eatSpace();
714
- state.tokenize = this.inTableRow(true, true);
709
+ state.tokenize = this.inTableRow(true, TableCell.Th);
715
710
  return this.makeLocalStyle(modeConfig.tags.tableDelimiter, state);
716
711
  }
717
712
  }
718
713
  return this.eatWikiText('')(stream, state);
719
714
  }
720
715
 
721
- inTableRow(isStart: boolean, isHead: boolean): Tokenizer {
716
+ inTableRow(isStart: boolean, type: TableCell): Tokenizer {
717
+ let style = '';
718
+ if (type === TableCell.Caption) {
719
+ style = modeConfig.tags.tableCaption;
720
+ } else if (type === TableCell.Th) {
721
+ style = modeConfig.tags.strong;
722
+ }
722
723
  return (stream, state) => {
723
724
  if (stream.sol()) {
724
725
  if (stream.match(/^\s*(?:[|!]|\{\{\s*!\s*\}\})/u, false)) {
@@ -726,19 +727,17 @@ class MediaWiki {
726
727
  return this.inTable(stream, state);
727
728
  }
728
729
  } else if (stream.match(/^[^'|{[<&~!]+/u)) {
729
- return this.makeStyle(isHead ? modeConfig.tags.strong : '', state);
730
- } else if (
731
- stream.match(/^(?:\||\{\{\s*!\s*\}\}){2}/u) || isHead && stream.match('!!')
732
- || isStart && stream.match(/^(?:\||\{\{\s*!\s*\}\})/u)
733
- ) {
730
+ return this.makeStyle(style, state);
731
+ } else if (stream.match(/^(?:\||\{\{\s*!\s*\}\}){2}/u) || type === TableCell.Th && stream.match('!!')) {
734
732
  this.isBold = false;
735
733
  this.isItalic = false;
736
- if (isStart) {
737
- state.tokenize = this.inTableRow(false, isHead);
738
- }
734
+ state.tokenize = this.inTableRow(true, type);
735
+ return this.makeLocalStyle(modeConfig.tags.tableDelimiter, state);
736
+ } else if (isStart && stream.match(/^(?:\||\{\{\s*!\s*\}\})/u)) {
737
+ state.tokenize = this.inTableRow(false, type);
739
738
  return this.makeLocalStyle(modeConfig.tags.tableDelimiter, state);
740
739
  }
741
- return this.eatWikiText(isHead ? modeConfig.tags.strong : '')(stream, state);
740
+ return this.eatWikiText(style)(stream, state);
742
741
  };
743
742
  }
744
743
 
@@ -938,14 +937,14 @@ class MediaWiki {
938
937
  // Template
939
938
  state.nTemplate++;
940
939
  state.stack.push(state.tokenize);
941
- state.tokenize = this.inTemplatePageName(false);
940
+ state.tokenize = this.inTemplatePageName();
942
941
  return this.makeLocalStyle(modeConfig.tags.templateBracket, state);
943
942
  }
944
943
  break;
945
944
  case '<': {
946
945
  if (stream.match('!--')) { // comment
947
946
  state.stack.push(state.tokenize);
948
- state.tokenize = this.inBlock(modeConfig.tags.comment, '-->');
947
+ state.tokenize = this.inBlock(modeConfig.tags.comment, '-->', true);
949
948
  return this.makeLocalStyle(modeConfig.tags.comment, state);
950
949
  }
951
950
  const isCloseTag = Boolean(stream.eat('/')),
@@ -954,17 +953,18 @@ class MediaWiki {
954
953
  const tagname = mt[0]!.toLowerCase();
955
954
  if (tagname in this.config.tags) {
956
955
  // Parser function
956
+ state.stack.push(state.tokenize);
957
957
  if (isCloseTag) {
958
958
  state.tokenize = this.inChar('>', modeConfig.tags.error);
959
959
  return this.makeLocalStyle(modeConfig.tags.error, state);
960
960
  }
961
961
  stream.backUp(tagname.length);
962
- state.stack.push(state.tokenize);
963
- state.tokenize = this.eatTagName(tagname.length, isCloseTag, false);
962
+ state.tokenize = this.eatTagName(tagname.length, isCloseTag);
964
963
  return this.makeLocalStyle(modeConfig.tags.extTagBracket, state);
965
964
  } else if (this.permittedHtmlTags.has(tagname)) {
966
965
  // Html tag
967
966
  if (isCloseTag && tagname !== state.inHtmlTag.pop()) {
967
+ state.stack.push(state.tokenize);
968
968
  state.tokenize = this.inChar('>', modeConfig.tags.error);
969
969
  return this.makeLocalStyle(modeConfig.tags.error, state);
970
970
  } else if (isCloseTag && this.implicitlyClosedHtmlTags.has(tagname)) {