securemark 0.295.3 → 0.295.4

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 CHANGED
@@ -1,5 +1,9 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.295.4
4
+
5
+ - Refactoring.
6
+
3
7
  ## 0.295.3
4
8
 
5
9
  - Refactoring.
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- /*! securemark v0.295.3 https://github.com/falsandtru/securemark | (c) 2017, falsandtru | UNLICENSED License */
1
+ /*! securemark v0.295.4 https://github.com/falsandtru/securemark | (c) 2017, falsandtru | UNLICENSED License */
2
2
  (function webpackUniversalModuleDefinition(root, factory) {
3
3
  if(typeof exports === 'object' && typeof module === 'object')
4
4
  module.exports = factory(require("Prism"), require("DOMPurify"));
@@ -3862,7 +3862,7 @@ Object.defineProperty(exports, "__esModule", ({
3862
3862
  value: true
3863
3863
  }));
3864
3864
  exports.inits = void 0;
3865
- function inits(parsers, resume) {
3865
+ function inits(parsers) {
3866
3866
  if (parsers.length === 1) return parsers[0];
3867
3867
  return input => {
3868
3868
  const {
@@ -3878,7 +3878,6 @@ function inits(parsers, resume) {
3878
3878
  const result = parsers[i](input);
3879
3879
  if (result === undefined) break;
3880
3880
  nodes = nodes?.import(result) ?? result;
3881
- if (resume?.(result) === false) break;
3882
3881
  }
3883
3882
  return nodes;
3884
3883
  };
@@ -3897,7 +3896,7 @@ Object.defineProperty(exports, "__esModule", ({
3897
3896
  value: true
3898
3897
  }));
3899
3898
  exports.sequence = void 0;
3900
- function sequence(parsers, resume) {
3899
+ function sequence(parsers) {
3901
3900
  if (parsers.length === 1) return parsers[0];
3902
3901
  return input => {
3903
3902
  const {
@@ -3913,7 +3912,6 @@ function sequence(parsers, resume) {
3913
3912
  const result = parsers[i](input);
3914
3913
  if (result === undefined) return;
3915
3914
  nodes = nodes?.import(result) ?? result;
3916
- if (resume?.(result) === false) return;
3917
3915
  }
3918
3916
  return nodes;
3919
3917
  };
@@ -3985,8 +3983,8 @@ Object.defineProperty(exports, "__esModule", ({
3985
3983
  exports.subsequence = void 0;
3986
3984
  const union_1 = __webpack_require__(2369);
3987
3985
  const inits_1 = __webpack_require__(2861);
3988
- function subsequence(parsers, resume) {
3989
- return (0, union_1.union)(parsers.map((_, i) => i + 1 < parsers.length ? (0, inits_1.inits)([parsers[i], subsequence(parsers.slice(i + 1), resume)], resume) : parsers[i]));
3986
+ function subsequence(parsers) {
3987
+ return (0, union_1.union)(parsers.map((_, i) => i + 1 < parsers.length ? (0, inits_1.inits)([parsers[i], subsequence(parsers.slice(i + 1))]) : parsers[i]));
3990
3988
  }
3991
3989
  exports.subsequence = subsequence;
3992
3990
 
@@ -4004,8 +4002,8 @@ Object.defineProperty(exports, "__esModule", ({
4004
4002
  exports.tails = void 0;
4005
4003
  const union_1 = __webpack_require__(2369);
4006
4004
  const sequence_1 = __webpack_require__(3989);
4007
- function tails(parsers, resume) {
4008
- return (0, union_1.union)(parsers.map((_, i) => (0, sequence_1.sequence)(parsers.slice(i), resume)));
4005
+ function tails(parsers) {
4006
+ return (0, union_1.union)(parsers.map((_, i) => (0, sequence_1.sequence)(parsers.slice(i))));
4009
4007
  }
4010
4008
  exports.tails = tails;
4011
4009
 
@@ -6567,19 +6565,19 @@ exports.bracket = (0, combinator_1.lazy)(() => (0, combinator_1.union)([input =>
6567
6565
  return d1(input);
6568
6566
  }
6569
6567
  }]));
6570
- const p1 = (0, combinator_1.lazy)(() => (0, combinator_1.surround)((0, source_1.str)('('), (0, combinator_1.precedence)(1, (0, combinator_1.recursion)(5 /* Recursion.bracket */, (0, combinator_1.some)(inline_1.inline, ')', [[')', 1]]))), (0, source_1.str)(')'), true, [], ([as, bs = new parser_1.List(), cs], context) => {
6568
+ const p1 = (0, combinator_1.lazy)(() => (0, combinator_1.surround)((0, source_1.str)('('), (0, combinator_1.precedence)(1, (0, combinator_1.recursion)(5 /* Recursion.bracket */, (0, combinator_1.some)(inline_1.inline, ')', [[')', 1]]))), (0, source_1.str)(')'),
6569
+ // 唯一の参照者であるAnnotation構文に対してのみバックトラックを記録しその他は記録しない。
6570
+ // 二重括弧構文の内括弧のバックトラックは二重括弧構文自身が記録するため記録不要。
6571
+ // Ruby構文の丸括弧は常にRuby構文が先に到達し記録するため記録不要。
6572
+ true, [], ([as, bs = new parser_1.List(), cs], context) => {
6571
6573
  const {
6572
6574
  source,
6573
6575
  position,
6574
6576
  range
6575
6577
  } = context;
6576
6578
  const head = position - range;
6577
- if (context.linebreak !== 0) {
6578
- if (head > 0 && source[head - 1] === '(') {
6579
- (0, combinator_1.setBacktrack)(context, 2 | 128 /* Backtrack.doublebracket */, head - 1);
6580
- }
6581
- } else if (source[position] !== ')' && source[head - 1] === '(') {
6582
- (0, combinator_1.setBacktrack)(context, 2 | 128 /* Backtrack.doublebracket */, head - 1);
6579
+ if (source[head + 1] === '(' && (context.linebreak !== 0 || source[position - 2] !== ')')) {
6580
+ (0, combinator_1.setBacktrack)(context, 2 | 128 /* Backtrack.doublebracket */, head);
6583
6581
  }
6584
6582
  const str = source.slice(position - range + 1, position - 1);
6585
6583
  return indexA.test(str) ? new parser_1.List([new parser_1.Node(as.head.value), new parser_1.Node(str), new parser_1.Node(cs.head.value)]) : new parser_1.List([new parser_1.Node((0, dom_1.html)('span', {
@@ -6623,12 +6621,8 @@ const s1 = (0, combinator_1.lazy)(() => (0, combinator_1.surround)((0, source_1.
6623
6621
  range
6624
6622
  } = context;
6625
6623
  const head = position - range;
6626
- if (context.linebreak !== 0) {
6627
- if (head > 0 && source[head - 1] === '[') {
6628
- (0, combinator_1.setBacktrack)(context, 2 | 128 /* Backtrack.doublebracket */, head - 1);
6629
- }
6630
- } else if (source[position] !== ']' && source[head - 1] === '[') {
6631
- (0, combinator_1.setBacktrack)(context, 2 | 128 /* Backtrack.doublebracket */, head - 1);
6624
+ if (source[head + 1] === '[' && (context.linebreak !== 0 || source[position - 2] !== ']')) {
6625
+ (0, combinator_1.setBacktrack)(context, 2 | 128 /* Backtrack.doublebracket */, head);
6632
6626
  }
6633
6627
  if (context.state & 8 /* State.link */) {
6634
6628
  if (context.linebreak !== 0) {
@@ -6637,15 +6631,14 @@ const s1 = (0, combinator_1.lazy)(() => (0, combinator_1.surround)((0, source_1.
6637
6631
  (0, combinator_1.setBacktrack)(context, 2 | 64 /* Backtrack.link */, head);
6638
6632
  } else {
6639
6633
  context.state ^= 8 /* State.link */;
6640
- const result = !(0, combinator_1.isBacktrack)(context, 1 | 64 /* Backtrack.link */) ? (0, link_1.textlink)({
6634
+ if (!(0, combinator_1.isBacktrack)(context, 1 | 64 /* Backtrack.link */) && !(0, link_1.textlink)({
6641
6635
  context
6642
- }) : undefined;
6643
- context.position = position;
6644
- if (!result) {
6636
+ })) {
6645
6637
  (0, combinator_1.setBacktrack)(context, 2 | 64 /* Backtrack.link */, head);
6646
6638
  }
6647
- context.state ^= 8 /* State.link */;
6639
+ context.position = position;
6648
6640
  context.range = range;
6641
+ context.state ^= 8 /* State.link */;
6649
6642
  }
6650
6643
  }
6651
6644
  return as.import(bs).import(cs);
@@ -7214,14 +7207,14 @@ Object.setPrototypeOf(attrspecs, null);
7214
7207
  Object.values(attrspecs).forEach(o => Object.setPrototypeOf(o, null));
7215
7208
  exports.html = (0, combinator_1.lazy)(() => (0, combinator_1.validate)(/<[a-z]+(?=[ >])/yi, (0, combinator_1.union)([(0, combinator_1.surround)(
7216
7209
  // https://html.spec.whatwg.org/multipage/syntax.html#void-elements
7217
- (0, source_1.str)(/<(?:area|base|br|col|embed|hr|img|input|link|meta|source|track|wbr)(?=[ >])/y), (0, combinator_1.some)((0, combinator_1.union)([exports.attribute])), (0, combinator_1.open)((0, source_1.str)(/ ?/y), (0, source_1.str)('>'), true), true, [], ([as, bs = new parser_1.List(), cs], context) => new parser_1.List([new parser_1.Node(elem(as.head.value.slice(1), false, [...(0, util_1.unwrap)(as.import(bs).import(cs))], new parser_1.List(), new parser_1.List(), context))]), ([as, bs = new parser_1.List()], context) => new parser_1.List([new parser_1.Node(elem(as.head.value.slice(1), false, [...(0, util_1.unwrap)(as.import(bs))], new parser_1.List(), new parser_1.List(), context))])), (0, combinator_1.match)(new RegExp(String.raw`<(${TAGS.join('|')})(?=[ >])`, 'y'), (0, memoize_1.memoize)(([, tag]) => (0, combinator_1.surround)((0, combinator_1.surround)((0, source_1.str)(`<${tag}`), (0, combinator_1.some)(exports.attribute), (0, combinator_1.open)((0, source_1.str)(/ ?/y), (0, source_1.str)('>'), true), true, [], ([as, bs = new parser_1.List(), cs]) => as.import(bs).import(cs), ([as, bs = new parser_1.List()]) => as.import(bs)),
7210
+ (0, source_1.str)(/<(?:area|base|br|col|embed|hr|img|input|link|meta|source|track|wbr)(?=[ >])/y), (0, combinator_1.precedence)(9, (0, combinator_1.some)((0, combinator_1.union)([exports.attribute]))), (0, combinator_1.open)((0, source_1.str)(/ ?/y), (0, source_1.str)('>'), true), true, [], ([as, bs = new parser_1.List(), cs], context) => new parser_1.List([new parser_1.Node(elem(as.head.value.slice(1), false, [...(0, util_1.unwrap)(as.import(bs).import(cs))], new parser_1.List(), new parser_1.List(), context))]), ([as, bs = new parser_1.List()], context) => new parser_1.List([new parser_1.Node(elem(as.head.value.slice(1), false, [...(0, util_1.unwrap)(as.import(bs))], new parser_1.List(), new parser_1.List(), context))])), (0, combinator_1.match)(new RegExp(String.raw`<(${TAGS.join('|')})(?=[ >])`, 'y'), (0, memoize_1.memoize)(([, tag]) => (0, combinator_1.surround)((0, combinator_1.surround)((0, source_1.str)(`<${tag}`), (0, combinator_1.precedence)(9, (0, combinator_1.some)(exports.attribute)), (0, combinator_1.open)((0, source_1.str)(/ ?/y), (0, source_1.str)('>'), true), true, [], ([as, bs = new parser_1.List(), cs]) => as.import(bs).import(cs), ([as, bs = new parser_1.List()]) => as.import(bs)),
7218
7211
  // 不可視のHTML構造が可視構造を変化させるべきでない。
7219
7212
  // 可視のHTMLは優先度変更を検討する。
7220
- // このため<>は将来的に共通構造を変化させる可能性があり
7213
+ // このため`<>`記号は将来的に共通構造を変化させる可能性があり
7221
7214
  // 共通構造を変化させない非構造文字列としては依然としてエスケープを要する。
7222
7215
  (0, combinator_1.precedence)(0, (0, combinator_1.recursion)(4 /* Recursion.inline */, (0, combinator_1.some)((0, combinator_1.union)([(0, combinator_1.some)(inline_1.inline, (0, visibility_1.blankWith)('\n', `</${tag}>`)), (0, combinator_1.open)('\n', (0, combinator_1.some)(inline_1.inline, `</${tag}>`), true)])))), (0, source_1.str)(`</${tag}>`), true, [], ([as, bs = new parser_1.List(), cs], context) => new parser_1.List([new parser_1.Node(elem(tag, true, [...(0, util_1.unwrap)(as)], bs, cs, context))]), ([as, bs = new parser_1.List()], context) => new parser_1.List([new parser_1.Node(elem(tag, true, [...(0, util_1.unwrap)(as)], bs, new parser_1.List(), context))])), ([, tag]) => tag, new Map())), (0, combinator_1.surround)(
7223
7216
  // https://html.spec.whatwg.org/multipage/syntax.html#void-elements
7224
- (0, source_1.str)(/<[a-z]+(?=[ >])/yi), (0, combinator_1.some)((0, combinator_1.union)([exports.attribute])), (0, combinator_1.open)((0, source_1.str)(/ ?/y), (0, source_1.str)('>'), true), true, [], ([as, bs = new parser_1.List(), cs], context) => new parser_1.List([new parser_1.Node(elem(as.head.value.slice(1), false, [...(0, util_1.unwrap)(as.import(bs).import(cs))], new parser_1.List(), new parser_1.List(), context))]), ([as, bs = new parser_1.List()], context) => new parser_1.List([new parser_1.Node(elem(as.head.value.slice(1), false, [...(0, util_1.unwrap)(as.import(bs))], new parser_1.List(), new parser_1.List(), context))]))])));
7217
+ (0, source_1.str)(/<[a-z]+(?=[ >])/yi), (0, combinator_1.precedence)(9, (0, combinator_1.some)((0, combinator_1.union)([exports.attribute]))), (0, combinator_1.open)((0, source_1.str)(/ ?/y), (0, source_1.str)('>'), true), true, [], ([as, bs = new parser_1.List(), cs], context) => new parser_1.List([new parser_1.Node(elem(as.head.value.slice(1), false, [...(0, util_1.unwrap)(as.import(bs).import(cs))], new parser_1.List(), new parser_1.List(), context))]), ([as, bs = new parser_1.List()], context) => new parser_1.List([new parser_1.Node(elem(as.head.value.slice(1), false, [...(0, util_1.unwrap)(as.import(bs))], new parser_1.List(), new parser_1.List(), context))]))])));
7225
7218
  exports.attribute = (0, combinator_1.union)([(0, source_1.str)(/ [a-z]+(?:-[a-z]+)*(?:="(?:\\[^\n]|[^\\\n"])*")?(?=[ >])/yi), (0, source_1.str)(/ [^\s<>]+/y)]);
7226
7219
  function elem(tag, content, as, bs, cs, context) {
7227
7220
  if (!tags.includes(tag)) return ielem('tag', `Invalid HTML tag name "${tag}"`, context);
@@ -7390,7 +7383,7 @@ exports.textlink = (0, combinator_1.lazy)(() => (0, combinator_1.constraint)(8 /
7390
7383
  })),
7391
7384
  // `{ `と`{`で個別にバックトラックが発生し+1nされる。
7392
7385
  // 自己再帰的にパースしてもオプションの不要なパースによる計算量の増加により相殺される。
7393
- (0, combinator_1.dup)((0, combinator_1.surround)(/{(?![{}])/y, (0, combinator_1.inits)([exports.uri, (0, combinator_1.some)(exports.option)]), / ?}/y, false, [], undefined, ([as, bs]) => bs && as.import(bs).push(new parser_1.Node("\u0018" /* Command.Cancel */)) && as))]), ([{
7386
+ (0, combinator_1.dup)((0, combinator_1.surround)(/{(?![{}])/y, (0, combinator_1.precedence)(9, (0, combinator_1.inits)([exports.uri, (0, combinator_1.some)(exports.option)])), / ?}/y, false, [], undefined, ([as, bs]) => bs && as.import(bs).push(new parser_1.Node("\u0018" /* Command.Cancel */)) && as))]), ([{
7394
7387
  value: content
7395
7388
  }, {
7396
7389
  value: params = undefined
@@ -7415,7 +7408,7 @@ exports.textlink = (0, combinator_1.lazy)(() => (0, combinator_1.constraint)(8 /
7415
7408
  if (content.length !== 0 && (0, visibility_1.trimBlankNodeEnd)(content).length === 0) return;
7416
7409
  return new parser_1.List([new parser_1.Node(parse(content, params, context))]);
7417
7410
  })))));
7418
- exports.medialink = (0, combinator_1.lazy)(() => (0, combinator_1.constraint)(8 /* State.link */ | 4 /* State.media */, (0, combinator_1.state)(251 /* State.linkers */, (0, combinator_1.bind)((0, combinator_1.sequence)([(0, combinator_1.dup)((0, combinator_1.surround)('[', (0, combinator_1.union)([inline_1.media, inline_1.shortmedia]), ']')), (0, combinator_1.dup)((0, combinator_1.surround)(/{(?![{}])/y, (0, combinator_1.inits)([exports.uri, (0, combinator_1.some)(exports.option)]), / ?}/y))]), ([{
7411
+ exports.medialink = (0, combinator_1.lazy)(() => (0, combinator_1.constraint)(8 /* State.link */ | 4 /* State.media */, (0, combinator_1.state)(251 /* State.linkers */, (0, combinator_1.bind)((0, combinator_1.sequence)([(0, combinator_1.dup)((0, combinator_1.surround)('[', (0, combinator_1.union)([inline_1.media, inline_1.shortmedia]), ']')), (0, combinator_1.dup)((0, combinator_1.surround)(/{(?![{}])/y, (0, combinator_1.precedence)(9, (0, combinator_1.inits)([exports.uri, (0, combinator_1.some)(exports.option)])), / ?}/y))]), ([{
7419
7412
  value: content
7420
7413
  }, {
7421
7414
  value: params
@@ -7616,7 +7609,7 @@ exports.media = (0, combinator_1.lazy)(() => (0, combinator_1.constraint)(4 /* S
7616
7609
  return void (0, combinator_1.setBacktrack)(context, 2 | 64 /* Backtrack.link */ | 32 /* Backtrack.ruby */, head);
7617
7610
  }
7618
7611
  return ns;
7619
- })), (0, combinator_1.dup)((0, combinator_1.surround)(/{(?![{}])/y, (0, combinator_1.inits)([link_1.uri, (0, combinator_1.some)(option)]), / ?}/y, false, [], undefined, ([as, bs]) => bs && as.import(bs).push(new parser_1.Node("\u0018" /* Command.Cancel */)) && as))]), nodes => nodes.length === 1 ? new parser_1.List([new parser_1.Node(new parser_1.List([new parser_1.Node('')])), nodes.delete(nodes.head)]) : new parser_1.List([new parser_1.Node(new parser_1.List([new parser_1.Node(nodes.head.value.foldl((acc, {
7612
+ })), (0, combinator_1.dup)((0, combinator_1.surround)(/{(?![{}])/y, (0, combinator_1.precedence)(9, (0, combinator_1.inits)([link_1.uri, (0, combinator_1.some)(option)])), / ?}/y, false, [], undefined, ([as, bs]) => bs && as.import(bs).push(new parser_1.Node("\u0018" /* Command.Cancel */)) && as))]), nodes => nodes.length === 1 ? new parser_1.List([new parser_1.Node(new parser_1.List([new parser_1.Node('')])), nodes.delete(nodes.head)]) : new parser_1.List([new parser_1.Node(new parser_1.List([new parser_1.Node(nodes.head.value.foldl((acc, {
7620
7613
  value
7621
7614
  }) => acc + value, ''))])), nodes.delete(nodes.last)])), ([{
7622
7615
  value: [{
@@ -7740,14 +7733,17 @@ exports.reference = (0, combinator_1.lazy)(() => (0, combinator_1.constraint)(64
7740
7733
  (0, combinator_1.setBacktrack)(context, 2 | 4 /* Backtrack.common */, head, 2);
7741
7734
  } else if (linebreak !== 0) {
7742
7735
  (0, combinator_1.setBacktrack)(context, 2 | 128 /* Backtrack.doublebracket */ | 64 /* Backtrack.link */ | 32 /* Backtrack.ruby */, head, 2);
7736
+ } else if (source[position + 1] !== '{') {
7737
+ (0, combinator_1.setBacktrack)(context, 2 | 64 /* Backtrack.link */, head + 1);
7743
7738
  } else {
7744
7739
  context.position += 1;
7745
- if (source[context.position] !== '{' || (0, combinator_1.isBacktrack)(context, 1 | 64 /* Backtrack.link */) || !(0, link_1.textlink)({
7740
+ if (!(0, link_1.textlink)({
7746
7741
  context
7747
7742
  })) {
7748
7743
  (0, combinator_1.setBacktrack)(context, 2 | 64 /* Backtrack.link */, head + 1);
7749
7744
  }
7750
7745
  context.position = position;
7746
+ context.range = range;
7751
7747
  }
7752
7748
  })));
7753
7749
  // Chicago-Style
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "securemark",
3
- "version": "0.295.3",
3
+ "version": "0.295.4",
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",
@@ -1,7 +1,7 @@
1
1
  import { Parser, List, Node, Context } from '../parser';
2
2
 
3
- export function inits<P extends Parser>(parsers: Parser.SubParsers<P>, resume?: (nodes: List<Node<Parser.SubNode<P>>>) => boolean): Parser.SubNode<P> extends Parser.Node<P> ? P : Parser<Parser.SubNode<P>, Parser.Context<P>, Parser.SubParsers<P>>;
4
- export function inits<N, D extends Parser<N>[]>(parsers: D, resume?: (nodes: List<Node<N>>) => boolean): Parser<N, Context, D> {
3
+ export function inits<P extends Parser>(parsers: Parser.SubParsers<P>): Parser.SubNode<P> extends Parser.Node<P> ? P : Parser<Parser.SubNode<P>, Parser.Context<P>, Parser.SubParsers<P>>;
4
+ export function inits<N, D extends Parser<N>[]>(parsers: D): Parser<N, Context, D> {
5
5
  assert(parsers.every(f => f));
6
6
  if (parsers.length === 1) return parsers[0];
7
7
  return input => {
@@ -14,7 +14,6 @@ export function inits<N, D extends Parser<N>[]>(parsers: D, resume?: (nodes: Lis
14
14
  const result = parsers[i](input);
15
15
  if (result === undefined) break;
16
16
  nodes = nodes?.import(result) ?? result;
17
- if (resume?.(result) === false) break;
18
17
  }
19
18
  return nodes;
20
19
  };
@@ -1,7 +1,7 @@
1
1
  import { Parser, List, Node, Context } from '../parser';
2
2
 
3
- export function sequence<P extends Parser>(parsers: Parser.SubParsers<P>, resume?: (nodes: List<Node<Parser.SubNode<P>>>) => boolean): Parser.SubNode<P> extends Parser.Node<P> ? P : Parser<Parser.SubNode<P>, Parser.Context<P>, Parser.SubParsers<P>>;
4
- export function sequence<N, D extends Parser<N>[]>(parsers: D, resume?: (nodes: List<Node<N>>) => boolean): Parser<N, Context, D> {
3
+ export function sequence<P extends Parser>(parsers: Parser.SubParsers<P>): Parser.SubNode<P> extends Parser.Node<P> ? P : Parser<Parser.SubNode<P>, Parser.Context<P>, Parser.SubParsers<P>>;
4
+ export function sequence<N, D extends Parser<N>[]>(parsers: D): Parser<N, Context, D> {
5
5
  assert(parsers.every(f => f));
6
6
  if (parsers.length === 1) return parsers[0];
7
7
  return input => {
@@ -14,7 +14,6 @@ export function sequence<N, D extends Parser<N>[]>(parsers: D, resume?: (nodes:
14
14
  const result = parsers[i](input);
15
15
  if (result === undefined) return;
16
16
  nodes = nodes?.import(result) ?? result;
17
- if (resume?.(result) === false) return;
18
17
  }
19
18
  return nodes;
20
19
  };
@@ -1,13 +1,13 @@
1
- import { Parser, List, Node, Context } from '../parser';
1
+ import { Parser, Context } from '../parser';
2
2
  import { union } from './union';
3
3
  import { inits } from './inits';
4
4
 
5
- export function subsequence<P extends Parser>(parsers: Parser.SubParsers<P>, resume?: (nodes: List<Node<Parser.SubNode<P>>>) => boolean): Parser.SubNode<P> extends Parser.Node<P> ? P : Parser<Parser.SubNode<P>, Parser.Context<P>, Parser.SubParsers<P>>;
6
- export function subsequence<N, D extends Parser<N>[]>(parsers: D, resume?: (nodes: List<Node<N>>) => boolean): Parser<N, Context, D> {
5
+ export function subsequence<P extends Parser>(parsers: Parser.SubParsers<P>): Parser.SubNode<P> extends Parser.Node<P> ? P : Parser<Parser.SubNode<P>, Parser.Context<P>, Parser.SubParsers<P>>;
6
+ export function subsequence<N, D extends Parser<N>[]>(parsers: D): Parser<N, Context, D> {
7
7
  assert(parsers.every(f => f));
8
8
  return union(
9
9
  parsers.map((_, i) =>
10
10
  i + 1 < parsers.length
11
- ? inits([parsers[i], subsequence(parsers.slice(i + 1), resume)], resume)
11
+ ? inits([parsers[i], subsequence(parsers.slice(i + 1))])
12
12
  : parsers[i]) as D);
13
13
  }
@@ -1,8 +1,8 @@
1
- import { Parser, List, Node, Context } from '../parser';
1
+ import { Parser, Context } from '../parser';
2
2
  import { union } from './union';
3
3
  import { sequence } from './sequence';
4
4
 
5
- export function tails<P extends Parser>(parsers: Parser.SubParsers<P>, resume?: (nodes: List<Node<Parser.SubNode<P>>>) => boolean): Parser.SubNode<P> extends Parser.Node<P> ? P : Parser<Parser.SubNode<P>, Parser.Context<P>, Parser.SubParsers<P>>;
6
- export function tails<N, D extends Parser<N>[]>(parsers: D, resume?: (nodes: List<Node<N>>) => boolean): Parser<N, Context, D> {
7
- return union(parsers.map((_, i) => sequence(parsers.slice(i), resume)) as D);
5
+ export function tails<P extends Parser>(parsers: Parser.SubParsers<P>): Parser.SubNode<P> extends Parser.Node<P> ? P : Parser<Parser.SubNode<P>, Parser.Context<P>, Parser.SubParsers<P>>;
6
+ export function tails<N, D extends Parser<N>[]>(parsers: D): Parser<N, Context, D> {
7
+ return union(parsers.map((_, i) => sequence(parsers.slice(i))) as D);
8
8
  }
@@ -364,16 +364,16 @@ describe('Unit: parser/api/parse', () => {
364
364
  this.timeout(5000);
365
365
  // 最悪計算量での実行速度はCommonMarkの公式JS実装の32nに対して50-400%程度。
366
366
  // 6n = annotation + reference + link + url/math + ruby + text
367
- const source = `((([[[[#$[${'.'.repeat(16665)}`;
367
+ const source = `((([[[[#$[${'.'.repeat(16664)}]]]`;
368
368
  assert.deepStrictEqual(
369
369
  [...parse(source, {}, new Context({ resources: { clock: 100000, recursions: [100] } })).children]
370
370
  .map(el => el.tagName),
371
- ['P']);
371
+ ['P', 'OL']);
372
372
  });
373
373
 
374
374
  it('backtrack error', function () {
375
375
  this.timeout(5000);
376
- const source = `((([[[[#$[${'.'.repeat(16665 + 1)}`;
376
+ const source = `((([[[[#$[${'.'.repeat(16664 + 1)}]]]`;
377
377
  assert.deepStrictEqual(
378
378
  [...parse(source, {}, new Context({ resources: { clock: 100000, recursions: [100] } })).children]
379
379
  .map(el => el.tagName),
@@ -34,7 +34,6 @@ describe('Unit: parser/block/table', () => {
34
34
  assert.deepStrictEqual(inspect(parser, input('|"|\n|-\n|', new Context())), [['<table><thead><tr><th>"</th></tr></thead><tbody><tr></tr></tbody></table>'], '']);
35
35
  assert.deepStrictEqual(inspect(parser, input('|`|`|\n|-\n|', new Context())), [['<table><thead><tr><th><code data-src="`|`">|</code></th></tr></thead><tbody><tr></tr></tbody></table>'], '']);
36
36
  assert.deepStrictEqual(inspect(parser, input('|((|\n|-\n|', new Context())), [['<table><thead><tr><th><span class="paren">(<span class="paren">(</span></span></th></tr></thead><tbody><tr></tr></tbody></table>'], '']);
37
- assert.deepStrictEqual(inspect(parser, input('|${|\n|-\n|', new Context())), [['<table><thead><tr><th>${</th></tr></thead><tbody><tr></tr></tbody></table>'], '']);
38
37
  assert.deepStrictEqual(inspect(parser, input('|a|b|\n|-|-|\n|1|2|', new Context())), [['<table><thead><tr><th>a</th><th>b</th></tr></thead><tbody><tr><td>1</td><td>2</td></tr></tbody></table>'], '']);
39
38
  assert.deepStrictEqual(inspect(parser, input('|a|b\n|-|-\n|1|2', new Context())), [['<table><thead><tr><th>a</th><th>b</th></tr></thead><tbody><tr><td>1</td><td>2</td></tr></tbody></table>'], '']);
40
39
  assert.deepStrictEqual(inspect(parser, input('|a|\n|-|\n|1|', new Context())), [['<table><thead><tr><th>a</th></tr></thead><tbody><tr><td>1</td></tr></tbody></table>'], '']);
@@ -38,17 +38,15 @@ const p1 = lazy(() => surround(
38
38
  str('('),
39
39
  precedence(1, recursion(Recursion.bracket, some(inline, ')', [[')', 1]]))),
40
40
  str(')'),
41
+ // 唯一の参照者であるAnnotation構文に対してのみバックトラックを記録しその他は記録しない。
42
+ // 二重括弧構文の内括弧のバックトラックは二重括弧構文自身が記録するため記録不要。
43
+ // Ruby構文の丸括弧は常にRuby構文が先に到達し記録するため記録不要。
41
44
  true, [],
42
45
  ([as, bs = new List(), cs], context) => {
43
46
  const { source, position, range } = context;
44
47
  const head = position - range;
45
- if (context.linebreak !== 0) {
46
- if (head > 0 && source[head - 1] === '(') {
47
- setBacktrack(context, 2 | Backtrack.doublebracket, head - 1);
48
- }
49
- }
50
- else if (source[position] !== ')' && source[head - 1] === '(') {
51
- setBacktrack(context, 2 | Backtrack.doublebracket, head - 1);
48
+ if (source[head + 1] === '(' && (context.linebreak !== 0 || source[position - 2] !== ')')) {
49
+ setBacktrack(context, 2 | Backtrack.doublebracket, head);
52
50
  }
53
51
  const str = source.slice(position - range + 1, position - 1);
54
52
  return indexA.test(str)
@@ -91,13 +89,8 @@ const s1 = lazy(() => surround(
91
89
  ([as, bs = new List(), cs], context) => {
92
90
  const { source, position, range } = context;
93
91
  const head = position - range;
94
- if (context.linebreak !== 0) {
95
- if (head > 0 && source[head - 1] === '[') {
96
- setBacktrack(context, 2 | Backtrack.doublebracket, head - 1);
97
- }
98
- }
99
- else if (source[position] !== ']' && source[head - 1] === '[') {
100
- setBacktrack(context, 2 | Backtrack.doublebracket, head - 1);
92
+ if (source[head + 1] === '[' && (context.linebreak !== 0 || source[position - 2] !== ']')) {
93
+ setBacktrack(context, 2 | Backtrack.doublebracket, head);
101
94
  }
102
95
  if (context.state & State.link) {
103
96
  if (context.linebreak !== 0) {
@@ -108,15 +101,12 @@ const s1 = lazy(() => surround(
108
101
  }
109
102
  else {
110
103
  context.state ^= State.link;
111
- const result = !isBacktrack(context, 1 | Backtrack.link)
112
- ? textlink({ context })
113
- : undefined;
114
- context.position = position;
115
- if (!result) {
104
+ if (!isBacktrack(context, 1 | Backtrack.link) && !textlink({ context })) {
116
105
  setBacktrack(context, 2 | Backtrack.link, head);
117
106
  }
118
- context.state ^= State.link;
107
+ context.position = position;
119
108
  context.range = range;
109
+ context.state ^= State.link;
120
110
  }
121
111
  }
122
112
  return as.import(bs as List<Node<string>>).import(cs);
@@ -24,7 +24,7 @@ export const html: HTMLParser = lazy(() => validate(/<[a-z]+(?=[ >])/yi,
24
24
  surround(
25
25
  // https://html.spec.whatwg.org/multipage/syntax.html#void-elements
26
26
  str(/<(?:area|base|br|col|embed|hr|img|input|link|meta|source|track|wbr)(?=[ >])/y),
27
- some(union([attribute])),
27
+ precedence(9, some(union([attribute]))),
28
28
  open(str(/ ?/y), str('>'), true),
29
29
  true, [],
30
30
  ([as, bs = new List(), cs], context) =>
@@ -37,13 +37,15 @@ export const html: HTMLParser = lazy(() => validate(/<[a-z]+(?=[ >])/yi,
37
37
  ([, tag]) =>
38
38
  surround<HTMLParser.TagParser, string>(
39
39
  surround(
40
- str(`<${tag}`), some(attribute), open(str(/ ?/y), str('>'), true),
40
+ str(`<${tag}`),
41
+ precedence(9, some(attribute)),
42
+ open(str(/ ?/y), str('>'), true),
41
43
  true, [],
42
44
  ([as, bs = new List(), cs]) => as.import(bs).import(cs),
43
45
  ([as, bs = new List()]) => as.import(bs)),
44
46
  // 不可視のHTML構造が可視構造を変化させるべきでない。
45
47
  // 可視のHTMLは優先度変更を検討する。
46
- // このため<>は将来的に共通構造を変化させる可能性があり
48
+ // このため`<>`記号は将来的に共通構造を変化させる可能性があり
47
49
  // 共通構造を変化させない非構造文字列としては依然としてエスケープを要する。
48
50
  precedence(0, recursion(Recursion.inline,
49
51
  some(union([
@@ -61,7 +63,7 @@ export const html: HTMLParser = lazy(() => validate(/<[a-z]+(?=[ >])/yi,
61
63
  surround(
62
64
  // https://html.spec.whatwg.org/multipage/syntax.html#void-elements
63
65
  str(/<[a-z]+(?=[ >])/yi),
64
- some(union([attribute])),
66
+ precedence(9, some(union([attribute]))),
65
67
  open(str(/ ?/y), str('>'), true),
66
68
  true, [],
67
69
  ([as, bs = new List(), cs], context) =>
@@ -35,7 +35,7 @@ export const textlink: LinkParser.TextLinkParser = lazy(() => constraint(State.l
35
35
  // 自己再帰的にパースしてもオプションの不要なパースによる計算量の増加により相殺される。
36
36
  dup(surround(
37
37
  /{(?![{}])/y,
38
- inits([uri, some(option)]),
38
+ precedence(9, inits([uri, some(option)])),
39
39
  / ?}/y,
40
40
  false, [],
41
41
  undefined,
@@ -78,7 +78,10 @@ export const medialink: LinkParser.MediaLinkParser = lazy(() => constraint(State
78
78
  '[',
79
79
  union([media, shortmedia]),
80
80
  ']')),
81
- dup(surround(/{(?![{}])/y, inits([uri, some(option)]), / ?}/y)),
81
+ dup(surround(
82
+ /{(?![{}])/y,
83
+ precedence(9, inits([uri, some(option)])),
84
+ / ?}/y)),
82
85
  ]),
83
86
  ([{ value: content }, { value: params }], context) =>
84
87
  new List([new Node(parse(content, params as List<Node<string>>, context))])))));
@@ -40,7 +40,7 @@ export const media: MediaParser = lazy(() => constraint(State.media, open(
40
40
  })),
41
41
  dup(surround(
42
42
  /{(?![{}])/y,
43
- inits([uri, some(option)]),
43
+ precedence(9, inits([uri, some(option)])),
44
44
  / ?}/y,
45
45
  false, [],
46
46
  undefined,
@@ -38,15 +38,19 @@ export const reference: ReferenceParser = lazy(() => constraint(State.reference,
38
38
  else if (linebreak !== 0) {
39
39
  setBacktrack(context, 2 | Backtrack.doublebracket | Backtrack.link | Backtrack.ruby, head, 2);
40
40
  }
41
+ else if (source[position + 1] !== '{') {
42
+ setBacktrack(context, 2 | Backtrack.link, head + 1);
43
+ }
41
44
  else {
42
45
  assert(source[position] === ']');
46
+ assert(~context.state & State.link);
43
47
  context.position += 1;
44
- if (source[context.position] !== '{' ||
45
- isBacktrack(context, 1 | Backtrack.link) ||
46
- !textlink({ context })) {
48
+ assert(!isBacktrack(context, 1 | Backtrack.link));
49
+ if (!textlink({ context })) {
47
50
  setBacktrack(context, 2 | Backtrack.link, head + 1);
48
51
  }
49
52
  context.position = position;
53
+ context.range = range;
50
54
  }
51
55
  })));
52
56
 
@@ -165,7 +165,7 @@ describe('Unit: parser/inline', () => {
165
165
  assert.deepStrictEqual(inspect(parser, input('[^a@b', new Context())), [['[^', '<a class="email" href="mailto:a@b">a@b</a>'], '']);
166
166
  assert.deepStrictEqual(inspect(parser, input('"[% *"*"*', new Context())), [['"', '[%', ' ', '*', '"', '*', '"', '*'], '']);
167
167
  assert.deepStrictEqual(inspect(parser, input('"[% "*"* %]', new Context())), [['"', '<span class="remark"><input type="checkbox"><span>[% "*"* %]</span></span>'], '']);
168
- assert.deepStrictEqual(inspect(parser, input('"{{""}}', new Context())), [['"', '{', '{', '"', '"', '}', '}'], '']);
168
+ assert.deepStrictEqual(inspect(parser, input('"{{""}}', new Context())), [['"', '{', '<a class="url" href="&quot;&quot;">""</a>', '}'], '']);
169
169
  assert.deepStrictEqual(inspect(parser, input('[#http://host/(<bdi>)]</bdi>', new Context())), [['<a class="index" href="#index::http://host/(&lt;bdi&gt;)">http://host/<span class="paren">(<span class="invalid">&lt;bdi&gt;</span>)</span></a>', '</bdi', '>'], '']);
170
170
  assert.deepStrictEqual(inspect(parser, input('[#@a/http://host/(<bdi>)]</bdi>', new Context())), [['<a class="index" href="#index::@a/http://host/(&lt;bdi&gt;)">@a/http://host/<span class="paren">(<span class="invalid">&lt;bdi&gt;</span>)</span></a>', '</bdi', '>'], '']);
171
171
  assert.deepStrictEqual(inspect(parser, input('[#a|<bdi>]</bdi>', new Context())), [['<a class="index" href="#index::a|&lt;bdi&gt;">a|<span class="invalid">&lt;bdi&gt;</span></a>', '</bdi', '>'], '']);