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/.eslintrc.json +26 -0
- package/CHANGELOG.md +12 -0
- package/design.md +1 -0
- package/dist/index.js +9292 -0
- package/global.test.d.ts +6 -2
- package/index.ts +4 -0
- package/karma.conf.js +20 -38
- package/package.json +30 -36
- package/src/parser/block/extension/figure.test.ts +1 -0
- package/src/parser/block/extension/table.test.ts +16 -30
- package/src/parser/block/extension/table.ts +21 -34
- package/src/parser/header.test.ts +1 -0
- package/src/parser/inline/bracket.test.ts +21 -2
- package/src/parser/inline/bracket.ts +2 -2
- package/src/renderer/render/code.ts +1 -1
- package/src/renderer/render/media/twitter.ts +2 -2
- package/tsconfig.json +10 -7
- package/webpack.config.js +129 -0
- package/dist/securemark.js +0 -8562
- package/gulpfile.js +0 -208
- package/package-lock.json +0 -11851
package/global.test.d.ts
CHANGED
package/index.ts
ADDED
package/karma.conf.js
CHANGED
|
@@ -1,48 +1,30 @@
|
|
|
1
1
|
module.exports = function (config) {
|
|
2
2
|
config.set({
|
|
3
|
-
|
|
3
|
+
browsers: ['Chrome', 'Firefox'],
|
|
4
4
|
frameworks: ['mocha'],
|
|
5
5
|
files: [
|
|
6
|
-
{ pattern: 'https://cdn.
|
|
7
|
-
{ pattern: 'https://
|
|
8
|
-
{ pattern: 'https://cdnjs.cloudflare.com/ajax/libs/
|
|
9
|
-
{ pattern: 'https://cdnjs.cloudflare.com/ajax/libs/
|
|
10
|
-
{ pattern: 'https://cdnjs.cloudflare.com/ajax/libs/
|
|
11
|
-
{ pattern: 'https://cdnjs.cloudflare.com/ajax/libs/
|
|
12
|
-
{ pattern: '
|
|
13
|
-
{ pattern: '
|
|
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
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
options: {
|
|
19
|
-
emitActualCode: false,
|
|
20
|
-
ignoreUpstreamSourceMap: true
|
|
21
|
-
}
|
|
16
|
+
reporters: ['dots', 'coverage'],
|
|
17
|
+
preprocessors: {
|
|
18
|
+
'dist/**/*.js': ['coverage'],
|
|
22
19
|
},
|
|
23
|
-
|
|
24
|
-
coverageIstanbulReporter: {
|
|
25
|
-
reports: ['html', 'lcovonly', 'text-summary'],
|
|
20
|
+
coverageReporter: {
|
|
26
21
|
dir: 'coverage',
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
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
|
-
|
|
43
|
-
|
|
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.
|
|
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/
|
|
16
|
+
"main": "./dist/index.js",
|
|
17
17
|
"files": [
|
|
18
18
|
"dist",
|
|
19
|
-
"
|
|
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
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"eslint
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"
|
|
47
|
-
"
|
|
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
|
|
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": "^
|
|
61
|
-
"npm-check-updates": "^
|
|
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.
|
|
65
|
-
"
|
|
66
|
-
"typed-dom": "0.0.
|
|
67
|
-
"
|
|
68
|
-
"
|
|
69
|
-
"
|
|
70
|
-
"
|
|
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
|
-
"
|
|
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(
|
|
487
|
-
`-\n#! 1\n${[...Array(
|
|
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(
|
|
481
|
+
...[...Array(32)].map((_, i) => html('td', `${i + 2}`)),
|
|
496
482
|
]),
|
|
497
483
|
html('tr', [
|
|
498
484
|
html('th', { class: 'highlight' }, '1'),
|
|
499
|
-
...[...Array(
|
|
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(
|
|
507
|
-
`-\n${[...Array(
|
|
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(
|
|
515
|
-
html('th', '
|
|
500
|
+
...[...Array(32)].map((_, i) => html('td', `${i + 1}`)),
|
|
501
|
+
html('th', '33'),
|
|
516
502
|
]),
|
|
517
503
|
html('tr', [
|
|
518
|
-
...[...Array(
|
|
519
|
-
html('th', { class: 'highlight' }, '
|
|
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(
|
|
527
|
-
`-\n${[...Array(
|
|
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(
|
|
534
|
-
html('th', { class: 'highlight' }, '
|
|
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(
|
|
540
|
-
html('td', { class: 'highlight', highlight: 'v' }, '
|
|
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,
|
|
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('~~~',
|
|
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 =
|
|
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 =
|
|
218
|
-
let highlights =
|
|
205
|
+
let heads = 0n;
|
|
206
|
+
let highlights = 0n;
|
|
219
207
|
let hasDataCell = false;
|
|
220
|
-
let lHeadCellIdx:
|
|
221
|
-
let rHeadCellIdx:
|
|
222
|
-
for (let j = 0; j < cells.length
|
|
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 |=
|
|
229
|
-
highlights |=
|
|
216
|
+
heads |= BigInt(isHeadCell) << jn;
|
|
217
|
+
highlights |= BigInt(cell.classList.contains('highlight')) << jn;
|
|
230
218
|
hasDataCell ||= !isHeadCell;
|
|
231
219
|
if (isHeadCell && !hasDataCell) {
|
|
232
|
-
lHeadCellIdx =
|
|
220
|
+
lHeadCellIdx = jn;
|
|
233
221
|
}
|
|
234
222
|
if (isHeadCell && hasDataCell) {
|
|
235
|
-
rHeadCellIdx ??=
|
|
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 &
|
|
251
|
-
highlights |= +`0b${`${highlights &
|
|
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 ??= -
|
|
293
|
-
rHeadCellIdx ??= -
|
|
279
|
+
lHeadCellIdx ??= -1n;
|
|
280
|
+
rHeadCellIdx ??= -1n;
|
|
294
281
|
const tHighlights = verticalHighlights;
|
|
295
282
|
const horizontalHighlights = heads & highlights;
|
|
296
|
-
const lHighlight = ~lHeadCellIdx && horizontalHighlights &
|
|
297
|
-
const rHighlight = ~rHeadCellIdx && horizontalHighlights &
|
|
298
|
-
for (let i = 0, m =
|
|
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('
|
|
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 = /^
|
|
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
|
|
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,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
|
|
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": "
|
|
3
|
+
"target": "ES2021",
|
|
4
4
|
"lib": [
|
|
5
|
-
"
|
|
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
|
-
"
|
|
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
|
}
|