securemark 0.286.3 → 0.287.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.287.0
4
+
5
+ - Change template syntax to disallow linebreaks.
6
+ - Change signature syntax to parse texts with inline syntax.
7
+
8
+ ## 0.286.4
9
+
10
+ - Fix template parser.
11
+
3
12
  ## 0.286.3
4
13
 
5
14
  - Refactoring.
package/design.md CHANGED
@@ -291,7 +291,7 @@ CodeMirrorが素では速いがVimModeでは数万文字程度でも耐え難く
291
291
 
292
292
  SecuremarkのAnnotation構文に典型的であるように文脈を変更する構文の中にその文脈に依存し変更される他の構文が存在する場合文脈の相違から解析結果を再利用不能(`αAβ | αA'B`)なバックトラックが生じる。またこの結果再帰的バックトラックが生じる可能性があり再帰的バックトラックは一般的にメモ化により解決されるがCommonMarkは実行性能追及のためメモ化を廃止しているためメモ化により性能を低下させてまで文脈依存構文の問題を解決するつもりはないと思われる(すなわちCommonMarkは機械を至上とし人間に制約を課す低水準の言語であり人間の需要を至上とするSecuremarkとは対極に位置する)。従って現在の再帰的バックトラックなしで解析可能な構文と最小計算量に制約されるCommonMarkにはこれ以上再帰的バックトラックが生じる可能性を増加させて文脈依存構文を追加できないという拡張性の欠陥が存在する。CommonMarkの仕様策定者が構文の拡張に(名称を維持するか否かにかかわらず)不自然なまでに消極的または進展がないのは正当な理由や怠慢からでなく文脈依存構文を追加するにつれて構文解析戦略の失敗が明白になっていくためおよび現在の高い実行性能を低下させたくないためであり陳腐な自尊心を守るためにこのような拡張性の欠陥を秘匿しCommonMarkとその仕様策定者である自分の評価が下がらないよう画策しているからである。でなければ何年も隠さず速やかにこの拡張性の欠陥を公表して助力を求めていなければならず不都合な事実を隠し全Markdown利用者および開発者を不必要に足止めした罪は重い。CommonMarkは`~~a~~`のような文脈自由構文は容易に追加できるがこうしたマージンを失えばもはや後はない。
293
293
  CommonMarkは小さく単純であるがゆえに正しくいられる象牙の塔であり仕様策定者はこの正しさを失わず正しいままでいたいがために象牙の塔に引きこもり小さな表面的完全性に固執し続けているに過ぎない。しかし実際にはCommonMarkはまったく完全ではなく本来文脈依存構文である構文を文脈自由構文として解析しているため破綻している部分があり実際のところCommonMarkは最初から現在までずっと壊れている。またCommonMarkはバックトラックなく最小計算量で解析するために文脈自由言語として設計されているが実際には文脈依存言語であるMarkdownから文脈依存構文を文脈自由構文に変換して除去することができずCommonMarkは最初の数年間は再帰的バックトラックに気づかず最悪計算量が指数関数計算量になっており修正後は最悪計算量が当初の想定の1nから32nへと32倍に劇的に悪化している。CommonMarkは未だにバックトラックを忌避し1nの最小計算量に固執しているがそんなものはとっくの昔に破綻してるのを未練がましく執着しているだけである。最悪計算量が32nにまで悪化するのであれば計算量が少ないよう適切に設計された文脈依存言語と大差なく最初から文脈依存言語として適切に設計するほうが自然で破綻がなく拡張性を確保できていた。文脈依存構文を強引に文脈自由構文として解析して最悪計算量が当初の想定の1nから32nに劇的に悪化し結局文脈依存言語の妥当な最悪計算量の水準に落ちていることから文脈自由言語として設計されたCommonMarkの破綻と失敗は明らかでありCommonMarkは文脈自由構文に固執せず最初から多少の文脈依存構文を許容するよう設計しなければならなかった。実際には文脈依存言語であるにもかかわらず文脈自由言語としてしか構文解析できなければ構文解析が破綻し構文が増えるほど破綻が拡大することは自明でありすでに破綻済みで失敗済みのCommonMarkに未来などない。文脈依存言語であるMarkdownに対して文脈自由構文解析器として作られたCommonMarkは最初から技術選択を間違え失敗しており最初から破綻していた。Markdownを文脈自由言語として解析しようとして行き詰ったCommonMarkとその閉塞に技術的合理性はなくCommonMarkは最初からの失敗していた過去の遺物であり廃棄すべき負債である。CommonMarkに動きがないのはすでに破綻しており死んでいることに気付かれないように死んでいるからに過ぎない。このようにCommonMarkは完全に破綻し失敗に終わっているためCommonMarkの拡張や発展を期待しても無駄であり既存の文脈依存構文による破綻がなく新たに文脈依存構文を追加可能な拡張性の高いMarkdown仕様は新しく作り直さなければ作れない。しかしCommonMarkの仕様策定者は独自の新しい仕様においてもMarkdownをバックトラックを排除した文脈自由言語として設計しているため救いようがない。しかもその構文と仕様は機械可読性を至上としているため非常に醜く人間が書くことも読むことも困難で実用性の欠如したものである。
294
- Securemarkはスーパークラス構文が解析に失敗した入力をサブクラス構文で解析しないことにより再帰的バックトラックを回避する(ここで解析中の構文自身はスーパークラスとサブクラスの両方に含まれるものとする)。スーパークラス構文A(`αAβ`)の解析が失敗すればサブクラス構文B(`α'A'β'`)の解析も失敗することは自明であり解析を試みるまでもなく省略できる。これは構文の文法が生成する言語空間がスーパーセットとサブセットの関係にあるならスーパーセットの言語空間の外にある文字列はサブセットの言語空間の内に入る余地がないことからも自明である(この解析法は事前処理によっても可能だが文脈内外のオートリンクURLの括弧解析などを高速に行うことは困難であるためMarkdownをこの事前処理により高速化することは難しい)。メモ化は解析結果を再利用することで結果的に副次的効果としてバックトラックを回避しているのでありメモ化はバックトラックを回避するだけなら過剰機能であり不要である(メモ化はバックトラックがなければ使用されないためバックトラックの少ないほとんどの入力に対してはほとんど使用されず無駄であり空間計算量を常に不必要に数倍以上に増加させてまで行う利益は少ないことから構文解析において必須ではない。バックトラック回避のためにメモ化するとバックトラックなしで解析可能な場合も常に不必要に空間計算量が増加することがメモ化の最大の欠点である。特に文脈自由構文解析器におけるメモ化の使用は完全に無駄でありバグである。バックトラックが他の方法で解決されるならば最終的に文脈ごと破棄され使用されないメモ化も無駄であり複数の文脈で解析結果が同一である文脈独立性のある構文ならメモ化した解析結果を異なる文脈で再利用でき有用だがそのような構文は基本的に少数であるため効果が限定的であり最悪計算量は改善されない)。この独自の解析法によりSecuremarkはメモ化なしに線形時間で解析不能な文脈依存言語をメモ化なしでおおよそ14nの最悪時間計算量に改善しさらに一定時間内で解析不能な入力の影響を解析時間と解析範囲の局限することで解決している。この解析方法はほとんどの自然な入力に対して1nに近い時間で効率的に動作し、最悪計算量で低速に動作させる入力に対してもこの開発効率と安全性優先の低速な実装をサーバーで使用し多数のユーザーのリクエストに応じるには低速で脆弱性となる可能性があるがクライアントで個別のユーザーの操作に応じるには十分高速であるためクライアントで解析する限り解析の効率または速度が実用上問題となることはなく仕様が固まり実行効率優先の高速な実装に移れば速度面の懸念もないだろう。またSecuremarkはメモ化を行っていないため実装依存の非効率性を除けば空間計算量も小さく、異なる構文や状態の解析結果を利用して未知の入力に対してもバックトラックを回避できるためメモ化より時間計算量が小さい。時間計算量と空間計算量を合わせてO(n, n)と表記すると文脈依存言語の通常の最悪計算量はO(n^2, n)、メモ化により効率化できた場合もO(nm, nm)(解析結果の構文木等を記録するため空間使用量S(m)>=m byte)に過ぎないがSecuremarkの非再帰構文解析法はO(nm, n + nm)(解析失敗のフラグしか記録しないためS(m)=m bit。なお成功フラグによる解析は解析済みかの情報が追加で必要になり処理が複雑化かつほとんどの成功した解析に対してメモリ消費と追加処理が発生し解析効率が全体として悪化するが失敗フラグは少数の失敗した解析でしか解析効率が悪化しないため失敗フラグを記録するほうが全体として解析効率が高く優れている)と極めて効率的であり最も優れている。なお現在のSecuremarkは開発効率優先の実装により空間計算量が低下しているが時間計算量は低下せずメモ化より優れている。またSecuremarkの再帰数制限はパーサーコンビネーターの使用による実装依存の制限であるため再帰が生じないよう書き換えれば再帰数制限もない。SecuremarkをCommonMarkのような再帰数制限のない実装に変換することは設計上何の支障もないがCommonMarkをSecuremarkのような文脈依存言語解析器に変更することは根本的な設計変更なしに不可能である。例えば二重リンク`[[]()]()`を解析するときCommonMarkはバックトラックと計算量を最小化すべく文脈自由構文解析器として設計されているためリンク構文内を異なる文脈として解析せず外側のリンク構文の解析を破棄して内側のみリンクとして解析するがSecuremarkは文脈依存構文解析器とし設計されているため内側のリンク構文を無効化して外側のみリンクとして解析する。旧構文だけ従来通り文脈自由構文として解析し新構文を文脈依存構文として解析することも不可能ではないが構文としても解析器としてもキメラ的な非常に不自然で歪なものとなり解析規則の一貫性のなさによりユーザーを混乱させることになる。いずれにせよCommonMarkはこのような根本的設計変更なしに文脈依存構文解析器に変更して拡張性を確保することはできないためMarkdownは素直にCommonMarkの文脈自由言語特有の解析規則を捨てて素直な文脈依存構文言語として新しい仕様を作るのが賢明である。
294
+ Securemarkはスーパークラス構文が解析に失敗した入力をサブクラス構文で解析しないことにより再帰的バックトラックを回避する(ここで解析中の構文自身はスーパークラスとサブクラスの両方に含まれるものとする)。スーパークラス構文A(`αAβ`)の解析が失敗すればサブクラス構文B(`α'A'β'`)の解析も失敗することは自明であり解析を試みるまでもなく省略できる。これは構文の文法が生成する言語空間がスーパーセットとサブセットの関係にあるならスーパーセットの言語空間の外にある文字列はサブセットの言語空間の内に入る余地がないことからも自明である(この解析法は事前処理によっても可能だが文脈内外のオートリンクURLの括弧解析などを高速に行うことは困難であるためMarkdownをこの事前処理により高速化することは難しい)。メモ化は解析結果を再利用することで結果的に副次的効果としてバックトラックを回避しているのでありメモ化はバックトラックを回避するだけなら過剰機能であり不要である(メモ化はバックトラックがなければ使用されないためバックトラックの少ないほとんどの入力に対してはほとんど使用されず無駄であり空間計算量を常に不必要に数倍以上に増加させてまで行う利益は少ないことから構文解析において必須ではない。バックトラック回避のためにメモ化するとバックトラックなしで解析可能な場合も常に不必要に空間計算量が増加することがメモ化の最大の欠点である(この問題は解析失敗時のみメモ化すれば解消可能のはずだが基本的にはこうなる)。特に文脈自由構文解析器におけるメモ化の使用は完全に無駄でありバグである。バックトラックが他の方法で解決されるならば最終的に文脈ごと破棄され使用されないメモ化も無駄であり複数の文脈で解析結果が同一である文脈独立性のある構文ならメモ化した解析結果を異なる文脈で再利用でき有用だがそのような構文は基本的に少数であるため効果が限定的であり最悪計算量は改善されない)。この独自の解析法によりSecuremarkはメモ化なしに線形時間で解析不能な文脈依存言語をメモ化なしでおおよそ12nの最悪時間計算量に改善しさらに一定時間内で解析不能な入力の影響を解析時間と解析範囲の局限することで解決している。この解析方法はほとんどの自然な入力に対して1nに近い時間で効率的に動作し、最悪計算量で低速に動作させる入力に対してもこの開発効率と安全性優先の低速な実装をサーバーで使用し多数のユーザーのリクエストに応じるには低速で脆弱性となる可能性があるがクライアントで個別のユーザーの操作に応じるには十分高速であるためクライアントで解析する限り解析の効率または速度が実用上問題となることはなく仕様が固まり実行効率優先の高速な実装に移れば速度面の懸念もないだろう。またSecuremarkはメモ化を行っていないため実装依存の非効率性を除けば空間計算量も小さく、異なる構文や状態の解析結果を利用して未知の入力に対してもバックトラックを回避できるためメモ化より時間計算量が小さい。時間計算量と空間計算量を合わせてO(n, n)と表記すると文脈依存言語の通常の最悪計算量はO(n^2, n)、メモ化により効率化できた場合もO(nm, nm)(解析結果の構文木等を記録するため空間使用量S(m)>=m byte)に過ぎないがSecuremarkの失敗単一化はO(nm, n + nm)(解析失敗のフラグしか記録しないためS(m)=m bit。また包含文字列を含め全体でn byteの構文1つに対してメモ化は少なくともn byteを消費するが失敗単一化のメモリ消費量は構文全体のサイズにかかわらず1 bit固定である。なお成功フラグによる解析は解析済みかの情報が追加で必要になり処理が複雑化かつほとんどの成功した解析に対してメモリ消費と追加処理が発生し解析効率が全体として悪化するが失敗フラグは少数の失敗した解析でしか解析効率が悪化しないため失敗フラグを記録するほうが全体として解析効率が高く優れている)と極めて効率的であり最も優れている。なお現在のSecuremarkは開発効率優先の実装により空間計算量が低下しているが時間計算量は低下せずメモ化より優れている。またSecuremarkの再帰数制限はパーサーコンビネーターの使用による実装依存の制限であるため再帰が生じないよう書き換えれば再帰数制限もない。SecuremarkをCommonMarkのような再帰数制限のない実装に変換することは設計上何の支障もないがCommonMarkをSecuremarkのような文脈依存言語解析器に変更することは根本的な設計変更なしに不可能である。例えば二重リンク`[[]()]()`を解析するときCommonMarkはバックトラックと計算量を最小化すべく文脈自由構文解析器として設計されているためリンク構文内を異なる文脈として解析せず外側のリンク構文の解析を破棄して内側のみリンクとして解析するがSecuremarkは文脈依存構文解析器とし設計されているため内側のリンク構文を無効化して外側のみリンクとして解析する。旧構文だけ従来通り文脈自由構文として解析し新構文を文脈依存構文として解析することも不可能ではないが構文としても解析器としてもキメラ的な非常に不自然で歪なものとなり解析規則の一貫性のなさによりユーザーを混乱させることになる。いずれにせよCommonMarkはこのような根本的設計変更なしに文脈依存構文解析器に変更して拡張性を確保することはできないためMarkdownは素直にCommonMarkの文脈自由言語特有の解析規則を捨てて素直な文脈依存構文言語として新しい仕様を作るのが賢明である。
295
295
 
