securemark 0.263.1 → 0.264.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.
Files changed (48) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/index.js +1205 -3025
  3. package/markdown.d.ts +1 -1
  4. package/package.json +18 -18
  5. package/src/combinator/data/parser/context.ts +3 -2
  6. package/src/parser/api/bind.test.ts +1 -1
  7. package/src/parser/api/parse.test.ts +3 -3
  8. package/src/parser/block/blockquote.test.ts +3 -3
  9. package/src/parser/block/dlist.ts +2 -3
  10. package/src/parser/block/extension/example.test.ts +1 -1
  11. package/src/parser/block/extension/fig.ts +2 -1
  12. package/src/parser/block/extension/figure.ts +2 -3
  13. package/src/parser/block/extension/table.ts +2 -3
  14. package/src/parser/block/heading.test.ts +1 -1
  15. package/src/parser/block/paragraph.test.ts +1 -1
  16. package/src/parser/block/paragraph.ts +2 -3
  17. package/src/parser/block/reply.ts +2 -3
  18. package/src/parser/context.ts +15 -19
  19. package/src/parser/inline/annotation.ts +1 -1
  20. package/src/parser/inline/bracket.test.ts +1 -1
  21. package/src/parser/inline/bracket.ts +1 -1
  22. package/src/parser/inline/deletion.test.ts +2 -2
  23. package/src/parser/inline/emphasis.test.ts +2 -2
  24. package/src/parser/inline/emphasis.ts +2 -2
  25. package/src/parser/inline/extension/index.test.ts +28 -32
  26. package/src/parser/inline/extension/index.ts +1 -1
  27. package/src/parser/inline/extension/indexee.ts +22 -12
  28. package/src/parser/inline/extension/placeholder.test.ts +10 -12
  29. package/src/parser/inline/extension/placeholder.ts +7 -7
  30. package/src/parser/inline/html.test.ts +1 -1
  31. package/src/parser/inline/html.ts +2 -2
  32. package/src/parser/inline/insertion.test.ts +2 -2
  33. package/src/parser/inline/link.test.ts +6 -5
  34. package/src/parser/inline/link.ts +43 -42
  35. package/src/parser/inline/mark.test.ts +11 -11
  36. package/src/parser/inline/mark.ts +12 -6
  37. package/src/parser/inline/strong.test.ts +2 -2
  38. package/src/parser/inline/strong.ts +2 -2
  39. package/src/parser/inline.test.ts +8 -7
  40. package/src/parser/source/escapable.test.ts +1 -1
  41. package/src/parser/source/escapable.ts +7 -1
  42. package/src/parser/source/text.test.ts +24 -35
  43. package/src/parser/source/text.ts +2 -15
  44. package/src/parser/visibility.ts +1 -6
  45. package/src/parser/locale/ja.test.ts +0 -14
  46. package/src/parser/locale/ja.ts +0 -3
  47. package/src/parser/locale.test.ts +0 -26
  48. package/src/parser/locale.ts +0 -61
package/markdown.d.ts CHANGED
@@ -779,8 +779,8 @@ export namespace MarkdownParser {
779
779
  }
780
780
  }
781
781
  export interface IndexerParser extends
782
- // [#]
783
782
  // [#index]
783
+ // [#]
784
784
  Inline<'extension/indexer'>,
785
785
  Parser<HTMLElement, Context, [
786
786
  Parser<HTMLAnchorElement, Context, []>,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "securemark",
3
- "version": "0.263.1",
3
+ "version": "0.264.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",
@@ -28,35 +28,35 @@
28
28
  "LICENSE"
29
29
  ],
30
30
  "devDependencies": {
31
- "@types/dompurify": "2.3.4",
32
- "@types/jquery": "3.5.14",
31
+ "@types/dompurify": "2.4.0",
32
+ "@types/jquery": "3.5.16",
33
33
  "@types/mathjax": "0.0.37",
34
- "@types/mocha": "10.0.0",
34
+ "@types/mocha": "10.0.1",
35
35
  "@types/power-assert": "1.5.8",
36
36
  "@types/prismjs": "1.26.0",
37
- "@typescript-eslint/parser": "^5.39.0",
38
- "babel-loader": "^8.2.5",
37
+ "@typescript-eslint/parser": "^5.49.0",
38
+ "babel-loader": "^9.1.2",
39
39
  "babel-plugin-unassert": "^3.2.0",
40
- "concurrently": "^7.4.0",
41
- "eslint": "^8.25.0",
42
- "eslint-plugin-redos": "^4.4.1",
40
+ "concurrently": "^7.6.0",
41
+ "eslint": "^8.32.0",
42
+ "eslint-plugin-redos": "^4.4.3",
43
43
  "eslint-webpack-plugin": "^3.2.0",
44
- "glob": "^8.0.3",
44
+ "glob": "^8.1.0",
45
45
  "karma": "^6.4.1",
46
46
  "karma-chrome-launcher": "^3.1.1",
47
47
  "karma-coverage": "^2.2.0",
48
48
  "karma-firefox-launcher": "^2.1.2",
49
49
  "karma-mocha": "^2.0.1",
50
50
  "karma-power-assert": "^1.0.0",
51
- "mocha": "^10.0.0",
52
- "npm-check-updates": "^16.3.10",
51
+ "mocha": "^10.2.0",
52
+ "npm-check-updates": "^16.6.3",
53
53
  "semver": "^7.3.8",
54
- "spica": "0.0.656",
55
- "ts-loader": "^9.4.1",
56
- "typed-dom": "^0.0.312",
57
- "typescript": "4.8.4",
58
- "webpack": "^5.74.0",
59
- "webpack-cli": "^4.10.0",
54
+ "spica": "0.0.719",
55
+ "ts-loader": "^9.4.2",
56
+ "typed-dom": "^0.0.315",
57
+ "typescript": "4.9.4",
58
+ "webpack": "^5.75.0",
59
+ "webpack-cli": "^5.0.1",
60
60
  "webpack-merge": "^5.8.0"
61
61
  },
