securemark 0.244.2 → 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 +4 -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 +28 -34
- package/src/parser/block/extension/table.test.ts +16 -30
- package/src/parser/block/extension/table.ts +21 -34
- 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 -8578
- package/gulpfile.js +0 -208
- package/package-lock.json +0 -11857
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
50
|
"mocha": "^10.0.0",
|
|
61
|
-
"npm-check-updates": "^
|
|
62
|
-
"power-assert": "^1.6.1",
|
|
51
|
+
"npm-check-updates": "^13.0.1",
|
|
63
52
|
"semver": "^7.3.7",
|
|
64
|
-
"spica": "0.0.
|
|
65
|
-
"
|
|
66
|
-
"typed-dom": "0.0.
|
|
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
|
-
"
|
|
70
|
-
"
|
|
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"
|
|
@@ -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;
|
|
@@ -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
|
}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const glob = require('glob');
|
|
3
|
+
const shell = cmd => require('child_process').execSync(cmd, { stdio: [0, 1, 2] });
|
|
4
|
+
const webpack = require('webpack');
|
|
5
|
+
const { mergeWithRules } = require('webpack-merge');
|
|
6
|
+
const ESLintPlugin = require('eslint-webpack-plugin');
|
|
7
|
+
const pkg = require('./package.json');
|
|
8
|
+
|
|
9
|
+
shell('rm -rf dist coverage');
|
|
10
|
+
|
|
11
|
+
module.exports = env => {
|
|
12
|
+
const merge = mergeWithRules({
|
|
13
|
+
entry: 'replace',
|
|
14
|
+
module: {
|
|
15
|
+
rules: {
|
|
16
|
+
test: 'match',
|
|
17
|
+
use: {
|
|
18
|
+
loader: 'match',
|
|
19
|
+
options: 'replace',
|
|
20
|
+
plugins: 'replace',
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
plugins: 'append',
|
|
25
|
+
});
|
|
26
|
+
const config = {
|
|
27
|
+
mode: 'production',
|
|
28
|
+
externals: {
|
|
29
|
+
benchmark: 'Benchmark',
|
|
30
|
+
prismjs: 'Prism',
|
|
31
|
+
dompurify: 'DOMPurify',
|
|
32
|
+
},
|
|
33
|
+
resolve: {
|
|
34
|
+
extensions: ['.ts', '.js'],
|
|
35
|
+
},
|
|
36
|
+
entry: glob.sync('./{src,test}/**/*.ts'),
|
|
37
|
+
output: {
|
|
38
|
+
filename: 'index.js',
|
|
39
|
+
path: path.resolve(__dirname, 'dist'),
|
|
40
|
+
library: pkg.name,
|
|
41
|
+
libraryTarget: 'umd',
|
|
42
|
+
globalObject: 'globalThis',
|
|
43
|
+
clean: true,
|
|
44
|
+
},
|
|
45
|
+
module: {
|
|
46
|
+
rules: [
|
|
47
|
+
{
|
|
48
|
+
test: /\.ts$/,
|
|
49
|
+
//exclude: /node_modules/,
|
|
50
|
+
use: [
|
|
51
|
+
{
|
|
52
|
+
loader: 'babel-loader',
|
|
53
|
+
options: {},
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
loader: 'ts-loader',
|
|
57
|
+
options: {
|
|
58
|
+
onlyCompileBundledFiles: true,
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
],
|
|
62
|
+
},
|
|
63
|
+
],
|
|
64
|
+
},
|
|
65
|
+
plugins: [
|
|
66
|
+
new webpack.BannerPlugin({
|
|
67
|
+
banner: `${pkg.name} v${pkg.version} ${pkg.repository.url} | (c) 2017, ${pkg.author} | ${pkg.license} License`,
|
|
68
|
+
}),
|
|
69
|
+
],
|
|
70
|
+
performance: {
|
|
71
|
+
maxEntrypointSize: Infinity,
|
|
72
|
+
maxAssetSize: Infinity,
|
|
73
|
+
},
|
|
74
|
+
optimization: {
|
|
75
|
+
minimize: false,
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
switch (env.mode) {
|
|
79
|
+
case 'test':
|
|
80
|
+
return merge(config);
|
|
81
|
+
case 'lint':
|
|
82
|
+
return merge(config, {
|
|
83
|
+
entry: glob.sync('./!(node_modules)**/*.ts'),
|
|
84
|
+
plugins: [
|
|
85
|
+
new ESLintPlugin({
|
|
86
|
+
extensions: ['ts'],
|
|
87
|
+
}),
|
|
88
|
+
],
|
|
89
|
+
});
|
|
90
|
+
case 'bench':
|
|
91
|
+
return merge(config, {
|
|
92
|
+
entry: glob.sync('./benchmark/**/*.ts'),
|
|
93
|
+
module: {
|
|
94
|
+
rules: [
|
|
95
|
+
{
|
|
96
|
+
test: /\.ts$/,
|
|
97
|
+
use: [
|
|
98
|
+
{
|
|
99
|
+
loader: 'babel-loader',
|
|
100
|
+
options: {
|
|
101
|
+
plugins: ['babel-plugin-unassert'],
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
],
|
|
105
|
+
},
|
|
106
|
+
],
|
|
107
|
+
},
|
|
108
|
+
});
|
|
109
|
+
case 'dist':
|
|
110
|
+
return merge(config, {
|
|
111
|
+
entry: glob.sync('./index.ts'),
|
|
112
|
+
module: {
|
|
113
|
+
rules: [
|
|
114
|
+
{
|
|
115
|
+
test: /\.ts$/,
|
|
116
|
+
use: [
|
|
117
|
+
{
|
|
118
|
+
loader: 'babel-loader',
|
|
119
|
+
options: {
|
|
120
|
+
plugins: ['babel-plugin-unassert'],
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
],
|
|
124
|
+
},
|
|
125
|
+
],
|
|
126
|
+
},
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
};
|