securemark 0.258.5 → 0.258.8
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 +12 -0
- package/design.md +13 -5
- package/dist/index.js +42 -58
- package/markdown.d.ts +4 -4
- package/package.json +1 -1
- package/src/combinator/data/parser/context/delimiter.ts +6 -3
- package/src/combinator/data/parser/context/memo.ts +1 -1
- package/src/combinator/data/parser/context.ts +1 -0
- package/src/parser/block/extension/table.ts +1 -1
- package/src/parser/block/olist.ts +1 -1
- package/src/parser/block/reply/quote.ts +1 -1
- package/src/parser/block/table.ts +1 -1
- package/src/parser/block/ulist.ts +1 -1
- package/src/parser/inline/annotation.test.ts +1 -1
- package/src/parser/inline/annotation.ts +2 -4
- package/src/parser/inline/bracket.test.ts +1 -1
- package/src/parser/inline/extension/index.ts +1 -1
- package/src/parser/inline/extension/placeholder.ts +1 -1
- package/src/parser/inline/html.test.ts +15 -15
- package/src/parser/inline/html.ts +8 -7
- package/src/parser/inline/link.test.ts +2 -2
- package/src/parser/inline/link.ts +7 -21
- package/src/parser/inline/reference.test.ts +1 -1
- package/src/parser/inline/reference.ts +2 -4
- package/src/parser/inline/template.test.ts +1 -1
- package/src/parser/inline/template.ts +1 -3
- package/src/parser/inline.test.ts +5 -5
package/CHANGELOG.md
CHANGED
package/design.md
CHANGED
|
@@ -284,17 +284,25 @@ CodeMirrorが素では速いがVimModeでは数万文字程度でも耐え難く
|
|
|
284
284
|
|
|
285
285
|
### バックトラック
|
|
286
286
|
|
|
287
|
-
SecuremarkのAnnotation
|
|
288
|
-
CommonMarkはLink
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
287
|
+
SecuremarkのAnnotation構文に典型的であるように文脈を変更する構文の中にその文脈に依存し変更される他の構文が存在する場合一般に文脈の相違から解析結果を再利用不能な(`αA'β | αAB`)バックトラックが生じる。文脈依存構文の解析中に文脈により解釈の異なる字句(`[a[`)または現在の文脈を終了する字句(ただの括弧がスコープを作らない場合の`(([a))`)に遭遇したとき、現在の文脈での解析の継続を試行する解析方法はメモ化なしではバックトラックが再帰的に生じ線形時間で解析できず、現在の文脈での解析を中止し直前の文脈を継続または新たな文脈を開始する解析方法はバックトラックなしで線形時間で解析できる。
|
|
288
|
+
CommonMarkはLink構文から明らかなように後者の解析方法により重篤なバックトラックなしで(インラインでは)ほぼ1回の走査で解析できる言語であるが同時にこれは文脈依存構文の正当な入れ子表現(`[<a@b>]`)を解析できないか不正な表現(`[<a@b>]()`)を除外できず二重リンク(`<a><a></a></a>`)を生成する、文脈依存構文の存在する数に応じて多項式的(おそらく$n^{2+c}$)に構文の壊れやすさの増す脆く拡張性の低い言語であることを意味する(構文の決定を遅延できれば解決できるがこれにより他の構文の解釈が非決定的にならない場合に限られる)。この問題はおそらくメモ化により解決できるがCommonMarkは実行性能追及のためメモ化を廃止しており二重リンクも放置しているためメモ化により性能を低下させてまで解決するつもりはないと思われる(すなわちCommonMarkは機械を至上とし人間に制約を課す低水準の言語であり人間の需要を至上とするSecuremarkとは対極に位置する)。
|
|
289
|
+
従ってほぼ1回の走査で解析可能な文法に制約されるCommonMarkには文脈依存構文を入れ子表現の広範な制限ならびに構文の可読性および開始記号の信頼性の多項式的な低下と引き換えにしか追加できないという拡張性の欠陥が存在する。CommonMarkの仕様策定者が構文の拡張に(名称を維持するか否かにかかわらず)不自然なまでに消極的または進展がないのは正当な理由や怠慢からでなく文脈依存構文を追加するにつれて構文解析戦略の欠陥が明白になっていくためおよび現在の高い実行性能を低下させたくないためである。`~~a~~`のような文脈自由構文は容易に追加できるがこうしたマージンを失えばもはや後はない。
|
|
290
|
+
Securemarkは線形時間で解析不能な前者の解析方法を各種最適化によりおおよそ4n以下の最悪計算量に改善しさらに解析時間と解析範囲の局限により一定時間内で解析不能な入力の影響を局限することでこれらの問題を解決している。この解析方法はほとんどの自然な入力に対して線形に近い時間で効率的に動作し、最悪計算量で低速に動作させる少数の機械的攻撃入力に対してもサーバーで多数のユーザーのリクエストに応じるには低速で脆弱性となる可能性があるがクライアントで単一のユーザーの操作に応じるには十分高速であるためクライアントで解析する限り解析の効率または速度が実用上問題となることはない。
|
|
291
|
+
|
|
292
|
+
### メモ化
|
|
293
|
+
|
|
294
|
+
一部の文脈依存言語を線形時間で解析できるようになるとしても状態数に応じて複数回走査が必要なこと、これにより時間効率が定性的には改善されても定量的には文脈自由言語より数倍悪いこと、オーバーヘッドが有意に大きいこと、時間の代わりに空間効率が非線形に悪化する可能性があることなどから理論上同じ線形時間だとしても実用上文脈自由言語と同等の実行性能にはならず文脈依存言語を文脈自由言語と等価の選択肢にするものではない。
|
|
295
|
+
|
|
296
|
+
### 最適化
|
|
297
|
+
|
|
298
|
+
現在Securemarkのボトルネックはプロファイルによると単なるパーサーの呼び出しが並んでおり引数の入力文字列を値渡しのためコピーするコストである可能性が疑われる。アルゴリズムとしてはメモ化したパース結果を複製せず永続データ構造として使用できるようおよび後処理に必要となるノードを収集しやすいようCSTを木構造に置き換える必要がある。またDOM出力の分離によりバックトラックのコストを削減する。
|
|
292
299
|
|
|
293
300
|
### 標準化
|
|
294
301
|
|
|
295
302
|
Markdownのように自然言語と自身の文法を分離する汎用構造がないメタ言語は構文を拡張する際に旧構文を破壊する新構文が自然言語の中に潜在せざるをえず後方互換性を保証することが不可能である。
|
|
296
303
|
このためCommonMarkは拡張構文を標準化した次期標準仕様との互換性を確保する役には立たずその有用性は構文の拡張を考慮しない範囲での効率的な実装方法の例示およびテストケースの集積による個別実装の支援ならびにその結果としての限定的互換性にとどまる。
|
|
297
304
|
さらにCommonMarkは前述の解析時間の制約から拡張性が低く、高度な構文や機能の実装可能性を考慮していないことから拡張仕様において準拠すべき技術的正当性もない。
|
|
305
|
+
実際GFMが二種類のフェンスドブロックのセマンティクスを分けずCommonMarkに準拠して単なるエイリアスとして有用な記号を浪費したのは顕著かつ明白な失敗だったと言えよう(Securemarkでは入力文字列の無変換表示(シンタックスハイライト)用と変換表示(拡張構文)用に分かれている)。
|
|
298
306
|
|
|
299
307
|
よってMarkdownの標準化は後方互換性確保が不可能であることから発展性がなくスナップショット以上の技術的意味を持たない。
|
|
300
308
|
MarkdownはGFMのように最初から高機能で完成度の高い拡張不要な独自実装のほうが標準としての互換性を確保でき、構文に曖昧さがない形式言語と異なりまず最小限の標準仕様を策定しのちに拡張していく通常の標準化方法が適さない特殊な言語である。
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! securemark v0.258.
|
|
1
|
+
/*! securemark v0.258.8 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("DOMPurify"), require("Prism"));
|
|
@@ -2884,6 +2884,7 @@ exports.syntax = syntax;
|
|
|
2884
2884
|
|
|
2885
2885
|
function creation(cost, parser) {
|
|
2886
2886
|
if (typeof cost === 'function') return creation(1, cost);
|
|
2887
|
+
if (cost === 0) return parser;
|
|
2887
2888
|
return (source, context) => {
|
|
2888
2889
|
const {
|
|
2889
2890
|
resources = {
|
|
@@ -3025,13 +3026,18 @@ class Delimiters {
|
|
|
3025
3026
|
} = this;
|
|
3026
3027
|
|
|
3027
3028
|
for (let i = 0; i < matchers.length; ++i) {
|
|
3028
|
-
|
|
3029
|
+
const matcher = matchers[i];
|
|
3030
|
+
if (precedence >= matcher[2]) continue;
|
|
3031
|
+
|
|
3032
|
+
switch (matcher[3](source)) {
|
|
3029
3033
|
case true:
|
|
3030
|
-
|
|
3031
|
-
continue;
|
|
3034
|
+
return true;
|
|
3032
3035
|
|
|
3033
3036
|
case false:
|
|
3034
3037
|
return false;
|
|
3038
|
+
|
|
3039
|
+
default:
|
|
3040
|
+
continue;
|
|
3035
3041
|
}
|
|
3036
3042
|
}
|
|
3037
3043
|
|
|
@@ -3094,7 +3100,7 @@ class Memo {
|
|
|
3094
3100
|
|
|
3095
3101
|
for (let i = position + this.offset, len = memory.length; i < len; ++i) {
|
|
3096
3102
|
memory.pop();
|
|
3097
|
-
} //console.log('clear', position + 1);
|
|
3103
|
+
} //console.log('clear', position + this.offset + 1);
|
|
3098
3104
|
|
|
3099
3105
|
}
|
|
3100
3106
|
|
|
@@ -4811,7 +4817,7 @@ function format(rows) {
|
|
|
4811
4817
|
const cell = isVirtual ? (0, array_1.splice)(cells, j, 0, global_1.undefined) && ranges[i][j] : cells[j];
|
|
4812
4818
|
const isHeadCell = cell.tagName === 'TH';
|
|
4813
4819
|
heads |= (0, global_1.BigInt)(isHeadCell) << jn;
|
|
4814
|
-
highlights |= (0, global_1.BigInt)(cell.
|
|
4820
|
+
highlights |= (0, global_1.BigInt)(cell.className === 'highlight') << jn;
|
|
4815
4821
|
hasDataCell ||= !isHeadCell;
|
|
4816
4822
|
|
|
4817
4823
|
if (isHeadCell && !hasDataCell) {
|
|
@@ -5163,7 +5169,7 @@ function initial(type) {
|
|
|
5163
5169
|
}
|
|
5164
5170
|
|
|
5165
5171
|
function format(el, type, form) {
|
|
5166
|
-
if (el.firstElementChild?.firstElementChild?.
|
|
5172
|
+
if (el.firstElementChild?.firstElementChild?.className === 'checkbox') {
|
|
5167
5173
|
el.setAttribute('class', 'checklist');
|
|
5168
5174
|
}
|
|
5169
5175
|
|
|
@@ -5345,7 +5351,7 @@ const qblock = (source, context) => {
|
|
|
5345
5351
|
continue;
|
|
5346
5352
|
}
|
|
5347
5353
|
|
|
5348
|
-
if (child.
|
|
5354
|
+
if (child.className === 'cite' || child.classList.contains('quote')) {
|
|
5349
5355
|
context.resources && (context.resources.clock -= child.childNodes.length);
|
|
5350
5356
|
nodes.splice(i, 1, ...child.childNodes);
|
|
5351
5357
|
--i;
|
|
@@ -5434,7 +5440,7 @@ const head = (0, combinator_1.creation)((0, combinator_1.fmap)(cell, ns => [(0,
|
|
|
5434
5440
|
const data = (0, combinator_1.creation)((0, combinator_1.fmap)(cell, ns => [(0, dom_1.html)('td', (0, visibility_1.trimNode)((0, dom_1.defrag)(ns)))]));
|
|
5435
5441
|
|
|
5436
5442
|
function format(rows) {
|
|
5437
|
-
const aligns = rows[0].
|
|
5443
|
+
const aligns = rows[0].className === 'invalid' ? [] : (0, duff_1.duffReduce)(rows.shift().children, (acc, el) => (0, array_1.push)(acc, [el.textContent]), []);
|
|
5438
5444
|
|
|
5439
5445
|
for (let i = 0; i < rows.length; ++i) {
|
|
5440
5446
|
(0, duff_1.duffEach)(rows[i].children, (col, i) => {
|
|
@@ -5492,7 +5498,7 @@ function fillFirstLine(ns) {
|
|
|
5492
5498
|
exports.fillFirstLine = fillFirstLine;
|
|
5493
5499
|
|
|
5494
5500
|
function format(el) {
|
|
5495
|
-
if (el.firstElementChild?.firstElementChild?.
|
|
5501
|
+
if (el.firstElementChild?.firstElementChild?.className === 'checkbox') {
|
|
5496
5502
|
el.setAttribute('class', 'checklist');
|
|
5497
5503
|
}
|
|
5498
5504
|
|
|
@@ -5689,25 +5695,23 @@ const combinator_1 = __webpack_require__(2087);
|
|
|
5689
5695
|
|
|
5690
5696
|
const inline_1 = __webpack_require__(1160);
|
|
5691
5697
|
|
|
5692
|
-
const link_1 = __webpack_require__(9628);
|
|
5693
|
-
|
|
5694
5698
|
const visibility_1 = __webpack_require__(7618);
|
|
5695
5699
|
|
|
5696
5700
|
const dom_1 = __webpack_require__(3252);
|
|
5697
5701
|
|
|
5698
5702
|
exports.annotation = (0, combinator_1.lazy)(() => (0, combinator_1.surround)('((', (0, combinator_1.constraint)(64
|
|
5699
5703
|
/* State.annotation */
|
|
5700
|
-
, false, (0, combinator_1.
|
|
5701
|
-
/* Syntax.annotation */
|
|
5702
|
-
, 6, 1, (0, combinator_1.state)(64
|
|
5704
|
+
, false, (0, combinator_1.state)(64
|
|
5703
5705
|
/* State.annotation */
|
|
5704
5706
|
| 2
|
|
5705
5707
|
/* State.media */
|
|
5706
|
-
, (0,
|
|
5708
|
+
, (0, combinator_1.syntax)(32
|
|
5709
|
+
/* Syntax.annotation */
|
|
5710
|
+
, 6, 1, (0, visibility_1.startLoose)((0, combinator_1.context)({
|
|
5707
5711
|
delimiters: global_1.undefined
|
|
5708
5712
|
}, (0, combinator_1.some)((0, combinator_1.union)([inline_1.inline]), ')', [[/^\\?\n/, 9], [')', 2], ['))', 6]])), ')')))), '))', false, ([, ns], rest) => [[(0, dom_1.html)('sup', {
|
|
5709
5713
|
class: 'annotation'
|
|
5710
|
-
}, [(0, dom_1.html)('span', (0, visibility_1.trimNode)((0, dom_1.defrag)(ns)))])], rest]
|
|
5714
|
+
}, [(0, dom_1.html)('span', (0, visibility_1.trimNode)((0, dom_1.defrag)(ns)))])], rest]));
|
|
5711
5715
|
|
|
5712
5716
|
/***/ }),
|
|
5713
5717
|
|
|
@@ -6249,9 +6253,7 @@ const dom_1 = __webpack_require__(3252);
|
|
|
6249
6253
|
|
|
6250
6254
|
exports.index = (0, combinator_1.lazy)(() => (0, combinator_1.validate)('[#', (0, combinator_1.fmap)((0, indexee_1.indexee)((0, combinator_1.surround)('[#', (0, combinator_1.constraint)(16
|
|
6251
6255
|
/* State.index */
|
|
6252
|
-
, false, (0, combinator_1.
|
|
6253
|
-
/* Syntax.index */
|
|
6254
|
-
, 2, 1, (0, combinator_1.state)(64
|
|
6256
|
+
, false, (0, combinator_1.state)(64
|
|
6255
6257
|
/* State.annotation */
|
|
6256
6258
|
| 32
|
|
6257
6259
|
/* State.reference */
|
|
@@ -6265,7 +6267,9 @@ exports.index = (0, combinator_1.lazy)(() => (0, combinator_1.validate)('[#', (0
|
|
|
6265
6267
|
/* State.media */
|
|
6266
6268
|
| 1
|
|
6267
6269
|
/* State.autolink */
|
|
6268
|
-
, (0,
|
|
6270
|
+
, (0, combinator_1.syntax)(1024
|
|
6271
|
+
/* Syntax.index */
|
|
6272
|
+
, 2, 1, (0, visibility_1.startTight)((0, combinator_1.open)((0, source_1.stropt)(/^\|?/), (0, visibility_1.trimBlankEnd)((0, combinator_1.some)((0, combinator_1.union)([signature, inline_1.inline]), ']', [[/^\\?\n/, 9], [']', 2]])), true))))), ']', false, ([, ns], rest) => [[(0, dom_1.html)('a', (0, dom_1.defrag)(ns))], rest])), ([el]) => [(0, dom_1.define)(el, {
|
|
6269
6273
|
id: el.id ? null : global_1.undefined,
|
|
6270
6274
|
class: 'index',
|
|
6271
6275
|
href: el.id ? `#${el.id}` : global_1.undefined
|
|
@@ -6462,7 +6466,7 @@ const visibility_1 = __webpack_require__(7618);
|
|
|
6462
6466
|
|
|
6463
6467
|
const dom_1 = __webpack_require__(3252);
|
|
6464
6468
|
|
|
6465
|
-
const array_1 = __webpack_require__(8112); // Don't use the symbols already used:
|
|
6469
|
+
const array_1 = __webpack_require__(8112); // Don't use the symbols already used: !#$%@&*+~=
|
|
6466
6470
|
// All syntax surrounded by square brackets shouldn't contain line breaks.
|
|
6467
6471
|
|
|
6468
6472
|
|
|
@@ -6514,11 +6518,11 @@ const attrspecs = {
|
|
|
6514
6518
|
};
|
|
6515
6519
|
global_1.Object.setPrototypeOf(attrspecs, null);
|
|
6516
6520
|
global_1.Object.values(attrspecs).forEach(o => global_1.Object.setPrototypeOf(o, null));
|
|
6517
|
-
exports.html = (0, combinator_1.lazy)(() => (0, combinator_1.validate)('<', (0, combinator_1.validate)(/^<[a-z]+(?=[^\S\n]|>)
|
|
6521
|
+
exports.html = (0, combinator_1.lazy)(() => (0, combinator_1.validate)('<', (0, combinator_1.validate)(/^<[a-z]+(?=[^\S\n]|>)/i, (0, combinator_1.syntax)(0
|
|
6518
6522
|
/* Syntax.none */
|
|
6519
|
-
, 5, 1, (0, combinator_1.union)([(0, combinator_1.focus)(/^<wbr[^\S\n]
|
|
6520
|
-
/^<(?:area|base|br|col|embed|hr|img|input|link|meta|source|track|wbr)(?=[^\S\n]|>)
|
|
6521
|
-
exports.attribute = (0, combinator_1.union)([(0, source_1.str)(/^[^\S\n]+[a-z]+(?:-[a-z]+)*(?:="(?:\\[^\n]|[^\\\n"])*")?(?=[^\S\n]|>)/)]); // https://developer.mozilla.org/en-US/docs/Web/HTML/Element
|
|
6523
|
+
, 5, 1, (0, combinator_1.union)([(0, combinator_1.focus)(/^<wbr[^\S\n]*>/i, () => [[(0, dom_1.html)('wbr')], '']), (0, combinator_1.surround)( // https://html.spec.whatwg.org/multipage/syntax.html#void-elements
|
|
6524
|
+
(0, source_1.str)(/^<(?:area|base|br|col|embed|hr|img|input|link|meta|source|track|wbr)(?=[^\S\n]|>)/i), (0, combinator_1.some)((0, combinator_1.union)([exports.attribute])), (0, source_1.str)(/^[^\S\n]*>/), true, ([as, bs = [], cs], rest) => [[elem(as[0].slice(1), (0, array_1.push)((0, array_1.unshift)(as, bs), cs), [], [])], rest]), (0, combinator_1.match)(new RegExp(String.raw`^<(${TAGS.join('|')})(?=[^\S\n]|>)`), (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, source_1.str)(/^[^\S\n]*>/), true), (0, combinator_1.subsequence)([(0, combinator_1.focus)(/^[^\S\n]*\n/, (0, combinator_1.some)(inline_1.inline)), (0, combinator_1.some)((0, combinator_1.open)(/^\n?/, (0, combinator_1.some)(inline_1.inline, (0, visibility_1.blankWith)('\n', `</${tag}>`), [[(0, visibility_1.blankWith)('\n', `</${tag}>`), 5]]), true))]), (0, source_1.str)(`</${tag}>`), true, ([as, bs = [], cs], rest) => [[elem(tag, as, bs, cs)], rest], ([as, bs = []], rest) => [[elem(tag, as, bs, [])], rest]), ([, tag]) => TAGS.indexOf(tag), [])), (0, combinator_1.match)(/^<([a-z]+)(?=[^\S\n]|>)/i, (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, source_1.str)(/^[^\S\n]*>/), true), (0, combinator_1.subsequence)([(0, combinator_1.focus)(/^[^\S\n]*\n/, (0, combinator_1.some)(inline_1.inline)), (0, combinator_1.some)(inline_1.inline, `</${tag}>`, [[`</${tag}>`, 5]])]), (0, source_1.str)(`</${tag}>`), true, ([as, bs = [], cs], rest) => [[elem(tag, as, bs, cs)], rest], ([as, bs = []], rest) => [[elem(tag, as, bs, [])], rest]), ([, tag]) => tag, new cache_1.Cache(10000)))])))));
|
|
6525
|
+
exports.attribute = (0, combinator_1.union)([(0, source_1.str)(/^[^\S\n]+[a-z]+(?:-[a-z]+)*(?:="(?:\\[^\n]|[^\\\n"])*")?(?=[^\S\n]|>)/i)]); // https://developer.mozilla.org/en-US/docs/Web/HTML/Element
|
|
6522
6526
|
// [...document.querySelectorAll('tbody > tr > td:first-child')].map(el => el.textContent.slice(1, -1))
|
|
6523
6527
|
|
|
6524
6528
|
const TAGS = global_1.Object.freeze(["html", "base", "head", "link", "meta", "style", "title", "body", "address", "article", "aside", "footer", "header", "h1", "h2", "h3", "h4", "h5", "h6", "main", "nav", "section", "blockquote", "dd", "div", "dl", "dt", "figcaption", "figure", "hr", "li", "menu", "ol", "p", "pre", "ul", "a", "abbr", "b", "bdi", "bdo", "br", "cite", "code", "data", "dfn", "em", "i", "kbd", "mark", "q", "rp", "rt", "ruby", "s", "samp", "small", "span", "strong", "sub", "sup", "time", "u", "var", "wbr", "area", "audio", "img", "map", "track", "video", "embed", "iframe", "object", "picture", "portal", "source", "svg", "math", "canvas", "noscript", "script", "del", "ins", "caption", "col", "colgroup", "table", "tbody", "td", "tfoot", "th", "thead", "tr", "button", "datalist", "fieldset", "form", "input", "label", "legend", "meter", "optgroup", "option", "output", "progress", "select", "textarea", "details", "dialog", "summary", "slot", "template", "acronym", "applet", "basefont", "bgsound", "big", "blink", "center", "content", "dir", "font", "frame", "frameset", "hgroup", "image", "keygen", "marquee", "menuitem", "nobr", "noembed", "noframes", "param", "plaintext", "rb", "rtc", "shadow", "spacer", "strike", "tt", "xmp"]);
|
|
@@ -6646,7 +6650,7 @@ exports.insertion = (0, combinator_1.lazy)(() => (0, combinator_1.surround)((0,
|
|
|
6646
6650
|
Object.defineProperty(exports, "__esModule", ({
|
|
6647
6651
|
value: true
|
|
6648
6652
|
}));
|
|
6649
|
-
exports.
|
|
6653
|
+
exports.resolve = exports.option = exports.uri = exports.textlink = exports.link = void 0;
|
|
6650
6654
|
|
|
6651
6655
|
const global_1 = __webpack_require__(4128);
|
|
6652
6656
|
|
|
@@ -6676,9 +6680,7 @@ const optspec = {
|
|
|
6676
6680
|
Object.setPrototypeOf(optspec, null);
|
|
6677
6681
|
exports.link = (0, combinator_1.lazy)(() => (0, combinator_1.validate)(['[', '{'], (0, combinator_1.bind)((0, combinator_1.constraint)(4
|
|
6678
6682
|
/* State.link */
|
|
6679
|
-
, false, (0, combinator_1.
|
|
6680
|
-
/* Syntax.link */
|
|
6681
|
-
, 2, 10, (0, combinator_1.fmap)((0, combinator_1.subsequence)([(0, combinator_1.state)(4
|
|
6683
|
+
, false, (0, combinator_1.creation)(10, (0, combinator_1.fmap)((0, combinator_1.subsequence)([(0, combinator_1.state)(4
|
|
6682
6684
|
/* State.link */
|
|
6683
6685
|
, (0, combinator_1.dup)((0, combinator_1.union)([(0, combinator_1.surround)('[', inline_1.media, ']'), (0, combinator_1.surround)('[', inline_1.shortmedia, ']'), (0, combinator_1.surround)('[', (0, combinator_1.state)(64
|
|
6684
6686
|
/* State.annotation */
|
|
@@ -6692,7 +6694,9 @@ exports.link = (0, combinator_1.lazy)(() => (0, combinator_1.validate)(['[', '{'
|
|
|
6692
6694
|
/* State.media */
|
|
6693
6695
|
| 1
|
|
6694
6696
|
/* State.autolink */
|
|
6695
|
-
, (0, combinator_1.
|
|
6697
|
+
, (0, combinator_1.syntax)(256
|
|
6698
|
+
/* Syntax.link */
|
|
6699
|
+
, 2, 0, (0, combinator_1.some)(inline_1.inline, ']', [[/^\\?\n/, 9], [']', 2]]))), ']', true)]))), (0, combinator_1.dup)((0, combinator_1.surround)(/^{(?![{}])/, (0, combinator_1.inits)([exports.uri, (0, combinator_1.some)(exports.option)]), /^[^\S\n]*}/))], nodes => nodes[0][0] !== ''), ([as, bs = []]) => bs[0] === '\r' && bs.shift() ? [as, bs] : as[0] === '\r' && as.shift() ? [[], as] : [as, []]))), ([content, params], rest, context) => {
|
|
6696
6700
|
if (content[0] === '') return [content, rest];
|
|
6697
6701
|
if (params.length === 0) return;
|
|
6698
6702
|
if (content.length !== 0 && (0, visibility_1.trimNode)(content).length === 0) return;
|
|
@@ -6705,7 +6709,7 @@ exports.link = (0, combinator_1.lazy)(() => (0, combinator_1.validate)(['[', '{'
|
|
|
6705
6709
|
|
|
6706
6710
|
const INSECURE_URI = params.shift();
|
|
6707
6711
|
const el = elem(INSECURE_URI, (0, dom_1.defrag)(content), new url_1.ReadonlyURL(resolve(INSECURE_URI, context.host ?? global_1.location, context.url ?? context.host ?? global_1.location), context.host?.href || global_1.location.href), context.host?.origin || global_1.location.origin);
|
|
6708
|
-
if (el.
|
|
6712
|
+
if (el.className === 'invalid') return [[el], rest];
|
|
6709
6713
|
return [[(0, dom_1.define)(el, (0, html_1.attributes)('link', [], optspec, params))], rest];
|
|
6710
6714
|
})));
|
|
6711
6715
|
exports.textlink = (0, combinator_1.lazy)(() => (0, combinator_1.validate)(['[', '{'], (0, combinator_1.bind)((0, combinator_1.creation)(10, (0, combinator_1.precedence)(2, (0, combinator_1.reverse)((0, combinator_1.tails)([(0, combinator_1.dup)((0, combinator_1.surround)('[', (0, combinator_1.some)((0, combinator_1.union)([source_1.unescsource]), ']'), ']')), (0, combinator_1.dup)((0, combinator_1.surround)(/^{(?![{}])/, (0, combinator_1.inits)([exports.uri, (0, combinator_1.some)(exports.option)]), /^[^\S\n]*}/))])))), ([params, content = []], rest, context) => {
|
|
@@ -6792,22 +6796,6 @@ function decode(uri) {
|
|
|
6792
6796
|
}
|
|
6793
6797
|
}
|
|
6794
6798
|
|
|
6795
|
-
function optimize(opener, ns, rest, next) {
|
|
6796
|
-
if (next[+(next[0] === '\\')] === '\n') return;
|
|
6797
|
-
let count = 0;
|
|
6798
|
-
|
|
6799
|
-
for (let i = 0; i < ns.length - 1; i += 2) {
|
|
6800
|
-
const fst = ns[i];
|
|
6801
|
-
const snd = ns[i + 1];
|
|
6802
|
-
if (fst !== '' || snd[0] !== opener[0]) break;
|
|
6803
|
-
count += snd.length;
|
|
6804
|
-
}
|
|
6805
|
-
|
|
6806
|
-
return [['', opener[0].repeat(opener.length + count)], rest.slice(count)];
|
|
6807
|
-
}
|
|
6808
|
-
|
|
6809
|
-
exports.optimize = optimize;
|
|
6810
|
-
|
|
6811
6799
|
/***/ }),
|
|
6812
6800
|
|
|
6813
6801
|
/***/ 2480:
|
|
@@ -7003,8 +6991,6 @@ const combinator_1 = __webpack_require__(2087);
|
|
|
7003
6991
|
|
|
7004
6992
|
const inline_1 = __webpack_require__(1160);
|
|
7005
6993
|
|
|
7006
|
-
const link_1 = __webpack_require__(9628);
|
|
7007
|
-
|
|
7008
6994
|
const source_1 = __webpack_require__(6743);
|
|
7009
6995
|
|
|
7010
6996
|
const visibility_1 = __webpack_require__(7618);
|
|
@@ -7015,17 +7001,17 @@ const dom_1 = __webpack_require__(3252);
|
|
|
7015
7001
|
|
|
7016
7002
|
exports.reference = (0, combinator_1.lazy)(() => (0, combinator_1.surround)('[[', (0, combinator_1.constraint)(32
|
|
7017
7003
|
/* State.reference */
|
|
7018
|
-
, false, (0, combinator_1.
|
|
7019
|
-
/* Syntax.reference */
|
|
7020
|
-
, 6, 1, (0, combinator_1.state)(64
|
|
7004
|
+
, false, (0, combinator_1.state)(64
|
|
7021
7005
|
/* State.annotation */
|
|
7022
7006
|
| 32
|
|
7023
7007
|
/* State.reference */
|
|
7024
7008
|
| 2
|
|
7025
7009
|
/* State.media */
|
|
7026
|
-
, (0,
|
|
7010
|
+
, (0, combinator_1.syntax)(4096
|
|
7011
|
+
/* Syntax.reference */
|
|
7012
|
+
, 6, 1, (0, visibility_1.startLoose)((0, combinator_1.context)({
|
|
7027
7013
|
delimiters: global_1.undefined
|
|
7028
|
-
}, (0, combinator_1.subsequence)([abbr, (0, combinator_1.open)((0, source_1.stropt)(/^(?=\^)/), (0, combinator_1.some)(inline_1.inline, ']', [[/^\\?\n/, 9], [']', 2], [']]', 6]])), (0, combinator_1.some)(inline_1.inline, ']', [[/^\\?\n/, 9], [']', 2], [']]', 6]])])), ']')))), ']]', false, ([, ns], rest) => [[(0, dom_1.html)('sup', attributes(ns), [(0, dom_1.html)('span', (0, visibility_1.trimNode)((0, dom_1.defrag)(ns)))])], rest]
|
|
7014
|
+
}, (0, combinator_1.subsequence)([abbr, (0, combinator_1.open)((0, source_1.stropt)(/^(?=\^)/), (0, combinator_1.some)(inline_1.inline, ']', [[/^\\?\n/, 9], [']', 2], [']]', 6]])), (0, combinator_1.some)(inline_1.inline, ']', [[/^\\?\n/, 9], [']', 2], [']]', 6]])])), ']')))), ']]', false, ([, ns], rest) => [[(0, dom_1.html)('sup', attributes(ns), [(0, dom_1.html)('span', (0, visibility_1.trimNode)((0, dom_1.defrag)(ns)))])], rest]));
|
|
7029
7015
|
const abbr = (0, combinator_1.creation)((0, combinator_1.bind)((0, combinator_1.surround)('^', (0, combinator_1.union)([(0, source_1.str)(/^(?![0-9]+\s?[|\]])[0-9A-Za-z]+(?:(?:-|(?=\W)(?!'\d)'?(?!\.\d)\.?(?!,\S),? ?)[0-9A-Za-z]+)*(?:-|'?\.?,? ?)?/)]), /^\|?(?=]])|^\|[^\S\n]*/), ([source], rest) => [[(0, dom_1.html)('abbr', source)], rest.replace(visibility_1.regBlankStart, '')]));
|
|
7030
7016
|
|
|
7031
7017
|
function attributes(ns) {
|
|
@@ -7214,8 +7200,6 @@ const global_1 = __webpack_require__(4128);
|
|
|
7214
7200
|
|
|
7215
7201
|
const combinator_1 = __webpack_require__(2087);
|
|
7216
7202
|
|
|
7217
|
-
const link_1 = __webpack_require__(9628);
|
|
7218
|
-
|
|
7219
7203
|
const source_1 = __webpack_require__(6743);
|
|
7220
7204
|
|
|
7221
7205
|
const dom_1 = __webpack_require__(3252);
|
|
@@ -7226,7 +7210,7 @@ exports.template = (0, combinator_1.lazy)(() => (0, combinator_1.surround)('{{',
|
|
|
7226
7210
|
/* Syntax.none */
|
|
7227
7211
|
, 2, 1, (0, combinator_1.some)((0, combinator_1.union)([bracket, source_1.escsource]), '}')), '}}', true, ([, ns = []], rest) => [[(0, dom_1.html)('span', {
|
|
7228
7212
|
class: 'template'
|
|
7229
|
-
}, `{{${ns.join('').replace(/\x1B/g, '')}}}`)], rest]
|
|
7213
|
+
}, `{{${ns.join('').replace(/\x1B/g, '')}}}`)], rest]));
|
|
7230
7214
|
const bracket = (0, combinator_1.lazy)(() => (0, combinator_1.creation)((0, combinator_1.union)([(0, combinator_1.surround)((0, source_1.str)('('), (0, combinator_1.some)((0, combinator_1.union)([bracket, source_1.escsource]), ')'), (0, source_1.str)(')'), true, global_1.undefined, ([as, bs = []], rest) => [(0, array_1.unshift)(as, bs), rest]), (0, combinator_1.surround)((0, source_1.str)('['), (0, combinator_1.some)((0, combinator_1.union)([bracket, source_1.escsource]), ']'), (0, source_1.str)(']'), true, global_1.undefined, ([as, bs = []], rest) => [(0, array_1.unshift)(as, bs), rest]), (0, combinator_1.surround)((0, source_1.str)('{'), (0, combinator_1.some)((0, combinator_1.union)([bracket, source_1.escsource]), '}'), (0, source_1.str)('}'), true, global_1.undefined, ([as, bs = []], rest) => [(0, array_1.unshift)(as, bs), rest]), (0, combinator_1.surround)((0, source_1.str)('"'), (0, combinator_1.precedence)(8, (0, combinator_1.some)(source_1.escsource, /^"|^\\?\n/)), (0, source_1.str)('"'), true)])));
|
|
7231
7215
|
|
|
7232
7216
|
/***/ }),
|
package/markdown.d.ts
CHANGED
|
@@ -963,15 +963,15 @@ export namespace MarkdownParser {
|
|
|
963
963
|
// <bdi>abc</bdi>
|
|
964
964
|
Inline<'html'>,
|
|
965
965
|
Parser<HTMLElement | string, Context, [
|
|
966
|
-
HTMLParser.
|
|
967
|
-
HTMLParser.
|
|
966
|
+
HTMLParser.VoidTagParser,
|
|
967
|
+
HTMLParser.VoidTagParser,
|
|
968
968
|
HTMLParser.TagParser,
|
|
969
969
|
HTMLParser.TagParser,
|
|
970
970
|
]> {
|
|
971
971
|
}
|
|
972
972
|
export namespace HTMLParser {
|
|
973
|
-
export interface
|
|
974
|
-
Inline<'html/
|
|
973
|
+
export interface VoidTagParser extends
|
|
974
|
+
Inline<'html/voidtag'>,
|
|
975
975
|
Parser<HTMLElement | string, Context, [
|
|
976
976
|
AttributeParser,
|
|
977
977
|
]> {
|
package/package.json
CHANGED
|
@@ -57,12 +57,15 @@ export class Delimiters {
|
|
|
57
57
|
public match(source: string, precedence = 1): boolean {
|
|
58
58
|
const { matchers } = this;
|
|
59
59
|
for (let i = 0; i < matchers.length; ++i) {
|
|
60
|
-
|
|
60
|
+
const matcher = matchers[i];
|
|
61
|
+
if (precedence >= matcher[2]) continue;
|
|
62
|
+
switch (matcher[3](source)) {
|
|
61
63
|
case true:
|
|
62
|
-
|
|
63
|
-
continue;
|
|
64
|
+
return true;
|
|
64
65
|
case false:
|
|
65
66
|
return false;
|
|
67
|
+
default:
|
|
68
|
+
continue;
|
|
66
69
|
}
|
|
67
70
|
}
|
|
68
71
|
return false;
|
|
@@ -89,6 +89,7 @@ export function creation<P extends Parser<unknown>>(parser: P): P;
|
|
|
89
89
|
export function creation<P extends Parser<unknown>>(cost: number, parser: P): P;
|
|
90
90
|
export function creation(cost: number | Parser<unknown>, parser?: Parser<unknown>): Parser<unknown> {
|
|
91
91
|
if (typeof cost === 'function') return creation(1, cost);
|
|
92
|
+
if (cost === 0) return parser!;
|
|
92
93
|
assert(cost >= 0);
|
|
93
94
|
return (source, context) => {
|
|
94
95
|
const { resources = { clock: 1, recursion: 1 } } = context;
|
|
@@ -228,7 +228,7 @@ function format(rows: Tree<RowParser>[]): HTMLTableSectionElement[] {
|
|
|
228
228
|
: cells[j];
|
|
229
229
|
const isHeadCell = cell.tagName === 'TH';
|
|
230
230
|
heads |= BigInt(isHeadCell) << jn;
|
|
231
|
-
highlights |= BigInt(cell.
|
|
231
|
+
highlights |= BigInt(cell.className === 'highlight') << jn;
|
|
232
232
|
hasDataCell ||= !isHeadCell;
|
|
233
233
|
if (isHeadCell && !hasDataCell) {
|
|
234
234
|
lHeadCellIdx = jn;
|
|
@@ -115,7 +115,7 @@ function initial(type: string): RegExp {
|
|
|
115
115
|
}
|
|
116
116
|
|
|
117
117
|
function format(el: HTMLOListElement, type: string, form: string): HTMLOListElement {
|
|
118
|
-
if (el.firstElementChild?.firstElementChild?.
|
|
118
|
+
if (el.firstElementChild?.firstElementChild?.className === 'checkbox') {
|
|
119
119
|
el.setAttribute('class', 'checklist');
|
|
120
120
|
}
|
|
121
121
|
define(el, {
|
|
@@ -57,7 +57,7 @@ const qblock: ReplyParser.QuoteParser.BlockParser = (source, context) => {
|
|
|
57
57
|
++i;
|
|
58
58
|
continue;
|
|
59
59
|
}
|
|
60
|
-
if (child.
|
|
60
|
+
if (child.className === 'cite' || child.classList.contains('quote')) {
|
|
61
61
|
context.resources && (context.resources.clock -= child.childNodes.length);
|
|
62
62
|
nodes.splice(i, 1, ...child.childNodes as NodeListOf<HTMLElement>);
|
|
63
63
|
--i;
|
|
@@ -61,7 +61,7 @@ const data: CellParser.DataParser = creation(fmap(
|
|
|
61
61
|
ns => [html('td', trimNode(defrag(ns)))]));
|
|
62
62
|
|
|
63
63
|
function format(rows: HTMLTableRowElement[]): HTMLTableRowElement[] {
|
|
64
|
-
const aligns = rows[0].
|
|
64
|
+
const aligns = rows[0].className === 'invalid'
|
|
65
65
|
? []
|
|
66
66
|
: duffReduce(rows.shift()!.children, (acc, el) => push(acc, [el.textContent!]), [] as string[]);
|
|
67
67
|
for (let i = 0; i < rows.length; ++i) {
|
|
@@ -41,7 +41,7 @@ export function fillFirstLine(ns: (HTMLElement | string)[]): (HTMLElement | stri
|
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
function format(el: HTMLUListElement): HTMLUListElement {
|
|
44
|
-
if (el.firstElementChild?.firstElementChild?.
|
|
44
|
+
if (el.firstElementChild?.firstElementChild?.className === 'checkbox') {
|
|
45
45
|
el.setAttribute('class', 'checklist');
|
|
46
46
|
}
|
|
47
47
|
return el;
|
|
@@ -14,7 +14,7 @@ describe('Unit: parser/inline/annotation', () => {
|
|
|
14
14
|
assert.deepStrictEqual(inspect(parser('(())')), undefined);
|
|
15
15
|
assert.deepStrictEqual(inspect(parser('(()))')), undefined);
|
|
16
16
|
assert.deepStrictEqual(inspect(parser('(( ))')), undefined);
|
|
17
|
-
assert.deepStrictEqual(inspect(parser('(( (a')),
|
|
17
|
+
assert.deepStrictEqual(inspect(parser('(( (a')), undefined);
|
|
18
18
|
assert.deepStrictEqual(inspect(parser('((\n))')), undefined);
|
|
19
19
|
assert.deepStrictEqual(inspect(parser('((\na))')), undefined);
|
|
20
20
|
assert.deepStrictEqual(inspect(parser('((\\\na))')), undefined);
|
|
@@ -2,7 +2,6 @@ import { undefined } from 'spica/global';
|
|
|
2
2
|
import { AnnotationParser } from '../inline';
|
|
3
3
|
import { union, some, context, syntax, constraint, state, surround, lazy } from '../../combinator';
|
|
4
4
|
import { inline } from '../inline';
|
|
5
|
-
import { optimize } from './link';
|
|
6
5
|
import { Syntax, State } from '../context';
|
|
7
6
|
import { startLoose, trimNode } from '../visibility';
|
|
8
7
|
import { html, defrag } from 'typed-dom/dom';
|
|
@@ -10,12 +9,11 @@ import { html, defrag } from 'typed-dom/dom';
|
|
|
10
9
|
export const annotation: AnnotationParser = lazy(() => surround(
|
|
11
10
|
'((',
|
|
12
11
|
constraint(State.annotation, false,
|
|
13
|
-
syntax(Syntax.annotation, 6, 1,
|
|
14
12
|
state(State.annotation | State.media,
|
|
13
|
+
syntax(Syntax.annotation, 6, 1,
|
|
15
14
|
startLoose(
|
|
16
15
|
context({ delimiters: undefined },
|
|
17
16
|
some(union([inline]), ')', [[/^\\?\n/, 9], [')', 2], ['))', 6]])), ')')))),
|
|
18
17
|
'))',
|
|
19
18
|
false,
|
|
20
|
-
([, ns], rest) => [[html('sup', { class: 'annotation' }, [html('span', trimNode(defrag(ns)))])], rest]
|
|
21
|
-
([, ns, rest], next) => next[0] === ')' ? undefined : optimize('((', ns, rest, next)));
|
|
19
|
+
([, ns], rest) => [[html('sup', { class: 'annotation' }, [html('span', trimNode(defrag(ns)))])], rest]));
|
|
@@ -75,7 +75,7 @@ describe('Unit: parser/inline/bracket', () => {
|
|
|
75
75
|
assert.deepStrictEqual(inspect(parser('"a')), [['"', 'a'], '']);
|
|
76
76
|
assert.deepStrictEqual(inspect(parser('"a"')), [['"', 'a', '"'], '']);
|
|
77
77
|
assert.deepStrictEqual(inspect(parser('"(")"')), [['"', '', '(', '"'], ')"']);
|
|
78
|
-
assert.deepStrictEqual(inspect(parser('"(("')), [['"', '', '((', '"'], '']);
|
|
78
|
+
assert.deepStrictEqual(inspect(parser('"(("')), [['"', '', '(', '', '(', '"'], '']);
|
|
79
79
|
assert.deepStrictEqual(inspect(parser('"(\\")"')), [['"', '<span class="paren">(")</span>', '"'], '']);
|
|
80
80
|
assert.deepStrictEqual(inspect(parser('"(\n)"')), [['"', '<span class="paren">(<br>)</span>', '"'], '']);
|
|
81
81
|
assert.deepStrictEqual(inspect(parser('"(\\\n)"')), [['"', '<span class="paren">(<span class="linebreak"> </span>)</span>', '"'], '']);
|
|
@@ -13,8 +13,8 @@ import IndexParser = ExtensionParser.IndexParser;
|
|
|
13
13
|
export const index: IndexParser = lazy(() => validate('[#', fmap(indexee(surround(
|
|
14
14
|
'[#',
|
|
15
15
|
constraint(State.index, false,
|
|
16
|
-
syntax(Syntax.index, 2, 1,
|
|
17
16
|
state(State.annotation | State.reference | State.index | State.label | State.link | State.media | State.autolink,
|
|
17
|
+
syntax(Syntax.index, 2, 1,
|
|
18
18
|
startTight(
|
|
19
19
|
open(stropt(/^\|?/), trimBlankEnd(some(union([
|
|
20
20
|
signature,
|
|
@@ -7,7 +7,7 @@ import { startTight } from '../../visibility';
|
|
|
7
7
|
import { html, defrag } from 'typed-dom/dom';
|
|
8
8
|
import { unshift } from 'spica/array';
|
|
9
9
|
|
|
10
|
-
// Don't use the symbols already used:
|
|
10
|
+
// Don't use the symbols already used: !#$%@&*+~=
|
|
11
11
|
|
|
12
12
|
// All syntax surrounded by square brackets shouldn't contain line breaks.
|
|
13
13
|
|
|
@@ -21,10 +21,10 @@ describe('Unit: parser/inline/html', () => {
|
|
|
21
21
|
it('invalid', () => {
|
|
22
22
|
assert.deepStrictEqual(inspect(parser('')), undefined);
|
|
23
23
|
assert.deepStrictEqual(inspect(parser('<0>')), undefined);
|
|
24
|
-
assert.deepStrictEqual(inspect(parser('<aT>')),
|
|
24
|
+
assert.deepStrictEqual(inspect(parser('<aT>')), [['<span class="invalid"><aT></span>'], '']);
|
|
25
25
|
assert.deepStrictEqual(inspect(parser('<a,b>')), undefined);
|
|
26
26
|
assert.deepStrictEqual(inspect(parser('<a, b>')), undefined);
|
|
27
|
-
assert.deepStrictEqual(inspect(parser('<T>')),
|
|
27
|
+
assert.deepStrictEqual(inspect(parser('<T>')), [['<span class="invalid"><T></span>'], '']);
|
|
28
28
|
assert.deepStrictEqual(inspect(parser('<bdi>')), [['<span class="invalid"><bdi></span>'], '']);
|
|
29
29
|
assert.deepStrictEqual(inspect(parser('<bdi>z')), [['<span class="invalid"><bdi>z</span>'], '']);
|
|
30
30
|
assert.deepStrictEqual(inspect(parser('<bdi></bdi>')), [['<span class="invalid"><bdi></bdi></span>'], '']);
|
|
@@ -39,8 +39,8 @@ describe('Unit: parser/inline/html', () => {
|
|
|
39
39
|
assert.deepStrictEqual(inspect(parser('<bdi>\\\na</bdi>')), [['<span class="invalid"><bdi><span class="linebreak"> </span>a</bdi></span>'], '']);
|
|
40
40
|
assert.deepStrictEqual(inspect(parser('<bdi>a')), [['<span class="invalid"><bdi>a</span>'], '']);
|
|
41
41
|
assert.deepStrictEqual(inspect(parser('<bdi>a</BDO>')), [['<span class="invalid"><bdi>a</BDO></span>'], '']);
|
|
42
|
-
assert.deepStrictEqual(inspect(parser('<BDI>a</BDI>')),
|
|
43
|
-
assert.deepStrictEqual(inspect(parser('<BDI>a</bdo>')),
|
|
42
|
+
assert.deepStrictEqual(inspect(parser('<BDI>a</BDI>')), [['<span class="invalid"><BDI>a</BDI></span>'], '']);
|
|
43
|
+
assert.deepStrictEqual(inspect(parser('<BDI>a</bdo>')), [['<span class="invalid"><BDI>a</bdo></span>'], '']);
|
|
44
44
|
assert.deepStrictEqual(inspect(parser('</bdi>')), undefined);
|
|
45
45
|
assert.deepStrictEqual(inspect(parser('<bdi/>')), undefined);
|
|
46
46
|
assert.deepStrictEqual(inspect(parser('<b><b><b>a</b></b></b>')), [['<span class="invalid"><b><span class="invalid"><b><span class="invalid"><b>a</b></span></b></span></b></span>'], '']);
|
|
@@ -87,9 +87,9 @@ describe('Unit: parser/inline/html', () => {
|
|
|
87
87
|
assert.deepStrictEqual(inspect(parser('<a>')), [['<span class="invalid"><a></span>'], '']);
|
|
88
88
|
assert.deepStrictEqual(inspect(parser('<bdi><a>a</a></bdi>')), [['<bdi><span class="invalid"><a>a</a></span></bdi>'], '']);
|
|
89
89
|
assert.deepStrictEqual(inspect(parser('<bdi>a<a>b</a>c</bdi>')), [['<bdi>a<span class="invalid"><a>b</a></span>c</bdi>'], '']);
|
|
90
|
-
assert.deepStrictEqual(inspect(parser('<img>')), [['<img'], '
|
|
91
|
-
assert.deepStrictEqual(inspect(parser('<bdi><img></bdi>')), [['<bdi><img></bdi>'], '']);
|
|
92
|
-
assert.deepStrictEqual(inspect(parser('<img />')),
|
|
90
|
+
assert.deepStrictEqual(inspect(parser('<img>')), [['<span class="invalid"><img></span>'], '']);
|
|
91
|
+
assert.deepStrictEqual(inspect(parser('<bdi><img></bdi>')), [['<bdi><span class="invalid"><img></span></bdi>'], '']);
|
|
92
|
+
assert.deepStrictEqual(inspect(parser('<img />')), undefined);
|
|
93
93
|
assert.deepStrictEqual(inspect(parser('<bdi><img /></bdi>')), [['<bdi><img /></bdi>'], '']);
|
|
94
94
|
});
|
|
95
95
|
|
|
@@ -100,15 +100,15 @@ describe('Unit: parser/inline/html', () => {
|
|
|
100
100
|
assert.deepStrictEqual(inspect(parser('<bdi >a</bdi>')), [['<bdi>a</bdi>'], '']);
|
|
101
101
|
assert.deepStrictEqual(inspect(parser('<bdi __proto__>a</bdi>')), undefined);
|
|
102
102
|
assert.deepStrictEqual(inspect(parser('<bdi constructor>a</bdi>')), [['<span class="invalid"><bdi constructor>a</bdi></span>'], '']);
|
|
103
|
-
assert.deepStrictEqual(inspect(parser('<bdi toString>a</bdi>')),
|
|
104
|
-
assert.deepStrictEqual(inspect(parser('<bdi X>a</bdi>')),
|
|
103
|
+
assert.deepStrictEqual(inspect(parser('<bdi toString>a</bdi>')), [['<span class="invalid"><bdi toString>a</bdi></span>'], '']);
|
|
104
|
+
assert.deepStrictEqual(inspect(parser('<bdi X>a</bdi>')), [['<span class="invalid"><bdi X>a</bdi></span>'], '']);
|
|
105
105
|
assert.deepStrictEqual(inspect(parser('<bdi x>a</bdi>')), [['<span class="invalid"><bdi x>a</bdi></span>'], '']);
|
|
106
106
|
assert.deepStrictEqual(inspect(parser('<bdo>a</bdo>')), [['<span class="invalid"><bdo>a</bdo></span>'], '']);
|
|
107
107
|
assert.deepStrictEqual(inspect(parser('<bdo >a</bdo>')), [['<span class="invalid"><bdo >a</bdo></span>'], '']);
|
|
108
108
|
assert.deepStrictEqual(inspect(parser('<bdo __proto__>a</bdo>')), undefined);
|
|
109
109
|
assert.deepStrictEqual(inspect(parser('<bdo constructor>a</bdo>')), [['<span class="invalid"><bdo constructor>a</bdo></span>'], '']);
|
|
110
|
-
assert.deepStrictEqual(inspect(parser('<bdo toString>a</bdo>')),
|
|
111
|
-
assert.deepStrictEqual(inspect(parser('<bdo X>a</bdo>')),
|
|
110
|
+
assert.deepStrictEqual(inspect(parser('<bdo toString>a</bdo>')), [['<span class="invalid"><bdo toString>a</bdo></span>'], '']);
|
|
111
|
+
assert.deepStrictEqual(inspect(parser('<bdo X>a</bdo>')), [['<span class="invalid"><bdo X>a</bdo></span>'], '']);
|
|
112
112
|
assert.deepStrictEqual(inspect(parser('<bdo x>a</bdo>')), [['<span class="invalid"><bdo x>a</bdo></span>'], '']);
|
|
113
113
|
assert.deepStrictEqual(inspect(parser('<bdo dir>a</bdo>')), [['<span class="invalid"><bdo dir>a</bdo></span>'], '']);
|
|
114
114
|
assert.deepStrictEqual(inspect(parser('<bdo dir=>a</bdo>')), undefined);
|
|
@@ -116,16 +116,16 @@ describe('Unit: parser/inline/html', () => {
|
|
|
116
116
|
assert.deepStrictEqual(inspect(parser('<bdo dir=">a</bdo>')), undefined);
|
|
117
117
|
assert.deepStrictEqual(inspect(parser('<bdo dir="">a</bdo>')), [['<span class="invalid"><bdo dir="">a</bdo></span>'], '']);
|
|
118
118
|
assert.deepStrictEqual(inspect(parser('<bdo dir="rtl" dir="rtl">a</bdo>')), [['<span class="invalid"><bdo dir="rtl" dir="rtl">a</bdo></span>'], '']);
|
|
119
|
-
assert.deepStrictEqual(inspect(parser('<bdo diR="rtl">a</bdo>')),
|
|
119
|
+
assert.deepStrictEqual(inspect(parser('<bdo diR="rtl">a</bdo>')), [['<span class="invalid"><bdo diR="rtl">a</bdo></span>'], '']);
|
|
120
120
|
assert.deepStrictEqual(inspect(parser('<bdo dir="rtl">a</bdo>')), [['<bdo dir="rtl">a</bdo>'], '']);
|
|
121
121
|
assert.deepStrictEqual(inspect(parser('<bdo dir="rtl" >a</bdo>')), [['<bdo dir="rtl">a</bdo>'], '']);
|
|
122
122
|
assert.deepStrictEqual(inspect(parser('<bdo dir="rtl" >a</bdo>')), [['<bdo dir="rtl">a</bdo>'], '']);
|
|
123
123
|
assert.deepStrictEqual(inspect(parser('<bdo dir="rtl">a</bdo>')), [['<bdo dir="rtl">a</bdo>'], '']);
|
|
124
124
|
assert.deepStrictEqual(inspect(parser('<wbr\n>')), undefined);
|
|
125
125
|
assert.deepStrictEqual(inspect(parser('<wbr >')), [['<wbr>'], '']);
|
|
126
|
-
assert.deepStrictEqual(inspect(parser('<wbr constructor>')), [['<wbr'], '
|
|
127
|
-
assert.deepStrictEqual(inspect(parser('<wbr X>')), [['<wbr'], '
|
|
128
|
-
assert.deepStrictEqual(inspect(parser('<wbr x>')), [['<wbr'], '
|
|
126
|
+
assert.deepStrictEqual(inspect(parser('<wbr constructor>')), [['<span class="invalid"><wbr constructor></span>'], '']);
|
|
127
|
+
assert.deepStrictEqual(inspect(parser('<wbr X>')), [['<span class="invalid"><wbr X></span>'], '']);
|
|
128
|
+
assert.deepStrictEqual(inspect(parser('<wbr x>')), [['<span class="invalid"><wbr x></span>'], '']);
|
|
129
129
|
});
|
|
130
130
|
|
|
131
131
|
});
|
|
@@ -19,14 +19,15 @@ const attrspecs = {
|
|
|
19
19
|
Object.setPrototypeOf(attrspecs, null);
|
|
20
20
|
Object.values(attrspecs).forEach(o => Object.setPrototypeOf(o, null));
|
|
21
21
|
|
|
22
|
-
export const html: HTMLParser = lazy(() => validate('<', validate(/^<[a-z]+(?=[^\S\n]|>)
|
|
22
|
+
export const html: HTMLParser = lazy(() => validate('<', validate(/^<[a-z]+(?=[^\S\n]|>)/i, syntax(Syntax.none, 5, 1, union([
|
|
23
23
|
focus(
|
|
24
|
-
/^<wbr[^\S\n]
|
|
24
|
+
/^<wbr[^\S\n]*>/i,
|
|
25
25
|
() => [[h('wbr')], '']),
|
|
26
|
-
|
|
26
|
+
surround(
|
|
27
27
|
// https://html.spec.whatwg.org/multipage/syntax.html#void-elements
|
|
28
|
-
/^<(?:area|base|br|col|embed|hr|img|input|link|meta|source|track|wbr)(?=[^\S\n]|>)
|
|
29
|
-
|
|
28
|
+
str(/^<(?:area|base|br|col|embed|hr|img|input|link|meta|source|track|wbr)(?=[^\S\n]|>)/i), some(union([attribute])), str(/^[^\S\n]*>/), true,
|
|
29
|
+
([as, bs = [], cs], rest) =>
|
|
30
|
+
[[elem(as[0].slice(1), push(unshift(as, bs), cs), [], [])], rest]),
|
|
30
31
|
match(
|
|
31
32
|
new RegExp(String.raw`^<(${TAGS.join('|')})(?=[^\S\n]|>)`),
|
|
32
33
|
memoize(
|
|
@@ -44,7 +45,7 @@ export const html: HTMLParser = lazy(() => validate('<', validate(/^<[a-z]+(?=[^
|
|
|
44
45
|
[[elem(tag, as, bs, [])], rest]),
|
|
45
46
|
([, tag]) => TAGS.indexOf(tag), [])),
|
|
46
47
|
match(
|
|
47
|
-
/^<([a-z]+)(?=[^\S\n]|>)
|
|
48
|
+
/^<([a-z]+)(?=[^\S\n]|>)/i,
|
|
48
49
|
memoize(
|
|
49
50
|
([, tag]) =>
|
|
50
51
|
surround<HTMLParser.TagParser, string>(surround(
|
|
@@ -63,7 +64,7 @@ export const html: HTMLParser = lazy(() => validate('<', validate(/^<[a-z]+(?=[^
|
|
|
63
64
|
])))));
|
|
64
65
|
|
|
65
66
|
export const attribute: HTMLParser.AttributeParser = union([
|
|
66
|
-
str(/^[^\S\n]+[a-z]+(?:-[a-z]+)*(?:="(?:\\[^\n]|[^\\\n"])*")?(?=[^\S\n]|>)/),
|
|
67
|
+
str(/^[^\S\n]+[a-z]+(?:-[a-z]+)*(?:="(?:\\[^\n]|[^\\\n"])*")?(?=[^\S\n]|>)/i),
|
|
67
68
|
]);
|
|
68
69
|
|
|
69
70
|
// https://developer.mozilla.org/en-US/docs/Web/HTML/Element
|
|
@@ -45,7 +45,7 @@ describe('Unit: parser/inline/link', () => {
|
|
|
45
45
|
it('invalid', () => {
|
|
46
46
|
assert.deepStrictEqual(inspect(parser('')), undefined);
|
|
47
47
|
assert.deepStrictEqual(inspect(parser('{}')), undefined);
|
|
48
|
-
assert.deepStrictEqual(inspect(parser('[{b}')),
|
|
48
|
+
assert.deepStrictEqual(inspect(parser('[{b}')), undefined);
|
|
49
49
|
assert.deepStrictEqual(inspect(parser('[]')), undefined);
|
|
50
50
|
assert.deepStrictEqual(inspect(parser('[]{}')), undefined);
|
|
51
51
|
assert.deepStrictEqual(inspect(parser('[]{ }')), undefined);
|
|
@@ -65,7 +65,7 @@ describe('Unit: parser/inline/link', () => {
|
|
|
65
65
|
assert.deepStrictEqual(inspect(parser('[\\ ]{b}')), undefined);
|
|
66
66
|
assert.deepStrictEqual(inspect(parser('[\\\n]{b}')), undefined);
|
|
67
67
|
assert.deepStrictEqual(inspect(parser('[	]{b}')), undefined);
|
|
68
|
-
assert.deepStrictEqual(inspect(parser('[[]{b}')),
|
|
68
|
+
assert.deepStrictEqual(inspect(parser('[[]{b}')), undefined);
|
|
69
69
|
assert.deepStrictEqual(inspect(parser('[]]{b}')), undefined);
|
|
70
70
|
assert.deepStrictEqual(inspect(parser('[a]{}')), undefined);
|
|
71
71
|
assert.deepStrictEqual(inspect(parser('[a\nb]{b}')), undefined);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { undefined, location, encodeURI, decodeURI, Location } from 'spica/global';
|
|
2
2
|
import { LinkParser, TextLinkParser } from '../inline';
|
|
3
|
-
import {
|
|
3
|
+
import { eval, exec } from '../../combinator/data/parser';
|
|
4
4
|
import { union, inits, tails, subsequence, some, constraint, syntax, creation, precedence, state, validate, surround, open, dup, reverse, lazy, fmap, bind } from '../../combinator';
|
|
5
5
|
import { inline, media, shortmedia } from '../inline';
|
|
6
6
|
import { attributes } from './html';
|
|
@@ -19,7 +19,7 @@ Object.setPrototypeOf(optspec, null);
|
|
|
19
19
|
|
|
20
20
|
export const link: LinkParser = lazy(() => validate(['[', '{'], bind(
|
|
21
21
|
constraint(State.link, false,
|
|
22
|
-
|
|
22
|
+
creation(10,
|
|
23
23
|
fmap(subsequence([
|
|
24
24
|
state(State.link,
|
|
25
25
|
dup(union([
|
|
@@ -28,11 +28,10 @@ export const link: LinkParser = lazy(() => validate(['[', '{'], bind(
|
|
|
28
28
|
surround(
|
|
29
29
|
'[',
|
|
30
30
|
state(State.annotation | State.reference | State.index | State.label | State.media | State.autolink,
|
|
31
|
-
|
|
31
|
+
syntax(Syntax.link, 2, 0,
|
|
32
|
+
some(inline, ']', [[/^\\?\n/, 9], [']', 2]]))),
|
|
32
33
|
']',
|
|
33
|
-
true,
|
|
34
|
-
undefined,
|
|
35
|
-
([, ns = [], rest], next) => next[0] === ']' ? undefined : optimize('[', ns, rest, next)),
|
|
34
|
+
true),
|
|
36
35
|
]))),
|
|
37
36
|
dup(surround(/^{(?![{}])/, inits([uri, some(option)]), /^[^\S\n]*}/)),
|
|
38
37
|
], nodes => nodes[0][0] !== ''),
|
|
@@ -59,7 +58,7 @@ export const link: LinkParser = lazy(() => validate(['[', '{'], bind(
|
|
|
59
58
|
resolve(INSECURE_URI, context.host ?? location, context.url ?? context.host ?? location),
|
|
60
59
|
context.host?.href || location.href),
|
|
61
60
|
context.host?.origin || location.origin);
|
|
62
|
-
if (el.
|
|
61
|
+
if (el.className === 'invalid') return [[el], rest];
|
|
63
62
|
assert(el.classList.length === 0);
|
|
64
63
|
return [[define(el, attributes('link', [], optspec, params))], rest];
|
|
65
64
|
})));
|
|
@@ -85,7 +84,7 @@ export const textlink: TextLinkParser = lazy(() => validate(['[', '{'], bind(
|
|
|
85
84
|
resolve(INSECURE_URI, context.host ?? location, context.url ?? context.host ?? location),
|
|
86
85
|
context.host?.href || location.href),
|
|
87
86
|
context.host?.origin || location.origin);
|
|
88
|
-
assert(
|
|
87
|
+
assert(el.className !== 'invalid');
|
|
89
88
|
assert(el.classList.length === 0);
|
|
90
89
|
return [[define(el, attributes('link', [], optspec, params))], rest];
|
|
91
90
|
})));
|
|
@@ -191,16 +190,3 @@ function decode(uri: string): string {
|
|
|
191
190
|
return uri.replace(/\s+/g, encodeURI);
|
|
192
191
|
}
|
|
193
192
|
}
|
|
194
|
-
|
|
195
|
-
export function optimize(opener: string, ns: readonly (string | HTMLElement)[], rest: string, next: string): Result<string> {
|
|
196
|
-
if (next[+(next[0] === '\\')] === '\n') return;
|
|
197
|
-
let count = 0;
|
|
198
|
-
for (let i = 0; i < ns.length - 1; i += 2) {
|
|
199
|
-
const fst = ns[i];
|
|
200
|
-
const snd = ns[i + 1] as string;
|
|
201
|
-
assert(typeof snd === 'string');
|
|
202
|
-
if (fst !== '' || snd[0] !== opener[0]) break;
|
|
203
|
-
count += snd.length;
|
|
204
|
-
}
|
|
205
|
-
return [['', opener[0].repeat(opener.length + count)], rest.slice(count)];
|
|
206
|
-
}
|
|
@@ -14,7 +14,7 @@ describe('Unit: parser/inline/reference', () => {
|
|
|
14
14
|
assert.deepStrictEqual(inspect(parser('[[]]')), undefined);
|
|
15
15
|
assert.deepStrictEqual(inspect(parser('[[]]]')), undefined);
|
|
16
16
|
assert.deepStrictEqual(inspect(parser('[[ ]]')), undefined);
|
|
17
|
-
assert.deepStrictEqual(inspect(parser('[[ [a')),
|
|
17
|
+
assert.deepStrictEqual(inspect(parser('[[ [a')), undefined);
|
|
18
18
|
assert.deepStrictEqual(inspect(parser('[[\n]]')), undefined);
|
|
19
19
|
assert.deepStrictEqual(inspect(parser('[[\na]]')), undefined);
|
|
20
20
|
assert.deepStrictEqual(inspect(parser('[[\\\na]]')), undefined);
|
|
@@ -2,7 +2,6 @@ import { undefined } from 'spica/global';
|
|
|
2
2
|
import { ReferenceParser } from '../inline';
|
|
3
3
|
import { union, subsequence, some, context, syntax, creation, constraint, state, surround, open, lazy, bind } from '../../combinator';
|
|
4
4
|
import { inline } from '../inline';
|
|
5
|
-
import { optimize } from './link';
|
|
6
5
|
import { str, stropt } from '../source';
|
|
7
6
|
import { Syntax, State } from '../context';
|
|
8
7
|
import { regBlankStart, startLoose, trimNode } from '../visibility';
|
|
@@ -12,8 +11,8 @@ import { html, defrag } from 'typed-dom/dom';
|
|
|
12
11
|
export const reference: ReferenceParser = lazy(() => surround(
|
|
13
12
|
'[[',
|
|
14
13
|
constraint(State.reference, false,
|
|
15
|
-
syntax(Syntax.reference, 6, 1,
|
|
16
14
|
state(State.annotation | State.reference | State.media,
|
|
15
|
+
syntax(Syntax.reference, 6, 1,
|
|
17
16
|
startLoose(
|
|
18
17
|
context({ delimiters: undefined },
|
|
19
18
|
subsequence([
|
|
@@ -23,8 +22,7 @@ export const reference: ReferenceParser = lazy(() => surround(
|
|
|
23
22
|
])), ']')))),
|
|
24
23
|
']]',
|
|
25
24
|
false,
|
|
26
|
-
([, ns], rest) => [[html('sup', attributes(ns), [html('span', trimNode(defrag(ns)))])], rest]
|
|
27
|
-
([, ns, rest], next) => next[0] === ']' ? undefined : optimize('[[', ns, rest, next)));
|
|
25
|
+
([, ns], rest) => [[html('sup', attributes(ns), [html('span', trimNode(defrag(ns)))])], rest]));
|
|
28
26
|
|
|
29
27
|
const abbr: ReferenceParser.AbbrParser = creation(bind(surround(
|
|
30
28
|
'^',
|
|
@@ -10,7 +10,7 @@ describe('Unit: parser/inline/template', () => {
|
|
|
10
10
|
assert.deepStrictEqual(inspect(parser('')), undefined);
|
|
11
11
|
assert.deepStrictEqual(inspect(parser('{')), undefined);
|
|
12
12
|
assert.deepStrictEqual(inspect(parser('{}')), undefined);
|
|
13
|
-
assert.deepStrictEqual(inspect(parser('{{')),
|
|
13
|
+
assert.deepStrictEqual(inspect(parser('{{')), undefined);
|
|
14
14
|
assert.deepStrictEqual(inspect(parser('{{\\}}')), undefined);
|
|
15
15
|
assert.deepStrictEqual(inspect(parser('{{a}b}')), undefined);
|
|
16
16
|
assert.deepStrictEqual(inspect(parser('{{{a}}')), undefined);
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { undefined } from 'spica/global';
|
|
2
2
|
import { TemplateParser } from '../inline';
|
|
3
3
|
import { union, some, syntax, creation, precedence, surround, lazy } from '../../combinator';
|
|
4
|
-
import { optimize } from './link';
|
|
5
4
|
import { escsource, str } from '../source';
|
|
6
5
|
import { Syntax } from '../context';
|
|
7
6
|
import { html } from 'typed-dom/dom';
|
|
@@ -9,8 +8,7 @@ import { unshift } from 'spica/array';
|
|
|
9
8
|
|
|
10
9
|
export const template: TemplateParser = lazy(() => surround(
|
|
11
10
|
'{{', syntax(Syntax.none, 2, 1, some(union([bracket, escsource]), '}')), '}}', true,
|
|
12
|
-
([, ns = []], rest) => [[html('span', { class: 'template' }, `{{${ns.join('').replace(/\x1B/g, '')}}}`)], rest]
|
|
13
|
-
([, ns = [], rest], next) => next[0] === '}' ? undefined : optimize('{{', ns, rest, next)));
|
|
11
|
+
([, ns = []], rest) => [[html('span', { class: 'template' }, `{{${ns.join('').replace(/\x1B/g, '')}}}`)], rest]));
|
|
14
12
|
|
|
15
13
|
const bracket: TemplateParser.BracketParser = lazy(() => creation(union([
|
|
16
14
|
surround(str('('), some(union([bracket, escsource]), ')'), str(')'), true, undefined, ([as, bs = []], rest) => [unshift(as, bs), rest]),
|
|
@@ -143,23 +143,23 @@ describe('Unit: parser/inline', () => {
|
|
|
143
143
|
assert.deepStrictEqual(inspect(parser('Di$ney Micro$oft')), [['Di', '$', 'ney', ' ', 'Micro', '$', 'oft'], '']);
|
|
144
144
|
assert.deepStrictEqual(inspect(parser('Di$ney, Micro$oft')), [['Di', '$', 'ney', ',', ' ', 'Micro', '$', 'oft'], '']);
|
|
145
145
|
assert.deepStrictEqual(inspect(parser('(((a))')), [['', '(', '<sup class="annotation"><span>a</span></sup>'], '']);
|
|
146
|
-
assert.deepStrictEqual(inspect(parser('((((a))')), [['', '((', '<sup class="annotation"><span>a</span></sup>'], '']);
|
|
146
|
+
assert.deepStrictEqual(inspect(parser('((((a))')), [['', '(', '', '(', '<sup class="annotation"><span>a</span></sup>'], '']);
|
|
147
147
|
assert.deepStrictEqual(inspect(parser('((((a))))')), [['<sup class="annotation"><span><span class="paren">((a))</span></span></sup>'], '']);
|
|
148
148
|
assert.deepStrictEqual(inspect(parser('((<bdi>))')), [['<sup class="annotation"><span><span class="invalid"><bdi></span></span></sup>'], '']);
|
|
149
|
-
assert.deepStrictEqual(inspect(parser('((${))}$')), [['', '((', '<span class="math" translate="no" data-src="${))}$">${))}$</span>'], '']);
|
|
149
|
+
assert.deepStrictEqual(inspect(parser('((${))}$')), [['', '(', '', '(', '<span class="math" translate="no" data-src="${))}$">${))}$</span>'], '']);
|
|
150
150
|
assert.deepStrictEqual(inspect(parser('"((""))')), [['"', '<sup class="annotation"><span>""</span></sup>'], '']);
|
|
151
151
|
assert.deepStrictEqual(inspect(parser('[[[a]]')), [['', '[', '<sup class="reference"><span>a</span></sup>'], '']);
|
|
152
|
-
assert.deepStrictEqual(inspect(parser('[[[[a]]')), [['', '[[', '<sup class="reference"><span>a</span></sup>'], '']);
|
|
152
|
+
assert.deepStrictEqual(inspect(parser('[[[[a]]')), [['', '[', '', '[', '<sup class="reference"><span>a</span></sup>'], '']);
|
|
153
153
|
assert.deepStrictEqual(inspect(parser('[[[[a]]]]')), [['<sup class="reference"><span>[[a]]</span></sup>'], '']);
|
|
154
154
|
assert.deepStrictEqual(inspect(parser('[[[$-1]]]')), [['<sup class="reference"><span><a class="label" data-label="$-1">$-1</a></span></sup>'], '']);
|
|
155
155
|
assert.deepStrictEqual(inspect(parser('[[[]{a}]]')), [['<sup class="reference"><span><a href="a">a</a></span></sup>'], '']);
|
|
156
156
|
assert.deepStrictEqual(inspect(parser('[[[a]{b}]]')), [['<sup class="reference"><span><a href="b">a</a></span></sup>'], '']);
|
|
157
157
|
assert.deepStrictEqual(inspect(parser('[(([a]{#}))]{#}')), [['<a href="#"><span class="paren">(<span class="paren">([a]{#})</span>)</span></a>'], '']);
|
|
158
158
|
assert.deepStrictEqual(inspect(parser('[[<bdi>]]')), [['<sup class="reference"><span><span class="invalid"><bdi></span></span></sup>'], '']);
|
|
159
|
-
assert.deepStrictEqual(inspect(parser('[[${]]}$')), [['', '[[', '<span class="math" translate="no" data-src="${]]}$">${]]}$</span>'], '']);
|
|
159
|
+
assert.deepStrictEqual(inspect(parser('[[${]]}$')), [['', '[', '', '[', '<span class="math" translate="no" data-src="${]]}$">${]]}$</span>'], '']);
|
|
160
160
|
assert.deepStrictEqual(inspect(parser('"[[""]]')), [['"', '<sup class="reference"><span>""</span></sup>'], '']);
|
|
161
161
|
assert.deepStrictEqual(inspect(parser('[[a](b)]{c}')), [['<a href="c"><ruby>a<rp>(</rp><rt>b</rt><rp>)</rp></ruby></a>'], '']);
|
|
162
|
-
assert.deepStrictEqual(inspect(parser('[[[[[[[{a}')), [['', '[[[[[[[', '<a href="a">a</a>'], '']);
|
|
162
|
+
assert.deepStrictEqual(inspect(parser('[[[[[[[{a}')), [['', '[', '', '[', '', '[', '', '[', '', '[', '', '[', '', '[', '<a href="a">a</a>'], '']);
|
|
163
163
|
assert.deepStrictEqual(inspect(parser('<http://host>')), [['<', '<a href="http://host" target="_blank">http://host</a>', '>'], '']);
|
|
164
164
|
assert.deepStrictEqual(inspect(parser('[~http://host')), [['', '[', '~', '<a href="http://host" target="_blank">http://host</a>'], '']);
|
|
165
165
|
assert.deepStrictEqual(inspect(parser('[~a@b')), [['', '[', '~', '<a class="email" href="mailto:a@b">a@b</a>'], '']);
|