securemark 0.244.1 → 0.246.0

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/global.test.d.ts CHANGED
@@ -1,7 +1,11 @@
1
1
  import assert from 'power-assert';
2
2
 
3
- type Assert = typeof assert;
3
+ declare namespace NS {
4
+ export {
5
+ assert,
6
+ }
7
+ }
4
8
 
5
9
  declare global {
6
- const assert: Assert;
10
+ const assert: typeof NS.assert;
7
11
  }
package/index.ts ADDED
@@ -0,0 +1,4 @@
1
+ import 'spica/global';
2
+ export * from './src/parser';
3
+ export * from './src/util';
4
+ export * from './src/renderer';
package/karma.conf.js CHANGED
@@ -1,48 +1,30 @@
1
1
  module.exports = function (config) {
2
2
  config.set({
3
- basePath: '',
3
+ browsers: ['Chrome', 'Firefox'],
4
4
  frameworks: ['mocha'],
5
5
  files: [
6
- { pattern: 'https://cdn.polyfill.io/v3/polyfill.js?flags=gated&features=default', watched: false, served: false, included: true },
7
- { pattern: 'https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js', watched: false, served: false, included: true },
8
- { pattern: 'https://cdnjs.cloudflare.com/ajax/libs/prism/1.22.0/prism.js', watched: false, served: false, included: true },
9
- { pattern: 'https://cdnjs.cloudflare.com/ajax/libs/prism/1.22.0/plugins/autoloader/prism-autoloader.min.js', watched: false, served: false, included: true },
10
- { pattern: 'https://cdnjs.cloudflare.com/ajax/libs/mathjax/3.2.0/es5/tex-chtml.min.js', watched: false, served: false, included: true },
11
- { pattern: 'https://cdnjs.cloudflare.com/ajax/libs/dompurify/2.2.2/purify.js', watched: false, served: false, included: true },
12
- { pattern: 'node_modules/power-assert/build/power-assert.js', watched: true, served: true, included: true },
13
- { pattern: 'dist/*.test.js', watched: true, served: true, included: true }
6
+ { pattern: 'https://cdn.jsdelivr.net/npm/power-assert@1.6.1/build/power-assert.js', watched: false, served: false, included: true, integrity: 'sha256-MuDC5CQFh3oWtiG0YE000HlkK08xAilD2v0ndZR+Kds=' },
7
+ { pattern: 'https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.js', watched: false, served: false, included: true, integrity: 'sha512-2iwCHjuj+PmdCyvb88rMOch0UcKQxVHi/gsAml1fN3eg82IDaO/cdzzeXX4iF2VzIIes7pODE1/G0ts3QBwslA==' },
8
+ { pattern: 'https://cdnjs.cloudflare.com/ajax/libs/benchmark/2.1.4/benchmark.js', watched: false, served: false, included: true, integrity: 'sha512-XnVGk21Ij51MbU8XezQpkwZ1/GA8b5qmoVGIOdJLBYycutjkaeemipzRJP7P6mEJl99OfnweA7M3e4WLfuG7Aw==' },
9
+ { pattern: 'https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.js', watched: false, served: false, included: true, integrity: 'sha512-n/4gHW3atM3QqRcbCn6ewmpxcLAHGaDjpEBu4xZd47N0W2oQ+6q7oc3PXstrJYXcbNU1OHdQ1T7pAP+gi5Yu8g==' },
10
+ { pattern: 'https://cdnjs.cloudflare.com/ajax/libs/prism/1.28.0/prism.min.js', watched: false, served: false, included: true, integrity: 'https://cdnjs.cloudflare.com/ajax/libs/prism/1.22.0/prism.js' },
11
+ { pattern: 'https://cdnjs.cloudflare.com/ajax/libs/prism/1.28.0/plugins/autoloader/prism-autoloader.min.js', watched: false, served: false, included: true, integrity: 'sha512-fTl/qcO1VgvKtOMApX2PdZzkziyr2stM65GYPLGuYMnuMm1z2JLJG6XVU7C/mR+E7xBUqCivykuhlzfqxXBXbg==' },
12
+ { pattern: 'https://cdnjs.cloudflare.com/ajax/libs/mathjax/3.2.0/es5/tex-chtml.min.js', watched: false, served: false, included: true, integrity: 'sha512-93xLZnNMlYI6xaQPf/cSdXoBZ23DThX7VehiGJJXB76HTTalQKPC5CIHuFX8dlQ5yzt6baBQRJ4sDXhzpojRJA==' },
13
+ { pattern: 'https://cdnjs.cloudflare.com/ajax/libs/dompurify/2.3.8/purify.js', watched: false, served: false, included: true, integrity: 'sha512-QaF+0tDlqVmwZaQSc0kImgYmw+Cd66TxA5D9X70I5V9BNSqk6yBTbyqw2VEUsVYV5OTbxw8HD9d45on1wvYv7g==' },
14
+ { pattern: 'dist/**/*.{js,map}', watched: true, served: true, included: true },
14
15
  ],
15
- exclude: [
16
- ],
17
- espowerPreprocessor: {
18
- options: {
19
- emitActualCode: false,
20
- ignoreUpstreamSourceMap: true
21
- }
16
+ reporters: ['dots', 'coverage'],
17
+ preprocessors: {
18
+ 'dist/**/*.js': ['coverage'],
22
19
  },
23
- reporters: ['dots'],
24
- coverageIstanbulReporter: {
25
- reports: ['html', 'lcovonly', 'text-summary'],
20
+ coverageReporter: {
26
21
  dir: 'coverage',
27
- combineBrowserReports: true,
28
- skipFilesWithNoCoverage: false,
29
- verbose: false,
30
- 'report-config': {
31
- html: {
32
- subdir: 'html',
33
- },
34
- },
35
- instrumentation: {
36
- 'default-excludes': false,
37
- },
38
- },
39
- coverageIstanbulInstrumenter: {
40
- esModules: true,
22
+ reporters: [
23
+ { type: 'html', subdir: browser => browser.split(/\s/)[0] },
24
+ { type: 'text-summary', subdir: '.', file: 'summary.txt' },
25
+ ],
41
26
  },
42
- autoWatch: true,
43
- autoWatchBatchDelay: 500,
44
- browserDisconnectTimeout: 30000,
45
- browsers: ['Chrome'],
46
- singleRun: true,
27
+ browserDisconnectTimeout: 60 * 1e3,
28
+ browserNoActivityTimeout: 90 * 1e3,
47
29
  });
48
30
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "securemark",
3
- "version": "0.244.1",
3
+ "version": "0.246.0",
4
4
  "description": "Secure markdown renderer working on browsers for user input data.",
5
5
  "private": false,
6
6
  "homepage": "https://github.com/falsandtru/securemark",
@@ -13,22 +13,20 @@
13
13
  "latex"
14
14
  ],
15
15
  "types": "./index.d.ts",
16
- "main": "./dist/securemark.js",
16
+ "main": "./dist/index.js",
17
17
  "files": [
18
18
  "dist",
19
- "*.d.ts",
19
+ "index.*",
20
20
  "src",
21
21
  "test",
22
+ "*.ts",
22
23
  "*.js",
23
24
  "*.json",
25
+ "*.map",
24
26
  "*.md",
25
27
  "NOTICE",
26
28
  "LICENSE"
27
29
  ],
28
- "browserify-shim": {
29
- "prismjs": "global:Prism",
30
- "dompurify": "global:DOMPurify"
31
- },
32
30
  "devDependencies": {
33
31
  "@types/dompurify": "2.3.3",
34
32
  "@types/jquery": "3.5.14",
@@ -36,41 +34,37 @@
36
34
  "@types/mocha": "9.1.1",
37
35
  "@types/power-assert": "1.5.8",
38
36
  "@types/prismjs": "1.26.0",
39
- "browserify": "^17.0.0",
40
- "browserify-shim": "^3.8.14",
41
- "concurrently": "^7.1.0",
42
- "del": "^6.0.0",
43
- "eslint-plugin-redos": "^4.3.0",
44
- "gulp": "^4.0.2",
45
- "gulp-derequire": "^3.0.0",
46
- "gulp-eslint": "^6.0.0",
47
- "gulp-footer": "^2.1.0",
48
- "gulp-header": "^2.0.9",
49
- "gulp-load-plugins": "^2.0.7",
50
- "gulp-mocha": "^8.0.0",
51
- "gulp-rename": "^2.0.0",
52
- "gulp-unassert": "^2.0.0",
53
- "karma": "^6.3.19",
37
+ "@typescript-eslint/parser": "^5.25.0",
38
+ "babel-loader": "^8.2.5",
39
+ "babel-plugin-unassert": "^3.2.0",
40
+ "concurrently": "^7.2.0",
41
+ "eslint": "^8.15.0",
42
+ "eslint-plugin-redos": "^4.4.0",
43
+ "eslint-webpack-plugin": "^3.1.1",
44
+ "glob": "^8.0.3",
45
+ "karma": "^6.3.20",
54
46
  "karma-chrome-launcher": "^3.1.1",
55
- "karma-coverage-istanbul-instrumenter": "^1.0.4",
56
- "karma-coverage-istanbul-reporter": "^3.0.3",
57
- "karma-espower-preprocessor": "^1.2.0",
47
+ "karma-coverage": "^2.2.0",
58
48
  "karma-firefox-launcher": "^2.1.2",
59
49
  "karma-mocha": "^2.0.1",
60
50
  "mocha": "^10.0.0",
61
- "npm-check-updates": "^12.5.11",
62
- "power-assert": "^1.6.1",
51
+ "npm-check-updates": "^13.0.1",
63
52
  "semver": "^7.3.7",
64
- "spica": "0.0.540",
65
- "tsify": "^5.0.4",
66
- "typed-dom": "0.0.272",
67
- "typed-query-selector": "^2.6.1",
53
+ "spica": "0.0.550",
54
+ "ts-loader": "^9.3.0",
55
+ "typed-dom": "^0.0.292",
68
56
  "typescript": "4.6.4",
69
- "vinyl-buffer": "^1.0.1",
70
- "vinyl-source-stream": "^2.0.0"
57
+ "webpack": "^5.72.1",
58
+ "webpack-cli": "^4.9.2",
59
+ "webpack-merge": "^5.8.0"
71
60
  },
72
61
  "scripts": {
73
- "test": "gulp test"
62
+ "update": "ncu -u && npm i --no-shrinkwrap && bundle update",
63
+ "dev": "concurrently \"webpack --env mode=test -w\" \"karma start --auto-watch --reporters dots\" \"webpack --env mode=dist -w --output-path ./gh-pages/assets/dist\" \"bundle exec jekyll serve -s ./gh-pages -d ./gh-pages/_site --incremental\"",
64
+ "test": "webpack --env mode=test && karma start --single-run --concurrency 1",
65
+ "lint": "webpack --env mode=lint",
66
+ "bench": "webpack --env mode=bench && karma start --single-run --concurrency 1 --reporters dots",
67
+ "dist": "webpack --env mode=dist"
74
68
  },
75
69
  "author": "falsandtru",
76
70
  "license": "UNLICENSED"
@@ -10,20 +10,6 @@ describe('Unit: parser/block/extension/table', () => {
10
10
  it('invalid', () => {
11
11
  assert.deepStrictEqual(inspect(parser('~~~table a\n-\n~~~')), [['<pre class="invalid" translate="no">~~~table a\n-\n~~~</pre>'], '']);
12
12
  assert.deepStrictEqual(inspect(parser(`~~~table\n0${'\n'.repeat(10001)}~~~`), '>'), [['<pre class="invalid" translate="no">'], '']);
13
- assert.deepStrictEqual(
14
- inspect(parser([
15
- '~~~table',
16
- `${[...Array(33)].map((_, i) => `${i + 1}`).join('\n')}`,
17
- '~~~'
18
- ].join('\n'))),
19
- [[`<pre class="invalid" translate="no">~~~table\n${[...Array(33)].map((_, i) => `${i + 1}`).join('\n')}\n~~~</pre>`], '']);
20
- assert.deepStrictEqual(
21
- inspect(parser([
22
- '~~~table',
23
- '::33 1',
24
- '~~~'
25
- ].join('\n'))),
26
- [[`<pre class="invalid" translate="no">~~~table\n::33 1\n~~~</pre>`], '']);
27
13
  });
28
14
 
29
15
  it('data', () => {
@@ -483,8 +469,8 @@ describe('Unit: parser/block/extension/table', () => {
483
469
  assert.deepStrictEqual(
484
470
  inspect(parser([
485
471
  '~~~table',
486
- `-\n# 1\n${[...Array(31)].map((_, i) => `: ${i + 2}`).join('\n')}`,
487
- `-\n#! 1\n${[...Array(31)].map((_, i) => `: ${i + 2}`).join('\n')}`,
472
+ `-\n# 1\n${[...Array(32)].map((_, i) => `: ${i + 2}`).join('\n')}`,
473
+ `-\n#! 1\n${[...Array(32)].map((_, i) => `: ${i + 2}`).join('\n')}`,
488
474
  '~~~'
489
475
  ].join('\n'))),
490
476
  [[html('table', [
@@ -492,52 +478,52 @@ describe('Unit: parser/block/extension/table', () => {
492
478
  html('tbody', [
493
479
  html('tr', [
494
480
  html('th', '1'),
495
- ...[...Array(31)].map((_, i) => html('td', `${i + 2}`)),
481
+ ...[...Array(32)].map((_, i) => html('td', `${i + 2}`)),
496
482
  ]),
497
483
  html('tr', [
498
484
  html('th', { class: 'highlight' }, '1'),
499
- ...[...Array(31)].map((_, i) => html('td', { class: 'highlight', highlight: 'h' }, `${i + 2}`)),
485
+ ...[...Array(32)].map((_, i) => html('td', { class: 'highlight', highlight: 'h' }, `${i + 2}`)),
500
486
  ]),
501
487
  ]),
502
488
  html('tfoot')]).outerHTML], '']);
503
489
  assert.deepStrictEqual(
504
490
  inspect(parser([
505
491
  '~~~table',
506
- `-\n${[...Array(31)].map((_, i) => `: ${i + 1}`).join('\n')}\n# 32`,
507
- `-\n${[...Array(31)].map((_, i) => `: ${i + 1}`).join('\n')}\n#! 32`,
492
+ `-\n${[...Array(32)].map((_, i) => `: ${i + 1}`).join('\n')}\n# 33`,
493
+ `-\n${[...Array(32)].map((_, i) => `: ${i + 1}`).join('\n')}\n#! 33`,
508
494
  '~~~'
509
495
  ].join('\n'))),
510
496
  [[html('table', [
511
497
  html('thead'),
512
498
  html('tbody', [
513
499
  html('tr', [
514
- ...[...Array(31)].map((_, i) => html('td', `${i + 1}`)),
515
- html('th', '32'),
500
+ ...[...Array(32)].map((_, i) => html('td', `${i + 1}`)),
501
+ html('th', '33'),
516
502
  ]),
517
503
  html('tr', [
518
- ...[...Array(31)].map((_, i) => html('td', { class: 'highlight', highlight: 'h' }, `${i + 1}`)),
519
- html('th', { class: 'highlight' }, '32'),
504
+ ...[...Array(32)].map((_, i) => html('td', { class: 'highlight', highlight: 'h' }, `${i + 1}`)),
505
+ html('th', { class: 'highlight' }, '33'),
520
506
  ]),
521
507
  ]),
522
508
  html('tfoot')]).outerHTML], '']);
523
509
  assert.deepStrictEqual(
524
510
  inspect(parser([
525
511
  '~~~table',
526
- `-\n${[...Array(31)].map((_, i) => `# ${i + 1}`).join('\n')}\n#! 32`,
527
- `-\n${[...Array(32)].map((_, i) => `: ${i + 1}`).join('\n')}`,
512
+ `-\n${[...Array(32)].map((_, i) => `# ${i + 1}`).join('\n')}\n#! 33`,
513
+ `-\n${[...Array(33)].map((_, i) => `: ${i + 1}`).join('\n')}`,
528
514
  '~~~'
529
515
  ].join('\n'))),
530
516
  [[html('table', [
531
517
  html('thead', [
532
518
  html('tr', [
533
- ...[...Array(31)].map((_, i) => html('th', `${i + 1}`)),
534
- html('th', { class: 'highlight' }, '32'),
519
+ ...[...Array(32)].map((_, i) => html('th', `${i + 1}`)),
520
+ html('th', { class: 'highlight' }, '33'),
535
521
  ]),
536
522
  ]),
537
523
  html('tbody', [
538
524
  html('tr', [
539
- ...[...Array(31)].map((_, i) => html('td', `${i + 1}`)),
540
- html('td', { class: 'highlight', highlight: 'v' }, '32'),
525
+ ...[...Array(32)].map((_, i) => html('td', `${i + 1}`)),
526
+ html('td', { class: 'highlight', highlight: 'v' }, '33'),
541
527
  ]),
542
528
  ]),
543
529
  html('tfoot')]).outerHTML], '']);
@@ -668,6 +654,15 @@ describe('Unit: parser/block/extension/table', () => {
668
654
  ]).outerHTML], '']);
669
655
  });
670
656
 
657
+ it('type', () => {
658
+ assert.deepStrictEqual(
659
+ inspect(parser('~~~table/invalid\n~~~')),
660
+ [['<pre class="invalid" translate="no">~~~table/invalid\n~~~</pre>'], '']);
661
+ assert.deepStrictEqual(
662
+ inspect(parser('~~~table/grid\n~~~')),
663
+ [[html('table', { 'data-type': 'grid' }).outerHTML], '']);
664
+ });
665
+
671
666
  });
672
667
 
673
668
  });
@@ -1,13 +1,13 @@
1
- import { undefined, Array } from 'spica/global';
1
+ import { undefined, BigInt, Array } from 'spica/global';
2
2
  import { max, min, isArray } from 'spica/alias';
3
3
  import { ExtensionParser } from '../../block';
4
4
  import { Tree, eval } from '../../../combinator/data/parser';
5
- import { union, subsequence, inits, some, block, line, validate, fence, rewrite, creator, open, clear, convert, trim, dup, recover, lazy, fmap } from '../../../combinator';
5
+ import { union, subsequence, inits, some, block, line, validate, fence, rewrite, creator, open, clear, convert, trim, dup, lazy, fmap } from '../../../combinator';
6
6
  import { inline } from '../../inline';
7
7
  import { str, anyline, emptyline, contentline } from '../../source';
8
8
  import { localize } from '../../locale';
9
9
  import { visualize } from '../../util';
10
- import { html, defrag } from 'typed-dom/dom';
10
+ import { html, define, defrag } from 'typed-dom/dom';
11
11
  import { unshift, splice } from 'spica/array';
12
12
 
13
13
  import TableParser = ExtensionParser.TableParser;
@@ -15,7 +15,7 @@ import RowParser = TableParser.RowParser;
15
15
  import AlignParser = TableParser.AlignParser;
16
16
  import CellParser = TableParser.CellParser;
17
17
 
18
- const opener = /^(~{3,})table(?!\S)([^\n]*)(?:$|\n)/;
18
+ const opener = /^(~{3,})table(?:\/(\S+))?(?!\S)([^\n]*)(?:$|\n)/;
19
19
 
20
20
  export const segment: TableParser.SegmentParser = block(validate('~~~',
21
21
  clear(fence(opener, 10000))));
@@ -23,10 +23,10 @@ export const segment: TableParser.SegmentParser = block(validate('~~~',
23
23
  export const segment_: TableParser.SegmentParser = block(validate('~~~',
24
24
  clear(fence(opener, 10000, false))), false);
25
25
 
26
- export const table: TableParser = block(validate('~~~', recover(fmap(
26
+ export const table: TableParser = block(validate('~~~', fmap(
27
27
  fence(opener, 10000),
28
28
  // Bug: Type mismatch between outer and inner.
29
- ([body, overflow, closer, opener, delim, param]: string[], _, context) => {
29
+ ([body, overflow, closer, opener, delim, type, param]: string[], _, context) => {
30
30
  if (!closer || overflow || param.trimStart()) return [html('pre', {
31
31
  class: 'invalid',
32
32
  translate: 'no',
@@ -37,20 +37,21 @@ export const table: TableParser = block(validate('~~~', recover(fmap(
37
37
  overflow ? `Invalid trailing line after the closing delimiter "${delim}"` :
38
38
  'Invalid argument',
39
39
  }, `${opener}${body}${overflow || closer}`)];
40
- return eval(parser(body, context)) ?? [html('table')];
41
- }),
42
- (source, _, reason) =>
43
- reason instanceof Error && reason.message === 'Number of columns must be 32 or less'
44
- ? [[
45
- html('pre', {
46
- class: 'invalid',
47
- translate: 'no',
48
- 'data-invalid-syntax': 'table',
49
- 'data-invalid-type': 'content',
50
- 'data-invalid-message': reason.message,
51
- }, source),
52
- ], '']
53
- : (() => { throw reason; })())));
40
+ switch (type) {
41
+ case 'grid':
42
+ case undefined:
43
+ return (eval(parser(body, context)) ?? [html('table')])
44
+ .map(el => define(el, { 'data-type': type }));
45
+ default:
46
+ return [html('pre', {
47
+ class: 'invalid',
48
+ translate: 'no',
49
+ 'data-invalid-syntax': 'table',
50
+ 'data-invalid-type': 'argument',
51
+ 'data-invalid-message': 'Invalid table type',
52
+ }, `${opener}${body}${closer}`)];
53
+ }
54
+ })));
54
55
 
55
56
  const parser: TableParser = lazy(() => block(localize(fmap(
56
57
  some(union([row])),
@@ -144,7 +145,7 @@ function format(rows: Tree<RowParser>[]): HTMLTableSectionElement[] {
144
145
  const valigns: ('middle' | 'top' | 'bottom' | '')[] = [];
145
146
  let target = thead;
146
147
  let ranges: Record<number, Record<number, HTMLTableCellElement>> = {};
147
- let verticalHighlights = 0;
148
+ let verticalHighlights = 0n;
148
149
  ROW:
149
150
  for (let i = 0; i < rows.length; ++i) {
150
151
  // Copy to make them retryable.
@@ -214,25 +215,25 @@ function format(rows: Tree<RowParser>[]): HTMLTableSectionElement[] {
214
215
  }
215
216
  assert(valigns.length > 0);
216
217
  const row = html('tr');
217
- let heads = 0;
218
- let highlights = 0;
218
+ let heads = 0n;
219
+ let highlights = 0n;
219
220
  let hasDataCell = false;
220
- let lHeadCellIdx: number;
221
- let rHeadCellIdx: number;
222
- for (let j = 0; j < cells.length && cells.length <= 32; ++j) {
221
+ let lHeadCellIdx: bigint;
222
+ let rHeadCellIdx: bigint;
223
+ for (let j = 0, jn = 0n; j < cells.length; jn = BigInt(++j)) {
223
224
  const isVirtual = !!ranges[i]?.[j];
224
225
  const cell = isVirtual
225
226
  ? splice(cells, j, 0, undefined) && ranges[i][j]
226
227
  : cells[j];
227
228
  const isHeadCell = cell.tagName === 'TH';
228
- heads |= +isHeadCell << j;
229
- highlights |= +!!cell.classList.contains('highlight') << j;
229
+ heads |= BigInt(isHeadCell) << jn;
230
+ highlights |= BigInt(cell.classList.contains('highlight')) << jn;
230
231
  hasDataCell ||= !isHeadCell;
231
232
  if (isHeadCell && !hasDataCell) {
232
- lHeadCellIdx = j;
233
+ lHeadCellIdx = jn;
233
234
  }
234
235
  if (isHeadCell && hasDataCell) {
235
- rHeadCellIdx ??= j;
236
+ rHeadCellIdx ??= jn;
236
237
  }
237
238
  const rowSpan = cell.rowSpan;
238
239
  assert(rowSpan > 0);
@@ -247,8 +248,8 @@ function format(rows: Tree<RowParser>[]): HTMLTableSectionElement[] {
247
248
  assert(colSpan > 0);
248
249
  if (colSpan > 1) {
249
250
  splice(cells, j + 1, 0, ...Array(colSpan - 1));
250
- heads |= +`0b${`${heads & 1 << j && 1}`.repeat(colSpan)}` << j;
251
- highlights |= +`0b${`${highlights & 1 << j && 1}`.repeat(colSpan)}` << j;
251
+ heads |= BigInt(+`0b${`${heads & 1n << jn && 1}`.repeat(colSpan)}`) << jn;
252
+ highlights |= BigInt(+`0b${`${highlights & 1n << jn && 1}`.repeat(colSpan)}`) << jn;
252
253
  j += colSpan - 1;
253
254
  }
254
255
  if (target === thead) {
@@ -282,20 +283,19 @@ function format(rows: Tree<RowParser>[]): HTMLTableSectionElement[] {
282
283
  aligns[j] && cell.setAttribute('align', aligns[j]);
283
284
  valigns[j] && cell.setAttribute('valign', valigns[j]);
284
285
  }
285
- if (cells.length > 32) throw new Error('Number of columns must be 32 or less');
286
286
  target.appendChild(row);
287
287
  switch (target) {
288
288
  case thead:
289
289
  verticalHighlights = heads & highlights;
290
290
  continue;
291
291
  case tbody:
292
- lHeadCellIdx ??= -1;
293
- rHeadCellIdx ??= -1;
292
+ lHeadCellIdx ??= -1n;
293
+ rHeadCellIdx ??= -1n;
294
294
  const tHighlights = verticalHighlights;
295
295
  const horizontalHighlights = heads & highlights;
296
- const lHighlight = ~lHeadCellIdx && horizontalHighlights & 1 << lHeadCellIdx;
297
- const rHighlight = ~rHeadCellIdx && horizontalHighlights & 1 << rHeadCellIdx;
298
- for (let i = 0, m = 1; i < cells.length; ++i, m <<= 1) {
296
+ const lHighlight = ~lHeadCellIdx && horizontalHighlights & 1n << lHeadCellIdx;
297
+ const rHighlight = ~rHeadCellIdx && horizontalHighlights & 1n << rHeadCellIdx;
298
+ for (let i = 0, m = 1n; i < cells.length; ++i, m <<= 1n) {
299
299
  const cell = cells[i];
300
300
  if (!cell) continue;
301
301
  if (heads & m) continue;
@@ -34,6 +34,7 @@ describe('Unit: parser/inline/bracket', () => {
34
34
  assert.deepStrictEqual(inspect(parser('(word, word)')), [['(', 'word, word', ')'], '']);
35
35
  assert.deepStrictEqual(inspect(parser('(A)')), [['(', 'A', ')'], '']);
36
36
  assert.deepStrictEqual(inspect(parser('(Name)')), [['(', 'Name', ')'], '']);
37
+ assert.deepStrictEqual(inspect(parser('(Word word)')), [['<span class="paren">(Word word)</span>'], '']);
37
38
  assert.deepStrictEqual(inspect(parser('(Word Word)')), [['<span class="paren">(Word Word)</span>'], '']);
38
39
  assert.deepStrictEqual(inspect(parser('(Name, Name)')), [['(', 'Name, Name', ')'], '']);
39
40
  assert.deepStrictEqual(inspect(parser('(ABBR)')), [['(', 'ABBR', ')'], '']);
@@ -43,6 +44,8 @@ describe('Unit: parser/inline/bracket', () => {
43
44
  assert.deepStrictEqual(inspect(parser('(0.1)')), [['(', '0.1', ')'], '']);
44
45
  assert.deepStrictEqual(inspect(parser('(a)')), [['(', 'a', ')'], '']);
45
46
  assert.deepStrictEqual(inspect(parser('(A)')), [['(', 'A', ')'], '']);
47
+ assert.deepStrictEqual(inspect(parser('(A,B)')), [['(', 'A,B', ')'], '']);
48
+ assert.deepStrictEqual(inspect(parser('(A、B)')), [['(', 'A、B', ')'], '']);
46
49
  });
47
50
 
48
51
  it('[', () => {
@@ -13,7 +13,7 @@ export const bracket: BracketParser = lazy(() => creator(union([
13
13
  surround(str('('), some(inline, ')'), str(')'), true,
14
14
  ([as, bs = [], cs], rest) => [[html('span', { class: 'paren' }, defrag(push(unshift(as, bs), cs)))], rest],
15
15
  ([as, bs = []], rest) => [unshift(as, bs), rest]),
16
- surround(str('('), str(new RegExp(index.source.replace(/[09AZaz., ]|\-(?!\w)/g, c => c.trimStart() && String.fromCharCode(c.charCodeAt(0) + 0xFEE0)))), str(')')),
16
+ surround(str('('), str(new RegExp(index.source.replace(', ', '[,、]').replace(/[09AZaz.]|\-(?!\w)/g, c => c.trimStart() && String.fromCharCode(c.charCodeAt(0) + 0xFEE0)))), str(')')),
17
17
  surround(str('('), some(inline, ')'), str(')'), true,
18
18
  ([as, bs = [], cs], rest) => [[html('span', { class: 'paren' }, defrag(push(unshift(as, bs), cs)))], rest],
19
19
  ([as, bs = []], rest) => [unshift(as, bs), rest]),
@@ -1,4 +1,4 @@
1
- import * as Prism from 'prismjs';
1
+ import Prism from 'prismjs';
2
2
  import { Collection } from 'spica/collection';
3
3
 
4
4
  export function code(target: HTMLElement, cache?: Collection<string, HTMLElement>): void {
@@ -1,7 +1,7 @@
1
1
  import { window, document } from 'spica/global';
2
2
  import { parse } from '../../../parser';
3
3
  import { html as h, define } from 'typed-dom/dom';
4
- import { sanitize } from 'dompurify';
4
+ import DOMPurify from 'dompurify';
5
5
 
6
6
  declare global {
7
7
  interface Window {
@@ -29,7 +29,7 @@ export function twitter(source: HTMLImageElement, url: URL): HTMLElement | undef
29
29
  timeout: 10 * 1e3,
30
30
  cache: true,
31
31
  success({ html }): void {
32
- el.innerHTML = sanitize(html);
32
+ el.innerHTML = DOMPurify.sanitize(html);
33
33
  if (window.twttr) return void window.twttr.widgets.load(el);
34
34
  const id = 'twitter-wjs';
35
35
  if (document.getElementById(id)) return;
package/tsconfig.json CHANGED
@@ -1,15 +1,16 @@
1
1
  {
2
2
  "compilerOptions": {
3
- "target": "ES2019",
3
+ "target": "ES2021",
4
4
  "lib": [
5
- "ES2019",
6
- "ES2021.Promise",
5
+ "ES2021",
7
6
  "DOM",
8
7
  "DOM.Iterable"
9
8
  ],
9
+ "outDir": "dist",
10
10
  "module": "commonjs",
11
11
  "moduleResolution": "node",
12
12
  "esModuleInterop": true,
13
+ "sourceMap": true,
13
14
  "strict": true,
14
15
  "strictFunctionTypes": false,
15
16
  "noUnusedParameters": true,
@@ -19,13 +20,15 @@
19
20
  "suppressImplicitAnyIndexErrors": true,
20
21
  "noFallthroughCasesInSwitch": true,
21
22
  "noErrorTruncation": true,
22
- "rootDir": "./",
23
- "forceConsistentCasingInFileNames": true,
24
- "removeComments": false
23
+ "forceConsistentCasingInFileNames": true
25
24
  },
26
25
  "include": [
27
26
  "*.ts",
28
27
  "src/**/*.ts",
29
- "test/**/*.ts"
28
+ "test/**/*.ts",
29
+ "benchmark/**/*.ts"
30
+ ],
31
+ "exclude": [
32
+ "node_modules"
30
33
  ]
31
34
  }