securemark 0.262.0 → 0.262.2
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/CHANGELOG.md +8 -0
- package/dist/index.js +388 -761
- package/package.json +6 -6
- package/src/combinator/control/constraint/contract.ts +6 -8
- package/src/combinator/data/parser/union.ts +12 -7
- package/src/parser/inline/extension/indexee.ts +2 -2
- package/src/parser/locale.ts +2 -2
- package/src/parser/processor/figure.ts +4 -4
- package/src/parser/processor/footnote.ts +9 -8
- package/src/util/info.ts +2 -2
- package/src/util/quote.ts +4 -3
- package/src/util/toc.ts +3 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "securemark",
|
|
3
|
-
"version": "0.262.
|
|
3
|
+
"version": "0.262.2",
|
|
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",
|
|
@@ -34,11 +34,11 @@
|
|
|
34
34
|
"@types/mocha": "9.1.1",
|
|
35
35
|
"@types/power-assert": "1.5.8",
|
|
36
36
|
"@types/prismjs": "1.26.0",
|
|
37
|
-
"@typescript-eslint/parser": "^5.
|
|
37
|
+
"@typescript-eslint/parser": "^5.37.0",
|
|
38
38
|
"babel-loader": "^8.2.5",
|
|
39
39
|
"babel-plugin-unassert": "^3.2.0",
|
|
40
40
|
"concurrently": "^7.4.0",
|
|
41
|
-
"eslint": "^8.23.
|
|
41
|
+
"eslint": "^8.23.1",
|
|
42
42
|
"eslint-plugin-redos": "^4.4.1",
|
|
43
43
|
"eslint-webpack-plugin": "^3.2.0",
|
|
44
44
|
"glob": "^8.0.3",
|
|
@@ -49,11 +49,11 @@
|
|
|
49
49
|
"karma-mocha": "^2.0.1",
|
|
50
50
|
"karma-power-assert": "^1.0.0",
|
|
51
51
|
"mocha": "^10.0.0",
|
|
52
|
-
"npm-check-updates": "^16.1.
|
|
52
|
+
"npm-check-updates": "^16.1.3",
|
|
53
53
|
"semver": "^7.3.7",
|
|
54
|
-
"spica": "0.0.
|
|
54
|
+
"spica": "0.0.626",
|
|
55
55
|
"ts-loader": "^9.3.1",
|
|
56
|
-
"typed-dom": "^0.0.
|
|
56
|
+
"typed-dom": "^0.0.309",
|
|
57
57
|
"typescript": "4.8.3",
|
|
58
58
|
"webpack": "^5.74.0",
|
|
59
59
|
"webpack-cli": "^4.10.0",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { global, undefined } from 'spica/global';
|
|
2
2
|
import { isArray } from 'spica/alias';
|
|
3
3
|
import { Parser, Ctx, Tree, Context, eval, exec, check } from '../../data/parser';
|
|
4
4
|
|
|
@@ -15,15 +15,13 @@ export function validate<T>(patterns: string | RegExp | (string | RegExp)[], has
|
|
|
15
15
|
assert(patterns.length > 0);
|
|
16
16
|
assert(patterns.every(pattern => pattern instanceof RegExp ? !pattern.flags.match(/[gmy]/) && pattern.source.startsWith('^') : true));
|
|
17
17
|
assert(parser);
|
|
18
|
-
const match: (source: string) => boolean =
|
|
19
|
-
'
|
|
20
|
-
|
|
21
|
-
'0',
|
|
22
|
-
...patterns.map(pattern =>
|
|
18
|
+
const match: (source: string) => boolean = global.eval([
|
|
19
|
+
'source =>',
|
|
20
|
+
patterns.map(pattern =>
|
|
23
21
|
typeof pattern === 'string'
|
|
24
22
|
? `|| source.slice(0, ${pattern.length}) === '${pattern}'`
|
|
25
|
-
: `|| /${pattern.source}/${pattern.flags}.test(source)`),
|
|
26
|
-
].join(''))
|
|
23
|
+
: `|| /${pattern.source}/${pattern.flags}.test(source)`).join('').slice(2),
|
|
24
|
+
].join(''));
|
|
27
25
|
return ({ source, context }) => {
|
|
28
26
|
if (source === '') return;
|
|
29
27
|
if (!match(source)) return;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { undefined
|
|
1
|
+
import { undefined } from 'spica/global';
|
|
2
2
|
import { Parser, Ctx, Tree, Context, SubParsers, SubTree } from '../parser';
|
|
3
3
|
|
|
4
4
|
export function union<P extends Parser<unknown>>(parsers: SubParsers<P>): SubTree<P> extends Tree<P> ? P : Parser<SubTree<P>, Context<P>, SubParsers<P>>;
|
|
@@ -9,12 +9,17 @@ export function union<T, D extends Parser<T>[]>(parsers: D): Parser<T, Ctx, D> {
|
|
|
9
9
|
return () => undefined;
|
|
10
10
|
case 1:
|
|
11
11
|
return parsers[0];
|
|
12
|
+
case 2:
|
|
13
|
+
return input => parsers[0](input) ?? parsers[1](input);
|
|
14
|
+
case 3:
|
|
15
|
+
return input => parsers[0](input) ?? parsers[1](input) ?? parsers[2](input);
|
|
12
16
|
default:
|
|
13
|
-
return
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
return input => {
|
|
18
|
+
for (let i = 0; i < parsers.length; ++i) {
|
|
19
|
+
const parser = parsers[i];
|
|
20
|
+
const result = parser(input);
|
|
21
|
+
if (result) return result;
|
|
22
|
+
}
|
|
23
|
+
};
|
|
19
24
|
}
|
|
20
25
|
}
|
|
@@ -3,7 +3,6 @@ import { MarkdownParser } from '../../../../markdown';
|
|
|
3
3
|
import { Parser } from '../../../combinator/data/parser';
|
|
4
4
|
import { fmap } from '../../../combinator';
|
|
5
5
|
import { define } from 'typed-dom/dom';
|
|
6
|
-
import { querySelectorAll } from 'typed-dom/query';
|
|
7
6
|
|
|
8
7
|
export function indexee<P extends Parser<unknown, MarkdownParser.Context>>(parser: P, optional?: boolean): P;
|
|
9
8
|
export function indexee(parser: Parser<HTMLElement, MarkdownParser.Context>, optional?: boolean): Parser<HTMLElement> {
|
|
@@ -28,7 +27,8 @@ export function text(source: HTMLElement | DocumentFragment, optional = false):
|
|
|
28
27
|
if (index) return index;
|
|
29
28
|
assert(!source.querySelector('.annotation, br'));
|
|
30
29
|
const target = source.cloneNode(true) as typeof source;
|
|
31
|
-
for (let es = querySelectorAll(
|
|
30
|
+
for (let es = target.querySelectorAll('code[data-src], .math[data-src], .comment, rt, rp, .reference, .checkbox, ul, ol'),
|
|
31
|
+
len = es.length, i = 0; i < len; ++i) {
|
|
32
32
|
const el = es[i];
|
|
33
33
|
switch (el.tagName) {
|
|
34
34
|
case 'CODE':
|
package/src/parser/locale.ts
CHANGED
|
@@ -2,7 +2,6 @@ import { Parser } from '../combinator/data/parser';
|
|
|
2
2
|
import { fmap } from '../combinator';
|
|
3
3
|
import { japanese } from './locale/ja';
|
|
4
4
|
import { html } from 'typed-dom/dom';
|
|
5
|
-
import { querySelectorAll } from 'typed-dom/query';
|
|
6
5
|
|
|
7
6
|
export function localize<P extends Parser<HTMLElement | string>>(parser: P): P;
|
|
8
7
|
export function localize(parser: Parser<HTMLElement | string>): Parser<HTMLElement | string> {
|
|
@@ -11,7 +10,8 @@ export function localize(parser: Parser<HTMLElement | string>): Parser<HTMLEleme
|
|
|
11
10
|
const el = ns.length === 1 && typeof ns[0] === 'object'
|
|
12
11
|
? ns[0]
|
|
13
12
|
: html('div', ns);
|
|
14
|
-
for (let es = querySelectorAll(
|
|
13
|
+
for (let es = el.querySelectorAll('.linebreak:not(:empty)'),
|
|
14
|
+
len = es.length, i = 0; i < len; ++i) {
|
|
15
15
|
const el = es[i];
|
|
16
16
|
assert(el.firstChild!.textContent === ' ');
|
|
17
17
|
if (!check(el)) continue;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Infinity, Set, Map } from 'spica/global';
|
|
2
2
|
import { number as calculate, isFixed } from '../inline/extension/label';
|
|
3
|
-
import {
|
|
3
|
+
import { MultiQueue } from 'spica/queue';
|
|
4
4
|
import { push } from 'spica/array';
|
|
5
5
|
import { define } from 'typed-dom/dom';
|
|
6
6
|
import { querySelectorAll } from 'typed-dom/query';
|
|
@@ -10,7 +10,7 @@ export function* figure(
|
|
|
10
10
|
footnotes?: { readonly references: HTMLOListElement; },
|
|
11
11
|
opts: { readonly id?: string; } = {},
|
|
12
12
|
): Generator<HTMLAnchorElement | undefined, undefined, undefined> {
|
|
13
|
-
const refs = new
|
|
13
|
+
const refs = new MultiQueue<string, HTMLAnchorElement>(push(
|
|
14
14
|
querySelectorAll(target, 'a.label:not(.disabled)[data-label]'),
|
|
15
15
|
footnotes && querySelectorAll(footnotes.references, 'a.label:not(.disabled)') || [])
|
|
16
16
|
.map(el => [el.getAttribute('data-label')!, el]));
|
|
@@ -20,9 +20,9 @@ export function* figure(
|
|
|
20
20
|
let bases: readonly string[] = base.split('.');
|
|
21
21
|
let index: readonly string[] = bases;
|
|
22
22
|
// Bug: Firefox
|
|
23
|
-
//for (let defs = querySelectorAll(
|
|
23
|
+
//for (let defs = target.querySelectorAll(':scope > figure[data-label], :scope > h1, :scope > h2'), len = defs.length, i = 0; i < len; ++i) {
|
|
24
24
|
for (
|
|
25
|
-
let defs = querySelectorAll(
|
|
25
|
+
let defs = target.querySelectorAll('figure[data-label], h1, h2'),
|
|
26
26
|
len = defs.length, i = 0; i < len; ++i) {
|
|
27
27
|
yield;
|
|
28
28
|
const def = defs[i];
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { undefined, Infinity, Map, Node } from 'spica/global';
|
|
2
2
|
import { text } from '../inline/extension/indexee';
|
|
3
|
-
import {
|
|
3
|
+
import { MultiQueue } from 'spica/queue';
|
|
4
4
|
import { frag, html, define } from 'typed-dom/dom';
|
|
5
|
-
import { querySelectorAll } from 'typed-dom/query';
|
|
6
5
|
|
|
7
6
|
export function* footnote(
|
|
8
7
|
target: ParentNode & Node,
|
|
@@ -11,8 +10,9 @@ export function* footnote(
|
|
|
11
10
|
bottom: Node | null = null,
|
|
12
11
|
): Generator<HTMLAnchorElement | HTMLLIElement | undefined, undefined, undefined> {
|
|
13
12
|
// Bug: Firefox
|
|
14
|
-
//querySelectorAll(
|
|
15
|
-
for (let es = querySelectorAll(
|
|
13
|
+
//target.querySelectorAll(`:scope > .annotations`).forEach(el => el.remove());
|
|
14
|
+
for (let es = target.querySelectorAll(`.annotations`),
|
|
15
|
+
len = es.length, i = 0; i < len; ++i) {
|
|
16
16
|
const el = es[i];
|
|
17
17
|
el.parentNode === target && el.remove();
|
|
18
18
|
}
|
|
@@ -39,12 +39,13 @@ function build(
|
|
|
39
39
|
bottom: Node | null = null,
|
|
40
40
|
): Generator<HTMLAnchorElement | HTMLLIElement | undefined, undefined, undefined> {
|
|
41
41
|
const defs = new Map<string, HTMLLIElement>();
|
|
42
|
-
const buffer = new
|
|
42
|
+
const buffer = new MultiQueue<string, HTMLElement>();
|
|
43
43
|
const titles = new Map<string, string>();
|
|
44
44
|
// Bug: Firefox
|
|
45
|
-
//const splitters = push([], querySelectorAll(
|
|
45
|
+
//const splitters = push([], target.querySelectorAll(`:scope > :is(${splitter ?? '_'})`));
|
|
46
46
|
const splitters: Element[] = [];
|
|
47
|
-
for (let es = querySelectorAll(
|
|
47
|
+
for (let es = target.querySelectorAll(splitter ?? '_'),
|
|
48
|
+
len = es.length, i = 0; i < len; ++i) {
|
|
48
49
|
const el = es[i];
|
|
49
50
|
el.parentNode === target && splitters.push(el);
|
|
50
51
|
}
|
|
@@ -52,7 +53,7 @@ function build(
|
|
|
52
53
|
let total = 0;
|
|
53
54
|
let style: 'count' | 'abbr';
|
|
54
55
|
for (
|
|
55
|
-
let refs = querySelectorAll(
|
|
56
|
+
let refs = target.querySelectorAll(`sup.${syntax}:not(.disabled)`),
|
|
56
57
|
len = refs.length, i = 0; i < len; ++i) {
|
|
57
58
|
yield;
|
|
58
59
|
const ref = refs[i];
|
package/src/util/info.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { Info } from '../..';
|
|
2
2
|
import { scope } from './scope';
|
|
3
|
-
import { querySelectorAll } from 'typed-dom/query';
|
|
4
3
|
|
|
5
4
|
export function info(source: DocumentFragment | HTMLElement | ShadowRoot): Info {
|
|
6
5
|
const match = scope(source, '.invalid');
|
|
@@ -19,7 +18,8 @@ export function info(source: DocumentFragment | HTMLElement | ShadowRoot): Info
|
|
|
19
18
|
|
|
20
19
|
function find<T extends HTMLElement>(selector: string): T[] {
|
|
21
20
|
const acc: T[] = [];
|
|
22
|
-
for (let es = querySelectorAll<T>(
|
|
21
|
+
for (let es = source.querySelectorAll<T>(selector),
|
|
22
|
+
len = es.length, i = 0; i < len; ++i) {
|
|
23
23
|
const el = es[i];
|
|
24
24
|
match(el) && acc.push(el);
|
|
25
25
|
}
|
package/src/util/quote.ts
CHANGED
|
@@ -2,14 +2,14 @@ import { Element } from 'spica/global';
|
|
|
2
2
|
import { exec } from '../combinator/data/parser';
|
|
3
3
|
import { cite } from '../parser/block/reply/cite';
|
|
4
4
|
import { define } from 'typed-dom/dom';
|
|
5
|
-
import { querySelectorAll } from 'typed-dom/query';
|
|
6
5
|
|
|
7
6
|
export function quote(anchor: string, range: Range): string {
|
|
8
7
|
if (exec(cite({ source: `>>${anchor}`, context: {} })) !== '') throw new Error(`Invalid anchor: ${anchor}`);
|
|
9
8
|
fit(range);
|
|
10
9
|
const node = trim(range.cloneContents());
|
|
11
10
|
if (!node.firstChild) return '';
|
|
12
|
-
for (let es = querySelectorAll(
|
|
11
|
+
for (let es = node.querySelectorAll('code[data-src], .math[data-src], .media[data-src], rt, rp'),
|
|
12
|
+
len = es.length, i = 0; i < len; ++i) {
|
|
13
13
|
const el = es[i];
|
|
14
14
|
switch (true) {
|
|
15
15
|
case el.matches('code'):
|
|
@@ -36,7 +36,8 @@ export function quote(anchor: string, range: Range): string {
|
|
|
36
36
|
node.prepend(`>>${anchor}\n> `);
|
|
37
37
|
anchor = '';
|
|
38
38
|
}
|
|
39
|
-
for (let es = querySelectorAll(
|
|
39
|
+
for (let es = node.querySelectorAll('br'),
|
|
40
|
+
len = es.length, i = 0; i < len; ++i) {
|
|
40
41
|
const el = es[i];
|
|
41
42
|
if (anchor && el.nextSibling instanceof Element && el.nextSibling.matches('.cite, .quote')) {
|
|
42
43
|
el.replaceWith(`\n>${el.nextSibling.matches('.quote.invalid') ? ' ' : ''}`);
|
package/src/util/toc.ts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { undefined } from 'spica/global';
|
|
2
2
|
import { push } from 'spica/array';
|
|
3
3
|
import { html } from 'typed-dom/dom';
|
|
4
|
-
import { querySelectorAll } from 'typed-dom/query';
|
|
5
4
|
|
|
6
5
|
// Bug: Firefox
|
|
7
|
-
//const selector =
|
|
6
|
+
//const selector = `:scope > :is(h1, h2, h3, h4, h5, h6, aside.aside)[id]`;
|
|
8
7
|
const selector = ':is(h1, h2, h3, h4, h5, h6, aside.aside)[id]';
|
|
9
8
|
|
|
10
9
|
export function toc(source: DocumentFragment | HTMLElement | ShadowRoot): HTMLUListElement {
|
|
11
10
|
const hs: HTMLHeadingElement[] = [];
|
|
12
|
-
for (let es = querySelectorAll(
|
|
11
|
+
for (let es = source.querySelectorAll(selector),
|
|
12
|
+
len = es.length, i = 0; i < len; ++i) {
|
|
13
13
|
const el = es[i];
|
|
14
14
|
assert(el.parentNode === source);
|
|
15
15
|
switch (el.tagName) {
|