securemark 0.283.4 → 0.283.5

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 (57) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/dist/index.js +76 -55
  3. package/package.json +1 -1
  4. package/src/parser/block/blockquote.ts +1 -1
  5. package/src/parser/block/dlist.ts +6 -6
  6. package/src/parser/block/extension/aside.ts +1 -1
  7. package/src/parser/block/extension/example.ts +2 -2
  8. package/src/parser/block/extension/figure.ts +3 -3
  9. package/src/parser/block/extension/table.ts +5 -5
  10. package/src/parser/block/heading.ts +6 -6
  11. package/src/parser/block/ilist.ts +1 -1
  12. package/src/parser/block/olist.ts +1 -1
  13. package/src/parser/block/paragraph.ts +3 -3
  14. package/src/parser/block/reply.ts +2 -2
  15. package/src/parser/block/sidefence.ts +1 -1
  16. package/src/parser/block/table.ts +4 -4
  17. package/src/parser/block/ulist.ts +1 -1
  18. package/src/parser/block.ts +4 -3
  19. package/src/parser/context.ts +10 -0
  20. package/src/parser/inline/annotation.ts +7 -4
  21. package/src/parser/inline/autolink/account.ts +1 -1
  22. package/src/parser/inline/autolink/anchor.ts +1 -1
  23. package/src/parser/inline/autolink/channel.ts +1 -1
  24. package/src/parser/inline/autolink/email.ts +1 -1
  25. package/src/parser/inline/autolink/hashnum.ts +1 -1
  26. package/src/parser/inline/autolink/hashtag.ts +1 -1
  27. package/src/parser/inline/autolink/url.ts +1 -1
  28. package/src/parser/inline/autolink.ts +1 -1
  29. package/src/parser/inline/bracket.ts +6 -6
  30. package/src/parser/inline/code.ts +1 -1
  31. package/src/parser/inline/deletion.ts +1 -1
  32. package/src/parser/inline/emphasis.ts +1 -1
  33. package/src/parser/inline/emstrong.ts +1 -1
  34. package/src/parser/inline/extension/index.ts +9 -6
  35. package/src/parser/inline/extension/indexer.ts +1 -1
  36. package/src/parser/inline/extension/label.ts +1 -1
  37. package/src/parser/inline/extension/placeholder.ts +1 -1
  38. package/src/parser/inline/html.ts +1 -1
  39. package/src/parser/inline/htmlentity.ts +3 -3
  40. package/src/parser/inline/insertion.ts +1 -1
  41. package/src/parser/inline/link.test.ts +7 -2
  42. package/src/parser/inline/link.ts +5 -10
  43. package/src/parser/inline/mark.ts +1 -1
  44. package/src/parser/inline/math.ts +1 -1
  45. package/src/parser/inline/media.ts +4 -4
  46. package/src/parser/inline/reference.ts +7 -4
  47. package/src/parser/inline/remark.ts +1 -1
  48. package/src/parser/inline/ruby.ts +3 -3
  49. package/src/parser/inline/shortmedia.ts +1 -1
  50. package/src/parser/inline/strong.ts +1 -1
  51. package/src/parser/inline/template.ts +2 -2
  52. package/src/parser/segment.ts +3 -2
  53. package/src/parser/source/escapable.ts +2 -2
  54. package/src/parser/source/str.ts +1 -1
  55. package/src/parser/source/text.ts +3 -3
  56. package/src/parser/source/unescapable.ts +4 -2
  57. package/src/parser/visibility.ts +14 -13
@@ -1,9 +1,9 @@
1
1
  import { HeadingParser } from '../block';
2
+ import { State } from '../context';
2
3
  import { union, some, state, block, line, validate, focus, rewrite, open, fmap } from '../../combinator';
3
4
  import { inline, indexee, indexer, dataindex } from '../inline';
4
5
  import { str } from '../source';
5
- import { State } from '../context';
6
- import { visualize, trimBlankStart, trimNodeEnd } from '../visibility';
6
+ import { visualize, trimBlank } from '../visibility';
7
7
  import { html, defrag } from 'typed-dom/dom';
8
8
 
