securemark 0.247.0 → 0.248.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 +12 -0
- package/design.md +7 -4
- package/dist/index.js +11 -77
- package/markdown.d.ts +0 -7
- package/package.json +3 -3
- package/src/parser/inline/annotation.ts +1 -1
- package/src/parser/inline/deletion.ts +2 -2
- package/src/parser/inline/html.test.ts +3 -3
- package/src/parser/inline/html.ts +14 -74
- package/src/parser/inline/insertion.ts +2 -2
- package/src/parser/inline/math.test.ts +4 -4
- package/src/parser/inline/math.ts +4 -4
- package/src/parser/inline/reference.ts +1 -1
- package/src/parser/util.ts +2 -2
package/CHANGELOG.md
CHANGED
package/design.md
CHANGED
|
@@ -278,8 +278,11 @@ CodeMirrorが素では速いがVimModeでは数万文字程度でも耐え難く
|
|
|
278
278
|
|
|
279
279
|
### バックトラック
|
|
280
280
|
|
|
281
|
-
SecuremarkのAnnotation
|
|
282
|
-
|
|
281
|
+
SecuremarkのAnnotation構文に典型的であるように文脈を変更する構文とその文脈に依存し変更される他の構文が存在する場合文脈の相違から解析結果を再利用不能な(`αA'β | αAB`)バックトラックが生じる。ここで解析中に文脈依存構文に遭遇した時、現在の文脈での解析を継続する場合はバックトラックが再帰的に生じ線形時間で解析できず、現在の文脈での解析を中止し直前の文脈を継続または新たな文脈を開始する場合は線形時間で解析できる。
|
|
282
|
+
CommonMarkはLink構文から明らかなように後者の解析方法により線形時間で解析できる言語であるがこれは同時に文脈依存構文の正当な入れ子表現すら解析できず文脈依存構文の存在する数に応じて指数関数的に構文の壊れやすさの増す脆く拡張性の低い言語であることを意味する。
|
|
283
|
+
従って線形時間で解析可能な文法に制約されるCommonMarkには文脈依存構文を入れ子表現の広範な制限ならびに構文の可読性および開始記号の信頼性の指数関数的な低下と引き換えにしか追加できないという拡張性の限界が存在する。
|
|
284
|
+
対してSecuremarkは線形時間で解析不能な前者の解析方法を採用し解析時間と解析範囲の局限により線形時間で解析不能な入力の影響を局限することでこの制限を回避している。
|
|
285
|
+
ただし実際には文脈依存構文の入れ子表現はほとんどがリンクの入れ子不可制約として正当に制限されており開始記号の文字列(終端記号)としての正当な使用も稀と思われるため実用上差異が生じることはほとんどないと思われる。
|
|
283
286
|
|
|
284
287
|
### 標準化
|
|
285
288
|
|
|
@@ -296,5 +299,5 @@ MarkdownはGFMのように最初から高機能で完成度の高い拡張不要
|
|
|
296
299
|
|
|
297
300
|
### Data URI
|
|
298
301
|
|
|
299
|
-
Data URI
|
|
300
|
-
|
|
302
|
+
Data URIは保存および転送容量削減ならびにユーザーおよび管理者双方の集約的管理のためサポートしない。
|
|
303
|
+
特に規制および公開レベルの媒体別設定の実現のためテキストとメディアの分離が必須となる。
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! securemark v0.
|
|
1
|
+
/*! securemark v0.248.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("DOMPurify"), require("Prism"));
|
|
@@ -5367,7 +5367,6 @@ exports.annotation = (0, combinator_1.lazy)(() => (0, combinator_1.creator)((0,
|
|
|
5367
5367
|
|
|
5368
5368
|
}
|
|
5369
5369
|
},
|
|
5370
|
-
state: global_1.undefined,
|
|
5371
5370
|
delimiters: global_1.undefined
|
|
5372
5371
|
}, (0, util_1.trimSpaceStart)((0, combinator_1.union)([(0, combinator_1.some)(inline_1.inline, ')', /^\\?\n/)]))))), '))'), ns => [(0, dom_1.html)('sup', {
|
|
5373
5372
|
class: 'annotation'
|
|
@@ -5754,7 +5753,7 @@ const dom_1 = __webpack_require__(3252);
|
|
|
5754
5753
|
|
|
5755
5754
|
const array_1 = __webpack_require__(8112);
|
|
5756
5755
|
|
|
5757
|
-
exports.deletion = (0, combinator_1.lazy)(() => (0, combinator_1.creator)((0, combinator_1.surround)((0, source_1.str)('~~'), (0, combinator_1.some)((0, combinator_1.union)([(0, combinator_1.some)(inline_1.inline, (0, util_1.blank)(/\n
|
|
5756
|
+
exports.deletion = (0, combinator_1.lazy)(() => (0, combinator_1.creator)((0, combinator_1.surround)((0, source_1.str)('~~'), (0, combinator_1.some)((0, combinator_1.union)([(0, combinator_1.some)(inline_1.inline, (0, util_1.blank)(/\n/, '~~')), (0, combinator_1.open)(/^\n/, (0, combinator_1.some)(inline_1.inline, '~'), true)])), (0, source_1.str)('~~'), false, ([, bs], rest) => [[(0, dom_1.html)('del', (0, dom_1.defrag)(bs))], rest], ([as, bs], rest) => [(0, array_1.unshift)(as, bs), rest])));
|
|
5758
5757
|
|
|
5759
5758
|
/***/ }),
|
|
5760
5759
|
|
|
@@ -6184,77 +6183,13 @@ const attrspec = {
|
|
|
6184
6183
|
};
|
|
6185
6184
|
Object.setPrototypeOf(attrspec, null);
|
|
6186
6185
|
Object.values(attrspec).forEach(o => Object.setPrototypeOf(o, null));
|
|
6187
|
-
exports.html = (0, combinator_1.lazy)(() => (0, combinator_1.creator)((0, combinator_1.validate)('<', (0, combinator_1.validate)(/^<[a-z]+(?=[^\S\n]|>)/, (0, combinator_1.union)([(0, combinator_1.match)(/^(?=<(wbr)(?=[^\S\n]|>))/, (0, memoize_1.memoize)(([, tag]) => (0, combinator_1.surround)(`<${tag}`, (0, combinator_1.some)((0, combinator_1.union)([exports.attribute])), /^\s*>/, true, ([, bs = []], rest) => [[(0, dom_1.html)(tag, attributes('html', [], attrspec[tag], bs))], rest]), ([, tag]) => tags.indexOf(tag), [])), (0, combinator_1.match)(/^(?=<(sup|sub|small)(?=[^\S\n]|>))/, (0, memoize_1.memoize)(([, tag]) => (0, combinator_1.validate)(`<${tag}`, `</${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*>/), true), (0, util_1.startLoose)((0, combinator_1.
|
|
6188
|
-
switch (tag) {
|
|
6189
|
-
case 'sup':
|
|
6190
|
-
case 'sub':
|
|
6191
|
-
return {
|
|
6192
|
-
state: {
|
|
6193
|
-
in: {
|
|
6194
|
-
supsub: true
|
|
6195
|
-
}
|
|
6196
|
-
},
|
|
6197
|
-
syntax: {
|
|
6198
|
-
inline: {
|
|
6199
|
-
annotation: false,
|
|
6200
|
-
reference: false,
|
|
6201
|
-
media: false
|
|
6202
|
-
}
|
|
6203
|
-
}
|
|
6204
|
-
};
|
|
6205
|
-
|
|
6206
|
-
case 'small':
|
|
6207
|
-
return {
|
|
6208
|
-
state: {
|
|
6209
|
-
in: {
|
|
6210
|
-
small: true
|
|
6211
|
-
}
|
|
6212
|
-
},
|
|
6213
|
-
syntax: {
|
|
6214
|
-
inline: {
|
|
6215
|
-
media: false
|
|
6216
|
-
}
|
|
6217
|
-
}
|
|
6218
|
-
};
|
|
6219
|
-
|
|
6220
|
-
default:
|
|
6221
|
-
return {};
|
|
6222
|
-
}
|
|
6223
|
-
})(), (0, combinator_1.some)((0, combinator_1.union)([(0, combinator_1.some)(inline_1.inline, (0, util_1.blank)(/\n?/, `</${tag}>`)), (0, combinator_1.open)(/^\n?/, (0, combinator_1.some)(inline_1.inline, '</'), true)]), `</${tag}>`)), `</${tag}>`), (0, source_1.str)(`</${tag}>`), false, ([as, bs, cs], rest, context) => [[elem(tag, as, (0, dom_1.defrag)(bs), cs, context)], rest])), ([, tag]) => tags.indexOf(tag), [])), (0, combinator_1.match)(/^(?=<(bdo|bdi)(?=[^\S\n]|>))/, (0, memoize_1.memoize)(([, tag]) => (0, combinator_1.validate)(`<${tag}`, `</${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*>/), true), (0, util_1.startLoose)((0, combinator_1.some)((0, combinator_1.union)([(0, combinator_1.some)(inline_1.inline, (0, util_1.blank)(/\n?/, `</${tag}>`)), (0, combinator_1.open)(/^\n?/, (0, combinator_1.some)(inline_1.inline, '</'), true)]), `</${tag}>`), `</${tag}>`), (0, source_1.str)(`</${tag}>`), false, ([as, bs, cs], rest, context) => [[elem(tag, as, (0, dom_1.defrag)(bs), cs, context)], rest], ([as, bs], rest) => as.length === 1 ? [(0, array_1.unshift)(as, bs), rest] : global_1.undefined)), ([, tag]) => tags.indexOf(tag), [])), (0, combinator_1.match)(/^(?=<([a-z]+)(?=[^\S\n]|>))/, (0, memoize_1.memoize)(([, tag]) => (0, combinator_1.validate)(`<${tag}`, `</${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*>/), true), (0, util_1.startLoose)((0, combinator_1.some)((0, combinator_1.union)([(0, combinator_1.some)(inline_1.inline, (0, util_1.blank)(/\n?/, `</${tag}>`)), (0, combinator_1.open)(/^\n?/, (0, combinator_1.some)(inline_1.inline, '</'), true)]), `</${tag}>`), `</${tag}>`), (0, source_1.str)(`</${tag}>`), false, ([as, bs, cs], rest, context) => [[elem(tag, as, (0, dom_1.defrag)(bs), cs, context)], rest], ([as, bs], rest) => as.length === 1 ? [(0, array_1.unshift)(as, bs), rest] : global_1.undefined)), ([, tag]) => tag, new cache_1.Cache(10000)))])))));
|
|
6186
|
+
exports.html = (0, combinator_1.lazy)(() => (0, combinator_1.creator)((0, combinator_1.validate)('<', (0, combinator_1.validate)(/^<[a-z]+(?=[^\S\n]|>)/, (0, combinator_1.union)([(0, combinator_1.match)(/^(?=<(wbr)(?=[^\S\n]|>))/, (0, memoize_1.memoize)(([, tag]) => (0, combinator_1.surround)(`<${tag}`, (0, combinator_1.some)((0, combinator_1.union)([exports.attribute])), /^\s*>/, true, ([, bs = []], rest) => [[(0, dom_1.html)(tag, attributes('html', [], attrspec[tag], bs))], rest]), ([, tag]) => tags.indexOf(tag), [])), (0, combinator_1.match)(/^(?=<(sup|sub|small|bdo|bdi)(?=[^\S\n]|>))/, (0, memoize_1.memoize)(([, tag]) => (0, combinator_1.validate)(`<${tag}`, `</${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*>/), true), (0, util_1.startLoose)((0, combinator_1.some)((0, combinator_1.union)([(0, combinator_1.some)(inline_1.inline, (0, util_1.blank)(/\n/, `</${tag}>`)), (0, combinator_1.open)(/^\n/, (0, combinator_1.some)(inline_1.inline, `</${tag}>`), true)]), `</${tag}>`), `</${tag}>`), (0, source_1.str)(`</${tag}>`), false, ([as, bs, cs], rest) => [[elem(tag, as, (0, dom_1.defrag)(bs), cs)], rest], ([as, bs], rest) => as.length === 1 ? [(0, array_1.unshift)(as, bs), rest] : global_1.undefined)), ([, tag]) => tags.indexOf(tag), [])), (0, combinator_1.match)(/^(?=<([a-z]+)(?=[^\S\n]|>))/, (0, memoize_1.memoize)(([, tag]) => (0, combinator_1.validate)(`<${tag}`, `</${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*>/), true), (0, util_1.startLoose)((0, combinator_1.some)((0, combinator_1.union)([(0, combinator_1.some)(inline_1.inline, (0, util_1.blank)(/\n/, `</${tag}>`)), (0, combinator_1.open)(/^\n/, (0, combinator_1.some)(inline_1.inline, `</${tag}>`), true)]), `</${tag}>`), `</${tag}>`), (0, source_1.str)(`</${tag}>`), false, ([as, bs, cs], rest) => [[elem(tag, as, (0, dom_1.defrag)(bs), cs)], rest], ([as, bs], rest) => as.length === 1 ? [(0, array_1.unshift)(as, bs), rest] : global_1.undefined)), ([, tag]) => tag, new cache_1.Cache(10000)))])))));
|
|
6224
6187
|
exports.attribute = (0, combinator_1.union)([(0, source_1.str)(/^[^\S\n]+[a-z]+(?:-[a-z]+)*(?:="(?:\\[^\n]|[^\\\n"])*")?(?=[^\S\n]|>)/)]);
|
|
6225
6188
|
|
|
6226
|
-
function elem(tag, as, bs, cs
|
|
6189
|
+
function elem(tag, as, bs, cs) {
|
|
6227
6190
|
if (!tags.includes(tag)) return invalid('tag', `Invalid HTML tag <${tag}>`, as, bs, cs);
|
|
6228
|
-
|
|
6229
|
-
switch (tag) {
|
|
6230
|
-
case 'sup':
|
|
6231
|
-
case 'sub':
|
|
6232
|
-
switch (true) {
|
|
6233
|
-
case context.state?.in?.supsub:
|
|
6234
|
-
return invalid('nest', `<${tag}> HTML tag cannot be used in <sup> or <sub> HTML tag`, as, bs, cs);
|
|
6235
|
-
}
|
|
6236
|
-
|
|
6237
|
-
break;
|
|
6238
|
-
|
|
6239
|
-
case 'small':
|
|
6240
|
-
switch (true) {
|
|
6241
|
-
case context.state?.in?.supsub:
|
|
6242
|
-
case context.state?.in?.small:
|
|
6243
|
-
return invalid('nest', `<${tag}> HTML tag cannot be used in <sup>, <sub>, or <small> HTML tag`, as, bs, cs);
|
|
6244
|
-
}
|
|
6245
|
-
|
|
6246
|
-
break;
|
|
6247
|
-
}
|
|
6248
|
-
|
|
6249
6191
|
const attrs = attributes('html', [], attrspec[tag], as.slice(1, -1));
|
|
6250
|
-
|
|
6251
|
-
switch (true) {
|
|
6252
|
-
case 'data-invalid-syntax' in attrs:
|
|
6253
|
-
return invalid('attribute', 'Invalid HTML attribute', as, bs, cs);
|
|
6254
|
-
|
|
6255
|
-
default:
|
|
6256
|
-
return (0, dom_1.html)(tag, attrs, bs);
|
|
6257
|
-
}
|
|
6192
|
+
return 'data-invalid-syntax' in attrs ? invalid('attribute', 'Invalid HTML attribute', as, bs, cs) : (0, dom_1.html)(tag, attrs, bs);
|
|
6258
6193
|
}
|
|
6259
6194
|
|
|
6260
6195
|
function invalid(type, message, as, bs, cs) {
|
|
@@ -6356,7 +6291,7 @@ const dom_1 = __webpack_require__(3252);
|
|
|
6356
6291
|
|
|
6357
6292
|
const array_1 = __webpack_require__(8112);
|
|
6358
6293
|
|
|
6359
|
-
exports.insertion = (0, combinator_1.lazy)(() => (0, combinator_1.creator)((0, combinator_1.surround)((0, source_1.str)('++'), (0, combinator_1.some)((0, combinator_1.union)([(0, combinator_1.some)(inline_1.inline, (0, util_1.blank)(/\n
|
|
6294
|
+
exports.insertion = (0, combinator_1.lazy)(() => (0, combinator_1.creator)((0, combinator_1.surround)((0, source_1.str)('++'), (0, combinator_1.some)((0, combinator_1.union)([(0, combinator_1.some)(inline_1.inline, (0, util_1.blank)(/\n/, '++')), (0, combinator_1.open)(/^\n/, (0, combinator_1.some)(inline_1.inline, '+'), true)])), (0, source_1.str)('++'), false, ([, bs], rest) => [[(0, dom_1.html)('ins', (0, dom_1.defrag)(bs))], rest], ([as, bs], rest) => [(0, array_1.unshift)(as, bs), rest])));
|
|
6360
6295
|
|
|
6361
6296
|
/***/ }),
|
|
6362
6297
|
|
|
@@ -6545,8 +6480,8 @@ const source_1 = __webpack_require__(6743);
|
|
|
6545
6480
|
const dom_1 = __webpack_require__(3252);
|
|
6546
6481
|
|
|
6547
6482
|
const syntax = /^(?:[ "([](?!\$)|\\{(?!\$)|\\[\\}$]?|^`|`(?!`)|[!#%&')\x2A-\x5A\]^_\x61-\x7A|~])+/;
|
|
6548
|
-
const forbiddenCommand = /\\(?:begin|tiny|huge|large)(?![
|
|
6549
|
-
exports.math = (0, combinator_1.lazy)(() => (0, combinator_1.creator)((0, combinator_1.validate)('$', (0, combinator_1.rewrite)((0, combinator_1.union)([(0, combinator_1.surround)('$', bracket, '$'), (0, combinator_1.surround)(/^\$(
|
|
6483
|
+
const forbiddenCommand = /\\(?:begin|tiny|huge|large)(?![a-z])/i;
|
|
6484
|
+
exports.math = (0, combinator_1.lazy)(() => (0, combinator_1.creator)((0, combinator_1.validate)('$', (0, combinator_1.rewrite)((0, combinator_1.union)([(0, combinator_1.surround)('$', bracket, '$'), (0, combinator_1.surround)(/^\$(?![\s{}])/, (0, combinator_1.some)((0, combinator_1.union)([bracket, quote, (0, source_1.str)(syntax)])), /^\$(?![0-9A-Za-z])/)]), (source, {
|
|
6550
6485
|
caches: {
|
|
6551
6486
|
math: cache
|
|
6552
6487
|
} = {}
|
|
@@ -6559,10 +6494,10 @@ exports.math = (0, combinator_1.lazy)(() => (0, combinator_1.creator)((0, combin
|
|
|
6559
6494
|
translate: 'no',
|
|
6560
6495
|
'data-invalid-syntax': 'math',
|
|
6561
6496
|
'data-invalid-type': 'content',
|
|
6562
|
-
'data-invalid-message': `"${source.match(forbiddenCommand)[0]}" command is
|
|
6497
|
+
'data-invalid-message': `"${source.match(forbiddenCommand)[0]}" command is forbidden`
|
|
6563
6498
|
}, source)], '']))));
|
|
6564
6499
|
const bracket = (0, combinator_1.lazy)(() => (0, combinator_1.creator)((0, combinator_1.surround)('{', (0, combinator_1.some)((0, combinator_1.union)([bracket, (0, combinator_1.some)(source_1.escsource, /^(?:[{}$]|\\?\n)/)])), '}', true)));
|
|
6565
|
-
const quote = (0, combinator_1.lazy)(() => (0, combinator_1.creator)((0, combinator_1.surround)('``', (0, combinator_1.some)((0, combinator_1.union)([quote, bracket, (0, combinator_1.focus)(/^(?:\\[\\{}$]|`(?!`)|[^`{}"$\n])
|
|
6500
|
+
const quote = (0, combinator_1.lazy)(() => (0, combinator_1.creator)((0, combinator_1.surround)('``', (0, combinator_1.some)((0, combinator_1.union)([quote, bracket, (0, combinator_1.focus)(/^(?:\\[\\{}$]|`(?!`)|[^`{}"$\n\P{ASCII}])*/u, (0, source_1.str)(syntax))])), /^"?/, true)));
|
|
6566
6501
|
|
|
6567
6502
|
/***/ }),
|
|
6568
6503
|
|
|
@@ -6700,7 +6635,6 @@ exports.reference = (0, combinator_1.lazy)(() => (0, combinator_1.creator)((0, c
|
|
|
6700
6635
|
|
|
6701
6636
|
}
|
|
6702
6637
|
},
|
|
6703
|
-
state: global_1.undefined,
|
|
6704
6638
|
delimiters: global_1.undefined
|
|
6705
6639
|
}, (0, combinator_1.subsequence)([abbr, (0, combinator_1.focus)(/^\^[^\S\n]*/, source => [['', source], '']), (0, util_1.trimSpaceStart)((0, combinator_1.some)(inline_1.inline, ']', /^\\?\n/))])))), ']]'), ns => [(0, dom_1.html)('sup', attributes(ns), (0, util_1.trimNodeEnd)((0, dom_1.defrag)(ns)))]))));
|
|
6706
6640
|
const abbr = (0, combinator_1.creator)((0, combinator_1.fmap)((0, combinator_1.verify)((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]*/), (_, rest, context) => (0, util_1.isStartLoose)(rest, context)), ([source]) => [(0, dom_1.html)('abbr', source)]));
|
|
@@ -7779,7 +7713,7 @@ const memoize_1 = __webpack_require__(1808);
|
|
|
7779
7713
|
const array_1 = __webpack_require__(8112);
|
|
7780
7714
|
|
|
7781
7715
|
function blank(prefix, suffix) {
|
|
7782
|
-
return new RegExp(String.raw
|
|
7716
|
+
return new RegExp(String.raw`^(?:${prefix && prefix.source}(?:\\\s|[^\S\n]|\n|&(?:${normalize_1.invisibleHTMLEntityNames.join('|')});|<wbr>)*)?${typeof suffix === 'string' ? suffix.replace(/[*+()\[\]]/g, '\\$&') : suffix.source}`);
|
|
7783
7717
|
}
|
|
7784
7718
|
|
|
7785
7719
|
exports.blank = blank;
|
package/markdown.d.ts
CHANGED
|
@@ -28,12 +28,6 @@ export namespace MarkdownParser {
|
|
|
28
28
|
readonly autolink?: boolean;
|
|
29
29
|
};
|
|
30
30
|
};
|
|
31
|
-
readonly state?: {
|
|
32
|
-
readonly in?: {
|
|
33
|
-
readonly supsub?: boolean;
|
|
34
|
-
readonly small?: boolean;
|
|
35
|
-
};
|
|
36
|
-
};
|
|
37
31
|
readonly caches?: {
|
|
38
32
|
readonly code?: Collection<string, HTMLElement>;
|
|
39
33
|
readonly math?: Collection<string, HTMLElement>;
|
|
@@ -987,7 +981,6 @@ export namespace MarkdownParser {
|
|
|
987
981
|
HTMLParser.OpenTagParser,
|
|
988
982
|
HTMLParser.TagParser,
|
|
989
983
|
HTMLParser.TagParser,
|
|
990
|
-
HTMLParser.TagParser,
|
|
991
984
|
]> {
|
|
992
985
|
}
|
|
993
986
|
export namespace HTMLParser {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "securemark",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.248.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",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"babel-loader": "^8.2.5",
|
|
39
39
|
"babel-plugin-unassert": "^3.2.0",
|
|
40
40
|
"concurrently": "^7.2.0",
|
|
41
|
-
"eslint": "^8.
|
|
41
|
+
"eslint": "^8.16.0",
|
|
42
42
|
"eslint-plugin-redos": "^4.4.0",
|
|
43
43
|
"eslint-webpack-plugin": "^3.1.1",
|
|
44
44
|
"glob": "^8.0.3",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"karma-mocha": "^2.0.1",
|
|
50
50
|
"karma-power-assert": "^1.0.0",
|
|
51
51
|
"mocha": "^10.0.0",
|
|
52
|
-
"npm-check-updates": "^13.0.
|
|
52
|
+
"npm-check-updates": "^13.0.3",
|
|
53
53
|
"semver": "^7.3.7",
|
|
54
54
|
"spica": "0.0.551",
|
|
55
55
|
"ts-loader": "^9.3.0",
|
|
@@ -19,7 +19,7 @@ export const annotation: AnnotationParser = lazy(() => creator(validate('((', ')
|
|
|
19
19
|
//label: true,
|
|
20
20
|
//link: true,
|
|
21
21
|
//autolink: true,
|
|
22
|
-
}},
|
|
22
|
+
}}, delimiters: undefined },
|
|
23
23
|
trimSpaceStart(union([some(inline, ')', /^\\?\n/)]))))),
|
|
24
24
|
'))'),
|
|
25
25
|
ns => [html('sup', { class: 'annotation' }, trimNodeEnd(defrag(ns)))]))));
|
|
@@ -9,8 +9,8 @@ import { unshift } from 'spica/array';
|
|
|
9
9
|
export const deletion: DeletionParser = lazy(() => creator(surround(
|
|
10
10
|
str('~~'),
|
|
11
11
|
some(union([
|
|
12
|
-
some(inline, blank(/\n
|
|
13
|
-
open(/^\n
|
|
12
|
+
some(inline, blank(/\n/, '~~')),
|
|
13
|
+
open(/^\n/, some(inline, '~'), true),
|
|
14
14
|
])),
|
|
15
15
|
str('~~'), false,
|
|
16
16
|
([, bs], rest) => [[html('del', defrag(bs))], rest],
|
|
@@ -41,7 +41,7 @@ describe('Unit: parser/inline/html', () => {
|
|
|
41
41
|
assert.deepStrictEqual(inspect(parser('</small>')), undefined);
|
|
42
42
|
assert.deepStrictEqual(inspect(parser('<small/>')), undefined);
|
|
43
43
|
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>'], '']);
|
|
44
|
-
assert.deepStrictEqual(inspect(parser('<small><small><small>a</small></small></small>')), [['<small><
|
|
44
|
+
assert.deepStrictEqual(inspect(parser('<small><small><small>a</small></small></small>')), [['<small><small><small>a</small></small></small>'], '']);
|
|
45
45
|
assert.deepStrictEqual(inspect(parser('<x a="*b*"')), undefined);
|
|
46
46
|
assert.deepStrictEqual(inspect(parser('<x a="*b*">')), undefined);
|
|
47
47
|
assert.deepStrictEqual(inspect(parser('<x a="*b*">c')), undefined);
|
|
@@ -72,8 +72,8 @@ describe('Unit: parser/inline/html', () => {
|
|
|
72
72
|
});
|
|
73
73
|
|
|
74
74
|
it('nest', () => {
|
|
75
|
-
assert.deepStrictEqual(inspect(parser('<small><small>a</small></small>')), [['<small><
|
|
76
|
-
assert.deepStrictEqual(inspect(parser('<small>a<small>b</small>c</small>')), [['<small>a<
|
|
75
|
+
assert.deepStrictEqual(inspect(parser('<small><small>a</small></small>')), [['<small><small>a</small></small>'], '']);
|
|
76
|
+
assert.deepStrictEqual(inspect(parser('<small>a<small>b</small>c</small>')), [['<small>a<small>b</small>c</small>'], '']);
|
|
77
77
|
assert.deepStrictEqual(inspect(parser('<small>`a`</small>')), [['<small><code data-src="`a`">a</code></small>'], '']);
|
|
78
78
|
});
|
|
79
79
|
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { undefined } from 'spica/global';
|
|
2
2
|
import { isFrozen, ObjectEntries } from 'spica/alias';
|
|
3
|
-
import { MarkdownParser } from '../../../markdown';
|
|
4
3
|
import { HTMLParser } from '../inline';
|
|
5
|
-
import { union, some, validate,
|
|
4
|
+
import { union, some, validate, creator, surround, open, match, lazy } from '../../combinator';
|
|
6
5
|
import { inline } from '../inline';
|
|
7
6
|
import { str } from '../source';
|
|
8
7
|
import { startLoose, blank } from '../util';
|
|
@@ -31,59 +30,19 @@ export const html: HTMLParser = lazy(() => creator(validate('<', validate(/^<[a-
|
|
|
31
30
|
[[h(tag as 'span', attributes('html', [], attrspec[tag], bs))], rest]),
|
|
32
31
|
([, tag]) => tags.indexOf(tag), [])),
|
|
33
32
|
match(
|
|
34
|
-
/^(?=<(sup|sub|small)(?=[^\S\n]|>))/,
|
|
35
|
-
memoize(
|
|
36
|
-
([, tag]) =>
|
|
37
|
-
validate(`<${tag}`, `</${tag}>`,
|
|
38
|
-
surround<HTMLParser.TagParser, string>(surround(
|
|
39
|
-
str(`<${tag}`), some(attribute), str(/^\s*>/), true),
|
|
40
|
-
startLoose(
|
|
41
|
-
context((() => {
|
|
42
|
-
switch (tag) {
|
|
43
|
-
case 'sup':
|
|
44
|
-
case 'sub':
|
|
45
|
-
return {
|
|
46
|
-
state: { in: { supsub: true } },
|
|
47
|
-
syntax: { inline: {
|
|
48
|
-
annotation: false,
|
|
49
|
-
reference: false,
|
|
50
|
-
media: false,
|
|
51
|
-
}},
|
|
52
|
-
};
|
|
53
|
-
case 'small':
|
|
54
|
-
return {
|
|
55
|
-
state: { in: { small: true } },
|
|
56
|
-
syntax: { inline: {
|
|
57
|
-
media: false,
|
|
58
|
-
}},
|
|
59
|
-
};
|
|
60
|
-
default:
|
|
61
|
-
assert(false);
|
|
62
|
-
return {};
|
|
63
|
-
}
|
|
64
|
-
})(),
|
|
65
|
-
some(union([
|
|
66
|
-
some(inline, blank(/\n?/, `</${tag}>`)),
|
|
67
|
-
open(/^\n?/, some(inline, '</'), true),
|
|
68
|
-
]), `</${tag}>`)), `</${tag}>`),
|
|
69
|
-
str(`</${tag}>`), false,
|
|
70
|
-
([as, bs, cs], rest, context) =>
|
|
71
|
-
[[elem(tag, as, defrag(bs), cs, context)], rest])),
|
|
72
|
-
([, tag]) => tags.indexOf(tag), [])),
|
|
73
|
-
match(
|
|
74
|
-
/^(?=<(bdo|bdi)(?=[^\S\n]|>))/,
|
|
33
|
+
/^(?=<(sup|sub|small|bdo|bdi)(?=[^\S\n]|>))/,
|
|
75
34
|
memoize(
|
|
76
35
|
([, tag]) =>
|
|
77
36
|
validate(`<${tag}`, `</${tag}>`,
|
|
78
37
|
surround<HTMLParser.TagParser, string>(surround(
|
|
79
38
|
str(`<${tag}`), some(attribute), str(/^\s*>/), true),
|
|
80
39
|
startLoose(some(union([
|
|
81
|
-
some(inline, blank(/\n
|
|
82
|
-
open(/^\n
|
|
40
|
+
some(inline, blank(/\n/, `</${tag}>`)),
|
|
41
|
+
open(/^\n/, some(inline, `</${tag}>`), true),
|
|
83
42
|
]), `</${tag}>`), `</${tag}>`),
|
|
84
43
|
str(`</${tag}>`), false,
|
|
85
|
-
([as, bs, cs], rest
|
|
86
|
-
[[elem(tag, as, defrag(bs), cs
|
|
44
|
+
([as, bs, cs], rest) =>
|
|
45
|
+
[[elem(tag, as, defrag(bs), cs)], rest],
|
|
87
46
|
([as, bs], rest) =>
|
|
88
47
|
as.length === 1 ? [unshift(as, bs), rest] : undefined)),
|
|
89
48
|
([, tag]) => tags.indexOf(tag), [])),
|
|
@@ -95,12 +54,12 @@ export const html: HTMLParser = lazy(() => creator(validate('<', validate(/^<[a-
|
|
|
95
54
|
surround<HTMLParser.TagParser, string>(surround(
|
|
96
55
|
str(`<${tag}`), some(attribute), str(/^\s*>/), true),
|
|
97
56
|
startLoose(some(union([
|
|
98
|
-
some(inline, blank(/\n
|
|
99
|
-
open(/^\n
|
|
57
|
+
some(inline, blank(/\n/, `</${tag}>`)),
|
|
58
|
+
open(/^\n/, some(inline, `</${tag}>`), true),
|
|
100
59
|
]), `</${tag}>`), `</${tag}>`),
|
|
101
60
|
str(`</${tag}>`), false,
|
|
102
|
-
([as, bs, cs], rest
|
|
103
|
-
[[elem(tag, as, defrag(bs), cs
|
|
61
|
+
([as, bs, cs], rest) =>
|
|
62
|
+
[[elem(tag, as, defrag(bs), cs)], rest],
|
|
104
63
|
([as, bs], rest) =>
|
|
105
64
|
as.length === 1 ? [unshift(as, bs), rest] : undefined)),
|
|
106
65
|
([, tag]) => tag,
|
|
@@ -111,35 +70,16 @@ export const attribute: HTMLParser.TagParser.AttributeParser = union([
|
|
|
111
70
|
str(/^[^\S\n]+[a-z]+(?:-[a-z]+)*(?:="(?:\\[^\n]|[^\\\n"])*")?(?=[^\S\n]|>)/),
|
|
112
71
|
]);
|
|
113
72
|
|
|
114
|
-
function elem(tag: string, as: string[], bs: (HTMLElement | string)[], cs: string[]
|
|
73
|
+
function elem(tag: string, as: string[], bs: (HTMLElement | string)[], cs: string[]): HTMLElement {
|
|
115
74
|
assert(as.length > 0);
|
|
116
75
|
assert(as[0][0] === '<' && as[as.length - 1].slice(-1) === '>');
|
|
117
76
|
assert(bs.length === defrag(bs).length);
|
|
118
77
|
assert(cs.length === 1);
|
|
119
78
|
if (!tags.includes(tag)) return invalid('tag', `Invalid HTML tag <${tag}>`, as, bs, cs);
|
|
120
|
-
switch (tag) {
|
|
121
|
-
case 'sup':
|
|
122
|
-
case 'sub':
|
|
123
|
-
switch (true) {
|
|
124
|
-
case context.state?.in?.supsub:
|
|
125
|
-
return invalid('nest', `<${tag}> HTML tag cannot be used in <sup> or <sub> HTML tag`, as, bs, cs);
|
|
126
|
-
}
|
|
127
|
-
break;
|
|
128
|
-
case 'small':
|
|
129
|
-
switch (true) {
|
|
130
|
-
case context.state?.in?.supsub:
|
|
131
|
-
case context.state?.in?.small:
|
|
132
|
-
return invalid('nest', `<${tag}> HTML tag cannot be used in <sup>, <sub>, or <small> HTML tag`, as, bs, cs);
|
|
133
|
-
}
|
|
134
|
-
break;
|
|
135
|
-
}
|
|
136
79
|
const attrs = attributes('html', [], attrspec[tag], as.slice(1, -1));
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
default:
|
|
141
|
-
return h(tag as 'span', attrs, bs);
|
|
142
|
-
}
|
|
80
|
+
return 'data-invalid-syntax' in attrs
|
|
81
|
+
? invalid('attribute', 'Invalid HTML attribute', as, bs, cs)
|
|
82
|
+
: h(tag as 'span', attrs, bs);
|
|
143
83
|
}
|
|
144
84
|
function invalid(type: string, message: string, as: (HTMLElement | string)[], bs: (HTMLElement | string)[], cs: (HTMLElement | string)[]): HTMLElement {
|
|
145
85
|
return h('span', {
|
|
@@ -9,8 +9,8 @@ import { unshift } from 'spica/array';
|
|
|
9
9
|
export const insertion: InsertionParser = lazy(() => creator(surround(
|
|
10
10
|
str('++'),
|
|
11
11
|
some(union([
|
|
12
|
-
some(inline, blank(/\n
|
|
13
|
-
open(/^\n
|
|
12
|
+
some(inline, blank(/\n/, '++')),
|
|
13
|
+
open(/^\n/, some(inline, '+'), true),
|
|
14
14
|
])),
|
|
15
15
|
str('++'), false,
|
|
16
16
|
([, bs], rest) => [[html('ins', defrag(bs))], rest],
|
|
@@ -54,13 +54,16 @@ describe('Unit: parser/inline/math', () => {
|
|
|
54
54
|
assert.deepStrictEqual(inspect(parser('${a} $')), undefined);
|
|
55
55
|
assert.deepStrictEqual(inspect(parser('${a{b}$')), undefined);
|
|
56
56
|
assert.deepStrictEqual(inspect(parser('${a}b}$')), undefined);
|
|
57
|
+
assert.deepStrictEqual(inspect(parser('${a}b$')), undefined);
|
|
58
|
+
assert.deepStrictEqual(inspect(parser('${a}b{c}$')), undefined);
|
|
59
|
+
assert.deepStrictEqual(inspect(parser('${a}{b}$')), undefined);
|
|
57
60
|
assert.deepStrictEqual(inspect(parser('${$}$')), undefined);
|
|
58
61
|
assert.deepStrictEqual(inspect(parser('${\\}$')), undefined);
|
|
59
62
|
assert.deepStrictEqual(inspect(parser('${\n}$')), undefined);
|
|
60
63
|
assert.deepStrictEqual(inspect(parser('${a\\$\nb}$')), undefined);
|
|
61
64
|
assert.deepStrictEqual(inspect(parser('${a\\$\\\nb}$')), undefined);
|
|
62
65
|
assert.deepStrictEqual(inspect(parser('$\\begin{}$')), [['<span class="invalid" translate="no">$\\begin{}$</span>'], '']);
|
|
63
|
-
assert.deepStrictEqual(inspect(parser('$\\
|
|
66
|
+
assert.deepStrictEqual(inspect(parser('$\\huge0$')), [['<span class="invalid" translate="no">$\\huge0$</span>'], '']);
|
|
64
67
|
assert.deepStrictEqual(inspect(parser('$\\Begin{}$')), [['<span class="invalid" translate="no">$\\Begin{}$</span>'], '']);
|
|
65
68
|
assert.deepStrictEqual(inspect(parser('${\\begin}$')), [['<span class="invalid" translate="no">${\\begin}$</span>'], '']);
|
|
66
69
|
assert.deepStrictEqual(inspect(parser(' ${a}$')), undefined);
|
|
@@ -128,9 +131,6 @@ describe('Unit: parser/inline/math', () => {
|
|
|
128
131
|
assert.deepStrictEqual(inspect(parser('${\\a}$')), [['<span class="math" translate="no" data-src="${\\a}$">${\\a}$</span>'], '']);
|
|
129
132
|
assert.deepStrictEqual(inspect(parser('${\\$}$')), [['<span class="math" translate="no" data-src="${\\$}$">${\\$}$</span>'], '']);
|
|
130
133
|
assert.deepStrictEqual(inspect(parser('${\\\\}$')), [['<span class="math" translate="no" data-src="${\\\\}$">${\\\\}$</span>'], '']);
|
|
131
|
-
assert.deepStrictEqual(inspect(parser('${a}b$')), [['<span class="math" translate="no" data-src="${a}b$">${a}b$</span>'], '']);
|
|
132
|
-
assert.deepStrictEqual(inspect(parser('${a}b{c}$')), [['<span class="math" translate="no" data-src="${a}b{c}$">${a}b{c}$</span>'], '']);
|
|
133
|
-
assert.deepStrictEqual(inspect(parser('${a}{b}$')), [['<span class="math" translate="no" data-src="${a}{b}$">${a}{b}$</span>'], '']);
|
|
134
134
|
assert.deepStrictEqual(inspect(parser('${あ}$')), [['<span class="math" translate="no" data-src="${あ}$">${あ}$</span>'], '']);
|
|
135
135
|
});
|
|
136
136
|
|
|
@@ -4,13 +4,13 @@ import { escsource, str } from '../source';
|
|
|
4
4
|
import { html } from 'typed-dom/dom';
|
|
5
5
|
|
|
6
6
|
const syntax = /^(?:[ "([](?!\$)|\\{(?!\$)|\\[\\}$]?|^`|`(?!`)|[!#%&')\x2A-\x5A\]^_\x61-\x7A|~])+/;
|
|
7
|
-
const forbiddenCommand = /\\(?:begin|tiny|huge|large)(?![
|
|
7
|
+
const forbiddenCommand = /\\(?:begin|tiny|huge|large)(?![a-z])/i;
|
|
8
8
|
|
|
9
9
|
export const math: MathParser = lazy(() => creator(validate('$', rewrite(
|
|
10
10
|
union([
|
|
11
11
|
surround('$', bracket, '$'),
|
|
12
12
|
surround(
|
|
13
|
-
/^\$(
|
|
13
|
+
/^\$(?![\s{}])/,
|
|
14
14
|
some(union([
|
|
15
15
|
bracket,
|
|
16
16
|
quote,
|
|
@@ -28,7 +28,7 @@ export const math: MathParser = lazy(() => creator(validate('$', rewrite(
|
|
|
28
28
|
translate: 'no',
|
|
29
29
|
'data-invalid-syntax': 'math',
|
|
30
30
|
'data-invalid-type': 'content',
|
|
31
|
-
'data-invalid-message': `"${source.match(forbiddenCommand)![0]}" command is
|
|
31
|
+
'data-invalid-message': `"${source.match(forbiddenCommand)![0]}" command is forbidden`,
|
|
32
32
|
},
|
|
33
33
|
source)
|
|
34
34
|
], '']))));
|
|
@@ -47,7 +47,7 @@ const quote: MathParser.QuoteParser = lazy(() => creator(surround(
|
|
|
47
47
|
some(union([
|
|
48
48
|
quote,
|
|
49
49
|
bracket,
|
|
50
|
-
focus(/^(?:\\[\\{}$]|`(?!`)|[^`{}"$\n])
|
|
50
|
+
focus(/^(?:\\[\\{}$]|`(?!`)|[^`{}"$\n\P{ASCII}])*/u, str(syntax)),
|
|
51
51
|
])),
|
|
52
52
|
/^"?/,
|
|
53
53
|
true)));
|
|
@@ -19,7 +19,7 @@ export const reference: ReferenceParser = lazy(() => creator(validate('[[', ']]'
|
|
|
19
19
|
//label: true,
|
|
20
20
|
//link: true,
|
|
21
21
|
//autolink: true,
|
|
22
|
-
}},
|
|
22
|
+
}}, delimiters: undefined },
|
|
23
23
|
subsequence([
|
|
24
24
|
abbr,
|
|
25
25
|
focus(/^\^[^\S\n]*/, source => [['', source], '']),
|
package/src/parser/util.ts
CHANGED
|
@@ -10,9 +10,9 @@ import { push } from 'spica/array';
|
|
|
10
10
|
|
|
11
11
|
export function blank(prefix: '' | RegExp, suffix: string | RegExp): RegExp {
|
|
12
12
|
return new RegExp(String.raw
|
|
13
|
-
|
|
13
|
+
`^(?:${
|
|
14
14
|
prefix && prefix.source
|
|
15
|
-
}(?:\\\s|[^\S\n]
|
|
15
|
+
}(?:\\\s|[^\S\n]|\n|&(?:${invisibleHTMLEntityNames.join('|')});|<wbr>)*)?${
|
|
16
16
|
typeof suffix === 'string' ? suffix.replace(/[*+()\[\]]/g, '\\$&') : suffix.source
|
|
17
17
|
}`);
|
|
18
18
|
}
|