62
62
  "scripts": {
@@ -1,5 +1,5 @@
1
1
  import { hasOwnProperty, ObjectCreate } from 'spica/alias';
2
- import { Parser, Result, Ctx, Context, eval, exec, Tree } from '../../data/parser';
2
+ import { Parser, Result, Ctx, Tree, Context, eval, exec } from '../../data/parser';
3
3
  import { Memo } from './context/memo';
4
4
 
5
5
  export function reset<P extends Parser<unknown>>(base: Context<P>, parser: P): P;
@@ -38,10 +38,11 @@ function apply<T>(parser: Parser<T>, source: string, context: Ctx, changes: [str
38
38
  if (prop in context && !hasOwnProperty(context, prop)) break;
39
39
  context[prop as string] = ObjectCreate(change[1]);
40
40
  break;
41
+ // @ts-expect-error
41
42
  case 'memo':
42
43
  if (!reset) break;
43
44
  context.memo = new Memo({ targets: context.memo?.targets });
44
- break;
45
+ // fallthrough
45
46
  default:
46
47
  values[i] = context[prop];
47
48
  context[prop] = change[1];
@@ -126,7 +126,7 @@ describe('Unit: parser/api/bind', () => {
126
126
  });
127
127
 
128
128
  it('normalize', () => {
129
- assert.deepStrictEqual(inspect(bind(html('div'), cfgs).parse('a\\\r\nb')), ['<p>a<span class="linebreak"> </span>b</p>']);
129
+ assert.deepStrictEqual(inspect(bind(html('div'), cfgs).parse('a\\\r\nb')), ['<p>a<br>b</p>']);
130
130
  });
131
131
 
132
132
  it('reentrant', () => {
@@ -71,7 +71,7 @@ describe('Unit: parser/api/parse', () => {
71
71
  ['<p>a <br>b</p>']);
72
72
  assert.deepStrictEqual(
73
73
  [...parse('a\\\nb').children].map(el => el.outerHTML),
74
- ['<p>a<span class="linebreak"> </span>b</p>']);
74
+ ['<p>a<br>b</p>']);
75
75
  assert.deepStrictEqual(
76
76
  [...parse('a\n\\ \nb').children].map(el => el.outerHTML),
77
77
  ['<p>a<br>\\<br>b</p>']);
@@ -209,7 +209,7 @@ describe('Unit: parser/api/parse', () => {
209
209
  [...parse('$-a\n$$\n$$\n\n(($-a[[b]][[c_d_]]))', { footnotes }).children].map(el => el.outerHTML),
210
210
  [
211
211
  '<figure data-type="math" data-label="$-a" data-group="$" data-number="1" id="label:$-a"><figcaption><span class="figindex">(1)</span><span class="figtext"></span></figcaption><div><div class="math" translate="no">$$\n$$</div></div></figure>',
212
- '<p><sup class="annotation" id="annotation:ref:1" title="(1)[1][2]"><span hidden=""><a class="label" data-label="$-a" href="#label:$-a">(1)</a><sup class="reference" id="reference:ref:1" title="b"><span hidden="">b</span><a href="#reference:def:1">[1]</a></sup><sup class="reference" id="reference:ref:2" title="cd"><span hidden="">c<em>d</em></span><a href="#reference:def:2">[2]</a></sup></span><a href="#annotation:def:1">*1</a></sup></p>',
212
+ '<p><sup class="annotation" id="annotation:ref:1" title="(1)"><span hidden=""><a class="label" data-label="$-a" href="#label:$-a">(1)</a><sup class="reference" id="reference:ref:1" title="b"><span hidden="">b</span><a href="#reference:def:1">[1]</a></sup><sup class="reference" id="reference:ref:2" title="cd"><span hidden="">c<em>d</em></span><a href="#reference:def:2">[2]</a></sup></span><a href="#annotation:def:1">*1</a></sup></p>',
213
213
  '<ol class="annotations"><li id="annotation:def:1" data-marker="*1"><a class="label" data-label="$-a" href="#label:$-a">(1)</a><sup class="reference" id="reference:ref:1" title="b"><span hidden="">b</span><a href="#reference:def:1">[1]</a></sup><sup class="reference" id="reference:ref:2" title="cd"><span hidden="">c<em>d</em></span><a href="#reference:def:2">[2]</a></sup><sup><a href="#annotation:ref:1">^1</a></sup></li></ol>',
214
214
  ]);
215
215
  assert.deepStrictEqual(
@@ -220,7 +220,7 @@ describe('Unit: parser/api/parse', () => {
220
220
  it('normalize', () => {
221
221
  assert.deepStrictEqual(
222
222
  [...parse('a\\\r\nb').children].map(el => el.outerHTML),
223
- ['<p>a<span class="linebreak"> </span>b</p>']);
223
+ ['<p>a<br>b</p>']);
224
224
  });
225
225
 
226
226
  it('backtrack', () => {
@@ -69,9 +69,9 @@ describe('Unit: parser/block/blockquote', () => {
69
69
  assert.deepStrictEqual(inspect(parser('!> \\\n')), [['<blockquote><section><p>\\</p><h2>References</h2><ol class="references"></ol></section></blockquote>'], '']);
70
70
  assert.deepStrictEqual(inspect(parser('!> a')), [['<blockquote><section><p>a</p><h2>References</h2><ol class="references"></ol></section></blockquote>'], '']);
71
71
  assert.deepStrictEqual(inspect(parser('!> a\n')), [['<blockquote><section><p>a</p><h2>References</h2><ol class="references"></ol></section></blockquote>'], '']);
72
- assert.deepStrictEqual(inspect(parser('!> a\\\nb')), [['<blockquote><section><p>a<span class="linebreak"> </span>b</p><h2>References</h2><ol class="references"></ol></section></blockquote>'], '']);
73
- assert.deepStrictEqual(inspect(parser('!> _a\nb_')), [['<blockquote><section><p><em>a<br>b</em></p><h2>References</h2><ol class="references"></ol></section></blockquote>'], '']);
74
- assert.deepStrictEqual(inspect(parser('!> _a\n> b_')), [['<blockquote><section><p><em>a<br>b</em></p><h2>References</h2><ol class="references"></ol></section></blockquote>'], '']);
72
+ assert.deepStrictEqual(inspect(parser('!> a\\\nb')), [['<blockquote><section><p>a<br>b</p><h2>References</h2><ol class="references"></ol></section></blockquote>'], '']);
73
+ assert.deepStrictEqual(inspect(parser('!> ++a\nb++')), [['<blockquote><section><p><ins>a<br>b</ins></p><h2>References</h2><ol class="references"></ol></section></blockquote>'], '']);
74
+ assert.deepStrictEqual(inspect(parser('!> ++a\n> b++')), [['<blockquote><section><p><ins>a<br>b</ins></p><h2>References</h2><ol class="references"></ol></section></blockquote>'], '']);
75
75
  assert.deepStrictEqual(inspect(parser('!> a \n b c ')), [['<blockquote><section><p> a<br> b c</p><h2>References</h2><ol class="references"></ol></section></blockquote>'], '']);
76
76
  assert.deepStrictEqual(inspect(parser('!>> a')), [['<blockquote><blockquote><section><p>a</p><h2>References</h2><ol class="references"></ol></section></blockquote></blockquote>'], '']);
77
77
  assert.deepStrictEqual(inspect(parser('!>> a\n> b')), [['<blockquote><blockquote><section><p>a</p><h2>References</h2><ol class="references"></ol></section></blockquote><section><p>b</p><h2>References</h2><ol class="references"></ol></section></blockquote>'], '']);
@@ -3,19 +3,18 @@ import { union, inits, some, creation, state, block, line, validate, rewrite, op
3
3
  import { inline, indexee, indexer } from '../inline';
4
4
  import { anyline } from '../source';
5
5
  import { State } from '../context';
6
- import { localize } from '../locale';
7
6
  import { visualize, trimBlank } from '../visibility';
8
7
  import { push } from 'spica/array';
9
8
  import { html, defrag } from 'typed-dom/dom';
10
9
 
11
- export const dlist: DListParser = lazy(() => block(localize(fmap(validate(
10
+ export const dlist: DListParser = lazy(() => block(fmap(validate(
12
11
  /^~[^\S\n]+(?=\S)/,
13
12
  some(inits([
14
13
  state(State.annotation | State.reference | State.index | State.label | State.link | State.media,
15
14
  some(term)),
16
15
  some(desc),
17
16
  ]))),
18
- es => [html('dl', fillTrailingDescription(es))]))));
17
+ es => [html('dl', fillTrailingDescription(es))])));
19
18
 
20
19
  const term: DListParser.TermParser = creation(1, false, line(indexee(fmap(open(
21
20
  /^~[^\S\n]+(?=\S)/,
@@ -18,7 +18,7 @@ describe('Unit: parser/block/extension/example', () => {
18
18
  assert.deepStrictEqual(inspect(parser('~~~example/markdown\n~~~')), [['<aside class="example" data-type="markdown"><pre translate="no"></pre><hr><section><h2>References</h2><ol class="references"></ol></section></aside>'], '']);
19
19
  assert.deepStrictEqual(inspect(parser('~~~example/markdown\n\n~~~')), [['<aside class="example" data-type="markdown"><pre translate="no"></pre><hr><section><h2>References</h2><ol class="references"></ol></section></aside>'], '']);
20
20
  assert.deepStrictEqual(inspect(parser('~~~example/markdown\na\n~~~')), [['<aside class="example" data-type="markdown"><pre translate="no">a</pre><hr><section><p>a</p><h2>References</h2><ol class="references"></ol></section></aside>'], '']);
21
- assert.deepStrictEqual(inspect(parser('~~~example/markdown\n_a\nb_\n~~~')), [['<aside class="example" data-type="markdown"><pre translate="no">_a\nb_</pre><hr><section><p><em>a<br>b</em></p><h2>References</h2><ol class="references"></ol></section></aside>'], '']);
21
+ assert.deepStrictEqual(inspect(parser('~~~example/markdown\n++a\nb++\n~~~')), [['<aside class="example" data-type="markdown"><pre translate="no">++a\nb++</pre><hr><section><p><ins>a<br>b</ins></p><h2>References</h2><ol class="references"></ol></section></aside>'], '']);
22
22
  assert.deepStrictEqual(inspect(parser('~~~example/markdown\n$fig-a\n!https://host\n~~~')), [['<aside class="example" data-type="markdown"><pre translate="no">$fig-a\n!https://host</pre><hr><section><figure data-type="media" data-label="fig-a" data-group="fig" data-number="1"><figcaption><span class="figindex">Fig. 1. </span><span class="figtext"></span></figcaption><div><a href="https://host" target="_blank"><img class="media" data-src="https://host" alt=""></a></div></figure><h2>References</h2><ol class="references"></ol></section></aside>'], '']);
23
23
  assert.deepStrictEqual(inspect(parser('~~~example/markdown\n[$fig-a]\n!https://host\n~~~')), [['<aside class="example" data-type="markdown"><pre translate="no">[$fig-a]\n!https://host</pre><hr><section><figure data-type="media" data-label="fig-a" data-group="fig" data-number="1"><figcaption><span class="figindex">Fig. 1. </span><span class="figtext"></span></figcaption><div><a href="https://host" target="_blank"><img class="media" data-src="https://host" alt=""></a></div></figure><h2>References</h2><ol class="references"></ol></section></aside>'], '']);
24
24
  assert.deepStrictEqual(inspect(parser('~~~example/markdown\n## a\n~~~')), [['<aside class="example" data-type="markdown"><pre translate="no">## a</pre><hr><section><h2>a</h2><h2>References</h2><ol class="references"></ol></section></aside>'], '']);
@@ -27,7 +27,8 @@ export const segment: FigParser.SegmentParser = block(validate(['[$', '$'],
27
27
 
28
28
  export const fig: FigParser = block(rewrite(segment, verify(convert(
29
29
  (source, context) => {
30
- const fence = (/^[^\n]*\n!?>+\s/.test(source) && source.match(/^~{3,}(?=[^\S\n]*$)/mg) || [])
30
+ // Bug: TypeScript
31
+ const fence = (/^[^\n]*\n!?>+\s/.test(source) && source.match(/^~{3,}(?=[^\S\n]*$)/mg) as string[] || [])
31
32
  .reduce((max, fence) => fence > max ? fence : max, '~~') + '~';
32
33
  return parser({ source, context })
33
34
  ? `${fence}figure ${source.replace(/^(.+\n.+\n)([\S\s]+?)\n?$/, '$1\n$2')}\n${fence}`
@@ -13,7 +13,6 @@ import { blockquote, segment as seg_blockquote } from '../blockquote';
13
13
  import { placeholder, segment_ as seg_placeholder } from './placeholder';
14
14
  import { inline, media, shortmedia } from '../../inline';
15
15
  import { State } from '../../context';
16
- import { localize } from '../../locale';
17
16
  import { visualize, trimBlank } from '../../visibility';
18
17
  import { memoize } from 'spica/memoize';
19
18
  import { html, defrag } from 'typed-dom/dom';
@@ -65,9 +64,9 @@ export const figure: FigureParser = block(fallback(rewrite(segment, fmap(
65
64
  line(shortmedia),
66
65
  ])),
67
66
  emptyline,
68
- block(localize(
67
+ block(
69
68
  state(State.media,
70
- visualize(trimBlank(trimEnd(some(inline))))))),
69
+ visualize(trimBlank(trimEnd(some(inline)))))),
71
70
  ]),
72
71
  ])),
73
72
  ([label, param, content, ...caption]: [HTMLAnchorElement, string, ...HTMLElement[]]) => [
@@ -4,7 +4,6 @@ import { Tree, eval } from '../../../combinator/data/parser';
4
4
  import { union, subsequence, inits, some, creation, block, line, validate, fence, rewrite, open, clear, convert, trim, dup, lazy, fmap } from '../../../combinator';
5
5
  import { inline } from '../../inline';
6
6
  import { str, anyline, emptyline, contentline } from '../../source';
7
- import { localize } from '../../locale';
8
7
  import { visualize } from '../../visibility';
9
8
  import { unshift, splice } from 'spica/array';
10
9
  import { html, define, defrag } from 'typed-dom/dom';
@@ -52,9 +51,9 @@ export const table: TableParser = block(validate('~~~', fmap(
52
51
  }
53
52
  })));
54
53
 
55
- const parser: TableParser = lazy(() => block(localize(fmap(
54
+ const parser: TableParser = lazy(() => block(fmap(
56
55
  some(union([row])),
57
- rows => [html('table', format(rows))]))));
56
+ rows => [html('table', format(rows))])));
58
57
 
59
58
  const row: RowParser = lazy(() => dup(fmap(
60
59
  subsequence([
@@ -75,7 +75,7 @@ describe('Unit: parser/block/heading', () => {
75
75
  assert.deepStrictEqual(inspect(parser('# a [#!http://host]')), [['<h1 id="index:!http://host">a<span class="indexer" data-index="!http://host"></span></h1>'], '']);
76
76
  assert.deepStrictEqual(inspect(parser('# a [#a((b))]')), [['<h1 id="index:a((b))">a<span class="indexer" data-index="a((b))"></span></h1>'], '']);
77
77
  assert.deepStrictEqual(inspect(parser('# a [#a[[b]]]')), [['<h1 id="index:a[[b]]">a<span class="indexer" data-index="a[[b]]"></span></h1>'], '']);
78
- assert.deepStrictEqual(inspect(parser('# a [#b |#c]')), [['<h1 id="index:c">a<span class="indexer" data-index="c"></span></h1>'], '']);
78
+ assert.deepStrictEqual(inspect(parser('# a [#b |c]')), [['<h1 id="index:c">a<span class="indexer" data-index="c"></span></h1>'], '']);
79
79
  assert.deepStrictEqual(inspect(parser('# a [#b] [#c]')), [['<h1 id="index:c">a [#b]<span class="indexer" data-index="c"></span></h1>'], '']);
80
80
  assert.deepStrictEqual(inspect(parser('# a [#b] \n')), [['<h1 id="index:b">a<span class="indexer" data-index="b"></span></h1>'], '']);
81
81
  assert.deepStrictEqual(inspect(parser('# a \\[#b]')), [['<h1 id="index:a_[#b]">a [#b]</h1>'], '']);
@@ -19,7 +19,7 @@ describe('Unit: parser/block/paragraph', () => {
19
19
  assert.deepStrictEqual(inspect(parser('a\\ ')), [['<p>a</p>'], '']);
20
20
  assert.deepStrictEqual(inspect(parser('a\\ \n')), [['<p>a</p>'], '']);
21
21
  assert.deepStrictEqual(inspect(parser('a\\\n')), [['<p>a</p>'], '']);
22
- assert.deepStrictEqual(inspect(parser('a\\\nb')), [['<p>a<span class="linebreak"> </span>b</p>'], '']);
22
+ assert.deepStrictEqual(inspect(parser('a\\\nb')), [['<p>a<br>b</p>'], '']);
23
23
  assert.deepStrictEqual(inspect(parser('a&NewLine;b')), [['<p>a b</p>'], '']);
24
24
  assert.deepStrictEqual(inspect(parser('&Tab;&NewLine;')), [['<p>&amp;Tab;&amp;NewLine;</p>'], '']);
25
25
  assert.deepStrictEqual(inspect(parser('<wbr>')), [['<p>&lt;wbr&gt;</p>'], '']);
@@ -1,10 +1,9 @@
1
1
  import { ParagraphParser } from '../block';
2
2
  import { union, some, block, trimEnd, fmap } from '../../combinator';
3
3
  import { inline } from '../inline';
4
- import { localize } from '../locale';
5
4
  import { visualize } from '../visibility';
6
5
  import { html, defrag } from 'typed-dom/dom';
7
6
 
8
- export const paragraph: ParagraphParser = block(localize(fmap(
7
+ export const paragraph: ParagraphParser = block(fmap(
9
8
  visualize(trimEnd(some(union([inline])))),
10
- ns => [html('p', defrag(ns))])));
9
+ ns => [html('p', defrag(ns))]));
@@ -4,7 +4,6 @@ import { cite } from './reply/cite';
4
4
  import { quote, syntax as delimiter } from './reply/quote';
5
5
  import { inline } from '../inline';
6
6
  import { anyline } from '../source';
7
- import { localize } from '../locale';
8
7
  import { visualize } from '../visibility';
9
8
  import { push, pop } from 'spica/array';
10
9
  import { html, defrag } from 'typed-dom/dom';
@@ -16,7 +15,7 @@ import { html, defrag } from 'typed-dom/dom';
16
15
  対象と引用は1:N(分割)、N:1(統合)のみ可能、N:N(混合)は不可能
17
16
  */
18
17
 
19
- export const reply: ReplyParser = block(validate('>', localize(fmap(
18
+ export const reply: ReplyParser = block(validate('>', fmap(
20
19
  inits([
21
20
  some(inits([
22
21
  cite,
@@ -30,4 +29,4 @@ export const reply: ReplyParser = block(validate('>', localize(fmap(
30
29
  ns => push(ns, [html('br')])),
31
30
  ])),
32
31
  ]),
33
- ns => [html('p', defrag(pop(ns)[0]))]))));
32
+ ns => [html('p', defrag(pop(ns)[0]))])));
@@ -1,28 +1,23 @@
1
1
  export const enum Syntax {
2
- reference = 1 << 13,
3
- comment = 1 << 12,
4
- index = 1 << 11,
5
- placeholder = 1 << 10,
6
- ruby = 1 << 9,
7
- link = 1 << 8,
8
- bracket = 1 << 7,
9
- media = 1 << 6,
10
- annotation = 1 << 5,
11
- mathbracket = 1 << 4,
12
- html = 1 << 3,
13
- math = 1 << 2,
2
+ reference = 1 << 8,
3
+ index = 1 << 7,
4
+ placeholder = 1 << 6,
5
+ ruby = 1 << 5,
6
+ link = 1 << 4,
7
+ bracket = 1 << 3,
8
+ media = 1 << 2,
14
9
  autolink = 1 << 1,
15
- quote = 1 << 0,
16
10
  none = 0,
17
11
  }
18
12
 
19
13
  export const enum State {
20
- annotation = 1 << 7,
21
- reference = 1 << 6,
22
- index = 1 << 5,
23
- label = 1 << 4,
24
- link = 1 << 3,
25
- media = 1 << 2,
14
+ annotation = 1 << 8,
15
+ reference = 1 << 7,
16
+ index = 1 << 6,
17
+ label = 1 << 5,
18
+ link = 1 << 4,
19
+ media = 1 << 3,
20
+ mark = 1 << 2,
26
21
  autolink = 1 << 1,
27
22
  shortcut = 1 << 0,
28
23
  none = 0,
@@ -33,6 +28,7 @@ export const enum State {
33
28
  | State.index
34
29
  | State.label
35
30
  | State.link
31
+ | State.mark
36
32
  | State.autolink,
37
33
  backtrackers = 0
38
34
  | State.annotation
@@ -8,7 +8,7 @@ import { html, defrag } from 'typed-dom/dom';
8
8
  export const annotation: AnnotationParser = lazy(() => surround(
9
9
  '((',
10
10
  constraint(State.annotation, false,
11
- syntax(Syntax.annotation, 6, 1, State.annotation | State.media,
11
+ syntax(Syntax.none, 6, 1, State.annotation | State.media,
12
12
  startLoose(
13
13
  context({ delimiters: undefined },
14
14
  some(union([inline]), ')', [[/^\\?\n/, 9], [')', 2], ['))', 6]])), ')'))),
@@ -78,7 +78,7 @@ describe('Unit: parser/inline/bracket', () => {
78
78
  assert.deepStrictEqual(inspect(parser('"(("')), [['"', '', '(', '', '(', '"'], '']);
79
79
  assert.deepStrictEqual(inspect(parser('"(\\")"')), [['"', '<span class="paren">(")</span>', '"'], '']);
80
80
  assert.deepStrictEqual(inspect(parser('"(\n)"')), [['"', '<span class="paren">(<br>)</span>', '"'], '']);
81
- assert.deepStrictEqual(inspect(parser('"(\\\n)"')), [['"', '<span class="paren">(<span class="linebreak"> </span>)</span>', '"'], '']);
81
+ assert.deepStrictEqual(inspect(parser('"(\\\n)"')), [['"', '<span class="paren">(<br>)</span>', '"'], '']);
82
82
  });
83
83
 
84
84
  });
@@ -24,7 +24,7 @@ export const bracket: BracketParser = lazy(() => union([
24
24
  undefined,
25
25
  ([as, bs = []], rest) => [unshift(as, bs), rest]),
26
26
  // Control media blinking in editing rather than control confusion of pairs of quote marks.
27
- surround(str('"'), syntax(Syntax.quote, 8, 1, State.none, some(inline, '"', [['"', 8]])), str('"'), true,
27
+ surround(str('"'), syntax(Syntax.none, 8, 1, State.none, some(inline, '"', [['"', 8]])), str('"'), true,
28
28
  undefined,
29
29
  ([as, bs = []], rest) => [unshift(as, bs), rest]),
30
30
  ]));
@@ -23,7 +23,7 @@ describe('Unit: parser/inline/deletion', () => {
23
23
  assert.deepStrictEqual(inspect(parser('~~ a ~~')), [['<del> a </del>'], '']);
24
24
  assert.deepStrictEqual(inspect(parser('~~ a ~~')), [['<del> a </del>'], '']);
25
25
  assert.deepStrictEqual(inspect(parser('~~\na~~')), [['<del><br>a</del>'], '']);
26
- assert.deepStrictEqual(inspect(parser('~~\\\na~~')), [['<del><span class="linebreak"> </span>a</del>'], '']);
26
+ assert.deepStrictEqual(inspect(parser('~~\\\na~~')), [['<del><br>a</del>'], '']);
27
27
  assert.deepStrictEqual(inspect(parser('~~<wbr>a~~')), [['<del><wbr>a</del>'], '']);
28
28
  assert.deepStrictEqual(inspect(parser('~~a ~~')), [['<del>a </del>'], '']);
29
29
  assert.deepStrictEqual(inspect(parser('~~a \n ~~')), [['<del>a </del>'], '']);
@@ -31,7 +31,7 @@ describe('Unit: parser/inline/deletion', () => {
31
31
  assert.deepStrictEqual(inspect(parser('~~a\n ~~')), [['<del>a </del>'], '']);
32
32
  assert.deepStrictEqual(inspect(parser('~~a\n<wbr>~~')), [['<del>a<wbr></del>'], '']);
33
33
  assert.deepStrictEqual(inspect(parser('~~a\nb~~')), [['<del>a<br>b</del>'], '']);
34
- assert.deepStrictEqual(inspect(parser('~~a\\\nb~~')), [['<del>a<span class="linebreak"> </span>b</del>'], '']);
34
+ assert.deepStrictEqual(inspect(parser('~~a\\\nb~~')), [['<del>a<br>b</del>'], '']);
35
35
  assert.deepStrictEqual(inspect(parser('~~\\~~~')), [['<del>~</del>'], '']);
36
36
  assert.deepStrictEqual(inspect(parser('~~a~~~')), [['<del>a</del>'], '~']);
37
37
  });
@@ -12,8 +12,10 @@ describe('Unit: parser/inline/emphasis', () => {
12
12
  assert.deepStrictEqual(inspect(parser('_a _')), [['_', 'a'], ' _']);
13
13
  assert.deepStrictEqual(inspect(parser('_a _')), [['_', 'a', ' '], ' _']);
14
14
  assert.deepStrictEqual(inspect(parser('_a\n_')), [['_', 'a'], '\n_']);
15
+ assert.deepStrictEqual(inspect(parser('_a\nb_')), [['_', 'a'], '\nb_']);
15
16
  assert.deepStrictEqual(inspect(parser('_a\\ _')), [['_', 'a'], '\\ _']);
16
17
  assert.deepStrictEqual(inspect(parser('_a\\\n_')), [['_', 'a'], '\\\n_']);
18
+ assert.deepStrictEqual(inspect(parser('_a\\\nb_')), [['_', 'a'], '\\\nb_']);
17
19
  assert.deepStrictEqual(inspect(parser('_ _')), undefined);
18
20
  assert.deepStrictEqual(inspect(parser('_ a_')), undefined);
19
21
  assert.deepStrictEqual(inspect(parser('_ a _')), undefined);
@@ -28,8 +30,6 @@ describe('Unit: parser/inline/emphasis', () => {
28
30
  it('basic', () => {
29
31
  assert.deepStrictEqual(inspect(parser('_a_')), [['<em>a</em>'], '']);
30
32
  assert.deepStrictEqual(inspect(parser('_ab_')), [['<em>ab</em>'], '']);
31
- assert.deepStrictEqual(inspect(parser('_a\nb_')), [['<em>a<br>b</em>'], '']);
32
- assert.deepStrictEqual(inspect(parser('_a\\\nb_')), [['<em>a<span class="linebreak"> </span>b</em>'], '']);
33
33
  });
34
34
 
35
35
  it('nest', () => {
@@ -11,8 +11,8 @@ export const emphasis: EmphasisParser = lazy(() => surround(
11
11
  str('_', '_'),
12
12
  syntax(Syntax.none, 1, 1, State.none,
13
13
  startTight(some(union([
14
- some(inline, blankWith('_')),
15
- open(some(inline, '_'), emphasis),
14
+ some(inline, blankWith('_'), [[/^\\?\n/, 9]]),
15
+ open(some(inline, '_', [[/^\\?\n/, 9]]), emphasis),
16
16
  ])))),
17
17
  str('_'), false,
18
18
  ([, bs], rest) => [[html('em', defrag(bs))], rest],
@@ -20,19 +20,17 @@ describe('Unit: parser/inline/extension/index', () => {
20
20
  assert.deepStrictEqual(inspect(parser('[#\\]')), undefined);
21
21
  assert.deepStrictEqual(inspect(parser('[#a')), undefined);
22
22
  assert.deepStrictEqual(inspect(parser('[#*a\nb*]')), undefined);
23
- assert.deepStrictEqual(inspect(parser('[#a\n|#b]')), undefined);
24
- assert.deepStrictEqual(inspect(parser('[#a|#\n]')), undefined);
25
- assert.deepStrictEqual(inspect(parser('[#a|#\\\n]')), undefined);
26
- assert.deepStrictEqual(inspect(parser('[#a|#(\n)]')), undefined);
27
- assert.deepStrictEqual(inspect(parser('[#a|#(\\\n)]')), undefined);
23
+ assert.deepStrictEqual(inspect(parser('[#a\n|b]')), undefined);
24
+ assert.deepStrictEqual(inspect(parser('[#a|\n]')), undefined);
25
+ assert.deepStrictEqual(inspect(parser('[#a|\\\n]')), undefined);
26
+ assert.deepStrictEqual(inspect(parser('[#a|(\n)]')), undefined);
27
+ assert.deepStrictEqual(inspect(parser('[#a|(\\\n)]')), undefined);
28
28
  assert.deepStrictEqual(inspect(parser('[# |]')), undefined);
29
- assert.deepStrictEqual(inspect(parser('[# |#]')), undefined);
30
- assert.deepStrictEqual(inspect(parser('[# |#b]')), undefined);
29
+ assert.deepStrictEqual(inspect(parser('[# |b]')), undefined);
31
30
  assert.deepStrictEqual(inspect(parser('[# a|]')), undefined);
32
- assert.deepStrictEqual(inspect(parser('[# a|#]')), undefined);
33
- assert.deepStrictEqual(inspect(parser('[# a|#b]')), undefined);
34
- assert.deepStrictEqual(inspect(parser('[# a|# ]')), undefined);
35
- assert.deepStrictEqual(inspect(parser('[# a|# b]')), undefined);
31
+ assert.deepStrictEqual(inspect(parser('[# a|b]')), undefined);
32
+ assert.deepStrictEqual(inspect(parser('[# a| ]')), undefined);
33
+ assert.deepStrictEqual(inspect(parser('[# a| b]')), undefined);
36
34
  assert.deepStrictEqual(inspect(parser(' [#a]')), undefined);
37
35
  });
38
36
 
@@ -70,28 +68,26 @@ describe('Unit: parser/inline/extension/index', () => {
70
68
 
71
69
  it('indexer', () => {
72
70
  assert.deepStrictEqual(inspect(parser('[#|]')), [['<a class="index" href="#index:|">|</a>'], '']);
73
- assert.deepStrictEqual(inspect(parser('[#|#]')), [['<a class="index" href="#index:|#">|#</a>'], '']);
74
- assert.deepStrictEqual(inspect(parser('[#|#b]')), [['<a class="index" href="#index:|#b">|#b</a>'], '']);
71
+ assert.deepStrictEqual(inspect(parser('[#|b]')), [['<a class="index" href="#index:|b">|b</a>'], '']);
75
72
  assert.deepStrictEqual(inspect(parser('[#a|]')), [['<a class="index" href="#index:a|">a|</a>'], '']);
76
- assert.deepStrictEqual(inspect(parser('[#a|#]')), [['<a class="index" href="#index:a|#">a|#</a>'], '']);
77
- assert.deepStrictEqual(inspect(parser('[#a|# ]')), [['<a class="index" href="#index:a|#">a|#</a>'], '']);
78
- assert.deepStrictEqual(inspect(parser('[#a|#\\ ]')), [['<a class="index" href="#index:a|#">a|#</a>'], '']);
79
- assert.deepStrictEqual(inspect(parser('[#a|#b]')), [['<a class="index" href="#index:b">a<span class="indexer" data-index="b"></span></a>'], '']);
80
- assert.deepStrictEqual(inspect(parser('[#a|#b ]')), [['<a class="index" href="#index:b">a<span class="indexer" data-index="b"></span></a>'], '']);
81
- assert.deepStrictEqual(inspect(parser('[#a|#b ]')), [['<a class="index" href="#index:b">a<span class="indexer" data-index="b"></span></a>'], '']);
82
- assert.deepStrictEqual(inspect(parser('[#a|#\\b]')), [['<a class="index" href="#index:b">a<span class="indexer" data-index="b"></span></a>'], '']);
83
- assert.deepStrictEqual(inspect(parser('[#a|#_b_]')), [['<a class="index" href="#index:_b_">a<span class="indexer" data-index="_b_"></span></a>'], '']);
84
- assert.deepStrictEqual(inspect(parser('[#a|#b c]')), [['<a class="index" href="#index:b_c">a<span class="indexer" data-index="b_c"></span></a>'], '']);
85
- assert.deepStrictEqual(inspect(parser('[#a|#b c]')), [['<a class="index" href="#index:b_c">a<span class="indexer" data-index="b_c"></span></a>'], '']);
86
- assert.deepStrictEqual(inspect(parser('[#a|#[]]')), [['<a class="index" href="#index:[]">a<span class="indexer" data-index="[]"></span></a>'], '']);
87
- assert.deepStrictEqual(inspect(parser('[#a|#&copy;]')), [['<a class="index" href="#index:&amp;copy;">a<span class="indexer" data-index="&amp;copy;"></span></a>'], '']);
88
- assert.deepStrictEqual(inspect(parser('[#a |#b]')), [['<a class="index" href="#index:b">a<span class="indexer" data-index="b"></span></a>'], '']);
89
- assert.deepStrictEqual(inspect(parser('[#a |#b]')), [['<a class="index" href="#index:b">a<span class="indexer" data-index="b"></span></a>'], '']);
90
- assert.deepStrictEqual(inspect(parser('[#a \\ |#b]')), [['<a class="index" href="#index:b">a<span class="indexer" data-index="b"></span></a>'], '']);
91
- assert.deepStrictEqual(inspect(parser('[#a &nbsp;|#b]')), [['<a class="index" href="#index:b">a<span class="indexer" data-index="b"></span></a>'], '']);
92
- assert.deepStrictEqual(inspect(parser('[#a <wbr>|#b]')), [['<a class="index" href="#index:b">a<span class="indexer" data-index="b"></span></a>'], '']);
93
- assert.deepStrictEqual(inspect(parser('[#a [% b %]|#c]')), [['<a class="index" href="#index:c">a <span class="comment"><input type="checkbox"><span>[% b %]</span></span><span class="indexer" data-index="c"></span></a>'], '']);
94
- assert.deepStrictEqual(inspect(parser('[#a\\ |#b]')), [['<a class="index" href="#index:b">a<span class="indexer" data-index="b"></span></a>'], '']);
73
+ assert.deepStrictEqual(inspect(parser('[#a| ]')), [['<a class="index" href="#index:a|">a|</a>'], '']);
74
+ assert.deepStrictEqual(inspect(parser('[#a|\\ ]')), [['<a class="index" href="#index:a|">a|</a>'], '']);
75
+ assert.deepStrictEqual(inspect(parser('[#a|b]')), [['<a class="index" href="#index:b">a<span class="indexer" data-index="b"></span></a>'], '']);
76
+ assert.deepStrictEqual(inspect(parser('[#a|b ]')), [['<a class="index" href="#index:b">a<span class="indexer" data-index="b"></span></a>'], '']);
77
+ assert.deepStrictEqual(inspect(parser('[#a|b ]')), [['<a class="index" href="#index:b">a<span class="indexer" data-index="b"></span></a>'], '']);
78
+ assert.deepStrictEqual(inspect(parser('[#a|\\b]')), [['<a class="index" href="#index:b">a<span class="indexer" data-index="b"></span></a>'], '']);
79
+ assert.deepStrictEqual(inspect(parser('[#a|_b_]')), [['<a class="index" href="#index:_b_">a<span class="indexer" data-index="_b_"></span></a>'], '']);
80
+ assert.deepStrictEqual(inspect(parser('[#a|b c]')), [['<a class="index" href="#index:b_c">a<span class="indexer" data-index="b_c"></span></a>'], '']);
81
+ assert.deepStrictEqual(inspect(parser('[#a|b c]')), [['<a class="index" href="#index:b_c">a<span class="indexer" data-index="b_c"></span></a>'], '']);
82
+ assert.deepStrictEqual(inspect(parser('[#a|[]]')), [['<a class="index" href="#index:[]">a<span class="indexer" data-index="[]"></span></a>'], '']);
83
+ assert.deepStrictEqual(inspect(parser('[#a|&copy;]')), [['<a class="index" href="#index:&amp;copy;">a<span class="indexer" data-index="&amp;copy;"></span></a>'], '']);
84
+ assert.deepStrictEqual(inspect(parser('[#a |b]')), [['<a class="index" href="#index:b">a<span class="indexer" data-index="b"></span></a>'], '']);
85
+ assert.deepStrictEqual(inspect(parser('[#a |b]')), [['<a class="index" href="#index:b">a<span class="indexer" data-index="b"></span></a>'], '']);
86
+ assert.deepStrictEqual(inspect(parser('[#a \\ |b]')), [['<a class="index" href="#index:b">a<span class="indexer" data-index="b"></span></a>'], '']);
87
+ assert.deepStrictEqual(inspect(parser('[#a &nbsp;|b]')), [['<a class="index" href="#index:b">a<span class="indexer" data-index="b"></span></a>'], '']);
88
+ assert.deepStrictEqual(inspect(parser('[#a <wbr>|b]')), [['<a class="index" href="#index:b">a<span class="indexer" data-index="b"></span></a>'], '']);
89
+ assert.deepStrictEqual(inspect(parser('[#a [% b %]|c]')), [['<a class="index" href="#index:c">a <span class="comment"><input type="checkbox"><span>[% b %]</span></span><span class="indexer" data-index="c"></span></a>'], '']);
90
+ assert.deepStrictEqual(inspect(parser('[#a\\ |b]')), [['<a class="index" href="#index:b">a<span class="indexer" data-index="b"></span></a>'], '']);
95
91
  });
96
92
 
97
93
  });
@@ -32,7 +32,7 @@ export const index: IndexParser = lazy(() => validate('[#', fmap(indexee(surroun
32
32
  ])));
33
33
 
34
34
  const signature: IndexParser.SignatureParser = lazy(() => creation(fmap(open(
35
- '|#',
35
+ '|',
36
36
  startTight(some(union([bracket, txt]), ']'))),
37
37
  ns => [
38
38
  html('span', { class: 'indexer', 'data-index': identity(ns.join('')).slice(6) }),
@@ -8,14 +8,23 @@ export function indexee(parser: Parser<HTMLElement, MarkdownParser.Context>, opt
8
8
  return fmap(parser, ([el], _, { id }) => [define(el, { id: id !== '' && identity(text(el, optional)) || undefined })]);
9
9
  }
10
10
 
11
- export function identity(text: string): string {
11
+ export function identity(text: string, name: 'index' | 'mark' = 'index'): string {
12
12
  assert(!text.includes('\n'));
13
- text &&= text.trim();
14
- return text && `index:${text.replace(/\s+/g, '_').slice(0, 101).replace(/^(.{97}).{4}$/, '$1...')}`;
13
+ text &&= text.trim().replace(/\s+/g, '_');
14
+ if (text.length <= 100) return text && `${name}:${text}`;
15
+ switch (name) {
16
+ case 'index':
17
+ return `${name}:${text.slice(0, 97)}...`;
18
+ case 'mark':
19
+ return `${name}:${text.slice(0, 50)}...${text.slice(-47)}`;
20
+ }
15
21
  }
16
- assert(identity('0'.repeat(100)).slice(6) === '0'.repeat(100));
17
- assert(identity('0'.repeat(101)).slice(6) === '0'.repeat(97) + '...');
18
- assert(identity('0'.repeat(200)).slice(6) === '0'.repeat(97) + '...');
22
+ assert(identity('0'.repeat(100 - 1) + 1).slice(6) === '0'.repeat(100 - 1) + 1);
23
+ assert(identity('0'.repeat(100) + 1).slice(6) === '0'.repeat(97) + '...');
24
+ assert(identity('0'.repeat(200) + 1).slice(6) === '0'.repeat(97) + '...');
25
+ assert(identity('0'.repeat(100 - 1) + 1, 'mark').slice(5) === '0'.repeat(100 - 1) + 1);
26
+ assert(identity('0'.repeat(100) + 1, 'mark').slice(5) === '0'.repeat(50) + '...' + '0'.repeat(47 - 1) + 1);
27
+ assert(identity('0'.repeat(200) + 1, 'mark').slice(5) === '0'.repeat(50) + '...' + '0'.repeat(47 - 1) + 1);
19
28
 
20
29
  export function text(source: HTMLElement | DocumentFragment, optional = false): string {
21
30
  assert(source instanceof DocumentFragment || !source.matches('.indexer'));
@@ -24,9 +33,9 @@ export function text(source: HTMLElement | DocumentFragment, optional = false):
24
33
  if (!indexer && optional) return '';
25
34
  const index = indexer?.getAttribute('data-index');
26
35
  if (index) return index;
27
- assert(!source.querySelector('.annotation, br'));
36
+ assert(!source.querySelector('br'));
28
37
  const target = source.cloneNode(true) as typeof source;
29
- for (let es = target.querySelectorAll('code[data-src], .math[data-src], .comment, rt, rp, .reference, .checkbox, ul, ol'),
38
+ for (let es = target.querySelectorAll('code[data-src], .math[data-src], .comment, rt, rp, br, .annotation, .reference, .checkbox, ul, ol'),
30
39
  len = es.length, i = 0; i < len; ++i) {
31
40
  const el = es[i];
32
41
  switch (el.tagName) {
@@ -39,6 +48,9 @@ export function text(source: HTMLElement | DocumentFragment, optional = false):
39
48
  case 'OL':
40
49
  el.remove();
41
50
  continue;
51
+ case 'BR':
52
+ el.replaceWith('\n');
53
+ continue;
42
54
  }
43
55
  switch (el.className) {
44
56
  case 'math':
@@ -46,11 +58,9 @@ export function text(source: HTMLElement | DocumentFragment, optional = false):
46
58
  continue;
47
59
  case 'comment':
48
60
  case 'checkbox':
49
- el.remove();
50
- continue;
61
+ case 'annotation':
51
62
  case 'reference':
52
- assert(el.firstElementChild?.hasAttribute('hidden'));
53
- el.firstChild!.remove();
63
+ el.remove();
54
64
  continue;
55
65
  }
56
66
  }