9
9
  export const segment: HeadingParser.SegmentParser = block(validate('#', focus(
@@ -16,19 +16,19 @@ export const heading: HeadingParser = block(rewrite(segment,
16
16
  line(indexee(fmap(union([
17
17
  open(
18
18
  str(/^##+/),
19
- visualize(trimBlankStart(some(union([indexer, inline])))), true),
19
+ visualize(trimBlank(some(union([indexer, inline])))), true),
20
20
  open(
21
21
  str('#'),
22
22
  state(State.linkers,
23
- visualize(trimBlankStart(some(union([indexer, inline]))))), true),
23
+ visualize(trimBlank(some(union([indexer, inline]))))), true),
24
24
  ]),
25
25
  ([h, ...ns]: [string, ...(HTMLElement | string)[]]) => [
26
26
  h.length <= 6
27
- ? html(`h${h.length as 1}`, { 'data-index': dataindex(ns) }, trimNodeEnd(defrag(ns)))
27
+ ? html(`h${h.length as 1}`, { 'data-index': dataindex(ns) }, defrag(ns))
28
28
  : html(`h6`, {
29
29
  class: 'invalid',
30
30
  'data-invalid-syntax': 'heading',
31
31
  'data-invalid-type': 'syntax',
32
32
  'data-invalid-message': 'Heading level must be up to 6',
33
- }, trimNodeEnd(defrag(ns)))
33
+ }, defrag(ns))
34
34
  ]))))));
@@ -1,9 +1,9 @@
1
1
  import { IListParser } from '../block';
2
+ import { Recursion } from '../context';
2
3
  import { union, inits, some, creation, block, line, validate, indent, open, trim, fallback, lazy, fmap } from '../../combinator';
3
4
  import { ulist_, invalid, fillFirstLine } from './ulist';
4
5
  import { olist_ } from './olist';
5
6
  import { inline } from '../inline';
6
- import { Recursion } from '../context';
7
7
  import { lineable } from '../util';
8
8
  import { visualize, trimBlank } from '../visibility';
9
9
  import { html, defrag } from 'typed-dom/dom';
@@ -1,11 +1,11 @@
1
1
  import { OListParser } from '../block';
2
+ import { Recursion } from '../context';
2
3
  import { union, inits, subsequence, some, creation, block, line, validate, indent, focus, open, match, trim, fallback, lazy, fmap } from '../../combinator';
3
4
  import { ulist_, checkbox, invalid, fillFirstLine } from './ulist';
4
5
  import { ilist_ } from './ilist';
5
6
  import { inline, indexee, indexer, dataindex } from '../inline';
6
7
  import { lineable } from '../util';
7
8
  import { visualize, trimBlank } from '../visibility';
8
- import { Recursion } from '../context';
9
9
  import { memoize } from 'spica/memoize';
10
10
  import { html, define, defrag } from 'typed-dom/dom';
11
11
 
@@ -2,9 +2,9 @@ import { ParagraphParser } from '../block';
2
2
  import { union, some, block, fmap } from '../../combinator';
3
3
  import { inline } from '../inline';
4
4
  import { lineable } from '../util';
5
- import { visualize, trimNodeEnd } from '../visibility';
5
+ import { visualize, trimBlankEnd } from '../visibility';
6
6
  import { html, defrag } from 'typed-dom/dom';
7
7
 
8
8
  export const paragraph: ParagraphParser = block(fmap(
9
- visualize(lineable(some(union([inline])))),
10
- ns => [html('p', trimNodeEnd(defrag(ns)))]));
9
+ visualize(trimBlankEnd(lineable(some(union([inline]))))),
10
+ ns => [html('p', defrag(ns))]));
@@ -5,7 +5,7 @@ import { quote, syntax as delimiter } from './reply/quote';
5
5
  import { inline } from '../inline';
6
6
  import { anyline } from '../source';
7
7
  import { lineable } from '../util';
8
- import { visualize, trimNodeEnd } from '../visibility';
8
+ import { visualize, trimBlankNodeEnd } from '../visibility';
9
9
  import { push } from 'spica/array';
10
10
  import { html, defrag } from 'typed-dom/dom';
11
11
 
@@ -30,4 +30,4 @@ export const reply: ReplyParser = block(validate('>', fmap(
30
30
  ns => push(ns, [html('br')])),
31
31
  ])),
32
32
  ]),
33
- ns => [html('p', trimNodeEnd(defrag(ns)))])));
33
+ ns => [html('p', trimBlankNodeEnd(defrag(ns)))])));
@@ -1,8 +1,8 @@
1
1
  import { SidefenceParser } from '../block';
2
+ import { Recursion } from '../context';
2
3
  import { union, some, creation, block, focus, rewrite, convert, lazy, fmap } from '../../combinator';
3
4
  import { autolink } from '../autolink';
4
5
  import { contentline } from '../source';
5
- import { Recursion } from '../context';
6
6
  import { html, define, defrag } from 'typed-dom/dom';
7
7
 
