securemark 0.244.0 → 0.245.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.0",
3
+ "version": "0.245.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
- "mocha": "^9.2.2",
61
- "npm-check-updates": "^12.5.9",
62
- "power-assert": "^1.6.1",
50
+ "mocha": "^10.0.0",
51
+ "npm-check-updates": "^13.0.1",
63
52
  "semver": "^7.3.7",
64
- "spica": "0.0.524",
65
- "tsify": "^5.0.4",
66
- "typed-dom": "0.0.267",
67
- "typed-query-selector": "^2.6.1",
68
- "typescript": "4.6.3",
69
- "vinyl-buffer": "^1.0.1",
70
- "vinyl-source-stream": "^2.0.0"
53
+ "spica": "0.0.550",
54
+ "ts-loader": "^9.3.0",
55
+ "typed-dom": "^0.0.292",
56
+ "typescript": "4.6.4",
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"
@@ -17,6 +17,7 @@ describe('Unit: parser/block/extension/figure', () => {
17
17
  assert.deepStrictEqual(inspect(parser('~~~figure [$group-name]\n!https://host\n\n\n\n~~~')), [['<pre class="invalid" translate="no">~~~figure [$group-name]\n!https://host\n\n\n\n~~~</pre>'], '']);
18
18
  assert.deepStrictEqual(inspect(parser('~~~figure [$group-name]\n !https://host\n~~~')), [['<pre class="invalid" translate="no">~~~figure [$group-name]\n !https://host\n~~~</pre>'], '']);
19
19
  assert.deepStrictEqual(inspect(parser('~~~figure [$group-name]\n!https://host\n~~~\n~~~')), [['<pre class="invalid" translate="no">~~~figure [$group-name]\n!https://host\n~~~\n~~~</pre>'], '']);
20
+ assert.deepStrictEqual(inspect(parser('~~~figure [$group-name]\n!https://host\n\ncaption\n~~~\n~~~')), [['<pre class="invalid" translate="no">~~~figure [$group-name]\n!https://host\n\ncaption\n~~~\n~~~</pre>'], '']);
20
21
  assert.deepStrictEqual(inspect(parser('~~~figure [$group-name]\n!https://host\n~~~~')), [['<pre class="invalid" translate="no">~~~figure [$group-name]\n!https://host\n~~~~</pre>'], '']);
21
22
  assert.deepStrictEqual(inspect(parser('~~~~figure [$group-name]\n!https://host\n~~~')), [['<pre class="invalid" translate="no">~~~~figure [$group-name]\n!https://host\n~~~</pre>'], '']);
22
23
  assert.deepStrictEqual(inspect(parser('~~~figure [$group-name]a\nhttps://host\n~~~')), [['<pre class="invalid" translate="no">~~~figure [$group-name]a\nhttps://host\n~~~</pre>'], '']);
@@ -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], '']);
@@ -1,8 +1,8 @@
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';
@@ -23,7 +23,7 @@ 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
29
  ([body, overflow, closer, opener, delim, param]: string[], _, context) => {
@@ -38,19 +38,7 @@ export const table: TableParser = block(validate('~~~', recover(fmap(
38
38
  'Invalid argument',
39
39
  }, `${opener}${body}${overflow || closer}`)];
40
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; })())));
41
+ })));
54
42
 