296
296
  ### 最適化
297
297
 
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- /*! securemark v0.286.3 https://github.com/falsandtru/securemark | (c) 2017, falsandtru | UNLICENSED License */
1
+ /*! securemark v0.287.0 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"));
@@ -2002,7 +2002,7 @@ exports.url = (0, combinator_1.lazy)(() => (0, combinator_1.validate)(['http://'
2002
2002
  exports.lineurl = (0, combinator_1.lazy)(() => (0, combinator_1.open)(source_1.linebreak, (0, combinator_1.focus)(/^!?https?:\/\/\S+(?=[^\S\n]*(?:$|\n))/, (0, combinator_1.tails)([(0, source_1.str)('!'), (0, combinator_1.union)([(0, combinator_1.constraint)(1 /* State.autolink */, false, (0, combinator_1.state)(1 /* State.autolink */, (0, combinator_1.convert)(url => `{ ${url} }`, link_1.unsafelink))), ({
2003
2003
  source
2004
2004
  }) => [[source], '']])]))));
2005
- const bracket = (0, combinator_1.lazy)(() => (0, combinator_1.union)([(0, combinator_1.surround)((0, source_1.str)('('), (0, combinator_1.recursion)(6 /* Recursion.terminal */, (0, combinator_1.some)((0, combinator_1.union)([bracket, source_1.unescsource]), ')')), (0, source_1.str)(')'), true, undefined, () => [["\u001B" /* Command.Escape */], ''], 3 | 0 /* Backtrack.url */), (0, combinator_1.surround)((0, source_1.str)('['), (0, combinator_1.recursion)(6 /* Recursion.terminal */, (0, combinator_1.some)((0, combinator_1.union)([bracket, source_1.unescsource]), ']')), (0, source_1.str)(']'), true, undefined, () => [["\u001B" /* Command.Escape */], ''], 3 | 0 /* Backtrack.url */), (0, combinator_1.surround)((0, source_1.str)('{'), (0, combinator_1.recursion)(6 /* Recursion.terminal */, (0, combinator_1.some)((0, combinator_1.union)([bracket, source_1.unescsource]), '}')), (0, source_1.str)('}'), true, undefined, () => [["\u001B" /* Command.Escape */], ''], 3 | 0 /* Backtrack.url */), (0, combinator_1.surround)((0, source_1.str)('"'), (0, combinator_1.precedence)(2, (0, combinator_1.recursion)(6 /* Recursion.terminal */, (0, combinator_1.some)(source_1.unescsource, '"'))), (0, source_1.str)('"'), true, undefined, () => [["\u001B" /* Command.Escape */], ''], 3 | 0 /* Backtrack.url */)]));
2005
+ const bracket = (0, combinator_1.lazy)(() => (0, combinator_1.union)([(0, combinator_1.surround)((0, source_1.str)('('), (0, combinator_1.recursion)(6 /* Recursion.terminal */, (0, combinator_1.some)((0, combinator_1.union)([bracket, source_1.unescsource]), ')')), (0, source_1.str)(')'), true, undefined, () => [["\u001B" /* Command.Escape */], ''], [3 | 0 /* Backtrack.lineunescbracket */]), (0, combinator_1.surround)((0, source_1.str)('['), (0, combinator_1.recursion)(6 /* Recursion.terminal */, (0, combinator_1.some)((0, combinator_1.union)([bracket, source_1.unescsource]), ']')), (0, source_1.str)(']'), true, undefined, () => [["\u001B" /* Command.Escape */], ''], [3 | 0 /* Backtrack.lineunescbracket */]), (0, combinator_1.surround)((0, source_1.str)('{'), (0, combinator_1.recursion)(6 /* Recursion.terminal */, (0, combinator_1.some)((0, combinator_1.union)([bracket, source_1.unescsource]), '}')), (0, source_1.str)('}'), true, undefined, () => [["\u001B" /* Command.Escape */], ''], [3 | 0 /* Backtrack.lineunescbracket */]), (0, combinator_1.surround)((0, source_1.str)('"'), (0, combinator_1.precedence)(2, (0, combinator_1.recursion)(6 /* Recursion.terminal */, (0, combinator_1.some)(source_1.unescsource, '"'))), (0, source_1.str)('"'), true, undefined, () => [["\u001B" /* Command.Escape */], ''], [3 | 0 /* Backtrack.lineunescbracket */])]));
2006
2006
 
2007
2007
  /***/ },
2008
2008
 
@@ -2076,7 +2076,7 @@ const source_1 = __webpack_require__(8745);
2076
2076
  const dom_1 = __webpack_require__(394);
2077
2077
  const body = (0, source_1.str)(/^\$[A-Za-z]*(?:(?:-[A-Za-z][0-9A-Za-z]*)+|-(?:(?:0|[1-9][0-9]*)\.)*(?:0|[1-9][0-9]*)(?![0-9A-Za-z]))/);
2078
2078
  exports.segment = (0, combinator_1.clear)((0, combinator_1.union)([(0, combinator_1.surround)('[', body, ']'), body]));