8
8
  export const sidefence: SidefenceParser = lazy(() => block(fmap(focus(
@@ -2,7 +2,7 @@ import { TableParser } from '../block';
2
2
  import { union, sequence, some, block, line, validate, focus, rewrite, surround, open, close, trimStart, fallback, lazy, fmap } from '../../combinator';
3
3
  import { inline, media, medialink, shortmedia } from '../inline';
4
4
  import { contentline } from '../source';
5
- import { trimBlankStart, trimNodeEnd } from '../visibility';
5
+ import { trimBlank } from '../visibility';
6
6
  import { duffReduce } from 'spica/duff';
7
7
  import { push } from 'spica/array';
8
8
  import { html, defrag } from 'typed-dom/dom';
@@ -53,17 +53,17 @@ const cell: CellParser = surround(
53
53
  close(medialink, /^\s*(?=\||$)/),
54
54
  close(media, /^\s*(?=\||$)/),
55
55
  close(shortmedia, /^\s*(?=\||$)/),
56
- trimBlankStart(some(inline, /^\|/, [[/^[|\\]?\s*$/, 9]])),
56
+ trimBlank(some(inline, /^\|/, [[/^[|\\]?\s*$/, 9]])),
57
57
  ])),
58
58
  /^[^|]*/, true);
59
59
 
60
60
  const head: CellParser.HeadParser = fmap(
61
61
  cell,
62
- ns => [html('th', trimNodeEnd(defrag(ns)))]);
62
+ ns => [html('th', defrag(ns))]);
63
63
 
64
64
  const data: CellParser.DataParser = fmap(
65
65
  cell,
66
- ns => [html('td', trimNodeEnd(defrag(ns)))]);
66
+ ns => [html('td', defrag(ns))]);
67
67
 
68
68
  function format(rows: HTMLTableRowElement[]): HTMLTableRowElement[] {
69
69
  const aligns = rows[0].className === 'invalid'
@@ -1,11 +1,11 @@
1
1
  import { UListParser } from '../block';
2
2
  import { Parser } from '../../combinator/data/parser';
3
+ import { Recursion } from '../context';
3
4
  import { union, inits, subsequence, some, creation, block, line, validate, indent, focus, rewrite, open, trim, fallback, lazy, fmap } from '../../combinator';
4
5
  import { olist_ } from './olist';
5
6
  import { ilist_ } from './ilist';
6
7
  import { inline, indexer, indexee, dataindex } from '../inline';
7
8
  import { contentline } from '../source';
8
- import { Recursion } from '../context';
9
9
  import { lineable } from '../util';
10
10
  import { visualize, trimBlank } from '../visibility';
11
11
  import { unshift } from 'spica/array';
@@ -1,4 +1,5 @@
1
1
  import { MarkdownParser } from '../../markdown';
2
+ import { Recursion, Command } from './context';
2
3
  import { union, reset, open, fallback, recover } from '../combinator';
3
4
  import { emptyline } from './source';
4
5
  import { pagebreak } from './block/pagebreak';
@@ -16,7 +17,6 @@ import { blockquote } from './block/blockquote';
16
17
  import { mediablock } from './block/mediablock';
17
18
  import { reply } from './block/reply';
18
19
  import { paragraph } from './block/paragraph';
19
- import { Recursion } from './context';
20
20
  import { rnd0Z } from 'spica/random';
21
21
  import { html } from 'typed-dom/dom';
22
22
 
@@ -71,8 +71,9 @@ export const block: BlockParser = reset(
71
71
  ])));
72
72
 
