securemark 0.293.5 → 0.294.1
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 +973 -617
- package/markdown.d.ts +13 -13
- package/package.json +3 -3
- package/src/combinator/control/constraint/block.test.ts +6 -6
- package/src/combinator/control/constraint/contract.ts +4 -4
- package/src/combinator/control/constraint/line.test.ts +7 -7
- package/src/combinator/control/constraint/line.ts +2 -2
- package/src/combinator/control/manipulation/clear.ts +2 -3
- package/src/combinator/control/manipulation/convert.ts +2 -2
- package/src/combinator/control/manipulation/duplicate.ts +4 -5
- package/src/combinator/control/manipulation/fence.ts +2 -2
- package/src/combinator/control/manipulation/indent.test.ts +2 -2
- package/src/combinator/control/manipulation/indent.ts +4 -8
- package/src/combinator/control/manipulation/reverse.ts +2 -2
- package/src/combinator/control/manipulation/scope.ts +4 -7
- package/src/combinator/control/manipulation/surround.ts +16 -20
- package/src/combinator/control/monad/bind.ts +7 -8
- package/src/combinator/control/monad/fmap.ts +7 -7
- package/src/combinator/data/data.ts +135 -0
- package/src/combinator/data/parser/context.test.ts +8 -8
- package/src/combinator/data/parser/context.ts +3 -3
- package/src/combinator/data/parser/inits.ts +8 -11
- package/src/combinator/data/parser/sequence.test.ts +3 -3
- package/src/combinator/data/parser/sequence.ts +8 -11
- package/src/combinator/data/parser/some.test.ts +3 -3
- package/src/combinator/data/parser/some.ts +7 -9
- package/src/combinator/data/parser/subsequence.test.ts +4 -4
- package/src/combinator/data/parser/subsequence.ts +3 -3
- package/src/combinator/data/parser/tails.ts +3 -3
- package/src/combinator/data/parser/union.test.ts +3 -3
- package/src/combinator/data/parser.ts +11 -20
- package/src/debug.test.ts +7 -6
- package/src/parser/api/bind.ts +8 -10
- package/src/parser/api/header.ts +2 -2
- package/src/parser/api/normalize.ts +2 -2
- package/src/parser/api/parse.ts +4 -2
- package/src/parser/block/blockquote.ts +6 -4
- package/src/parser/block/codeblock.ts +8 -7
- package/src/parser/block/dlist.ts +9 -8
- package/src/parser/block/extension/aside.ts +27 -21
- package/src/parser/block/extension/example.ts +29 -26
- package/src/parser/block/extension/fig.ts +1 -1
- package/src/parser/block/extension/figbase.ts +6 -5
- package/src/parser/block/extension/figure.ts +24 -20
- package/src/parser/block/extension/message.ts +35 -24
- package/src/parser/block/extension/placeholder.ts +17 -13
- package/src/parser/block/extension/table.ts +47 -40
- package/src/parser/block/heading.test.ts +3 -12
- package/src/parser/block/heading.ts +12 -8
- package/src/parser/block/ilist.ts +13 -12
- package/src/parser/block/mathblock.ts +21 -17
- package/src/parser/block/mediablock.ts +7 -5
- package/src/parser/block/olist.ts +15 -5
- package/src/parser/block/pagebreak.ts +2 -1
- package/src/parser/block/paragraph.ts +3 -1
- package/src/parser/block/reply/cite.ts +20 -15
- package/src/parser/block/reply/quote.ts +6 -4
- package/src/parser/block/reply.ts +6 -3
- package/src/parser/block/sidefence.ts +8 -7
- package/src/parser/block/table.ts +23 -22
- package/src/parser/block/ulist.ts +16 -12
- package/src/parser/block.ts +11 -6
- package/src/parser/header.ts +18 -18
- package/src/parser/inline/annotation.ts +3 -1
- package/src/parser/inline/autolink/account.ts +3 -2
- package/src/parser/inline/autolink/anchor.ts +3 -2
- package/src/parser/inline/autolink/channel.ts +5 -4
- package/src/parser/inline/autolink/email.ts +4 -3
- package/src/parser/inline/autolink/hashnum.ts +3 -2
- package/src/parser/inline/autolink/hashtag.ts +4 -3
- package/src/parser/inline/autolink/url.ts +7 -6
- package/src/parser/inline/bracket.ts +16 -15
- package/src/parser/inline/code.ts +5 -4
- package/src/parser/inline/deletion.ts +5 -5
- package/src/parser/inline/emphasis.ts +4 -3
- package/src/parser/inline/emstrong.test.ts +18 -18
- package/src/parser/inline/emstrong.ts +37 -28
- package/src/parser/inline/extension/index.ts +22 -19
- package/src/parser/inline/extension/indexee.ts +2 -2
- package/src/parser/inline/extension/indexer.ts +2 -1
- package/src/parser/inline/extension/label.ts +7 -3
- package/src/parser/inline/extension/placeholder.ts +6 -6
- package/src/parser/inline/html.ts +27 -28
- package/src/parser/inline/htmlentity.ts +9 -8
- package/src/parser/inline/insertion.ts +5 -5
- package/src/parser/inline/italic.ts +5 -5
- package/src/parser/inline/link.ts +36 -38
- package/src/parser/inline/mark.ts +7 -7
- package/src/parser/inline/math.ts +5 -4
- package/src/parser/inline/media.ts +33 -32
- package/src/parser/inline/reference.ts +19 -20
- package/src/parser/inline/remark.ts +11 -11
- package/src/parser/inline/ruby.ts +50 -53
- package/src/parser/inline/strong.ts +4 -3
- package/src/parser/inline/template.ts +16 -15
- package/src/parser/inline.test.ts +3 -3
- package/src/parser/processor/note.ts +2 -2
- package/src/parser/segment.ts +5 -3
- package/src/parser/source/escapable.ts +9 -8
- package/src/parser/source/line.ts +9 -3
- package/src/parser/source/str.ts +3 -3
- package/src/parser/source/text.ts +9 -8
- package/src/parser/source/unescapable.ts +6 -5
- package/src/parser/util.ts +20 -15
- package/src/parser/visibility.ts +19 -20
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { max, min
|
|
1
|
+
import { max, min } from 'spica/alias';
|
|
2
2
|
import { ExtensionParser } from '../../block';
|
|
3
|
-
import {
|
|
3
|
+
import { List, Data, subinput } from '../../../combinator/data/parser';
|
|
4
4
|
import { union, subsequence, inits, some, block, line, validate, fence, rewrite, clear, surround, open, convert, dup, lazy, fmap } from '../../../combinator';
|
|
5
5
|
import { inline, medialink, media, lineshortmedia } from '../../inline';
|
|
6
6
|
import { str, anyline, emptyline, contentline } from '../../source';
|
|
7
|
-
import { invalid } from '../../util';
|
|
7
|
+
import { unwrap, invalid } from '../../util';
|
|
8
8
|
import { visualize, trimBlank, trimBlankEnd } from '../../visibility';
|
|
9
|
-
import {
|
|
9
|
+
import { splice } from 'spica/array';
|
|
10
10
|
import { html, define, defrag } from 'typed-dom/dom';
|
|
11
11
|
|
|
12
12
|
import TableParser = ExtensionParser.TableParser;
|
|
@@ -25,40 +25,49 @@ export const segment_: TableParser.SegmentParser = block(
|
|
|
25
25
|
export const table: TableParser = block(fmap(
|
|
26
26
|
fence(opener, 10000),
|
|
27
27
|
// Bug: Type mismatch between outer and inner.
|
|
28
|
-
(
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
'
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
overflow ?
|
|
37
|
-
|
|
38
|
-
|
|
28
|
+
(nodes: List<Data<string>>, context) => {
|
|
29
|
+
const [body, overflow, closer, opener, delim, type, param] = unwrap(nodes);
|
|
30
|
+
if (!closer || overflow || param.trimStart()) return new List([
|
|
31
|
+
new Data(html('pre', {
|
|
32
|
+
class: 'invalid',
|
|
33
|
+
translate: 'no',
|
|
34
|
+
...invalid(
|
|
35
|
+
'table',
|
|
36
|
+
!closer || overflow ? 'fence' : 'argument',
|
|
37
|
+
!closer ? `Missing the closing delimiter "${delim}"` :
|
|
38
|
+
overflow ? `Invalid trailing line after the closing delimiter "${delim}"` :
|
|
39
|
+
'Invalid argument'),
|
|
40
|
+
}, `${opener}${body}${overflow || closer}`))
|
|
41
|
+
]);
|
|
39
42
|
switch (type) {
|
|
40
43
|
case 'grid':
|
|
41
44
|
case undefined:
|
|
42
|
-
return (
|
|
43
|
-
.
|
|
45
|
+
return (parser(subinput(body, context)) ?? new List([new Data(html('table'))]))
|
|
46
|
+
.foldl(
|
|
47
|
+
(acc, { value }) => acc.push(new Data(define(value, { 'data-type': type }))) && acc,
|
|
48
|
+
new List());
|
|
44
49
|
default:
|
|
45
|
-
return [
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
+
return new List([
|
|
51
|
+
new Data(html('pre', {
|
|
52
|
+
class: 'invalid',
|
|
53
|
+
translate: 'no',
|
|
54
|
+
...invalid('table', 'argument', 'Invalid table type'),
|
|
55
|
+
}, `${opener}${body}${closer}`))
|
|
56
|
+
]);
|
|
50
57
|
}
|
|
51
58
|
}));
|
|
52
59
|
|
|
53
60
|
const parser: TableParser = lazy(() => block(fmap(
|
|
54
61
|
some(union([row])),
|
|
55
|
-
rows =>
|
|
62
|
+
rows => new List([
|
|
63
|
+
new Data(html('table', format([...unwrap(rows)])))
|
|
64
|
+
]))));
|
|
56
65
|
|
|
57
66
|
const row: RowParser = lazy(() => dup(fmap(
|
|
58
67
|
subsequence([
|
|
59
|
-
|
|
68
|
+
union([
|
|
60
69
|
align,
|
|
61
|
-
])
|
|
70
|
+
]),
|
|
62
71
|
some(union([
|
|
63
72
|
head,
|
|
64
73
|
data,
|
|
@@ -66,13 +75,13 @@ const row: RowParser = lazy(() => dup(fmap(
|
|
|
66
75
|
emptyline,
|
|
67
76
|
])),
|
|
68
77
|
]),
|
|
69
|
-
ns =>
|
|
78
|
+
ns => Array.isArray(ns.head?.value) ? ns : ns.unshift(new Data([[]])) && ns)));
|
|
70
79
|
|
|
71
80
|
const alignment = /[-=<>]+(?:\/[-=^v]*)?(?=[^\S\n]*\n)/y;
|
|
72
81
|
|
|
73
82
|
const align: AlignParser = line(fmap(
|
|
74
83
|
union([str(alignment)]),
|
|
75
|
-
([
|
|
84
|
+
([{ value }]) => new List([new Data(value.split('/').map(s => s.split('')) as [string[], string[]?])])));
|
|
76
85
|
|
|
77
86
|
const delimiter = /[-=<>]+(?:\/[-=^v]*)?(?=[^\S\n]*\n)|[#:](?:(?!:\D|0)\d*:(?!0)\d*)?(?:!+[+]?)?(?=\s)/y;
|
|
78
87
|
|
|
@@ -91,11 +100,11 @@ const head: CellParser.HeadParser = block(fmap(open(
|
|
|
91
100
|
media,
|
|
92
101
|
lineshortmedia,
|
|
93
102
|
]),
|
|
94
|
-
|
|
103
|
+
/[^\S\n]*(?:$|\n)/y)),
|
|
95
104
|
open(/(?:[^\S\n]*\n|\s)/y, visualize(trimBlank(some(inline))), true),
|
|
96
105
|
])),
|
|
97
106
|
true),
|
|
98
|
-
ns => [html('th', attributes(ns.shift()
|
|
107
|
+
ns => new List([new Data(html('th', attributes(ns.shift()!.value as string), defrag(unwrap(ns))))])),
|
|
99
108
|
false);
|
|
100
109
|
|
|
101
110
|
const data: CellParser.DataParser = block(fmap(open(
|
|
@@ -113,11 +122,11 @@ const data: CellParser.DataParser = block(fmap(open(
|
|
|
113
122
|
media,
|
|
114
123
|
lineshortmedia,
|
|
115
124
|
]),
|
|
116
|
-
|
|
125
|
+
/[^\S\n]*(?:$|\n)/y)),
|
|
117
126
|
open(/(?:[^\S\n]*\n|\s)/y, visualize(trimBlankEnd(some(inline))), true),
|
|
118
127
|
])),
|
|
119
128
|
true),
|
|
120
|
-
ns => [html('td', attributes(ns.shift()
|
|
129
|
+
ns => new List([new Data(html('td', attributes(ns.shift()!.value as string), defrag(unwrap(ns))))])),
|
|
121
130
|
false);
|
|
122
131
|
|
|
123
132
|
const dataline: CellParser.DatalineParser = line(
|
|
@@ -157,7 +166,7 @@ function attributes(source: string): Record<string, string | undefined> {
|
|
|
157
166
|
};
|
|
158
167
|
}
|
|
159
168
|
|
|
160
|
-
function format(rows:
|
|
169
|
+
function format(rows: List<Data<[string[], string[]?] | HTMLTableCellElement>>[]): HTMLTableSectionElement[] {
|
|
161
170
|
const thead = html('thead');
|
|
162
171
|
const tbody = html('tbody');
|
|
163
172
|
const tfoot = html('tfoot');
|
|
@@ -167,13 +176,11 @@ function format(rows: Node<RowParser>[]): HTMLTableSectionElement[] {
|
|
|
167
176
|
let ranges: Record<number, Record<number, HTMLTableCellElement>> = {};
|
|
168
177
|
let verticalHighlightExtensions = 0n;
|
|
169
178
|
let verticalHighlightLevels: string[] = [];
|
|
170
|
-
|
|
171
|
-
|
|
179
|
+
|
|
180
|
+
let cnt = 0;
|
|
181
|
+
for (const list of rows) ROW: for (let i = cnt++; i < cnt; ++i) {
|
|
172
182
|
// Copy to make them retryable.
|
|
173
|
-
const [[[...as], [...vs] = []], ...cells] =
|
|
174
|
-
assert(as !== rows[i][0]?.[0]);
|
|
175
|
-
assert(vs !== rows[i][0]?.[1]);
|
|
176
|
-
assert(cells !== rows[i]);
|
|
183
|
+
const [{ value: [[...as], [...vs] = []] }, ...cells] = list as any as [Data<[string[], string[]?]>, ...Data<HTMLTableCellElement>[]];
|
|
177
184
|
let isBody = target === tfoot
|
|
178
185
|
? false
|
|
179
186
|
: undefined;
|
|
@@ -248,7 +255,7 @@ function format(rows: Node<RowParser>[]): HTMLTableSectionElement[] {
|
|
|
248
255
|
const isVirtual = !!ranges[i]?.[j];
|
|
249
256
|
const cell = isVirtual
|
|
250
257
|
? splice(cells, j, 0, undefined) && ranges[i][j]
|
|
251
|
-
: cells[j];
|
|
258
|
+
: cells[j].value;
|
|
252
259
|
const isHeadCell = cell.tagName === 'TH';
|
|
253
260
|
heads |= isHeadCell ? 1n << jn : 0n;
|
|
254
261
|
highlights |= cell.className === 'highlight' ? 1n << jn : 0n;
|
|
@@ -326,7 +333,7 @@ function format(rows: Node<RowParser>[]): HTMLTableSectionElement[] {
|
|
|
326
333
|
const lHighlight = ~lHeadCellIndex && horizontalHighlights & 1n << lHeadCellIndex;
|
|
327
334
|
const rHighlight = ~rHeadCellIndex && horizontalHighlights & 1n << rHeadCellIndex;
|
|
328
335
|
for (let i = 0, m = 1n; i < cells.length; ++i, m <<= 1n) {
|
|
329
|
-
const cell = cells[i];
|
|
336
|
+
const cell = cells[i]?.value;
|
|
330
337
|
if (!cell) continue;
|
|
331
338
|
if (heads & m) continue;
|
|
332
339
|
assert(cell.tagName === 'TD');
|
|
@@ -1,16 +1,11 @@
|
|
|
1
|
-
import { heading
|
|
2
|
-
import { input
|
|
1
|
+
import { heading } from './heading';
|
|
2
|
+
import { input } from '../../combinator/data/parser';
|
|
3
3
|
import { some } from '../../combinator';
|
|
4
4
|
import { inspect } from '../../debug.test';
|
|
5
5
|
|
|
6
6
|
describe('Unit: parser/block/heading', () => {
|
|
7
7
|
describe('heading', () => {
|
|
8
|
-
const parser = (source: string) =>
|
|
9
|
-
const result = segment(input(source, ctx));
|
|
10
|
-
return result
|
|
11
|
-
? [eval(result).flatMap(seg => eval<HTMLElement | string>(heading(input(seg, {})), [seg]))] as const
|
|
12
|
-
: some(heading)(input(source, ctx));
|
|
13
|
-
};
|
|
8
|
+
const parser = (source: string) => some(heading)(input(source, ctx));
|
|
14
9
|
const { context: ctx } = input('', {});
|
|
15
10
|
|
|
16
11
|
it('invalid', () => {
|
|
@@ -54,10 +49,6 @@ describe('Unit: parser/block/heading', () => {
|
|
|
54
49
|
assert.deepStrictEqual(inspect(parser('# a[[b]]'), ctx), [['<h1 id="index::a[[b]]">a[[b]]</h1>'], '']);
|
|
55
50
|
assert.deepStrictEqual(inspect(parser('## a[[b]]'), ctx), [['<h2 id="index::a[[b]]">a[[b]]</h2>'], '']);
|
|
56
51
|
assert.deepStrictEqual(inspect(parser('###### a'), ctx), [['<h6 id="index::a">a</h6>'], '']);
|
|
57
|
-
assert.deepStrictEqual(inspect(parser('# a\n##'), ctx), [['<h1 id="index::a">a</h1>', '##'], '']);
|
|
58
|
-
assert.deepStrictEqual(inspect(parser('# a\n## '), ctx), [['<h1 id="index::a">a</h1>', '## '], '']);
|
|
59
|
-
assert.deepStrictEqual(inspect(parser('# a\n## b'), ctx), [['<h1 id="index::a">a</h1>', '<h2 id="index::b">b</h2>'], '']);
|
|
60
|
-
assert.deepStrictEqual(inspect(parser('# a\n##\n## b'), ctx), [['<h1 id="index::a">a</h1>', '##\n', '<h2 id="index::b">b</h2>'], '']);
|
|
61
52
|
});
|
|
62
53
|
|
|
63
54
|
it('indexer', () => {
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import { HeadingParser } from '../block';
|
|
2
2
|
import { State } from '../context';
|
|
3
|
+
import { List, Data } from '../../combinator/data/parser';
|
|
3
4
|
import { union, some, state, block, line, validate, focus, rewrite, open, fmap } from '../../combinator';
|
|
4
5
|
import { inline, indexee, indexer, dataindex } from '../inline';
|
|
5
6
|
import { str } from '../source';
|
|
6
7
|
import { visualize, trimBlank } from '../visibility';
|
|
7
|
-
import { invalid } from '../util';
|
|
8
|
+
import { unwrap, invalid } from '../util';
|
|
8
9
|
import { html, defrag } from 'typed-dom/dom';
|
|
9
10
|
|
|
10
11
|
export const segment: HeadingParser.SegmentParser = block(validate('#', focus(
|
|
11
12
|
/#+[^\S\n]+\S[^\n]*(?:\n#+(?!\S)[^\n]*)*(?:$|\n)/y,
|
|
12
|
-
some(line(({ context: { source } }) => [
|
|
13
|
+
some(line(({ context: { source } }) => new List([new Data(source)]))))));
|
|
13
14
|
|
|
14
15
|
export const heading: HeadingParser = block(rewrite(segment,
|
|
15
16
|
// その他の表示制御は各所のCSSで行う。
|
|
@@ -23,11 +24,14 @@ export const heading: HeadingParser = block(rewrite(segment,
|
|
|
23
24
|
state(State.linkers,
|
|
24
25
|
visualize(trimBlank(some(union([indexer, inline]))))), true),
|
|
25
26
|
]),
|
|
26
|
-
(
|
|
27
|
-
h
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
(nodes, context) => {
|
|
28
|
+
const [h, ...ns] = unwrap(nodes) as [string, ...(HTMLElement | string)[]];
|
|
29
|
+
return new List([
|
|
30
|
+
h.length <= 6
|
|
31
|
+
? new Data(html(`h${h.length as 1}`, { 'data-index': dataindex(nodes) }, defrag(ns)))
|
|
32
|
+
: new Data(html(`h6`, {
|
|
30
33
|
class: 'invalid',
|
|
31
34
|
...invalid('heading', 'syntax', 'Heading level must be up to 6'),
|
|
32
|
-
}, context.source.slice(context.position - context.range!, context.position))
|
|
33
|
-
|
|
35
|
+
}, context.source.slice(context.position - context.range!, context.position)))
|
|
36
|
+
]);
|
|
37
|
+
}))))));
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { IListParser } from '../block';
|
|
2
2
|
import { Parser } from '../../combinator/data/parser';
|
|
3
3
|
import { Recursion } from '../context';
|
|
4
|
+
import { List, Data } from '../../combinator/data/parser';
|
|
4
5
|
import { union, inits, some, recursion, block, line, validate, indent, rewrite, open, fallback, lazy, fmap } from '../../combinator';
|
|
5
6
|
import { ulist_, fillFirstLine } from './ulist';
|
|
6
7
|
import { olist_ } from './olist';
|
|
7
8
|
import { inline } from '../inline';
|
|
8
9
|
import { contentline } from '../source';
|
|
9
10
|
import { visualize, trimBlank } from '../visibility';
|
|
10
|
-
import { invalid } from '../util';
|
|
11
|
+
import { unwrap, invalid } from '../util';
|
|
11
12
|
import { html, defrag } from 'typed-dom/dom';
|
|
12
13
|
|
|
13
14
|
export const ilist: IListParser = lazy(() => block(validate(
|
|
@@ -23,21 +24,21 @@ export const ilist_: IListParser = lazy(() => block(fmap(validate(
|
|
|
23
24
|
indent(union([ulist_, olist_, ilist_])),
|
|
24
25
|
]),
|
|
25
26
|
ilistitem),
|
|
26
|
-
ns => [html('li', defrag(fillFirstLine(ns)))]),
|
|
27
|
+
ns => new List([new Data(html('li', defrag(unwrap(fillFirstLine(ns)))))])),
|
|
27
28
|
])))),
|
|
28
|
-
|
|
29
|
-
html('ul', {
|
|
29
|
+
ns => new List([
|
|
30
|
+
new Data(html('ul', {
|
|
30
31
|
class: 'invalid',
|
|
31
32
|
...invalid('list', 'syntax', 'Use "-" instead of "+" or "*"'),
|
|
32
|
-
},
|
|
33
|
-
])));
|
|
33
|
+
}, unwrap(ns))),
|
|
34
|
+
]))));
|
|
34
35
|
|
|
35
36
|
export const ilistitem = rewrite(
|
|
36
|
-
inits([contentline, indent<Parser<string>>(({ context: { source } }) => [
|
|
37
|
-
({ context: { source } }) => [
|
|
38
|
-
'',
|
|
39
|
-
html('span', {
|
|
37
|
+
inits([contentline, indent<Parser<string>>(({ context: { source } }) => new List([new Data(source)]))]),
|
|
38
|
+
({ context: { source } }) => new List([
|
|
39
|
+
new Data(''),
|
|
40
|
+
new Data(html('span', {
|
|
40
41
|
class: 'invalid',
|
|
41
42
|
...invalid('list', 'syntax', 'Fix the indent or the head of the list item'),
|
|
42
|
-
}, source.replace('\n', ''))
|
|
43
|
-
]
|
|
43
|
+
}, source.replace('\n', '')))
|
|
44
|
+
]));
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { MathBlockParser } from '../block';
|
|
2
|
+
import { List, Data } from '../../combinator/data/parser';
|
|
2
3
|
import { block, fence, clear, fmap } from '../../combinator';
|
|
3
|
-
import { invalid } from '../util';
|
|
4
|
+
import { unwrap, invalid } from '../util';
|
|
4
5
|
import { html } from 'typed-dom/dom';
|
|
5
6
|
|
|
6
7
|
const opener = /(\${2,})(?!\$)([^\n]*)(?:$|\n)/y;
|
|
@@ -14,19 +15,22 @@ export const segment_: MathBlockParser.SegmentParser = block(
|
|
|
14
15
|
export const mathblock: MathBlockParser = block(fmap(
|
|
15
16
|
fence(opener, 300),
|
|
16
17
|
// Bug: Type mismatch between outer and inner.
|
|
17
|
-
(
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
class: '
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
'
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
18
|
+
(nodes, { caches: { math: cache = undefined } = {} }) => {
|
|
19
|
+
const [body, overflow, closer, opener, delim, param] = unwrap<string>(nodes);
|
|
20
|
+
return new List([
|
|
21
|
+
delim.length === 2 && closer && !overflow && param.trimStart() === ''
|
|
22
|
+
? new Data(cache?.get(`${delim}\n${body}${delim}`)?.cloneNode(true) as HTMLDivElement ||
|
|
23
|
+
html('div', { class: 'math', translate: 'no' }, `${delim}\n${body}${delim}`))
|
|
24
|
+
: new Data(html('pre', {
|
|
25
|
+
class: 'invalid',
|
|
26
|
+
translate: 'no',
|
|
27
|
+
...invalid(
|
|
28
|
+
'mathblock',
|
|
29
|
+
delim.length > 2 ? 'syntax' : !closer || overflow ? 'fence' : 'argument',
|
|
30
|
+
delim.length > 2 ? 'Invalid syntax' :
|
|
31
|
+
!closer ? `Missing the closing delimiter "${delim}"` :
|
|
32
|
+
overflow ? `Invalid trailing line after the closing delimiter "${delim}"` :
|
|
33
|
+
'Invalid argument'),
|
|
34
|
+
}, `${opener}${body}${overflow || closer}`)),
|
|
35
|
+
]);
|
|
36
|
+
}));
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { MediaBlockParser } from '../block';
|
|
2
|
+
import { List, Data } from '../../combinator/data/parser';
|
|
2
3
|
import { union, inits, some, block, line, fallback, fmap } from '../../combinator';
|
|
3
4
|
import { medialink, media, lineshortmedia } from '../inline';
|
|
4
|
-
import { invalid } from '../util';
|
|
5
|
+
import { unwrap, invalid } from '../util';
|
|
5
6
|
import { html } from 'typed-dom/dom';
|
|
6
7
|
|
|
7
8
|
export const mediablock: MediaBlockParser = block(fmap(
|
|
@@ -15,9 +16,10 @@ export const mediablock: MediaBlockParser = block(fmap(
|
|
|
15
16
|
medialink,
|
|
16
17
|
media,
|
|
17
18
|
lineshortmedia,
|
|
18
|
-
]), ({ context: { source } }) => [
|
|
19
|
+
]), ({ context: { source } }) => new List([
|
|
20
|
+
new Data(html('span', {
|
|
19
21
|
class: 'invalid',
|
|
20
22
|
...invalid('mediablock', 'syntax', 'Not media syntax'),
|
|
21
|
-
}, source.replace('\n', ''))
|
|
22
|
-
|
|
23
|
-
ns => [html('div', ns)]));
|
|
23
|
+
}, source.replace('\n', '')))
|
|
24
|
+
]))))]),
|
|
25
|
+
ns => new List([new Data(html('div', unwrap(ns)))])));
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { OListParser } from '../block';
|
|
2
2
|
import { Recursion } from '../context';
|
|
3
|
+
import { List, Data } from '../../combinator/data/parser';
|
|
3
4
|
import { union, inits, subsequence, some, recursion, block, line, validate, indent, focus, open, match, fallback, lazy, fmap } from '../../combinator';
|
|
4
5
|
import { ulist_, checkbox, fillFirstLine } from './ulist';
|
|
5
6
|
import { ilist_, ilistitem } from './ilist';
|
|
6
7
|
import { inline, indexee, indexer, dataindex } from '../inline';
|
|
7
|
-
import { invalid } from '../util';
|
|
8
|
+
import { invalid, unwrap } from '../util';
|
|
8
9
|
import { visualize, trimBlank } from '../visibility';
|
|
9
10
|
import { memoize } from 'spica/memoize';
|
|
10
11
|
import { html, define, defrag } from 'typed-dom/dom';
|
|
@@ -40,17 +41,26 @@ const list = (type: string, form: string): OListParser.ListParser => fmap(
|
|
|
40
41
|
indent(union([ulist_, olist_, ilist_])),
|
|
41
42
|
]),
|
|
42
43
|
ilistitem),
|
|
43
|
-
ns =>
|
|
44
|
+
ns => new List([
|
|
45
|
+
new Data(html('li', {
|
|
46
|
+
'data-index': dataindex(ns),
|
|
47
|
+
'data-marker': ns.shift()?.value as string || undefined,
|
|
48
|
+
}, defrag(unwrap(fillFirstLine(ns)))))
|
|
49
|
+
]))),
|
|
44
50
|
]))),
|
|
45
|
-
|
|
51
|
+
ns => new List([new Data(format(html('ol', unwrap(ns)), type, form))]));
|
|
46
52
|
|
|
47
53
|
const heads = {
|
|
48
54
|
'.': focus(
|
|
49
55
|
openers['.'],
|
|
50
|
-
({ context: { source } }) =>
|
|
56
|
+
({ context: { source } }) => new List([
|
|
57
|
+
new Data(source.trimEnd().split('.', 1)[0] + '.')
|
|
58
|
+
])),
|
|
51
59
|
'(': focus(
|
|
52
60
|
openers['('],
|
|
53
|
-
({ context: { source } }) =>
|
|
61
|
+
({ context: { source } }) => new List([
|
|
62
|
+
new Data(source.trimEnd().replace(/^\($/, '(1)').replace(/^\((\w+)$/, '($1)'))
|
|
63
|
+
])),
|
|
54
64
|
} as const;
|
|
55
65
|
|
|
56
66
|
function idx(value: string): number {
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { PagebreakParser } from '../block';
|
|
2
|
+
import { List, Data } from '../../combinator/data/parser';
|
|
2
3
|
import { block, line, focus } from '../../combinator';
|
|
3
4
|
import { html } from 'typed-dom/dom';
|
|
4
5
|
|
|
5
6
|
export const pagebreak: PagebreakParser = block(line(focus(
|
|
6
7
|
/={3,}[^\S\n]*(?:$|\n)/y,
|
|
7
|
-
() => [
|
|
8
|
+
() => new List([new Data(html('hr'))]))));
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { ParagraphParser } from '../block';
|
|
2
|
+
import { List, Data } from '../../combinator/data/parser';
|
|
2
3
|
import { union, some, block, fmap } from '../../combinator';
|
|
3
4
|
import { inline } from '../inline';
|
|
4
5
|
import { visualize, trimBlankEnd } from '../visibility';
|
|
6
|
+
import { unwrap } from '../util';
|
|
5
7
|
import { html, defrag } from 'typed-dom/dom';
|
|
6
8
|
|
|
7
9
|
export const paragraph: ParagraphParser = block(fmap(
|
|
8
10
|
visualize(trimBlankEnd(some(union([inline])))),
|
|
9
|
-
ns => [html('p', defrag(ns))]));
|
|
11
|
+
ns => new List([new Data(html('p', defrag(unwrap(ns))))])));
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ReplyParser } from '../../block';
|
|
2
|
+
import { List, Data } from '../../../combinator/data/parser';
|
|
2
3
|
import { union, line, focus, open, fmap } from '../../../combinator';
|
|
3
4
|
import { anchor } from '../../inline/autolink/anchor';
|
|
4
5
|
import { str } from '../../source';
|
|
@@ -14,20 +15,24 @@ export const cite: ReplyParser.CiteParser = line(fmap(
|
|
|
14
15
|
anchor,
|
|
15
16
|
// Subject page representation.
|
|
16
17
|
// リンクの実装は後で検討
|
|
17
|
-
focus(/>>#\S*(?=\s*$)/y, ({ context: { source } }) => [
|
|
18
|
-
focus(/>>https?:\/\/\S+(?=\s*$)/y, ({ context: { source } }) => [
|
|
19
|
-
focus(/>>.+(?=\s*$)/y, ({ context: { source } }) => [
|
|
18
|
+
focus(/>>#\S*(?=\s*$)/y, ({ context: { source } }) => new List([new Data(html('a', { class: 'anchor' }, source))])),
|
|
19
|
+
focus(/>>https?:\/\/\S+(?=\s*$)/y, ({ context: { source } }) => new List([new Data(html('a', { class: 'anchor', href: source.slice(2).trimEnd(), target: '_blank' }, source))])),
|
|
20
|
+
focus(/>>.+(?=\s*$)/y, ({ context: { source } }) => new List([new Data(source)])),
|
|
20
21
|
])),
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
defrag([
|
|
27
|
-
`${quotes}>`,
|
|
22
|
+
nodes => {
|
|
23
|
+
const quotes = nodes.head!.value as string;
|
|
24
|
+
const node = nodes.last!.value;
|
|
25
|
+
return new List([
|
|
26
|
+
new Data(html('span',
|
|
28
27
|
typeof node === 'object'
|
|
29
|
-
?
|
|
30
|
-
:
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
28
|
+
? { class: 'cite' }
|
|
29
|
+
: { class: 'cite invalid', ...invalid('cite', 'syntax', 'Invalid syntax') },
|
|
30
|
+
defrag([
|
|
31
|
+
`${quotes}>`,
|
|
32
|
+
typeof node === 'object'
|
|
33
|
+
? define(node, { 'data-depth': `${quotes.length + 1}` }, node.innerText.slice(1))
|
|
34
|
+
: node.slice(1),
|
|
35
|
+
]))),
|
|
36
|
+
new Data(html('br')),
|
|
37
|
+
]);
|
|
38
|
+
}));
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { ReplyParser } from '../../block';
|
|
2
|
+
import { List, Data } from '../../../combinator/data/parser';
|
|
2
3
|
import { union, some, block, validate, rewrite, convert, lazy, fmap } from '../../../combinator';
|
|
3
4
|
import { math } from '../../inline/math';
|
|
4
5
|
import { autolink } from '../../inline/autolink';
|
|
5
6
|
import { linebreak, unescsource, anyline } from '../../source';
|
|
7
|
+
import { unwrap } from '../../util';
|
|
6
8
|
import { html, defrag } from 'typed-dom/dom';
|
|
7
9
|
|
|
8
10
|
export const syntax = />+[^\S\n]/y;
|
|
@@ -21,8 +23,8 @@ export const quote: ReplyParser.QuoteParser = lazy(() => block(fmap(
|
|
|
21
23
|
unescsource,
|
|
22
24
|
])),
|
|
23
25
|
false)),
|
|
24
|
-
(ns
|
|
25
|
-
source[position - 1] === '\n' ? ns.pop() as HTMLBRElement : html('br'),
|
|
26
|
-
html('span', { class: 'quote' }, defrag(ns)),
|
|
27
|
-
].reverse()),
|
|
26
|
+
(ns, { source, position }) => new List([
|
|
27
|
+
new Data(source[position - 1] === '\n' ? ns.pop()!.value as HTMLBRElement : html('br')),
|
|
28
|
+
new Data(html('span', { class: 'quote' }, defrag(unwrap(ns)))),
|
|
29
|
+
].reverse())),
|
|
28
30
|
false));
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { ReplyParser } from '../block';
|
|
2
|
+
import { List, Data } from '../../combinator/data/parser';
|
|
2
3
|
import { union, some, block, validate, rewrite, fmap } from '../../combinator';
|
|
3
4
|
import { cite, syntax as csyntax } from './reply/cite';
|
|
4
5
|
import { quote, syntax as qsyntax } from './reply/quote';
|
|
5
6
|
import { inline } from '../inline';
|
|
6
7
|
import { anyline } from '../source';
|
|
7
8
|
import { visualize, trimBlankNodeEnd } from '../visibility';
|
|
8
|
-
import {
|
|
9
|
+
import { unwrap } from '../util';
|
|
9
10
|
import { html, defrag } from 'typed-dom/dom';
|
|
10
11
|
|
|
11
12
|
const delimiter = new RegExp(`${csyntax.source}|${qsyntax.source}`, 'y');
|
|
@@ -17,6 +18,8 @@ export const reply: ReplyParser = block(validate(csyntax, fmap(
|
|
|
17
18
|
rewrite(
|
|
18
19
|
some(anyline, delimiter),
|
|
19
20
|
visualize(fmap(some(inline), (ns, { source, position }) =>
|
|
20
|
-
source[position - 1] === '\n'
|
|
21
|
+
source[position - 1] === '\n'
|
|
22
|
+
? ns
|
|
23
|
+
: ns.push(new Data(html('br'))) && ns)))
|
|
21
24
|
])),
|
|
22
|
-
ns => [html('p', trimBlankNodeEnd(
|
|
25
|
+
ns => new List([new Data(html('p', defrag(unwrap(trimBlankNodeEnd(ns)))))]))));
|
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
import { SidefenceParser } from '../block';
|
|
2
2
|
import { Recursion } from '../context';
|
|
3
|
+
import { List, Data } from '../../combinator/data/parser';
|
|
3
4
|
import { union, some, recursion, block, focus, rewrite, convert, lazy, fmap } from '../../combinator';
|
|
4
5
|
import { autolink } from '../autolink';
|
|
5
6
|
import { contentline } from '../source';
|
|
6
|
-
import { invalid } from '../util';
|
|
7
|
+
import { unwrap, invalid } from '../util';
|
|
7
8
|
import { html, define, defrag } from 'typed-dom/dom';
|
|
8
9
|
|
|
9
10
|
export const sidefence: SidefenceParser = lazy(() => block(fmap(focus(
|
|
10
11
|
/(?=\|+(?:[^\S\n]|\n\|))(?:\|+(?:[^\S\n][^\n]*)?(?:$|\n))+$/y,
|
|
11
12
|
union([source])),
|
|
12
|
-
([
|
|
13
|
-
define(
|
|
13
|
+
([{ value }]) => new List([
|
|
14
|
+
new Data(define(value, {
|
|
14
15
|
class: 'invalid',
|
|
15
16
|
...invalid('sidefence', 'syntax', 'Reserved syntax'),
|
|
16
|
-
}),
|
|
17
|
-
])));
|
|
17
|
+
})),
|
|
18
|
+
]))));
|
|
18
19
|
|
|
19
20
|
const opener = /(?=\|\|+(?:$|\s))/y;
|
|
20
21
|
const unindent = (source: string) => source.replace(/(?<=^|\n)\|(?:[^\S\n]|(?=\|*(?:$|\s)))|\n$/g, '');
|
|
@@ -26,6 +27,6 @@ const source: SidefenceParser.SourceParser = lazy(() => fmap(
|
|
|
26
27
|
convert(unindent, source, false, true)),
|
|
27
28
|
rewrite(
|
|
28
29
|
some(contentline, opener),
|
|
29
|
-
convert(unindent, fmap(autolink, ns => [html('pre', defrag(ns))]), false, true)),
|
|
30
|
+
convert(unindent, fmap(autolink, ns => new List([new Data(html('pre', defrag(unwrap(ns))))])), false, true)),
|
|
30
31
|
]))),
|
|
31
|
-
ns => [html('blockquote', ns)]));
|
|
32
|
+
ns => new List([new Data(html('blockquote', unwrap(ns)))])));
|