securemark 0.240.0 → 0.241.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/CHANGELOG.md +12 -0
- package/design.md +2 -2
- package/dist/securemark.js +1260 -2745
- package/gulpfile.js +1 -1
- package/index.d.ts +0 -1
- package/package-lock.json +285 -160
- package/package.json +8 -8
- package/src/combinator/control/manipulation/fallback.ts +0 -1
- package/src/combinator/control/manipulation/indent.ts +3 -3
- package/src/combinator/data/parser/some.ts +28 -6
- package/src/combinator/data/parser.ts +21 -16
- package/src/debug.test.ts +1 -1
- package/src/parser/api/bind.test.ts +1 -1
- package/src/parser/api/parse.test.ts +7 -1
- package/src/parser/api/parse.ts +1 -1
- package/src/parser/block/blockquote.ts +1 -1
- package/src/parser/block/codeblock.ts +1 -1
- package/src/parser/block/dlist.ts +1 -1
- package/src/parser/block/extension/aside.ts +1 -1
- package/src/parser/block/extension/example.ts +1 -1
- package/src/parser/block/extension/figbase.ts +1 -1
- package/src/parser/block/extension/figure.ts +21 -20
- package/src/parser/block/extension/message.ts +1 -1
- package/src/parser/block/extension/placeholder.ts +1 -1
- package/src/parser/block/extension/table.test.ts +1 -1
- package/src/parser/block/extension/table.ts +1 -1
- package/src/parser/block/heading.ts +1 -1
- package/src/parser/block/horizontalrule.ts +1 -1
- package/src/parser/block/ilist.ts +1 -1
- package/src/parser/block/mathblock.ts +1 -1
- package/src/parser/block/olist.ts +8 -8
- package/src/parser/block/paragraph.ts +1 -1
- package/src/parser/block/reply/cite.ts +1 -1
- package/src/parser/block/reply/quote.ts +1 -1
- package/src/parser/block/reply.ts +1 -1
- package/src/parser/block/table.ts +1 -1
- package/src/parser/block/ulist.ts +1 -1
- package/src/parser/block.ts +1 -1
- package/src/parser/header.ts +1 -1
- package/src/parser/inline/annotation.ts +2 -2
- package/src/parser/inline/autolink/account.ts +1 -1
- package/src/parser/inline/autolink/anchor.ts +1 -1
- package/src/parser/inline/autolink/channel.ts +1 -1
- package/src/parser/inline/autolink/email.ts +1 -1
- package/src/parser/inline/autolink/hashnum.ts +1 -1
- package/src/parser/inline/autolink/hashtag.ts +1 -1
- package/src/parser/inline/bracket.test.ts +5 -1
- package/src/parser/inline/bracket.ts +3 -3
- package/src/parser/inline/code.ts +1 -1
- package/src/parser/inline/comment.ts +2 -2
- package/src/parser/inline/deletion.ts +1 -1
- package/src/parser/inline/emphasis.ts +1 -1
- package/src/parser/inline/emstrong.ts +1 -1
- package/src/parser/inline/extension/index.ts +1 -1
- package/src/parser/inline/extension/indexee.ts +1 -1
- package/src/parser/inline/extension/indexer.ts +1 -1
- package/src/parser/inline/extension/label.ts +1 -1
- package/src/parser/inline/extension/placeholder.ts +1 -1
- package/src/parser/inline/html.ts +1 -1
- package/src/parser/inline/htmlentity.ts +1 -1
- package/src/parser/inline/insertion.ts +1 -1
- package/src/parser/inline/link.ts +1 -1
- package/src/parser/inline/mark.ts +1 -1
- package/src/parser/inline/math.ts +1 -1
- package/src/parser/inline/media.ts +1 -1
- package/src/parser/inline/reference.ts +2 -2
- package/src/parser/inline/ruby.ts +1 -1
- package/src/parser/inline/strong.ts +1 -1
- package/src/parser/inline/template.ts +1 -1
- package/src/parser/inline.test.ts +4 -0
- package/src/parser/locale.ts +1 -1
- package/src/parser/processor/figure.test.ts +1 -1
- package/src/parser/processor/figure.ts +1 -1
- package/src/parser/processor/footnote.test.ts +1 -1
- package/src/parser/processor/footnote.ts +5 -4
- package/src/parser/source/text.ts +1 -1
- package/src/renderer/render/math.ts +1 -1
- package/src/renderer/render/media/audio.ts +1 -1
- package/src/renderer/render/media/image.ts +1 -1
- package/src/renderer/render/media/pdf.ts +1 -1
- package/src/renderer/render/media/twitter.ts +21 -23
- package/src/renderer/render/media/video.ts +1 -1
- package/src/renderer/render/media/youtube.ts +1 -1
- package/src/renderer/render/media.test.ts +1 -1
- package/src/util/quote.ts +1 -1
- package/src/util/toc.test.ts +1 -1
- package/src/util/toc.ts +1 -1
- package/src/util.ts +0 -1
- package/src/util/sync.ts +0 -57
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "securemark",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.241.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",
|
|
@@ -33,12 +33,12 @@
|
|
|
33
33
|
"@types/dompurify": "2.3.3",
|
|
34
34
|
"@types/jquery": "3.5.14",
|
|
35
35
|
"@types/mathjax": "0.0.37",
|
|
36
|
-
"@types/mocha": "9.1.
|
|
36
|
+
"@types/mocha": "9.1.1",
|
|
37
37
|
"@types/power-assert": "1.5.8",
|
|
38
38
|
"@types/prismjs": "1.26.0",
|
|
39
39
|
"browserify": "^17.0.0",
|
|
40
40
|
"browserify-shim": "^3.8.14",
|
|
41
|
-
"concurrently": "^7.
|
|
41
|
+
"concurrently": "^7.1.0",
|
|
42
42
|
"del": "^6.0.0",
|
|
43
43
|
"eslint-plugin-redos": "^4.3.0",
|
|
44
44
|
"gulp": "^4.0.2",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"gulp-mocha": "^8.0.0",
|
|
51
51
|
"gulp-rename": "^2.0.0",
|
|
52
52
|
"gulp-unassert": "^2.0.0",
|
|
53
|
-
"karma": "^6.3.
|
|
53
|
+
"karma": "^6.3.19",
|
|
54
54
|
"karma-chrome-launcher": "^3.1.1",
|
|
55
55
|
"karma-coverage-istanbul-instrumenter": "^1.0.4",
|
|
56
56
|
"karma-coverage-istanbul-reporter": "^3.0.3",
|
|
@@ -58,12 +58,12 @@
|
|
|
58
58
|
"karma-firefox-launcher": "^2.1.2",
|
|
59
59
|
"karma-mocha": "^2.0.1",
|
|
60
60
|
"mocha": "^9.2.2",
|
|
61
|
-
"npm-check-updates": "^12.5.
|
|
61
|
+
"npm-check-updates": "^12.5.9",
|
|
62
62
|
"power-assert": "^1.6.1",
|
|
63
|
-
"semver": "^7.3.
|
|
64
|
-
"spica": "0.0.
|
|
63
|
+
"semver": "^7.3.7",
|
|
64
|
+
"spica": "0.0.521",
|
|
65
65
|
"tsify": "^5.0.4",
|
|
66
|
-
"typed-dom": "0.0.
|
|
66
|
+
"typed-dom": "0.0.253",
|
|
67
67
|
"typescript": "4.6.3",
|
|
68
68
|
"vinyl-buffer": "^1.0.1",
|
|
69
69
|
"vinyl-source-stream": "^2.0.0"
|
|
@@ -2,7 +2,6 @@ import { Parser, Tree, Context } from '../../data/parser';
|
|
|
2
2
|
import { union } from '../../data/parser/union';
|
|
3
3
|
|
|
4
4
|
export function fallback<P extends Parser<unknown>>(parser: P, otherwise: Parser<Tree<P>, Context<P>>): P;
|
|
5
|
-
export function fallback<T, P extends Parser<T>>(parser: P, otherwise: Parser<T, Context<P>>): P;
|
|
6
5
|
export function fallback<T>(parser: Parser<T>, otherwise: Parser<T>): Parser<T> {
|
|
7
6
|
return union([parser, otherwise]);
|
|
8
7
|
}
|
|
@@ -5,7 +5,7 @@ import { line } from '../constraint/line';
|
|
|
5
5
|
import { bind } from '../monad/bind';
|
|
6
6
|
import { match } from './match';
|
|
7
7
|
import { open } from './surround';
|
|
8
|
-
import {
|
|
8
|
+
import { memoize } from 'spica/memoize';
|
|
9
9
|
import { join } from 'spica/array';
|
|
10
10
|
|
|
11
11
|
export function indent<P extends Parser<unknown>>(parser: P): P;
|
|
@@ -13,10 +13,10 @@ export function indent<T>(parser: Parser<T>): Parser<T> {
|
|
|
13
13
|
assert(parser);
|
|
14
14
|
return bind(match(
|
|
15
15
|
/^(?=(([ \t])\2*))/,
|
|
16
|
-
|
|
16
|
+
memoize(
|
|
17
17
|
([, indent]) =>
|
|
18
18
|
some(line(open(indent, source => [[unline(source)], '']))),
|
|
19
|
-
([, indent]) => indent)),
|
|
19
|
+
([, indent]) => indent.length * 2 + +(indent[0] === ' '), [])),
|
|
20
20
|
(nodes, rest, context) => {
|
|
21
21
|
const result = parser(join(nodes, '\n'), context);
|
|
22
22
|
return result && exec(result) === ''
|
|
@@ -14,14 +14,14 @@ const signature = (pattern: string | RegExp | undefined): string => {
|
|
|
14
14
|
}
|
|
15
15
|
};
|
|
16
16
|
const matcher = memoize(
|
|
17
|
-
(pattern: string | RegExp | undefined): (source: string) =>
|
|
17
|
+
(pattern: string | RegExp | undefined): (source: string) => true | undefined => {
|
|
18
18
|
switch (typeof pattern) {
|
|
19
19
|
case 'undefined':
|
|
20
|
-
return () =>
|
|
20
|
+
return () => undefined;
|
|
21
21
|
case 'string':
|
|
22
|
-
return source => source.slice(0, pattern.length) === pattern;
|
|
22
|
+
return source => source.slice(0, pattern.length) === pattern || undefined;
|
|
23
23
|
case 'object':
|
|
24
|
-
return reduce(source => pattern.test(source));
|
|
24
|
+
return reduce(source => pattern.test(source) || undefined);
|
|
25
25
|
}
|
|
26
26
|
},
|
|
27
27
|
signature);
|
|
@@ -42,8 +42,8 @@ export function some<T>(parser: Parser<T>, until?: string | RegExp | number, dee
|
|
|
42
42
|
let rest = source;
|
|
43
43
|
let nodes: T[] | undefined;
|
|
44
44
|
if (deep && context) {
|
|
45
|
-
// bracket >
|
|
46
|
-
// bracket >
|
|
45
|
+
// bracket > link > media | bracket
|
|
46
|
+
// bracket > index > bracket
|
|
47
47
|
context.delimiters ??= new Delimiters();
|
|
48
48
|
context.delimiters.push(delimiter);
|
|
49
49
|
}
|
|
@@ -69,3 +69,25 @@ export function some<T>(parser: Parser<T>, until?: string | RegExp | number, dee
|
|
|
69
69
|
: undefined;
|
|
70
70
|
};
|
|
71
71
|
}
|
|
72
|
+
|
|
73
|
+
export function escape<P extends Parser<unknown>>(parser: P, delim: string): P;
|
|
74
|
+
export function escape<T>(parser: Parser<T>, delim: string): Parser<T> {
|
|
75
|
+
assert(parser);
|
|
76
|
+
const delimiter = {
|
|
77
|
+
signature: signature(delim),
|
|
78
|
+
matcher: (source: string) => source.slice(0, delim.length) !== delim && undefined,
|
|
79
|
+
escape: true,
|
|
80
|
+
} as const;
|
|
81
|
+
return (source, context) => {
|
|
82
|
+
if (source === '') return;
|
|
83
|
+
if (context) {
|
|
84
|
+
context.delimiters ??= new Delimiters();
|
|
85
|
+
context.delimiters.push(delimiter);
|
|
86
|
+
}
|
|
87
|
+
const result = parser(source, context);
|
|
88
|
+
if (context.delimiters) {
|
|
89
|
+
context.delimiters.pop();
|
|
90
|
+
}
|
|
91
|
+
return result;
|
|
92
|
+
};
|
|
93
|
+
}
|
|
@@ -20,26 +20,31 @@ type ExtractSubTree<D extends Parser<unknown>[]> = ExtractSubParser<D> extends i
|
|
|
20
20
|
type ExtractSubParser<D extends Parser<unknown>[]> = D extends (infer P)[] ? P extends Parser<unknown> ? P : never : never;
|
|
21
21
|
|
|
22
22
|
export class Delimiters {
|
|
23
|
-
private readonly
|
|
24
|
-
private readonly
|
|
25
|
-
public push(delimiter: { readonly signature: string; readonly matcher: (source: string) => boolean; }): void {
|
|
26
|
-
const { signature, matcher } = delimiter;
|
|
27
|
-
this.
|
|
28
|
-
|
|
29
|
-
|
|
23
|
+
private readonly matchers: ((source: string) => boolean | undefined)[] = [];
|
|
24
|
+
private readonly record: Record<string, boolean> = {};
|
|
25
|
+
public push(delimiter: { readonly signature: string; readonly matcher: (source: string) => boolean | undefined; readonly escape?: boolean; }): void {
|
|
26
|
+
const { signature, matcher, escape } = delimiter;
|
|
27
|
+
if (this.record[signature] === !escape) {
|
|
28
|
+
this.matchers.unshift(() => undefined);
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
this.matchers.unshift(matcher);
|
|
32
|
+
this.record[signature] = !escape;
|
|
33
|
+
}
|
|
30
34
|
}
|
|
31
35
|
public pop(): void {
|
|
32
|
-
assert(this.
|
|
33
|
-
this.
|
|
36
|
+
assert(this.matchers.length > 0);
|
|
37
|
+
this.matchers.shift();
|
|
34
38
|
}
|
|
35
39
|
public match(source: string): boolean {
|
|
36
|
-
const {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
const { matchers } = this;
|
|
41
|
+
for (let i = 0; i < matchers.length; ++i) {
|
|
42
|
+
switch (matchers[i](source)) {
|
|
43
|
+
case true:
|
|
44
|
+
return true;
|
|
45
|
+
case false:
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
43
48
|
}
|
|
44
49
|
return false;
|
|
45
50
|
}
|
package/src/debug.test.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Result, eval, exec } from './combinator/data/parser';
|
|
2
|
-
import { html, define } from 'typed-dom';
|
|
2
|
+
import { html, define } from 'typed-dom/dom';
|
|
3
3
|
|
|
4
4
|
export function inspect(result: Result<HTMLElement | string>, until: number | string = Infinity): Result<string> {
|
|
5
5
|
return result && [
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { parse } from './parse';
|
|
2
|
-
import { html } from 'typed-dom';
|
|
2
|
+
import { html } from 'typed-dom/dom';
|
|
3
3
|
|
|
4
4
|
describe('Unit: parser/api/parse', () => {
|
|
5
5
|
describe('parse', () => {
|
|
@@ -218,6 +218,12 @@ describe('Unit: parser/api/parse', () => {
|
|
|
218
218
|
['<p>a<span class="linebreak"> </span>b</p>']);
|
|
219
219
|
});
|
|
220
220
|
|
|
221
|
+
it('creation', () => {
|
|
222
|
+
assert.deepStrictEqual(
|
|
223
|
+
[...parse('"[# '.repeat(100)).children].map(el => el.outerHTML),
|
|
224
|
+
[`<p>${'"[# '.repeat(100).trim()}</p>`]);
|
|
225
|
+
});
|
|
226
|
+
|
|
221
227
|
it('recursion', () => {
|
|
222
228
|
assert.deepStrictEqual(
|
|
223
229
|
[...parse('('.repeat(199)).children].map(el => el.outerHTML),
|
package/src/parser/api/parse.ts
CHANGED
|
@@ -9,7 +9,7 @@ import { normalize } from './normalize';
|
|
|
9
9
|
import { headers } from './header';
|
|
10
10
|
import { figure } from '../processor/figure';
|
|
11
11
|
import { footnote } from '../processor/footnote';
|
|
12
|
-
import { frag } from 'typed-dom';
|
|
12
|
+
import { frag } from 'typed-dom/dom';
|
|
13
13
|
import { ReadonlyURL } from 'spica/url';
|
|
14
14
|
|
|
15
15
|
interface Options extends ParserOptions {
|
|
@@ -3,7 +3,7 @@ import { union, some, block, validate, rewrite, creator, open, convert, lazy, fm
|
|
|
3
3
|
import { autolink } from '../autolink';
|
|
4
4
|
import { contentline } from '../source';
|
|
5
5
|
import { parse } from '../api/parse';
|
|
6
|
-
import { html, defrag } from 'typed-dom';
|
|
6
|
+
import { html, defrag } from 'typed-dom/dom';
|
|
7
7
|
|
|
8
8
|
export const segment: BlockquoteParser.SegmentParser = block(validate(['!>', '>'], union([
|
|
9
9
|
validate(/^!?>+(?=[^\S\n]|\n[^\S\n]*\S)/, some(contentline)),
|
|
@@ -3,7 +3,7 @@ import { CodeBlockParser } from '../block';
|
|
|
3
3
|
import { eval } from '../../combinator/data/parser';
|
|
4
4
|
import { some, block, validate, fence, clear, fmap } from '../../combinator';
|
|
5
5
|
import { autolink } from '../autolink';
|
|
6
|
-
import { html, defrag } from 'typed-dom';
|
|
6
|
+
import { html, defrag } from 'typed-dom/dom';
|
|
7
7
|
|
|
8
8
|
const opener = /^(`{3,})(?!`)([^\n]*)(?:$|\n)/;
|
|
9
9
|
const language = /^[0-9a-z]+(?:-[a-z][0-9a-z]*)*$/i;
|
|
@@ -4,7 +4,7 @@ import { inline, indexee, indexer } from '../inline';
|
|
|
4
4
|
import { anyline } from '../source';
|
|
5
5
|
import { localize } from '../locale';
|
|
6
6
|
import { visualize } from '../util';
|
|
7
|
-
import { html, defrag } from 'typed-dom';
|
|
7
|
+
import { html, defrag } from 'typed-dom/dom';
|
|
8
8
|
import { push } from 'spica/array';
|
|
9
9
|
|
|
10
10
|
export const dlist: DListParser = lazy(() => block(localize(fmap(validate(
|
|
@@ -2,7 +2,7 @@ import { ExtensionParser } from '../../block';
|
|
|
2
2
|
import { block, validate, fence, creator, fmap } from '../../../combinator';
|
|
3
3
|
import { identity, text } from '../../inline/extension/indexee';
|
|
4
4
|
import { parse } from '../../api/parse';
|
|
5
|
-
import { html } from 'typed-dom';
|
|
5
|
+
import { html } from 'typed-dom/dom';
|
|
6
6
|
|
|
7
7
|
export const aside: ExtensionParser.AsideParser = creator(100, block(validate('~~~', fmap(
|
|
8
8
|
fence(/^(~{3,})aside(?!\S)([^\n]*)(?:$|\n)/, 300),
|
|
@@ -3,7 +3,7 @@ import { eval } from '../../../combinator/data/parser';
|
|
|
3
3
|
import { block, validate, fence, creator, fmap } from '../../../combinator';
|
|
4
4
|
import { parse } from '../../api/parse';
|
|
5
5
|
import { mathblock } from '../mathblock';
|
|
6
|
-
import { html } from 'typed-dom';
|
|
6
|
+
import { html } from 'typed-dom/dom';
|
|
7
7
|
|
|
8
8
|
const opener = /^(~{3,})(?:example\/(\S+)|(?!\S))([^\n]*)(?:$|\n)/;
|
|
9
9
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ExtensionParser } from '../../block';
|
|
2
2
|
import { union, block, line, validate, fmap } from '../../../combinator';
|
|
3
3
|
import { label } from '../../inline/extension/label';
|
|
4
|
-
import { html } from 'typed-dom';
|
|
4
|
+
import { html } from 'typed-dom/dom';
|
|
5
5
|
|
|
6
6
|
export const figbase: ExtensionParser.FigbaseParser = block(fmap(
|
|
7
7
|
validate(/^\[?\$-(?:[0-9]+\.)*0\]?[^\S\n]*(?!\S|\n[^\S\n]*\S)/,
|
|
@@ -15,7 +15,7 @@ import { placeholder, segment_ as seg_placeholder } from './placeholder';
|
|
|
15
15
|
import { inline, media, shortmedia } from '../../inline';
|
|
16
16
|
import { localize } from '../../locale';
|
|
17
17
|
import { visualize } from '../../util';
|
|
18
|
-
import { html, defrag } from 'typed-dom';
|
|
18
|
+
import { html, defrag } from 'typed-dom/dom';
|
|
19
19
|
import { memoize } from 'spica/memoize';
|
|
20
20
|
import { unshift } from 'spica/array';
|
|
21
21
|
|
|
@@ -46,7 +46,7 @@ export const segment: FigureParser.SegmentParser = block(match(
|
|
|
46
46
|
]),
|
|
47
47
|
]),
|
|
48
48
|
closer),
|
|
49
|
-
([, fence]) => fence.length)));
|
|
49
|
+
([, fence]) => fence.length, [])));
|
|
50
50
|
|
|
51
51
|
export const figure: FigureParser = block(rewrite(segment, fmap(
|
|
52
52
|
convert(source => source.slice(source.search(/[[$]/), source.trimEnd().lastIndexOf('\n')),
|
|
@@ -120,43 +120,44 @@ function attributes(label: string, param: string, content: HTMLElement, caption:
|
|
|
120
120
|
'data-invalid-message': 'Invalid argument',
|
|
121
121
|
} ||
|
|
122
122
|
group === '$' && (type !== 'math' || caption.length > 0) && {
|
|
123
|
-
'data-invalid-type': '
|
|
124
|
-
'data-invalid-message': '
|
|
123
|
+
'data-invalid-type': 'label',
|
|
124
|
+
'data-invalid-message': '"$" label group must be used to math formulas with no caption',
|
|
125
125
|
} ||
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
'data-invalid-
|
|
126
|
+
type === 'media' && {} ||
|
|
127
|
+
['fig', 'figure'].includes(group) && {
|
|
128
|
+
'data-invalid-type': 'label',
|
|
129
|
+
'data-invalid-message': '"fig" and "figure" label groups must be used to media',
|
|
129
130
|
} ||
|
|
130
131
|
group === 'table' && type !== group && {
|
|
131
|
-
'data-invalid-type': '
|
|
132
|
-
'data-invalid-message': '
|
|
132
|
+
'data-invalid-type': 'label',
|
|
133
|
+
'data-invalid-message': '"table" label group must be used to tables',
|
|
133
134
|
} ||
|
|
134
135
|
group === 'list' && type !== group && {
|
|
135
|
-
'data-invalid-type': '
|
|
136
|
-
'data-invalid-message': '
|
|
136
|
+
'data-invalid-type': 'label',
|
|
137
|
+
'data-invalid-message': '"list" label group must be used to lists',
|
|
137
138
|
} ||
|
|
138
139
|
group === 'quote' && type !== group && {
|
|
139
|
-
'data-invalid-type': '
|
|
140
|
-
'data-invalid-message': '
|
|
140
|
+
'data-invalid-type': 'label',
|
|
141
|
+
'data-invalid-message': '"quote" label group must be used to blockquotes',
|
|
141
142
|
} ||
|
|
142
143
|
group === 'text' && type !== group && {
|
|
143
|
-
'data-invalid-type': '
|
|
144
|
-
'data-invalid-message': '
|
|
144
|
+
'data-invalid-type': 'label',
|
|
145
|
+
'data-invalid-message': '"text" label group must be used to codeblocks with no language',
|
|
145
146
|
} ||
|
|
146
147
|
group === 'code' && type !== group && {
|
|
147
|
-
'data-invalid-type': '
|
|
148
|
-
'data-invalid-message': '
|
|
148
|
+
'data-invalid-type': 'label',
|
|
149
|
+
'data-invalid-message': '"code" label group must be used to codeblocks with any language',
|
|
149
150
|
} ||
|
|
150
151
|
group === 'example' && type !== group && {
|
|
151
|
-
'data-invalid-type': '
|
|
152
|
-
'data-invalid-message': '
|
|
152
|
+
'data-invalid-type': 'label',
|
|
153
|
+
'data-invalid-message': '"example" label group must be used to examples',
|
|
153
154
|
} ||
|
|
154
155
|
undefined;
|
|
155
156
|
return {
|
|
156
157
|
'data-type': type,
|
|
157
158
|
'data-label': label,
|
|
158
159
|
'data-group': group,
|
|
159
|
-
...invalid && {
|
|
160
|
+
...invalid?.['data-invalid-type'] && {
|
|
160
161
|
class: 'invalid',
|
|
161
162
|
'data-invalid-syntax': 'figure',
|
|
162
163
|
...invalid,
|
|
@@ -11,7 +11,7 @@ import { codeblock } from '../codeblock';
|
|
|
11
11
|
import { mathblock } from '../mathblock';
|
|
12
12
|
import { blockquote } from '../blockquote';
|
|
13
13
|
import { paragraph } from '../paragraph';
|
|
14
|
-
import { html } from 'typed-dom';
|
|
14
|
+
import { html } from 'typed-dom/dom';
|
|
15
15
|
import { unshift, push } from 'spica/array';
|
|
16
16
|
|
|
17
17
|
import MessageParser = ExtensionParser.MessageParser;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { table } from './table';
|
|
2
2
|
import { some } from '../../../combinator';
|
|
3
3
|
import { inspect } from '../../../debug.test';
|
|
4
|
-
import { html } from 'typed-dom';
|
|
4
|
+
import { html } from 'typed-dom/dom';
|
|
5
5
|
|
|
6
6
|
describe('Unit: parser/block/extension/table', () => {
|
|
7
7
|
describe('table', () => {
|
|
@@ -7,7 +7,7 @@ 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';
|
|
10
|
+
import { html, defrag } from 'typed-dom/dom';
|
|
11
11
|
import { unshift, splice } from 'spica/array';
|
|
12
12
|
|
|
13
13
|
import TableParser = ExtensionParser.TableParser;
|
|
@@ -3,7 +3,7 @@ import { union, some, block, line, validate, focus, rewrite, context, open, trim
|
|
|
3
3
|
import { inline, indexee, indexer } from '../inline';
|
|
4
4
|
import { str } from '../source';
|
|
5
5
|
import { visualize } from '../util';
|
|
6
|
-
import { html, defrag } from 'typed-dom';
|
|
6
|
+
import { html, defrag } from 'typed-dom/dom';
|
|
7
7
|
|
|
8
8
|
export const segment: HeadingParser.SegmentParser = block(validate('#', focus(
|
|
9
9
|
/^#+[^\S\n]+\S[^\n]*(?:\n#+(?!\S)[^\n]*)*(?:$|\n)/,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { HorizontalRuleParser } from '../block';
|
|
2
2
|
import { block, line, focus } from '../../combinator';
|
|
3
|
-
import { html } from 'typed-dom';
|
|
3
|
+
import { html } from 'typed-dom/dom';
|
|
4
4
|
|
|
5
5
|
export const horizontalrule: HorizontalRuleParser = block(line(focus(
|
|
6
6
|
/^-{3,}[^\S\n]*(?:$|\n)/,
|
|
@@ -4,7 +4,7 @@ import { ulist_, fillFirstLine } from './ulist';
|
|
|
4
4
|
import { olist_ } from './olist';
|
|
5
5
|
import { inline } from '../inline';
|
|
6
6
|
import { contentline } from '../source';
|
|
7
|
-
import { html, defrag } from 'typed-dom';
|
|
7
|
+
import { html, defrag } from 'typed-dom/dom';
|
|
8
8
|
|
|
9
9
|
export const ilist: IListParser = lazy(() => block(validate(
|
|
10
10
|
/^[-+*](?=[^\S\n]|\n[^\S\n]*\S)/,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { undefined } from 'spica/global';
|
|
2
2
|
import { MathBlockParser } from '../block';
|
|
3
3
|
import { block, validate, fence, clear, fmap } from '../../combinator';
|
|
4
|
-
import { html } from 'typed-dom';
|
|
4
|
+
import { html } from 'typed-dom/dom';
|
|
5
5
|
|
|
6
6
|
const opener = /^(\${2,})(?!\$)([^\n]*)(?:$|\n)/;
|
|
7
7
|
|
|
@@ -5,7 +5,7 @@ import { checkbox, ulist_, fillFirstLine } from './ulist';
|
|
|
5
5
|
import { ilist_ } from './ilist';
|
|
6
6
|
import { inline, indexee, indexer } from '../inline';
|
|
7
7
|
import { contentline } from '../source';
|
|
8
|
-
import { html, define, defrag } from 'typed-dom';
|
|
8
|
+
import { html, define, defrag } from 'typed-dom/dom';
|
|
9
9
|
import { memoize } from 'spica/memoize';
|
|
10
10
|
import { shift } from 'spica/array';
|
|
11
11
|
|
|
@@ -25,23 +25,23 @@ export const olist: OListParser = lazy(() => block(validate(
|
|
|
25
25
|
export const olist_: OListParser = lazy(() => block(union([
|
|
26
26
|
match(
|
|
27
27
|
new RegExp(`^(?=${openers['.'].source.replace('?:', '')})`),
|
|
28
|
-
memoize(ms => list(type(ms[1]), '.'), ms => type(ms[1]))),
|
|
28
|
+
memoize(ms => list(type(ms[1]), '.'), ms => type(ms[1]).charCodeAt(0) || 0, [])),
|
|
29
29
|
match(
|
|
30
30
|
new RegExp(`^(?=${openers['('].source.replace('?:', '')})`),
|
|
31
|
-
memoize(ms => list(type(ms[1]), '('), ms => type(ms[1]))),
|
|
31
|
+
memoize(ms => list(type(ms[1]), '('), ms => type(ms[1]).charCodeAt(0) || 0, [])),
|
|
32
32
|
])));
|
|
33
33
|
|
|
34
|
-
const list = (type: string,
|
|
34
|
+
const list = (type: string, form: string): OListParser.ListParser => fmap(
|
|
35
35
|
some(creator(union([
|
|
36
36
|
indexee(fmap(fallback(
|
|
37
37
|
inits([
|
|
38
|
-
line(open(heads[
|
|
38
|
+
line(open(heads[form], trim(subsequence([checkbox, trimStart(some(union([indexer, inline])))])), true)),
|
|
39
39
|
indent(union([ulist_, olist_, ilist_])),
|
|
40
40
|
]),
|
|
41
41
|
invalid),
|
|
42
42
|
(ns: [string, ...(HTMLElement | string)[]]) => [html('li', { 'data-marker': ns[0] }, defrag(fillFirstLine(shift(ns)[1])))]), true),
|
|
43
43
|
]))),
|
|
44
|
-
es => [format(html('ol', es), type,
|
|
44
|
+
es => [format(html('ol', es), type, form)]);
|
|
45
45
|
|
|
46
46
|
const heads = {
|
|
47
47
|
'.': focus(
|
|
@@ -107,13 +107,13 @@ function initial(type: string): RegExp {
|
|
|
107
107
|
}
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
-
function format(el: HTMLOListElement, type: string,
|
|
110
|
+
function format(el: HTMLOListElement, type: string, form: string): HTMLOListElement {
|
|
111
111
|
if (el.firstElementChild?.firstElementChild?.classList.contains('checkbox')) {
|
|
112
112
|
el.setAttribute('class', 'checklist');
|
|
113
113
|
}
|
|
114
114
|
define(el, {
|
|
115
115
|
type: type || undefined,
|
|
116
|
-
'data-format':
|
|
116
|
+
'data-format': form === '.' ? undefined : 'paren',
|
|
117
117
|
'data-type': style(type) || undefined,
|
|
118
118
|
});
|
|
119
119
|
const marker = el.firstElementChild?.getAttribute('data-marker')!.match(initial(type))?.[0] ?? '';
|
|
@@ -3,7 +3,7 @@ import { union, some, block, trim, fmap } from '../../combinator';
|
|
|
3
3
|
import { inline } from '../inline';
|
|
4
4
|
import { localize } from '../locale';
|
|
5
5
|
import { visualize } from '../util';
|
|
6
|
-
import { html, defrag } from 'typed-dom';
|
|
6
|
+
import { html, defrag } from 'typed-dom/dom';
|
|
7
7
|
|
|
8
8
|
export const paragraph: ParagraphParser = block(localize(fmap(
|
|
9
9
|
trim(visualize(some(union([inline])))),
|
|
@@ -2,7 +2,7 @@ import { ReplyParser } from '../../block';
|
|
|
2
2
|
import { union, tails, line, validate, focus, creator, reverse, fmap } from '../../../combinator';
|
|
3
3
|
import { anchor } from '../../inline/autolink/anchor';
|
|
4
4
|
import { str } from '../../source';
|
|
5
|
-
import { html, define, defrag } from 'typed-dom';
|
|
5
|
+
import { html, define, defrag } from 'typed-dom/dom';
|
|
6
6
|
|
|
7
7
|
export const cite: ReplyParser.CiteParser = creator(line(fmap(validate(
|
|
8
8
|
'>>',
|
|
@@ -4,7 +4,7 @@ import { union, some, block, line, validate, rewrite, creator, lazy, fmap } from
|
|
|
4
4
|
import { math } from '../../inline/math';
|
|
5
5
|
import { str, anyline } from '../../source';
|
|
6
6
|
import { autolink } from '../../autolink';
|
|
7
|
-
import { html, defrag } from 'typed-dom';
|
|
7
|
+
import { html, defrag } from 'typed-dom/dom';
|
|
8
8
|
|
|
9
9
|
export const syntax = /^>+(?=[^\S\n])|^>(?=[^\s>])|^>+(?=[^\s>])(?![0-9a-z]+(?:-[0-9a-z]+)*(?![0-9A-Za-z@#:]))/;
|
|
10
10
|
|
|
@@ -6,7 +6,7 @@ import { inline } from '../inline';
|
|
|
6
6
|
import { anyline } from '../source';
|
|
7
7
|
import { localize } from '../locale';
|
|
8
8
|
import { visualize } from '../util';
|
|
9
|
-
import { html, defrag } from 'typed-dom';
|
|
9
|
+
import { html, defrag } from 'typed-dom/dom';
|
|
10
10
|
import { push, pop } from 'spica/array';
|
|
11
11
|
|
|
12
12
|
/*
|
|
@@ -2,7 +2,7 @@ import { TableParser } from '../block';
|
|
|
2
2
|
import { union, sequence, some, block, line, validate, focus, rewrite, creator, surround, open, fallback, lazy, fmap } from '../../combinator';
|
|
3
3
|
import { inline } from '../inline';
|
|
4
4
|
import { contentline } from '../source';
|
|
5
|
-
import { html, defrag } from 'typed-dom';
|
|
5
|
+
import { html, defrag } from 'typed-dom/dom';
|
|
6
6
|
import { push } from 'spica/array';
|
|
7
7
|
|
|
8
8
|
import RowParser = TableParser.RowParser;
|
|
@@ -3,7 +3,7 @@ import { union, inits, subsequence, some, block, line, validate, indent, focus,
|
|
|
3
3
|
import { olist_ } from './olist';
|
|
4
4
|
import { ilist_ } from './ilist';
|
|
5
5
|
import { inline, indexer, indexee } from '../inline';
|
|
6
|
-
import { html, defrag } from 'typed-dom';
|
|
6
|
+
import { html, defrag } from 'typed-dom/dom';
|
|
7
7
|
import { unshift } from 'spica/array';
|
|
8
8
|
import { contentline } from '../source';
|
|
9
9
|
|
package/src/parser/block.ts
CHANGED
|
@@ -15,7 +15,7 @@ import { mathblock } from './block/mathblock';
|
|
|
15
15
|
import { extension } from './block/extension';
|
|
16
16
|
import { reply } from './block/reply';
|
|
17
17
|
import { paragraph } from './block/paragraph';
|
|
18
|
-
import { html } from 'typed-dom';
|
|
18
|
+
import { html } from 'typed-dom/dom';
|
|
19
19
|
import { rnd0Z } from 'spica/random';
|
|
20
20
|
|
|
21
21
|
export import BlockParser = MarkdownParser.BlockParser;
|
package/src/parser/header.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { union, inits, some, block, line, validate, focus, rewrite, guard, clear
|
|
|
3
3
|
import { segment } from './segment';
|
|
4
4
|
import { str } from './source';
|
|
5
5
|
import { normalize } from './api/normalize';
|
|
6
|
-
import { html, defrag } from 'typed-dom';
|
|
6
|
+
import { html, defrag } from 'typed-dom/dom';
|
|
7
7
|
|
|
8
8
|
export const header: MarkdownParser.HeaderParser = lazy(() => validate(
|
|
9
9
|
/^---+[^\S\v\f\r\n]*\r?\n[^\S\n]*(?=\S)/,
|
|
@@ -3,7 +3,7 @@ import { AnnotationParser } from '../inline';
|
|
|
3
3
|
import { union, some, validate, guard, context, creator, surround, lazy, fmap } from '../../combinator';
|
|
4
4
|
import { inline } from '../inline';
|
|
5
5
|
import { startLoose, trimSpaceStart, trimNodeEnd } from '../util';
|
|
6
|
-
import { html, defrag } from 'typed-dom';
|
|
6
|
+
import { html, defrag } from 'typed-dom/dom';
|
|
7
7
|
|
|
8
8
|
export const annotation: AnnotationParser = lazy(() => creator(validate('((', '))', '\n', fmap(surround(
|
|
9
9
|
'((',
|
|
@@ -19,7 +19,7 @@ export const annotation: AnnotationParser = lazy(() => creator(validate('((', ')
|
|
|
19
19
|
//label: true,
|
|
20
20
|
//link: true,
|
|
21
21
|
//autolink: true,
|
|
22
|
-
}}, state: undefined },
|
|
22
|
+
}}, state: undefined, delimiters: undefined },
|
|
23
23
|
trimSpaceStart(union([some(inline, ')', /^\\?\n/)]))))),
|
|
24
24
|
'))'),
|
|
25
25
|
ns => [html('sup', { class: 'annotation' }, trimNodeEnd(defrag(ns)))]))));
|
|
@@ -2,7 +2,7 @@ import { AutolinkParser } from '../../inline';
|
|
|
2
2
|
import { union, tails, verify, rewrite, context, open, convert, fmap, lazy } from '../../../combinator';
|
|
3
3
|
import { link } from '../link';
|
|
4
4
|
import { str } from '../../source';
|
|
5
|
-
import { define } from 'typed-dom';
|
|
5
|
+
import { define } from 'typed-dom/dom';
|
|
6
6
|
|
|
7
7
|
// https://example/@user must be a user page or a redirect page going there.
|
|
8
8
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { AutolinkParser } from '../../inline';
|
|
2
2
|
import { union, validate, focus, context, convert, fmap, lazy } from '../../../combinator';
|
|
3
3
|
import { link } from '../link';
|
|
4
|
-
import { define } from 'typed-dom';
|
|
4
|
+
import { define } from 'typed-dom/dom';
|
|
5
5
|
|
|
6
6
|
// Timeline(pseudonym): user/tid
|
|
7
7
|
// Thread(anonymous): cid
|