73
73
  function error(parser: BlockParser): BlockParser {
74
+ const reg = new RegExp(String.raw`^${Command.Error}.*\n`)
74
75
  return recover<BlockParser>(fallback(
75
- open('\x07', ({source}) => { throw new Error(source.split('\n', 1)[0]); }),
76
+ open(Command.Error, ({ source }) => { throw new Error(source.split('\n', 1)[0]); }),
76
77
  parser),
77
78
  ({ source, context: { id } }, reason) => [[
78
79
  html('h1',
@@ -89,7 +90,7 @@ function error(parser: BlockParser): BlockParser {
89
90
  translate: 'no',
90
91
  },
91
92
  source
92
- .replace(/^\x07.*\n/, '')
93
+ .replace(reg, '')
93
94
  .slice(0, 1001)
94
95
  .replace(/^(.{997}).{4}$/s, '$1...') || undefined),
95
96
  ], '']);
@@ -38,3 +38,13 @@ export const enum Backtrack {
38
38
  url = 2 << 2,
39
39
  bracket = 1 << 2,
40
40
  }
41
+
42
+ export const enum Command {
43
+ Error = '\x07',
44
+ Escape = '\x1B',
45
+ Separator = '\x1F',
46
+ }
47
+
48
+ export const CmdRegExp = {
49
+ Escape: /\x1B/g,
50
+ } as const;
@@ -1,16 +1,19 @@
1
1
  import { AnnotationParser } from '../inline';
2
+ import { State, Recursion, Backtrack } from '../context';
2
3
  import { union, some, syntax, creation, constraint, surround, lazy } from '../../combinator';
3
4
  import { inline } from '../inline';
4
- import { State, Recursion, Backtrack } from '../context';
5
- import { trimBlankStart, trimNodeEnd } from '../visibility';
5
+ import { trimBlankStart, trimBlankNodeEnd } from '../visibility';
6
6
  import { html, defrag } from 'typed-dom/dom';
7
7
 
8
8
  export const annotation: AnnotationParser = lazy(() => creation(1, Recursion.ignore, surround(
9
9
  '((',
10
10
  constraint(State.annotation, false,
11
11
  syntax(1, State.annotation | State.media,
12
- trimBlankStart(some(union([inline]), ')', [[/^\\?\n/, 9], [')', 1]])))),
12
+ trimBlankStart(some(union([inline]), ')', [['\n', 9], [')', 1]])))),
13
13
  '))',
14
14
  false,
15
- ([, ns], rest) => [[html('sup', { class: 'annotation' }, [html('span', trimNodeEnd(defrag(ns)))])], rest],
15
+ ([, ns], rest) =>
16
+ trimBlankNodeEnd(ns).length > 0
17
+ ? [[html('sup', { class: 'annotation' }, [html('span', defrag(ns))])], rest]
18
+ : undefined,
16
19
  undefined, 1 | Backtrack.bracket)));
@@ -1,8 +1,8 @@
1
1
  import { AutolinkParser } from '../../inline';
2
+ import { State } from '../../context';
2
3
  import { union, tails, syntax, constraint, rewrite, open, convert, fmap, lazy } from '../../../combinator';
3
4
  import { unsafelink } from '../link';
4
5
  import { str } from '../../source';
5
- import { State } from '../../context';
6
6
  import { define } from 'typed-dom/dom';
7
7
 
8
8
  // https://example/@user must be a user page or a redirect page going there.
@@ -1,7 +1,7 @@
1
1
  import { AutolinkParser } from '../../inline';
2
+ import { State } from '../../context';
2
3
  import { union, syntax, constraint, validate, focus, convert, fmap, lazy } from '../../../combinator';
3
4
  import { unsafelink } from '../link';
4
- import { State } from '../../context';
5
5
  import { define } from 'typed-dom/dom';
6
6
 
7
7
  // Timeline(pseudonym): user/tid
@@ -1,8 +1,8 @@
1
1
  import { AutolinkParser } from '../../inline';
2
+ import { State } from '../../context';
2
3
  import { sequence, some, constraint, validate, bind } from '../../../combinator';
3
4
  import { account } from './account';
4
5
  import { hashtag } from './hashtag';
5
- import { State } from '../../context';
6
6
  import { stringify } from '../../util';
7
7
  import { define } from 'typed-dom/dom';
8
8
 
@@ -1,7 +1,7 @@
1
1
  import { AutolinkParser } from '../../inline';
2
+ import { State, Recursion } from '../../context';
2
3
  import { syntax, creation, constraint, verify, rewrite } from '../../../combinator';
3
4
  import { str } from '../../source';
4
- import { State, Recursion } from '../../context';
5
5
  import { html } from 'typed-dom/dom';
6
6
 
7
7
  // https://html.spec.whatwg.org/multipage/input.html
@@ -1,9 +1,9 @@
1
1
  import { AutolinkParser } from '../../inline';
2
+ import { State } from '../../context';
2
3
  import { union, syntax, constraint, rewrite, open, convert, fmap, lazy } from '../../../combinator';
3
4
  import { unsafelink } from '../link';
4
5
  import { emoji } from './hashtag';
5
6
  import { str } from '../../source';
6
- import { State } from '../../context';
7
7
  import { define } from 'typed-dom/dom';
8
8
 