55
43
  const parser: TableParser = lazy(() => block(localize(fmap(
56
44
  some(union([row])),
@@ -144,7 +132,7 @@ function format(rows: Tree<RowParser>[]): HTMLTableSectionElement[] {
144
132
  const valigns: ('middle' | 'top' | 'bottom' | '')[] = [];
145
133
  let target = thead;
146
134
  let ranges: Record<number, Record<number, HTMLTableCellElement>> = {};
147
- let verticalHighlights = 0;
135
+ let verticalHighlights = 0n;
148
136
  ROW:
149
137
  for (let i = 0; i < rows.length; ++i) {
150
138
  // Copy to make them retryable.
@@ -214,25 +202,25 @@ function format(rows: Tree<RowParser>[]): HTMLTableSectionElement[] {
214
202
  }
215
203
  assert(valigns.length > 0);
216
204
  const row = html('tr');
217
- let heads = 0;
218
- let highlights = 0;
205
+ let heads = 0n;
206
+ let highlights = 0n;
219
207
  let hasDataCell = false;
220
- let lHeadCellIdx: number;
221
- let rHeadCellIdx: number;
222
- for (let j = 0; j < cells.length && cells.length <= 32; ++j) {
208
+ let lHeadCellIdx: bigint;
209
+ let rHeadCellIdx: bigint;
210
+ for (let j = 0, jn = 0n; j < cells.length; jn = BigInt(++j)) {
223
211
  const isVirtual = !!ranges[i]?.[j];
224
212
  const cell = isVirtual
225
213
  ? splice(cells, j, 0, undefined) && ranges[i][j]
226
214
  : cells[j];
227
215
  const isHeadCell = cell.tagName === 'TH';
228
- heads |= +isHeadCell << j;
229
- highlights |= +!!cell.classList.contains('highlight') << j;
216
+ heads |= BigInt(isHeadCell) << jn;
217
+ highlights |= BigInt(cell.classList.contains('highlight')) << jn;
230
218
  hasDataCell ||= !isHeadCell;
231
219
  if (isHeadCell && !hasDataCell) {
232
- lHeadCellIdx = j;
220
+ lHeadCellIdx = jn;
233
221
  }
234
222
  if (isHeadCell && hasDataCell) {
235
- rHeadCellIdx ??= j;
223
+ rHeadCellIdx ??= jn;
236
224
  }
237
225
  const rowSpan = cell.rowSpan;
238
226
  assert(rowSpan > 0);
@@ -247,8 +235,8 @@ function format(rows: Tree<RowParser>[]): HTMLTableSectionElement[] {
247
235
  assert(colSpan > 0);
248
236
  if (colSpan > 1) {
249
237
  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;
238
+ heads |= BigInt(+`0b${`${heads & 1n << jn && 1}`.repeat(colSpan)}`) << jn;
239
+ highlights |= BigInt(+`0b${`${highlights & 1n << jn && 1}`.repeat(colSpan)}`) << jn;
252
240
  j += colSpan - 1;
253
241
  }
254
242
  if (target === thead) {
@@ -282,20 +270,19 @@ function format(rows: Tree<RowParser>[]): HTMLTableSectionElement[] {
282
270
  aligns[j] && cell.setAttribute('align', aligns[j]);
283
271
  valigns[j] && cell.setAttribute('valign', valigns[j]);
284
272
  }
285
- if (cells.length > 32) throw new Error('Number of columns must be 32 or less');
286
273
  target.appendChild(row);
287
274
  switch (target) {
288
275
  case thead:
289
276
  verticalHighlights = heads & highlights;
290
277
  continue;
291
278
  case tbody:
292
- lHeadCellIdx ??= -1;
293
- rHeadCellIdx ??= -1;
279
+ lHeadCellIdx ??= -1n;
280
+ rHeadCellIdx ??= -1n;
294
281
  const tHighlights = verticalHighlights;
295
282
  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) {
283
+ const lHighlight = ~lHeadCellIdx && horizontalHighlights & 1n << lHeadCellIdx;
284
+ const rHighlight = ~rHeadCellIdx && horizontalHighlights & 1n << rHeadCellIdx;
285
+ for (let i = 0, m = 1n; i < cells.length; ++i, m <<= 1n) {
299
286
  const cell = cells[i];
300
287
  if (!cell) continue;
301
288
  if (heads & m) continue;
@@ -21,6 +21,7 @@ describe('Unit: parser/header', () => {
21
21
  assert.deepStrictEqual(inspect(parser('---\n \n---')), undefined);
22
22
  assert.deepStrictEqual(inspect(parser('---\n-\n---')), [['<pre class="invalid" translate="no">---\n-\n---</pre>'], '']);
23
23
  assert.deepStrictEqual(inspect(parser('----\na: b\n----')), [['<pre class="invalid" translate="no">----\na: b\n----</pre>'], '']);
24
+ assert.deepStrictEqual(inspect(parser(`---\n${'a: b\n'.repeat(101)}---`)), [[`<pre class="invalid" translate="no">---\n${'a: b\n'.repeat(101)}---</pre>`], '']);
24
25
  });
25
26
 
26
27
  it('basic', () => {
@@ -16,17 +16,36 @@ describe('Unit: parser/inline/bracket', () => {
16
16
  assert.deepStrictEqual(inspect(parser('(1)')), [['(', '1', ')'], '']);
17
17
  assert.deepStrictEqual(inspect(parser('(10)')), [['(', '10', ')'], '']);
18
18
  assert.deepStrictEqual(inspect(parser('(2000)')), [['(', '2000', ')'], '']);
19
- assert.deepStrictEqual(inspect(parser('(1, 2)')), [['(', '1, 2', ')'], '']);
20
19
  assert.deepStrictEqual(inspect(parser('(0-1)')), [['(', '0-1', ')'], '']);
21
20
  assert.deepStrictEqual(inspect(parser('(0)-1')), [['(', '0', ')'], '-1']);
22
21
  assert.deepStrictEqual(inspect(parser('(0.1)')), [['(', '0.1', ')'], '']);
23
22
  assert.deepStrictEqual(inspect(parser('(0.1.2)')), [['(', '0.1.2', ')'], '']);
24
23
  assert.deepStrictEqual(inspect(parser('(1.1, 1.2-1.3, 1.4)')), [['(', '1.1, 1.2-1.3, 1.4', ')'], '']);
24
+ assert.deepStrictEqual(inspect(parser('(1 2)')), [['<span class="paren">(1 2)</span>'], '']);
25
+ assert.deepStrictEqual(inspect(parser('(1, 2)')), [['(', '1, 2', ')'], '']);
26
+ assert.deepStrictEqual(inspect(parser('(1a)')), [['(', '1a', ')'], '']);
25
27
  assert.deepStrictEqual(inspect(parser('(a)')), [['(', 'a', ')'], '']);
28
+ assert.deepStrictEqual(inspect(parser('(a1)')), [['(', 'a1', ')'], '']);
29
+ assert.deepStrictEqual(inspect(parser('(a-1)')), [['(', 'a-1', ')'], '']);
30
+ assert.deepStrictEqual(inspect(parser('(a.1)')), [['(', 'a.1', ')'], '']);
31
+ assert.deepStrictEqual(inspect(parser('(a b)')), [['<span class="paren">(a b)</span>'], '']);
32
+ assert.deepStrictEqual(inspect(parser('(word)')), [['(', 'word', ')'], '']);
33
+ assert.deepStrictEqual(inspect(parser('(word word)')), [['<span class="paren">(word word)</span>'], '']);
34
+ assert.deepStrictEqual(inspect(parser('(word, word)')), [['(', 'word, word', ')'], '']);
26
35
  assert.deepStrictEqual(inspect(parser('(A)')), [['(', 'A', ')'], '']);
36
+ assert.deepStrictEqual(inspect(parser('(Name)')), [['(', 'Name', ')'], '']);
37
+ assert.deepStrictEqual(inspect(parser('(Word word)')), [['<span class="paren">(Word word)</span>'], '']);
38
+ assert.deepStrictEqual(inspect(parser('(Word Word)')), [['<span class="paren">(Word Word)</span>'], '']);
39
+ assert.deepStrictEqual(inspect(parser('(Name, Name)')), [['(', 'Name, Name', ')'], '']);
40
+ assert.deepStrictEqual(inspect(parser('(ABBR)')), [['(', 'ABBR', ')'], '']);
41
+ assert.deepStrictEqual(inspect(parser('(ABBR, ABBR)')), [['(', 'ABBR, ABBR', ')'], '']);
27
42
  assert.deepStrictEqual(inspect(parser('(1,2)')), [['(', '1,2', ')'], '']);
28
43
  assert.deepStrictEqual(inspect(parser('(0-1)')), [['(', '0-1', ')'], '']);
29
- assert.deepStrictEqual(inspect(parser('(0.1)(A)')), [['(', '0.1', ')', '(', 'A', ')'], '']);
44
+ assert.deepStrictEqual(inspect(parser('(0.1)')), [['(', '0.1', ')'], '']);
45
+ assert.deepStrictEqual(inspect(parser('(a)')), [['(', 'a', ')'], '']);
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', ')'], '']);
30
49
  });
31
50
 
32
51
  it('[', () => {
@@ -6,14 +6,14 @@ import { str } from '../source';
6
6
  import { html, defrag } from 'typed-dom/dom';
7
7
  import { unshift, push } from 'spica/array';
8
8
 
9
- const index = /^(?:[0-9]+(?:(?:[.-]|, )[0-9]+)*|[A-Za-z])/;
9
+ const index = /^[0-9A-Za-z]+(?:(?:[.-]|, )[0-9A-Za-z]+)*/;
10
10
 
11
11
  export const bracket: BracketParser = lazy(() => creator(union([
12
12
  surround(str('('), str(index), str(')')),
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
  }