securemark 0.295.3 → 0.295.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.295.5
4
+
5
+ - Refactoring.
6
+
7
+ ## 0.295.4
8
+
9
+ - Refactoring.
10
+
3
11
  ## 0.295.3
4
12
 
5
13
  - 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.5 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) {
@@ -6636,15 +6630,12 @@ const s1 = (0, combinator_1.lazy)(() => (0, combinator_1.surround)((0, source_1.
6636
6630
  } else if (source[position] !== '{') {
6637
6631
  (0, combinator_1.setBacktrack)(context, 2 | 64 /* Backtrack.link */, head);
6638
6632
  } else {
6639
- context.state ^= 8 /* State.link */;
6640
- const result = !(0, combinator_1.isBacktrack)(context, 1 | 64 /* Backtrack.link */) ? (0, link_1.textlink)({
6633
+ if (!(0, combinator_1.isBacktrack)(context, 1 | 64 /* Backtrack.link */) && !(0, link_1.textlink)({
6641
6634
  context
6642
- }) : undefined;
6643
- context.position = position;
6644
- if (!result) {
6635
+ })) {
6645
6636
  (0, combinator_1.setBacktrack)(context, 2 | 64 /* Backtrack.link */, head);
6646
6637
  }
6647
- context.state ^= 8 /* State.link */;
6638
+ context.position = position;
6648
6639
  context.range = range;
6649
6640
  }
6650
6641
  }
@@ -6914,19 +6905,14 @@ const dom_1 = __webpack_require__(394);
6914
6905
  exports.index = (0, combinator_1.lazy)(() => (0, combinator_1.constraint)(32 /* State.index */, (0, combinator_1.fmap)((0, indexee_1.indexee)((0, combinator_1.surround)((0, source_1.str)('[#'), (0, combinator_1.precedence)(1, (0, combinator_1.state)(251 /* State.linkers */, (0, visibility_1.tightStart)((0, combinator_1.some)((0, combinator_1.inits)([inline_1.inline, exports.signature]), ']', [[']', 1]])))), (0, source_1.str)(']'), false, [3 | 4 /* Backtrack.common */], ([, bs], context) => context.linebreak === 0 && (0, visibility_1.trimBlankNodeEnd)(bs).length > 0 ? new parser_1.List([new parser_1.Node((0, dom_1.html)('a', {
6915
6906
  'data-index': dataindex(bs)
6916
6907
  }, (0, dom_1.defrag)((0, util_1.unwrap)(bs))))]) : undefined, undefined)), ns => {
6917
- if (ns.length === 1) {
6918
- const el = ns.head.value;
6919
- return new parser_1.List([new parser_1.Node((0, dom_1.define)(el, {
6920
- id: el.id ? null : undefined,
6921
- class: 'index',
6922
- href: el.id ? `#${el.id}` : undefined
6923
- }))]);
6924
- } else {
6925
- ns.pop();
6926
- return ns;
6927
- }
6908
+ const el = ns.head.value;
6909
+ return new parser_1.List([new parser_1.Node((0, dom_1.define)(el, {
6910
+ id: el.id ? null : undefined,
6911
+ class: 'index',
6912
+ href: el.id ? `#${el.id}` : undefined
6913
+ }))]);
6928
6914
  })));
6929
- exports.signature = (0, combinator_1.lazy)(() => (0, combinator_1.validate)('|', (0, combinator_1.surround)((0, source_1.str)(/\|(?!\\?\s)/y), (0, combinator_1.some)((0, combinator_1.union)([htmlentity_1.unsafehtmlentity, (0, combinator_1.some)(source_1.txt, /(?:[$"`\[\](){}<>()[]{}|])/y)]), ']'), /(?=])/y, false, [3 | 16 /* Backtrack.escapable */], ([, ns], context) => {
6915
+ exports.signature = (0, combinator_1.lazy)(() => (0, combinator_1.validate)('|', (0, combinator_1.surround)((0, source_1.str)(/\|(?!\\?\s)/y), (0, combinator_1.precedence)(9, (0, combinator_1.some)((0, combinator_1.union)([htmlentity_1.unsafehtmlentity, (0, combinator_1.some)(source_1.txt, /(?:[$"`\[\](){}<>()[]{}|])/y)]), ']')), /(?=])/y, false, [3 | 16 /* Backtrack.escapable */], ([, ns], context) => {
6930
6916
  const index = (0, indexee_1.identity)('index', undefined, ns.foldl((acc, {
6931
6917
  value
6932
6918
  }) => acc + value, ''))?.slice(7);
@@ -7214,14 +7200,14 @@ Object.setPrototypeOf(attrspecs, null);
7214
7200
  Object.values(attrspecs).forEach(o => Object.setPrototypeOf(o, null));
7215
7201
  exports.html = (0, combinator_1.lazy)(() => (0, combinator_1.validate)(/<[a-z]+(?=[ >])/yi, (0, combinator_1.union)([(0, combinator_1.surround)(
7216
7202
  // 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)),
7203
+ (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
7204
  // 不可視のHTML構造が可視構造を変化させるべきでない。
7219
7205
  // 可視のHTMLは優先度変更を検討する。
7220
- // このため<>は将来的に共通構造を変化させる可能性があり
7206
+ // このため`<>`記号は将来的に共通構造を変化させる可能性があり
7221
7207
  // 共通構造を変化させない非構造文字列としては依然としてエスケープを要する。
7222
7208
  (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
7209
  // 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))]))])));
7210
+ (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
7211
  exports.attribute = (0, combinator_1.union)([(0, source_1.str)(/ [a-z]+(?:-[a-z]+)*(?:="(?:\\[^\n]|[^\\\n"])*")?(?=[ >])/yi), (0, source_1.str)(/ [^\s<>]+/y)]);
7226
7212
  function elem(tag, content, as, bs, cs, context) {
7227
7213
  if (!tags.includes(tag)) return ielem('tag', `Invalid HTML tag name "${tag}"`, context);
@@ -7381,20 +7367,21 @@ const optspec = {
7381
7367
  rel: ['nofollow']
7382
7368
  };
7383
7369
  Object.setPrototypeOf(optspec, null);
7384
- exports.textlink = (0, combinator_1.lazy)(() => (0, combinator_1.constraint)(8 /* State.link */, (0, combinator_1.precedence)(1, (0, combinator_1.state)(251 /* State.linkers */, (0, combinator_1.bind)((0, combinator_1.subsequence)([(0, combinator_1.dup)((0, combinator_1.surround)('[', (0, visibility_1.trimBlankStart)((0, combinator_1.some)((0, combinator_1.union)([inline_1.inline]), ']', [[']', 1]])), ']', true, [3 | 4 /* Backtrack.common */ | 64 /* Backtrack.link */, 2 | 32 /* Backtrack.ruby */], ([, ns = new parser_1.List()], context) => {
7370
+ exports.textlink = (0, combinator_1.lazy)(() => (0, combinator_1.bind)((0, combinator_1.subsequence)([(0, combinator_1.constraint)(8 /* State.link */, (0, combinator_1.state)(251 /* State.linkers */, (0, combinator_1.dup)((0, combinator_1.surround)('[', (0, combinator_1.precedence)(1, (0, visibility_1.trimBlankStart)((0, combinator_1.some)((0, combinator_1.union)([inline_1.inline]), ']', [[']', 1]]))), ']', true, [3 | 4 /* Backtrack.common */ | 64 /* Backtrack.link */, 2 | 32 /* Backtrack.ruby */], ([, ns = new parser_1.List()], context) => {
7385
7371
  if (context.linebreak !== 0) {
7386
7372
  const head = context.position - context.range;
7387
7373
  return void (0, combinator_1.setBacktrack)(context, 2 | 64 /* Backtrack.link */ | 32 /* Backtrack.ruby */, head);
7388
7374
  }
7389
7375
  return ns.push(new parser_1.Node("\u001F" /* Command.Separator */)) && ns;
7390
- })),
7376
+ })))),
7391
7377
  // `{ `と`{`で個別にバックトラックが発生し+1nされる。
7392
7378
  // 自己再帰的にパースしてもオプションの不要なパースによる計算量の増加により相殺される。
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))]), ([{
7379
+ (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
7380
  value: content
7395
7381
  }, {
7396
7382
  value: params = undefined
7397
7383
  } = {}], context) => {
7384
+ if (context.state & 8 /* State.link */) return new parser_1.List([new parser_1.Node(context.source.slice(context.position - context.range, context.position))]);
7398
7385
  if (content.last.value === "\u001F" /* Command.Separator */) {
7399
7386
  content.pop();
7400
7387
  if (params === undefined) {
@@ -7414,8 +7401,8 @@ exports.textlink = (0, combinator_1.lazy)(() => (0, combinator_1.constraint)(8 /
7414
7401
  }
7415
7402
  if (content.length !== 0 && (0, visibility_1.trimBlankNodeEnd)(content).length === 0) return;
7416
7403
  return new parser_1.List([new parser_1.Node(parse(content, params, context))]);
7417
- })))));
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))]), ([{
7404
+ }));
7405
+ 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
7406
  value: content
7420
7407
  }, {
7421
7408
  value: params
@@ -7616,7 +7603,7 @@ exports.media = (0, combinator_1.lazy)(() => (0, combinator_1.constraint)(4 /* S
7616
7603
  return void (0, combinator_1.setBacktrack)(context, 2 | 64 /* Backtrack.link */ | 32 /* Backtrack.ruby */, head);
7617
7604
  }
7618
7605
  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, {
7606
+ })), (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
7607
  value
7621
7608
  }) => acc + value, ''))])), nodes.delete(nodes.last)])), ([{
7622
7609
  value: [{
@@ -7740,14 +7727,17 @@ exports.reference = (0, combinator_1.lazy)(() => (0, combinator_1.constraint)(64
7740
7727
  (0, combinator_1.setBacktrack)(context, 2 | 4 /* Backtrack.common */, head, 2);
7741
7728
  } else if (linebreak !== 0) {
7742
7729
  (0, combinator_1.setBacktrack)(context, 2 | 128 /* Backtrack.doublebracket */ | 64 /* Backtrack.link */ | 32 /* Backtrack.ruby */, head, 2);
7730
+ } else if (source[position + 1] !== '{') {
7731
+ (0, combinator_1.setBacktrack)(context, 2 | 64 /* Backtrack.link */, head + 1);
7743
7732
  } else {
7744
7733
  context.position += 1;
7745
- if (source[context.position] !== '{' || (0, combinator_1.isBacktrack)(context, 1 | 64 /* Backtrack.link */) || !(0, link_1.textlink)({
7734
+ if (!(0, link_1.textlink)({
7746
7735
  context
7747
7736
  })) {
7748
7737
  (0, combinator_1.setBacktrack)(context, 2 | 64 /* Backtrack.link */, head + 1);
7749
7738
  }
7750
7739
  context.position = position;
7740
+ context.range = range;
7751
7741
  }
7752
7742
  })));
7753
7743
  // Chicago-Style
@@ -7861,11 +7851,11 @@ exports.ruby = (0, combinator_1.lazy)(() => (0, combinator_1.bind)((0, combinato
7861
7851
  value: ruby = ''
7862
7852
  } = {}]) => acc.import(ruby ? new parser_1.List([new parser_1.Node(text), new parser_1.Node((0, dom_1.html)('rp', '(')), new parser_1.Node((0, dom_1.html)('rt', ruby)), new parser_1.Node((0, dom_1.html)('rp', ')'))]) : new parser_1.List([new parser_1.Node(text), new parser_1.Node((0, dom_1.html)('rt'))])), new parser_1.List())))))]);
7863
7853
  default:
7864
- return new parser_1.List([new parser_1.Node((0, dom_1.html)('ruby', (0, dom_1.defrag)((0, util_1.unwrap)(new parser_1.List([new parser_1.Node(texts.foldr(({
7854
+ return new parser_1.List([new parser_1.Node((0, dom_1.html)('ruby', (0, dom_1.defrag)((0, util_1.unwrap)(new parser_1.List([new parser_1.Node(texts.foldl((acc, {
7865
7855
  value
7866
- }, acc) => value + ' ' + acc, '').slice(0, -1)), new parser_1.Node((0, dom_1.html)('rp', '(')), new parser_1.Node((0, dom_1.html)('rt', rubies.foldr(({
7856
+ }) => acc ? acc + ' ' + value : value, '')), new parser_1.Node((0, dom_1.html)('rp', '(')), new parser_1.Node((0, dom_1.html)('rt', rubies.foldl((acc, {
7867
7857
  value
7868
- }, acc) => value + ' ' + acc, '').trim())), new parser_1.Node((0, dom_1.html)('rp', ')'))])))))]);
7858
+ }) => acc ? acc + ' ' + value : value, '').trim())), new parser_1.Node((0, dom_1.html)('rp', ')'))])))))]);
7869
7859
  }
7870
7860
  }));
7871
7861
  const delimiter = /[$"`\[\](){}<>()[]{}|]|\\?\n/y;
@@ -8313,7 +8303,7 @@ const extension_1 = __webpack_require__(6193);
8313
8303
  const source_1 = __webpack_require__(8745);
8314
8304
  exports.MAX_SEGMENT_SIZE = 100_000; // 100,000 bytes (Max value size of FDB)
8315
8305
  exports.MAX_INPUT_SIZE = exports.MAX_SEGMENT_SIZE * 10;
8316
- const parser = (0, combinator_1.union)([(0, combinator_1.some)(source_1.emptyline), input => {
8306
+ const parser = (0, combinator_1.union)([(0, combinator_1.some)(source_1.emptyline, exports.MAX_SEGMENT_SIZE + 1), input => {
8317
8307
  const {
8318
8308
  context: {
8319
8309
  source,
@@ -8339,7 +8329,7 @@ const parser = (0, combinator_1.union)([(0, combinator_1.some)(source_1.emptylin
8339
8329
  case '$':
8340
8330
  return (0, extension_1.segment)(input);
8341
8331
  }
8342
- }, (0, combinator_1.some)(source_1.contentline)]);
8332
+ }, (0, combinator_1.some)(source_1.contentline, exports.MAX_SEGMENT_SIZE + 1)]);
8343
8333
  function* segment(source) {
8344
8334
  if (!validate(source, exports.MAX_INPUT_SIZE)) return yield `${"\u0007" /* Command.Error */}Too large input over ${exports.MAX_INPUT_SIZE.toLocaleString('en')} bytes.\n${source.slice(0, 1001)}`;
8345
8335
  for (let position = 0; position < source.length;) {
package/markdown.d.ts CHANGED
@@ -714,7 +714,7 @@ export namespace MarkdownParser {
714
714
  // [#index]
715
715
  // [#index|signature]
716
716
  Inline<'extension/index'>,
717
- Parser<string | HTMLElement, Context, [
717
+ Parser<HTMLAnchorElement, Context, [
718
718
  InlineParser,
719
719
  IndexParser.SignatureParser,
720
720
  ]> {
@@ -767,7 +767,7 @@ export namespace MarkdownParser {
767
767
  // { uri }
768
768
  // [abc]{uri nofollow}
769
769
  Inline<'link'>,
770
- Parser<HTMLAnchorElement | HTMLSpanElement, Context, [
770
+ Parser<HTMLAnchorElement | HTMLSpanElement | string, Context, [
771
771
  LinkParser.MediaLinkParser,
772
772
  LinkParser.TextLinkParser,
773
773
  ]> {
@@ -775,7 +775,7 @@ export namespace MarkdownParser {
775
775
  export namespace LinkParser {
776
776
  export interface TextLinkParser extends
777
777
  Inline<'link/textlink'>,
778
- Parser<HTMLAnchorElement | HTMLSpanElement, Context, [
778
+ Parser<HTMLAnchorElement | HTMLSpanElement | string, Context, [
779
779
  Parser<List<Node<string | HTMLElement>>, Context, [
780
780
  InlineParser,
781
781
  ]>,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "securemark",
3
- "version": "0.295.3",
3
+ "version": "0.295.5",
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
  }
@@ -30,7 +30,7 @@ describe('Unit: parser/api/bind', () => {
30
30
  const cfgs = { notes: { references: html('ol') } };
31
31
 
32
32
  it('huge input', () => {
33
- const iter = bind(html('div'), { ...cfgs, id: '' }).parse(`${'\n'.repeat(10 * 1000 ** 2)}`);
33
+ const iter = bind(html('div'), { ...cfgs, id: '' }).parse(`${'\n'.repeat(1e6 + 1)}`);
34
34
  assert.deepStrictEqual(
35
35
  inspect(iter),
36
36
  [
@@ -42,7 +42,7 @@ describe('Unit: parser/api/bind', () => {
42
42
  it('huge segment', function () {
43
43
  this.timeout(10 * 1000);
44
44
 
45
- const iter = bind(html('div'), { ...cfgs, id: '' }).parse(`${'\n'.repeat(1000 ** 2 - 1)}`);
45
+ const iter = bind(html('div'), { ...cfgs, id: '' }).parse(`${'\n'.repeat(1e5 + 1)}`);
46
46
  assert.deepStrictEqual(
47
47
  inspect(iter, 3),
48
48
  [
@@ -6,7 +6,7 @@ describe('Unit: parser/api/parse', () => {
6
6
  describe('parse', () => {
7
7
  it('huge input', () => {
8
8
  assert.deepStrictEqual(
9
- [...parse(`${'\n'.repeat(10 * 1000 ** 2)}`, { id: '' }).children].map(el => el.outerHTML),
9
+ [...parse(`${'\n'.repeat(1e6 + 1)}`, { id: '' }).children].map(el => el.outerHTML),
10
10
  [
11
11
  '<h1 class="error">Error: Too large input over 1,000,000 bytes.</h1>',
12
12
  `<pre class="error" translate="no">${'\n'.repeat(997)}...</pre>`,
@@ -15,7 +15,7 @@ describe('Unit: parser/api/parse', () => {
15
15
 
16
16
  it('huge segment', () => {
17
17
  assert.deepStrictEqual(
18
- [...parse(`${'\n'.repeat(100 * 1000 + 1)}`, { id: '' }).children].map(el => el.outerHTML),
18
+ [...parse(`${'\n'.repeat(1e5 + 1)}`, { id: '' }).children].map(el => el.outerHTML),
19
19
  [
20
20
  '<h1 class="error">Error: Too large segment over 100,000 bytes.</h1>',
21
21
  `<pre class="error" translate="no">${'\n'.repeat(997)}...</pre>`,
@@ -360,22 +360,32 @@ describe('Unit: parser/api/parse', () => {
360
360
  ]);
361
361
  });
362
362
 
363
- it('backtrack', function () {
364
- this.timeout(5000);
363
+ it('backtrack 1', () => {
365
364
  // 最悪計算量での実行速度はCommonMarkの公式JS実装の32nに対して50-400%程度。
366
365
  // 6n = annotation + reference + link + url/math + ruby + text
367
- const source = `((([[[[#$[${'.'.repeat(16665)}`;
368
366
  assert.deepStrictEqual(
369
- [...parse(source, {}, new Context({ resources: { clock: 100000, recursions: [100] } })).children]
367
+ [...parse(`((([[[[#$[${'.'.repeat(16665)}`, {}, new Context({ resources: { clock: 100000, recursions: [100] } })).children]
370
368
  .map(el => el.tagName),
371
369
  ['P']);
372
370
  });
373
371
 
374
- it('backtrack error', function () {
375
- this.timeout(5000);
376
- const source = `((([[[[#$[${'.'.repeat(16665 + 1)}`;
372
+ it('backtrack 1 error', () => {
377
373
  assert.deepStrictEqual(
378
- [...parse(source, {}, new Context({ resources: { clock: 100000, recursions: [100] } })).children]
374
+ [...parse(`((([[[[#$[${'.'.repeat(16665 + 1)}`, {}, new Context({ resources: { clock: 100000, recursions: [100] } })).children]
375
+ .map(el => el.tagName),
376
+ ['H1', 'PRE']);
377
+ });
378
+
379
+ it('backtrack 2', () => {
380
+ assert.deepStrictEqual(
381
+ [...parse(`((([[[[#$[${'.'.repeat(16664)}]]]`, {}, new Context({ resources: { clock: 100000, recursions: [100] } })).children]
382
+ .map(el => el.tagName),
383
+ ['P', 'OL']);
384
+ });
385
+
386
+ it('backtrack 2 error', () => {
387
+ assert.deepStrictEqual(
388
+ [...parse(`((([[[[#$[${'.'.repeat(16664 + 1)}]]]`, {}, new Context({ resources: { clock: 100000, recursions: [100] } })).children]
379
389
  .map(el => el.tagName),
380
390
  ['H1', 'PRE']);
381
391
  });
@@ -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) {
@@ -107,15 +100,10 @@ const s1 = lazy(() => surround(
107
100
  setBacktrack(context, 2 | Backtrack.link, head);
108
101
  }
109
102
  else {
110
- context.state ^= State.link;
111
- const result = !isBacktrack(context, 1 | Backtrack.link)
112
- ? textlink({ context })
113
- : undefined;
114
- context.position = position;
115
- if (!result) {
103
+ if (!isBacktrack(context, 1 | Backtrack.link) && !textlink({ context })) {
116
104
  setBacktrack(context, 2 | Backtrack.link, head);
117
105
  }
118
- context.state ^= State.link;
106
+ context.position = position;
119
107
  context.range = range;
120
108
  }
121
109
  }
@@ -29,29 +29,23 @@ export const index: IndexParser = lazy(() => constraint(State.index, fmap(indexe
29
29
  : undefined,
30
30
  undefined)),
31
31
  ns => {
32
- if (ns.length === 1) {
33
- const el = ns.head!.value as HTMLElement;
34
- return new List([
35
- new Node(define(el, {
36
- id: el.id ? null : undefined,
37
- class: 'index',
38
- href: el.id ? `#${el.id}` : undefined,
39
- }))
40
- ]);
41
- }
42
- else {
43
- assert(ns.last?.value === '');
44
- ns.pop();
45
- return ns;
46
- }
32
+ assert(ns.length === 1);
33
+ const el = ns.head!.value as HTMLAnchorElement;
34
+ return new List([
35
+ new Node(define(el, {
36
+ id: el.id ? null : undefined,
37
+ class: 'index',
38
+ href: el.id ? `#${el.id}` : undefined,
39
+ }))
40
+ ]);
47
41
  })));
48
42
 
49
43
  export const signature: IndexParser.SignatureParser = lazy(() => validate('|', surround(
50
44
  str(/\|(?!\\?\s)/y),
51
- some(union([
45
+ precedence(9, some(union([
52
46
  unsafehtmlentity,
53
47
  some(txt, /(?:[$"`\[\](){}<>()[]{}|])/y),
54
- ]), ']'),
48
+ ]), ']')),
55
49
  /(?=])/y,
56
50
  false,
57
51
  [3 | Backtrack.escapable],
@@ -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) =>
@@ -15,12 +15,12 @@ const optspec = {
15
15
  } as const;
16
16
  Object.setPrototypeOf(optspec, null);
17
17
 
18
- export const textlink: LinkParser.TextLinkParser = lazy(() => constraint(State.link,
19
- precedence(1, state(State.linkers,
20
- bind(subsequence([
21
- dup(surround(
18
+ export const textlink: LinkParser.TextLinkParser = lazy(() => bind(
19
+ subsequence([
20
+ constraint(State.link, state(State.linkers, dup(surround(
22
21
  '[',
23
- trimBlankStart(some(union([inline]), ']', [[']', 1]])),
22
+ precedence(1,
23
+ trimBlankStart(some(union([inline]), ']', [[']', 1]]))),
24
24
  ']',
25
25
  true,
26
26
  [3 | Backtrack.common | Backtrack.link, 2 | Backtrack.ruby],
@@ -30,12 +30,12 @@ export const textlink: LinkParser.TextLinkParser = lazy(() => constraint(State.l
30
30
  return void setBacktrack(context, 2 | Backtrack.link | Backtrack.ruby, head);
31
31
  }
32
32
  return ns.push(new Node(Command.Separator)) && ns;
33
- })),
33
+ })))),
34
34
  // `{ `と`{`で個別にバックトラックが発生し+1nされる。
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,
@@ -43,6 +43,7 @@ export const textlink: LinkParser.TextLinkParser = lazy(() => constraint(State.l
43
43
  bs && as.import(bs).push(new Node(Command.Cancel)) && as)),
44
44
  ]),
45
45
  ([{ value: content }, { value: params = undefined } = {}], context) => {
46
+ if (context.state & State.link) return new List([new Node(context.source.slice(context.position - context.range, context.position))]);
46
47
  if (content.last!.value === Command.Separator) {
47
48
  content.pop();
48
49
  if (params === undefined) {
@@ -69,7 +70,7 @@ export const textlink: LinkParser.TextLinkParser = lazy(() => constraint(State.l
69
70
  assert(content.head?.value !== '');
70
71
  if (content.length !== 0 && trimBlankNodeEnd(content).length === 0) return;
71
72
  return new List([new Node(parse(content, params as List<Node<string>>, context))]);
72
- })))));
73
+ }));
73
74
 
74
75
  export const medialink: LinkParser.MediaLinkParser = lazy(() => constraint(State.link | State.media,
75
76
  state(State.linkers,
@@ -78,7 +79,10 @@ export const medialink: LinkParser.MediaLinkParser = lazy(() => constraint(State
78
79
  '[',
79
80
  union([media, shortmedia]),
80
81
  ']')),
81
- dup(surround(/{(?![{}])/y, inits([uri, some(option)]), / ?}/y)),
82
+ dup(surround(
83
+ /{(?![{}])/y,
84
+ precedence(9, inits([uri, some(option)])),
85
+ / ?}/y)),
82
86
  ]),
83
87
  ([{ value: content }, { value: params }], context) =>
84
88
  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
 
@@ -53,9 +53,9 @@ export const ruby: RubyParser = lazy(() => bind(
53
53
  assert(rubies.length > 0);
54
54
  return new List([
55
55
  new Node(html('ruby', defrag(unwrap(new List<Node<string | HTMLElement>>([
56
- new Node(texts.foldr(({ value }, acc) => value + ' ' + acc, '').slice(0, -1)),
56
+ new Node(texts.foldl((acc, { value }) => acc ? acc + ' ' + value : value, '')),
57
57
  new Node(html('rp', '(')),
58
- new Node(html('rt', rubies.foldr(({ value }, acc) => value + ' ' + acc, '').trim())),
58
+ new Node(html('rt', rubies.foldl((acc, { value }) => acc ? acc + ' ' + value : value, '').trim())),
59
59
  new Node(html('rp', ')')),
60
60
  ]))))),
61
61
  ]);
@@ -165,11 +165,13 @@ 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', '>'], '']);
172
172
  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', '>'], '']);
173
+ assert.deepStrictEqual(inspect(parser, input('[]{"}[[""]]}]', new Context())), [['<a class="url" href="&quot;">"</a>', '<sup class="reference"><span>""</span></sup>', '}', ']'], '']);
174
+ assert.deepStrictEqual(inspect(parser, input('[ []{"}[[""]]}]', new Context())), [['[', ' ', '<a class="url" href="&quot;">"</a>', '<sup class="reference"><span>""</span></sup>', '}', ']'], '']);
173
175
  });
174
176
 
175
177
  it('uri', () => {
@@ -4,12 +4,12 @@ import { Command } from './context';
4
4
  describe('Unit: parser/segment', () => {
5
5
  describe('segment', () => {
6
6
  it('huge input', () => {
7
- const result = segment(`${'\n'.repeat(10 * 1000 ** 2)}`).next().value?.split('\n', 1)[0];
7
+ const result = segment(`${'\n'.repeat(1e6 + 1)}`).next().value?.split('\n', 1)[0];
8
8
  assert(result?.startsWith(`${Command.Error}Too large input`));
9
9
  });
10
10
 
11
11
  it('huge segment', () => {
12
- const result = segment(`${'\n'.repeat(1000 ** 2 - 1)}`).next().value?.split('\n', 1)[0];
12
+ const result = segment(`${'\n'.repeat(1e5 + 1)}`).next().value?.split('\n', 1)[0];
13
13
  assert(result?.startsWith(`${Command.Error}Too large segment`));
14
14
  });
15
15
 
@@ -13,7 +13,7 @@ export const MAX_SEGMENT_SIZE = 100_000; // 100,000 bytes (Max value size of FDB
13
13
  export const MAX_INPUT_SIZE = MAX_SEGMENT_SIZE * 10;
14
14
 
15
15
  const parser: SegmentParser = union([
16
- some(emptyline),
16
+ some(emptyline, MAX_SEGMENT_SIZE + 1),
17
17
  input => {
18
18
  const { context: { source, position } } = input;
19
19
  if (position === source.length) return;
@@ -36,7 +36,7 @@ const parser: SegmentParser = union([
36
36
  return extension(input);
37
37
  }
38
38
  },
39
- some(contentline),
39
+ some(contentline, MAX_SEGMENT_SIZE + 1),
40
40
  ]) as any;
41
41
 
42
42
  export function* segment(source: string): Generator<string, undefined, undefined> {