9
9
  export const hashnum: AutolinkParser.HashnumParser = lazy(() => rewrite(
@@ -1,8 +1,8 @@
1
1
  import { AutolinkParser } from '../../inline';
2
+ import { State } from '../../context';
2
3
  import { union, syntax, constraint, rewrite, open, convert, fmap, lazy } from '../../../combinator';
3
4
  import { unsafelink } from '../link';
4
5
  import { str } from '../../source';
5
- import { State } from '../../context';
6
6
  import { define } from 'typed-dom/dom';
7
7
 
8
8
  // https://example/hashtags/a must be a hashtag page or a redirect page going there.
@@ -1,8 +1,8 @@
1
1
  import { AutolinkParser } from '../../inline';
2
+ import { State, Recursion, Backtrack } from '../../context';
2
3
  import { union, tails, some, syntax, creation, precedence, constraint, validate, focus, rewrite, convert, surround, open, lazy } from '../../../combinator';
3
4
  import { unsafelink } from '../link';
4
5
  import { linebreak, unescsource, str } from '../../source';
5
- import { State, Recursion, Backtrack } from '../../context';
6
6
 
7
7
  const closer = /^[-+*=~^_,.;:!?]*(?=[\\"`|\[\](){}<>]|$)/;
8
8
 
@@ -1,4 +1,5 @@
1
1
  import { AutolinkParser } from '../inline';
2
+ import { State } from '../context';
2
3
  import { union, some, syntax, validate, lazy, fmap } from '../../combinator';
3
4
  import { url, lineurl } from './autolink/url';
4
5
  import { email } from './autolink/email';
@@ -8,7 +9,6 @@ import { hashtag, emoji } from './autolink/hashtag';
8
9
  import { hashnum } from './autolink/hashnum';
9
10
  import { anchor } from './autolink/anchor';
10
11
  import { str } from '../source';
11
- import { State } from '../context';
12
12
  import { stringify } from '../util';
13
13
 
14
14
  export const autolink: AutolinkParser = lazy(() =>
@@ -1,8 +1,8 @@
1
1
  import { BracketParser } from '../inline';
2
+ import { State, Recursion, Backtrack } from '../context';
2
3
  import { union, some, syntax, creation, surround, lazy } from '../../combinator';
3
4
  import { inline } from '../inline';
4
5
  import { str } from '../source';
5
- import { State, Recursion, Backtrack } from '../context';
6
6
  import { unshift, push } from 'spica/array';
7
7
  import { html, defrag } from 'typed-dom/dom';
8
8
 
@@ -32,19 +32,19 @@ export const bracket: BracketParser = lazy(() => union([
32
32
  undefined,
33
33
  ([as, bs = []], rest) => [unshift(as, bs), rest]),
34
34
  // 改行禁止はバックトラックなしでは内側の構文を破壊するため安易に行えない。
35
- surround(str('"'), creation(0, Recursion.bracket, syntax(2, State.none, some(inline, '"', [[/^\\?\n/, 9], ['"', 2]]))), str('"'), true,
35
+ surround(str('"'), creation(0, Recursion.bracket, syntax(2, State.none, some(inline, '"', [['\n', 9], ['"', 2]]))), str('"'), true,
36
36
  undefined,
37
37
  ([as, bs = []], rest) => [unshift(as, bs), rest]),
38
- surround(str('“'), creation(0, Recursion.bracket, syntax(2, State.none, some(inline, '”', [[/^\\?\n/, 9], ['”', 2]]))), str('”'), true,
38
+ surround(str('“'), creation(0, Recursion.bracket, syntax(2, State.none, some(inline, '”', [['\n', 9], ['”', 2]]))), str('”'), true,
39
39
  undefined,
40
40
  ([as, bs = []], rest) => [unshift(as, bs), rest]),
41
- surround(str('‘'), creation(0, Recursion.bracket, syntax(2, State.none, some(inline, '’', [[/^\\?\n/, 9], ['’', 2]]))), str('’'), true,
41
+ surround(str('‘'), creation(0, Recursion.bracket, syntax(2, State.none, some(inline, '’', [['\n', 9], ['’', 2]]))), str('’'), true,
42
42
  undefined,
43
43
  ([as, bs = []], rest) => [unshift(as, bs), rest]),
44
- surround(str('「'), creation(0, Recursion.bracket, syntax(2, State.none, some(inline, '」', [[/^\\?\n/, 9], ['」', 2]]))), str('」'), true,
44
+ surround(str('「'), creation(0, Recursion.bracket, syntax(2, State.none, some(inline, '」', [['\n', 9], ['」', 2]]))), str('」'), true,
45
45
  undefined,
46
46
  ([as, bs = []], rest) => [unshift(as, bs), rest]),
47
- surround(str('『'), creation(0, Recursion.bracket, syntax(2, State.none, some(inline, '』', [[/^\\?\n/, 9], ['』', 2]]))), str('』'), true,
47
+ surround(str('『'), creation(0, Recursion.bracket, syntax(2, State.none, some(inline, '』', [['\n', 9], ['』', 2]]))), str('』'), true,
48
48
  undefined,
49
49
  ([as, bs = []], rest) => [unshift(as, bs), rest]),
50
50
  ]));
@@ -1,6 +1,6 @@
1
1
  import { CodeParser } from '../inline';
2
- import { creation, validate, match } from '../../combinator';
3
2
  import { Recursion } from '../context';
3
+ import { creation, validate, match } from '../../combinator';
4
4
  import { html } from 'typed-dom/dom';
5
5
 
6
6
  export const code: CodeParser = creation(1, Recursion.ignore, validate('`', match(
@@ -1,8 +1,8 @@
1
1
  import { DeletionParser } from '../inline';
2
+ import { State, Recursion } from '../context';
2
3
  import { union, some, syntax, creation, surround, open, lazy } from '../../combinator';
3
4
  import { inline } from '../inline';
4
5
  import { str } from '../source';
5
- import { State, Recursion } from '../context';
6
6
  import { blankWith } from '../visibility';
7
7
  import { unshift } from 'spica/array';
8
8
  import { html, defrag } from 'typed-dom/dom';
@@ -1,10 +1,10 @@
1
1
  import { EmphasisParser } from '../inline';
2
+ import { State, Recursion } from '../context';
2
3
  import { union, some, syntax, creation, surround, open, lazy } from '../../combinator';
3
4
  import { inline } from '../inline';
4
5
  import { emstrong } from './emstrong';
5
6
  import { strong } from './strong';
6
7
  import { str } from '../source';
7
- import { State, Recursion } from '../context';
8
8
  import { startTight, blankWith } from '../visibility';
9
9
  import { unshift } from 'spica/array';
10
10
  import { html, defrag } from 'typed-dom/dom';
@@ -1,11 +1,11 @@
1
1
  import { EmStrongParser, EmphasisParser, StrongParser } from '../inline';
2
+ import { State, Recursion } from '../context';
2
3
  import { Result, IntermediateParser } from '../../combinator/data/parser';
3
4
  import { union, syntax, creation, some, surround, open, lazy, bind } from '../../combinator';
4
5
  import { inline } from '../inline';
5
6
  import { strong } from './strong';
6
7
  import { emphasis } from './emphasis';
7
8
  import { str } from '../source';
8
- import { State, Recursion } from '../context';
9
9
  import { startTight, blankWith } from '../visibility';
10
10
  import { html, defrag } from 'typed-dom/dom';
11
11
  import { unshift } from 'spica/array';
@@ -1,10 +1,10 @@
1
1
  import { ExtensionParser } from '../../inline';
2
+ import { State, Recursion, Backtrack } from '../../context';
2
3
  import { union, inits, some, syntax, creation, precedence, constraint, validate, surround, open, lazy, fmap } from '../../../combinator';
3
4
  import { inline } from '../../inline';
4
5
  import { indexee, identity } from './indexee';
5
6
  import { txt, str } from '../../source';
6
- import { State, Recursion, Backtrack } from '../../context';
7
- import { startTight, trimNodeEnd } from '../../visibility';
7
+ import { startTight, trimBlankNodeEnd } from '../../visibility';
8
8
  import { html, define, defrag } from 'typed-dom/dom';
9
9
 
10
10
  import IndexParser = ExtensionParser.IndexParser;
@@ -17,10 +17,13 @@ export const index: IndexParser = lazy(() => validate('[#', creation(1, Recursio
17
17
  some(inits([
18
18
  inline,
19
19
  signature,
20
- ]), ']', [[/^\\?\n/, 9], [']', 1]])))),
20
+ ]), ']', [['\n', 9], [']', 1]])))),
21
21
  ']',
22
22
  false,
23
- ([, ns], rest) => [[html('a', { 'data-index': dataindex(ns) }, trimNodeEnd(defrag(ns)))], rest],
23
+ ([, ns], rest) =>
24
+ trimBlankNodeEnd(ns).length > 0
25
+ ? [[html('a', { 'data-index': dataindex(ns) }, defrag(ns))], rest]
26
+ : undefined,
24
27
  undefined, 1 | Backtrack.bracket)),
25
28
  ([el]: [HTMLAnchorElement]) => [
26
29
  define(el,
@@ -32,8 +35,8 @@ export const index: IndexParser = lazy(() => validate('[#', creation(1, Recursio
32
35
  ]))));
33
36
 
34
37
  export const signature: IndexParser.SignatureParser = lazy(() => validate('|', creation(1, Recursion.ignore, fmap(open(
35
- '|',
36
- startTight(some(union([bracket, txt]), ']'))),
38
+ /^\|(?!\\?\s)/,
39
+ some(union([bracket, txt]), ']')),
37
40
  ns => [
38
41
  html('span', { class: 'indexer', 'data-index': identity('index', undefined, ns.join(''))!.slice(7) }),
39
42
  ]))));
@@ -1,7 +1,7 @@
1
1
  import { ExtensionParser } from '../../inline';
2
+ import { Recursion } from '../../context';
2
3
  import { union, creation, focus, surround } from '../../../combinator';
3
4
  import { signature } from './index';
4
- import { Recursion } from '../../context';
5
5
  import { html } from 'typed-dom/dom';
6
6
 
7
7
  export const indexer: ExtensionParser.IndexerParser = surround(
@@ -1,7 +1,7 @@
1
1
  import { ExtensionParser } from '../../inline';
2
+ import { State, Recursion } from '../../context';
2
3
  import { union, constraint, creation, validate, surround, clear, fmap } from '../../../combinator';
3
4
  import { str } from '../../source';
4
- import { State, Recursion } from '../../context';
5
5
  import { html } from 'typed-dom/dom';
6
6
 
7
7
  const body = str(/^\$[A-Za-z]*(?:(?:-[A-Za-z][0-9A-Za-z]*)+|-(?:(?:0|[1-9][0-9]*)\.)*(?:0|[1-9][0-9]*)(?![0-9A-Za-z]))/);
@@ -1,8 +1,8 @@
1
1
  import { ExtensionParser } from '../../inline';
2
+ import { State, Recursion, Backtrack } from '../../context';
2
3
  import { union, some, syntax, creation, validate, surround, lazy } from '../../../combinator';
3
4
  import { inline } from '../../inline';
4
5
  import { str } from '../../source';
5
- import { State, Recursion, Backtrack } from '../../context';
6
6
  import { startTight } from '../../visibility';
7
7
  import { unshift } from 'spica/array';
8
8
  import { html, defrag } from 'typed-dom/dom';
@@ -1,8 +1,8 @@
1
1
  import { HTMLParser } from '../inline';
2
+ import { State, Recursion } from '../context';
2
3
  import { union, subsequence, some, syntax, creation, validate, focus, surround, open, match, lazy } from '../../combinator';
3
4
  import { inline } from '../inline';
4
5
  import { str } from '../source';
5
- import { State, Recursion } from '../context';
6
6
  import { isStartLooseNodes, blankWith } from '../visibility';
7
7
  import { memoize } from 'spica/memoize';
8
8
  import { Clock } from 'spica/clock';
@@ -1,17 +1,17 @@
1
1
  import { HTMLEntityParser, UnsafeHTMLEntityParser } from '../inline';
2
+ import { Recursion, Command } from '../context';
2
3
  import { union, creation, validate, focus, fmap } from '../../combinator';
3
- import { Recursion } from '../context';
4
4
  import { html } from 'typed-dom/dom';
5
5
  import { reduce } from 'spica/memoize';
6
6
 
7
7
  export const unsafehtmlentity: UnsafeHTMLEntityParser = creation(1, Recursion.ignore, validate('&', focus(
8
8
  /^&[0-9A-Za-z]{1,99};/,
9
- ({ source }) => [[parse(source) ?? `\x1B${source}`], ''])));
9
+ ({ source }) => [[parse(source) ?? `${Command.Escape}${source}`], ''])));
10
10
 
11
11
  export const htmlentity: HTMLEntityParser = fmap(
12
12
  union([unsafehtmlentity]),
13
13
  ([text]) => [
14
- text[0] === '\x1B'
14
+ text[0] === Command.Escape
15
15
  ? html('span', {
16
16
  class: 'invalid',
17
17
  'data-invalid-syntax': 'htmlentity',
@@ -1,8 +1,8 @@
1
1
  import { InsertionParser } from '../inline';
2
+ import { State, Recursion } from '../context';
2
3
  import { union, some, syntax, creation, surround, open, lazy } from '../../combinator';
3
4
  import { inline } from '../inline';
4
5
  import { str } from '../source';
5
- import { State, Recursion } from '../context';
6
6
  import { blankWith } from '../visibility';
7
7
  import { unshift } from 'spica/array';
8
8
  import { html, defrag } from 'typed-dom/dom';
@@ -1,10 +1,15 @@
1
- import { link } from './link';
2
- import { some } from '../../combinator';
1
+ import { LinkParser } from '../inline';
2
+ import { textlink, medialink } from './link';
3
+ import { some, union } from '../../combinator';
3
4
  import { inspect } from '../../debug.test';
4
5
  import { MarkdownParser } from '../../../markdown';
5
6
 
6
7
  describe('Unit: parser/inline/link', () => {
7
8
  describe('link', () => {
9
+ const link: LinkParser = union([
10
+ medialink,
11
+ textlink,
12
+ ]);
8
13
  const parser = (source: string, context: MarkdownParser.Context = {}) => some(link)({ source, context });
9
14
 
10
15
  it('xss', () => {
@@ -1,11 +1,11 @@
1
1
  import { MarkdownParser } from '../../../markdown';
2
2
  import { LinkParser } from '../inline';
3
+ import { State, Recursion, Backtrack } from '../context';
3
4
  import { union, inits, tails, sequence, some, constraint, syntax, creation, precedence, validate, surround, open, dup, reverse, lazy, fmap, bind } from '../../combinator';
4
5
  import { inline, media, shortmedia } from '../inline';
5
6
  import { attributes } from './html';
6
7
  import { linebreak, unescsource, str } from '../source';
7
- import { State, Recursion, Backtrack } from '../context';
8
- import { trimBlankStart, trimNodeEnd } from '../visibility';
8
+ import { trimBlankStart, trimBlankNodeEnd } from '../visibility';
9
9
  import { stringify } from '../util';
10
10
  import { ReadonlyURL } from 'spica/url';
11
11
  import { html, define, defrag } from 'typed-dom/dom';
@@ -15,18 +15,13 @@ const optspec = {
15
15
  } as const;
16
16
  Object.setPrototypeOf(optspec, null);
17
17
 
18
- export const link: LinkParser = lazy(() => union([
19
- medialink,
20
- textlink,
21
- ]));
22
-
23
18
  export const textlink: LinkParser.TextLinkParser = lazy(() => validate(['[', '{'], creation(1, Recursion.ignore,
24
19
  constraint(State.link, false,
25
20
  syntax(1, State.linkers | State.media,
26
21
  bind(reverse(tails([
27
22
  dup(surround(
28
23
  '[',
29
- trimBlankStart(some(union([inline]), ']', [[/^\\?\n/, 9], [']', 1]])),
24
+ trimBlankStart(some(union([inline]), ']', [['\n', 9], [']', 1]])),
30
25
  ']',
31
26
  true, undefined, undefined, 1 | Backtrack.bracket)),
32
27
  dup(surround(
@@ -38,8 +33,8 @@ export const textlink: LinkParser.TextLinkParser = lazy(() => validate(['[', '{'
38
33
  ([params, content = []]: [string[], (HTMLElement | string)[]], rest, context) => {
39
34
  assert(!html('div', content).querySelector('a, .media, .annotation, .reference'));
40
35
  assert(content[0] !== '');
41
- if (content.length !== 0 && trimNodeEnd(content = defrag(content)).length === 0) return;
42
- return [[parse(content, params, context)], rest];
36
+ if (content.length !== 0 && trimBlankNodeEnd(content).length === 0) return;
37
+ return [[parse(defrag(content), params, context)], rest];
43
38
  }))))));
44
39
 
45
40
  export const medialink: LinkParser.MediaLinkParser = lazy(() => validate(['[', '{'], creation(1, Recursion.ignore,
@@ -1,10 +1,10 @@
1
1
  import { MarkParser } from '../inline';
2
+ import { State, Recursion } from '../context';
2
3
  import { union, some, syntax, creation, constraint, surround, open, lazy } from '../../combinator';
3
4
  import { inline } from '../inline';
4
5
  import { identity, signature } from './extension/indexee';
5
6
  import { str } from '../source';
6
7
  import { startTight, blankWith } from '../visibility';
7
- import { State, Recursion } from '../context';
8
8
  import { unshift } from 'spica/array';
9
9
  import { html, define, defrag } from 'typed-dom/dom';
10
10
 
@@ -1,7 +1,7 @@
1
1
  import { MathParser } from '../inline';
2
+ import { Recursion } from '../context';
2
3
  import { union, some, creation, precedence, validate, focus, rewrite, surround, lazy } from '../../combinator';
3
4
  import { escsource, unescsource, str } from '../source';
4
- import { Recursion } from '../context';
5
5
  import { html } from 'typed-dom/dom';
6
6
 
7
7
  const forbiddenCommand = /\\(?:begin|tiny|huge|large)(?![a-z])/i;