2079
- exports.label = (0, combinator_1.constraint)(16 /* State.label */, false, (0, combinator_1.fmap)((0, combinator_1.union)([(0, combinator_1.surround)('[', body, ']', false, undefined, undefined, 1 | 4 /* Backtrack.bracket */), body]), ([text]) => [(0, dom_1.html)('a', {
2079
+ exports.label = (0, combinator_1.constraint)(16 /* State.label */, false, (0, combinator_1.fmap)((0, combinator_1.union)([(0, combinator_1.surround)('[', body, ']', false, undefined, undefined, [1 | 12 /* Backtrack.linebracket */, 1]), body]), ([text]) => [(0, dom_1.html)('a', {
2080
2080
  class: 'label',
2081
2081
  'data-label': text.slice(text[1] === '-' ? 0 : 1).toLowerCase()
2082
2082
  }, text)]));
@@ -3274,7 +3274,7 @@ const optspec = {
3274
3274
  rel: ['nofollow']
3275
3275
  };
3276
3276
  Object.setPrototypeOf(optspec, null);
3277
- exports.textlink = (0, combinator_1.lazy)(() => (0, combinator_1.constraint)(8 /* State.link */, false, (0, combinator_1.creation)(10, (0, combinator_1.precedence)(1, (0, combinator_1.state)(251 /* State.linkers */ | 4 /* State.media */, (0, combinator_1.bind)((0, combinator_1.reverse)((0, combinator_1.tails)([(0, combinator_1.dup)((0, combinator_1.surround)('[', (0, visibility_1.trimBlankStart)((0, combinator_1.some)((0, combinator_1.union)([inline_1.inline]), ']', [['\n', 9], [']', 1]])), ']', true, undefined, undefined, 1 | 8 /* Backtrack.linebracket */, 4 /* Backtrack.bracket */ | 1 /* BacktrackState.nobreak */)), (0, combinator_1.dup)((0, combinator_1.surround)(/^{(?![{}])/, (0, combinator_1.inits)([exports.uri, (0, combinator_1.some)(exports.option)]), /^[^\S\n]*}/, false, undefined, undefined, 3 | 20 /* Backtrack.link */))])), ([params, content = []], rest, context) => {
3277
+ exports.textlink = (0, combinator_1.lazy)(() => (0, combinator_1.constraint)(8 /* State.link */, false, (0, combinator_1.creation)(10, (0, combinator_1.precedence)(1, (0, combinator_1.state)(251 /* State.linkers */ | 4 /* State.media */, (0, combinator_1.bind)((0, combinator_1.reverse)((0, combinator_1.tails)([(0, combinator_1.dup)((0, combinator_1.surround)('[', (0, visibility_1.trimBlankStart)((0, combinator_1.some)((0, combinator_1.union)([inline_1.inline]), ']', [['\n', 9], [']', 1]])), ']', true, undefined, undefined, [1 | 12 /* Backtrack.linebracket */], 8 /* Backtrack.bracket */ | 1 /* BacktrackState.nobreak */)), (0, combinator_1.dup)((0, combinator_1.surround)(/^{(?![{}])/, (0, combinator_1.inits)([exports.uri, (0, combinator_1.some)(exports.option)]), /^[^\S\n]*}/, false, undefined, undefined, [3 | 24 /* Backtrack.link */]))])), ([params, content = []], rest, context) => {
3278
3278
  if (content.length !== 0 && (0, visibility_1.trimBlankNodeEnd)(content).length === 0) return;
3279
3279
  return [[parse((0, dom_1.defrag)(content), params, context)], rest];
3280
3280
  }))))));
@@ -4007,6 +4007,7 @@ const escsource = ({
4007
4007
  (0, combinator_1.consume)(1, context);
4008
4008
  switch (source[0]) {
4009
4009
  case '\r':
4010
+ (0, combinator_1.consume)(-1, context);
4010
4011
  return [[], source.slice(1)];
4011
4012
  case "\u001B" /* Command.Escape */:
4012
4013
  (0, combinator_1.consume)(1, context);
@@ -4360,7 +4361,7 @@ const visibility_1 = __webpack_require__(6364);
4360
4361
  const dom_1 = __webpack_require__(394);
4361
4362
  exports.annotation = (0, combinator_1.lazy)(() => (0, combinator_1.constraint)(128 /* State.annotation */, false, (0, combinator_1.surround)('((', (0, combinator_1.precedence)(1, (0, combinator_1.state)(128 /* State.annotation */ | 4 /* State.media */, (0, visibility_1.trimBlankStart)((0, combinator_1.some)((0, combinator_1.union)([inline_1.inline]), ')', [['\n', 9], [')', 1]])))), '))', false, ([, ns], rest) => (0, visibility_1.trimBlankNodeEnd)(ns).length > 0 ? [[(0, dom_1.html)('sup', {
4362
4363
  class: 'annotation'
4363
- }, [(0, dom_1.html)('span', (0, dom_1.defrag)(ns))])], rest] : undefined, undefined, 1 | 8 /* Backtrack.linebracket */, 4 /* Backtrack.bracket */ | 1 /* BacktrackState.nobreak */)));
4364
+ }, [(0, dom_1.html)('span', (0, dom_1.defrag)(ns))])], rest] : undefined, undefined, [3 | 16 /* Backtrack.linedoublebracket */, 1 | 12 /* Backtrack.linebracket */], 8 /* Backtrack.bracket */ | 1 /* BacktrackState.nobreak */)));
4364
4365
 
4365
4366
  /***/ },
4366
4367
 
@@ -5027,10 +5028,10 @@ exports.template = void 0;
5027
5028
  const combinator_1 = __webpack_require__(3484);
5028
5029
  const source_1 = __webpack_require__(8745);
5029
5030
  const dom_1 = __webpack_require__(394);
5030
- exports.template = (0, combinator_1.lazy)(() => (0, combinator_1.surround)('{{', (0, combinator_1.precedence)(1, (0, combinator_1.some)((0, combinator_1.verify)((0, combinator_1.union)([bracket, source_1.escsource]), ns => ns[0] !== "\u001B" /* Command.Escape */), '}')), '}}', true, ([, ns = []], rest) => [[(0, dom_1.html)('span', {
5031
+ exports.template = (0, combinator_1.lazy)(() => (0, combinator_1.surround)('{{', (0, combinator_1.precedence)(1, (0, combinator_1.some)((0, combinator_1.verify)((0, combinator_1.union)([bracket, source_1.escsource]), ns => ns[0] !== "\u001B" /* Command.Escape */), '}', [['\n', 9]])), '}}', true, ([, ns = []], rest) => [[(0, dom_1.html)('span', {
5031
5032
  class: 'template'
5032
- }, `{{${ns.join('')}}}`)], rest], undefined, 3 | 28 /* Backtrack.template */));
5033
- const bracket = (0, combinator_1.lazy)(() => (0, combinator_1.union)([(0, combinator_1.surround)((0, source_1.str)('('), (0, combinator_1.recursion)(6 /* Recursion.terminal */, (0, combinator_1.some)((0, combinator_1.union)([bracket, source_1.escsource]), ')')), (0, source_1.str)(')'), true, undefined, () => [["\u001B" /* Command.Escape */], ''], 3 | 28 /* Backtrack.template */), (0, combinator_1.surround)((0, source_1.str)('['), (0, combinator_1.recursion)(6 /* Recursion.terminal */, (0, combinator_1.some)((0, combinator_1.union)([bracket, source_1.escsource]), ']')), (0, source_1.str)(']'), true, undefined, () => [["\u001B" /* Command.Escape */], ''], 3 | 28 /* Backtrack.template */), (0, combinator_1.surround)((0, source_1.str)('{'), (0, combinator_1.recursion)(6 /* Recursion.terminal */, (0, combinator_1.some)((0, combinator_1.union)([bracket, source_1.escsource]), '}')), (0, source_1.str)('}'), true, undefined, () => [["\u001B" /* Command.Escape */], ''], 3 | 28 /* Backtrack.template */), (0, combinator_1.surround)((0, source_1.str)('"'), (0, combinator_1.precedence)(2, (0, combinator_1.recursion)(6 /* Recursion.terminal */, (0, combinator_1.some)(source_1.escsource, /^["\n]/))), (0, source_1.str)('"'), true, undefined, () => [["\u001B" /* Command.Escape */], ''], 3 | 28 /* Backtrack.template */)]));
5033
+ }, `{{${ns.join('')}}}`)], rest], undefined, [3 | 16 /* Backtrack.linedoublebracket */, 1 | 4 /* Backtrack.lineescbracket */], 8 /* Backtrack.bracket */));
5034
+ const bracket = (0, combinator_1.lazy)(() => (0, combinator_1.union)([(0, combinator_1.surround)((0, source_1.str)('('), (0, combinator_1.recursion)(6 /* Recursion.terminal */, (0, combinator_1.some)((0, combinator_1.union)([bracket, source_1.escsource]), ')')), (0, source_1.str)(')'), true, undefined, () => [["\u001B" /* Command.Escape */], ''], [3 | 4 /* Backtrack.lineescbracket */]), (0, combinator_1.surround)((0, source_1.str)('['), (0, combinator_1.recursion)(6 /* Recursion.terminal */, (0, combinator_1.some)((0, combinator_1.union)([bracket, source_1.escsource]), ']')), (0, source_1.str)(']'), true, undefined, () => [["\u001B" /* Command.Escape */], ''], [3 | 4 /* Backtrack.lineescbracket */]), (0, combinator_1.surround)((0, source_1.str)('{'), (0, combinator_1.recursion)(6 /* Recursion.terminal */, (0, combinator_1.some)((0, combinator_1.union)([bracket, source_1.escsource]), '}')), (0, source_1.str)('}'), true, undefined, () => [["\u001B" /* Command.Escape */], ''], [3 | 4 /* Backtrack.lineescbracket */]), (0, combinator_1.surround)((0, source_1.str)('"'), (0, combinator_1.precedence)(2, (0, combinator_1.recursion)(6 /* Recursion.terminal */, (0, combinator_1.some)(source_1.escsource, /^["\n]/))), (0, source_1.str)('"'), true, undefined, () => [["\u001B" /* Command.Escape */], ''], [3 | 4 /* Backtrack.lineescbracket */])]));
5034
5035
 
5035
5036
  /***/ },
5036
5037
 
@@ -5071,11 +5072,11 @@ const array_1 = __webpack_require__(6876);
5071
5072
  const dom_1 = __webpack_require__(394);
5072
5073
  const indexA = /^[0-9A-Za-z]+(?:(?:[.-]|, )[0-9A-Za-z]+)*(?=\))/;
5073
5074
  const indexF = new RegExp(indexA.source.replace(', ', '[,、]').replace(/[09AZaz.]|\-(?!\w)|\)(?=\)$)/g, c => String.fromCodePoint(c.codePointAt(0) + 0xFEE0)));
5074
- exports.bracket = (0, combinator_1.lazy)(() => (0, combinator_1.union)([(0, combinator_1.surround)((0, source_1.str)('('), (0, combinator_1.recursion)(5 /* Recursion.bracket */, (0, combinator_1.precedence)(1, (0, source_1.str)(indexA))), (0, source_1.str)(')'), false, undefined, undefined, 3 | 4 /* Backtrack.bracket */), (0, combinator_1.surround)((0, source_1.str)('('), (0, combinator_1.recursion)(5 /* Recursion.bracket */, (0, combinator_1.precedence)(1, (0, combinator_1.some)(inline_1.inline, ')', [[')', 1]]))), (0, source_1.str)(')'), true, ([as, bs = [], cs], rest) => [[(0, dom_1.html)('span', {
5075
+ exports.bracket = (0, combinator_1.lazy)(() => (0, combinator_1.union)([(0, combinator_1.surround)((0, source_1.str)('('), (0, combinator_1.recursion)(5 /* Recursion.bracket */, (0, combinator_1.precedence)(1, (0, source_1.str)(indexA))), (0, source_1.str)(')'), false, undefined, undefined, [3 | 8 /* Backtrack.bracket */]), (0, combinator_1.surround)((0, source_1.str)('('), (0, combinator_1.recursion)(5 /* Recursion.bracket */, (0, combinator_1.precedence)(1, (0, combinator_1.some)(inline_1.inline, ')', [[')', 1]]))), (0, source_1.str)(')'), true, ([as, bs = [], cs], rest) => [[(0, dom_1.html)('span', {
5075
5076
  class: 'paren'
5076
- }, (0, dom_1.defrag)((0, array_1.push)((0, array_1.unshift)(as, bs), cs)))], rest], ([as, bs = []], rest) => [(0, array_1.unshift)(as, bs), rest], 3 | 4 /* Backtrack.bracket */), (0, combinator_1.surround)((0, source_1.str)('('), (0, combinator_1.recursion)(5 /* Recursion.bracket */, (0, combinator_1.precedence)(1, (0, source_1.str)(indexF))), (0, source_1.str)(')'), false, undefined, undefined, 3 | 4 /* Backtrack.bracket */), (0, combinator_1.surround)((0, source_1.str)('('), (0, combinator_1.recursion)(5 /* Recursion.bracket */, (0, combinator_1.precedence)(1, (0, combinator_1.some)(inline_1.inline, ')', [[')', 1]]))), (0, source_1.str)(')'), true, ([as, bs = [], cs], rest) => [[(0, dom_1.html)('span', {
5077
+ }, (0, dom_1.defrag)((0, array_1.push)((0, array_1.unshift)(as, bs), cs)))], rest], ([as, bs = []], rest) => [(0, array_1.unshift)(as, bs), rest], [3 | 8 /* Backtrack.bracket */]), (0, combinator_1.surround)((0, source_1.str)('('), (0, combinator_1.recursion)(5 /* Recursion.bracket */, (0, combinator_1.precedence)(1, (0, source_1.str)(indexF))), (0, source_1.str)(')'), false, undefined, undefined, [3 | 8 /* Backtrack.bracket */]), (0, combinator_1.surround)((0, source_1.str)('('), (0, combinator_1.recursion)(5 /* Recursion.bracket */, (0, combinator_1.precedence)(1, (0, combinator_1.some)(inline_1.inline, ')', [[')', 1]]))), (0, source_1.str)(')'), true, ([as, bs = [], cs], rest) => [[(0, dom_1.html)('span', {
5077
5078
  class: 'paren'
5078
- }, (0, dom_1.defrag)((0, array_1.push)((0, array_1.unshift)(as, bs), cs)))], rest], ([as, bs = []], rest) => [(0, array_1.unshift)(as, bs), rest]), (0, combinator_1.surround)((0, source_1.str)('['), (0, combinator_1.recursion)(5 /* Recursion.bracket */, (0, combinator_1.precedence)(1, (0, combinator_1.some)(inline_1.inline, ']', [[']', 1]]))), (0, source_1.str)(']'), true, undefined, ([as, bs = []], rest) => [(0, array_1.unshift)(as, bs), rest], 3 | 4 /* Backtrack.bracket */), (0, combinator_1.surround)((0, source_1.str)('['), (0, combinator_1.recursion)(5 /* Recursion.bracket */, (0, combinator_1.precedence)(1, (0, combinator_1.some)(inline_1.inline, ']', [[']', 1]]))), (0, source_1.str)(']'), true, undefined, ([as, bs = []], rest) => [(0, array_1.unshift)(as, bs), rest]), (0, combinator_1.surround)((0, source_1.str)('{'), (0, combinator_1.recursion)(5 /* Recursion.bracket */, (0, combinator_1.precedence)(1, (0, combinator_1.some)(inline_1.inline, '}', [['}', 1]]))), (0, source_1.str)('}'), true, undefined, ([as, bs = []], rest) => [(0, array_1.unshift)(as, bs), rest], 3 | 4 /* Backtrack.bracket */), (0, combinator_1.surround)((0, source_1.str)('{'), (0, combinator_1.recursion)(5 /* Recursion.bracket */, (0, combinator_1.precedence)(1, (0, combinator_1.some)(inline_1.inline, '}', [['}', 1]]))), (0, source_1.str)('}'), true, undefined, ([as, bs = []], rest) => [(0, array_1.unshift)(as, bs), rest]),
5079
+ }, (0, dom_1.defrag)((0, array_1.push)((0, array_1.unshift)(as, bs), cs)))], rest], ([as, bs = []], rest) => [(0, array_1.unshift)(as, bs), rest]), (0, combinator_1.surround)((0, source_1.str)('['), (0, combinator_1.recursion)(5 /* Recursion.bracket */, (0, combinator_1.precedence)(1, (0, combinator_1.some)(inline_1.inline, ']', [[']', 1]]))), (0, source_1.str)(']'), true, undefined, ([as, bs = []], rest) => [(0, array_1.unshift)(as, bs), rest], [3 | 8 /* Backtrack.bracket */]), (0, combinator_1.surround)((0, source_1.str)('['), (0, combinator_1.recursion)(5 /* Recursion.bracket */, (0, combinator_1.precedence)(1, (0, combinator_1.some)(inline_1.inline, ']', [[']', 1]]))), (0, source_1.str)(']'), true, undefined, ([as, bs = []], rest) => [(0, array_1.unshift)(as, bs), rest]), (0, combinator_1.surround)((0, source_1.str)('{'), (0, combinator_1.recursion)(5 /* Recursion.bracket */, (0, combinator_1.precedence)(1, (0, combinator_1.some)(inline_1.inline, '}', [['}', 1]]))), (0, source_1.str)('}'), true, undefined, ([as, bs = []], rest) => [(0, array_1.unshift)(as, bs), rest], [3 | 8 /* Backtrack.bracket */]), (0, combinator_1.surround)((0, source_1.str)('{'), (0, combinator_1.recursion)(5 /* Recursion.bracket */, (0, combinator_1.precedence)(1, (0, combinator_1.some)(inline_1.inline, '}', [['}', 1]]))), (0, source_1.str)('}'), true, undefined, ([as, bs = []], rest) => [(0, array_1.unshift)(as, bs), rest]),
5079
5080
  // 改行禁止はバックトラックなしでは内側の構文を破壊するため安易に行えない。
5080
5081
  (0, combinator_1.surround)((0, source_1.str)('"'), (0, combinator_1.recursion)(5 /* Recursion.bracket */, (0, combinator_1.precedence)(2, (0, combinator_1.some)(inline_1.inline, '"', [['\n', 9], ['"', 2]]))), (0, source_1.str)('"'), true, undefined, ([as, bs = []], rest) => [(0, array_1.unshift)(as, bs), rest]), (0, combinator_1.surround)((0, source_1.str)('“'), (0, combinator_1.recursion)(5 /* Recursion.bracket */, (0, combinator_1.precedence)(2, (0, combinator_1.some)(inline_1.inline, '”', [['\n', 9], ['”', 2]]))), (0, source_1.str)('”'), true, undefined, ([as, bs = []], rest) => [(0, array_1.unshift)(as, bs), rest]), (0, combinator_1.surround)((0, source_1.str)('‘'), (0, combinator_1.recursion)(5 /* Recursion.bracket */, (0, combinator_1.precedence)(2, (0, combinator_1.some)(inline_1.inline, '’', [['\n', 9], ['’', 2]]))), (0, source_1.str)('’'), true, undefined, ([as, bs = []], rest) => [(0, array_1.unshift)(as, bs), rest]), (0, combinator_1.surround)((0, source_1.str)('「'), (0, combinator_1.recursion)(5 /* Recursion.bracket */, (0, combinator_1.precedence)(2, (0, combinator_1.some)(inline_1.inline, '」', [['\n', 9], ['」', 2]]))), (0, source_1.str)('」'), true, undefined, ([as, bs = []], rest) => [(0, array_1.unshift)(as, bs), rest]), (0, combinator_1.surround)((0, source_1.str)('『'), (0, combinator_1.recursion)(5 /* Recursion.bracket */, (0, combinator_1.precedence)(2, (0, combinator_1.some)(inline_1.inline, '』', [['\n', 9], ['』', 2]]))), (0, source_1.str)('』'), true, undefined, ([as, bs = []], rest) => [(0, array_1.unshift)(as, bs), rest])]));
5081
5082
 
@@ -5156,19 +5157,22 @@ const inline_1 = __webpack_require__(7973);
5156
5157
  const indexee_1 = __webpack_require__(7610);
5157
5158
  const source_1 = __webpack_require__(8745);
5158
5159
  const visibility_1 = __webpack_require__(6364);
5160
+ const array_1 = __webpack_require__(6876);
5159
5161
  const dom_1 = __webpack_require__(394);
5160
5162
  exports.index = (0, combinator_1.lazy)(() => (0, combinator_1.constraint)(32 /* State.index */, false, (0, combinator_1.fmap)((0, indexee_1.indexee)((0, combinator_1.surround)('[#', (0, combinator_1.precedence)(1, (0, combinator_1.state)(251 /* State.linkers */ | 4 /* State.media */, (0, visibility_1.tightStart)((0, combinator_1.some)((0, combinator_1.inits)([inline_1.inline, exports.signature]), ']', [['\n', 9], [']', 1]])))), ']', false, ([, ns], rest) => (0, visibility_1.trimBlankNodeEnd)(ns).length > 0 ? [[(0, dom_1.html)('a', {
5161
5163
  'data-index': dataindex(ns)
5162
- }, (0, dom_1.defrag)(ns))], rest] : undefined, undefined, 1 | 8 /* Backtrack.linebracket */, 4 /* Backtrack.bracket */ | 1 /* BacktrackState.nobreak */)), ([el]) => [(0, dom_1.define)(el, {
5164
+ }, (0, dom_1.defrag)(ns))], rest] : undefined, undefined, [3 | 12 /* Backtrack.linebracket */], 8 /* Backtrack.bracket */ | 1 /* BacktrackState.nobreak */)), ([el]) => [(0, dom_1.define)(el, {
5163
5165
  id: el.id ? null : undefined,
5164
5166
  class: 'index',
5165
5167
  href: el.id ? `#${el.id}` : undefined
5166
5168
  })])));
5167
- exports.signature = (0, combinator_1.lazy)(() => (0, combinator_1.validate)('|', (0, combinator_1.fmap)((0, combinator_1.open)(/^\|(?!\\?\s)/, (0, combinator_1.some)((0, combinator_1.verify)((0, combinator_1.union)([bracket, source_1.txt]), ns => ns[0] !== "\u001B" /* Command.Escape */), ']')), ns => [(0, dom_1.html)('span', {
5168
- class: 'indexer',
5169
- 'data-index': (0, indexee_1.identity)('index', undefined, ns.join('')).slice(7)
5170
- })])));
5171
- const bracket = (0, combinator_1.lazy)(() => (0, combinator_1.union)([(0, combinator_1.surround)((0, source_1.str)('('), (0, combinator_1.recursion)(6 /* Recursion.terminal */, (0, combinator_1.some)((0, combinator_1.union)([bracket, source_1.txt]), ')')), (0, source_1.str)(')'), true, undefined, () => [["\u001B" /* Command.Escape */], ''], 3 | 24 /* Backtrack.index */), (0, combinator_1.surround)((0, source_1.str)('['), (0, combinator_1.recursion)(6 /* Recursion.terminal */, (0, combinator_1.some)((0, combinator_1.union)([bracket, source_1.txt]), ']')), (0, source_1.str)(']'), true, undefined, () => [["\u001B" /* Command.Escape */], ''], 3 | 24 /* Backtrack.index */), (0, combinator_1.surround)((0, source_1.str)('{'), (0, combinator_1.recursion)(6 /* Recursion.terminal */, (0, combinator_1.some)((0, combinator_1.union)([bracket, source_1.txt]), '}')), (0, source_1.str)('}'), true, undefined, () => [["\u001B" /* Command.Escape */], ''], 3 | 24 /* Backtrack.index */), (0, combinator_1.surround)((0, source_1.str)('"'), (0, combinator_1.precedence)(2, (0, combinator_1.recursion)(6 /* Recursion.terminal */, (0, combinator_1.some)(source_1.txt, '"'))), (0, source_1.str)('"'), true, undefined, () => [["\u001B" /* Command.Escape */], ''], 3 | 24 /* Backtrack.index */)]));
5169
+ exports.signature = (0, combinator_1.lazy)(() => (0, combinator_1.validate)('|', (0, combinator_1.surround)((0, source_1.str)(/^\|(?!\\?\s)/), (0, combinator_1.some)((0, combinator_1.union)([inline_1.inline]), ']'), /^(?=])/, false, ([as, bs], rest) => {
5170
+ const index = (0, indexee_1.identity)('index', undefined, (0, indexee_1.text)((0, dom_1.frag)(bs)))?.slice(7);
5171
+ return index ? [[(0, dom_1.html)('span', {
5172
+ class: 'indexer',
5173
+ 'data-index': index
5174
+ })], rest] : [(0, array_1.unshift)(as, bs), rest];
5175
+ }, ([as, bs], rest) => [(0, array_1.unshift)(as, bs), rest])));
5172
5176
  function dataindex(ns) {
5173
5177
  if (ns.length === 0) return;
5174
5178
  for (let i = ns.length - 1; i >= 0; --i) {
@@ -5280,10 +5284,7 @@ const parser_1 = __webpack_require__(605);
5280
5284
  const combinator_1 = __webpack_require__(3484);
5281
5285
  const dom_1 = __webpack_require__(394);
5282
5286
  function lineable(parser) {
5283
- return (0, combinator_1.convert)((source, context) => {
5284
- (0, combinator_1.consume)(-1, context);
5285
- return `\r${source}`;
5286
- }, parser);
5287
+ return (0, combinator_1.convert)(source => `\r${source}`, parser);
5287
5288
  }
5288
5289
  exports.lineable = lineable;
5289
5290
  function repeat(symbol, parser, cons, termination = (acc, rest, prefix, postfix) => {
@@ -5565,6 +5566,7 @@ const text = ({
5565
5566
  (0, combinator_1.consume)(1, context);
5566
5567
  switch (source[0]) {
5567
5568
  case '\r':
5569
+ (0, combinator_1.consume)(-1, context);
5568
5570
  return [[], source.slice(1)];
5569
5571
  case "\u001B" /* Command.Escape */:
5570
5572
  case '\\':
@@ -5945,7 +5947,7 @@ exports.clear = exports.close = exports.open = exports.surround = void 0;
5945
5947
  const parser_1 = __webpack_require__(605);
5946
5948
  const fmap_1 = __webpack_require__(2705);
5947
5949
  const array_1 = __webpack_require__(6876);
5948
- function surround(opener, parser, closer, optional = false, f, g, backtrack = 0, bstate = 0) {
5950
+ function surround(opener, parser, closer, optional = false, f, g, backtracks = [], bstate = 0) {
5949
5951
  switch (typeof opener) {
5950
5952
  case 'string':
5951
5953
  case 'object':
@@ -5969,19 +5971,21 @@ function surround(opener, parser, closer, optional = false, f, g, backtrack = 0,
5969
5971
  if (res1 === undefined) return;
5970
5972
  const rl = (0, parser_1.eval)(res1);
5971
5973
  const mr_ = (0, parser_1.exec)(res1);
5972
- if (backtrack & 1) {
5973
- const {
5974
- backtracks = {},
5975
- backtrack: state = 0,
5976
- offset = 0
5977
- } = context;
5978
- for (let i = 0; i < source.length - mr_.length; ++i) {
5979
- if (source[i] !== source[0]) break;
5980
- const pos = source.length + offset - i - 1;
5981
- if (!(pos in backtracks)) continue;
5982
- // bracket only
5983
- const shift = backtrack >>> 2 === state >>> 2 ? state & 3 : 0;
5984
- if (backtracks[pos] & 1 << (backtrack >>> 2) + shift) return;
5974
+ for (const backtrack of backtracks) {
5975
+ if (backtrack & 1) {
5976
+ const {
5977
+ backtracks = {},
5978
+ backtrack: state = 0,
5979
+ offset = 0
5980
+ } = context;
5981
+ for (let i = 0; i < source.length - mr_.length; ++i) {
5982
+ if (source[i] !== source[0]) break;
5983
+ const pos = source.length + offset - i - 1;
5984
+ if (!(pos in backtracks)) continue;
5985
+ // bracket only
5986
+ const shift = backtrack >>> 2 === state >>> 2 ? state & 3 : 0;
5987
+ if (backtracks[pos] & 1 << (backtrack >>> 2) + shift) return;
5988
+ }
5985
5989
  }
5986
5990
  }
5987
5991
  const {
@@ -6003,15 +6007,17 @@ function surround(opener, parser, closer, optional = false, f, g, backtrack = 0,
6003
6007
  const rr = (0, parser_1.eval)(res3);
6004
6008
  const rest = (0, parser_1.exec)(res3, r_);
6005
6009
  if (rest.length === lmr_.length) return;
6006
- if (backtrack & 2 && rr === undefined) {
6007
- const {
6008
- backtracks = {},
6009
- backtrack: state = 0,
6010
- offset = 0
6011
- } = context;
6012
- // bracket only
6013
- const shift = backtrack >>> 2 === state >>> 2 ? state & 3 : 0;
6014
- backtracks[source.length + offset - 1] |= 1 << (backtrack >>> 2) + shift;
6010
+ for (const backtrack of backtracks) {
6011
+ if (backtrack & 2 && rr === undefined) {
6012
+ const {
6013
+ backtracks = {},
6014
+ backtrack: state = 0,
6015
+ offset = 0
6016
+ } = context;
6017
+ // bracket only
6018
+ const shift = backtrack >>> 2 === state >>> 2 ? state & 3 : 0;
6019
+ backtracks[source.length + offset - 1] |= 1 << (backtrack >>> 2) + shift;
6020
+ }
6015
6021
  }
6016
6022
  return rr ? f ? f([rl, rm, rr], rest, context) : [(0, array_1.push)((0, array_1.unshift)(rl, rm ?? []), rr), rest] : g ? g([rl, rm, mr_], rest, context) : undefined;
6017
6023
  };
@@ -6214,7 +6220,7 @@ exports.placeholder = (0, combinator_1.lazy)(() => (0, combinator_1.surround)((0
6214
6220
  'data-invalid-syntax': 'extension',
6215
6221
  'data-invalid-type': 'syntax',
6216
6222
  'data-invalid-message': `Invalid start symbol or linebreak`
6217
- }, (0, dom_1.defrag)(bs))], rest], ([as, bs], rest) => [(0, array_1.unshift)(as, bs), rest], 3 | 4 /* Backtrack.bracket */));
6223
+ }, (0, dom_1.defrag)(bs))], rest], ([as, bs], rest) => [(0, array_1.unshift)(as, bs), rest], [3 | 8 /* Backtrack.bracket */]));
6218
6224
 
6219
6225
  /***/ },
6220
6226
 
@@ -7158,13 +7164,13 @@ exports.ruby = (0, combinator_1.lazy)(() => (0, combinator_1.fmap)((0, combinato
7158
7164
  }), [undefined])[0];
7159
7165
  ns && ns.at(-1) === '' && ns.pop();
7160
7166
  return ns && (0, visibility_1.isTightNodeStart)(ns) ? [ns, rest] : undefined;
7161
- }, undefined, 3 | 16 /* Backtrack.ruby */)), (0, combinator_1.dup)((0, combinator_1.surround)('(', (0, source_1.str)(/^(?:\\[^\n]|[^\\[\](){}<>"\n])+/u), ')', false, ([, [source]], rest, context) => {
7167
+ }, undefined, [3 | 20 /* Backtrack.ruby */])), (0, combinator_1.dup)((0, combinator_1.surround)('(', (0, source_1.str)(/^(?:\\[^\n]|[^\\[\](){}<>"\n])+/u), ')', false, ([, [source]], rest, context) => {
7162
7168
  const ns = (0, parser_1.eval)(text({
7163
7169
  source,
7164
7170
  context
7165
7171
  }), [undefined])[0];
7166
7172
  return ns && [ns, rest];
7167
- }, undefined, 3 | 16 /* Backtrack.ruby */))]), ([texts, rubies]) => {
7173
+ }, undefined, [3 | 20 /* Backtrack.ruby */]))]), ([texts, rubies]) => {
7168
7174
  switch (true) {
7169
7175
  case rubies.length <= texts.length:
7170
7176
  return [(0, dom_1.html)('ruby', attributes(texts, rubies), (0, dom_1.defrag)(texts.reduce((acc, _, i) => (0, array_1.push)(acc, (0, array_1.unshift)([texts[i]], i < rubies.length && rubies[i] ? [(0, dom_1.html)('rp', '('), (0, dom_1.html)('rt', rubies[i]), (0, dom_1.html)('rp', ')')] : [(0, dom_1.html)('rt')])), [])))];
@@ -7312,7 +7318,7 @@ const optspec = {
7312
7318
  rel: undefined
7313
7319
  };
7314
7320
  Object.setPrototypeOf(optspec, null);
7315
- exports.media = (0, combinator_1.lazy)(() => (0, combinator_1.constraint)(4 /* State.media */, false, (0, combinator_1.validate)(['![', '!{'], (0, combinator_1.creation)(10, (0, combinator_1.open)('!', (0, combinator_1.bind)((0, combinator_1.verify)((0, combinator_1.fmap)((0, combinator_1.tails)([(0, combinator_1.dup)((0, combinator_1.surround)('[', (0, combinator_1.precedence)(1, (0, combinator_1.some)((0, combinator_1.verify)((0, combinator_1.union)([htmlentity_1.unsafehtmlentity, bracket, source_1.txt]), ns => ns[0] !== "\u001B" /* Command.Escape */), ']', [['\n', 9]])), ']', true, undefined, undefined, 1 | 12 /* Backtrack.media */)), (0, combinator_1.dup)((0, combinator_1.surround)(/^{(?![{}])/, (0, combinator_1.inits)([link_1.uri, (0, combinator_1.some)(option)]), /^[^\S\n]*}/, false, undefined, undefined, 3 | 20 /* Backtrack.link */))]), ([as, bs]) => bs ? [[as.join('').trim() || as.join('')], bs] : [[''], as]), ([[text]]) => text === '' || text.trim() !== ''), ([[text], params], rest, context) => {
7321
+ exports.media = (0, combinator_1.lazy)(() => (0, combinator_1.constraint)(4 /* State.media */, false, (0, combinator_1.validate)(['![', '!{'], (0, combinator_1.creation)(10, (0, combinator_1.open)('!', (0, combinator_1.bind)((0, combinator_1.verify)((0, combinator_1.fmap)((0, combinator_1.tails)([(0, combinator_1.dup)((0, combinator_1.surround)('[', (0, combinator_1.precedence)(1, (0, combinator_1.some)((0, combinator_1.verify)((0, combinator_1.union)([htmlentity_1.unsafehtmlentity, bracket, source_1.txt]), ns => ns[0] !== "\u001B" /* Command.Escape */), ']', [['\n', 9]])), ']', true, undefined, undefined, [3 | 4 /* Backtrack.lineescbracket */])), (0, combinator_1.dup)((0, combinator_1.surround)(/^{(?![{}])/, (0, combinator_1.inits)([link_1.uri, (0, combinator_1.some)(option)]), /^[^\S\n]*}/, false, undefined, undefined, [3 | 24 /* Backtrack.link */]))]), ([as, bs]) => bs ? [[as.join('').trim() || as.join('')], bs] : [[''], as]), ([[text]]) => text === '' || text.trim() !== ''), ([[text], params], rest, context) => {
7316
7322
  const INSECURE_URI = params.shift();
7317
7323
  const url = new url_1.ReadonlyURL((0, link_1.resolve)(INSECURE_URI, context.host ?? location, context.url ?? context.host ?? location), context.host?.href || location.href);
7318
7324
  let cache;
@@ -7339,7 +7345,7 @@ exports.media = (0, combinator_1.lazy)(() => (0, combinator_1.constraint)(4 /* S
7339
7345
  });
7340
7346
  }))))));
7341
7347
  exports.linemedia = (0, combinator_1.surround)(source_1.linebreak, (0, combinator_1.union)([exports.media]), /^(?=[^\S\n]*(?:$|\n))/);
7342
- const bracket = (0, combinator_1.lazy)(() => (0, combinator_1.recursion)(6 /* Recursion.terminal */, (0, combinator_1.union)([(0, combinator_1.surround)((0, source_1.str)('('), (0, combinator_1.some)((0, combinator_1.union)([htmlentity_1.unsafehtmlentity, bracket, source_1.txt]), ')'), (0, source_1.str)(')'), true, undefined, () => [["\u001B" /* Command.Escape */], ''], 3 | 12 /* Backtrack.media */), (0, combinator_1.surround)((0, source_1.str)('['), (0, combinator_1.some)((0, combinator_1.union)([htmlentity_1.unsafehtmlentity, bracket, source_1.txt]), ']'), (0, source_1.str)(']'), true, undefined, () => [["\u001B" /* Command.Escape */], ''], 3 | 12 /* Backtrack.media */), (0, combinator_1.surround)((0, source_1.str)('{'), (0, combinator_1.some)((0, combinator_1.union)([htmlentity_1.unsafehtmlentity, bracket, source_1.txt]), '}'), (0, source_1.str)('}'), true, undefined, () => [["\u001B" /* Command.Escape */], ''], 3 | 12 /* Backtrack.media */), (0, combinator_1.surround)((0, source_1.str)('"'), (0, combinator_1.precedence)(2, (0, combinator_1.some)((0, combinator_1.union)([htmlentity_1.unsafehtmlentity, source_1.txt]), '"')), (0, source_1.str)('"'), true, undefined, () => [["\u001B" /* Command.Escape */], ''], 3 | 12 /* Backtrack.media */)])));
7348
+ const bracket = (0, combinator_1.lazy)(() => (0, combinator_1.recursion)(6 /* Recursion.terminal */, (0, combinator_1.union)([(0, combinator_1.surround)((0, source_1.str)('('), (0, combinator_1.some)((0, combinator_1.union)([htmlentity_1.unsafehtmlentity, bracket, source_1.txt]), ')'), (0, source_1.str)(')'), true, undefined, () => [["\u001B" /* Command.Escape */], ''], [3 | 4 /* Backtrack.lineescbracket */]), (0, combinator_1.surround)((0, source_1.str)('['), (0, combinator_1.some)((0, combinator_1.union)([htmlentity_1.unsafehtmlentity, bracket, source_1.txt]), ']'), (0, source_1.str)(']'), true, undefined, () => [["\u001B" /* Command.Escape */], ''], [3 | 4 /* Backtrack.lineescbracket */]), (0, combinator_1.surround)((0, source_1.str)('{'), (0, combinator_1.some)((0, combinator_1.union)([htmlentity_1.unsafehtmlentity, bracket, source_1.txt]), '}'), (0, source_1.str)('}'), true, undefined, () => [["\u001B" /* Command.Escape */], ''], [3 | 4 /* Backtrack.lineescbracket */]), (0, combinator_1.surround)((0, source_1.str)('"'), (0, combinator_1.precedence)(2, (0, combinator_1.some)((0, combinator_1.union)([htmlentity_1.unsafehtmlentity, source_1.txt]), '"')), (0, source_1.str)('"'), true, undefined, () => [["\u001B" /* Command.Escape */], ''], [3 | 4 /* Backtrack.lineescbracket */])])));
7343
7349
  const option = (0, combinator_1.lazy)(() => (0, combinator_1.union)([(0, combinator_1.fmap)((0, source_1.str)(/^[^\S\n]+[1-9][0-9]*x[1-9][0-9]*(?=[^\S\n]|})/), ([opt]) => [` width="${opt.slice(1).split('x')[0]}"`, ` height="${opt.slice(1).split('x')[1]}"`]), (0, combinator_1.fmap)((0, source_1.str)(/^[^\S\n]+[1-9][0-9]*:[1-9][0-9]*(?=[^\S\n]|})/), ([opt]) => [` aspect-ratio="${opt.slice(1).split(':').join('/')}"`]), link_1.option]));
7344
7350
  function sanitize(target, uri, alt) {
7345
7351
  switch (uri.protocol) {
@@ -8333,6 +8339,7 @@ const unescsource = ({
8333
8339
  (0, combinator_1.consume)(1, context);
8334
8340
  switch (source[0]) {
8335
8341
  case '\r':
8342
+ (0, combinator_1.consume)(-1, context);
8336
8343
  return [[], source.slice(1)];
8337
8344
  case "\u001B" /* Command.Escape */:
8338
8345
  (0, combinator_1.consume)(1, context);
@@ -8907,7 +8914,7 @@ const dom_1 = __webpack_require__(394);
8907
8914
  const array_1 = __webpack_require__(6876);
8908
8915
  exports.reference = (0, combinator_1.lazy)(() => (0, combinator_1.constraint)(64 /* State.reference */, false, (0, combinator_1.surround)('[[', (0, combinator_1.precedence)(1, (0, combinator_1.state)(128 /* State.annotation */ | 64 /* State.reference */ | 4 /* State.media */, (0, combinator_1.subsequence)([abbr, (0, visibility_1.trimBlankStart)((0, combinator_1.some)(inline_1.inline, ']', [['\n', 9], [']', 1]]))]))), ']]', false, ([, ns], rest) => (0, visibility_1.trimBlankNodeEnd)(ns).length > 0 ? [[(0, dom_1.html)('sup', attributes(ns), [(0, dom_1.html)('span', (0, dom_1.defrag)(ns))])], rest] : undefined, ([as, bs], rest, {
8909
8916
  state = 0
8910
- }) => state & 128 /* State.annotation */ ? [(0, array_1.unshift)(as, bs), rest] : undefined, 1 | 8 /* Backtrack.linebracket */, 4 /* Backtrack.bracket */ | 1 /* BacktrackState.nobreak */)));
8917
+ }) => state & 128 /* State.annotation */ ? [(0, array_1.unshift)(as, bs), rest] : undefined, [3 | 16 /* Backtrack.linedoublebracket */, 1 | 12 /* Backtrack.linebracket */], 8 /* Backtrack.bracket */ | 1 /* BacktrackState.nobreak */)));
8911
8918
  // Chicago-Style
8912
8919
  const abbr = (0, combinator_1.surround)('^', (0, combinator_1.union)([(0, source_1.str)(/^(?=[A-Z])(?:[0-9A-Za-z]'?|(?:[-.:]|\.?\??,? ?)(?!['\-.:?, ]))+/)]), /^\|?(?=]])|^\|[^\S\n]*/, true, ([, ns], rest) => ns ? [['\n', ns[0].trimEnd()], rest.replace(visibility_1.blank.start, '')] : [[''], `^${rest}`], ([,, rest]) => [[''], `^${rest}`]);
8913
8920
  function attributes(ns) {
package/markdown.d.ts CHANGED
@@ -754,9 +754,8 @@ export namespace MarkdownParser {
754
754
  export namespace IndexParser {
755
755
  export interface SignatureParser extends
756
756
  Inline<'extension/index/signature'>,
757
- Parser<HTMLElement, Context, [
758
- SignatureParser.BracketParser,
759
- SourceParser.TxtParser,
757
+ Parser<string | HTMLElement, Context, [
758
+ InlineParser,
760
759
  ]> {
761
760
  }
762
761
  export namespace SignatureParser {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "securemark",
3
- "version": "0.286.3",
3
+ "version": "0.287.0",
4
4
  "description": "Secure markdown renderer working on browsers for user input data.",
5
5
  "private": false,
6
6
  "homepage": "https://github.com/falsandtru/securemark",
@@ -7,7 +7,7 @@ export function surround<P extends Parser<unknown>, S = string>(
7
7
  optional?: false,
8
8
  f?: (rss: [S[], SubTree<P>[], S[]], rest: string, context: Context<P>) => Result<Tree<P>, Context<P>, SubParsers<P>>,
9
9
  g?: (rss: [S[], SubTree<P>[], string], rest: string, context: Context<P>) => Result<Tree<P>, Context<P>, SubParsers<P>>,
10
- backtrack?: number,
10
+ backtracks?: readonly number[],
11
11
  bstate?: number,
12
12
  ): P;
13
13
  export function surround<P extends Parser<unknown>, S = string>(
@@ -15,7 +15,7 @@ export function surround<P extends Parser<unknown>, S = string>(
15
15
  optional?: boolean,
16
16
  f?: (rss: [S[], SubTree<P>[] | undefined, S[]], rest: string, context: Context<P>) => Result<Tree<P>, Context<P>, SubParsers<P>>,
17
17
  g?: (rss: [S[], SubTree<P>[] | undefined, string], rest: string, context: Context<P>) => Result<Tree<P>, Context<P>, SubParsers<P>>,
18
- backtrack?: number,
18
+ backtracks?: readonly number[],
19
19
  bstate?: number,
20
20
  ): P;
21
21
  export function surround<P extends Parser<unknown>, S = string>(
@@ -23,7 +23,7 @@ export function surround<P extends Parser<unknown>, S = string>(
23
23
  optional?: false,
24
24
  f?: (rss: [S[], Tree<P>[], S[]], rest: string, context: Context<P>) => Result<Tree<P>, Context<P>, SubParsers<P>>,
25
25
  g?: (rss: [S[], Tree<P>[], string], rest: string, context: Context<P>) => Result<Tree<P>, Context<P>, SubParsers<P>>,
26
- backtrack?: number,
26
+ backtracks?: readonly number[],
27
27
  bstate?: number,
28
28
  ): P;
29
29
  export function surround<P extends Parser<unknown>, S = string>(
@@ -31,7 +31,7 @@ export function surround<P extends Parser<unknown>, S = string>(
31
31
  optional?: boolean,
32
32
  f?: (rss: [S[], Tree<P>[] | undefined, S[]], rest: string, context: Context<P>) => Result<Tree<P>, Context<P>, SubParsers<P>>,
33
33
  g?: (rss: [S[], Tree<P>[] | undefined, string], rest: string, context: Context<P>) => Result<Tree<P>, Context<P>, SubParsers<P>>,
34
- backtrack?: number,
34
+ backtracks?: readonly number[],
35
35
  bstate?: number,
36
36
  ): P;
37
37
  export function surround<T>(
@@ -39,7 +39,7 @@ export function surround<T>(
39
39
  optional: boolean = false,
40
40
  f?: (rss: [T[], T[], T[]], rest: string, context: Ctx) => Result<T>,
41
41
  g?: (rss: [T[], T[], string], rest: string, context: Ctx) => Result<T>,
42
- backtrack: number = 0,
42
+ backtracks: readonly number[] = [],
43
43
  bstate: number = 0,
44
44
  ): Parser<T> {
45
45
  switch (typeof opener) {
@@ -60,15 +60,17 @@ export function surround<T>(
60
60
  if (res1 === undefined) return;
61
61
  const rl = eval(res1);
62
62
  const mr_ = exec(res1);
63
- if (backtrack & 1) {
64
- const { backtracks = {}, backtrack: state = 0, offset = 0 } = context;
65
- for (let i = 0; i < source.length - mr_.length; ++i) {
66
- if (source[i] !== source[0]) break;
67
- const pos = source.length + offset - i - 1;
68
- if (!(pos in backtracks)) continue;
69
- // bracket only
70
- const shift = backtrack >>> 2 === state >>> 2 ? state & 3 : 0;
71
- if (backtracks[pos] & 1 << (backtrack >>> 2) + shift) return;
63
+ for (const backtrack of backtracks) {
64
+ if (backtrack & 1) {
65
+ const { backtracks = {}, backtrack: state = 0, offset = 0 } = context;
66
+ for (let i = 0; i < source.length - mr_.length; ++i) {
67
+ if (source[i] !== source[0]) break;
68
+ const pos = source.length + offset - i - 1;
69
+ if (!(pos in backtracks)) continue;
70
+ // bracket only
71
+ const shift = backtrack >>> 2 === state >>> 2 ? state & 3 : 0;
72
+ if (backtracks[pos] & 1 << (backtrack >>> 2) + shift) return;
73
+ }
72
74
  }
73
75
  }
74
76
  const { backtrack: state = 0 } = context;
@@ -84,11 +86,13 @@ export function surround<T>(
84
86
  const rr = eval(res3);
85
87
  const rest = exec(res3, r_);
86
88
  if (rest.length === lmr_.length) return;
87
- if (backtrack & 2 && rr === undefined) {
88
- const { backtracks = {}, backtrack: state = 0, offset = 0 } = context;
89
- // bracket only
90
- const shift = backtrack >>> 2 === state >>> 2 ? state & 3 : 0;
91
- backtracks[source.length + offset - 1] |= 1 << (backtrack >>> 2) + shift;
89
+ for (const backtrack of backtracks) {
90
+ if (backtrack & 2 && rr === undefined) {
91
+ const { backtracks = {}, backtrack: state = 0, offset = 0 } = context;
92
+ // bracket only
93
+ const shift = backtrack >>> 2 === state >>> 2 ? state & 3 : 0;
94
+ backtracks[source.length + offset - 1] |= 1 << (backtrack >>> 2) + shift;
95
+ }
92
96
  }
93
97
  return rr
94
98
  ? f
@@ -350,7 +350,7 @@ describe('Unit: parser/api/parse', () => {
350
350
 
351
351
  it('backtrack', function () {
352
352
  this.timeout(5000);
353
- const str = `${'.'.repeat(9)}((${'['.repeat(13)}{{http://[[[${'.'.repeat(7134)}`;
353
+ const str = `${'.'.repeat(0 + 0)}((${'['.repeat(13)}{{http://[[[${'.'.repeat(8326)}`;
354
354
  assert.deepStrictEqual(
355
355
  [...parse(str).children].map(el => el.outerHTML.replace(/:\w+/, ':rnd')),
356
356
  [`<p>${str}</p>`]);
@@ -358,7 +358,7 @@ describe('Unit: parser/api/parse', () => {
358
358
 
359
359
  it('backtrack error', function () {
360
360
  this.timeout(5000);
361
- const str = `${'.'.repeat(9)}((${'['.repeat(13)}{{http://[[[${'.'.repeat(7134 + 1)}`;
361
+ const str = `${'.'.repeat(0 + 1)}((${'['.repeat(13)}{{http://[[[${'.'.repeat(8326)}`;
362
362
  assert.deepStrictEqual(
363
363
  [...parse(str).children].map(el => el.outerHTML.replace(/:\w+/, ':rnd')),
364
364
  [
@@ -69,7 +69,7 @@ describe('Unit: parser/block/heading', () => {
69
69
  assert.deepStrictEqual(inspect(parser('# a [|b ]')), [['<h1 id="index::b">a<span class="indexer" data-index="b"></span></h1>'], '']);
70
70
  assert.deepStrictEqual(inspect(parser('# a [|b ]')), [['<h1 id="index::b">a<span class="indexer" data-index="b"></span></h1>'], '']);
71
71
  assert.deepStrictEqual(inspect(parser('# a [|b c]')), [['<h1 id="index::b_c">a<span class="indexer" data-index="b_c"></span></h1>'], '']);
72
- assert.deepStrictEqual(inspect(parser('# a [|*b*`c`${d}$]')), [['<h1 id="index::*b*`c`${d}$">a<span class="indexer" data-index="*b*`c`${d}$"></span></h1>'], '']);
72
+ assert.deepStrictEqual(inspect(parser('# a [|*b*`c`${d}$]')), [['<h1 id="index::b`c`${d}$">a<span class="indexer" data-index="b`c`${d}$"></span></h1>'], '']);
73
73
  assert.deepStrictEqual(inspect(parser('# a [|@a]')), [['<h1 id="index::@a">a<span class="indexer" data-index="@a"></span></h1>'], '']);
74
74
  assert.deepStrictEqual(inspect(parser('# a [|http://host]')), [['<h1 id="index::http://host">a<span class="indexer" data-index="http://host"></span></h1>'], '']);
75
75
  assert.deepStrictEqual(inspect(parser('# a [|!http://host]')), [['<h1 id="index::!http://host">a<span class="indexer" data-index="!http://host"></span></h1>'], '']);
@@ -71,10 +71,6 @@ describe('Unit: parser/block/paragraph', () => {
71
71
  assert.deepStrictEqual(inspect(parser('[%\n<wbr>\n%]\na')), [['<p><span class="remark"><input type="checkbox"><span>[%<br>&lt;wbr&gt;<br>%]</span></span><br>a</p>'], '']);
72
72
  });
73
73
 
74
- it('template', () => {
75
- assert.deepStrictEqual(inspect(parser('{{\n\\\n}}')), [['<p><span class="template">{{\n\\\n}}</span></p>'], '']);
76
- });
77
-
78
74
  });
79
75
 
80
76
  });
@@ -29,14 +29,13 @@ export const enum Recursion {
29
29
  }
30
30
 
31
31
  export const enum Backtrack {
32
- template = 7 << 2,
33
- index = 6 << 2,
34
- link = 5 << 2,
35
- ruby = 4 << 2,
36
- media = 3 << 2,
37
- linebracket = 2 << 2,
38
- bracket = 1 << 2,
39
- url = 0 << 2,
32
+ link = 6 << 2,
33
+ ruby = 5 << 2,
34
+ linedoublebracket = 4 << 2,
35
+ linebracket = 3 << 2,
36
+ bracket = 2 << 2,
37
+ lineescbracket = 1 << 2,
38
+ lineunescbracket = 0 << 2,
40
39
  }
41
40
  // バックトラックを削減するため括弧派生構文を改行禁止し
42
41
  // 括弧派生構文内のバックトラック状態を統一する。
@@ -15,4 +15,4 @@ export const annotation: AnnotationParser = lazy(() => constraint(State.annotati
15
15
  trimBlankNodeEnd(ns).length > 0
16
16
  ? [[html('sup', { class: 'annotation' }, [html('span', defrag(ns))])], rest]
17
17
  : undefined,
18
- undefined, 1 | Backtrack.linebracket, Backtrack.bracket | BacktrackState.nobreak)));
18
+ undefined, [3 | Backtrack.linedoublebracket, 1 | Backtrack.linebracket], Backtrack.bracket | BacktrackState.nobreak)));
@@ -36,11 +36,11 @@ export const lineurl: AutolinkParser.UrlParser.LineUrlParser = lazy(() => open(
36
36
 
37
37
  const bracket: AutolinkParser.UrlParser.BracketParser = lazy(() => union([
38
38
  surround(str('('), recursion(Recursion.terminal, some(union([bracket, unescsource]), ')')), str(')'), true,
39
- undefined, () => [[Command.Escape], ''], 3 | Backtrack.url),
39
+ undefined, () => [[Command.Escape], ''], [3 | Backtrack.lineunescbracket]),
40
40
  surround(str('['), recursion(Recursion.terminal, some(union([bracket, unescsource]), ']')), str(']'), true,
41
- undefined, () => [[Command.Escape], ''], 3 | Backtrack.url),
41
+ undefined, () => [[Command.Escape], ''], [3 | Backtrack.lineunescbracket]),
42
42
  surround(str('{'), recursion(Recursion.terminal, some(union([bracket, unescsource]), '}')), str('}'), true,
43
- undefined, () => [[Command.Escape], ''], 3 | Backtrack.url),
43
+ undefined, () => [[Command.Escape], ''], [3 | Backtrack.lineunescbracket]),
44
44
  surround(str('"'), precedence(2, recursion(Recursion.terminal, some(unescsource, '"'))), str('"'), true,
45
- undefined, () => [[Command.Escape], ''], 3 | Backtrack.url),
45
+ undefined, () => [[Command.Escape], ''], [3 | Backtrack.lineunescbracket]),
46
46
  ]));
@@ -50,7 +50,6 @@ describe('Unit: parser/inline/bracket', () => {
50
50
  assert.deepStrictEqual(inspect(parser('(A、B)')), [['(', 'A、B', ')'], '']);
51
51
  assert.deepStrictEqual(inspect(parser('(<bdi>a\\\nb</bdi>)')), [['<span class="paren">(<bdi>a<br>b</bdi>)</span>'], '']);
52
52
  assert.deepStrictEqual(inspect(parser('([% a\\\nb %])')), [['<span class="paren">(<span class="remark"><input type="checkbox"><span>[% a<br>b %]</span></span>)</span>'], '']);
53
- assert.deepStrictEqual(inspect(parser('({{\\\n}})')), [['<span class="paren">(<span class="template">{{\\\n}}</span>)</span>'], '']);
54
53
  });
55
54
 
56
55
  it('[', () => {
@@ -12,24 +12,24 @@ const indexF = new RegExp(indexA.source.replace(', ', '[,、]')
12
12
 
13
13
  export const bracket: BracketParser = lazy(() => union([
14
14
  surround(str('('), recursion(Recursion.bracket, precedence(1, str(indexA))), str(')'), false,
15
- undefined, undefined, 3 | Backtrack.bracket),
15
+ undefined, undefined, [3 | Backtrack.bracket]),
16
16
  surround(str('('), recursion(Recursion.bracket, precedence(1, some(inline, ')', [[')', 1]]))), str(')'), true,
17
17
  ([as, bs = [], cs], rest) => [[html('span', { class: 'paren' }, defrag(push(unshift(as, bs), cs)))], rest],
18
- ([as, bs = []], rest) => [unshift(as, bs), rest], 3 | Backtrack.bracket),
18
+ ([as, bs = []], rest) => [unshift(as, bs), rest], [3 | Backtrack.bracket]),
19
19
  surround(str('('), recursion(Recursion.bracket, precedence(1, str(indexF))), str(')'), false,
20
- undefined, undefined, 3 | Backtrack.bracket),
20
+ undefined, undefined, [3 | Backtrack.bracket]),
21
21
  surround(str('('), recursion(Recursion.bracket, precedence(1, some(inline, ')', [[')', 1]]))), str(')'), true,
22
22
  ([as, bs = [], cs], rest) => [[html('span', { class: 'paren' }, defrag(push(unshift(as, bs), cs)))], rest],
23
23
  ([as, bs = []], rest) => [unshift(as, bs), rest]),
24
24
  surround(str('['), recursion(Recursion.bracket, precedence(1, some(inline, ']', [[']', 1]]))), str(']'), true,
25
25
  undefined,
26
- ([as, bs = []], rest) => [unshift(as, bs), rest], 3 | Backtrack.bracket),
26
+ ([as, bs = []], rest) => [unshift(as, bs), rest], [3 | Backtrack.bracket]),
27
27
  surround(str('['), recursion(Recursion.bracket, precedence(1, some(inline, ']', [[']', 1]]))), str(']'), true,
28
28
  undefined,
29
29
  ([as, bs = []], rest) => [unshift(as, bs), rest]),
30
30
  surround(str('{'), recursion(Recursion.bracket, precedence(1, some(inline, '}', [['}', 1]]))), str('}'), true,
31
31
  undefined,
32
- ([as, bs = []], rest) => [unshift(as, bs), rest], 3 | Backtrack.bracket),
32
+ ([as, bs = []], rest) => [unshift(as, bs), rest], [3 | Backtrack.bracket]),
33
33
  surround(str('{'), recursion(Recursion.bracket, precedence(1, some(inline, '}', [['}', 1]]))), str('}'), true,
34
34
  undefined,
35
35
  ([as, bs = []], rest) => [unshift(as, bs), rest]),
@@ -84,13 +84,16 @@ describe('Unit: parser/inline/extension/index', () => {
84
84
  assert.deepStrictEqual(inspect(parser('[#a|b ]')), [['<a class="index" href="#index::b">a<span class="indexer" data-index="b"></span></a>'], '']);
85
85
  assert.deepStrictEqual(inspect(parser('[#a|b ]')), [['<a class="index" href="#index::b">a<span class="indexer" data-index="b"></span></a>'], '']);
86
86
  assert.deepStrictEqual(inspect(parser('[#a|\\b]')), [['<a class="index" href="#index::b">a<span class="indexer" data-index="b"></span></a>'], '']);
87
- assert.deepStrictEqual(inspect(parser('[#a|*b*]')), [['<a class="index" href="#index::*b*">a<span class="indexer" data-index="*b*"></span></a>'], '']);
87
+ assert.deepStrictEqual(inspect(parser('[#a|*b*]')), [['<a class="index" href="#index::b">a<span class="indexer" data-index="b"></span></a>'], '']);
88
+ assert.deepStrictEqual(inspect(parser('[#a|*]*]')), [['<a class="index" href="#index::*">a<span class="indexer" data-index="*"></span></a>'], '*]']);
88
89
  assert.deepStrictEqual(inspect(parser('[#a|b c]')), [['<a class="index" href="#index::b_c">a<span class="indexer" data-index="b_c"></span></a>'], '']);
89
90
  assert.deepStrictEqual(inspect(parser('[#a|b c]')), [['<a class="index" href="#index::b__c">a<span class="indexer" data-index="b__c"></span></a>'], '']);
90
91
  assert.deepStrictEqual(inspect(parser('[#a|b\tc]')), [['<a class="index" href="#index::b_c=xeqYk">a<span class="indexer" data-index="b_c=xeqYk"></span></a>'], '']);
91
92
  assert.deepStrictEqual(inspect(parser('[#a|b_c]')), [['<a class="index" href="#index::b_c=KUxv5">a<span class="indexer" data-index="b_c=KUxv5"></span></a>'], '']);
92
93
  assert.deepStrictEqual(inspect(parser('[#a|[]]')), [['<a class="index" href="#index::[]">a<span class="indexer" data-index="[]"></span></a>'], '']);
93
- assert.deepStrictEqual(inspect(parser('[#a|&copy;]')), [['<a class="index" href="#index::&amp;copy;">a<span class="indexer" data-index="&amp;copy;"></span></a>'], '']);
94
+ assert.deepStrictEqual(inspect(parser('[#a|&copy;]')), [['<a class="index" href="#index::©">a<span class="indexer" data-index="©"></span></a>'], '']);
95
+ assert.deepStrictEqual(inspect(parser('[#a|&nbsp;]')), [['<a class="index" href="#index::a|">a|</a>'], '']);
96
+ assert.deepStrictEqual(inspect(parser('[#a|<wbr>]')), [['<a class="index" href="#index::a|">a|</a>'], '']);
94
97
  assert.deepStrictEqual(inspect(parser('[#a |b]')), [['<a class="index" href="#index::b">a<span class="indexer" data-index="b"></span></a>'], '']);
95
98
  assert.deepStrictEqual(inspect(parser('[#a |b]')), [['<a class="index" href="#index::b">a<span class="indexer" data-index="b"></span></a>'], '']);
96
99
  assert.deepStrictEqual(inspect(parser('[#a \\ |b]')), [['<a class="index" href="#index::b">a<span class="indexer" data-index="b"></span></a>'], '']);
@@ -1,11 +1,12 @@
1
1
  import { ExtensionParser } from '../../inline';
2
- import { State, Recursion, Backtrack, BacktrackState, Command } from '../../context';
3
- import { union, inits, some, recursion, precedence, state, constraint, validate, verify, surround, open, lazy, fmap } from '../../../combinator';
2
+ import { State, Backtrack, BacktrackState } from '../../context';
3
+ import { union, inits, some, precedence, state, constraint, validate, surround, lazy, fmap } from '../../../combinator';
4
4
  import { inline } from '../../inline';
5
- import { indexee, identity } from './indexee';
6
- import { txt, str } from '../../source';
5
+ import { indexee, identity, text } from './indexee';
6
+ import { str } from '../../source';
7
7
  import { tightStart, trimBlankNodeEnd } from '../../visibility';
8
- import { html, define, defrag } from 'typed-dom/dom';
8
+ import { unshift } from 'spica/array';
9
+ import { frag, html, define, defrag } from 'typed-dom/dom';
9
10
 
10
11
  import IndexParser = ExtensionParser.IndexParser;
11
12
 
@@ -23,7 +24,7 @@ export const index: IndexParser = lazy(() => constraint(State.index, false, fmap
23
24
  trimBlankNodeEnd(ns).length > 0
24
25
  ? [[html('a', { 'data-index': dataindex(ns) }, defrag(ns))], rest]
25
26
  : undefined,
26
- undefined, 1 | Backtrack.linebracket, Backtrack.bracket | BacktrackState.nobreak)),
27
+ undefined, [3 | Backtrack.linebracket], Backtrack.bracket | BacktrackState.nobreak)),
27
28
  ([el]: [HTMLAnchorElement]) => [
28
29
  define(el,
29
30
  {
@@ -33,23 +34,18 @@ export const index: IndexParser = lazy(() => constraint(State.index, false, fmap
33
34
  }),
34
35
  ])));
35
36
 
36
- export const signature: IndexParser.SignatureParser = lazy(() => validate('|', fmap(open(
37
- /^\|(?!\\?\s)/,
38
- some(verify(union([bracket, txt]), ns => ns[0] !== Command.Escape), ']')),
39
- ns => [
40
- html('span', { class: 'indexer', 'data-index': identity('index', undefined, ns.join(''))!.slice(7) }),
41
- ])));
42
-
43
- const bracket: IndexParser.SignatureParser.BracketParser = lazy(() => union([
44
- surround(str('('), recursion(Recursion.terminal, some(union([bracket, txt]), ')')), str(')'), true,
45
- undefined, () => [[Command.Escape], ''], 3 | Backtrack.index),
46
- surround(str('['), recursion(Recursion.terminal, some(union([bracket, txt]), ']')), str(']'), true,
47
- undefined, () => [[Command.Escape], ''], 3 | Backtrack.index),
48
- surround(str('{'), recursion(Recursion.terminal, some(union([bracket, txt]), '}')), str('}'), true,
49
- undefined, () => [[Command.Escape], ''], 3 | Backtrack.index),
50
- surround(str('"'), precedence(2, recursion(Recursion.terminal, some(txt, '"'))), str('"'), true,
51
- undefined, () => [[Command.Escape], ''], 3 | Backtrack.index),
52
- ]));
37
+ export const signature: IndexParser.SignatureParser = lazy(() => validate('|', surround(
38
+ str(/^\|(?!\\?\s)/),
39
+ some(union([inline]), ']'),
40
+ /^(?=])/,
41
+ false,
42
+ ([as, bs], rest) => {
43
+ const index = identity('index', undefined, text(frag(bs)))?.slice(7);
44
+ return index
45
+ ? [[html('span', { class: 'indexer', 'data-index': index })], rest]
46
+ : [unshift(as, bs), rest];
47
+ },
48
+ ([as, bs], rest) => [unshift(as, bs), rest])));
53
49
 
54
50
  export function dataindex(ns: readonly (string | HTMLElement)[]): string | undefined {
55
51
  if (ns.length === 0) return;
@@ -28,7 +28,7 @@ describe('Unit: parser/inline/extension/indexer', () => {
28
28
  assert.deepStrictEqual(inspect(parser(' [|a\tb]')), [['<span class="indexer" data-index="a_b=33Mw2l"></span>'], '']);
29
29
  assert.deepStrictEqual(inspect(parser(' [|a_b]')), [['<span class="indexer" data-index="a_b=2H8oCG"></span>'], '']);
30
30
  assert.deepStrictEqual(inspect(parser(' [|A]')), [['<span class="indexer" data-index="A"></span>'], '']);
31
- assert.deepStrictEqual(inspect(parser(' [|*A*]')), [['<span class="indexer" data-index="*A*"></span>'], '']);
31
+ assert.deepStrictEqual(inspect(parser(' [|*A*]')), [['<span class="indexer" data-index="A"></span>'], '']);
32
32
  assert.deepStrictEqual(inspect(parser(' [|`A`]')), [['<span class="indexer" data-index="`A`"></span>'], '']);
33
33
  assert.deepStrictEqual(inspect(parser(' [|${A}$]')), [['<span class="indexer" data-index="${A}$"></span>'], '']);
34
34
  assert.deepStrictEqual(inspect(parser(' [|a]')), [['<span class="indexer" data-index="a"></span>'], '']);
@@ -13,7 +13,7 @@ export const segment: ExtensionParser.LabelParser.SegmentParser = clear(union([
13
13
 
14
14
  export const label: ExtensionParser.LabelParser = constraint(State.label, false, fmap(
15
15
  union([
16
- surround('[', body, ']', false, undefined, undefined, 1 | Backtrack.bracket),
16
+ surround('[', body, ']', false, undefined, undefined, [1 | Backtrack.linebracket, 1]),
17
17
  body,
18
18
  ]),
19
19
  ([text]) => [
@@ -24,4 +24,4 @@ export const placeholder: ExtensionParser.PlaceholderParser = lazy(() => surroun
24
24
  'data-invalid-message': `Invalid start symbol or linebreak`,
25
25
  }, defrag(bs)),
26
26
  ], rest],
27
- ([as, bs], rest) => [unshift(as, bs), rest], 3 | Backtrack.bracket));
27
+ ([as, bs], rest) => [unshift(as, bs), rest], [3 | Backtrack.bracket]));
@@ -22,12 +22,12 @@ export const textlink: LinkParser.TextLinkParser = lazy(() => constraint(State.l
22
22
  '[',
23
23
  trimBlankStart(some(union([inline]), ']', [['\n', 9], [']', 1]])),
24
24
  ']',
25
- true, undefined, undefined, 1 | Backtrack.linebracket, Backtrack.bracket | BacktrackState.nobreak)),
25
+ true, undefined, undefined, [1 | Backtrack.linebracket], Backtrack.bracket | BacktrackState.nobreak)),
26
26
  dup(surround(
27
27
  /^{(?![{}])/,
28
28
  inits([uri, some(option)]),
29
29
  /^[^\S\n]*}/,
30
- false, undefined, undefined, 3 | Backtrack.link)),
30
+ false, undefined, undefined, [3 | Backtrack.link])),
31
31
  ])),
32
32
  ([params, content = []]: [string[], (HTMLElement | string)[]], rest, context) => {
33
33
  assert(!html('div', content).querySelector('a, .media, .annotation, .reference'));
@@ -29,12 +29,12 @@ export const media: MediaParser = lazy(() => constraint(State.media, false, vali
29
29
  txt,
30
30
  ]), ns => ns[0] !== Command.Escape), ']', [['\n', 9]])),
31
31
  ']',
32
- true, undefined, undefined, 1 | Backtrack.media)),
32
+ true, undefined, undefined, [3 | Backtrack.lineescbracket])),
33
33
  dup(surround(
34
34
  /^{(?![{}])/,
35
35
  inits([uri, some(option)]),
36
36
  /^[^\S\n]*}/,
37
- false, undefined, undefined, 3 | Backtrack.link)),
37
+ false, undefined, undefined, [3 | Backtrack.link])),
38
38
  ]),
39
39
  ([as, bs]) => bs ? [[as.join('').trim() || as.join('')], bs] : [[''], as]),
40
40
  ([[text]]) => text === '' || text.trim() !== ''),
@@ -75,13 +75,13 @@ export const linemedia: MediaParser.LineMediaParser = surround(
75
75
 
76
76
  const bracket: MediaParser.TextParser.BracketParser = lazy(() => recursion(Recursion.terminal, union([
77
77
  surround(str('('), some(union([unsafehtmlentity, bracket, txt]), ')'), str(')'), true,
78
- undefined, () => [[Command.Escape], ''], 3 | Backtrack.media),
78
+ undefined, () => [[Command.Escape], ''], [3 | Backtrack.lineescbracket]),
79
79
  surround(str('['), some(union([unsafehtmlentity, bracket, txt]), ']'), str(']'), true,
80
- undefined, () => [[Command.Escape], ''], 3 | Backtrack.media),
80
+ undefined, () => [[Command.Escape], ''], [3 | Backtrack.lineescbracket]),
81
81
  surround(str('{'), some(union([unsafehtmlentity, bracket, txt]), '}'), str('}'), true,
82
- undefined, () => [[Command.Escape], ''], 3 | Backtrack.media),
82
+ undefined, () => [[Command.Escape], ''], [3 | Backtrack.lineescbracket]),
83
83
  surround(str('"'), precedence(2, some(union([unsafehtmlentity, txt]), '"')), str('"'), true,
84
- undefined, () => [[Command.Escape], ''], 3 | Backtrack.media),
84
+ undefined, () => [[Command.Escape], ''], [3 | Backtrack.lineescbracket]),
85
85
  ])));
86
86
 
87
87
  const option: MediaParser.ParameterParser.OptionParser = lazy(() => union([
@@ -24,7 +24,7 @@ export const reference: ReferenceParser = lazy(() => constraint(State.reference,
24
24
  state & State.annotation
25
25
  ? [unshift(as, bs), rest]
26
26
  : undefined,
27
- 1 | Backtrack.linebracket, Backtrack.bracket | BacktrackState.nobreak)));
27
+ [3 | Backtrack.linedoublebracket, 1 | Backtrack.linebracket], Backtrack.bracket | BacktrackState.nobreak)));
28
28
 
29
29
  // Chicago-Style
30
30
  const abbr: ReferenceParser.AbbrParser = surround(
@@ -18,7 +18,7 @@ export const ruby: RubyParser = lazy(() => fmap(
18
18
  ns && ns.at(-1) === '' && ns.pop();
19
19
  return ns && isTightNodeStart(ns) ? [ns, rest] : undefined;
20
20
  },
21
- undefined, 3 | Backtrack.ruby)),
21
+ undefined, [3 | Backtrack.ruby])),
22
22
  dup(surround(
23
23
  '(', str(/^(?:\\[^\n]|[^\\[\](){}<>"\n])+/u), ')',
24
24
  false,
@@ -26,7 +26,7 @@ export const ruby: RubyParser = lazy(() => fmap(
26
26
  const ns = eval(text({ source, context }), [undefined])[0];
27
27
  return ns && [ns, rest];
28
28
  },
29
- undefined, 3 | Backtrack.ruby)),
29
+ undefined, [3 | Backtrack.ruby])),
30
30
  ]),
31
31
  ([texts, rubies]) => {
32
32
  switch (true) {
@@ -12,6 +12,8 @@ describe('Unit: parser/inline/template', () => {
12
12
  assert.deepStrictEqual(inspect(parser('{}')), undefined);
13
13
  assert.deepStrictEqual(inspect(parser('{{')), undefined);
14
14
  assert.deepStrictEqual(inspect(parser('{{\\}}')), undefined);
15
+ assert.deepStrictEqual(inspect(parser('{{\n}}')), undefined);
16
+ assert.deepStrictEqual(inspect(parser('{{\\\n}}')), undefined);
15
17
  assert.deepStrictEqual(inspect(parser('{{a}b}')), undefined);
16
18
  assert.deepStrictEqual(inspect(parser('{{{a}}')), undefined);
17
19
  assert.deepStrictEqual(inspect(parser(' {{}}')), undefined);
@@ -22,7 +24,6 @@ describe('Unit: parser/inline/template', () => {
22
24
  assert.deepStrictEqual(inspect(parser('{{}}}')), [['<span class="template">{{}}</span>'], '}']);
23
25
  assert.deepStrictEqual(inspect(parser('{{ }}')), [['<span class="template">{{ }}</span>'], '']);
24
26
  assert.deepStrictEqual(inspect(parser('{{ a }}')), [['<span class="template">{{ a }}</span>'], '']);
25
- assert.deepStrictEqual(inspect(parser('{{\n}}')), [['<span class="template">{{\n}}</span>'], '']);
26
27
  assert.deepStrictEqual(inspect(parser('{{a}}')), [['<span class="template">{{a}}</span>'], '']);
27
28
  assert.deepStrictEqual(inspect(parser('{{a b}}')), [['<span class="template">{{a b}}</span>'], '']);
28
29
  assert.deepStrictEqual(inspect(parser('{{\\}}}')), [['<span class="template">{{\\}}}</span>'], '']);
@@ -6,19 +6,20 @@ import { html } from 'typed-dom/dom';
6
6
 
7
7
  export const template: TemplateParser = lazy(() => surround(
8
8
  '{{',
9
- precedence(1, some(verify(union([bracket, escsource]), ns => ns[0] !== Command.Escape), '}')),
9
+ precedence(1,
10
+ some(verify(union([bracket, escsource]), ns => ns[0] !== Command.Escape), '}', [['\n', 9]])),
10
11
  '}}',
11
12
  true,
12
13
  ([, ns = []], rest) => [[html('span', { class: 'template' }, `{{${ns.join('')}}}`)], rest],
13
- undefined, 3 | Backtrack.template));
14
+ undefined, [3 | Backtrack.linedoublebracket, 1 | Backtrack.lineescbracket], Backtrack.bracket));
14
15
 
15
16
  const bracket: TemplateParser.BracketParser = lazy(() => union([
16
17
  surround(str('('), recursion(Recursion.terminal, some(union([bracket, escsource]), ')')), str(')'), true,
17
- undefined, () => [[Command.Escape], ''], 3 | Backtrack.template),
18
+ undefined, () => [[Command.Escape], ''], [3 | Backtrack.lineescbracket]),
18
19
  surround(str('['), recursion(Recursion.terminal, some(union([bracket, escsource]), ']')), str(']'), true,
19
- undefined, () => [[Command.Escape], ''], 3 | Backtrack.template),
20
+ undefined, () => [[Command.Escape], ''], [3 | Backtrack.lineescbracket]),
20
21
  surround(str('{'), recursion(Recursion.terminal, some(union([bracket, escsource]), '}')), str('}'), true,
21
- undefined, () => [[Command.Escape], ''], 3 | Backtrack.template),
22
+ undefined, () => [[Command.Escape], ''], [3 | Backtrack.lineescbracket]),
22
23
  surround(str('"'), precedence(2, recursion(Recursion.terminal, some(escsource, /^["\n]/))), str('"'), true,
23
- undefined, () => [[Command.Escape], ''], 3 | Backtrack.template),
24
+ undefined, () => [[Command.Escape], ''], [3 | Backtrack.lineescbracket]),
24
25
  ]));
@@ -127,6 +127,7 @@ describe('Unit: parser/inline', () => {
127
127
  assert.deepStrictEqual(inspect(parser('((${))}$')), [['(', '(', '<span class="math" translate="no" data-src="${))}$">${))}$</span>'], '']);
128
128
  assert.deepStrictEqual(inspect(parser('((a\nb))')), [['<span class="paren">(<span class="paren">(a<br>b)</span>)</span>'], '']);
129
129
  assert.deepStrictEqual(inspect(parser('(((a\nb)))')), [['<span class="paren">(<span class="paren">(<span class="paren">(a<br>b)</span>)</span>)</span>'], '']);
130
+ assert.deepStrictEqual(inspect(parser('(([:a\n]')), [['(', '(', '<span class="invalid">a<br></span>'], '']);
130
131
  assert.deepStrictEqual(inspect(parser('"((""))')), [['"', '(', '(', '"', '"', ')', ')'], '']);
131
132
  assert.deepStrictEqual(inspect(parser('[[[a]]')), [['[', '<sup class="reference"><span>a</span></sup>'], '']);
132
133
  assert.deepStrictEqual(inspect(parser('[[[[a]]')), [['[', '[', '<sup class="reference"><span>a</span></sup>'], '']);
@@ -153,6 +154,8 @@ describe('Unit: parser/inline', () => {
153
154
  assert.deepStrictEqual(inspect(parser('"{{""}}')), [['"', '{', '{', '"', '"', '}', '}'], '']);
154
155
  assert.deepStrictEqual(inspect(parser('[#http://host/(<bdi>)]</bdi>')), [['<a class="index" href="#index::http://host/(&lt;bdi&gt;)">http://host/(&lt;bdi&gt;)</a>', '<', '/', 'bdi', '>'], '']);
155
156
  assert.deepStrictEqual(inspect(parser('[#@a/http://host/(<bdi>)]</bdi>')), [[ '[', '#@a/http', ':', '/', '/', 'host', '/', '(', '<bdi>)]</bdi>' ], '']);
157
+ assert.deepStrictEqual(inspect(parser('[#a|<bdi>]</bdi>')), [['[', '<a class="hashtag" href="/hashtags/a">#a</a>', '|', '<bdi>]</bdi>'], '']);
158
+ assert.deepStrictEqual(inspect(parser('[[#a|<bdi>]</bdi>')), [['[', '[', '<a class="hashtag" href="/hashtags/a">#a</a>', '|', '<bdi>]</bdi>'], '']);
156
159
  });
157
160
 
158
161
  it('uri', () => {
@@ -17,6 +17,7 @@ export const escsource: EscapableSourceParser = ({ source, context }) => {
17
17
  switch (source[0]) {
18
18
  case '\r':
19
19
  assert(!source.includes('\r', 1));
20
+ consume(-1, context);
20
21
  return [[], source.slice(1)];
21
22
  case Command.Escape:
22
23
  consume(1, context);
@@ -21,6 +21,7 @@ export const text: TextParser = ({ source, context }) => {
21
21
  switch (source[0]) {
22
22
  case '\r':
23
23
  assert(!source.includes('\r', 1));
24
+ consume(-1, context);
24
25
  return [[], source.slice(1)];
25
26
  case Command.Escape:
26
27
  case '\\':
@@ -15,6 +15,7 @@ export const unescsource: UnescapableSourceParser = ({ source, context }) => {
15
15
  switch (source[0]) {
16
16
  case '\r':
17
17
  assert(!source.includes('\r', 1));
18
+ consume(-1, context);
18
19
  return [[], source.slice(1)];
19
20
  case Command.Escape:
20
21
  assert(source[0] !== Command.Escape);
@@ -1,15 +1,12 @@
1
1
  import { min } from 'spica/alias';
2
2
  import { Command } from './context';
3
3
  import { Parser, Result, Ctx, Tree, Context, eval, exec } from '../combinator/data/parser';
4
- import { consume, convert } from '../combinator';
4
+ import { convert } from '../combinator';
5
5
  import { define } from 'typed-dom/dom';
6
6
 
7
7
  export function lineable<P extends Parser<HTMLElement | string>>(parser: P): P;
8
8
  export function lineable<T extends HTMLElement | string>(parser: Parser<T>): Parser<T> {
9
- return convert((source, context) => {
10
- consume(-1, context);
11
- return `\r${source}`;
12
- }, parser);
9
+ return convert(source => `\r${source}`, parser);
13
10
  }
14
11
 
15
12
  export function repeat<P extends Parser<HTMLElement | string>>(symbol: string, parser: P, cons: (nodes: Tree<P>[], context: Context<P>) => Tree<P>[], termination?: (acc: Tree<P>[][], rest: string, prefix: number, postfix: number, state: boolean) => Result<string | Tree<P>>): P;