securemark 0.268.1 → 0.269.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 +8 -0
- package/dist/index.js +46 -37
- package/markdown.d.ts +59 -41
- package/package.json +4 -4
- package/src/parser/autolink.test.ts +2 -2
- package/src/parser/autolink.ts +5 -12
- package/src/parser/block/paragraph.test.ts +4 -2
- package/src/parser/block/paragraph.ts +3 -2
- package/src/parser/block/reply/quote.test.ts +2 -2
- package/src/parser/block/reply/quote.ts +8 -12
- package/src/parser/inline/autolink/url.test.ts +2 -0
- package/src/parser/inline/autolink/url.ts +13 -2
- package/src/parser/inline/autolink.ts +33 -30
- package/src/parser/inline/extension/indexee.ts +4 -3
- package/src/parser/inline/extension/placeholder.test.ts +1 -1
- package/src/parser/inline/link.ts +8 -3
- package/src/parser/inline/media.ts +6 -1
- package/src/parser/inline/shortmedia.ts +12 -3
- package/src/parser/inline.test.ts +6 -9
- package/src/parser/inline.ts +8 -7
- package/src/parser/source/escapable.ts +5 -1
- package/src/parser/source/text.ts +5 -1
- package/src/parser/source/unescapable.ts +7 -1
- package/src/parser/util.ts +0 -10
- package/src/parser/visibility.ts +1 -2
- package/src/util/info.ts +5 -3
- package/src/util/quote.test.ts +2 -2
package/CHANGELOG.md
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! securemark v0.
|
|
1
|
+
/*! securemark v0.269.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"));
|
|
@@ -4274,14 +4274,11 @@ exports.parse = parse;
|
|
|
4274
4274
|
Object.defineProperty(exports, "__esModule", ({
|
|
4275
4275
|
value: true
|
|
4276
4276
|
}));
|
|
4277
|
-
exports.
|
|
4277
|
+
exports.autolink = void 0;
|
|
4278
4278
|
const combinator_1 = __webpack_require__(2087);
|
|
4279
|
-
const link_1 = __webpack_require__(9628);
|
|
4280
4279
|
const autolink_1 = __webpack_require__(6051);
|
|
4281
4280
|
const source_1 = __webpack_require__(6743);
|
|
4282
|
-
|
|
4283
|
-
exports.autolink = (0, combinator_1.lazy)(() => (0, combinator_1.some)((0, combinator_1.line)((0, combinator_1.subsequence)([exports.lineurl, (0, combinator_1.some)((0, combinator_1.union)([autolink_1.autolink, source_1.linebreak, source_1.unescsource]))]))));
|
|
4284
|
-
exports.lineurl = (0, combinator_1.lazy)(() => (0, combinator_1.focus)(/^!?https?:\/\/\S+(?=[^\S\n]*(?:$|\n))/, (0, util_1.format)((0, combinator_1.tails)([(0, source_1.str)('!'), link_1.link]))));
|
|
4281
|
+
exports.autolink = (0, combinator_1.lazy)(() => (0, combinator_1.convert)(source => `\r${source}`, (0, combinator_1.some)((0, combinator_1.union)([autolink_1.autolink, source_1.linebreak, source_1.unescsource]))));
|
|
4285
4282
|
|
|
4286
4283
|
/***/ }),
|
|
4287
4284
|
|
|
@@ -5378,7 +5375,7 @@ const combinator_1 = __webpack_require__(2087);
|
|
|
5378
5375
|
const inline_1 = __webpack_require__(1160);
|
|
5379
5376
|
const visibility_1 = __webpack_require__(7618);
|
|
5380
5377
|
const dom_1 = __webpack_require__(3252);
|
|
5381
|
-
exports.paragraph = (0, combinator_1.block)((0, combinator_1.fmap)((0, visibility_1.visualize)((0, combinator_1.trimEnd)((0, combinator_1.some)((0, combinator_1.union)([inline_1.inline])))), ns => [(0, dom_1.html)('p', (0, dom_1.defrag)(ns))]));
|
|
5378
|
+
exports.paragraph = (0, combinator_1.block)((0, combinator_1.fmap)((0, combinator_1.convert)(source => `\r${source}`, (0, visibility_1.visualize)((0, combinator_1.trimEnd)((0, combinator_1.some)((0, combinator_1.union)([inline_1.inline]))))), ns => [(0, dom_1.html)('p', (0, dom_1.defrag)(ns))]));
|
|
5382
5379
|
|
|
5383
5380
|
/***/ }),
|
|
5384
5381
|
|
|
@@ -5462,7 +5459,6 @@ const combinator_1 = __webpack_require__(2087);
|
|
|
5462
5459
|
const math_1 = __webpack_require__(8946);
|
|
5463
5460
|
const autolink_1 = __webpack_require__(6051);
|
|
5464
5461
|
const source_1 = __webpack_require__(6743);
|
|
5465
|
-
const autolink_2 = __webpack_require__(7185);
|
|
5466
5462
|
const dom_1 = __webpack_require__(3252);
|
|
5467
5463
|
exports.syntax = /^>+(?=[^\S\n])|^>(?=[^\s>])|^>+(?=[^\s>])(?![0-9a-z]+(?:-[0-9a-z]+)*(?![0-9A-Za-z@#:]))/;
|
|
5468
5464
|
exports.quote = (0, combinator_1.lazy)(() => (0, combinator_1.creation)(1, false, (0, combinator_1.block)((0, combinator_1.fmap)((0, combinator_1.validate)('>', (0, combinator_1.union)([(0, combinator_1.rewrite)((0, combinator_1.some)((0, combinator_1.validate)(new RegExp(exports.syntax.source.split('|')[0]), source_1.anyline)), qblock), (0, combinator_1.rewrite)((0, combinator_1.validate)(new RegExp(exports.syntax.source.split('|').slice(1).join('|')), source_1.anyline), (0, combinator_1.line)((0, combinator_1.union)([(0, source_1.str)(/^.+/)])))])), ns => [(0, dom_1.html)('span', ns.length > 1 ? {
|
|
@@ -5482,7 +5478,7 @@ const qblock = ({
|
|
|
5482
5478
|
const quotes = source.match(/^>+[^\S\n]/mg);
|
|
5483
5479
|
const content = lines.reduce((acc, line, i) => acc + line.slice(quotes[i].length), '');
|
|
5484
5480
|
const nodes = (0, parser_1.eval)(text({
|
|
5485
|
-
source: content
|
|
5481
|
+
source: `\r${content}`,
|
|
5486
5482
|
context
|
|
5487
5483
|
}), []);
|
|
5488
5484
|
nodes.unshift(quotes.shift());
|
|
@@ -5508,7 +5504,7 @@ const qblock = ({
|
|
|
5508
5504
|
nodes.unshift('');
|
|
5509
5505
|
return [nodes, ''];
|
|
5510
5506
|
};
|
|
5511
|
-
const text = (0, combinator_1.some)((0, combinator_1.
|
|
5507
|
+
const text = (0, combinator_1.some)((0, combinator_1.union)([math_1.math, autolink_1.autolink, source_1.linebreak, source_1.unescsource]));
|
|
5512
5508
|
|
|
5513
5509
|
/***/ }),
|
|
5514
5510
|
|
|
@@ -5702,7 +5698,7 @@ const shortmedia_1 = __webpack_require__(4189);
|
|
|
5702
5698
|
const autolink_1 = __webpack_require__(6051);
|
|
5703
5699
|
const bracket_1 = __webpack_require__(5196);
|
|
5704
5700
|
const source_1 = __webpack_require__(6743);
|
|
5705
|
-
exports.inline = (0, combinator_1.union)([annotation_1.annotation, reference_1.reference, template_1.template, comment_1.comment, math_1.math, extension_1.extension, ruby_1.ruby, link_1.
|
|
5701
|
+
exports.inline = (0, combinator_1.union)([annotation_1.annotation, reference_1.reference, template_1.template, comment_1.comment, math_1.math, extension_1.extension, ruby_1.ruby, link_1.textlink, link_1.linemedialink, media_1.linemedia, html_1.html, insertion_1.insertion, deletion_1.deletion, mark_1.mark, strong_1.strong, emphasis_1.emphasis, code_1.code, htmlentity_1.htmlentity, shortmedia_1.lineshortmedia, autolink_1.autolink, bracket_1.bracket, source_1.text]);
|
|
5706
5702
|
var indexee_1 = __webpack_require__(1269);
|
|
5707
5703
|
Object.defineProperty(exports, "indexee", ({
|
|
5708
5704
|
enumerable: true,
|
|
@@ -5776,7 +5772,7 @@ const hashnum_1 = __webpack_require__(5631);
|
|
|
5776
5772
|
const anchor_1 = __webpack_require__(6495);
|
|
5777
5773
|
const source_1 = __webpack_require__(6743);
|
|
5778
5774
|
const util_1 = __webpack_require__(9437);
|
|
5779
|
-
exports.autolink = (0, combinator_1.
|
|
5775
|
+
exports.autolink = (0, combinator_1.validate)(/^(?:[@#>0-9a-z\r\n]|\S[#>])/i, (0, combinator_1.constraint)(2 /* State.autolink */, false, (0, combinator_1.syntax)(2 /* Syntax.autolink */, 1, 1, ~1 /* State.shortcut */, (0, combinator_1.union)([(0, combinator_1.some)((0, combinator_1.union)([url_1.lineurl])), (0, combinator_1.fmap)((0, combinator_1.some)((0, combinator_1.union)([url_1.url, email_1.email,
|
|
5780
5776
|
// Escape unmatched email-like strings.
|
|
5781
5777
|
(0, combinator_1.focus)(/^[0-9a-z](?:[_.+-](?=[0-9a-z])|[0-9a-z])*(?:@(?:[0-9a-z]+(?:[.-][0-9a-z]+)*)?)*/i, ({
|
|
5782
5778
|
source
|
|
@@ -5793,7 +5789,7 @@ exports.autolink = (0, combinator_1.fmap)((0, combinator_1.validate)(/^(?:[@#>0-
|
|
|
5793
5789
|
// Escape unmatched hashtag-like strings.
|
|
5794
5790
|
(0, source_1.str)(new RegExp(/^#+(?:[^\p{C}\p{S}\p{P}\s]|emoji|')*/u.source.replace('emoji', hashtag_1.emoji), 'u')),
|
|
5795
5791
|
// Escape invalid leading characters.
|
|
5796
|
-
(0, source_1.str)(/^[0-9\p{Sc}](?=>)/u), anchor_1.anchor]))
|
|
5792
|
+
(0, source_1.str)(/^[0-9\p{Sc}](?=>)/u), anchor_1.anchor])), ns => ns.length === 1 ? ns : [(0, util_1.stringify)(ns)])]))));
|
|
5797
5793
|
|
|
5798
5794
|
/***/ }),
|
|
5799
5795
|
|
|
@@ -5949,12 +5945,13 @@ exports.hashtag = (0, combinator_1.lazy)(() => (0, combinator_1.fmap)((0, combin
|
|
|
5949
5945
|
Object.defineProperty(exports, "__esModule", ({
|
|
5950
5946
|
value: true
|
|
5951
5947
|
}));
|
|
5952
|
-
exports.url = void 0;
|
|
5948
|
+
exports.lineurl = exports.url = void 0;
|
|
5953
5949
|
const combinator_1 = __webpack_require__(2087);
|
|
5954
5950
|
const link_1 = __webpack_require__(9628);
|
|
5955
5951
|
const source_1 = __webpack_require__(6743);
|
|
5956
5952
|
const closer = /^[-+*=~^_,.;:!?]*(?=[\\"`|\[\](){}<>]|$)/;
|
|
5957
5953
|
exports.url = (0, combinator_1.lazy)(() => (0, combinator_1.validate)(['http://', 'https://'], (0, combinator_1.rewrite)((0, combinator_1.open)(/^https?:\/\/(?=[\x21-\x7E])/, (0, combinator_1.focus)(/^[\x21-\x7E]+/, (0, combinator_1.some)((0, combinator_1.union)([bracket, (0, combinator_1.some)(source_1.unescsource, closer)])))), (0, combinator_1.convert)(url => `{ ${url} }`, (0, combinator_1.union)([link_1.unsafelink])))));
|
|
5954
|
+
exports.lineurl = (0, combinator_1.open)(source_1.linebreak, (0, combinator_1.tails)([(0, source_1.str)('!'), (0, combinator_1.focus)(/^https?:\/\/\S+(?=[^\S\n]*(?:$|\n))/, (0, combinator_1.convert)(url => `{ ${url} }`, link_1.unsafelink))]));
|
|
5958
5955
|
const bracket = (0, combinator_1.lazy)(() => (0, combinator_1.creation)((0, combinator_1.precedence)(2, (0, combinator_1.union)([(0, combinator_1.surround)('(', (0, combinator_1.some)((0, combinator_1.union)([bracket, source_1.unescsource]), ')'), ')', true), (0, combinator_1.surround)('[', (0, combinator_1.some)((0, combinator_1.union)([bracket, source_1.unescsource]), ']'), ']', true), (0, combinator_1.surround)('{', (0, combinator_1.some)((0, combinator_1.union)([bracket, source_1.unescsource]), '}'), '}', true), (0, combinator_1.surround)('"', (0, combinator_1.precedence)(8, (0, combinator_1.some)(source_1.unescsource, '"')), '"', true)]))));
|
|
5959
5956
|
|
|
5960
5957
|
/***/ }),
|
|
@@ -6143,12 +6140,13 @@ function identity(id, text, name = 'index') {
|
|
|
6143
6140
|
if (id === '') return undefined;
|
|
6144
6141
|
text &&= text.trim().replace(/\s+/g, '_');
|
|
6145
6142
|
if (text === '') return undefined;
|
|
6146
|
-
|
|
6143
|
+
const cs = [...text];
|
|
6144
|
+
if (cs.length <= 100) return `${name}:${id ?? ''}:${text}`;
|
|
6147
6145
|
switch (name) {
|
|
6148
6146
|
case 'index':
|
|
6149
|
-
return `${name}:${id ?? ''}:${
|
|
6147
|
+
return `${name}:${id ?? ''}:${cs.slice(0, 97).join('')}...`;
|
|
6150
6148
|
case 'mark':
|
|
6151
|
-
return `${name}:${id ?? ''}:${
|
|
6149
|
+
return `${name}:${id ?? ''}:${cs.slice(0, 50).join('')}...${cs.slice(-47).join('')}`;
|
|
6152
6150
|
}
|
|
6153
6151
|
}
|
|
6154
6152
|
exports.identity = identity;
|
|
@@ -6418,7 +6416,7 @@ exports.insertion = (0, combinator_1.lazy)(() => (0, combinator_1.surround)((0,
|
|
|
6418
6416
|
Object.defineProperty(exports, "__esModule", ({
|
|
6419
6417
|
value: true
|
|
6420
6418
|
}));
|
|
6421
|
-
exports.resolve = exports.option = exports.uri = exports.unsafelink = exports.link = void 0;
|
|
6419
|
+
exports.resolve = exports.option = exports.uri = exports.unsafelink = exports.linemedialink = exports.medialink = exports.textlink = exports.link = void 0;
|
|
6422
6420
|
const combinator_1 = __webpack_require__(2087);
|
|
6423
6421
|
const inline_1 = __webpack_require__(1160);
|
|
6424
6422
|
const html_1 = __webpack_require__(5994);
|
|
@@ -6431,11 +6429,12 @@ const optspec = {
|
|
|
6431
6429
|
rel: ['nofollow']
|
|
6432
6430
|
};
|
|
6433
6431
|
Object.setPrototypeOf(optspec, null);
|
|
6434
|
-
exports.link = (0, combinator_1.lazy)(() => (0, combinator_1.validate)(['[', '{'], (0, combinator_1.union)([medialink, textlink])));
|
|
6435
|
-
|
|
6432
|
+
exports.link = (0, combinator_1.lazy)(() => (0, combinator_1.validate)(['[', '{'], (0, combinator_1.union)([exports.medialink, exports.textlink])));
|
|
6433
|
+
exports.textlink = (0, combinator_1.lazy)(() => (0, combinator_1.constraint)(16 /* State.link */, false, (0, combinator_1.syntax)(16 /* Syntax.link */, 2, 10, 502 /* State.linkers */ | 8 /* State.media */, (0, combinator_1.bind)((0, combinator_1.reverse)((0, combinator_1.tails)([(0, combinator_1.dup)((0, combinator_1.surround)('[', (0, combinator_1.some)((0, combinator_1.union)([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]*}/))])), ([params, content = []], rest, context) => {
|
|
6436
6434
|
return parse(content, params, rest, context);
|
|
6437
6435
|
}))));
|
|
6438
|
-
|
|
6436
|
+
exports.medialink = (0, combinator_1.lazy)(() => (0, combinator_1.constraint)(16 /* State.link */ | 8 /* State.media */, false, (0, combinator_1.syntax)(16 /* Syntax.link */, 2, 10, 502 /* State.linkers */, (0, combinator_1.bind)((0, combinator_1.reverse)((0, combinator_1.sequence)([(0, combinator_1.dup)((0, combinator_1.surround)('[', (0, combinator_1.union)([inline_1.media, inline_1.shortmedia]), ']')), (0, combinator_1.dup)((0, combinator_1.surround)(/^{(?![{}])/, (0, combinator_1.inits)([exports.uri, (0, combinator_1.some)(exports.option)]), /^[^\S\n]*}/))])), ([params, content = []], rest, context) => parse(content, params, rest, context)))));
|
|
6437
|
+
exports.linemedialink = (0, combinator_1.surround)(source_1.linebreak, (0, combinator_1.union)([exports.medialink]), /^(?=[^\S\n]*(?:$|\n))/);
|
|
6439
6438
|
exports.unsafelink = (0, combinator_1.lazy)(() => (0, combinator_1.creation)(10, (0, combinator_1.precedence)(2, (0, combinator_1.bind)((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) => parse(content, params, rest, context)))));
|
|
6440
6439
|
exports.uri = (0, combinator_1.union)([(0, combinator_1.open)(/^[^\S\n]+/, (0, source_1.str)(/^\S+/)), (0, source_1.str)(/^[^\s{}]+/)]);
|
|
6441
6440
|
exports.option = (0, combinator_1.union)([(0, combinator_1.fmap)((0, source_1.str)(/^[^\S\n]+nofollow(?=[^\S\n]|})/), () => [` rel="nofollow"`]), (0, source_1.str)(/^[^\S\n]+[a-z]+(?:-[a-z]+)*(?:="(?:\\[^\n]|[^\\\n"])*")?(?=[^\S\n]|})/), (0, combinator_1.fmap)((0, source_1.str)(/^[^\S\n]+[^\s{}]+/), opt => [` \\${opt.slice(1)}`])]);
|
|
@@ -6600,7 +6599,7 @@ const bracket = (0, combinator_1.lazy)(() => (0, combinator_1.creation)((0, comb
|
|
|
6600
6599
|
Object.defineProperty(exports, "__esModule", ({
|
|
6601
6600
|
value: true
|
|
6602
6601
|
}));
|
|
6603
|
-
exports.media = void 0;
|
|
6602
|
+
exports.linemedia = exports.media = void 0;
|
|
6604
6603
|
const combinator_1 = __webpack_require__(2087);
|
|
6605
6604
|
const link_1 = __webpack_require__(9628);
|
|
6606
6605
|
const html_1 = __webpack_require__(5994);
|
|
@@ -6645,6 +6644,7 @@ exports.media = (0, combinator_1.lazy)(() => (0, combinator_1.validate)(['![', '
|
|
|
6645
6644
|
context
|
|
6646
6645
|
});
|
|
6647
6646
|
}))))));
|
|
6647
|
+
exports.linemedia = (0, combinator_1.surround)(source_1.linebreak, (0, combinator_1.union)([exports.media]), /^(?=[^\S\n]*(?:$|\n))/);
|
|
6648
6648
|
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)([htmlentity_1.unsafehtmlentity, bracket, source_1.txt]), ')'), (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.some)((0, combinator_1.union)([htmlentity_1.unsafehtmlentity, bracket, source_1.txt]), ']'), (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.some)((0, combinator_1.union)([htmlentity_1.unsafehtmlentity, bracket, source_1.txt]), '}'), (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.precedence)(8, (0, combinator_1.some)((0, combinator_1.union)([htmlentity_1.unsafehtmlentity, source_1.txt]), '"')), (0, source_1.str)('"'), true)])));
|
|
6649
6649
|
const option = (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]);
|
|
6650
6650
|
function sanitize(target, uri, alt) {
|
|
@@ -6824,11 +6824,13 @@ function attributes(texts, rubies) {
|
|
|
6824
6824
|
Object.defineProperty(exports, "__esModule", ({
|
|
6825
6825
|
value: true
|
|
6826
6826
|
}));
|
|
6827
|
-
exports.shortmedia = void 0;
|
|
6827
|
+
exports.lineshortmedia = exports.shortmedia = void 0;
|
|
6828
6828
|
const combinator_1 = __webpack_require__(2087);
|
|
6829
6829
|
const url_1 = __webpack_require__(4318);
|
|
6830
6830
|
const media_1 = __webpack_require__(1303);
|
|
6831
|
+
const source_1 = __webpack_require__(6743);
|
|
6831
6832
|
exports.shortmedia = (0, combinator_1.rewrite)((0, combinator_1.constraint)(8 /* State.media */, false, (0, combinator_1.open)('!', url_1.url)), (0, combinator_1.convert)(source => `!{ ${source.slice(1)} }`, (0, combinator_1.union)([media_1.media])));
|
|
6833
|
+
exports.lineshortmedia = (0, combinator_1.open)(source_1.linebreak, (0, combinator_1.focus)(/^!https?:\/\/\S+(?=[^\S\n]*(?:$|\n))/, (0, combinator_1.convert)(source => `!{ ${source.slice(1)} }`, (0, combinator_1.union)([media_1.media]))));
|
|
6832
6834
|
|
|
6833
6835
|
/***/ }),
|
|
6834
6836
|
|
|
@@ -7335,7 +7337,8 @@ const combinator_1 = __webpack_require__(2087);
|
|
|
7335
7337
|
const text_1 = __webpack_require__(7763);
|
|
7336
7338
|
const delimiter = /[\s\x00-\x2F\x3A-\x40\x5B-\x60\x7B-\x7F]/;
|
|
7337
7339
|
exports.escsource = (0, combinator_1.creation)(1, false, ({
|
|
7338
|
-
source
|
|
7340
|
+
source,
|
|
7341
|
+
context
|
|
7339
7342
|
}) => {
|
|
7340
7343
|
if (source === '') return;
|
|
7341
7344
|
const i = source.search(delimiter);
|
|
@@ -7344,6 +7347,9 @@ exports.escsource = (0, combinator_1.creation)(1, false, ({
|
|
|
7344
7347
|
return [[source], ''];
|
|
7345
7348
|
case 0:
|
|
7346
7349
|
switch (source[0]) {
|
|
7350
|
+
case '\r':
|
|
7351
|
+
context.resources && ++context.resources.clock;
|
|
7352
|
+
return [[], source.slice(1)];
|
|
7347
7353
|
case '\x1B':
|
|
7348
7354
|
return [[source.slice(1, 2)], source.slice(2)];
|
|
7349
7355
|
case '\\':
|
|
@@ -7457,6 +7463,9 @@ exports.text = (0, combinator_1.creation)(1, false, ({
|
|
|
7457
7463
|
return [[source], ''];
|
|
7458
7464
|
case 0:
|
|
7459
7465
|
switch (source[0]) {
|
|
7466
|
+
case '\r':
|
|
7467
|
+
context.resources && ++context.resources.clock;
|
|
7468
|
+
return [[], source.slice(1)];
|
|
7460
7469
|
case '\x1B':
|
|
7461
7470
|
case '\\':
|
|
7462
7471
|
switch (source[1]) {
|
|
@@ -7488,7 +7497,7 @@ exports.text = (0, combinator_1.creation)(1, false, ({
|
|
|
7488
7497
|
}
|
|
7489
7498
|
});
|
|
7490
7499
|
exports.txt = (0, combinator_1.union)([exports.text]);
|
|
7491
|
-
exports.linebreak = (0, combinator_1.focus)(
|
|
7500
|
+
exports.linebreak = (0, combinator_1.focus)(/^[\r\n]/, (0, combinator_1.union)([exports.text]));
|
|
7492
7501
|
function isAlphanumeric(char) {
|
|
7493
7502
|
if (char < '0' || '\x7F' < char) return false;
|
|
7494
7503
|
return '0' <= char && char <= '9' || 'a' <= char && char <= 'z' || 'A' <= char && char <= 'Z';
|
|
@@ -7510,7 +7519,8 @@ exports.unescsource = void 0;
|
|
|
7510
7519
|
const combinator_1 = __webpack_require__(2087);
|
|
7511
7520
|
const text_1 = __webpack_require__(7763);
|
|
7512
7521
|
exports.unescsource = (0, combinator_1.creation)(1, false, ({
|
|
7513
|
-
source
|
|
7522
|
+
source,
|
|
7523
|
+
context
|
|
7514
7524
|
}) => {
|
|
7515
7525
|
if (source === '') return;
|
|
7516
7526
|
const i = source.search(text_1.delimiter);
|
|
@@ -7519,6 +7529,11 @@ exports.unescsource = (0, combinator_1.creation)(1, false, ({
|
|
|
7519
7529
|
return [[source], ''];
|
|
7520
7530
|
case 0:
|
|
7521
7531
|
{
|
|
7532
|
+
switch (source[0]) {
|
|
7533
|
+
case '\r':
|
|
7534
|
+
context.resources && ++context.resources.clock;
|
|
7535
|
+
return [[], source.slice(1)];
|
|
7536
|
+
}
|
|
7522
7537
|
const b = source[0] !== '\n' && source[0].trimStart() === '';
|
|
7523
7538
|
const i = b || (0, text_1.isAlphanumeric)(source[0]) ? source.search(b ? text_1.nonWhitespace : text_1.nonAlphanumeric) || 1 : 1;
|
|
7524
7539
|
return [[source.slice(0, i - +b || 1)], source.slice(i - +b || 1)];
|
|
@@ -7531,7 +7546,7 @@ exports.unescsource = (0, combinator_1.creation)(1, false, ({
|
|
|
7531
7546
|
/***/ }),
|
|
7532
7547
|
|
|
7533
7548
|
/***/ 9437:
|
|
7534
|
-
/***/ ((__unused_webpack_module, exports
|
|
7549
|
+
/***/ ((__unused_webpack_module, exports) => {
|
|
7535
7550
|
|
|
7536
7551
|
"use strict";
|
|
7537
7552
|
|
|
@@ -7539,12 +7554,7 @@ exports.unescsource = (0, combinator_1.creation)(1, false, ({
|
|
|
7539
7554
|
Object.defineProperty(exports, "__esModule", ({
|
|
7540
7555
|
value: true
|
|
7541
7556
|
}));
|
|
7542
|
-
exports.stringify =
|
|
7543
|
-
const combinator_1 = __webpack_require__(2087);
|
|
7544
|
-
function format(parser) {
|
|
7545
|
-
return (0, combinator_1.convert)(source => source.replace(/(?<=^!?)https?:\/\/(?:[[]|[^\p{C}\p{S}\p{P}\s])\S*(?=[^\S\n]*(?:$|\n))/gm, '{ $& }'), parser);
|
|
7546
|
-
}
|
|
7547
|
-
exports.format = format;
|
|
7557
|
+
exports.stringify = void 0;
|
|
7548
7558
|
function stringify(nodes) {
|
|
7549
7559
|
let acc = '';
|
|
7550
7560
|
for (let i = 0; i < nodes.length; ++i) {
|
|
@@ -7576,13 +7586,12 @@ const parser_1 = __webpack_require__(6728);
|
|
|
7576
7586
|
const combinator_1 = __webpack_require__(2087);
|
|
7577
7587
|
const htmlentity_1 = __webpack_require__(1562);
|
|
7578
7588
|
const source_1 = __webpack_require__(6743);
|
|
7579
|
-
const util_1 = __webpack_require__(9437);
|
|
7580
7589
|
const normalize_1 = __webpack_require__(185);
|
|
7581
7590
|
const memoize_1 = __webpack_require__(1808);
|
|
7582
7591
|
const array_1 = __webpack_require__(8112);
|
|
7583
7592
|
function visualize(parser) {
|
|
7584
7593
|
const blankline = new RegExp(/^(?:\\$|\\?[^\S\n]|&IHN;|<wbr[^\S\n]*>)+$/.source.replace('IHN', `(?:${normalize_1.invisibleHTMLEntityNames.join('|')})`), 'gm');
|
|
7585
|
-
return (0, combinator_1.union)([(0, combinator_1.convert)(source => source.replace(blankline, line => line.replace(/[\\&<]/g, '\x1B$&')), (0, combinator_1.verify)(
|
|
7594
|
+
return (0, combinator_1.union)([(0, combinator_1.convert)(source => source.replace(blankline, line => line.replace(/[\\&<]/g, '\x1B$&')), (0, combinator_1.verify)(parser, (ns, rest, context) => !rest && hasVisible(ns, context))), (0, combinator_1.some)((0, combinator_1.union)([source_1.linebreak, source_1.unescsource]))]);
|
|
7586
7595
|
}
|
|
7587
7596
|
exports.visualize = visualize;
|
|
7588
7597
|
function hasVisible(nodes, {
|
|
@@ -8388,7 +8397,7 @@ function unlink(h) {
|
|
|
8388
8397
|
/***/ 3252:
|
|
8389
8398
|
/***/ (function(module) {
|
|
8390
8399
|
|
|
8391
|
-
/*! typed-dom v0.0.
|
|
8400
|
+
/*! typed-dom v0.0.317 https://github.com/falsandtru/typed-dom | (c) 2016, falsandtru | (Apache-2.0 AND MPL-2.0) License */
|
|
8392
8401
|
(function webpackUniversalModuleDefinition(root, factory) {
|
|
8393
8402
|
if(true)
|
|
8394
8403
|
module.exports = factory();
|
|
@@ -8719,7 +8728,7 @@ exports.defrag = defrag;
|
|
|
8719
8728
|
/***/ 6120:
|
|
8720
8729
|
/***/ (function(module) {
|
|
8721
8730
|
|
|
8722
|
-
/*! typed-dom v0.0.
|
|
8731
|
+
/*! typed-dom v0.0.317 https://github.com/falsandtru/typed-dom | (c) 2016, falsandtru | (Apache-2.0 AND MPL-2.0) License */
|
|
8723
8732
|
(function webpackUniversalModuleDefinition(root, factory) {
|
|
8724
8733
|
if(true)
|
|
8725
8734
|
module.exports = factory();
|
package/markdown.d.ts
CHANGED
|
@@ -346,7 +346,7 @@ export namespace MarkdownParser {
|
|
|
346
346
|
BlockquoteParser,
|
|
347
347
|
PlaceholderParser,
|
|
348
348
|
InlineParser.MediaParser,
|
|
349
|
-
InlineParser.
|
|
349
|
+
InlineParser.ShortMediaParser,
|
|
350
350
|
]>,
|
|
351
351
|
SourceParser.EmptyLineParser,
|
|
352
352
|
InlineParser,
|
|
@@ -598,13 +598,10 @@ export namespace MarkdownParser {
|
|
|
598
598
|
export interface TextParser extends
|
|
599
599
|
Block<'reply/quote/text'>,
|
|
600
600
|
Parser<string | HTMLElement, Context, [
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
SourceParser.LinebreakParser,
|
|
606
|
-
SourceParser.UnescapableSourceParser,
|
|
607
|
-
]>,
|
|
601
|
+
InlineParser.MathParser,
|
|
602
|
+
InlineParser.AutolinkParser,
|
|
603
|
+
SourceParser.LinebreakParser,
|
|
604
|
+
SourceParser.UnescapableSourceParser,
|
|
608
605
|
]> {
|
|
609
606
|
}
|
|
610
607
|
export interface PlaceholderParser extends
|
|
@@ -633,8 +630,9 @@ export namespace MarkdownParser {
|
|
|
633
630
|
InlineParser.MathParser,
|
|
634
631
|
InlineParser.ExtensionParser,
|
|
635
632
|
InlineParser.RubyParser,
|
|
636
|
-
InlineParser.LinkParser,
|
|
637
|
-
InlineParser.
|
|
633
|
+
InlineParser.LinkParser.TextLinkParser,
|
|
634
|
+
InlineParser.LinkParser.LineMediaLinkParser,
|
|
635
|
+
InlineParser.MediaParser.LineMediaParser,
|
|
638
636
|
InlineParser.HTMLParser,
|
|
639
637
|
InlineParser.InsertionParser,
|
|
640
638
|
InlineParser.DeletionParser,
|
|
@@ -643,7 +641,7 @@ export namespace MarkdownParser {
|
|
|
643
641
|
InlineParser.EmphasisParser,
|
|
644
642
|
InlineParser.CodeParser,
|
|
645
643
|
InlineParser.HTMLEntityParser,
|
|
646
|
-
InlineParser.
|
|
644
|
+
InlineParser.ShortMediaParser.LineShortMediaParser,
|
|
647
645
|
InlineParser.AutolinkParser,
|
|
648
646
|
InlineParser.BracketParser,
|
|
649
647
|
SourceParser.TextParser,
|
|
@@ -842,6 +840,12 @@ export namespace MarkdownParser {
|
|
|
842
840
|
]> {
|
|
843
841
|
}
|
|
844
842
|
export namespace LinkParser {
|
|
843
|
+
export interface LineMediaLinkParser extends
|
|
844
|
+
Inline<'link/linemedialink'>,
|
|
845
|
+
Parser<HTMLElement, Context, [
|
|
846
|
+
LinkParser.MediaLinkParser,
|
|
847
|
+
]> {
|
|
848
|
+
}
|
|
845
849
|
export interface TextLinkParser extends
|
|
846
850
|
Inline<'link/textlink'>,
|
|
847
851
|
Parser<HTMLAnchorElement, Context, [
|
|
@@ -856,7 +860,7 @@ export namespace MarkdownParser {
|
|
|
856
860
|
Parser<HTMLAnchorElement, Context, [
|
|
857
861
|
Parser<HTMLElement[], Context, [
|
|
858
862
|
MediaParser,
|
|
859
|
-
|
|
863
|
+
ShortMediaParser,
|
|
860
864
|
]>,
|
|
861
865
|
LinkParser.ParameterParser,
|
|
862
866
|
]> {
|
|
@@ -872,7 +876,7 @@ export namespace MarkdownParser {
|
|
|
872
876
|
Inline<'link/content'>,
|
|
873
877
|
Parser<(HTMLElement | string)[], Context, [
|
|
874
878
|
MediaParser,
|
|
875
|
-
|
|
879
|
+
ShortMediaParser,
|
|
876
880
|
InlineParser,
|
|
877
881
|
]> {
|
|
878
882
|
}
|
|
@@ -917,6 +921,12 @@ export namespace MarkdownParser {
|
|
|
917
921
|
]> {
|
|
918
922
|
}
|
|
919
923
|
export namespace MediaParser {
|
|
924
|
+
export interface LineMediaParser extends
|
|
925
|
+
Inline<'media/linemedia'>,
|
|
926
|
+
Parser<HTMLElement, Context, [
|
|
927
|
+
MediaParser,
|
|
928
|
+
]> {
|
|
929
|
+
}
|
|
920
930
|
export interface TextParser extends
|
|
921
931
|
Inline<'media/text'>,
|
|
922
932
|
Parser<string[], Context, [
|
|
@@ -1060,28 +1070,41 @@ export namespace MarkdownParser {
|
|
|
1060
1070
|
Inline<'unsafehtmlentity'>,
|
|
1061
1071
|
Parser<string, Context, []> {
|
|
1062
1072
|
}
|
|
1063
|
-
export interface
|
|
1073
|
+
export interface ShortMediaParser extends
|
|
1064
1074
|
// !https://host
|
|
1065
1075
|
Inline<'shortmedia'>,
|
|
1066
1076
|
Parser<HTMLElement, Context, [
|
|
1067
1077
|
MediaParser,
|
|
1068
1078
|
]> {
|
|
1069
1079
|
}
|
|
1080
|
+
export namespace ShortMediaParser {
|
|
1081
|
+
export interface LineShortMediaParser extends
|
|
1082
|
+
Inline<'shortmedia/lineshortmedia'>,
|
|
1083
|
+
Parser<HTMLElement, Context, [
|
|
1084
|
+
MediaParser,
|
|
1085
|
+
]> {
|
|
1086
|
+
}
|
|
1087
|
+
}
|
|
1070
1088
|
export interface AutolinkParser extends
|
|
1071
1089
|
Inline<'autolink'>,
|
|
1072
1090
|
Parser<HTMLElement | string, Context, [
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1091
|
+
Parser<HTMLElement | string, Context, [
|
|
1092
|
+
AutolinkParser.UrlParser.LineUrlParser,
|
|
1093
|
+
]>,
|
|
1094
|
+
Parser<HTMLElement | string, Context, [
|
|
1095
|
+
AutolinkParser.UrlParser,
|
|
1096
|
+
AutolinkParser.EmailParser,
|
|
1097
|
+
SourceParser.StrParser,
|
|
1098
|
+
AutolinkParser.ChannelParser,
|
|
1099
|
+
AutolinkParser.AccountParser,
|
|
1100
|
+
SourceParser.StrParser,
|
|
1101
|
+
SourceParser.StrParser,
|
|
1102
|
+
AutolinkParser.HashtagParser,
|
|
1103
|
+
AutolinkParser.HashnumParser,
|
|
1104
|
+
SourceParser.StrParser,
|
|
1105
|
+
SourceParser.StrParser,
|
|
1106
|
+
AutolinkParser.AnchorParser,
|
|
1107
|
+
]>,
|
|
1085
1108
|
]> {
|
|
1086
1109
|
}
|
|
1087
1110
|
export namespace AutolinkParser {
|
|
@@ -1093,6 +1116,13 @@ export namespace MarkdownParser {
|
|
|
1093
1116
|
]> {
|
|
1094
1117
|
}
|
|
1095
1118
|
export namespace UrlParser {
|
|
1119
|
+
export interface LineUrlParser extends
|
|
1120
|
+
Inline<'url/lineurl'>,
|
|
1121
|
+
Parser<string | HTMLElement, Context, [
|
|
1122
|
+
SourceParser.StrParser,
|
|
1123
|
+
InlineParser.LinkParser.UnsafeLinkParser,
|
|
1124
|
+
]> {
|
|
1125
|
+
}
|
|
1096
1126
|
export interface BracketParser extends
|
|
1097
1127
|
Inline<'url/bracket'>,
|
|
1098
1128
|
Parser<string, Context, [
|
|
@@ -1176,23 +1206,11 @@ export namespace MarkdownParser {
|
|
|
1176
1206
|
export interface AutolinkParser extends
|
|
1177
1207
|
Markdown<'autolink'>,
|
|
1178
1208
|
Parser<string | HTMLElement, Context, [
|
|
1179
|
-
AutolinkParser
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
SourceParser.LinebreakParser,
|
|
1183
|
-
SourceParser.UnescapableSourceParser,
|
|
1184
|
-
]>,
|
|
1209
|
+
InlineParser.AutolinkParser,
|
|
1210
|
+
SourceParser.LinebreakParser,
|
|
1211
|
+
SourceParser.UnescapableSourceParser,
|
|
1185
1212
|
]> {
|
|
1186
1213
|
}
|
|
1187
|
-
export namespace AutolinkParser {
|
|
1188
|
-
export interface LineUrlParser extends
|
|
1189
|
-
Markdown<'autolink/lineurl'>,
|
|
1190
|
-
Parser<string | HTMLElement, Context, [
|
|
1191
|
-
SourceParser.StrParser,
|
|
1192
|
-
InlineParser.LinkParser,
|
|
1193
|
-
]> {
|
|
1194
|
-
}
|
|
1195
|
-
}
|
|
1196
1214
|
export namespace SourceParser {
|
|
1197
1215
|
interface Source<T extends string> extends Markdown<`source/${T}`> { }
|
|
1198
1216
|
export interface TextParser extends
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "securemark",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.269.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",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"@types/mocha": "10.0.1",
|
|
35
35
|
"@types/power-assert": "1.5.8",
|
|
36
36
|
"@types/prismjs": "1.26.0",
|
|
37
|
-
"@typescript-eslint/parser": "^5.
|
|
37
|
+
"@typescript-eslint/parser": "^5.54.0",
|
|
38
38
|
"babel-loader": "^9.1.2",
|
|
39
39
|
"babel-plugin-unassert": "^3.2.0",
|
|
40
40
|
"concurrently": "^7.6.0",
|
|
@@ -49,11 +49,11 @@
|
|
|
49
49
|
"karma-mocha": "^2.0.1",
|
|
50
50
|
"karma-power-assert": "^1.0.0",
|
|
51
51
|
"mocha": "^10.2.0",
|
|
52
|
-
"npm-check-updates": "^16.7.
|
|
52
|
+
"npm-check-updates": "^16.7.10",
|
|
53
53
|
"semver": "^7.3.8",
|
|
54
54
|
"spica": "0.0.719",
|
|
55
55
|
"ts-loader": "^9.4.2",
|
|
56
|
-
"typed-dom": "^0.0.
|
|
56
|
+
"typed-dom": "^0.0.317",
|
|
57
57
|
"typescript": "4.9.5",
|
|
58
58
|
"webpack": "^5.75.0",
|
|
59
59
|
"webpack-cli": "^5.0.1",
|
|
@@ -6,8 +6,8 @@ describe('Unit: parser/autolink', () => {
|
|
|
6
6
|
const parser = (source: string) => autolink({ source, context: {} });
|
|
7
7
|
|
|
8
8
|
it('basic', () => {
|
|
9
|
-
assert.deepStrictEqual(inspect(parser('
|
|
10
|
-
assert.deepStrictEqual(inspect(parser('!http://host')), [['!', '<a class="url" href="http://host" target="_blank">http://host
|
|
9
|
+
assert.deepStrictEqual(inspect(parser('http://host#\\')), [['<a class="url" href="http://host#\\" target="_blank">http://host#\\</a>'], '']);
|
|
10
|
+
assert.deepStrictEqual(inspect(parser('!http://host#\\')), [['!', '<a class="url" href="http://host#\\" target="_blank">http://host#\\</a>'], '']);
|
|
11
11
|
assert.deepStrictEqual(inspect(parser('#a')), [['<a class="hashtag" href="/hashtags/a">#a</a>'], '']);
|
|
12
12
|
assert.deepStrictEqual(inspect(parser('@a#b')), [['<a class="channel" href="/@a?ch=b">@a#b</a>'], '']);
|
|
13
13
|
assert.deepStrictEqual(inspect(parser('\\\n')), [['\\', '<br>'], '']);
|
package/src/parser/autolink.ts
CHANGED
|
@@ -1,21 +1,14 @@
|
|
|
1
1
|
import { MarkdownParser } from '../../markdown';
|
|
2
|
-
import { union,
|
|
3
|
-
import { link } from './inline/link';
|
|
2
|
+
import { union, some, convert, lazy } from '../combinator';
|
|
4
3
|
import { autolink as autolink_ } from './inline/autolink';
|
|
5
|
-
import { linebreak, unescsource
|
|
6
|
-
import { format } from './util';
|
|
4
|
+
import { linebreak, unescsource } from './source';
|
|
7
5
|
|
|
8
6
|
export import AutolinkParser = MarkdownParser.AutolinkParser;
|
|
9
7
|
|
|
10
|
-
export const autolink: AutolinkParser = lazy(() =>
|
|
11
|
-
|
|
8
|
+
export const autolink: AutolinkParser = lazy(() =>
|
|
9
|
+
convert(source => `\r${source}`,
|
|
12
10
|
some(union([
|
|
13
11
|
autolink_,
|
|
14
12
|
linebreak,
|
|
15
13
|
unescsource,
|
|
16
|
-
]))
|
|
17
|
-
]))));
|
|
18
|
-
|
|
19
|
-
export const lineurl: AutolinkParser.LineUrlParser = lazy(() => focus(
|
|
20
|
-
/^!?https?:\/\/\S+(?=[^\S\n]*(?:$|\n))/,
|
|
21
|
-
format(tails([str('!'), link]))));
|
|
14
|
+
]))));
|
|
@@ -30,9 +30,11 @@ describe('Unit: parser/block/paragraph', () => {
|
|
|
30
30
|
assert.deepStrictEqual(inspect(parser('_a\n<wbr>_\nb')), [['<p>_a<br><wbr>_<br>b</p>'], '']);
|
|
31
31
|
assert.deepStrictEqual(inspect(parser('*a\n<wbr>*\nb')), [['<p>*a<br><wbr>*<br>b</p>'], '']);
|
|
32
32
|
assert.deepStrictEqual(inspect(parser('==a\n<wbr>==\nb')), [['<p>==a<br><wbr>==<br>b</p>'], '']);
|
|
33
|
-
assert.deepStrictEqual(inspect(parser('http://host
|
|
33
|
+
assert.deepStrictEqual(inspect(parser('http://host#\\')), [['<p><a class="url" href="http://host#\\" target="_blank">http://host#\\</a></p>'], '']);
|
|
34
34
|
assert.deepStrictEqual(inspect(parser('a\nhttp://host#\\ \nb')), [['<p>a<br><a class="url" href="http://host#\\" target="_blank">http://host#\\</a><br>b</p>'], '']);
|
|
35
|
-
assert.deepStrictEqual(inspect(parser('!http://host
|
|
35
|
+
assert.deepStrictEqual(inspect(parser('!http://host#\\')), [['<p><a href="http://host#\\" target="_blank"><img class="media" data-src="http://host#\\" alt=""></a></p>'], '']);
|
|
36
|
+
assert.deepStrictEqual(inspect(parser('!http://host#\\ a')), [['<p>!<a class="url" href="http://host#" target="_blank">http://host#</a> a</p>'], '']);
|
|
37
|
+
assert.deepStrictEqual(inspect(parser(' !http://host#\\')), [['<p> !<a class="url" href="http://host#" target="_blank">http://host#</a></p>'], '']);
|
|
36
38
|
assert.deepStrictEqual(inspect(parser('\ta')), [['<p>\ta</p>'], '']);
|
|
37
39
|
});
|
|
38
40
|
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { ParagraphParser } from '../block';
|
|
2
|
-
import { union, some, block, trimEnd, fmap } from '../../combinator';
|
|
2
|
+
import { union, some, block, convert, trimEnd, fmap } from '../../combinator';
|
|
3
3
|
import { inline } from '../inline';
|
|
4
4
|
import { visualize } from '../visibility';
|
|
5
5
|
import { html, defrag } from 'typed-dom/dom';
|
|
6
6
|
|
|
7
7
|
export const paragraph: ParagraphParser = block(fmap(
|
|
8
|
-
|
|
8
|
+
convert(source => `\r${source}`,
|
|
9
|
+
visualize(trimEnd(some(union([inline]))))),
|
|
9
10
|
ns => [html('p', defrag(ns))]));
|
|
@@ -55,9 +55,9 @@ describe('Unit: parser/block/reply/quote', () => {
|
|
|
55
55
|
assert.deepStrictEqual(inspect(parser('> $-a, $-b')), [['<span class="quote">> $-a, $-b</span>', '<br>'], '']);
|
|
56
56
|
assert.deepStrictEqual(inspect(parser('> $a=b$')), [['<span class="quote">> <span class="math" translate="no" data-src="$a=b$">$a=b$</span></span>', '<br>'], '']);
|
|
57
57
|
assert.deepStrictEqual(inspect(parser('> ${a}$')), [['<span class="quote">> <span class="math" translate="no" data-src="${a}$">${a}$</span></span>', '<br>'], '']);
|
|
58
|
-
assert.deepStrictEqual(inspect(parser('> http://host
|
|
58
|
+
assert.deepStrictEqual(inspect(parser('> http://host#\\')), [['<span class="quote">> <a class="url" href="http://host#\\" target="_blank">http://host#\\</a></span>', '<br>'], '']);
|
|
59
59
|
assert.deepStrictEqual(inspect(parser('> a\n> http://host#\\ \n> b')), [['<span class="quote">> a<br>> <a class="url" href="http://host#\\" target="_blank">http://host#\\</a> <br>> b</span>', '<br>'], '']);
|
|
60
|
-
assert.deepStrictEqual(inspect(parser('> !http://host
|
|
60
|
+
assert.deepStrictEqual(inspect(parser('> !http://host#\\')), [['<span class="quote">> !<a class="url" href="http://host#\\" target="_blank">http://host#\\</a></span>', '<br>'], '']);
|
|
61
61
|
});
|
|
62
62
|
|
|
63
63
|
});
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { ReplyParser } from '../../block';
|
|
2
2
|
import { eval } from '../../../combinator/data/parser';
|
|
3
|
-
import { union,
|
|
3
|
+
import { union, some, creation, block, line, validate, rewrite, lazy, fmap } from '../../../combinator';
|
|
4
4
|
import { math } from '../../inline/math';
|
|
5
5
|
import { autolink } from '../../inline/autolink';
|
|
6
6
|
import { linebreak, unescsource, str, anyline } from '../../source';
|
|
7
|
-
import { lineurl } from '../../autolink';
|
|
8
7
|
import { html, defrag } from 'typed-dom/dom';
|
|
9
8
|
|
|
10
9
|
export const syntax = /^>+(?=[^\S\n])|^>(?=[^\s>])|^>+(?=[^\s>])(?![0-9a-z]+(?:-[0-9a-z]+)*(?![0-9A-Za-z@#:]))/;
|
|
@@ -42,7 +41,7 @@ const qblock: ReplyParser.QuoteParser.BlockParser = ({ source, context }) => {
|
|
|
42
41
|
assert(quotes);
|
|
43
42
|
assert(quotes.length > 0);
|
|
44
43
|
const content = lines.reduce((acc, line, i) => acc + line.slice(quotes[i].length), '');
|
|
45
|
-
const nodes = eval(text({ source: content
|
|
44
|
+
const nodes = eval(text({ source: `\r${content}`, context }), []);
|
|
46
45
|
nodes.unshift(quotes.shift()!);
|
|
47
46
|
for (let i = 0; i < nodes.length; ++i) {
|
|
48
47
|
const child = nodes[i] as string | Text | Element;
|
|
@@ -72,12 +71,9 @@ const qblock: ReplyParser.QuoteParser.BlockParser = ({ source, context }) => {
|
|
|
72
71
|
return [nodes, ''];
|
|
73
72
|
};
|
|
74
73
|
|
|
75
|
-
const text: ReplyParser.QuoteParser.TextParser = some(
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
unescsource,
|
|
82
|
-
])),
|
|
83
|
-
])));
|
|
74
|
+
const text: ReplyParser.QuoteParser.TextParser = some(union([
|
|
75
|
+
math, // quote補助関数が残した数式をパースする。他の構文で数式を残す場合はソーステキストを直接使用する。
|
|
76
|
+
autolink,
|
|
77
|
+
linebreak,
|
|
78
|
+
unescsource,
|
|
79
|
+
]));
|
|
@@ -28,6 +28,8 @@ describe('Unit: parser/inline/autolink/url', () => {
|
|
|
28
28
|
assert.deepStrictEqual(inspect(parser('http://a#( )')), [['<a class="url" href="http://a#" target="_blank">http://a#</a>'], '( )']);
|
|
29
29
|
assert.deepStrictEqual(inspect(parser('http://a#(\n)')), [['<a class="url" href="http://a#" target="_blank">http://a#</a>'], '(\n)']);
|
|
30
30
|
assert.deepStrictEqual(inspect(parser('http://[::]')), [['<a class="url" href="http://[::]" target="_blank">http://[::]</a>'], '']);
|
|
31
|
+
assert.deepStrictEqual(inspect(parser('\rhttp://a#\\')), [['<a class="url" href="http://a#\\" target="_blank">http://a#\\</a>'], '']);
|
|
32
|
+
assert.deepStrictEqual(inspect(parser('\rhttp://a#\\\nhttp://b#\\')), [['<a class="url" href="http://a#\\" target="_blank">http://a#\\</a>', '<br>', '<a class="url" href="http://b#\\" target="_blank">http://b#\\</a>'], '']);
|
|
31
33
|
});
|
|
32
34
|
|
|
33
35
|
it('trailing symbols', () => {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { AutolinkParser } from '../../inline';
|
|
2
|
-
import { union, some, creation, precedence, validate, focus, rewrite, convert, surround, open, lazy } from '../../../combinator';
|
|
2
|
+
import { union, tails, some, creation, precedence, validate, focus, rewrite, convert, surround, open, lazy } from '../../../combinator';
|
|
3
3
|
import { unsafelink } from '../link';
|
|
4
|
-
import { unescsource } from '../../source';
|
|
4
|
+
import { linebreak, unescsource, str } from '../../source';
|
|
5
5
|
|
|
6
6
|
const closer = /^[-+*=~^_,.;:!?]*(?=[\\"`|\[\](){}<>]|$)/;
|
|
7
7
|
|
|
@@ -13,6 +13,17 @@ export const url: AutolinkParser.UrlParser = lazy(() => validate(['http://', 'ht
|
|
|
13
13
|
url => `{ ${url} }`,
|
|
14
14
|
union([unsafelink])))));
|
|
15
15
|
|
|
16
|
+
export const lineurl: AutolinkParser.UrlParser.LineUrlParser = open(
|
|
17
|
+
linebreak,
|
|
18
|
+
tails([
|
|
19
|
+
str('!'),
|
|
20
|
+
focus(
|
|
21
|
+
/^https?:\/\/\S+(?=[^\S\n]*(?:$|\n))/,
|
|
22
|
+
convert(
|
|
23
|
+
url => `{ ${url} }`,
|
|
24
|
+
unsafelink)),
|
|
25
|
+
]));
|
|
26
|
+
|
|
16
27
|
const bracket: AutolinkParser.UrlParser.BracketParser = lazy(() => creation(precedence(2, union([
|
|
17
28
|
surround('(', some(union([bracket, unescsource]), ')'), ')', true),
|
|
18
29
|
surround('[', some(union([bracket, unescsource]), ']'), ']', true),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AutolinkParser } from '../inline';
|
|
2
2
|
import { union, some, syntax, constraint, validate, focus, fmap } from '../../combinator';
|
|
3
|
-
import { url } from './autolink/url';
|
|
3
|
+
import { url, lineurl } from './autolink/url';
|
|
4
4
|
import { email } from './autolink/email';
|
|
5
5
|
import { channel } from './autolink/channel';
|
|
6
6
|
import { account } from './autolink/account';
|
|
@@ -11,34 +11,37 @@ import { str } from '../source';
|
|
|
11
11
|
import { Syntax, State } from '../context';
|
|
12
12
|
import { stringify } from '../util';
|
|
13
13
|
|
|
14
|
-
export const autolink: AutolinkParser =
|
|
15
|
-
validate(/^(?:[@#>0-9a-z]|\S[#>])/i,
|
|
14
|
+
export const autolink: AutolinkParser =
|
|
15
|
+
validate(/^(?:[@#>0-9a-z\r\n]|\S[#>])/i,
|
|
16
16
|
constraint(State.autolink, false,
|
|
17
17
|
syntax(Syntax.autolink, 1, 1, ~State.shortcut,
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
(
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
18
|
+
union([
|
|
19
|
+
some(union([lineurl])),
|
|
20
|
+
fmap(some(union([
|
|
21
|
+
url,
|
|
22
|
+
email,
|
|
23
|
+
// Escape unmatched email-like strings.
|
|
24
|
+
focus(
|
|
25
|
+
/^[0-9a-z](?:[_.+-](?=[0-9a-z])|[0-9a-z])*(?:@(?:[0-9a-z]+(?:[.-][0-9a-z]+)*)?)*/i,
|
|
26
|
+
({ source }) => {
|
|
27
|
+
if (source.length > 255 || source.includes('@')) return [[source], ''];
|
|
28
|
+
const i = source.indexOf('_');
|
|
29
|
+
if (i === -1) return [[source], ''];
|
|
30
|
+
return [[source.slice(0, i)], source.slice(i)];
|
|
31
|
+
}),
|
|
32
|
+
channel,
|
|
33
|
+
account,
|
|
34
|
+
// Escape unmatched account-like strings.
|
|
35
|
+
str(/^@+[0-9a-z]*(?:-[0-9a-z]+)*/i),
|
|
36
|
+
// Escape invalid leading characters.
|
|
37
|
+
str(new RegExp(/^(?:[^\p{C}\p{S}\p{P}\s]|emoji)(?=#)/u.source.replace('emoji', emoji), 'u')),
|
|
38
|
+
hashtag,
|
|
39
|
+
hashnum,
|
|
40
|
+
// Escape unmatched hashtag-like strings.
|
|
41
|
+
str(new RegExp(/^#+(?:[^\p{C}\p{S}\p{P}\s]|emoji|')*/u.source.replace('emoji', emoji), 'u')),
|
|
42
|
+
// Escape invalid leading characters.
|
|
43
|
+
str(/^[0-9\p{Sc}](?=>)/u),
|
|
44
|
+
anchor,
|
|
45
|
+
])),
|
|
46
|
+
ns => ns.length === 1 ? ns : [stringify(ns)]),
|
|
47
|
+
]))));
|
|
@@ -14,12 +14,13 @@ export function identity(id: string | undefined, text: string, name: 'index' | '
|
|
|
14
14
|
if (id === '') return undefined;
|
|
15
15
|
text &&= text.trim().replace(/\s+/g, '_');
|
|
16
16
|
if (text === '') return undefined;
|
|
17
|
-
|
|
17
|
+
const cs = [...text];
|
|
18
|
+
if (cs.length <= 100) return `${name}:${id ?? ''}:${text}`;
|
|
18
19
|
switch (name) {
|
|
19
20
|
case 'index':
|
|
20
|
-
return `${name}:${id ?? ''}:${
|
|
21
|
+
return `${name}:${id ?? ''}:${cs.slice(0, 97).join('')}...`;
|
|
21
22
|
case 'mark':
|
|
22
|
-
return `${name}:${id ?? ''}:${
|
|
23
|
+
return `${name}:${id ?? ''}:${cs.slice(0, 50).join('')}...${cs.slice(-47).join('')}`;
|
|
23
24
|
}
|
|
24
25
|
assert(false);
|
|
25
26
|
}
|
|
@@ -48,7 +48,7 @@ describe('Unit: parser/inline/extension/placeholder', () => {
|
|
|
48
48
|
assert.deepStrictEqual(inspect(parser('[^a[% b %][% c %]]')), [['<span class="invalid">a<span class="comment"><input type="checkbox"><span>[% b %]</span></span><span class="comment"><input type="checkbox"><span>[% c %]</span></span></span>'], '']);
|
|
49
49
|
assert.deepStrictEqual(inspect(parser('[^\\]]')), [['<span class="invalid">]</span>'], '']);
|
|
50
50
|
assert.deepStrictEqual(inspect(parser('[^(])]')), [['<span class="invalid"><span class="paren">(])</span></span>'], '']);
|
|
51
|
-
assert.deepStrictEqual(inspect(parser('[^!http://host]')), [['<span class="invalid"
|
|
51
|
+
assert.deepStrictEqual(inspect(parser('[^!http://host]')), [['<span class="invalid">!<a class="url" href="http://host" target="_blank">http://host</a></span>'], '']);
|
|
52
52
|
assert.deepStrictEqual(inspect(parser('[^[% a %]]')), [['<span class="invalid"><span class="comment"><input type="checkbox"><span>[% a %]</span></span></span>'], '']);
|
|
53
53
|
assert.deepStrictEqual(inspect(parser('[^[% a %]b]')), [['<span class="invalid"><span class="comment"><input type="checkbox"><span>[% a %]</span></span>b</span>'], '']);
|
|
54
54
|
});
|
|
@@ -4,7 +4,7 @@ import { Result } from '../../combinator/data/parser';
|
|
|
4
4
|
import { union, inits, tails, sequence, some, constraint, syntax, creation, precedence, validate, surround, open, dup, reverse, lazy, fmap, bind } from '../../combinator';
|
|
5
5
|
import { inline, media, shortmedia } from '../inline';
|
|
6
6
|
import { attributes } from './html';
|
|
7
|
-
import { unescsource, str } from '../source';
|
|
7
|
+
import { linebreak, unescsource, str } from '../source';
|
|
8
8
|
import { Syntax, State } from '../context';
|
|
9
9
|
import { trimNode } from '../visibility';
|
|
10
10
|
import { stringify } from '../util';
|
|
@@ -21,7 +21,7 @@ export const link: LinkParser = lazy(() => validate(['[', '{'], union([
|
|
|
21
21
|
textlink,
|
|
22
22
|
])));
|
|
23
23
|
|
|
24
|
-
const textlink: LinkParser.TextLinkParser = lazy(() =>
|
|
24
|
+
export const textlink: LinkParser.TextLinkParser = lazy(() =>
|
|
25
25
|
constraint(State.link, false,
|
|
26
26
|
syntax(Syntax.link, 2, 10, State.linkers | State.media,
|
|
27
27
|
bind(reverse(tails([
|
|
@@ -37,7 +37,7 @@ const textlink: LinkParser.TextLinkParser = lazy(() =>
|
|
|
37
37
|
return parse(content, params, rest, context);
|
|
38
38
|
}))));
|
|
39
39
|
|
|
40
|
-
const medialink: LinkParser.MediaLinkParser = lazy(() =>
|
|
40
|
+
export const medialink: LinkParser.MediaLinkParser = lazy(() =>
|
|
41
41
|
constraint(State.link | State.media, false,
|
|
42
42
|
syntax(Syntax.link, 2, 10, State.linkers,
|
|
43
43
|
bind(reverse(sequence([
|
|
@@ -50,6 +50,11 @@ const medialink: LinkParser.MediaLinkParser = lazy(() =>
|
|
|
50
50
|
([params, content = []]: [string[], (HTMLElement | string)[]], rest, context) =>
|
|
51
51
|
parse(content, params, rest, context)))));
|
|
52
52
|
|
|
53
|
+
export const linemedialink: LinkParser.LineMediaLinkParser = surround(
|
|
54
|
+
linebreak,
|
|
55
|
+
union([medialink]),
|
|
56
|
+
/^(?=[^\S\n]*(?:$|\n))/);
|
|
57
|
+
|
|
53
58
|
export const unsafelink: LinkParser.UnsafeLinkParser = lazy(() =>
|
|
54
59
|
creation(10, precedence(2,
|
|
55
60
|
bind(reverse(tails([
|
|
@@ -3,7 +3,7 @@ import { union, inits, tails, some, syntax, creation, precedence, constraint, va
|
|
|
3
3
|
import { unsafelink, uri, option as linkoption, resolve } from './link';
|
|
4
4
|
import { attributes } from './html';
|
|
5
5
|
import { unsafehtmlentity } from './htmlentity';
|
|
6
|
-
import { txt, str } from '../source';
|
|
6
|
+
import { txt, linebreak, str } from '../source';
|
|
7
7
|
import { Syntax, State } from '../context';
|
|
8
8
|
import { ReadonlyURL } from 'spica/url';
|
|
9
9
|
import { unshift, push } from 'spica/array';
|
|
@@ -61,6 +61,11 @@ export const media: MediaParser = lazy(() => validate(['![', '!{'], open(
|
|
|
61
61
|
({ source: `{ ${INSECURE_URI}${params.join('')} }${rest}`, context });
|
|
62
62
|
}))))));
|
|
63
63
|
|
|
64
|
+
export const linemedia: MediaParser.LineMediaParser = surround(
|
|
65
|
+
linebreak,
|
|
66
|
+
union([media]),
|
|
67
|
+
/^(?=[^\S\n]*(?:$|\n))/);
|
|
68
|
+
|
|
64
69
|
const bracket: MediaParser.TextParser.BracketParser = lazy(() => creation(union([
|
|
65
70
|
surround(str('('), some(union([unsafehtmlentity, bracket, txt]), ')'), str(')'), true, undefined, ([as, bs = []], rest) => [unshift(as, bs), rest]),
|
|
66
71
|
surround(str('['), some(union([unsafehtmlentity, bracket, txt]), ']'), str(']'), true, undefined, ([as, bs = []], rest) => [unshift(as, bs), rest]),
|
|
@@ -1,12 +1,21 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { union, constraint, rewrite, open, convert } from '../../combinator';
|
|
1
|
+
import { ShortMediaParser } from '../inline';
|
|
2
|
+
import { union, constraint, focus, rewrite, open, convert } from '../../combinator';
|
|
3
3
|
import { url } from './autolink/url';
|
|
4
4
|
import { media } from './media';
|
|
5
|
+
import { linebreak } from '../source';
|
|
5
6
|
import { State } from '../context';
|
|
6
7
|
|
|
7
|
-
export const shortmedia:
|
|
8
|
+
export const shortmedia: ShortMediaParser = rewrite(
|
|
8
9
|
constraint(State.media, false,
|
|
9
10
|
open('!', url)),
|
|
10
11
|
convert(
|
|
11
12
|
source => `!{ ${source.slice(1)} }`,
|
|
12
13
|
union([media])));
|
|
14
|
+
|
|
15
|
+
export const lineshortmedia: ShortMediaParser.LineShortMediaParser = open(
|
|
16
|
+
linebreak,
|
|
17
|
+
focus(
|
|
18
|
+
/^!https?:\/\/\S+(?=[^\S\n]*(?:$|\n))/,
|
|
19
|
+
convert(
|
|
20
|
+
source => `!{ ${source.slice(1)} }`,
|
|
21
|
+
union([media]))));
|
|
@@ -56,11 +56,11 @@ describe('Unit: parser/inline', () => {
|
|
|
56
56
|
assert.deepStrictEqual(inspect(parser('{}')), [['{', '}'], '']);
|
|
57
57
|
assert.deepStrictEqual(inspect(parser('{a}')), [['<a class="url" href="a">a</a>'], '']);
|
|
58
58
|
assert.deepStrictEqual(inspect(parser('{{a}}')), [['<span class="template">{{a}}</span>'], '']);
|
|
59
|
-
assert.deepStrictEqual(inspect(parser('!{}')), [['!', '{', '}'], '']);
|
|
60
|
-
assert.deepStrictEqual(inspect(parser('!{a}')), [['<a href="a" target="_blank"><img class="media" data-src="a" alt=""></a>'], '']);
|
|
61
|
-
assert.deepStrictEqual(inspect(parser('!{{a}}')), [['!', '<span class="template">{{a}}</span>'], '']);
|
|
62
|
-
assert.deepStrictEqual(inspect(parser('!{{{a}}}')), [['!', '<span class="template">{{{a}}}</span>'], '']);
|
|
63
|
-
assert.deepStrictEqual(inspect(parser('!!{a}')), [['!', '<a
|
|
59
|
+
assert.deepStrictEqual(inspect(parser('\r!{}')), [['!', '{', '}'], '']);
|
|
60
|
+
assert.deepStrictEqual(inspect(parser('\r!{a}')), [['<a href="a" target="_blank"><img class="media" data-src="a" alt=""></a>'], '']);
|
|
61
|
+
assert.deepStrictEqual(inspect(parser('\r!{{a}}')), [['!', '<span class="template">{{a}}</span>'], '']);
|
|
62
|
+
assert.deepStrictEqual(inspect(parser('\r!{{{a}}}')), [['!', '<span class="template">{{{a}}}</span>'], '']);
|
|
63
|
+
assert.deepStrictEqual(inspect(parser('\r!!{a}')), [['!', '!', '<a class="url" href="a">a</a>'], '']);
|
|
64
64
|
assert.deepStrictEqual(inspect(parser('${a}')), [['$', '<a class="url" href="a">a</a>'], '']);
|
|
65
65
|
assert.deepStrictEqual(inspect(parser('${{a}}')), [['$', '<span class="template">{{a}}</span>'], '']);
|
|
66
66
|
assert.deepStrictEqual(inspect(parser('${{{a}}}')), [['$', '<span class="template">{{{a}}}</span>'], '']);
|
|
@@ -105,11 +105,8 @@ describe('Unit: parser/inline', () => {
|
|
|
105
105
|
assert.deepStrictEqual(inspect(parser('0http://host')), [['0http', ':', '/', '/', 'host'], '']);
|
|
106
106
|
assert.deepStrictEqual(inspect(parser('0aAhttp://host')), [['0aAhttp', ':', '/', '/', 'host'], '']);
|
|
107
107
|
assert.deepStrictEqual(inspect(parser('?http://host')), [['?', '<a class="url" href="http://host" target="_blank">http://host</a>'], '']);
|
|
108
|
-
assert.deepStrictEqual(inspect(parser('0!http://host')), [['0', '<a href="http://host" target="_blank"
|
|
108
|
+
assert.deepStrictEqual(inspect(parser('0!http://host')), [['0', '!', '<a class="url" href="http://host" target="_blank">http://host</a>'], '']);
|
|
109
109
|
assert.deepStrictEqual(inspect(parser('0?http://host')), [['0', '?', '<a class="url" href="http://host" target="_blank">http://host</a>'], '']);
|
|
110
|
-
assert.deepStrictEqual(inspect(parser('0!!http://host')), [['0', '!', '<a href="http://host" target="_blank"><img class="media" data-src="http://host" alt=""></a>'], '']);
|
|
111
|
-
assert.deepStrictEqual(inspect(parser('0?!http://host')), [['0', '?', '<a href="http://host" target="_blank"><img class="media" data-src="http://host" alt=""></a>'], '']);
|
|
112
|
-
assert.deepStrictEqual(inspect(parser('0!?http://host')), [['0', '!', '?', '<a class="url" href="http://host" target="_blank">http://host</a>'], '']);
|
|
113
110
|
assert.deepStrictEqual(inspect(parser('_http://host')), [['_', '<a class="url" href="http://host" target="_blank">http://host</a>'], '']);
|
|
114
111
|
assert.deepStrictEqual(inspect(parser('_http://host_')), [['<em><a class="url" href="http://host" target="_blank">http://host</a></em>'], '']);
|
|
115
112
|
assert.deepStrictEqual(inspect(parser('*http://host*')), [['<strong><a class="url" href="http://host" target="_blank">http://host</a></strong>'], '']);
|
package/src/parser/inline.ts
CHANGED
|
@@ -7,7 +7,7 @@ import { comment } from './inline/comment';
|
|
|
7
7
|
import { math } from './inline/math';
|
|
8
8
|
import { extension } from './inline/extension';
|
|
9
9
|
import { ruby } from './inline/ruby';
|
|
10
|
-
import {
|
|
10
|
+
import { textlink, linemedialink } from './inline/link';
|
|
11
11
|
import { html } from './inline/html';
|
|
12
12
|
import { insertion } from './inline/insertion';
|
|
13
13
|
import { deletion } from './inline/deletion';
|
|
@@ -15,9 +15,9 @@ import { mark } from './inline/mark';
|
|
|
15
15
|
import { emphasis } from './inline/emphasis';
|
|
16
16
|
import { strong } from './inline/strong';
|
|
17
17
|
import { code } from './inline/code';
|
|
18
|
-
import {
|
|
18
|
+
import { linemedia } from './inline/media';
|
|
19
19
|
import { htmlentity } from './inline/htmlentity';
|
|
20
|
-
import {
|
|
20
|
+
import { lineshortmedia } from './inline/shortmedia';
|
|
21
21
|
import { autolink } from './inline/autolink';
|
|
22
22
|
import { bracket } from './inline/bracket';
|
|
23
23
|
import { text } from './source';
|
|
@@ -41,7 +41,7 @@ export import CodeParser = InlineParser.CodeParser;
|
|
|
41
41
|
export import MediaParser = InlineParser.MediaParser;
|
|
42
42
|
export import HTMLEntityParser = InlineParser.HTMLEntityParser;
|
|
43
43
|
export import UnsafeHTMLEntityParser = InlineParser.UnsafeHTMLEntityParser;
|
|
44
|
-
export import
|
|
44
|
+
export import ShortMediaParser = InlineParser.ShortMediaParser;
|
|
45
45
|
export import AutolinkParser = InlineParser.AutolinkParser;
|
|
46
46
|
export import BracketParser = InlineParser.BracketParser;
|
|
47
47
|
|
|
@@ -53,8 +53,9 @@ export const inline: InlineParser = union([
|
|
|
53
53
|
math,
|
|
54
54
|
extension,
|
|
55
55
|
ruby,
|
|
56
|
-
|
|
57
|
-
|
|
56
|
+
textlink,
|
|
57
|
+
linemedialink,
|
|
58
|
+
linemedia,
|
|
58
59
|
html,
|
|
59
60
|
insertion,
|
|
60
61
|
deletion,
|
|
@@ -63,7 +64,7 @@ export const inline: InlineParser = union([
|
|
|
63
64
|
emphasis,
|
|
64
65
|
code,
|
|
65
66
|
htmlentity,
|
|
66
|
-
|
|
67
|
+
lineshortmedia,
|
|
67
68
|
autolink,
|
|
68
69
|
bracket,
|
|
69
70
|
text
|
|
@@ -4,7 +4,7 @@ import { nonWhitespace } from './text';
|
|
|
4
4
|
|
|
5
5
|
const delimiter = /[\s\x00-\x2F\x3A-\x40\x5B-\x60\x7B-\x7F]/;
|
|
6
6
|
|
|
7
|
-
export const escsource: EscapableSourceParser = creation(1, false, ({ source }) => {
|
|
7
|
+
export const escsource: EscapableSourceParser = creation(1, false, ({ source, context }) => {
|
|
8
8
|
if (source === '') return;
|
|
9
9
|
const i = source.search(delimiter);
|
|
10
10
|
switch (i) {
|
|
@@ -12,6 +12,10 @@ export const escsource: EscapableSourceParser = creation(1, false, ({ source })
|
|
|
12
12
|
return [[source], ''];
|
|
13
13
|
case 0:
|
|
14
14
|
switch (source[0]) {
|
|
15
|
+
case '\r':
|
|
16
|
+
assert(!source.includes('\r', 1));
|
|
17
|
+
context.resources && ++context.resources.clock;
|
|
18
|
+
return [[], source.slice(1)];
|
|
15
19
|
case '\x1B':
|
|
16
20
|
return [[source.slice(1, 2)], source.slice(2)];
|
|
17
21
|
case '\\':
|
|
@@ -16,6 +16,10 @@ export const text: TextParser = creation(1, false, ({ source, context }) => {
|
|
|
16
16
|
return [[source], ''];
|
|
17
17
|
case 0:
|
|
18
18
|
switch (source[0]) {
|
|
19
|
+
case '\r':
|
|
20
|
+
assert(!source.includes('\r', 1));
|
|
21
|
+
context.resources && ++context.resources.clock;
|
|
22
|
+
return [[], source.slice(1)];
|
|
19
23
|
case '\x1B':
|
|
20
24
|
case '\\':
|
|
21
25
|
switch (source[1]) {
|
|
@@ -60,7 +64,7 @@ export const txt: TxtParser = union([
|
|
|
60
64
|
text,
|
|
61
65
|
]) as TxtParser;
|
|
62
66
|
|
|
63
|
-
export const linebreak: LinebreakParser = focus(
|
|
67
|
+
export const linebreak: LinebreakParser = focus(/^[\r\n]/, union([
|
|
64
68
|
text,
|
|
65
69
|
])) as LinebreakParser;
|
|
66
70
|
|
|
@@ -2,7 +2,7 @@ import { UnescapableSourceParser } from '../source';
|
|
|
2
2
|
import { creation } from '../../combinator';
|
|
3
3
|
import { delimiter, nonWhitespace, nonAlphanumeric, isAlphanumeric } from './text';
|
|
4
4
|
|
|
5
|
-
export const unescsource: UnescapableSourceParser = creation(1, false, ({ source }) => {
|
|
5
|
+
export const unescsource: UnescapableSourceParser = creation(1, false, ({ source, context }) => {
|
|
6
6
|
assert(source[0] !== '\x1B');
|
|
7
7
|
if (source === '') return;
|
|
8
8
|
const i = source.search(delimiter);
|
|
@@ -10,6 +10,12 @@ export const unescsource: UnescapableSourceParser = creation(1, false, ({ source
|
|
|
10
10
|
case -1:
|
|
11
11
|
return [[source], ''];
|
|
12
12
|
case 0: {
|
|
13
|
+
switch (source[0]) {
|
|
14
|
+
case '\r':
|
|
15
|
+
assert(!source.includes('\r', 1));
|
|
16
|
+
context.resources && ++context.resources.clock;
|
|
17
|
+
return [[], source.slice(1)];
|
|
18
|
+
}
|
|
13
19
|
const b = source[0] !== '\n' && source[0].trimStart() === '';
|
|
14
20
|
const i = b || isAlphanumeric(source[0])
|
|
15
21
|
? source.search(b ? nonWhitespace : nonAlphanumeric) || 1
|
package/src/parser/util.ts
CHANGED
|
@@ -1,13 +1,3 @@
|
|
|
1
|
-
import { Parser } from '../combinator/data/parser';
|
|
2
|
-
import { convert } from '../combinator';
|
|
3
|
-
|
|
4
|
-
export function format<P extends Parser<HTMLElement | string>>(parser: P): P;
|
|
5
|
-
export function format<T extends HTMLElement | string>(parser: Parser<T>): Parser<T> {
|
|
6
|
-
return convert(
|
|
7
|
-
source => source.replace(/(?<=^!?)https?:\/\/(?:[[]|[^\p{C}\p{S}\p{P}\s])\S*(?=[^\S\n]*(?:$|\n))/gm, '{ $& }'),
|
|
8
|
-
parser);
|
|
9
|
-
}
|
|
10
|
-
|
|
11
1
|
export function stringify(nodes: readonly (HTMLElement | string)[]): string {
|
|
12
2
|
let acc = '';
|
|
13
3
|
for (let i = 0; i < nodes.length; ++i) {
|
package/src/parser/visibility.ts
CHANGED
|
@@ -4,7 +4,6 @@ import { union, some, verify, convert, fmap } from '../combinator';
|
|
|
4
4
|
import { unsafehtmlentity } from './inline/htmlentity';
|
|
5
5
|
import { linebreak, unescsource } from './source';
|
|
6
6
|
import { State } from './context';
|
|
7
|
-
import { format } from './util';
|
|
8
7
|
import { invisibleHTMLEntityNames } from './api/normalize';
|
|
9
8
|
import { reduce } from 'spica/memoize';
|
|
10
9
|
import { push } from 'spica/array';
|
|
@@ -17,7 +16,7 @@ export function visualize<T extends HTMLElement | string>(parser: Parser<T>): Pa
|
|
|
17
16
|
return union([
|
|
18
17
|
convert(
|
|
19
18
|
source => source.replace(blankline, line => line.replace(/[\\&<]/g, '\x1B$&')),
|
|
20
|
-
verify(
|
|
19
|
+
verify(parser, (ns, rest, context) => !rest && hasVisible(ns, context))),
|
|
21
20
|
some(union([linebreak, unescsource])),
|
|
22
21
|
]);
|
|
23
22
|
}
|
package/src/util/info.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ParseSelector } from 'typed-query-selector/parser';
|
|
1
2
|
import { Info } from '../..';
|
|
2
3
|
import { scope } from './scope';
|
|
3
4
|
|
|
@@ -16,9 +17,10 @@ export function info(source: DocumentFragment | HTMLElement | ShadowRoot): Info
|
|
|
16
17
|
media: find('.media[data-src]'),
|
|
17
18
|
};
|
|
18
19
|
|
|
19
|
-
function find<T extends
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
function find<T extends string>(selector: T): ParseSelector<T, HTMLElement>[];
|
|
21
|
+
function find(selector: string): HTMLElement[] {
|
|
22
|
+
const acc = [];
|
|
23
|
+
for (let es = source.querySelectorAll<HTMLElement>(selector),
|
|
22
24
|
len = es.length, i = 0; i < len; ++i) {
|
|
23
25
|
const el = es[i];
|
|
24
26
|
match(el) && acc.push(el);
|
package/src/util/quote.test.ts
CHANGED
|
@@ -5,10 +5,10 @@ describe('Unit: util/quote', () => {
|
|
|
5
5
|
describe('quote', () => {
|
|
6
6
|
it('basic', () => {
|
|
7
7
|
const range = document.createRange();
|
|
8
|
-
const el = parse('>>1\n>2\n> a\n>>4 `b` ${c}
|
|
8
|
+
const el = parse('>>1\n>2\n> a\n>>4 `b` ${c}$\n!{d}\n [e](f) ').firstElementChild!;
|
|
9
9
|
range.setStart(el.firstChild!.firstChild!, 0);
|
|
10
10
|
range.setEnd(el.lastChild!.lastChild!.lastChild!, 1);
|
|
11
|
-
assert(quote('3', range) === `>>>1\n> >2\n>> a\n>>3\n> >>4 \`b\` \${c}
|
|
11
|
+
assert(quote('3', range) === `>>>1\n> >2\n>> a\n>>3\n> >>4 \`b\` \${c}$\n> !{d}\n> e`);
|
|
12
12
|
});
|
|
13
13
|
|
|
14
14
|
it('adjustment', () => {
|