securemark 0.294.4 → 0.294.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 (43) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/dist/index.js +140 -89
  3. package/package.json +3 -3
  4. package/src/combinator/control/manipulation/fence.ts +2 -0
  5. package/src/combinator/control/manipulation/indent.ts +1 -1
  6. package/src/combinator/control/manipulation/match.ts +11 -8
  7. package/src/parser/api/parse.test.ts +3 -3
  8. package/src/parser/block/blockquote.test.ts +3 -9
  9. package/src/parser/block/blockquote.ts +4 -4
  10. package/src/parser/block/dlist.ts +4 -4
  11. package/src/parser/block/extension/example.ts +1 -3
  12. package/src/parser/block/extension/fig.test.ts +0 -1
  13. package/src/parser/block/extension/fig.ts +6 -6
  14. package/src/parser/block/extension/figbase.ts +1 -1
  15. package/src/parser/block/extension/figure.test.ts +1 -1
  16. package/src/parser/block/extension/figure.ts +6 -6
  17. package/src/parser/block/extension/message.ts +1 -1
  18. package/src/parser/block/extension/table.ts +4 -4
  19. package/src/parser/block/heading.ts +4 -4
  20. package/src/parser/block/reply/cite.ts +1 -1
  21. package/src/parser/block/reply/quote.ts +2 -2
  22. package/src/parser/block/sidefence.test.ts +1 -3
  23. package/src/parser/block/sidefence.ts +4 -4
  24. package/src/parser/block/table.ts +2 -2
  25. package/src/parser/block.ts +1 -1
  26. package/src/parser/header.ts +3 -3
  27. package/src/parser/inline/autolink/account.ts +5 -7
  28. package/src/parser/inline/autolink/channel.ts +15 -15
  29. package/src/parser/inline/autolink/hashtag.ts +10 -8
  30. package/src/parser/inline/code.ts +12 -18
  31. package/src/parser/inline/deletion.ts +3 -3
  32. package/src/parser/inline/emstrong.ts +3 -3
  33. package/src/parser/inline/extension/indexer.ts +1 -1
  34. package/src/parser/inline/html.ts +1 -1
  35. package/src/parser/inline/insertion.ts +3 -3
  36. package/src/parser/inline/italic.ts +3 -3
  37. package/src/parser/inline/link.ts +3 -3
  38. package/src/parser/inline/mark.ts +3 -3
  39. package/src/parser/inline/remark.ts +3 -3
  40. package/src/parser/inline.ts +2 -0
  41. package/src/parser/source/text.ts +8 -4
  42. package/src/parser/util.ts +1 -1
  43. package/src/parser/visibility.ts +1 -1
@@ -1,7 +1,7 @@
1
1
  import { AutolinkParser } from '../../inline';
2
2
  import { State, Backtrack } from '../../context';
3
3
  import { List, Data } from '../../../combinator/data/parser';
4
- import { union, state, constraint, verify, rewrite, open, convert, fmap, lazy } from '../../../combinator';
4
+ import { union, state, constraint, verify, rewrite, surround, convert, fmap, lazy } from '../../../combinator';
5
5
  import { unsafelink } from '../link';
6
6
  import { str } from '../../source';
7
7
  import { define } from 'typed-dom/dom';
@@ -12,17 +12,19 @@ import { define } from 'typed-dom/dom';
12
12
  export const emoji = String.raw`\p{Emoji_Modifier_Base}\p{Emoji_Modifier}?|\p{Emoji_Presentation}|\p{Emoji}\uFE0F`;
13
13
 
