securemark 0.261.2 → 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 +4 -0
- package/dist/index.js +153 -114
- package/package.json +1 -1
- 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/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 +1 -1
- 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 +1 -1
- package/src/parser/inline/emphasis.ts +1 -1
- 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 +1 -1
- package/src/parser/inline/link.ts +1 -1
- package/src/parser/inline/mark.ts +1 -1
- package/src/parser/inline/media.ts +1 -1
- 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/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 +8 -7
- package/src/parser/processor/footnote.test.ts +2 -2
- package/src/parser/processor/footnote.ts +15 -11
- package/src/renderer/render.ts +1 -1
- package/src/util/info.ts +7 -5
- package/src/util/quote.ts +14 -12
- package/src/util/toc.ts +14 -8
|
@@ -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,8 +4,8 @@ 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
11
|
str('++', '+'),
|
|
@@ -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,8 +4,8 @@ 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
11
|
str('==', '='),
|
|
@@ -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,8 +4,8 @@ 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
11
|
str('*', '*'),
|
|
@@ -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,
|
|
@@ -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;
|
|
@@ -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) {
|
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 { querySelectorAllWith } 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
|
|
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
|
}
|
package/src/util/toc.ts
CHANGED
|
@@ -1,22 +1,26 @@
|
|
|
1
1
|
import { undefined } from 'spica/global';
|
|
2
|
-
import { html } from 'typed-dom/dom';
|
|
3
|
-
import { duffEach, duffReduce } from 'spica/duff';
|
|
4
2
|
import { push } from 'spica/array';
|
|
3
|
+
import { html } from 'typed-dom/dom';
|
|
4
|
+
import { querySelectorAll } from 'typed-dom/query';
|
|
5
5
|
|
|
6
6
|
// Bug: Firefox
|
|
7
7
|
//const selector = 'h1 h2 h3 h4 h5 h6 aside.aside'.split(' ').map(s => `:scope > ${s}[id]`).join();
|
|
8
8
|
const selector = ':is(h1, h2, h3, h4, h5, h6, aside.aside)[id]';
|
|
9
9
|
|
|
10
10
|
export function toc(source: DocumentFragment | HTMLElement | ShadowRoot): HTMLUListElement {
|
|
11
|
-
const hs =
|
|
11
|
+
const hs: HTMLHeadingElement[] = [];
|
|
12
|
+
for (let es = querySelectorAll(source, selector), i = 0; i < es.length; ++i) {
|
|
13
|
+
const el = es[i];
|
|
12
14
|
assert(el.parentNode === source);
|
|
13
15
|
switch (el.tagName) {
|
|
14
16
|
case 'ASIDE':
|
|
15
|
-
|
|
17
|
+
hs.push(html(el.firstElementChild!.tagName.toLowerCase() as 'h1', { id: el.id, class: 'aside' }, el.firstElementChild!.cloneNode(true).childNodes));
|
|
18
|
+
continue;
|
|
16
19
|
default:
|
|
17
|
-
|
|
20
|
+
hs.push(el as HTMLHeadingElement);
|
|
21
|
+
continue;
|
|
18
22
|
}
|
|
19
|
-
}
|
|
23
|
+
}
|
|
20
24
|
return parse(cons(hs));
|
|
21
25
|
}
|
|
22
26
|
|
|
@@ -58,7 +62,9 @@ function level(h: HTMLHeadingElement): number {
|
|
|
58
62
|
}
|
|
59
63
|
|
|
60
64
|
function unlink(h: HTMLHeadingElement): Iterable<Node> {
|
|
61
|
-
|
|
62
|
-
|
|
65
|
+
for (let es = h.getElementsByTagName('a'), len = es.length, i = 0; i < len; ++i) {
|
|
66
|
+
const el = es[i];
|
|
67
|
+
el.replaceWith(...el.childNodes);
|
|
68
|
+
}
|
|
63
69
|
return h.childNodes;
|
|
64
70
|
}
|