securemark 0.257.0 → 0.257.1
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 +4 -0
- package/dist/index.js +73 -84
- package/markdown.d.ts +21 -6
- package/package.json +1 -1
- package/src/debug.test.ts +1 -1
- package/src/parser/inline/annotation.test.ts +6 -5
- package/src/parser/inline/annotation.ts +5 -4
- package/src/parser/inline/autolink/account.ts +3 -7
- package/src/parser/inline/autolink/anchor.ts +3 -7
- package/src/parser/inline/autolink/hashnum.ts +3 -7
- package/src/parser/inline/autolink/hashtag.ts +3 -7
- package/src/parser/inline/autolink/url.test.ts +1 -0
- package/src/parser/inline/autolink/url.ts +3 -4
- package/src/parser/inline/bracket.test.ts +1 -1
- package/src/parser/inline/link.ts +54 -13
- package/src/parser/inline/media.ts +4 -4
- package/src/parser/inline/reference.test.ts +6 -5
- package/src/parser/inline/reference.ts +6 -14
- package/src/parser/inline.test.ts +3 -3
- package/src/parser/inline.ts +1 -0
- package/src/parser/util.ts +18 -18
package/CHANGELOG.md
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! securemark v0.257.
|
|
1
|
+
/*! securemark v0.257.1 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"));
|
|
@@ -5402,13 +5402,13 @@ const combinator_1 = __webpack_require__(2087);
|
|
|
5402
5402
|
|
|
5403
5403
|
const inline_1 = __webpack_require__(1160);
|
|
5404
5404
|
|
|
5405
|
-
const
|
|
5405
|
+
const link_1 = __webpack_require__(9628);
|
|
5406
5406
|
|
|
5407
5407
|
const util_1 = __webpack_require__(9437);
|
|
5408
5408
|
|
|
5409
5409
|
const dom_1 = __webpack_require__(3252);
|
|
5410
5410
|
|
|
5411
|
-
exports.annotation = (0, combinator_1.lazy)(() => (0, combinator_1.creator)((0, combinator_1.recursion)((0, combinator_1.precedence)(6, (0, combinator_1.validate)('((', (0, combinator_1.surround)('((', (0, combinator_1.guard)(context => context.syntax?.inline?.annotation ?? true, (0, combinator_1.context)({
|
|
5411
|
+
exports.annotation = (0, combinator_1.lazy)(() => (0, combinator_1.creator)((0, combinator_1.recursion)((0, combinator_1.precedence)(6, (0, combinator_1.validate)('((', (0, combinator_1.surround)('((', (0, combinator_1.guard)(context => context.syntax?.inline?.annotation ?? true, (0, util_1.startLoose)((0, combinator_1.context)({
|
|
5412
5412
|
syntax: {
|
|
5413
5413
|
inline: {
|
|
5414
5414
|
annotation: false,
|
|
@@ -5423,9 +5423,9 @@ exports.annotation = (0, combinator_1.lazy)(() => (0, combinator_1.creator)((0,
|
|
|
5423
5423
|
}
|
|
5424
5424
|
},
|
|
5425
5425
|
delimiters: global_1.undefined
|
|
5426
|
-
}, (0,
|
|
5426
|
+
}, (0, combinator_1.some)((0, combinator_1.union)([inline_1.inline]), ')', [[/^\\?\n/, 9], [')', 3], ['))', 6]])), ')')), '))', false, ([, ns], rest) => [[(0, dom_1.html)('sup', {
|
|
5427
5427
|
class: 'annotation'
|
|
5428
|
-
}, [(0, dom_1.html)('span', (0, util_1.
|
|
5428
|
+
}, [(0, dom_1.html)('span', (0, util_1.trimNode)((0, dom_1.defrag)(ns)))])], rest], ([, ns, rest], next) => next[0] === ')' ? global_1.undefined : (0, link_1.optimize)('((', ns, rest)))))));
|
|
5429
5429
|
|
|
5430
5430
|
/***/ }),
|
|
5431
5431
|
|
|
@@ -5488,14 +5488,7 @@ const source_1 = __webpack_require__(6743);
|
|
|
5488
5488
|
const dom_1 = __webpack_require__(3252); // https://example/@user must be a user page or a redirect page going there.
|
|
5489
5489
|
|
|
5490
5490
|
|
|
5491
|
-
exports.account = (0, combinator_1.lazy)(() => (0, combinator_1.fmap)((0, combinator_1.rewrite)((0, combinator_1.open)('@', (0, combinator_1.tails)([(0, combinator_1.verify)((0, source_1.str)(/^[0-9A-Za-z](?:(?:[0-9A-Za-z]|-(?=\w)){0,61}[0-9A-Za-z])?(?:\.[0-9A-Za-z](?:(?:[0-9A-Za-z]|-(?=\w)){0,61}[0-9A-Za-z])?)*\//), ([source]) => source.length <= 253 + 1), (0, combinator_1.verify)((0, source_1.str)(/^[A-Za-z][0-9A-Za-z]*(?:-[0-9A-Za-z]+)*/), ([source]) => source.length <= 64)])), (0, combinator_1.
|
|
5492
|
-
syntax: {
|
|
5493
|
-
inline: {
|
|
5494
|
-
link: true,
|
|
5495
|
-
autolink: false
|
|
5496
|
-
}
|
|
5497
|
-
}
|
|
5498
|
-
}, (0, combinator_1.convert)(source => `[${source}]{ ${source.includes('/') ? `https://${source.slice(1).replace('/', '/@')}` : `/${source}`} }`, (0, combinator_1.union)([link_1.link])))), ([el]) => [(0, dom_1.define)(el, {
|
|
5491
|
+
exports.account = (0, combinator_1.lazy)(() => (0, combinator_1.fmap)((0, combinator_1.rewrite)((0, combinator_1.open)('@', (0, combinator_1.tails)([(0, combinator_1.verify)((0, source_1.str)(/^[0-9A-Za-z](?:(?:[0-9A-Za-z]|-(?=\w)){0,61}[0-9A-Za-z])?(?:\.[0-9A-Za-z](?:(?:[0-9A-Za-z]|-(?=\w)){0,61}[0-9A-Za-z])?)*\//), ([source]) => source.length <= 253 + 1), (0, combinator_1.verify)((0, source_1.str)(/^[A-Za-z][0-9A-Za-z]*(?:-[0-9A-Za-z]+)*/), ([source]) => source.length <= 64)])), (0, combinator_1.convert)(source => `[${source}]{ ${source.includes('/') ? `https://${source.slice(1).replace('/', '/@')}` : `/${source}`} }`, (0, combinator_1.union)([link_1.textlink]))), ([el]) => [(0, dom_1.define)(el, {
|
|
5499
5492
|
class: 'account'
|
|
5500
5493
|
})]));
|
|
5501
5494
|
|
|
@@ -5524,14 +5517,7 @@ const dom_1 = __webpack_require__(3252); // Timeline(pseudonym): user/tid
|
|
|
5524
5517
|
// 外部表現は投稿ごとに投稿者の投稿時のタイムゾーンに統一する(非時系列順)
|
|
5525
5518
|
|
|
5526
5519
|
|
|
5527
|
-
exports.anchor = (0, combinator_1.lazy)(() => (0, combinator_1.validate)('>>', (0, combinator_1.fmap)((0, combinator_1.focus)(/^>>(?:[A-Za-z][0-9A-Za-z]*(?:-[0-9A-Za-z]+)*\/)?[0-9A-Za-z]+(?:-[0-9A-Za-z]+)*(?![0-9A-Za-z@#:])/, (0, combinator_1.
|
|
5528
|
-
syntax: {
|
|
5529
|
-
inline: {
|
|
5530
|
-
link: true,
|
|
5531
|
-
autolink: false
|
|
5532
|
-
}
|
|
5533
|
-
}
|
|
5534
|
-
}, (0, combinator_1.convert)(source => `[${source}]{ ${source.includes('/') ? `/@${source.slice(2).replace('/', '/timeline/')}` : `?at=${source.slice(2)}`} }`, (0, combinator_1.union)([link_1.link])))), ([el]) => [(0, dom_1.define)(el, {
|
|
5520
|
+
exports.anchor = (0, combinator_1.lazy)(() => (0, combinator_1.validate)('>>', (0, combinator_1.fmap)((0, combinator_1.focus)(/^>>(?:[A-Za-z][0-9A-Za-z]*(?:-[0-9A-Za-z]+)*\/)?[0-9A-Za-z]+(?:-[0-9A-Za-z]+)*(?![0-9A-Za-z@#:])/, (0, combinator_1.convert)(source => `[${source}]{ ${source.includes('/') ? `/@${source.slice(2).replace('/', '/timeline/')}` : `?at=${source.slice(2)}`} }`, (0, combinator_1.union)([link_1.textlink]))), ([el]) => [(0, dom_1.define)(el, {
|
|
5535
5521
|
class: 'anchor'
|
|
5536
5522
|
})])));
|
|
5537
5523
|
|
|
@@ -5618,14 +5604,7 @@ const source_1 = __webpack_require__(6743);
|
|
|
5618
5604
|
|
|
5619
5605
|
const dom_1 = __webpack_require__(3252);
|
|
5620
5606
|
|
|
5621
|
-
exports.hashnum = (0, combinator_1.lazy)(() => (0, combinator_1.fmap)((0, combinator_1.rewrite)((0, combinator_1.open)('#', (0, source_1.str)(new RegExp(/^[0-9]{1,16}(?![^\p{C}\p{S}\p{P}\s]|emoji|['_])/u.source.replace(/emoji/, hashtag_1.emoji), 'u'))), (0, combinator_1.
|
|
5622
|
-
syntax: {
|
|
5623
|
-
inline: {
|
|
5624
|
-
link: true,
|
|
5625
|
-
autolink: false
|
|
5626
|
-
}
|
|
5627
|
-
}
|
|
5628
|
-
}, (0, combinator_1.convert)(source => `[${source}]{ ${source.slice(1)} }`, (0, combinator_1.union)([link_1.link])))), ([el]) => [(0, dom_1.define)(el, {
|
|
5607
|
+
exports.hashnum = (0, combinator_1.lazy)(() => (0, combinator_1.fmap)((0, combinator_1.rewrite)((0, combinator_1.open)('#', (0, source_1.str)(new RegExp(/^[0-9]{1,16}(?![^\p{C}\p{S}\p{P}\s]|emoji|['_])/u.source.replace(/emoji/, hashtag_1.emoji), 'u'))), (0, combinator_1.convert)(source => `[${source}]{ ${source.slice(1)} }`, (0, combinator_1.union)([link_1.textlink]))), ([el]) => [(0, dom_1.define)(el, {
|
|
5629
5608
|
class: 'hashnum',
|
|
5630
5609
|
href: null
|
|
5631
5610
|
})]));
|
|
@@ -5654,14 +5633,7 @@ const dom_1 = __webpack_require__(3252); // https://example/hashtags/a must be a
|
|
|
5654
5633
|
|
|
5655
5634
|
|
|
5656
5635
|
exports.emoji = String.raw`\p{Emoji_Modifier_Base}\p{Emoji_Modifier}?|\p{Emoji_Presentation}|\p{Emoji}\uFE0F`;
|
|
5657
|
-
exports.hashtag = (0, combinator_1.lazy)(() => (0, combinator_1.fmap)((0, combinator_1.rewrite)((0, combinator_1.open)('#', (0, combinator_1.tails)([(0, combinator_1.verify)((0, source_1.str)(/^[0-9A-Za-z](?:(?:[0-9A-Za-z]|-(?=\w)){0,61}[0-9A-Za-z])?(?:\.[0-9A-Za-z](?:(?:[0-9A-Za-z]|-(?=\w)){0,61}[0-9A-Za-z])?)*\//), ([source]) => source.length <= 253 + 1), (0, combinator_1.verify)((0, source_1.str)(new RegExp([/^(?=[0-9]{0,127}_?(?:[^\d\p{C}\p{S}\p{P}\s]|emoji))/u.source, /(?:[^\p{C}\p{S}\p{P}\s]|emoji|_(?=[^\p{C}\p{S}\p{P}\s]|emoji)){1,128}/u.source, /(?!_?(?:[^\p{C}\p{S}\p{P}\s]|emoji)|')/u.source].join('').replace(/emoji/g, exports.emoji), 'u')), ([source]) => source.length <= 128)])), (0, combinator_1.
|
|
5658
|
-
syntax: {
|
|
5659
|
-
inline: {
|
|
5660
|
-
link: true,
|
|
5661
|
-
autolink: false
|
|
5662
|
-
}
|
|
5663
|
-
}
|
|
5664
|
-
}, (0, combinator_1.convert)(source => `[${source}]{ ${source.includes('/') ? `https://${source.slice(1).replace('/', '/hashtags/')}` : `/hashtags/${source.slice(1)}`} }`, (0, combinator_1.union)([link_1.link])))), ([el]) => [(0, dom_1.define)(el, {
|
|
5636
|
+
exports.hashtag = (0, combinator_1.lazy)(() => (0, combinator_1.fmap)((0, combinator_1.rewrite)((0, combinator_1.open)('#', (0, combinator_1.tails)([(0, combinator_1.verify)((0, source_1.str)(/^[0-9A-Za-z](?:(?:[0-9A-Za-z]|-(?=\w)){0,61}[0-9A-Za-z])?(?:\.[0-9A-Za-z](?:(?:[0-9A-Za-z]|-(?=\w)){0,61}[0-9A-Za-z])?)*\//), ([source]) => source.length <= 253 + 1), (0, combinator_1.verify)((0, source_1.str)(new RegExp([/^(?=[0-9]{0,127}_?(?:[^\d\p{C}\p{S}\p{P}\s]|emoji))/u.source, /(?:[^\p{C}\p{S}\p{P}\s]|emoji|_(?=[^\p{C}\p{S}\p{P}\s]|emoji)){1,128}/u.source, /(?!_?(?:[^\p{C}\p{S}\p{P}\s]|emoji)|')/u.source].join('').replace(/emoji/g, exports.emoji), 'u')), ([source]) => source.length <= 128)])), (0, combinator_1.convert)(source => `[${source}]{ ${source.includes('/') ? `https://${source.slice(1).replace('/', '/hashtags/')}` : `/hashtags/${source.slice(1)}`} }`, (0, combinator_1.union)([link_1.textlink]))), ([el]) => [(0, dom_1.define)(el, {
|
|
5665
5637
|
class: 'hashtag'
|
|
5666
5638
|
}, el.innerText)]));
|
|
5667
5639
|
|
|
@@ -5684,10 +5656,8 @@ const link_1 = __webpack_require__(9628);
|
|
|
5684
5656
|
|
|
5685
5657
|
const source_1 = __webpack_require__(6743);
|
|
5686
5658
|
|
|
5687
|
-
const
|
|
5688
|
-
|
|
5689
|
-
const closer = /^[-+*=~^,.;:!?]*(?=["`|\[\](){}<>]|\\?$)/;
|
|
5690
|
-
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, util_1.clean)((0, combinator_1.union)([link_1.link]))))));
|
|
5659
|
+
const closer = /^[-+*=~^,.;:!?]*(?=[\\"`|\[\](){}<>]|$)/;
|
|
5660
|
+
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.textlink])))));
|
|
5691
5661
|
const bracket = (0, combinator_1.lazy)(() => (0, combinator_1.creator)((0, combinator_1.precedence)(3, (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)]))));
|
|
5692
5662
|
|
|
5693
5663
|
/***/ }),
|
|
@@ -6356,7 +6326,7 @@ exports.insertion = (0, combinator_1.lazy)(() => (0, combinator_1.creator)((0, c
|
|
|
6356
6326
|
Object.defineProperty(exports, "__esModule", ({
|
|
6357
6327
|
value: true
|
|
6358
6328
|
}));
|
|
6359
|
-
exports.resolve = exports.option = exports.uri = exports.link = void 0;
|
|
6329
|
+
exports.optimize = exports.resolve = exports.option = exports.uri = exports.textlink = exports.link = void 0;
|
|
6360
6330
|
|
|
6361
6331
|
const global_1 = __webpack_require__(4128);
|
|
6362
6332
|
|
|
@@ -6382,7 +6352,7 @@ const optspec = {
|
|
|
6382
6352
|
rel: ['nofollow']
|
|
6383
6353
|
};
|
|
6384
6354
|
Object.setPrototypeOf(optspec, null);
|
|
6385
|
-
exports.link = (0, combinator_1.lazy)(() => (0, combinator_1.validate)(['[', '{'], (0, combinator_1.creator)(10, (0, combinator_1.precedence)(3, (0, combinator_1.bind)((0, combinator_1.guard)(context => context.syntax?.inline?.link ?? true, (0, combinator_1.
|
|
6355
|
+
exports.link = (0, combinator_1.lazy)(() => (0, combinator_1.validate)(['[', '{'], (0, combinator_1.creator)(10, (0, combinator_1.precedence)(3, (0, combinator_1.bind)((0, combinator_1.guard)(context => context.syntax?.inline?.link ?? true, (0, combinator_1.fmap)((0, combinator_1.subsequence)([(0, combinator_1.context)({
|
|
6386
6356
|
syntax: {
|
|
6387
6357
|
inline: {
|
|
6388
6358
|
link: false
|
|
@@ -6401,15 +6371,25 @@ exports.link = (0, combinator_1.lazy)(() => (0, combinator_1.validate)(['[', '{'
|
|
|
6401
6371
|
autolink: false
|
|
6402
6372
|
}
|
|
6403
6373
|
}
|
|
6404
|
-
}, (0,
|
|
6405
|
-
|
|
6374
|
+
}, (0, combinator_1.some)(inline_1.inline, ']', [[/^\\?\n/, 9], [']', 3]])), ']', true, global_1.undefined, ([, ns = [], rest], next) => next[0] === ']' ? global_1.undefined : optimize('[', ns, rest))]))), // 全体の失敗が確定した時も解析し予算を浪費している
|
|
6375
|
+
(0, combinator_1.dup)((0, combinator_1.surround)(/^{(?![{}])/, (0, combinator_1.inits)([exports.uri, (0, combinator_1.some)(exports.option)]), /^[^\S\n]*}/))]), ([as, bs = []]) => bs[0] === '\r' && bs.shift() ? [as, bs] : as[0] === '\r' && as.shift() ? [[], as] : [as, []])), ([content, params], rest, context) => {
|
|
6376
|
+
if (params.length === 0) return;
|
|
6377
|
+
if (content[0] === '') return [content, rest];
|
|
6378
|
+
if (content.length !== 0 && (0, util_1.trimNode)(content).length === 0) return;
|
|
6406
6379
|
if ((0, parser_1.eval)((0, combinator_1.some)(autolink_1.autolink)((0, util_1.stringify)(content), context))?.some(node => typeof node === 'object')) return;
|
|
6407
6380
|
const INSECURE_URI = params.shift();
|
|
6408
6381
|
const el = elem(INSECURE_URI, (0, dom_1.defrag)(content), new url_1.ReadonlyURL(resolve(INSECURE_URI, context.host ?? global_1.location, context.url ?? context.host ?? global_1.location), context.host?.href || global_1.location.href), context.host?.origin || global_1.location.origin);
|
|
6409
6382
|
if (el.classList.contains('invalid')) return [[el], rest];
|
|
6410
6383
|
return [[(0, dom_1.define)(el, (0, html_1.attributes)('link', [], optspec, params))], rest];
|
|
6411
6384
|
})))));
|
|
6412
|
-
exports.
|
|
6385
|
+
exports.textlink = (0, combinator_1.lazy)(() => (0, combinator_1.validate)(['[', '{'], (0, combinator_1.creator)(10, (0, combinator_1.precedence)(3, (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) => {
|
|
6386
|
+
params.shift();
|
|
6387
|
+
(0, util_1.trimNode)(content);
|
|
6388
|
+
const INSECURE_URI = params.shift();
|
|
6389
|
+
const el = elem(INSECURE_URI, (0, dom_1.defrag)(content), new url_1.ReadonlyURL(resolve(INSECURE_URI, context.host ?? global_1.location, context.url ?? context.host ?? global_1.location), context.host?.href || global_1.location.href), context.host?.origin || global_1.location.origin);
|
|
6390
|
+
return [[(0, dom_1.define)(el, (0, html_1.attributes)('link', [], optspec, params))], rest];
|
|
6391
|
+
})))));
|
|
6392
|
+
exports.uri = (0, combinator_1.fmap)((0, combinator_1.union)([(0, combinator_1.open)(/^[^\S\n]+/, (0, source_1.str)(/^\S+/)), (0, source_1.str)(/^[^\s{}]+/)]), ([uri]) => ['\r', uri]);
|
|
6413
6393
|
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)}`])]);
|
|
6414
6394
|
|
|
6415
6395
|
function resolve(uri, host, source) {
|
|
@@ -6486,6 +6466,19 @@ function decode(uri) {
|
|
|
6486
6466
|
}
|
|
6487
6467
|
}
|
|
6488
6468
|
|
|
6469
|
+
function optimize(opener, ns, rest) {
|
|
6470
|
+
let count = 0;
|
|
6471
|
+
|
|
6472
|
+
for (let i = 0; i < ns.length - 1; i += 2) {
|
|
6473
|
+
if (ns[i] !== '' || ns[i + 1] !== opener[0]) break;
|
|
6474
|
+
++count;
|
|
6475
|
+
}
|
|
6476
|
+
|
|
6477
|
+
return [['', opener[0].repeat(opener.length + count)], rest.slice(count)];
|
|
6478
|
+
}
|
|
6479
|
+
|
|
6480
|
+
exports.optimize = optimize;
|
|
6481
|
+
|
|
6489
6482
|
/***/ }),
|
|
6490
6483
|
|
|
6491
6484
|
/***/ 2480:
|
|
@@ -6589,7 +6582,7 @@ const optspec = {
|
|
|
6589
6582
|
rel: global_1.undefined
|
|
6590
6583
|
};
|
|
6591
6584
|
Object.setPrototypeOf(optspec, null);
|
|
6592
|
-
exports.media = (0, combinator_1.lazy)(() => (0, combinator_1.validate)(['![', '!{'], (0, combinator_1.creator)(10, (0, combinator_1.precedence)(3, (0, combinator_1.bind)((0, combinator_1.verify)((0, combinator_1.fmap)((0, combinator_1.open)('!', (0, combinator_1.guard)(context => context.syntax?.inline?.media ?? true, (0, combinator_1.tails)([(0, combinator_1.dup)((0, combinator_1.surround)('[', (0, combinator_1.some)((0, combinator_1.union)([htmlentity_1.unsafehtmlentity, bracket, source_1.txt]), ']', [[/^\\?\n/, 9]]), ']', true)), (0, combinator_1.dup)((0, combinator_1.surround)(/^{(?![{}])/, (0, combinator_1.inits)([link_1.uri, (0, combinator_1.some)(option)]), /^[^\S\n]*}/))]))), ([as, bs]) => bs ? [[as.join('').trim() || as.join('')], bs] : [[''], as]), ([[text]]) => text === '' || text.trim() !== ''), ([[text], params], rest, context) => {
|
|
6585
|
+
exports.media = (0, combinator_1.lazy)(() => (0, combinator_1.validate)(['![', '!{'], (0, combinator_1.creator)(10, (0, combinator_1.precedence)(3, (0, combinator_1.bind)((0, combinator_1.verify)((0, combinator_1.fmap)((0, combinator_1.open)('!', (0, combinator_1.guard)(context => context.syntax?.inline?.media ?? true, (0, combinator_1.tails)([(0, combinator_1.dup)((0, combinator_1.surround)('[', (0, combinator_1.some)((0, combinator_1.union)([htmlentity_1.unsafehtmlentity, bracket, source_1.txt]), ']', [[/^\\?\n/, 9]]), ']', true)), (0, combinator_1.dup)((0, combinator_1.surround)(/^{(?![{}])/, (0, combinator_1.inits)([link_1.uri, (0, combinator_1.some)(option)]), /^[^\S\n]*}/))]))), ([as, bs]) => bs ? [[as.join('').trim() || as.join('')], (0, array_1.shift)(bs)[1]] : [[''], (0, array_1.shift)(as)[1]]), ([[text]]) => text === '' || text.trim() !== ''), ([[text], params], rest, context) => {
|
|
6593
6586
|
const INSECURE_URI = params.shift();
|
|
6594
6587
|
const url = new url_1.ReadonlyURL((0, link_1.resolve)(INSECURE_URI, context.host ?? global_1.location, context.url ?? context.host ?? global_1.location), context.host?.href || global_1.location.href);
|
|
6595
6588
|
let cache;
|
|
@@ -6608,7 +6601,7 @@ exports.media = (0, combinator_1.lazy)(() => (0, combinator_1.validate)(['![', '
|
|
|
6608
6601
|
}
|
|
6609
6602
|
|
|
6610
6603
|
if (context.syntax?.inline?.link === false || cache && cache.tagName !== 'IMG') return [[el], rest];
|
|
6611
|
-
return (0, combinator_1.fmap)(link_1.
|
|
6604
|
+
return (0, combinator_1.fmap)(link_1.textlink, ([link]) => [(0, dom_1.define)(link, {
|
|
6612
6605
|
target: '_blank'
|
|
6613
6606
|
}, [el])])(`{ ${INSECURE_URI}${params.join('')} }${rest}`, context);
|
|
6614
6607
|
})))));
|
|
@@ -6666,7 +6659,7 @@ function sanitize(target, uri, alt) {
|
|
|
6666
6659
|
Object.defineProperty(exports, "__esModule", ({
|
|
6667
6660
|
value: true
|
|
6668
6661
|
}));
|
|
6669
|
-
exports.
|
|
6662
|
+
exports.reference = void 0;
|
|
6670
6663
|
|
|
6671
6664
|
const global_1 = __webpack_require__(4128);
|
|
6672
6665
|
|
|
@@ -6674,13 +6667,15 @@ const combinator_1 = __webpack_require__(2087);
|
|
|
6674
6667
|
|
|
6675
6668
|
const inline_1 = __webpack_require__(1160);
|
|
6676
6669
|
|
|
6670
|
+
const link_1 = __webpack_require__(9628);
|
|
6671
|
+
|
|
6677
6672
|
const source_1 = __webpack_require__(6743);
|
|
6678
6673
|
|
|
6679
6674
|
const util_1 = __webpack_require__(9437);
|
|
6680
6675
|
|
|
6681
6676
|
const dom_1 = __webpack_require__(3252);
|
|
6682
6677
|
|
|
6683
|
-
exports.reference = (0, combinator_1.lazy)(() => (0, combinator_1.validate)('[[', (0, combinator_1.creator)((0, combinator_1.recursion)((0, combinator_1.precedence)(6, (0, combinator_1.surround)('[[', (0, combinator_1.guard)(context => context.syntax?.inline?.reference ?? true, (0, combinator_1.context)({
|
|
6678
|
+
exports.reference = (0, combinator_1.lazy)(() => (0, combinator_1.validate)('[[', (0, combinator_1.creator)((0, combinator_1.recursion)((0, combinator_1.precedence)(6, (0, combinator_1.surround)('[[', (0, combinator_1.guard)(context => context.syntax?.inline?.reference ?? true, (0, util_1.startLoose)((0, combinator_1.context)({
|
|
6684
6679
|
syntax: {
|
|
6685
6680
|
inline: {
|
|
6686
6681
|
annotation: false,
|
|
@@ -6694,7 +6689,7 @@ exports.reference = (0, combinator_1.lazy)(() => (0, combinator_1.validate)('[['
|
|
|
6694
6689
|
}
|
|
6695
6690
|
},
|
|
6696
6691
|
delimiters: global_1.undefined
|
|
6697
|
-
}, (0, combinator_1.subsequence)([abbr, (0, combinator_1.open)((0, source_1.stropt)(/^(?=\^)/), (0, combinator_1.some)(inline_1.inline, ']', [[/^\\?\n/, 9], [']', 3], [']]', 6]])), (0,
|
|
6692
|
+
}, (0, combinator_1.subsequence)([abbr, (0, combinator_1.open)((0, source_1.stropt)(/^(?=\^)/), (0, combinator_1.some)(inline_1.inline, ']', [[/^\\?\n/, 9], [']', 3], [']]', 6]])), (0, combinator_1.some)(inline_1.inline, ']', [[/^\\?\n/, 9], [']', 3], [']]', 6]])])), ']')), ']]', false, ([, ns], rest) => [[(0, dom_1.html)('sup', attributes(ns), [(0, dom_1.html)('span', (0, util_1.trimNode)((0, dom_1.defrag)(ns)))])], rest], ([, ns, rest], next) => next[0] === ']' ? global_1.undefined : (0, link_1.optimize)('[[', ns, rest)))))));
|
|
6698
6693
|
const abbr = (0, combinator_1.creator)((0, combinator_1.bind)((0, combinator_1.surround)('^', (0, combinator_1.union)([(0, source_1.str)(/^(?![0-9]+\s?[|\]])[0-9A-Za-z]+(?:(?:-|(?=\W)(?!'\d)'?(?!\.\d)\.?(?!,\S),? ?)[0-9A-Za-z]+)*(?:-|'?\.?,? ?)?/)]), /^\|?(?=]])|^\|[^\S\n]*/), ([source], rest) => [[(0, dom_1.html)('abbr', source)], rest.replace(util_1.regBlankStart, '')]));
|
|
6699
6694
|
|
|
6700
6695
|
function attributes(ns) {
|
|
@@ -6711,19 +6706,6 @@ function attributes(ns) {
|
|
|
6711
6706
|
};
|
|
6712
6707
|
}
|
|
6713
6708
|
|
|
6714
|
-
function optimize(opener, ns, rest) {
|
|
6715
|
-
let count = 0;
|
|
6716
|
-
|
|
6717
|
-
for (let i = 0; i < ns.length - 1; i += 2) {
|
|
6718
|
-
if (ns[i] !== '' || ns[i + 1] !== opener[0]) break;
|
|
6719
|
-
++count;
|
|
6720
|
-
}
|
|
6721
|
-
|
|
6722
|
-
return [[opener[0].repeat(opener.length + count)], rest.slice(count)];
|
|
6723
|
-
}
|
|
6724
|
-
|
|
6725
|
-
exports.optimize = optimize;
|
|
6726
|
-
|
|
6727
6709
|
/***/ }),
|
|
6728
6710
|
|
|
6729
6711
|
/***/ 6705:
|
|
@@ -7798,7 +7780,7 @@ exports.unescsource = (0, combinator_1.creator)(source => {
|
|
|
7798
7780
|
Object.defineProperty(exports, "__esModule", ({
|
|
7799
7781
|
value: true
|
|
7800
7782
|
}));
|
|
7801
|
-
exports.stringify = exports.
|
|
7783
|
+
exports.stringify = exports.trimNode = exports.trimBlankEnd = exports.trimBlankStart = exports.trimBlank = exports.isStartTightNodes = exports.isStartLooseNodes = exports.startTight = exports.startLoose = exports.visualize = exports.blankWith = exports.regBlankStart = exports.clean = void 0;
|
|
7802
7784
|
|
|
7803
7785
|
const global_1 = __webpack_require__(4128);
|
|
7804
7786
|
|
|
@@ -7993,23 +7975,32 @@ function trimBlankEnd(parser) {
|
|
|
7993
7975
|
return (0, combinator_1.fmap)(parser, trimNodeEnd);
|
|
7994
7976
|
}
|
|
7995
7977
|
|
|
7996
|
-
exports.trimBlankEnd = trimBlankEnd;
|
|
7997
|
-
|
|
7998
|
-
|
|
7999
|
-
|
|
8000
|
-
|
|
8001
|
-
|
|
8002
|
-
|
|
8003
|
-
|
|
8004
|
-
|
|
8005
|
-
|
|
8006
|
-
|
|
8007
|
-
|
|
8008
|
-
|
|
8009
|
-
|
|
8010
|
-
|
|
8011
|
-
|
|
8012
|
-
|
|
7978
|
+
exports.trimBlankEnd = trimBlankEnd;
|
|
7979
|
+
|
|
7980
|
+
function trimNode(nodes) {
|
|
7981
|
+
return trimNodeStart(trimNodeEnd(nodes));
|
|
7982
|
+
}
|
|
7983
|
+
|
|
7984
|
+
exports.trimNode = trimNode;
|
|
7985
|
+
|
|
7986
|
+
function trimNodeStart(nodes) {
|
|
7987
|
+
for (let node = nodes[0]; nodes.length > 0 && !isVisible(node = nodes[0], 0);) {
|
|
7988
|
+
if (nodes.length === 1 && typeof node === 'object' && node.className === 'indexer') break;
|
|
7989
|
+
|
|
7990
|
+
if (typeof node === 'string') {
|
|
7991
|
+
const pos = node.trimStart().length;
|
|
7992
|
+
|
|
7993
|
+
if (pos > 0) {
|
|
7994
|
+
nodes[0] = node.slice(pos);
|
|
7995
|
+
break;
|
|
7996
|
+
}
|
|
7997
|
+
}
|
|
7998
|
+
|
|
7999
|
+
nodes.shift();
|
|
8000
|
+
}
|
|
8001
|
+
|
|
8002
|
+
return nodes;
|
|
8003
|
+
}
|
|
8013
8004
|
|
|
8014
8005
|
function trimNodeEnd(nodes) {
|
|
8015
8006
|
const skip = nodes.length > 0 && typeof nodes[nodes.length - 1] === 'object' && nodes[nodes.length - 1]['className'] === 'indexer' ? [nodes.pop()] : [];
|
|
@@ -8030,8 +8021,6 @@ function trimNodeEnd(nodes) {
|
|
|
8030
8021
|
return (0, array_1.push)(nodes, skip);
|
|
8031
8022
|
}
|
|
8032
8023
|
|
|
8033
|
-
exports.trimNodeEnd = trimNodeEnd;
|
|
8034
|
-
|
|
8035
8024
|
function stringify(nodes) {
|
|
8036
8025
|
let acc = '';
|
|
8037
8026
|
|
package/markdown.d.ts
CHANGED
|
@@ -869,11 +869,20 @@ export namespace MarkdownParser {
|
|
|
869
869
|
// { uri }
|
|
870
870
|
// [abc]{uri nofollow}
|
|
871
871
|
Inline<'link'>,
|
|
872
|
-
Parser<
|
|
872
|
+
Parser<HTMLElement | string, Context, [
|
|
873
873
|
LinkParser.ContentParser,
|
|
874
874
|
LinkParser.ParameterParser,
|
|
875
875
|
]> {
|
|
876
876
|
}
|
|
877
|
+
export interface TextLinkParser extends
|
|
878
|
+
// { uri }
|
|
879
|
+
// [abc]{uri nofollow}
|
|
880
|
+
Inline<'textlink'>,
|
|
881
|
+
Parser<HTMLAnchorElement, Context, [
|
|
882
|
+
LinkParser.TextParser,
|
|
883
|
+
LinkParser.ParameterParser,
|
|
884
|
+
]> {
|
|
885
|
+
}
|
|
877
886
|
export namespace LinkParser {
|
|
878
887
|
export interface ContentParser extends
|
|
879
888
|
Inline<'link/content'>,
|
|
@@ -883,6 +892,12 @@ export namespace MarkdownParser {
|
|
|
883
892
|
InlineParser,
|
|
884
893
|
]> {
|
|
885
894
|
}
|
|
895
|
+
export interface TextParser extends
|
|
896
|
+
Inline<'link/text'>,
|
|
897
|
+
Parser<string[], Context, [
|
|
898
|
+
SourceParser.UnescapableSourceParser,
|
|
899
|
+
]> {
|
|
900
|
+
}
|
|
886
901
|
export interface ParameterParser extends
|
|
887
902
|
Inline<'link/parameter'>,
|
|
888
903
|
Parser<string[], Context, [
|
|
@@ -1107,7 +1122,7 @@ export namespace MarkdownParser {
|
|
|
1107
1122
|
// https://host
|
|
1108
1123
|
Inline<'url'>,
|
|
1109
1124
|
Parser<HTMLAnchorElement, Context, [
|
|
1110
|
-
|
|
1125
|
+
TextLinkParser,
|
|
1111
1126
|
]> {
|
|
1112
1127
|
}
|
|
1113
1128
|
export namespace UrlParser {
|
|
@@ -1149,28 +1164,28 @@ export namespace MarkdownParser {
|
|
|
1149
1164
|
// @user
|
|
1150
1165
|
Inline<'account'>,
|
|
1151
1166
|
Parser<HTMLAnchorElement, Context, [
|
|
1152
|
-
|
|
1167
|
+
TextLinkParser,
|
|
1153
1168
|
]> {
|
|
1154
1169
|
}
|
|
1155
1170
|
export interface HashtagParser extends
|
|
1156
1171
|
// #tag
|
|
1157
1172
|
Inline<'hashtag'>,
|
|
1158
1173
|
Parser<HTMLAnchorElement, Context, [
|
|
1159
|
-
|
|
1174
|
+
TextLinkParser,
|
|
1160
1175
|
]> {
|
|
1161
1176
|
}
|
|
1162
1177
|
export interface HashnumParser extends
|
|
1163
1178
|
// #1
|
|
1164
1179
|
Inline<'hashnum'>,
|
|
1165
1180
|
Parser<HTMLAnchorElement, Context, [
|
|
1166
|
-
|
|
1181
|
+
TextLinkParser,
|
|
1167
1182
|
]> {
|
|
1168
1183
|
}
|
|
1169
1184
|
export interface AnchorParser extends
|
|
1170
1185
|
// >>1
|
|
1171
1186
|
Inline<'anchor'>,
|
|
1172
1187
|
Parser<HTMLAnchorElement, Context, [
|
|
1173
|
-
|
|
1188
|
+
TextLinkParser,
|
|
1174
1189
|
]> {
|
|
1175
1190
|
}
|
|
1176
1191
|
}
|
package/package.json
CHANGED
package/src/debug.test.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { querySelector, querySelectorAll } from 'typed-dom/query';
|
|
|
5
5
|
export function inspect(result: Result<HTMLElement | string>, until: number | string = Infinity): Result<string> {
|
|
6
6
|
return result && [
|
|
7
7
|
eval(result).map((node, i, nodes) => {
|
|
8
|
-
assert(node || node === '' && '([{'.includes(nodes[i + 1]
|
|
8
|
+
assert(node || node === '' && '([{'.includes(nodes[i + 1][0]));
|
|
9
9
|
if (typeof node === 'string') return node;
|
|
10
10
|
node = node.cloneNode(true);
|
|
11
11
|
assert(!querySelector(node, '.invalid[data-invalid-message$="."]'));
|
|
@@ -14,14 +14,15 @@ describe('Unit: parser/inline/annotation', () => {
|
|
|
14
14
|
assert.deepStrictEqual(inspect(parser('(())')), undefined);
|
|
15
15
|
assert.deepStrictEqual(inspect(parser('(()))')), undefined);
|
|
16
16
|
assert.deepStrictEqual(inspect(parser('(( ))')), undefined);
|
|
17
|
+
assert.deepStrictEqual(inspect(parser('(( (a')), [['', '(('], ' (a']);
|
|
17
18
|
assert.deepStrictEqual(inspect(parser('((\n))')), undefined);
|
|
18
19
|
assert.deepStrictEqual(inspect(parser('((\na))')), undefined);
|
|
19
20
|
assert.deepStrictEqual(inspect(parser('((\\\na))')), undefined);
|
|
20
|
-
assert.deepStrictEqual(inspect(parser('((a\n))')), [['(('], 'a\n))']);
|
|
21
|
-
assert.deepStrictEqual(inspect(parser('((a\\\n))')), [['(('], 'a\\\n))']);
|
|
22
|
-
assert.deepStrictEqual(inspect(parser('((a\nb))')), [['(('], 'a\nb))']);
|
|
23
|
-
assert.deepStrictEqual(inspect(parser('((a\\\nb))')), [['(('], 'a\\\nb))']);
|
|
24
|
-
assert.deepStrictEqual(inspect(parser('((*a\nb*))')), [['(('], '*a\nb*))']);
|
|
21
|
+
assert.deepStrictEqual(inspect(parser('((a\n))')), [['', '(('], 'a\n))']);
|
|
22
|
+
assert.deepStrictEqual(inspect(parser('((a\\\n))')), [['', '(('], 'a\\\n))']);
|
|
23
|
+
assert.deepStrictEqual(inspect(parser('((a\nb))')), [['', '(('], 'a\nb))']);
|
|
24
|
+
assert.deepStrictEqual(inspect(parser('((a\\\nb))')), [['', '(('], 'a\\\nb))']);
|
|
25
|
+
assert.deepStrictEqual(inspect(parser('((*a\nb*))')), [['', '(('], '*a\nb*))']);
|
|
25
26
|
assert.deepStrictEqual(inspect(parser('((\\))')), undefined);
|
|
26
27
|
assert.deepStrictEqual(inspect(parser('((a)b))')), undefined);
|
|
27
28
|
assert.deepStrictEqual(inspect(parser('(((a))')), undefined);
|
|
@@ -2,13 +2,14 @@ import { undefined } from 'spica/global';
|
|
|
2
2
|
import { AnnotationParser } from '../inline';
|
|
3
3
|
import { union, some, validate, guard, context, precedence, creator, recursion, surround, lazy } from '../../combinator';
|
|
4
4
|
import { inline } from '../inline';
|
|
5
|
-
import { optimize } from './
|
|
6
|
-
import {
|
|
5
|
+
import { optimize } from './link';
|
|
6
|
+
import { startLoose, trimNode } from '../util';
|
|
7
7
|
import { html, defrag } from 'typed-dom/dom';
|
|
8
8
|
|
|
9
9
|
export const annotation: AnnotationParser = lazy(() => creator(recursion(precedence(6, validate('((', surround(
|
|
10
10
|
'((',
|
|
11
11
|
guard(context => context.syntax?.inline?.annotation ?? true,
|
|
12
|
+
startLoose(
|
|
12
13
|
context({ syntax: { inline: {
|
|
13
14
|
annotation: false,
|
|
14
15
|
// Redundant
|
|
@@ -20,8 +21,8 @@ export const annotation: AnnotationParser = lazy(() => creator(recursion(precede
|
|
|
20
21
|
//link: true,
|
|
21
22
|
//autolink: true,
|
|
22
23
|
}}, delimiters: undefined },
|
|
23
|
-
|
|
24
|
+
some(union([inline]), ')', [[/^\\?\n/, 9], [')', 3], ['))', 6]])), ')')),
|
|
24
25
|
'))',
|
|
25
26
|
false,
|
|
26
|
-
([, ns], rest) => [[html('sup', { class: 'annotation' }, [html('span',
|
|
27
|
+
([, ns], rest) => [[html('sup', { class: 'annotation' }, [html('span', trimNode(defrag(ns)))])], rest],
|
|
27
28
|
([, ns, rest], next) => next[0] === ')' ? undefined : optimize('((', ns, rest)))))));
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AutolinkParser } from '../../inline';
|
|
2
|
-
import { union, tails, verify, rewrite,
|
|
3
|
-
import {
|
|
2
|
+
import { union, tails, verify, rewrite, open, convert, fmap, lazy } from '../../../combinator';
|
|
3
|
+
import { textlink } from '../link';
|
|
4
4
|
import { str } from '../../source';
|
|
5
5
|
import { define } from 'typed-dom/dom';
|
|
6
6
|
|
|
@@ -17,10 +17,6 @@ export const account: AutolinkParser.AccountParser = lazy(() => fmap(rewrite(
|
|
|
17
17
|
str(/^[A-Za-z][0-9A-Za-z]*(?:-[0-9A-Za-z]+)*/),
|
|
18
18
|
([source]) => source.length <= 64),
|
|
19
19
|
])),
|
|
20
|
-
context({ syntax: { inline: {
|
|
21
|
-
link: true,
|
|
22
|
-
autolink: false,
|
|
23
|
-
}}},
|
|
24
20
|
convert(
|
|
25
21
|
source =>
|
|
26
22
|
`[${source}]{ ${
|
|
@@ -28,5 +24,5 @@ export const account: AutolinkParser.AccountParser = lazy(() => fmap(rewrite(
|
|
|
28
24
|
? `https://${source.slice(1).replace('/', '/@')}`
|
|
29
25
|
: `/${source}`
|
|
30
26
|
} }`,
|
|
31
|
-
union([
|
|
27
|
+
union([textlink]))),
|
|
32
28
|
([el]) => [define(el, { class: 'account' })]));
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AutolinkParser } from '../../inline';
|
|
2
|
-
import { union, validate, focus,
|
|
3
|
-
import {
|
|
2
|
+
import { union, validate, focus, convert, fmap, lazy } from '../../../combinator';
|
|
3
|
+
import { textlink } from '../link';
|
|
4
4
|
import { define } from 'typed-dom/dom';
|
|
5
5
|
|
|
6
6
|
// Timeline(pseudonym): user/tid
|
|
@@ -14,10 +14,6 @@ import { define } from 'typed-dom/dom';
|
|
|
14
14
|
|
|
15
15
|
export const anchor: AutolinkParser.AnchorParser = lazy(() => validate('>>', fmap(focus(
|
|
16
16
|
/^>>(?:[A-Za-z][0-9A-Za-z]*(?:-[0-9A-Za-z]+)*\/)?[0-9A-Za-z]+(?:-[0-9A-Za-z]+)*(?![0-9A-Za-z@#:])/,
|
|
17
|
-
context({ syntax: { inline: {
|
|
18
|
-
link: true,
|
|
19
|
-
autolink: false,
|
|
20
|
-
}}},
|
|
21
17
|
convert(
|
|
22
18
|
source =>
|
|
23
19
|
`[${source}]{ ${
|
|
@@ -25,5 +21,5 @@ export const anchor: AutolinkParser.AnchorParser = lazy(() => validate('>>', fma
|
|
|
25
21
|
? `/@${source.slice(2).replace('/', '/timeline/')}`
|
|
26
22
|
: `?at=${source.slice(2)}`
|
|
27
23
|
} }`,
|
|
28
|
-
union([
|
|
24
|
+
union([textlink]))),
|
|
29
25
|
([el]) => [define(el, { class: 'anchor' })])));
|
|
@@ -1,17 +1,13 @@
|
|
|
1
1
|
import { AutolinkParser } from '../../inline';
|
|
2
|
-
import { union, rewrite,
|
|
3
|
-
import {
|
|
2
|
+
import { union, rewrite, open, convert, fmap, lazy } from '../../../combinator';
|
|
3
|
+
import { textlink } from '../link';
|
|
4
4
|
import { emoji } from './hashtag';
|
|
5
5
|
import { str } from '../../source';
|
|
6
6
|
import { define } from 'typed-dom/dom';
|
|
7
7
|
|
|
8
8
|
export const hashnum: AutolinkParser.HashnumParser = lazy(() => fmap(rewrite(
|
|
9
9
|
open('#', str(new RegExp(/^[0-9]{1,16}(?![^\p{C}\p{S}\p{P}\s]|emoji|['_])/u.source.replace(/emoji/, emoji), 'u'))),
|
|
10
|
-
context({ syntax: { inline: {
|
|
11
|
-
link: true,
|
|
12
|
-
autolink: false,
|
|
13
|
-
}}},
|
|
14
10
|
convert(
|
|
15
11
|
source => `[${source}]{ ${source.slice(1)} }`,
|
|
16
|
-
union([
|
|
12
|
+
union([textlink]))),
|
|
17
13
|
([el]) => [define(el, { class: 'hashnum', href: null })]));
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AutolinkParser } from '../../inline';
|
|
2
|
-
import { union, tails, verify, rewrite,
|
|
3
|
-
import {
|
|
2
|
+
import { union, tails, verify, rewrite, open, convert, fmap, lazy } from '../../../combinator';
|
|
3
|
+
import { textlink } from '../link';
|
|
4
4
|
import { str } from '../../source';
|
|
5
5
|
import { define } from 'typed-dom/dom';
|
|
6
6
|
|
|
@@ -24,10 +24,6 @@ export const hashtag: AutolinkParser.HashtagParser = lazy(() => fmap(rewrite(
|
|
|
24
24
|
].join('').replace(/emoji/g, emoji), 'u')),
|
|
25
25
|
([source]) => source.length <= 128),
|
|
26
26
|
])),
|
|
27
|
-
context({ syntax: { inline: {
|
|
28
|
-
link: true,
|
|
29
|
-
autolink: false,
|
|
30
|
-
}}},
|
|
31
27
|
convert(
|
|
32
28
|
source =>
|
|
33
29
|
`[${source}]{ ${
|
|
@@ -35,5 +31,5 @@ export const hashtag: AutolinkParser.HashtagParser = lazy(() => fmap(rewrite(
|
|
|
35
31
|
? `https://${source.slice(1).replace('/', '/hashtags/')}`
|
|
36
32
|
: `/hashtags/${source.slice(1)}`
|
|
37
33
|
} }`,
|
|
38
|
-
union([
|
|
34
|
+
union([textlink]))),
|
|
39
35
|
([el]) => [define(el, { class: 'hashtag' }, el.innerText)]));
|
|
@@ -72,6 +72,7 @@ describe('Unit: parser/inline/autolink/url', () => {
|
|
|
72
72
|
assert.deepStrictEqual(inspect(parser('http://host>')), [['<a href="http://host" target="_blank">http://host</a>'], '>']);
|
|
73
73
|
assert.deepStrictEqual(inspect(parser('http://host(')), [['<a href="http://host" target="_blank">http://host</a>'], '(']);
|
|
74
74
|
assert.deepStrictEqual(inspect(parser('http://host)')), [['<a href="http://host" target="_blank">http://host</a>'], ')']);
|
|
75
|
+
assert.deepStrictEqual(inspect(parser('http://host\\"')), [['<a href="http://host" target="_blank">http://host</a>'], '\\"']);
|
|
75
76
|
assert.deepStrictEqual(inspect(parser('http://host!?**.*--++==~~^^')), [['<a href="http://host" target="_blank">http://host</a>'], '!?**.*--++==~~^^']);
|
|
76
77
|
});
|
|
77
78
|
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { AutolinkParser } from '../../inline';
|
|
2
2
|
import { union, some, validate, focus, rewrite, precedence, creator, convert, surround, open, lazy } from '../../../combinator';
|
|
3
|
-
import {
|
|
3
|
+
import { textlink } from '../link';
|
|
4
4
|
import { unescsource } from '../../source';
|
|
5
|
-
import { clean } from '../../util';
|
|
6
5
|
|
|
7
|
-
const closer = /^[-+*=~^,.;:!?]*(?=["`|\[\](){}<>]
|
|
6
|
+
const closer = /^[-+*=~^,.;:!?]*(?=[\\"`|\[\](){}<>]|$)/;
|
|
8
7
|
|
|
9
8
|
export const url: AutolinkParser.UrlParser = lazy(() => validate(['http://', 'https://'], rewrite(
|
|
10
9
|
open(
|
|
@@ -12,7 +11,7 @@ export const url: AutolinkParser.UrlParser = lazy(() => validate(['http://', 'ht
|
|
|
12
11
|
focus(/^[\x21-\x7E]+/, some(union([bracket, some(unescsource, closer)])))),
|
|
13
12
|
convert(
|
|
14
13
|
url => `{ ${url} }`,
|
|
15
|
-
|
|
14
|
+
union([textlink])))));
|
|
16
15
|
|
|
17
16
|
const bracket: AutolinkParser.UrlParser.BracketParser = lazy(() => creator(precedence(3, union([
|
|
18
17
|
surround('(', some(union([bracket, unescsource]), ')'), ')', true),
|
|
@@ -73,7 +73,7 @@ describe('Unit: parser/inline/bracket', () => {
|
|
|
73
73
|
assert.deepStrictEqual(inspect(parser('"a')), [['"', 'a'], '']);
|
|
74
74
|
assert.deepStrictEqual(inspect(parser('"a"')), [['"', 'a', '"'], '']);
|
|
75
75
|
assert.deepStrictEqual(inspect(parser('"(")"')), [['"', '', '(', '"'], ')"']);
|
|
76
|
-
assert.deepStrictEqual(inspect(parser('"(("')), [['"', '((', '"'], '']);
|
|
76
|
+
assert.deepStrictEqual(inspect(parser('"(("')), [['"', '', '((', '"'], '']);
|
|
77
77
|
assert.deepStrictEqual(inspect(parser('"(\\")"')), [['"', '<span class="paren">(")</span>', '"'], '']);
|
|
78
78
|
assert.deepStrictEqual(inspect(parser('"(\n)"')), [['"', '<span class="paren">(<br>)</span>', '"'], '']);
|
|
79
79
|
assert.deepStrictEqual(inspect(parser('"(\\\n)"')), [['"', '<span class="paren">(<span class="linebreak"> </span>)</span>', '"'], '']);
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { undefined, location, encodeURI, decodeURI, Location } from 'spica/global';
|
|
2
|
-
import { LinkParser } from '../inline';
|
|
3
|
-
import { eval } from '../../combinator/data/parser';
|
|
4
|
-
import { union, inits, tails, some, validate, guard, context, precedence, creator, surround, open, dup, reverse, lazy, fmap, bind } from '../../combinator';
|
|
2
|
+
import { LinkParser, TextLinkParser } from '../inline';
|
|
3
|
+
import { Result, eval } from '../../combinator/data/parser';
|
|
4
|
+
import { union, inits, tails, subsequence, some, validate, guard, context, precedence, creator, surround, open, dup, reverse, lazy, fmap, bind } from '../../combinator';
|
|
5
5
|
import { inline, media, shortmedia } from '../inline';
|
|
6
6
|
import { attributes } from './html';
|
|
7
7
|
import { autolink } from '../autolink';
|
|
8
|
-
import { str } from '../source';
|
|
9
|
-
import {
|
|
8
|
+
import { unescsource, str } from '../source';
|
|
9
|
+
import { trimNode, stringify } from '../util';
|
|
10
10
|
import { html, define, defrag } from 'typed-dom/dom';
|
|
11
11
|
import { ReadonlyURL } from 'spica/url';
|
|
12
12
|
|
|
@@ -17,7 +17,7 @@ Object.setPrototypeOf(optspec, null);
|
|
|
17
17
|
|
|
18
18
|
export const link: LinkParser = lazy(() => validate(['[', '{'], creator(10, precedence(3, bind(
|
|
19
19
|
guard(context => context.syntax?.inline?.link ?? true,
|
|
20
|
-
|
|
20
|
+
fmap(subsequence([
|
|
21
21
|
context({ syntax: { inline: {
|
|
22
22
|
link: false,
|
|
23
23
|
}}},
|
|
@@ -36,15 +36,22 @@ export const link: LinkParser = lazy(() => validate(['[', '{'], creator(10, prec
|
|
|
36
36
|
media: false,
|
|
37
37
|
autolink: false,
|
|
38
38
|
}}},
|
|
39
|
-
|
|
39
|
+
some(inline, ']', [[/^\\?\n/, 9], [']', 3]])),
|
|
40
40
|
']',
|
|
41
|
-
true
|
|
41
|
+
true,
|
|
42
|
+
undefined,
|
|
43
|
+
([, ns = [], rest], next) => next[0] === ']' ? undefined : optimize('[', ns, rest)),
|
|
42
44
|
]))),
|
|
45
|
+
// 全体の失敗が確定した時も解析し予算を浪費している
|
|
43
46
|
dup(surround(/^{(?![{}])/, inits([uri, some(option)]), /^[^\S\n]*}/)),
|
|
44
|
-
])
|
|
45
|
-
([
|
|
47
|
+
]),
|
|
48
|
+
([as, bs = []]) => bs[0] === '\r' && bs.shift() ? [as, bs] : as[0] === '\r' && as.shift() ? [[], as] : [as, []])),
|
|
49
|
+
([content, params]: [(HTMLElement | string)[], string[]], rest, context) => {
|
|
50
|
+
if (params.length === 0) return;
|
|
51
|
+
assert(content[0] !== '' || params.length === 0);
|
|
52
|
+
if (content[0] === '') return [content, rest];
|
|
46
53
|
assert(params.every(p => typeof p === 'string'));
|
|
47
|
-
content
|
|
54
|
+
if (content.length !== 0 && trimNode(content).length === 0) return;
|
|
48
55
|
if (eval(some(autolink)(stringify(content), context))?.some(node => typeof node === 'object')) return;
|
|
49
56
|
assert(!html('div', content).querySelector('a, .media, .annotation, .reference') || (content[0] as HTMLElement).matches('.media'));
|
|
50
57
|
const INSECURE_URI = params.shift()!;
|
|
@@ -62,10 +69,35 @@ export const link: LinkParser = lazy(() => validate(['[', '{'], creator(10, prec
|
|
|
62
69
|
return [[define(el, attributes('link', [], optspec, params))], rest];
|
|
63
70
|
})))));
|
|
64
71
|
|
|
65
|
-
export const
|
|
72
|
+
export const textlink: TextLinkParser = lazy(() => validate(['[', '{'], creator(10, precedence(3, bind(
|
|
73
|
+
reverse(tails([
|
|
74
|
+
dup(surround('[', some(union([unescsource]), ']'), ']')),
|
|
75
|
+
dup(surround(/^{(?![{}])/, inits([uri, some(option)]), /^[^\S\n]*}/)),
|
|
76
|
+
])),
|
|
77
|
+
([params, content = []], rest, context) => {
|
|
78
|
+
assert(params[0] === '\r');
|
|
79
|
+
params.shift();
|
|
80
|
+
assert(params.every(p => typeof p === 'string'));
|
|
81
|
+
trimNode(content);
|
|
82
|
+
const INSECURE_URI = params.shift()!;
|
|
83
|
+
assert(INSECURE_URI === INSECURE_URI.trim());
|
|
84
|
+
assert(!INSECURE_URI.match(/\s/));
|
|
85
|
+
const el = elem(
|
|
86
|
+
INSECURE_URI,
|
|
87
|
+
defrag(content),
|
|
88
|
+
new ReadonlyURL(
|
|
89
|
+
resolve(INSECURE_URI, context.host ?? location, context.url ?? context.host ?? location),
|
|
90
|
+
context.host?.href || location.href),
|
|
91
|
+
context.host?.origin || location.origin);
|
|
92
|
+
assert(!el.classList.contains('invalid'));
|
|
93
|
+
assert(el.classList.length === 0);
|
|
94
|
+
return [[define(el, attributes('link', [], optspec, params))], rest];
|
|
95
|
+
})))));
|
|
96
|
+
|
|
97
|
+
export const uri: LinkParser.ParameterParser.UriParser = fmap(union([
|
|
66
98
|
open(/^[^\S\n]+/, str(/^\S+/)),
|
|
67
99
|
str(/^[^\s{}]+/),
|
|
68
|
-
]);
|
|
100
|
+
]), ([uri]) => ['\r', uri]);
|
|
69
101
|
|
|
70
102
|
export const option: LinkParser.ParameterParser.OptionParser = union([
|
|
71
103
|
fmap(str(/^[^\S\n]+nofollow(?=[^\S\n]|})/), () => [` rel="nofollow"`]),
|
|
@@ -163,3 +195,12 @@ function decode(uri: string): string {
|
|
|
163
195
|
return uri.replace(/\s+/g, encodeURI);
|
|
164
196
|
}
|
|
165
197
|
}
|
|
198
|
+
|
|
199
|
+
export function optimize(opener: string, ns: readonly (string | HTMLElement)[], rest: string): Result<string> {
|
|
200
|
+
let count = 0;
|
|
201
|
+
for (let i = 0; i < ns.length - 1; i += 2) {
|
|
202
|
+
if (ns[i] !== '' || ns[i + 1] !== opener[0]) break;
|
|
203
|
+
++count;
|
|
204
|
+
}
|
|
205
|
+
return [['', opener[0].repeat(opener.length + count)], rest.slice(count)];
|
|
206
|
+
}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { undefined, location } from 'spica/global';
|
|
2
2
|
import { MediaParser } from '../inline';
|
|
3
3
|
import { union, inits, tails, some, validate, verify, guard, precedence, creator, surround, open, dup, lazy, fmap, bind } from '../../combinator';
|
|
4
|
-
import {
|
|
4
|
+
import { textlink, uri, option as linkoption, resolve } from './link';
|
|
5
5
|
import { attributes } from './html';
|
|
6
6
|
import { unsafehtmlentity } from './htmlentity';
|
|
7
7
|
import { txt, str } from '../source';
|
|
8
8
|
import { html, define } from 'typed-dom/dom';
|
|
9
9
|
import { ReadonlyURL } from 'spica/url';
|
|
10
|
-
import { unshift, push } from 'spica/array';
|
|
10
|
+
import { unshift, shift, push } from 'spica/array';
|
|
11
11
|
|
|
12
12
|
const optspec = {
|
|
13
13
|
'width': [],
|
|
@@ -28,7 +28,7 @@ export const media: MediaParser = lazy(() => validate(['![', '!{'], creator(10,
|
|
|
28
28
|
true)),
|
|
29
29
|
dup(surround(/^{(?![{}])/, inits([uri, some(option)]), /^[^\S\n]*}/)),
|
|
30
30
|
]))),
|
|
31
|
-
([as, bs]) => bs ? [[as.join('').trim() || as.join('')], bs] : [[''], as]),
|
|
31
|
+
([as, bs]) => bs ? [[as.join('').trim() || as.join('')], shift(bs)[1]] : [[''], shift(as)[1]]),
|
|
32
32
|
([[text]]) => text === '' || text.trim() !== ''),
|
|
33
33
|
([[text], params], rest, context) => {
|
|
34
34
|
assert(text === text.trim());
|
|
@@ -54,7 +54,7 @@ export const media: MediaParser = lazy(() => validate(['![', '!{'], creator(10,
|
|
|
54
54
|
}
|
|
55
55
|
if (context.syntax?.inline?.link === false || cache && cache.tagName !== 'IMG') return [[el], rest];
|
|
56
56
|
return fmap(
|
|
57
|
-
|
|
57
|
+
textlink as MediaParser,
|
|
58
58
|
([link]) => [define(link, { target: '_blank' }, [el])])
|
|
59
59
|
(`{ ${INSECURE_URI}${params.join('')} }${rest}`, context);
|
|
60
60
|
})))));
|
|
@@ -14,14 +14,15 @@ describe('Unit: parser/inline/reference', () => {
|
|
|
14
14
|
assert.deepStrictEqual(inspect(parser('[[]]')), undefined);
|
|
15
15
|
assert.deepStrictEqual(inspect(parser('[[]]]')), undefined);
|
|
16
16
|
assert.deepStrictEqual(inspect(parser('[[ ]]')), undefined);
|
|
17
|
+
assert.deepStrictEqual(inspect(parser('[[ [a')), [['', '[['], ' [a']);
|
|
17
18
|
assert.deepStrictEqual(inspect(parser('[[\n]]')), undefined);
|
|
18
19
|
assert.deepStrictEqual(inspect(parser('[[\na]]')), undefined);
|
|
19
20
|
assert.deepStrictEqual(inspect(parser('[[\\\na]]')), undefined);
|
|
20
|
-
assert.deepStrictEqual(inspect(parser('[[a\n]]')), [['[['], 'a\n]]']);
|
|
21
|
-
assert.deepStrictEqual(inspect(parser('[[a\\\n]]')), [['[['], 'a\\\n]]']);
|
|
22
|
-
assert.deepStrictEqual(inspect(parser('[[a\nb]]')), [['[['], 'a\nb]]']);
|
|
23
|
-
assert.deepStrictEqual(inspect(parser('[[a\\\nb]]')), [['[['], 'a\\\nb]]']);
|
|
24
|
-
assert.deepStrictEqual(inspect(parser('[[*a\nb*]]')), [['[['], '*a\nb*]]']);
|
|
21
|
+
assert.deepStrictEqual(inspect(parser('[[a\n]]')), [['', '[['], 'a\n]]']);
|
|
22
|
+
assert.deepStrictEqual(inspect(parser('[[a\\\n]]')), [['', '[['], 'a\\\n]]']);
|
|
23
|
+
assert.deepStrictEqual(inspect(parser('[[a\nb]]')), [['', '[['], 'a\nb]]']);
|
|
24
|
+
assert.deepStrictEqual(inspect(parser('[[a\\\nb]]')), [['', '[['], 'a\\\nb]]']);
|
|
25
|
+
assert.deepStrictEqual(inspect(parser('[[*a\nb*]]')), [['', '[['], '*a\nb*]]']);
|
|
25
26
|
assert.deepStrictEqual(inspect(parser('[[\\]]')), undefined);
|
|
26
27
|
assert.deepStrictEqual(inspect(parser('[[a]b]]')), undefined);
|
|
27
28
|
assert.deepStrictEqual(inspect(parser('[[[a]]')), undefined);
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import { undefined } from 'spica/global';
|
|
2
2
|
import { ReferenceParser } from '../inline';
|
|
3
|
-
import { Result } from '../../combinator/data/parser';
|
|
4
3
|
import { union, subsequence, some, validate, guard, context, precedence, creator, recursion, surround, open, lazy, bind } from '../../combinator';
|
|
5
4
|
import { inline } from '../inline';
|
|
5
|
+
import { optimize } from './link';
|
|
6
6
|
import { str, stropt } from '../source';
|
|
7
|
-
import { regBlankStart,
|
|
7
|
+
import { regBlankStart, startLoose, trimNode, stringify } from '../util';
|
|
8
8
|
import { html, defrag } from 'typed-dom/dom';
|
|
9
9
|
|
|
10
10
|
export const reference: ReferenceParser = lazy(() => validate('[[', creator(recursion(precedence(6, surround(
|
|
11
11
|
'[[',
|
|
12
12
|
guard(context => context.syntax?.inline?.reference ?? true,
|
|
13
|
+
startLoose(
|
|
13
14
|
context({ syntax: { inline: {
|
|
14
15
|
annotation: false,
|
|
15
16
|
reference: false,
|
|
@@ -23,11 +24,11 @@ export const reference: ReferenceParser = lazy(() => validate('[[', creator(recu
|
|
|
23
24
|
subsequence([
|
|
24
25
|
abbr,
|
|
25
26
|
open(stropt(/^(?=\^)/), some(inline, ']', [[/^\\?\n/, 9], [']', 3], [']]', 6]])),
|
|
26
|
-
|
|
27
|
-
]))),
|
|
27
|
+
some(inline, ']', [[/^\\?\n/, 9], [']', 3], [']]', 6]]),
|
|
28
|
+
])), ']')),
|
|
28
29
|
']]',
|
|
29
30
|
false,
|
|
30
|
-
([, ns], rest) => [[html('sup', attributes(ns), [html('span',
|
|
31
|
+
([, ns], rest) => [[html('sup', attributes(ns), [html('span', trimNode(defrag(ns)))])], rest],
|
|
31
32
|
([, ns, rest], next) => next[0] === ']' ? undefined : optimize('[[', ns, rest)))))));
|
|
32
33
|
|
|
33
34
|
const abbr: ReferenceParser.AbbrParser = creator(bind(surround(
|
|
@@ -51,12 +52,3 @@ function attributes(ns: (string | HTMLElement)[]): Record<string, string | undef
|
|
|
51
52
|
}
|
|
52
53
|
: { class: 'reference' };
|
|
53
54
|
}
|
|
54
|
-
|
|
55
|
-
export function optimize(opener: string, ns: readonly (string | HTMLElement)[], rest: string): Result<string> {
|
|
56
|
-
let count = 0;
|
|
57
|
-
for (let i = 0; i < ns.length - 1; i += 2) {
|
|
58
|
-
if (ns[i] !== '' || ns[i + 1] !== opener[0]) break;
|
|
59
|
-
++count;
|
|
60
|
-
}
|
|
61
|
-
return [[opener[0].repeat(opener.length + count)], rest.slice(count)];
|
|
62
|
-
}
|
|
@@ -143,12 +143,12 @@ describe('Unit: parser/inline', () => {
|
|
|
143
143
|
assert.deepStrictEqual(inspect(parser('Di$ney Micro$oft')), [['Di', '$', 'ney', ' ', 'Micro', '$', 'oft'], '']);
|
|
144
144
|
assert.deepStrictEqual(inspect(parser('Di$ney, Micro$oft')), [['Di', '$', 'ney', ',', ' ', 'Micro', '$', 'oft'], '']);
|
|
145
145
|
assert.deepStrictEqual(inspect(parser('(((a))')), [['', '(', '<sup class="annotation"><span>a</span></sup>'], '']);
|
|
146
|
-
assert.deepStrictEqual(inspect(parser('((((a))')), [['((', '<sup class="annotation"><span>a</span></sup>'], '']);
|
|
146
|
+
assert.deepStrictEqual(inspect(parser('((((a))')), [['', '((', '<sup class="annotation"><span>a</span></sup>'], '']);
|
|
147
147
|
assert.deepStrictEqual(inspect(parser('((((a))))')), [['<sup class="annotation"><span><span class="paren">((a))</span></span></sup>'], '']);
|
|
148
148
|
assert.deepStrictEqual(inspect(parser('((<bdi>))')), [['<sup class="annotation"><span><span class="invalid"><bdi></span></span></sup>'], '']);
|
|
149
149
|
assert.deepStrictEqual(inspect(parser('"((""))')), [['"', '<sup class="annotation"><span>""</span></sup>'], '']);
|
|
150
150
|
assert.deepStrictEqual(inspect(parser('[[[a]]')), [['', '[', '<sup class="reference"><span>a</span></sup>'], '']);
|
|
151
|
-
assert.deepStrictEqual(inspect(parser('[[[[a]]')), [['[[', '<sup class="reference"><span>a</span></sup>'], '']);
|
|
151
|
+
assert.deepStrictEqual(inspect(parser('[[[[a]]')), [['', '[[', '<sup class="reference"><span>a</span></sup>'], '']);
|
|
152
152
|
assert.deepStrictEqual(inspect(parser('[[[[a]]]]')), [['<sup class="reference"><span>[[a]]</span></sup>'], '']);
|
|
153
153
|
assert.deepStrictEqual(inspect(parser('[[[$-1]]]')), [['<sup class="reference"><span><a class="label" data-label="$-1">$-1</a></span></sup>'], '']);
|
|
154
154
|
assert.deepStrictEqual(inspect(parser('[[[]{a}]]')), [['<sup class="reference"><span><a href="a">a</a></span></sup>'], '']);
|
|
@@ -165,7 +165,7 @@ describe('Unit: parser/inline', () => {
|
|
|
165
165
|
assert.deepStrictEqual(inspect(parser('[^a@b')), [['[^', '<a class="email" href="mailto:a@b">a@b</a>'], '']);
|
|
166
166
|
assert.deepStrictEqual(inspect(parser('[#a*b\nc*]')), [['[', '<a href="/hashtags/a" class="hashtag">#a</a>', '<em>b<br>c</em>', ']'], '']);
|
|
167
167
|
assert.deepStrictEqual(inspect(parser('[*a\nb*]{/}')), [['[', '<em>a<br>b</em>', ']', '<a href="/">/</a>'], '']);
|
|
168
|
-
assert.deepStrictEqual(inspect(parser('[[*a\nb*]]')), [['[[', '<em>a<br>b</em>', ']', ']'], '']);
|
|
168
|
+
assert.deepStrictEqual(inspect(parser('[[*a\nb*]]')), [['', '[[', '<em>a<br>b</em>', ']', ']'], '']);
|
|
169
169
|
assert.deepStrictEqual(inspect(parser('"[% *"*"*')), [['"', '[%', ' ', '*', '"', '*', '"', '*'], '']);
|
|
170
170
|
assert.deepStrictEqual(inspect(parser('"[% "*"* %]')), [['"', '[%', ' ', '"', '*', '"', '*', ' ', '%', ']'], '']);
|
|
171
171
|
});
|
package/src/parser/inline.ts
CHANGED
|
@@ -34,6 +34,7 @@ export import MathParser = InlineParser.MathParser;
|
|
|
34
34
|
export import ExtensionParser = InlineParser.ExtensionParser;
|
|
35
35
|
export import RubyParser = InlineParser.RubyParser;
|
|
36
36
|
export import LinkParser = InlineParser.LinkParser;
|
|
37
|
+
export import TextLinkParser = InlineParser.TextLinkParser;
|
|
37
38
|
export import HTMLParser = InlineParser.HTMLParser;
|
|
38
39
|
export import InsertionParser = InlineParser.InsertionParser;
|
|
39
40
|
export import DeletionParser = InlineParser.DeletionParser;
|
package/src/parser/util.ts
CHANGED
|
@@ -182,24 +182,24 @@ export function trimBlankEnd<T extends HTMLElement | string>(parser: Parser<T>):
|
|
|
182
182
|
parser,
|
|
183
183
|
trimNodeEnd);
|
|
184
184
|
}
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
185
|
+
export function trimNode<T extends HTMLElement | string>(nodes: T[]): T[] {
|
|
186
|
+
return trimNodeStart(trimNodeEnd(nodes));
|
|
187
|
+
}
|
|
188
|
+
function trimNodeStart<T extends HTMLElement | string>(nodes: T[]): T[] {
|
|
189
|
+
for (let node = nodes[0]; nodes.length > 0 && !isVisible(node = nodes[0], 0);) {
|
|
190
|
+
if (nodes.length === 1 && typeof node === 'object' && node.className === 'indexer') break;
|
|
191
|
+
if (typeof node === 'string') {
|
|
192
|
+
const pos = node.trimStart().length;
|
|
193
|
+
if (pos > 0) {
|
|
194
|
+
nodes[0] = node.slice(pos) as T;
|
|
195
|
+
break;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
nodes.shift();
|
|
199
|
+
}
|
|
200
|
+
return nodes;
|
|
201
|
+
}
|
|
202
|
+
function trimNodeEnd<T extends HTMLElement | string>(nodes: T[]): T[] {
|
|
203
203
|
const skip = nodes.length > 0 &&
|
|
204
204
|
typeof nodes[nodes.length - 1] === 'object' &&
|
|
205
205
|
nodes[nodes.length - 1]['className'] === 'indexer'
|