securemark 0.261.0 → 0.262.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/dist/index.js +1117 -646
- package/markdown.d.ts +0 -11
- package/package.json +9 -9
- package/src/combinator/data/parser/context/memo.ts +1 -1
- package/src/combinator/data/parser/inits.ts +1 -1
- package/src/combinator/data/parser/sequence.ts +1 -1
- package/src/debug.test.ts +3 -3
- package/src/parser/api/bind.ts +2 -2
- package/src/parser/api/parse.test.ts +1 -1
- package/src/parser/api/parse.ts +1 -1
- package/src/parser/block/blockquote.test.ts +31 -31
- package/src/parser/block/blockquote.ts +1 -1
- package/src/parser/block/dlist.ts +1 -1
- package/src/parser/block/extension/aside.test.ts +3 -3
- package/src/parser/block/extension/aside.ts +1 -0
- package/src/parser/block/extension/example.test.ts +11 -11
- package/src/parser/block/extension/example.ts +1 -1
- package/src/parser/block/extension/fig.test.ts +5 -5
- package/src/parser/block/extension/figure.test.ts +2 -2
- package/src/parser/block/extension/figure.ts +1 -1
- package/src/parser/block/extension/message.ts +1 -1
- package/src/parser/block/extension/table.ts +1 -1
- package/src/parser/block/olist.ts +5 -7
- package/src/parser/block/reply.ts +1 -1
- package/src/parser/block/table.ts +8 -8
- package/src/parser/block/ulist.ts +1 -1
- package/src/parser/block.ts +1 -1
- package/src/parser/inline/bracket.ts +1 -1
- package/src/parser/inline/comment.ts +1 -1
- package/src/parser/inline/deletion.ts +2 -2
- package/src/parser/inline/emphasis.ts +3 -3
- package/src/parser/inline/extension/indexee.ts +9 -8
- package/src/parser/inline/extension/placeholder.ts +1 -1
- package/src/parser/inline/html.ts +1 -1
- package/src/parser/inline/insertion.ts +2 -2
- package/src/parser/inline/link.ts +1 -1
- package/src/parser/inline/mark.ts +2 -2
- package/src/parser/inline/media.ts +1 -1
- package/src/parser/inline/ruby.ts +1 -1
- package/src/parser/inline/strong.ts +3 -3
- package/src/parser/inline/template.ts +1 -1
- package/src/parser/inline.ts +0 -3
- package/src/parser/locale/ja.ts +1 -1
- package/src/parser/locale.test.ts +1 -1
- package/src/parser/locale.ts +5 -4
- package/src/parser/processor/figure.test.ts +3 -3
- package/src/parser/processor/figure.ts +10 -8
- package/src/parser/processor/footnote.test.ts +2 -2
- package/src/parser/processor/footnote.ts +17 -12
- package/src/parser/source/str.ts +4 -2
- package/src/parser/source/text.ts +2 -2
- package/src/renderer/render.ts +3 -3
- package/src/util/info.ts +7 -5
- package/src/util/quote.ts +14 -12
- package/src/util/toc.ts +14 -8
- package/src/parser/inline/escape.ts +0 -21
|
@@ -3,9 +3,9 @@ import { union, some, syntax, validate, surround, open, close, match, lazy } fro
|
|
|
3
3
|
import { inline } from '../inline';
|
|
4
4
|
import { text, str } from '../source';
|
|
5
5
|
import { Syntax, State } from '../context';
|
|
6
|
-
import { html, defrag } from 'typed-dom/dom';
|
|
7
6
|
import { memoize } from 'spica/memoize';
|
|
8
7
|
import { unshift, push } from 'spica/array';
|
|
8
|
+
import { html, defrag } from 'typed-dom/dom';
|
|
9
9
|
|
|
10
10
|
export const comment: CommentParser = lazy(() => validate('[%', syntax(Syntax.none, 4, 1, State.none, match(
|
|
11
11
|
/^\[(%+)\s/,
|
|
@@ -4,11 +4,11 @@ import { inline } from '../inline';
|
|
|
4
4
|
import { str } from '../source';
|
|
5
5
|
import { Syntax, State } from '../context';
|
|
6
6
|
import { blankWith } from '../visibility';
|
|
7
|
-
import { html, defrag } from 'typed-dom/dom';
|
|
8
7
|
import { unshift } from 'spica/array';
|
|
8
|
+
import { html, defrag } from 'typed-dom/dom';
|
|
9
9
|
|
|
10
10
|
export const deletion: DeletionParser = lazy(() => surround(
|
|
11
|
-
str('~~'),
|
|
11
|
+
str('~~', '~'),
|
|
12
12
|
syntax(Syntax.none, 1, 1, State.none,
|
|
13
13
|
some(union([
|
|
14
14
|
some(inline, blankWith('\n', '~~')),
|
|
@@ -4,16 +4,16 @@ import { inline } from '../inline';
|
|
|
4
4
|
import { str } from '../source';
|
|
5
5
|
import { Syntax, State } from '../context';
|
|
6
6
|
import { startTight, blankWith } from '../visibility';
|
|
7
|
-
import { html, defrag } from 'typed-dom/dom';
|
|
8
7
|
import { unshift } from 'spica/array';
|
|
8
|
+
import { html, defrag } from 'typed-dom/dom';
|
|
9
9
|
|
|
10
10
|
export const emphasis: EmphasisParser = lazy(() => surround(
|
|
11
|
-
str('_'),
|
|
11
|
+
str('_', '_'),
|
|
12
12
|
syntax(Syntax.none, 1, 1, State.none,
|
|
13
13
|
startTight(some(union([
|
|
14
14
|
some(inline, blankWith('_')),
|
|
15
15
|
open(some(inline, '_'), emphasis),
|
|
16
|
-
]))
|
|
16
|
+
])))),
|
|
17
17
|
str('_'), false,
|
|
18
18
|
([, bs], rest) => [[html('em', defrag(bs))], rest],
|
|
19
19
|
([as, bs], rest) => [unshift(as, bs), rest]));
|
|
@@ -3,7 +3,7 @@ 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 {
|
|
6
|
+
import { querySelectorAll } from 'typed-dom/query';
|
|
7
7
|
|
|
8
8
|
export function indexee<P extends Parser<unknown, MarkdownParser.Context>>(parser: P, optional?: boolean): P;
|
|
9
9
|
export function indexee(parser: Parser<HTMLElement, MarkdownParser.Context>, optional?: boolean): Parser<HTMLElement> {
|
|
@@ -28,32 +28,33 @@ export function text(source: HTMLElement | DocumentFragment, optional = false):
|
|
|
28
28
|
if (index) return index;
|
|
29
29
|
assert(!source.querySelector('.annotation, br'));
|
|
30
30
|
const target = source.cloneNode(true) as typeof source;
|
|
31
|
-
|
|
31
|
+
for (let es = querySelectorAll(target, 'code[data-src], .math[data-src], .comment, rt, rp, .reference, .checkbox, ul, ol'), i = 0; i < es.length; ++i) {
|
|
32
|
+
const el = es[i];
|
|
32
33
|
switch (el.tagName) {
|
|
33
34
|
case 'CODE':
|
|
34
35
|
define(el, el.getAttribute('data-src')!);
|
|
35
|
-
|
|
36
|
+
continue;
|
|
36
37
|
case 'RT':
|
|
37
38
|
case 'RP':
|
|
38
39
|
case 'UL':
|
|
39
40
|
case 'OL':
|
|
40
41
|
el.remove();
|
|
41
|
-
|
|
42
|
+
continue;
|
|
42
43
|
}
|
|
43
44
|
switch (el.className) {
|
|
44
45
|
case 'math':
|
|
45
46
|
define(el, el.getAttribute('data-src')!);
|
|
46
|
-
|
|
47
|
+
continue;
|
|
47
48
|
case 'comment':
|
|
48
49
|
case 'checkbox':
|
|
49
50
|
el.remove();
|
|
50
|
-
|
|
51
|
+
continue;
|
|
51
52
|
case 'reference':
|
|
52
53
|
assert(el.firstElementChild?.hasAttribute('hidden'));
|
|
53
54
|
el.firstChild!.remove();
|
|
54
|
-
|
|
55
|
+
continue;
|
|
55
56
|
}
|
|
56
|
-
}
|
|
57
|
+
}
|
|
57
58
|
// Better:
|
|
58
59
|
//return target.innerText;
|
|
59
60
|
return target.textContent!;
|
|
@@ -4,8 +4,8 @@ import { inline } from '../../inline';
|
|
|
4
4
|
import { str } from '../../source';
|
|
5
5
|
import { Syntax, State } from '../../context';
|
|
6
6
|
import { startTight } from '../../visibility';
|
|
7
|
-
import { html, defrag } from 'typed-dom/dom';
|
|
8
7
|
import { unshift } from 'spica/array';
|
|
8
|
+
import { html, defrag } from 'typed-dom/dom';
|
|
9
9
|
|
|
10
10
|
// Don't use the symbols already used: !#$%@&*+~=
|
|
11
11
|
|
|
@@ -5,10 +5,10 @@ import { inline } from '../inline';
|
|
|
5
5
|
import { str } from '../source';
|
|
6
6
|
import { Syntax, State } from '../context';
|
|
7
7
|
import { isStartLooseNodes, blankWith } from '../visibility';
|
|
8
|
-
import { html as h, defrag } from 'typed-dom/dom';
|
|
9
8
|
import { memoize } from 'spica/memoize';
|
|
10
9
|
import { Cache } from 'spica/cache';
|
|
11
10
|
import { unshift, push, splice } from 'spica/array';
|
|
11
|
+
import { html as h, defrag } from 'typed-dom/dom';
|
|
12
12
|
|
|
13
13
|
const tags = Object.freeze(['bdo', 'bdi']);
|
|
14
14
|
const attrspecs = {
|
|
@@ -4,11 +4,11 @@ import { inline } from '../inline';
|
|
|
4
4
|
import { str } from '../source';
|
|
5
5
|
import { Syntax, State } from '../context';
|
|
6
6
|
import { blankWith } from '../visibility';
|
|
7
|
-
import { html, defrag } from 'typed-dom/dom';
|
|
8
7
|
import { unshift } from 'spica/array';
|
|
8
|
+
import { html, defrag } from 'typed-dom/dom';
|
|
9
9
|
|
|
10
10
|
export const insertion: InsertionParser = lazy(() => surround(
|
|
11
|
-
str('++'),
|
|
11
|
+
str('++', '+'),
|
|
12
12
|
syntax(Syntax.none, 1, 1, State.none,
|
|
13
13
|
some(union([
|
|
14
14
|
some(inline, blankWith('\n', '++')),
|
|
@@ -10,8 +10,8 @@ import { unescsource, str } from '../source';
|
|
|
10
10
|
import { Syntax, State } from '../context';
|
|
11
11
|
import { trimNode } from '../visibility';
|
|
12
12
|
import { stringify } from '../util';
|
|
13
|
-
import { html, define, defrag } from 'typed-dom/dom';
|
|
14
13
|
import { ReadonlyURL } from 'spica/url';
|
|
14
|
+
import { html, define, defrag } from 'typed-dom/dom';
|
|
15
15
|
|
|
16
16
|
const optspec = {
|
|
17
17
|
rel: ['nofollow'],
|
|
@@ -4,11 +4,11 @@ import { inline } from '../inline';
|
|
|
4
4
|
import { str } from '../source';
|
|
5
5
|
import { startTight, blankWith } from '../visibility';
|
|
6
6
|
import { Syntax, State } from '../context';
|
|
7
|
-
import { html, defrag } from 'typed-dom/dom';
|
|
8
7
|
import { unshift } from 'spica/array';
|
|
8
|
+
import { html, defrag } from 'typed-dom/dom';
|
|
9
9
|
|
|
10
10
|
export const mark: MarkParser = lazy(() => surround(
|
|
11
|
-
str('=='),
|
|
11
|
+
str('==', '='),
|
|
12
12
|
syntax(Syntax.none, 1, 1, State.none,
|
|
13
13
|
startTight(some(union([
|
|
14
14
|
some(inline, blankWith('==')),
|
|
@@ -6,9 +6,9 @@ import { attributes } from './html';
|
|
|
6
6
|
import { unsafehtmlentity } from './htmlentity';
|
|
7
7
|
import { txt, str } from '../source';
|
|
8
8
|
import { Syntax, State } from '../context';
|
|
9
|
-
import { html, define } from 'typed-dom/dom';
|
|
10
9
|
import { ReadonlyURL } from 'spica/url';
|
|
11
10
|
import { unshift, push } from 'spica/array';
|
|
11
|
+
import { html, define } from 'typed-dom/dom';
|
|
12
12
|
|
|
13
13
|
const optspec = {
|
|
14
14
|
'width': [],
|
|
@@ -6,8 +6,8 @@ import { unsafehtmlentity } from './htmlentity';
|
|
|
6
6
|
import { text as txt, str } from '../source';
|
|
7
7
|
import { Syntax, State } from '../context';
|
|
8
8
|
import { isStartTightNodes } from '../visibility';
|
|
9
|
-
import { html, defrag } from 'typed-dom/dom';
|
|
10
9
|
import { unshift, push } from 'spica/array';
|
|
10
|
+
import { html, defrag } from 'typed-dom/dom';
|
|
11
11
|
|
|
12
12
|
export const ruby: RubyParser = lazy(() => validate('[', syntax(Syntax.ruby, 2, 1, State.all, fmap(verify(fmap(
|
|
13
13
|
sequence([
|
|
@@ -4,16 +4,16 @@ import { inline } from '../inline';
|
|
|
4
4
|
import { str } from '../source';
|
|
5
5
|
import { Syntax, State } from '../context';
|
|
6
6
|
import { startTight, blankWith } from '../visibility';
|
|
7
|
-
import { html, defrag } from 'typed-dom/dom';
|
|
8
7
|
import { unshift } from 'spica/array';
|
|
8
|
+
import { html, defrag } from 'typed-dom/dom';
|
|
9
9
|
|
|
10
10
|
export const strong: StrongParser = lazy(() => surround(
|
|
11
|
-
str('*'),
|
|
11
|
+
str('*', '*'),
|
|
12
12
|
syntax(Syntax.none, 1, 1, State.none,
|
|
13
13
|
startTight(some(union([
|
|
14
14
|
some(inline, blankWith('*')),
|
|
15
15
|
open(some(inline, '*'), strong),
|
|
16
|
-
]))
|
|
16
|
+
])))),
|
|
17
17
|
str('*'), false,
|
|
18
18
|
([, bs], rest) => [[html('strong', defrag(bs))], rest],
|
|
19
19
|
([as, bs], rest) => [unshift(as, bs), rest]));
|
|
@@ -3,8 +3,8 @@ import { TemplateParser } from '../inline';
|
|
|
3
3
|
import { union, some, syntax, creation, precedence, surround, lazy } from '../../combinator';
|
|
4
4
|
import { escsource, str } from '../source';
|
|
5
5
|
import { Syntax, State } from '../context';
|
|
6
|
-
import { html } from 'typed-dom/dom';
|
|
7
6
|
import { unshift } from 'spica/array';
|
|
7
|
+
import { html } from 'typed-dom/dom';
|
|
8
8
|
|
|
9
9
|
export const template: TemplateParser = lazy(() => surround(
|
|
10
10
|
'{{', syntax(Syntax.none, 2, 1, State.all, some(union([bracket, escsource]), '}')), '}}', true,
|
package/src/parser/inline.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { MarkdownParser } from '../../markdown';
|
|
2
2
|
import { union } from '../combinator';
|
|
3
|
-
import { escape } from './inline/escape';
|
|
4
3
|
import { annotation } from './inline/annotation';
|
|
5
4
|
import { reference } from './inline/reference';
|
|
6
5
|
import { template } from './inline/template';
|
|
@@ -24,7 +23,6 @@ import { bracket } from './inline/bracket';
|
|
|
24
23
|
import { text } from './source';
|
|
25
24
|
|
|
26
25
|
export import InlineParser = MarkdownParser.InlineParser;
|
|
27
|
-
export import EscapeParser = InlineParser.EscapeParser;
|
|
28
26
|
export import AnnotationParser = InlineParser.AnnotationParser;
|
|
29
27
|
export import ReferenceParser = InlineParser.ReferenceParser;
|
|
30
28
|
export import TemplateParser = InlineParser.TemplateParser;
|
|
@@ -48,7 +46,6 @@ export import AutolinkParser = InlineParser.AutolinkParser;
|
|
|
48
46
|
export import BracketParser = InlineParser.BracketParser;
|
|
49
47
|
|
|
50
48
|
export const inline: InlineParser = union([
|
|
51
|
-
escape,
|
|
52
49
|
annotation,
|
|
53
50
|
reference,
|
|
54
51
|
template,
|
package/src/parser/locale/ja.ts
CHANGED
|
@@ -10,7 +10,7 @@ describe('Unit: parser/locale', () => {
|
|
|
10
10
|
assert.deepStrictEqual(inspect(parser('。\\\n0')), [['<p>。<span class="linebreak"></span>0</p>'], '']);
|
|
11
11
|
assert.deepStrictEqual(inspect(parser('。 \\\n0')), [['<p>。<span class="linebreak"></span>0</p>'], '']);
|
|
12
12
|
assert.deepStrictEqual(inspect(parser('_。_\\\n0')), [['<p><em>。</em><span class="linebreak"></span>0</p>'], '']);
|
|
13
|
-
assert.deepStrictEqual(inspect(parser('!> 。\\\n0')), [['<blockquote><section><p>。<span class="linebreak"></span>0</p><ol class="references"></ol></section></blockquote>'], '']);
|
|
13
|
+
assert.deepStrictEqual(inspect(parser('!> 。\\\n0')), [['<blockquote><section><p>。<span class="linebreak"></span>0</p><h2>References</h2><ol class="references"></ol></section></blockquote>'], '']);
|
|
14
14
|
assert.deepStrictEqual(inspect(parser('[。](a)\\\n0')), [['<p><ruby>。<rp>(</rp><rt>a</rt><rp>)</rp></ruby><span class="linebreak"></span>0</p>'], '']);
|
|
15
15
|
assert.deepStrictEqual(inspect(parser('[。 ](a )\\\n0')), [['<p><ruby>。<rp>(</rp><rt>a</rt><rp>)</rp></ruby><span class="linebreak"></span>0</p>'], '']);
|
|
16
16
|
assert.deepStrictEqual(inspect(parser('。<wbr>\\\n0')), [['<p>。<wbr><span class="linebreak"></span>0</p>'], '']);
|
package/src/parser/locale.ts
CHANGED
|
@@ -2,7 +2,7 @@ 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 {
|
|
5
|
+
import { querySelectorAll } from 'typed-dom/query';
|
|
6
6
|
|
|
7
7
|
export function localize<P extends Parser<HTMLElement | string>>(parser: P): P;
|
|
8
8
|
export function localize(parser: Parser<HTMLElement | string>): Parser<HTMLElement | string> {
|
|
@@ -11,11 +11,12 @@ export function localize(parser: Parser<HTMLElement | string>): Parser<HTMLEleme
|
|
|
11
11
|
const el = ns.length === 1 && typeof ns[0] === 'object'
|
|
12
12
|
? ns[0]
|
|
13
13
|
: html('div', ns);
|
|
14
|
-
|
|
14
|
+
for (let es = querySelectorAll(el, '.linebreak:not(:empty)'), i = 0; i < es.length; ++i) {
|
|
15
|
+
const el = es[i];
|
|
15
16
|
assert(el.firstChild!.textContent === ' ');
|
|
16
|
-
if (!check(el))
|
|
17
|
+
if (!check(el)) continue;
|
|
17
18
|
el.firstChild!.remove();
|
|
18
|
-
}
|
|
19
|
+
}
|
|
19
20
|
return ns;
|
|
20
21
|
});
|
|
21
22
|
}
|
|
@@ -117,8 +117,8 @@ describe('Unit: parser/processor/figure', () => {
|
|
|
117
117
|
assert.deepStrictEqual(
|
|
118
118
|
[...target.children].map(el => el.outerHTML),
|
|
119
119
|
[
|
|
120
|
-
'<blockquote><blockquote><section><figure data-type="quote" data-label="test-a" data-group="test" data-number="1"><figcaption><span class="figindex">Test 1. </span><span class="figtext"></span></figcaption><div><blockquote></blockquote></div></figure><ol class="references"></ol></section></blockquote><section><figure data-type="quote" data-label="test-a" data-group="test" data-number="1"><figcaption><span class="figindex">Test 1. </span><span class="figtext"></span></figcaption><div><blockquote></blockquote></div></figure><ol class="references"></ol></section></blockquote>',
|
|
121
|
-
'<aside class="example" data-type="markdown"><pre translate="no">~~~figure $test-a\n> \n\n~~~\n\n$test-a</pre><hr><section><figure data-type="quote" data-label="test-a" data-group="test" data-number="1"><figcaption><span class="figindex">Test 1. </span><span class="figtext"></span></figcaption><div><blockquote></blockquote></div></figure><p><a class="label disabled" data-label="test-a">Test 1</a></p><ol class="references"></ol></section></aside>',
|
|
120
|
+
'<blockquote><blockquote><section><figure data-type="quote" data-label="test-a" data-group="test" data-number="1"><figcaption><span class="figindex">Test 1. </span><span class="figtext"></span></figcaption><div><blockquote></blockquote></div></figure><h2>References</h2><ol class="references"></ol></section></blockquote><section><figure data-type="quote" data-label="test-a" data-group="test" data-number="1"><figcaption><span class="figindex">Test 1. </span><span class="figtext"></span></figcaption><div><blockquote></blockquote></div></figure><h2>References</h2><ol class="references"></ol></section></blockquote>',
|
|
121
|
+
'<aside class="example" data-type="markdown"><pre translate="no">~~~figure $test-a\n> \n\n~~~\n\n$test-a</pre><hr><section><figure data-type="quote" data-label="test-a" data-group="test" data-number="1"><figcaption><span class="figindex">Test 1. </span><span class="figtext"></span></figcaption><div><blockquote></blockquote></div></figure><p><a class="label disabled" data-label="test-a">Test 1</a></p><h2>References</h2><ol class="references"></ol></section></aside>',
|
|
122
122
|
'<figure data-type="quote" data-label="test-b" data-group="test" data-number="1" id="label:test-b"><figcaption><span class="figindex">Test 1. </span><span class="figtext"></span></figcaption><div><blockquote></blockquote></div></figure>',
|
|
123
123
|
'<figure data-type="quote" data-label="test-a" data-group="test" data-number="2" id="label:test-a"><figcaption><span class="figindex">Test 2. </span><span class="figtext"></span></figcaption><div><blockquote></blockquote></div></figure>',
|
|
124
124
|
]);
|
|
@@ -173,7 +173,7 @@ describe('Unit: parser/processor/figure', () => {
|
|
|
173
173
|
'<h2 id="index:0">0</h2>',
|
|
174
174
|
'<figure data-type="quote" data-label="test-1" data-group="test" data-number="1" id="label:test-1"><figcaption><span class="figindex">Test 1. </span><span class="figtext"></span></figcaption><div><blockquote></blockquote></div></figure>',
|
|
175
175
|
'<h2 id="index:0">0</h2>',
|
|
176
|
-
'<blockquote><section><h2>0</h2><ol class="references"></ol></section></blockquote>',
|
|
176
|
+
'<blockquote><section><h2>0</h2><h2>References</h2><ol class="references"></ol></section></blockquote>',
|
|
177
177
|
'<figure data-type="quote" data-label="test-b" data-group="test" data-number="2.1" id="label:test-b"><figcaption><span class="figindex">Test 2.1. </span><span class="figtext"></span></figcaption><div><blockquote></blockquote></div></figure>',
|
|
178
178
|
'<h2 id="index:0">0</h2>',
|
|
179
179
|
'<figure data-label="$-0.0.0" data-group="$" class="invalid" data-invalid-syntax="figure" data-invalid-type="argument" data-invalid-message="Base index must be $-x.0 format"></figure>',
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
import { Infinity, Set, Map } from 'spica/global';
|
|
2
2
|
import { number as calculate, isFixed } from '../inline/extension/label';
|
|
3
|
-
import { define } from 'typed-dom/dom';
|
|
4
3
|
import { MultiMap } from 'spica/multimap';
|
|
5
4
|
import { push } from 'spica/array';
|
|
5
|
+
import { define } from 'typed-dom/dom';
|
|
6
|
+
import { querySelectorAll } from 'typed-dom/query';
|
|
6
7
|
|
|
7
8
|
export function* figure(
|
|
8
9
|
target: ParentNode & Node,
|
|
9
10
|
footnotes?: { readonly references: HTMLOListElement; },
|
|
10
11
|
opts: { readonly id?: string; } = {},
|
|
11
12
|
): Generator<HTMLAnchorElement | undefined, undefined, undefined> {
|
|
12
|
-
const refs = new MultiMap<string, HTMLAnchorElement>(push(
|
|
13
|
-
|
|
14
|
-
footnotes
|
|
13
|
+
const refs = new MultiMap<string, HTMLAnchorElement>(push(
|
|
14
|
+
querySelectorAll(target, 'a.label:not(.disabled)[data-label]'),
|
|
15
|
+
footnotes && querySelectorAll(footnotes.references, 'a.label:not(.disabled)') || [])
|
|
15
16
|
.map(el => [el.getAttribute('data-label')!, el]));
|
|
16
17
|
const labels = new Set<string>();
|
|
17
18
|
const numbers = new Map<string, string>();
|
|
@@ -19,10 +20,10 @@ export function* figure(
|
|
|
19
20
|
let bases: readonly string[] = base.split('.');
|
|
20
21
|
let index: readonly string[] = bases;
|
|
21
22
|
// Bug: Firefox
|
|
22
|
-
//for (let defs =
|
|
23
|
+
//for (let defs = querySelectorAll(target, ':scope > figure[data-label], :scope > h1, :scope > h2'), len = defs.length, i = 0; i < len; ++i) {
|
|
23
24
|
for (
|
|
24
|
-
let defs =
|
|
25
|
-
|
|
25
|
+
let defs = querySelectorAll(target, 'figure[data-label], h1, h2'),
|
|
26
|
+
len = defs.length, i = 0; i < len; ++i) {
|
|
26
27
|
yield;
|
|
27
28
|
const def = defs[i];
|
|
28
29
|
if (def.parentNode !== target) continue;
|
|
@@ -141,7 +142,8 @@ export function* figure(
|
|
|
141
142
|
}
|
|
142
143
|
labels.add(label);
|
|
143
144
|
opts.id !== '' && def.setAttribute('id', `label:${opts.id ? `${opts.id}:` : ''}${label}`);
|
|
144
|
-
for (
|
|
145
|
+
for (let rs = refs.take(label, Infinity), i = 0; i < rs.length; ++i) {
|
|
146
|
+
const ref = rs[i];
|
|
145
147
|
if (ref.getAttribute('data-invalid-message') === messages.reference) {
|
|
146
148
|
define(ref, {
|
|
147
149
|
class: void ref.classList.remove('invalid'),
|
|
@@ -151,8 +151,8 @@ describe('Unit: parser/processor/footnote', () => {
|
|
|
151
151
|
assert.deepStrictEqual(
|
|
152
152
|
[...target.children].map(el => el.outerHTML),
|
|
153
153
|
[
|
|
154
|
-
'<blockquote><blockquote><section><p><sup class="annotation disabled" title="a"><span hidden="">a</span><a>*1</a></sup></p><ol class="annotations"><li data-marker="*1">a<sup><a>^1</a></sup></li></ol><ol class="references"></ol></section></blockquote><section><p><sup class="annotation disabled" title="a"><span hidden="">a</span><a>*1</a></sup><br>~~~</p><ol class="annotations"><li data-marker="*1">a<sup><a>^1</a></sup></li></ol><ol class="references"></ol></section></blockquote>',
|
|
155
|
-
'<aside class="example" data-type="markdown"><pre translate="no">((a))</pre><hr><section><p><sup class="annotation disabled" title="a"><span hidden="">a</span><a>*1</a></sup></p><ol class="annotations"><li data-marker="*1">a<sup><a>^1</a></sup></li></ol><ol class="references"></ol></section></aside>',
|
|
154
|
+
'<blockquote><blockquote><section><p><sup class="annotation disabled" title="a"><span hidden="">a</span><a>*1</a></sup></p><ol class="annotations"><li data-marker="*1">a<sup><a>^1</a></sup></li></ol><h2>References</h2><ol class="references"></ol></section></blockquote><section><p><sup class="annotation disabled" title="a"><span hidden="">a</span><a>*1</a></sup><br>~~~</p><ol class="annotations"><li data-marker="*1">a<sup><a>^1</a></sup></li></ol><h2>References</h2><ol class="references"></ol></section></blockquote>',
|
|
155
|
+
'<aside class="example" data-type="markdown"><pre translate="no">((a))</pre><hr><section><p><sup class="annotation disabled" title="a"><span hidden="">a</span><a>*1</a></sup></p><ol class="annotations"><li data-marker="*1">a<sup><a>^1</a></sup></li></ol><h2>References</h2><ol class="references"></ol></section></aside>',
|
|
156
156
|
'<p><sup class="annotation" id="annotation:ref:1" title="a"><span hidden="">a</span><a href="#annotation:def:1">*1</a></sup></p>',
|
|
157
157
|
]);
|
|
158
158
|
assert.deepStrictEqual(
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { undefined, Infinity, Map, Node } from 'spica/global';
|
|
2
2
|
import { text } from '../inline/extension/indexee';
|
|
3
|
-
import { frag, html, define } from 'typed-dom/dom';
|
|
4
3
|
import { MultiMap } from 'spica/multimap';
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
4
|
+
import { frag, html, define } from 'typed-dom/dom';
|
|
5
|
+
import { querySelectorAll } from 'typed-dom/query';
|
|
7
6
|
|
|
8
7
|
export function* footnote(
|
|
9
8
|
target: ParentNode & Node,
|
|
@@ -12,8 +11,11 @@ export function* footnote(
|
|
|
12
11
|
bottom: Node | null = null,
|
|
13
12
|
): Generator<HTMLAnchorElement | HTMLLIElement | undefined, undefined, undefined> {
|
|
14
13
|
// Bug: Firefox
|
|
15
|
-
//
|
|
16
|
-
|
|
14
|
+
//querySelectorAll(target, `:scope > .annotations`).forEach(el => el.remove());
|
|
15
|
+
for (let es = querySelectorAll(target, `.annotations`), i = 0; i < es.length; ++i) {
|
|
16
|
+
const el = es[i];
|
|
17
|
+
el.parentNode === target && el.remove();
|
|
18
|
+
}
|
|
17
19
|
yield* reference(target, footnotes?.references, opts, bottom);
|
|
18
20
|
yield* annotation(target, footnotes?.annotations, opts, bottom);
|
|
19
21
|
return;
|
|
@@ -40,16 +42,18 @@ function build(
|
|
|
40
42
|
const buffer = new MultiMap<string, HTMLElement>();
|
|
41
43
|
const titles = new Map<string, string>();
|
|
42
44
|
// Bug: Firefox
|
|
43
|
-
//const splitters = push([],
|
|
44
|
-
const splitters =
|
|
45
|
-
|
|
46
|
-
|
|
45
|
+
//const splitters = push([], querySelectorAll(target, `:scope > :is(${splitter ?? '_'})`));
|
|
46
|
+
const splitters: Element[] = [];
|
|
47
|
+
for (let es = querySelectorAll(target, splitter ?? '_'), i = 0; i < es.length; ++i) {
|
|
48
|
+
const el = es[i];
|
|
49
|
+
el.parentNode === target && splitters.push(el);
|
|
50
|
+
}
|
|
47
51
|
let count = 0;
|
|
48
52
|
let total = 0;
|
|
49
53
|
let style: 'count' | 'abbr';
|
|
50
54
|
for (
|
|
51
|
-
let refs =
|
|
52
|
-
|
|
55
|
+
let refs = querySelectorAll(target, `sup.${syntax}:not(.disabled)`),
|
|
56
|
+
len = refs.length, i = 0; i < len; ++i) {
|
|
53
57
|
yield;
|
|
54
58
|
const ref = refs[i];
|
|
55
59
|
while (+splitters[0]?.compareDocumentPosition(ref) & Node.DOCUMENT_POSITION_FOLLOWING) {
|
|
@@ -114,7 +118,8 @@ function build(
|
|
|
114
118
|
if (title && !blank && def.childNodes.length === 1) {
|
|
115
119
|
def.insertBefore(content.cloneNode(true), def.lastChild);
|
|
116
120
|
assert(def.childNodes.length > 1);
|
|
117
|
-
for (
|
|
121
|
+
for (let refs = buffer.take(identifier, Infinity), i = 0; i < refs.length; ++i) {
|
|
122
|
+
const ref = refs[i];
|
|
118
123
|
if (ref.getAttribute('data-invalid-type') !== 'content') continue;
|
|
119
124
|
define(ref, {
|
|
120
125
|
title,
|
package/src/parser/source/str.ts
CHANGED
|
@@ -3,12 +3,13 @@ import { StrParser } from '../source';
|
|
|
3
3
|
import { Parser, Context } from '../../combinator/data/parser';
|
|
4
4
|
import { creation } from '../../combinator';
|
|
5
5
|
|
|
6
|
-
export function str(pattern: string | RegExp): StrParser;
|
|
7
|
-
export function str(pattern: string | RegExp): Parser<string, Context<StrParser>, []> {
|
|
6
|
+
export function str(pattern: string | RegExp, not?: string): StrParser;
|
|
7
|
+
export function str(pattern: string | RegExp, not?: string): Parser<string, Context<StrParser>, []> {
|
|
8
8
|
assert(pattern);
|
|
9
9
|
return typeof pattern === 'string'
|
|
10
10
|
? creation(1, false, ({ source }) => {
|
|
11
11
|
if (source === '') return;
|
|
12
|
+
if (not && source.slice(pattern.length, pattern.length + not.length) === not) return;
|
|
12
13
|
return source.slice(0, pattern.length) === pattern
|
|
13
14
|
? [[pattern], source.slice(pattern.length)]
|
|
14
15
|
: undefined;
|
|
@@ -16,6 +17,7 @@ export function str(pattern: string | RegExp): Parser<string, Context<StrParser>
|
|
|
16
17
|
: creation(1, false, ({ source }) => {
|
|
17
18
|
if (source === '') return;
|
|
18
19
|
const m = source.match(pattern);
|
|
20
|
+
if (m && not && source.slice(m[0].length, m[0].length + not.length) === not) return;
|
|
19
21
|
return m && m[0].length > 0
|
|
20
22
|
? [[m[0]], source.slice(m[0].length)]
|
|
21
23
|
: undefined;
|
|
@@ -4,10 +4,10 @@ import { union, creation, focus } from '../../combinator';
|
|
|
4
4
|
import { str } from './str';
|
|
5
5
|
import { html } from 'typed-dom/dom';
|
|
6
6
|
|
|
7
|
-
export const delimiter = /[\s\x00-\x7F]|\S[#>]|[\p{Ideo}\p{
|
|
7
|
+
export const delimiter = /[\s\x00-\x7F]|\S[#>]|[\p{Ideo}\p{scx=Hiragana}\p{scx=Katakana}~!?][^\S\n]*(?=\\\n)/u;
|
|
8
8
|
export const nonWhitespace = /[\S\n]|$/;
|
|
9
9
|
export const nonAlphanumeric = /[^0-9A-Za-z]|\S[#>]|$/;
|
|
10
|
-
const nssb = /^[\p{Ideo}\p{
|
|
10
|
+
const nssb = /^[\p{Ideo}\p{scx=Hiragana}\p{scx=Katakana}~!?][^\S\n]*(?=\\\n)/u;
|
|
11
11
|
const repeat = str(/^(.)\1*/);
|
|
12
12
|
|
|
13
13
|
export const text: TextParser = creation(1, false, ({ source, context }) => {
|
package/src/renderer/render.ts
CHANGED
|
@@ -3,8 +3,8 @@ import { RenderingOptions } from '../../';
|
|
|
3
3
|
import { code } from './render/code';
|
|
4
4
|
import { math } from './render/math';
|
|
5
5
|
import { media } from './render/media';
|
|
6
|
-
import { querySelectorAll } from 'typed-dom/query';
|
|
7
6
|
import { reduce } from 'spica/memoize';
|
|
7
|
+
import { querySelectorAllWith } from 'typed-dom/query';
|
|
8
8
|
|
|
9
9
|
const selector = 'img.media:not(.invalid):not([src])[data-src], a > :not(img).media:not(.invalid), pre.code:not(.invalid), .math:not(.invalid)';
|
|
10
10
|
|
|
@@ -14,8 +14,8 @@ const extend = reduce((opts: RenderingOptions): RenderingOptions =>
|
|
|
14
14
|
export function render(source: HTMLElement, opts: RenderingOptions = {}): void {
|
|
15
15
|
opts = extend(opts);
|
|
16
16
|
const base = location.href;
|
|
17
|
-
for (
|
|
18
|
-
render_(base,
|
|
17
|
+
for (let es = querySelectorAllWith<HTMLElement>(source, selector), i = 0; i < es.length; ++i) {
|
|
18
|
+
render_(base, es[i], opts);
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
21
|
|
package/src/util/info.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { Info } from '../..';
|
|
2
2
|
import { scope } from './scope';
|
|
3
|
-
import {
|
|
4
|
-
import { push } from 'spica/array';
|
|
3
|
+
import { querySelectorAll } from 'typed-dom/query';
|
|
5
4
|
|
|
6
5
|
export function info(source: DocumentFragment | HTMLElement | ShadowRoot): Info {
|
|
7
6
|
const match = scope(source, '.invalid');
|
|
@@ -19,8 +18,11 @@ export function info(source: DocumentFragment | HTMLElement | ShadowRoot): Info
|
|
|
19
18
|
};
|
|
20
19
|
|
|
21
20
|
function find<T extends HTMLElement>(selector: string): T[] {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
21
|
+
const acc: T[] = [];
|
|
22
|
+
for (let es = querySelectorAll<T>(source, selector), i = 0; i < es.length; ++i) {
|
|
23
|
+
const el = es[i];
|
|
24
|
+
match(el) && acc.push(el);
|
|
25
|
+
}
|
|
26
|
+
return acc;
|
|
25
27
|
}
|
|
26
28
|
}
|
package/src/util/quote.ts
CHANGED
|
@@ -2,30 +2,31 @@ 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 {
|
|
5
|
+
import { querySelectorAll } from 'typed-dom/query';
|
|
6
6
|
|
|
7
7
|
export function quote(anchor: string, range: Range): string {
|
|
8
8
|
if (exec(cite({ source: `>>${anchor}`, context: {} })) !== '') throw new Error(`Invalid anchor: ${anchor}`);
|
|
9
9
|
fit(range);
|
|
10
10
|
const node = trim(range.cloneContents());
|
|
11
11
|
if (!node.firstChild) return '';
|
|
12
|
-
|
|
12
|
+
for (let es = querySelectorAll(node, 'code[data-src], .math[data-src], .media[data-src], rt, rp'), i = 0; i < es.length; ++i) {
|
|
13
|
+
const el = es[i];
|
|
13
14
|
switch (true) {
|
|
14
15
|
case el.matches('code'):
|
|
15
16
|
case el.matches('.math'):
|
|
16
17
|
define(el, el.getAttribute('data-src')!);
|
|
17
|
-
|
|
18
|
+
continue;
|
|
18
19
|
case el.matches('.media'):
|
|
19
20
|
el.replaceWith(
|
|
20
21
|
/[\s{}]/.test(el.getAttribute('data-src')!)
|
|
21
22
|
? `!{ ${el.getAttribute('data-src')} }`
|
|
22
23
|
: `!{${el.getAttribute('data-src')}}`);
|
|
23
|
-
|
|
24
|
+
continue;
|
|
24
25
|
case el.matches('rt, rp'):
|
|
25
26
|
el.remove();
|
|
26
|
-
|
|
27
|
+
continue;
|
|
27
28
|
}
|
|
28
|
-
}
|
|
29
|
+
}
|
|
29
30
|
if (range.startOffset === 0 &&
|
|
30
31
|
range.startContainer.parentElement?.matches('.cite, .quote') &&
|
|
31
32
|
(!range.startContainer.previousSibling || range.startContainer.previousSibling.nodeName === 'BR')) {
|
|
@@ -35,25 +36,26 @@ export function quote(anchor: string, range: Range): string {
|
|
|
35
36
|
node.prepend(`>>${anchor}\n> `);
|
|
36
37
|
anchor = '';
|
|
37
38
|
}
|
|
38
|
-
|
|
39
|
+
for (let es = querySelectorAll(node, 'br'), i = 0; i < es.length; ++i) {
|
|
40
|
+
const el = es[i];
|
|
39
41
|
if (anchor && el.nextSibling instanceof Element && el.nextSibling.matches('.cite, .quote')) {
|
|
40
42
|
el.replaceWith(`\n>${el.nextSibling.matches('.quote.invalid') ? ' ' : ''}`);
|
|
41
|
-
|
|
43
|
+
continue;
|
|
42
44
|
}
|
|
43
45
|
if (anchor && el.parentElement?.closest('.cite, .quote')) {
|
|
44
46
|
el.replaceWith(`\n>${el.parentElement.closest('.quote.invalid') ? ' ' : ''}`);
|
|
45
|
-
|
|
47
|
+
continue;
|
|
46
48
|
}
|
|
47
49
|
if (anchor) {
|
|
48
50
|
el.replaceWith(`\n>>${anchor}\n> `);
|
|
49
51
|
anchor = '';
|
|
50
|
-
|
|
52
|
+
continue;
|
|
51
53
|
}
|
|
52
54
|
else {
|
|
53
55
|
el.replaceWith(`\n> `);
|
|
54
|
-
|
|
56
|
+
continue;
|
|
55
57
|
}
|
|
56
|
-
}
|
|
58
|
+
}
|
|
57
59
|
anchor && node.append(`\n>>${anchor}`);
|
|
58
60
|
return node.textContent!;
|
|
59
61
|
}
|