14
14
  export const hashtag: AutolinkParser.HashtagParser = lazy(() => rewrite(
15
- open(
15
+ verify(surround(
16
16
  new RegExp([
17
17
  /(?<![^\p{C}\p{S}\p{P}\s]|emoji)#/yiu.source,
18
18
  ].join('').replace(/emoji/g, emoji), 'yu'),
19
- verify(
20
- str(new RegExp([
21
- /(?!['_])(?:[^\p{C}\p{S}\p{P}\s]|emoji|'(?=[0-9A-Za-z])|_(?=[^'\p{C}\p{S}\p{P}\s]|emoji))+(?![0-9a-z@#]|>>|:\S|[^\p{C}\p{S}\p{P}\s]|emoji)/yu.source,
22
- ].join('').replace(/emoji/g, emoji), 'yu')),
23
- ([{ value }]) => !/^[0-9]{1,4}$|^[0-9]{5}/.test(value)),
24
- false,
19
+ str(new RegExp([
20
+ /(?!['_])(?:[^\p{C}\p{S}\p{P}\s]|emoji|'(?=[0-9A-Za-z])|_(?=[^\p{C}\p{S}\p{P}\s]|emoji))+/yu.source,
21
+ ].join('').replace(/emoji/g, emoji), 'yu')),
22
+ str(new RegExp([
23
+ /(?![0-9a-z@#]|>>|:\S|[^\p{C}\p{S}\p{P}\s]|emoji)/yu.source,
24
+ ].join('').replace(/emoji/g, emoji), 'yu')),
25
+ false, undefined, undefined,
25
26
  [3 | Backtrack.autolink]),
27
+ ([{ value }]) => !/^[0-9]{1,4}$|^[0-9]{5}/.test(value)),
26
28
  constraint(State.autolink, state(State.autolink, fmap(convert(
27
29
  source => `[${source}]{ ${`/hashtags/${source.slice(1)}`} }`,
28
30
  union([unsafelink]),
@@ -1,26 +1,20 @@
1
1
  import { CodeParser } from '../inline';
2
2
  import { List, Data } from '../../combinator/data/parser';
3
- import { open, match } from '../../combinator';
4
- import { Backtrack } from '../context';
3
+ import { match } from '../../combinator';
5
4
  import { invalid } from '../util';
6
5
  import { html } from 'typed-dom/dom';
7
6
 
8
- export const code: CodeParser = open(
9
- /(?=`)/y,
10
- match(
11
- /(`+)(?!`)([^\n]*?)(?:((?<!`)\1(?!`))|(?=$|\n))/y,
12
- ([whole, opener, body, closer]) => () =>
13
- closer
14
- ? new List([new Data(html('code', { 'data-src': whole }, format(body)))])
15
- : body
16
- ? new List([new Data(html('code', {
17
- class: 'invalid',
18
- ...invalid('code', 'syntax', `Missing the closing symbol "${opener}"`)
19
- }, whole))])
20
- : new List([new Data(opener)]),
21
- true),
22
- false,
23
- [3 | Backtrack.bracket]);
7
+ export const code: CodeParser = match(
8
+ /(`+)(?!`)([^\n]*?)(?:((?<!`)\1(?!`))|(?=$|\n))/y,
9
+ ([whole, opener, body, closer]) => () =>
10
+ closer
11
+ ? new List([new Data(html('code', { 'data-src': whole }, format(body)))])
12
+ : body
13
+ ? new List([new Data(html('code', {
14
+ class: 'invalid',
15
+ ...invalid('code', 'syntax', `Missing the closing symbol "${opener}"`)
16
+ }, whole))])
17
+ : new List([new Data(opener)]));
24
18
 
25
19
  function format(text: string): string {
26
20
  return text.length > 2
@@ -1,13 +1,13 @@
1
1
  import { DeletionParser } from '../inline';
2
2
  import { Recursion, Command } from '../context';
3
3
  import { List, Data } from '../../combinator/data/parser';
4
- import { union, some, recursion, precedence, validate, surround, open, lazy } from '../../combinator';
4
+ import { union, some, recursion, precedence, surround, open, lazy } from '../../combinator';
5
5
  import { inline } from '../inline';
6
6
  import { blankWith } from '../visibility';
7
7
  import { unwrap, repeat } from '../util';
8
8
  import { html, defrag } from 'typed-dom/dom';
9
9
 
10
- export const deletion: DeletionParser = lazy(() => validate('~~',
10
+ export const deletion: DeletionParser = lazy(() =>
11
11
  precedence(0, repeat('~~', surround(
12
12
  '',
13
13
  recursion(Recursion.inline,
@@ -18,4 +18,4 @@ export const deletion: DeletionParser = lazy(() => validate('~~',
18
18
  '~~', false,
19
19
  ([, bs], { buffer }) => buffer!.import(bs),
20
20
  ([, bs], { buffer }) => bs && buffer!.import(bs).push(new Data(Command.Cancel)) && buffer!),
21
- nodes => new List([new Data(html('del', defrag(unwrap(nodes))))])))));
21
+ nodes => new List([new Data(html('del', defrag(unwrap(nodes))))]))));
@@ -1,7 +1,7 @@
1
1
  import { EmStrongParser, EmphasisParser, StrongParser } from '../inline';
2
2
  import { Recursion, Command } from '../context';
3
3
  import { Result, List, Data, Node, Context, IntermediateParser } from '../../combinator/data/parser';
4
- import { union, some, recursion, precedence, validate, surround, open, lazy, bind } from '../../combinator';
4
+ import { union, some, recursion, precedence, surround, open, lazy, bind } from '../../combinator';
5
5
  import { inline } from '../inline';
6
6
  import { strong } from './strong';
7
7
  import { emphasis } from './emphasis';
@@ -24,7 +24,7 @@ const subemphasis: IntermediateParser<EmphasisParser> = lazy(() => some(union([
24
24
  // 開閉が明示的でない構文は開閉の不明確な記号による再帰的適用を行わず
25
25
  // 可能な限り早く閉じるよう解析しなければならない。
26
26
  // このため終端記号の後ろを見て終端を中止し同じ構文を再帰的に適用してはならない。
27
- export const emstrong: EmStrongParser = lazy(() => validate('***',
27
+ export const emstrong: EmStrongParser = lazy(() =>
28
28
  precedence(0, repeat('***', surround(
29
29
  '',
30
30
  recursion(Recursion.inline,
@@ -142,7 +142,7 @@ export const emstrong: EmStrongParser = lazy(() => validate('***',
142
142
  nodes = prepend('*'.repeat(prefix - postfix), nodes);
143
143
  }
144
144
  return nodes;
145
- }))));
145
+ })));
146
146
 
147
147
  function prepend<N>(prefix: string, nodes: List<Data<N>>): List<Data<N>> {
148
148
  if (typeof nodes.head?.value === 'string') {
@@ -11,7 +11,7 @@ import { html } from 'typed-dom/dom';
11
11
  // 継続的編集において最も簡便となる。
12
12
 
13
13
  export const indexer: ExtensionParser.IndexerParser = surround(
14
- /\s\[(?=\|\S)/y,
14
+ / \[(?=\|\S)/y,
15
15
  union([
16
16
  signature,
17
17
  focus(/\|(?=\])/y, () => new List([new Data(html('span', { class: 'indexer', 'data-index': '' }))])),
@@ -32,7 +32,7 @@ export const html: HTMLParser = lazy(() => validate(/<[a-z]+(?=[ >])/yi,
32
32
  ([as, bs = new List()], context) =>
33
33
  new List([new Data(elem(as.head!.value.slice(1), false, [...unwrap(as.import(bs))], new List(), new List(), context))])),
34
34
  match(
35
- new RegExp(String.raw`<(${TAGS.join('|')})(?=[^\S\n]|>)`, 'y'),
35
+ new RegExp(String.raw`<(${TAGS.join('|')})(?=[ >])`, 'y'),
36
36
  memoize(
37
37
  ([, tag]) =>
38
38
  surround<HTMLParser.TagParser, string>(
@@ -1,13 +1,13 @@
1
1
  import { InsertionParser } from '../inline';
2
2
  import { Recursion, Command } from '../context';
3
3
  import { List, Data } from '../../combinator/data/parser';
4
- import { union, some, recursion, precedence, validate, surround, open, lazy } from '../../combinator';
4
+ import { union, some, recursion, precedence, surround, open, lazy } from '../../combinator';
5
5
  import { inline } from '../inline';
6
6
  import { blankWith } from '../visibility';
7
7
  import { unwrap, repeat } from '../util';
8
8
  import { html, defrag } from 'typed-dom/dom';
9
9
 
10
- export const insertion: InsertionParser = lazy(() => validate('++',
10
+ export const insertion: InsertionParser = lazy(() =>
11
11
  precedence(0, repeat('++', surround(
12
12
  '',
13
13
  recursion(Recursion.inline,
@@ -18,4 +18,4 @@ export const insertion: InsertionParser = lazy(() => validate('++',
18
18
  '++', false,
19
19
  ([, bs], { buffer }) => buffer!.import(bs),
20
20
  ([, bs], { buffer }) => bs && buffer!.import(bs).push(new Data(Command.Cancel)) && buffer!),
21
- nodes => new List([new Data(html('ins', defrag(unwrap(nodes))))])))));
21
+ nodes => new List([new Data(html('ins', defrag(unwrap(nodes))))]))));
@@ -1,7 +1,7 @@
1
1
  import { ItalicParser } from '../inline';
2
2
  import { Recursion, Command } from '../context';
3
3
  import { List, Data } from '../../combinator/data/parser';
4
- import { union, some, recursion, precedence, validate, surround, open, lazy } from '../../combinator';
4
+ import { union, some, recursion, precedence, surround, open, lazy } from '../../combinator';
5
5
  import { inline } from '../inline';
6
6
  import { tightStart, blankWith } from '../visibility';
7
7
  import { unwrap, repeat } from '../util';
@@ -10,7 +10,7 @@ import { html, defrag } from 'typed-dom/dom';
10
10
  // 可読性のため実際にはオブリーク体を指定する。
11
11
  // 斜体は単語に使うとかえって見づらく読み飛ばしやすくなるため使わないべきであり
12
12
  // ある程度の長さのある文に使うのが望ましい。
13
- export const italic: ItalicParser = lazy(() => validate('///',
13
+ export const italic: ItalicParser = lazy(() =>
14
14
  precedence(0, repeat('///', surround(
15
15
  '',
16
16
  recursion(Recursion.inline,
@@ -21,4 +21,4 @@ export const italic: ItalicParser = lazy(() => validate('///',
21
21
  '///', false,
22
22
  ([, bs], { buffer }) => buffer!.import(bs),
23
23
  ([, bs], { buffer }) => bs && buffer!.import(bs).push(new Data(Command.Cancel)) && buffer!),
24
- nodes => new List([new Data(html('i', defrag(unwrap(nodes))))])))));
24
+ nodes => new List([new Data(html('i', defrag(unwrap(nodes))))]))));
@@ -2,7 +2,7 @@ import { MarkdownParser } from '../../../markdown';
2
2
  import { LinkParser } from '../inline';
3
3
  import { State, Backtrack, Command } from '../context';
4
4
  import { List, Data } from '../../combinator/data/parser';
5
- import { union, inits, tails, sequence, subsequence, some, creation, precedence, state, constraint, validate, surround, open, setBacktrack, dup, reverse, lazy, fmap, bind } from '../../combinator';
5
+ import { union, inits, tails, sequence, subsequence, some, creation, precedence, state, constraint, surround, open, setBacktrack, dup, reverse, lazy, fmap, bind } from '../../combinator';
6
6
  import { inline, media, shortmedia } from '../inline';
7
7
  import { attributes } from './html';
8
8
  import { unescsource, str } from '../source';
@@ -75,7 +75,7 @@ export const textlink: LinkParser.TextLinkParser = lazy(() => constraint(State.l
75
75
  return new List([new Data(parse(content, params as List<Data<string>>, context))]);
76
76
  }))))));
77
77
 
78
- export const medialink: LinkParser.MediaLinkParser = lazy(() => constraint(State.link | State.media, validate(/[[{]/y, creation(10,
78
+ export const medialink: LinkParser.MediaLinkParser = lazy(() => constraint(State.link | State.media, creation(10,
79
79
  state(State.linkers,
80
80
  bind(sequence([
81
81
  dup(surround(
@@ -85,7 +85,7 @@ export const medialink: LinkParser.MediaLinkParser = lazy(() => constraint(State
85
85
  dup(surround(/{(?![{}])/y, inits([uri, some(option)]), / ?}/y)),
86
86
  ]),
87
87
  ([{ value: content }, { value: params }], context) =>
88
- new List([new Data(parse(content, params as List<Data<string>>, context))])))))));
88
+ new List([new Data(parse(content, params as List<Data<string>>, context))]))))));
89
89
 
90
90
  export const unsafelink: LinkParser.UnsafeLinkParser = lazy(() =>
91
91
  creation(10,
@@ -1,14 +1,14 @@
1
1
  import { MarkParser } from '../inline';
2
2
  import { State, Recursion, Command } from '../context';
3
3
  import { List, Data } from '../../combinator/data/parser';
4
- import { union, some, recursion, precedence, state, constraint, validate, surround, open, lazy } from '../../combinator';
4
+ import { union, some, recursion, precedence, state, constraint, surround, open, lazy } from '../../combinator';
5
5
  import { inline } from '../inline';
6
6
  import { identity, signature } from './extension/indexee';
7
7
  import { tightStart, blankWith } from '../visibility';
8
8
  import { unwrap, repeat } from '../util';
9
9
  import { html, define, defrag } from 'typed-dom/dom';
10
10
 
11
- export const mark: MarkParser = lazy(() => constraint(State.linkers & ~State.mark, validate('==',
11
+ export const mark: MarkParser = lazy(() => constraint(State.linkers & ~State.mark,
12
12
  precedence(0, state(State.mark, repeat('==', surround(
13
13
  '',
14
14
  recursion(Recursion.inline,
@@ -25,4 +25,4 @@ export const mark: MarkParser = lazy(() => constraint(State.linkers & ~State.mar
25
25
  return el.id
26
26
  ? new List([new Data(el), new Data(html('a', { href: `#${el.id}` }))])
27
27
  : new List([new Data(el)]);
28
- }))))));
28
+ })))));
@@ -8,9 +8,9 @@ import { unwrap, invalid } from '../util';
8
8
  import { html, defrag } from 'typed-dom/dom';
9
9
 
10
10
  export const remark: RemarkParser = lazy(() => fallback(surround(
11
- str(/\[%(?=\s)/y),
11
+ str(/\[%(?=[ \n])/y),
12
12
  precedence(3, recursion(Recursion.inline,
13
- some(union([inline]), /\s%\]/y, [[/\s%\]/y, 3]]))),
13
+ some(union([inline]), /[ \n]%\]/y, [[/[ \n]%\]/y, 3]]))),
14
14
  close(text, str(`%]`)), true,
15
15
  ([as, bs = new List(), cs]) => new List([
16
16
  new Data(html('span', { class: 'remark' }, [
@@ -19,6 +19,6 @@ export const remark: RemarkParser = lazy(() => fallback(surround(
19
19
  ])),
20
20
  ]),
21
21
  ([as, bs]) => bs && as.import(bs as List<Data<string>>)),
22
- focus(/\[%+(?=\s)/y, ({ context: { source } }) => new List([
22
+ focus(/\[%+(?=[ \n])/y, ({ context: { source } }) => new List([
23
23
  new Data(html('span', { class: 'invalid', ...invalid('remark', 'syntax', 'Invalid start symbol') }, source))
24
24
  ]))));
@@ -66,6 +66,7 @@ export const inline: InlineParser = lazy(() => union([
66
66
  case '%':
67
67
  return remark(input)
68
68
  || textlink(input)
69
+ || ruby(input)
69
70
  || bracket(input);
70
71
  case '#':
71
72
  case '$':
@@ -74,6 +75,7 @@ export const inline: InlineParser = lazy(() => union([
74
75
  case '|':
75
76
  return extension(input)
76
77
  || textlink(input)
78
+ || ruby(input)
77
79
  || bracket(input);
78
80
  }
79
81
  return textlink(input)
@@ -103,7 +103,6 @@ export function next(source: string, position: number, delimiter?: RegExp): numb
103
103
  const char = source[index];
104
104
  switch (char) {
105
105
  case '$':
106
- case '%':
107
106
  case '*':
108
107
  case '+':
109
108
  case '~':
@@ -111,10 +110,15 @@ export function next(source: string, position: number, delimiter?: RegExp): numb
111
110
  case '/':
112
111
  index = backToWhitespace(source, position, index);
113
112
  break;
113
+ case '%':
114
+ index += index - 1 > position && source.startsWith(' %]', index - 1)
115
+ ? -1
116
+ : 0;
117
+ break;
114
118
  case '[':
115
- index = source[index + 1] === '|'
116
- ? backToWhitespace(source, position, index)
117
- : index;
119
+ index += index - 1 > position && source.startsWith(' [|', index - 1)
120
+ ? -1
121
+ : 0;
118
122
  break;
119
123
  case ':':
120
124
  index = source.startsWith('//', index + 1)
@@ -28,7 +28,7 @@ export function repeat<N extends HTMLElement | string>(symbol: string, parser: P
28
28
  return failsafe(input => {
29
29
  const { context } = input;
30
30
  const { source, position } = context;
31
- assert(source.startsWith(symbol, context.position));
31
+ if (!source.startsWith(symbol, context.position)) return;
32
32
  let nodes = new List<Data<N>>();
33
33
  let i = symbol.length;
34
34
  for (; source[context.position + i] === source[context.position];) ++i;
@@ -8,7 +8,7 @@ import { invisibleHTMLEntityNames } from './api/normalize';
8
8
  export namespace blank {
9
9
  export const line = new RegExp(
10
10
  // TODO: 行全体をエスケープ
11
- /^(?:[^\S\r\n])*(?!\s)(\\?[^\S\r\n]|&IHN;|<wbr ?>|\\$)+$/mg.source
11
+ /^(\\?[^\S\r\n]|&IHN;|<wbr ?>|\\$)+$/mg.source
12
12
  .replace('IHN', `(?:${invisibleHTMLEntityNames.join('|')})`),
13
13
  'gm');
14
14
  export const start = new RegExp(