securemark 0.287.1 → 0.288.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 +4 -0
- package/dist/index.js +51 -57
- package/markdown.d.ts +11 -34
- package/package.json +1 -1
- package/src/combinator/control/manipulation/convert.ts +4 -4
- package/src/combinator/control/manipulation/trim.ts +3 -3
- package/src/parser/autolink.test.ts +4 -2
- package/src/parser/autolink.ts +2 -1
- package/src/parser/block/blockquote.test.ts +2 -0
- package/src/parser/block/blockquote.ts +4 -4
- package/src/parser/block/codeblock.test.ts +2 -0
- package/src/parser/block/extension/fig.ts +2 -1
- package/src/parser/block/extension/figure.ts +1 -1
- package/src/parser/block/extension/table.ts +2 -2
- package/src/parser/block/paragraph.test.ts +4 -5
- package/src/parser/block/reply/cite.test.ts +8 -10
- package/src/parser/block/reply/cite.ts +24 -11
- package/src/parser/block/reply/quote.test.ts +18 -17
- package/src/parser/block/reply/quote.ts +15 -30
- package/src/parser/block/reply.test.ts +14 -1
- package/src/parser/block/reply.ts +12 -24
- package/src/parser/block/sidefence.test.ts +2 -0
- package/src/parser/block/sidefence.ts +2 -2
- package/src/parser/header.ts +1 -1
- package/src/parser/inline/autolink/account.ts +2 -1
- package/src/parser/inline/autolink/anchor.ts +2 -1
- package/src/parser/inline/autolink/hashnum.ts +2 -1
- package/src/parser/inline/autolink/hashtag.ts +2 -1
- package/src/parser/inline/autolink/url.ts +4 -2
- package/src/parser/inline/shortmedia.ts +4 -2
- package/src/parser/inline/template.ts +1 -1
- package/src/parser/inline.test.ts +2 -0
- package/src/parser/source/str.ts +2 -1
- package/src/parser/util.ts +6 -3
- package/src/parser/visibility.ts +4 -2
- 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.288.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"));
|
|
@@ -24,15 +24,15 @@ Object.defineProperty(exports, "__esModule", ({
|
|
|
24
24
|
exports.trimEnd = exports.trimStart = exports.trim = void 0;
|
|
25
25
|
const convert_1 = __webpack_require__(6572);
|
|
26
26
|
function trim(parser) {
|
|
27
|
-
return (0, convert_1.convert)(source => source.trim(), parser);
|
|
27
|
+
return (0, convert_1.convert)(source => source.trim(), parser, false);
|
|
28
28
|
}
|
|
29
29
|
exports.trim = trim;
|
|
30
30
|
function trimStart(parser) {
|
|
31
|
-
return (0, convert_1.convert)(source => source.trimStart(), parser);
|
|
31
|
+
return (0, convert_1.convert)(source => source.trimStart(), parser, true);
|
|
32
32
|
}
|
|
33
33
|
exports.trimStart = trimStart;
|
|
34
34
|
function trimEnd(parser) {
|
|
35
|
-
return (0, convert_1.convert)(source => source.trimEnd(), parser);
|
|
35
|
+
return (0, convert_1.convert)(source => source.trimEnd(), parser, false);
|
|
36
36
|
}
|
|
37
37
|
exports.trimEnd = trimEnd;
|
|
38
38
|
|
|
@@ -1302,31 +1302,37 @@ class ReadonlyURLSearchParams extends URLSearchParams {
|
|
|
1302
1302
|
Object.defineProperty(exports, "__esModule", ({
|
|
1303
1303
|
value: true
|
|
1304
1304
|
}));
|
|
1305
|
-
exports.cite = void 0;
|
|
1305
|
+
exports.cite = exports.syntax = void 0;
|
|
1306
1306
|
const combinator_1 = __webpack_require__(3484);
|
|
1307
1307
|
const anchor_1 = __webpack_require__(8535);
|
|
1308
1308
|
const source_1 = __webpack_require__(8745);
|
|
1309
1309
|
const dom_1 = __webpack_require__(394);
|
|
1310
|
-
exports.
|
|
1310
|
+
exports.syntax = /^>*(?=>>[^>\s]\S*[^\S\n]*(?:$|\n))/;
|
|
1311
|
+
exports.cite = (0, combinator_1.line)((0, combinator_1.fmap)((0, combinator_1.validate)('>>', (0, combinator_1.open)((0, source_1.str)(exports.syntax), (0, combinator_1.union)([anchor_1.anchor,
|
|
1311
1312
|
// Subject page representation.
|
|
1312
1313
|
// リンクの実装は後で検討
|
|
1313
|
-
(0, combinator_1.focus)(
|
|
1314
|
-
class: 'anchor'
|
|
1315
|
-
}, '>>.')], ''], false), (0, combinator_1.focus)(/^>>#\S*(?=\s*$)/, ({
|
|
1314
|
+
(0, combinator_1.focus)(/^>>#\S*(?=\s*$)/, ({
|
|
1316
1315
|
source
|
|
1317
1316
|
}) => [[(0, dom_1.html)('a', {
|
|
1318
1317
|
class: 'anchor'
|
|
1319
|
-
}, source)], ''], false), (0, combinator_1.focus)(/^>>https
|
|
1318
|
+
}, source)], ''], false), (0, combinator_1.focus)(/^>>https?:\/\/\S+(?=\s*$)/, ({
|
|
1320
1319
|
source
|
|
1321
1320
|
}) => [[(0, dom_1.html)('a', {
|
|
1322
1321
|
class: 'anchor',
|
|
1323
1322
|
href: source.slice(2).trimEnd(),
|
|
1324
1323
|
target: '_blank'
|
|
1325
|
-
}, source)], ''], false)
|
|
1324
|
+
}, source)], ''], false), (0, combinator_1.focus)(/^>>.+(?=\s*$)/, ({
|
|
1325
|
+
source
|
|
1326
|
+
}) => [[source], ''], false)]))), ([quotes, node]) => [(0, dom_1.html)('span', typeof node === 'object' ? {
|
|
1326
1327
|
class: 'cite'
|
|
1327
|
-
}
|
|
1328
|
+
} : {
|
|
1329
|
+
class: 'cite invalid',
|
|
1330
|
+
'data-invalid-syntax': 'cite',
|
|
1331
|
+
'data-invalid-type': 'syntax',
|
|
1332
|
+
'data-invalid-message': 'Invalid syntax'
|
|
1333
|
+
}, (0, dom_1.defrag)([`${quotes}>`, typeof node === 'object' ? (0, dom_1.define)(node, {
|
|
1328
1334
|
'data-depth': `${quotes.length + 1}`
|
|
1329
|
-
},
|
|
1335
|
+
}, node.innerText.slice(1)) : node.slice(1)])), (0, dom_1.html)('br')]));
|
|
1330
1336
|
|
|
1331
1337
|
/***/ },
|
|
1332
1338
|
|
|
@@ -1727,7 +1733,7 @@ exports.autolink = void 0;
|
|
|
1727
1733
|
const combinator_1 = __webpack_require__(3484);
|
|
1728
1734
|
const autolink_1 = __webpack_require__(8072);
|
|
1729
1735
|
const source_1 = __webpack_require__(8745);
|
|
1730
|
-
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]))));
|
|
1736
|
+
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])), false));
|
|
1731
1737
|
|
|
1732
1738
|
/***/ },
|
|
1733
1739
|
|
|
@@ -1996,10 +2002,10 @@ const combinator_1 = __webpack_require__(3484);
|
|
|
1996
2002
|
const link_1 = __webpack_require__(3628);
|
|
1997
2003
|
const source_1 = __webpack_require__(8745);
|
|
1998
2004
|
const closer = /^[-+*=~^_,.;:!?]*(?=[\\"`|\[\](){}<>]|$)/;
|
|
1999
|
-
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.precedence)(1, (0, combinator_1.some)((0, combinator_1.union)([(0, combinator_1.verify)(bracket, ns => ns.length > 0), (0, combinator_1.some)(source_1.unescsource, closer)]))))), (0, combinator_1.union)([(0, combinator_1.constraint)(1 /* State.autolink */, false, (0, combinator_1.state)(1 /* State.autolink */, (0, combinator_1.convert)(url => `{ ${url} }`, link_1.unsafelink))), ({
|
|
2005
|
+
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.precedence)(1, (0, combinator_1.some)((0, combinator_1.union)([(0, combinator_1.verify)(bracket, ns => ns.length > 0), (0, combinator_1.some)(source_1.unescsource, closer)]))))), (0, combinator_1.union)([(0, combinator_1.constraint)(1 /* State.autolink */, false, (0, combinator_1.state)(1 /* State.autolink */, (0, combinator_1.convert)(url => `{ ${url} }`, link_1.unsafelink, false))), ({
|
|
2000
2006
|
source
|
|
2001
2007
|
}) => [[source], '']]))));
|
|
2002
|
-
exports.lineurl = (0, combinator_1.lazy)(() => (0, combinator_1.open)(source_1.linebreak, (0, combinator_1.focus)(/^!?https?:\/\/\S+(?=[^\S\n]*(?:$|\n))/, (0, combinator_1.tails)([(0, source_1.str)('!'), (0, combinator_1.union)([(0, combinator_1.constraint)(1 /* State.autolink */, false, (0, combinator_1.state)(1 /* State.autolink */, (0, combinator_1.convert)(url => `{ ${url} }`, link_1.unsafelink))), ({
|
|
2008
|
+
exports.lineurl = (0, combinator_1.lazy)(() => (0, combinator_1.open)(source_1.linebreak, (0, combinator_1.focus)(/^!?https?:\/\/\S+(?=[^\S\n]*(?:$|\n))/, (0, combinator_1.tails)([(0, source_1.str)('!'), (0, combinator_1.union)([(0, combinator_1.constraint)(1 /* State.autolink */, false, (0, combinator_1.state)(1 /* State.autolink */, (0, combinator_1.convert)(url => `{ ${url} }`, link_1.unsafelink, false))), ({
|
|
2003
2009
|
source
|
|
2004
2010
|
}) => [[source], '']])]))));
|
|
2005
2011
|
const bracket = (0, combinator_1.lazy)(() => (0, combinator_1.union)([(0, combinator_1.surround)((0, source_1.str)('('), (0, combinator_1.recursion)(6 /* Recursion.terminal */, (0, combinator_1.some)((0, combinator_1.union)([bracket, source_1.unescsource]), ')')), (0, source_1.str)(')'), true, undefined, () => [[], ''], [3 | 0 /* Backtrack.lineunescbracket */]), (0, combinator_1.surround)((0, source_1.str)('['), (0, combinator_1.recursion)(6 /* Recursion.terminal */, (0, combinator_1.some)((0, combinator_1.union)([bracket, source_1.unescsource]), ']')), (0, source_1.str)(']'), true, undefined, () => [[], ''], [3 | 0 /* Backtrack.lineunescbracket */]), (0, combinator_1.surround)((0, source_1.str)('{'), (0, combinator_1.recursion)(6 /* Recursion.terminal */, (0, combinator_1.some)((0, combinator_1.union)([bracket, source_1.unescsource]), '}')), (0, source_1.str)('}'), true, undefined, () => [[], ''], [3 | 0 /* Backtrack.lineunescbracket */]), (0, combinator_1.surround)((0, source_1.str)('"'), (0, combinator_1.precedence)(2, (0, combinator_1.recursion)(6 /* Recursion.terminal */, (0, combinator_1.some)(source_1.unescsource, '"'))), (0, source_1.str)('"'), true, undefined, () => [[], ''], [3 | 0 /* Backtrack.lineunescbracket */])]));
|
|
@@ -2494,7 +2500,7 @@ exports.header = (0, combinator_1.lazy)(() => (0, combinator_1.validate)(/^---+[
|
|
|
2494
2500
|
class: 'header'
|
|
2495
2501
|
}, [(0, dom_1.html)('details', {
|
|
2496
2502
|
open: ''
|
|
2497
|
-
}, (0, dom_1.defrag)([(0, dom_1.html)('summary', 'Header'), ...es]))])])), false)), ({
|
|
2503
|
+
}, (0, dom_1.defrag)([(0, dom_1.html)('summary', 'Header'), ...es]))])]), false), false)), ({
|
|
2498
2504
|
source
|
|
2499
2505
|
}) => [[(0, dom_1.html)('pre', {
|
|
2500
2506
|
class: 'invalid',
|
|
@@ -3424,7 +3430,7 @@ const align = (0, combinator_1.line)((0, combinator_1.fmap)((0, combinator_1.uni
|
|
|
3424
3430
|
const delimiter = /^[-=<>]+(?:\/[-=^v]*)?(?=[^\S\n]*\n)|^[#:](?:(?!:\D|0)\d*:(?!0)\d*)?(?:!+[+]?)?(?=\s)/;
|
|
3425
3431
|
const head = (0, combinator_1.block)((0, combinator_1.fmap)((0, combinator_1.open)((0, source_1.str)(/^#(?:(?!:\D|0)\d*:(?!0)\d*)?(?:!+[+]?)?(?=\s)/), (0, combinator_1.rewrite)((0, combinator_1.inits)([source_1.anyline, (0, combinator_1.some)(source_1.contentline, delimiter)]), (0, combinator_1.union)([(0, combinator_1.block)((0, combinator_1.surround)(/^[^\n]/, inline_1.medialink, /^\s*$/)), (0, combinator_1.block)((0, combinator_1.surround)(/^[^\n]/, inline_1.media, /^\s*$/)), (0, combinator_1.block)((0, combinator_1.surround)(/^[^\n]/, inline_1.shortmedia, /^\s*$/)), (0, combinator_1.open)(/^(?:\s*\n|\s)/, (0, visibility_1.visualize)((0, visibility_1.trimBlank)((0, combinator_1.some)(inline_1.inline))), true)])), true), ns => [(0, dom_1.html)('th', attributes(ns.shift()), (0, dom_1.defrag)(ns))]), false);
|
|
3426
3432
|
const data = (0, combinator_1.block)((0, combinator_1.fmap)((0, combinator_1.open)((0, source_1.str)(/^:(?:(?!:\D|0)\d*:(?!0)\d*)?(?:!+[+]?)?(?=\s)/), (0, combinator_1.rewrite)((0, combinator_1.inits)([source_1.anyline, (0, combinator_1.some)(source_1.contentline, delimiter)]), (0, combinator_1.union)([(0, combinator_1.block)((0, combinator_1.surround)(/^[^\n]/, inline_1.medialink, /^\s*$/)), (0, combinator_1.block)((0, combinator_1.surround)(/^[^\n]/, inline_1.media, /^\s*$/)), (0, combinator_1.block)((0, combinator_1.surround)(/^[^\n]/, inline_1.shortmedia, /^\s*$/)), (0, combinator_1.open)(/^(?:\s*\n|\s)/, (0, visibility_1.visualize)((0, visibility_1.trimBlankEnd)((0, util_1.lineable)((0, combinator_1.some)(inline_1.inline)))), true)])), true), ns => [(0, dom_1.html)('td', attributes(ns.shift()), (0, dom_1.defrag)(ns))]), false);
|
|
3427
|
-
const dataline = (0, combinator_1.line)((0, combinator_1.rewrite)(source_1.contentline, (0, combinator_1.union)([(0, combinator_1.validate)(/^!+\s/, (0, combinator_1.convert)(source => `:${source}`, data)), (0, combinator_1.convert)(source => `: ${source}`, data)])));
|
|
3433
|
+
const dataline = (0, combinator_1.line)((0, combinator_1.rewrite)(source_1.contentline, (0, combinator_1.union)([(0, combinator_1.validate)(/^!+\s/, (0, combinator_1.convert)(source => `:${source}`, data, true)), (0, combinator_1.convert)(source => `: ${source}`, data, true)])));
|
|
3428
3434
|
function attributes(source) {
|
|
3429
3435
|
let [, rowspan = undefined, colspan = undefined, highlight = undefined, extension = undefined] = source.match(/^[#:](?:(\d+)?:(\d+)?)?(?:(!+)([+]?))?$/) ?? [];
|
|
3430
3436
|
rowspan === '1' ? rowspan = undefined : undefined;
|
|
@@ -4053,15 +4059,9 @@ const inline_1 = __webpack_require__(7973);
|
|
|
4053
4059
|
const source_1 = __webpack_require__(8745);
|
|
4054
4060
|
const util_1 = __webpack_require__(4992);
|
|
4055
4061
|
const visibility_1 = __webpack_require__(6364);
|
|
4056
|
-
const array_1 = __webpack_require__(6876);
|
|
4057
4062
|
const dom_1 = __webpack_require__(394);
|
|
4058
|
-
|
|
4059
|
-
|
|
4060
|
-
対象がページである場合>>.を表現方法とする
|
|
4061
|
-
対象をURLで指定すべき(引用ツリーにルートを追加する)場合はない
|
|
4062
|
-
対象と引用は1:N(分割)、N:1(統合)のみ可能、N:N(混合)は不可能
|
|
4063
|
-
*/
|
|
4064
|
-
exports.reply = (0, combinator_1.block)((0, combinator_1.validate)('>', (0, combinator_1.fmap)((0, combinator_1.inits)([(0, combinator_1.some)((0, combinator_1.inits)([cite_1.cite, quote_1.quote])), (0, combinator_1.some)((0, combinator_1.subsequence)([(0, combinator_1.some)(quote_1.quote), (0, combinator_1.fmap)((0, combinator_1.rewrite)((0, combinator_1.some)(source_1.anyline, quote_1.syntax), (0, visibility_1.visualize)((0, util_1.lineable)((0, combinator_1.some)(inline_1.inline)))), ns => (0, array_1.push)(ns, [(0, dom_1.html)('br')]))]))]), ns => [(0, dom_1.html)('p', (0, visibility_1.trimBlankNodeEnd)((0, dom_1.defrag)(ns)))])));
|
|
4063
|
+
const delimiter = new RegExp(String.raw`${cite_1.syntax.source}|${quote_1.syntax.source}`);
|
|
4064
|
+
exports.reply = (0, combinator_1.block)((0, combinator_1.validate)(cite_1.syntax, (0, combinator_1.fmap)((0, combinator_1.some)((0, combinator_1.union)([cite_1.cite, quote_1.quote, (0, combinator_1.rewrite)((0, combinator_1.some)(source_1.anyline, delimiter), (0, visibility_1.visualize)((0, util_1.lineable)((0, combinator_1.some)(inline_1.inline), true)))])), ns => [(0, dom_1.html)('p', (0, visibility_1.trimBlankNodeEnd)((0, dom_1.defrag)(ns)))])));
|
|
4065
4065
|
|
|
4066
4066
|
/***/ },
|
|
4067
4067
|
|
|
@@ -4338,7 +4338,8 @@ function str(pattern, not) {
|
|
|
4338
4338
|
const m = source.match(pattern);
|
|
4339
4339
|
count && m && (0, combinator_1.consume)(m[0].length, context);
|
|
4340
4340
|
if (m && not && source.slice(m[0].length, m[0].length + not.length) === not) return;
|
|
4341
|
-
|
|
4341
|
+
//assert(!m || m[0]);
|
|
4342
|
+
return m ? [[m[0]], source.slice(m[0].length)] : undefined;
|
|
4342
4343
|
};
|
|
4343
4344
|
}
|
|
4344
4345
|
exports.str = str;
|
|
@@ -4403,7 +4404,7 @@ const link_1 = __webpack_require__(3628);
|
|
|
4403
4404
|
const source_1 = __webpack_require__(8745);
|
|
4404
4405
|
const dom_1 = __webpack_require__(394);
|
|
4405
4406
|
// https://example/@user must be a user page or a redirect page going there.
|
|
4406
|
-
exports.account = (0, combinator_1.lazy)(() => (0, combinator_1.rewrite)((0, combinator_1.open)('@', (0, combinator_1.tails)([(0, source_1.str)(/^[0-9a-z](?:(?:[0-9a-z]|-(?=[0-9a-z])){0,61}[0-9a-z])?(?:\.[0-9a-z](?:(?:[0-9a-z]|-(?=[0-9a-z])){0,61}[0-9a-z])?)*\//i), (0, source_1.str)(/^[a-z][0-9a-z]*(?:[-.][0-9a-z]+)*/i)])), (0, combinator_1.union)([(0, combinator_1.constraint)(1 /* State.autolink */, false, (0, combinator_1.state)(1 /* State.autolink */, (0, combinator_1.fmap)((0, combinator_1.convert)(source => `[${source}]{ ${source.includes('/') ? `https://${source.slice(1).replace('/', '/@')}` : `/${source}`} }`, link_1.unsafelink), ([el]) => [(0, dom_1.define)(el, {
|
|
4407
|
+
exports.account = (0, combinator_1.lazy)(() => (0, combinator_1.rewrite)((0, combinator_1.open)('@', (0, combinator_1.tails)([(0, source_1.str)(/^[0-9a-z](?:(?:[0-9a-z]|-(?=[0-9a-z])){0,61}[0-9a-z])?(?:\.[0-9a-z](?:(?:[0-9a-z]|-(?=[0-9a-z])){0,61}[0-9a-z])?)*\//i), (0, source_1.str)(/^[a-z][0-9a-z]*(?:[-.][0-9a-z]+)*/i)])), (0, combinator_1.union)([(0, combinator_1.constraint)(1 /* State.autolink */, false, (0, combinator_1.state)(1 /* State.autolink */, (0, combinator_1.fmap)((0, combinator_1.convert)(source => `[${source}]{ ${source.includes('/') ? `https://${source.slice(1).replace('/', '/@')}` : `/${source}`} }`, link_1.unsafelink, false), ([el]) => [(0, dom_1.define)(el, {
|
|
4407
4408
|
class: 'account'
|
|
4408
4409
|
})]))), ({
|
|
4409
4410
|
source
|
|
@@ -4709,7 +4710,7 @@ const dom_1 = __webpack_require__(394);
|
|
|
4709
4710
|
exports.segment = (0, combinator_1.block)((0, combinator_1.match)(/^(~{3,})(?:figure[^\S\n])?(?=\[?\$)/, (0, memoize_1.memoize)(([, fence], closer = new RegExp(String.raw`^${fence}[^\S\n]*(?:$|\n)`)) => (0, combinator_1.close)((0, combinator_1.sequence)([source_1.contentline, (0, combinator_1.inits)([
|
|
4710
4711
|
// All parsers which can include closing terms.
|
|
4711
4712
|
(0, combinator_1.union)([codeblock_1.segment_, mathblock_1.segment_, table_2.segment_, blockquote_1.segment, placeholder_1.segment_, (0, combinator_1.some)(source_1.contentline, closer)]), source_1.emptyline, (0, combinator_1.union)([source_1.emptyline, (0, combinator_1.some)(source_1.contentline, closer)])])]), closer), ([, fence]) => fence.length, {}), false));
|
|
4712
|
-
exports.figure = (0, combinator_1.block)((0, combinator_1.fallback)((0, combinator_1.rewrite)(exports.segment, (0, combinator_1.fmap)((0, combinator_1.convert)(source => source.slice(source.match(/^~+(?:\w+\s+)?/)[0].length, source.trimEnd().lastIndexOf('\n')), (0, combinator_1.sequence)([(0, combinator_1.line)((0, combinator_1.sequence)([label_1.label, (0, source_1.str)(/^(?=\s).*\n/)])), (0, combinator_1.inits)([(0, combinator_1.block)((0, combinator_1.union)([ulist_1.ulist, olist_1.olist, table_1.table, codeblock_1.codeblock, mathblock_1.mathblock, example_1.example, table_2.table, blockquote_1.blockquote, placeholder_1.placeholder, (0, combinator_1.line)(inline_1.media), (0, combinator_1.line)(inline_1.shortmedia)])), source_1.emptyline, (0, combinator_1.block)((0, visibility_1.visualize)((0, visibility_1.trimBlank)((0, combinator_1.some)(inline_1.inline))))])])), ([label, param, content, ...caption]) => [(0, dom_1.html)('figure', attributes(label.getAttribute('data-label'), param, content, caption), [(0, dom_1.html)('figcaption', [(0, dom_1.html)('span', {
|
|
4713
|
+
exports.figure = (0, combinator_1.block)((0, combinator_1.fallback)((0, combinator_1.rewrite)(exports.segment, (0, combinator_1.fmap)((0, combinator_1.convert)(source => source.slice(source.match(/^~+(?:\w+\s+)?/)[0].length, source.trimEnd().lastIndexOf('\n')), (0, combinator_1.sequence)([(0, combinator_1.line)((0, combinator_1.sequence)([label_1.label, (0, source_1.str)(/^(?=\s).*\n/)])), (0, combinator_1.inits)([(0, combinator_1.block)((0, combinator_1.union)([ulist_1.ulist, olist_1.olist, table_1.table, codeblock_1.codeblock, mathblock_1.mathblock, example_1.example, table_2.table, blockquote_1.blockquote, placeholder_1.placeholder, (0, combinator_1.line)(inline_1.media), (0, combinator_1.line)(inline_1.shortmedia)])), source_1.emptyline, (0, combinator_1.block)((0, visibility_1.visualize)((0, visibility_1.trimBlank)((0, combinator_1.some)(inline_1.inline))))])]), false), ([label, param, content, ...caption]) => [(0, dom_1.html)('figure', attributes(label.getAttribute('data-label'), param, content, caption), [(0, dom_1.html)('figcaption', [(0, dom_1.html)('span', {
|
|
4713
4714
|
class: 'figindex'
|
|
4714
4715
|
}), (0, dom_1.html)('span', {
|
|
4715
4716
|
class: 'figtext'
|
|
@@ -5030,7 +5031,7 @@ const source_1 = __webpack_require__(8745);
|
|
|
5030
5031
|
const dom_1 = __webpack_require__(394);
|
|
5031
5032
|
exports.template = (0, combinator_1.lazy)(() => (0, combinator_1.surround)('{{', (0, combinator_1.precedence)(1, (0, combinator_1.some)((0, combinator_1.union)([bracket, source_1.escsource]), '}', [['\n', 9]])), '}}', true, ([, ns = []], rest) => [[(0, dom_1.html)('span', {
|
|
5032
5033
|
class: 'template'
|
|
5033
|
-
}, `{{${ns.join('')}}}`)], rest], undefined, [3 | 16 /* Backtrack.linedoublebracket */, 1 | 4 /* Backtrack.lineescbracket */]
|
|
5034
|
+
}, `{{${ns.join('')}}}`)], rest], undefined, [3 | 16 /* Backtrack.linedoublebracket */, 1 | 4 /* Backtrack.lineescbracket */]));
|
|
5034
5035
|
const bracket = (0, combinator_1.lazy)(() => (0, combinator_1.union)([(0, combinator_1.surround)((0, source_1.str)('('), (0, combinator_1.recursion)(6 /* Recursion.terminal */, (0, combinator_1.some)((0, combinator_1.union)([bracket, source_1.escsource]), ')')), (0, source_1.str)(')'), true, undefined, () => [[], ''], [3 | 4 /* Backtrack.lineescbracket */]), (0, combinator_1.surround)((0, source_1.str)('['), (0, combinator_1.recursion)(6 /* Recursion.terminal */, (0, combinator_1.some)((0, combinator_1.union)([bracket, source_1.escsource]), ']')), (0, source_1.str)(']'), true, undefined, () => [[], ''], [3 | 4 /* Backtrack.lineescbracket */]), (0, combinator_1.surround)((0, source_1.str)('{'), (0, combinator_1.recursion)(6 /* Recursion.terminal */, (0, combinator_1.some)((0, combinator_1.union)([bracket, source_1.escsource]), '}')), (0, source_1.str)('}'), true, undefined, () => [[], ''], [3 | 4 /* Backtrack.lineescbracket */]), (0, combinator_1.surround)((0, source_1.str)('"'), (0, combinator_1.precedence)(2, (0, combinator_1.recursion)(6 /* Recursion.terminal */, (0, combinator_1.some)(source_1.escsource, '"'))), (0, source_1.str)('"'), true, undefined, () => [[], ''], [3 | 4 /* Backtrack.lineescbracket */])]));
|
|
5035
5036
|
|
|
5036
5037
|
/***/ },
|
|
@@ -5220,18 +5221,12 @@ const math_1 = __webpack_require__(2962);
|
|
|
5220
5221
|
const autolink_1 = __webpack_require__(8072);
|
|
5221
5222
|
const source_1 = __webpack_require__(8745);
|
|
5222
5223
|
const dom_1 = __webpack_require__(394);
|
|
5223
|
-
exports.syntax = /^>+
|
|
5224
|
-
exports.quote = (0, combinator_1.lazy)(() => (0, combinator_1.block)((0, combinator_1.fmap)((0, combinator_1.validate)('>', (0, combinator_1.
|
|
5224
|
+
exports.syntax = /^>+[^\S\n]/;
|
|
5225
|
+
exports.quote = (0, combinator_1.lazy)(() => (0, combinator_1.block)((0, combinator_1.fmap)((0, combinator_1.validate)('>', (0, combinator_1.rewrite)((0, combinator_1.some)((0, combinator_1.validate)(exports.syntax, source_1.anyline)), (0, combinator_1.convert)(source => source.replace(/\n$/, '').replace(/(?<=^>+[^\S\n])/mg, '\r'), (0, combinator_1.some)((0, combinator_1.union)([math_1.math,
|
|
5226
|
+
// quote補助関数が残した数式をパースする。他の構文で数式を残す場合はソーステキストを直接使用する。
|
|
5227
|
+
autolink_1.autolink, source_1.linebreak, source_1.unescsource])), false))), ns => [(0, dom_1.html)('span', {
|
|
5225
5228
|
class: 'quote'
|
|
5226
|
-
} : {
|
|
5227
|
-
class: 'quote invalid',
|
|
5228
|
-
'data-invalid-syntax': 'quote',
|
|
5229
|
-
'data-invalid-type': 'syntax',
|
|
5230
|
-
'data-invalid-message': `Missing the whitespace after "${ns[0].split(/[^>]/, 1)[0]}"`
|
|
5231
5229
|
}, (0, dom_1.defrag)(ns)), (0, dom_1.html)('br')]), false));
|
|
5232
|
-
const qblock = (0, combinator_1.convert)(source => source.replace(/\n$/, '').replace(/(?<=^>+[^\S\n])/mg, '\r'), (0, combinator_1.some)((0, combinator_1.union)([math_1.math,
|
|
5233
|
-
// quote補助関数が残した数式をパースする。他の構文で数式を残す場合はソーステキストを直接使用する。
|
|
5234
|
-
autolink_1.autolink, source_1.linebreak, source_1.unescsource])));
|
|
5235
5230
|
|
|
5236
5231
|
/***/ },
|
|
5237
5232
|
|
|
@@ -5283,8 +5278,8 @@ const alias_1 = __webpack_require__(5413);
|
|
|
5283
5278
|
const parser_1 = __webpack_require__(605);
|
|
5284
5279
|
const combinator_1 = __webpack_require__(3484);
|
|
5285
5280
|
const dom_1 = __webpack_require__(394);
|
|
5286
|
-
function lineable(parser) {
|
|
5287
|
-
return (0, combinator_1.convert)(source => `\r${source}`, parser);
|
|
5281
|
+
function lineable(parser, fillTrailingLinebreak = false) {
|
|
5282
|
+
return (0, combinator_1.convert)(source => `\r${source}${fillTrailingLinebreak && source.at(-1) !== '\n' ? '\n' : ''}`, parser, !fillTrailingLinebreak);
|
|
5288
5283
|
}
|
|
5289
5284
|
exports.lineable = lineable;
|
|
5290
5285
|
function repeat(symbol, parser, cons, termination = (acc, rest, prefix, postfix) => {
|
|
@@ -5926,7 +5921,7 @@ const dom_1 = __webpack_require__(394);
|
|
|
5926
5921
|
// https://example/hashtags/a must be a hashtag page or a redirect page going there.
|
|
5927
5922
|
// https://github.com/tc39/proposal-regexp-unicode-property-escapes#matching-emoji
|
|
5928
5923
|
exports.emoji = String.raw`\p{Emoji_Modifier_Base}\p{Emoji_Modifier}?|\p{Emoji_Presentation}|\p{Emoji}\uFE0F`;
|
|
5929
|
-
exports.hashtag = (0, combinator_1.lazy)(() => (0, combinator_1.rewrite)((0, combinator_1.open)('#', (0, source_1.str)(new RegExp([/^(?!['_])(?=(?:[0-9]{1,9})?(?:[^\d\p{C}\p{S}\p{P}\s]|emoji|'(?=[0-9A-Za-z])|_(?=[^'\p{C}\p{S}\p{P}\s]|emoji)))/u.source, /(?:[^\p{C}\p{S}\p{P}\s]|emoji|'(?=[0-9A-Za-z])|_(?=[^'\p{C}\p{S}\p{P}\s]|emoji))+/u.source].join('').replace(/emoji/g, exports.emoji), 'u'))), (0, combinator_1.union)([(0, combinator_1.constraint)(1 /* State.autolink */, false, (0, combinator_1.state)(1 /* State.autolink */, (0, combinator_1.fmap)((0, combinator_1.convert)(source => `[${source}]{ ${`/hashtags/${source.slice(1)}`} }`, link_1.unsafelink), ([el]) => [(0, dom_1.define)(el, {
|
|
5924
|
+
exports.hashtag = (0, combinator_1.lazy)(() => (0, combinator_1.rewrite)((0, combinator_1.open)('#', (0, source_1.str)(new RegExp([/^(?!['_])(?=(?:[0-9]{1,9})?(?:[^\d\p{C}\p{S}\p{P}\s]|emoji|'(?=[0-9A-Za-z])|_(?=[^'\p{C}\p{S}\p{P}\s]|emoji)))/u.source, /(?:[^\p{C}\p{S}\p{P}\s]|emoji|'(?=[0-9A-Za-z])|_(?=[^'\p{C}\p{S}\p{P}\s]|emoji))+/u.source].join('').replace(/emoji/g, exports.emoji), 'u'))), (0, combinator_1.union)([(0, combinator_1.constraint)(1 /* State.autolink */, false, (0, combinator_1.state)(1 /* State.autolink */, (0, combinator_1.fmap)((0, combinator_1.convert)(source => `[${source}]{ ${`/hashtags/${source.slice(1)}`} }`, link_1.unsafelink, false), ([el]) => [(0, dom_1.define)(el, {
|
|
5930
5925
|
class: 'hashtag'
|
|
5931
5926
|
})]))), ({
|
|
5932
5927
|
source
|
|
@@ -6098,8 +6093,8 @@ exports.blockquote = (0, combinator_1.lazy)(() => (0, combinator_1.block)((0, co
|
|
|
6098
6093
|
const opener = /^(?=>>+(?:$|\s))/;
|
|
6099
6094
|
const indent = (0, combinator_1.block)((0, combinator_1.open)(opener, (0, combinator_1.some)(source_1.contentline, /^>(?:$|\s)/)), false);
|
|
6100
6095
|
const unindent = source => source.replace(/(?<=^|\n)>(?:[^\S\n]|(?=>*(?:$|\s)))|\n$/g, '');
|
|
6101
|
-
const source = (0, combinator_1.lazy)(() => (0, combinator_1.fmap)((0, combinator_1.some)((0, combinator_1.recursion)(2 /* Recursion.blockquote */, (0, combinator_1.union)([(0, combinator_1.rewrite)(indent, (0, combinator_1.convert)(unindent, source, true)), (0, combinator_1.rewrite)((0, combinator_1.some)(source_1.contentline, opener), (0, combinator_1.convert)(unindent, (0, combinator_1.fmap)(autolink_1.autolink, ns => [(0, dom_1.html)('pre', (0, dom_1.defrag)(ns))]), true))]))), ns => [(0, dom_1.html)('blockquote', ns)]));
|
|
6102
|
-
const markdown = (0, combinator_1.lazy)(() => (0, combinator_1.fmap)((0, combinator_1.some)((0, combinator_1.recursion)(2 /* Recursion.blockquote */, (0, combinator_1.union)([(0, combinator_1.rewrite)(indent, (0, combinator_1.convert)(unindent, markdown, true)), (0, combinator_1.creation)(10, (0, combinator_1.rewrite)((0, combinator_1.some)(source_1.contentline, opener), (0, combinator_1.convert)(unindent, ({
|
|
6096
|
+
const source = (0, combinator_1.lazy)(() => (0, combinator_1.fmap)((0, combinator_1.some)((0, combinator_1.recursion)(2 /* Recursion.blockquote */, (0, combinator_1.union)([(0, combinator_1.rewrite)(indent, (0, combinator_1.convert)(unindent, source, false, true)), (0, combinator_1.rewrite)((0, combinator_1.some)(source_1.contentline, opener), (0, combinator_1.convert)(unindent, (0, combinator_1.fmap)(autolink_1.autolink, ns => [(0, dom_1.html)('pre', (0, dom_1.defrag)(ns))]), false, true))]))), ns => [(0, dom_1.html)('blockquote', ns)]));
|
|
6097
|
+
const markdown = (0, combinator_1.lazy)(() => (0, combinator_1.fmap)((0, combinator_1.some)((0, combinator_1.recursion)(2 /* Recursion.blockquote */, (0, combinator_1.union)([(0, combinator_1.rewrite)(indent, (0, combinator_1.convert)(unindent, markdown, false, true)), (0, combinator_1.creation)(10, (0, combinator_1.rewrite)((0, combinator_1.some)(source_1.contentline, opener), (0, combinator_1.convert)(unindent, ({
|
|
6103
6098
|
source,
|
|
6104
6099
|
context
|
|
6105
6100
|
}) => {
|
|
@@ -6113,7 +6108,7 @@ const markdown = (0, combinator_1.lazy)(() => (0, combinator_1.fmap)((0, combina
|
|
|
6113
6108
|
}
|
|
6114
6109
|
}, context);
|
|
6115
6110
|
return [[(0, dom_1.html)('section', [document, (0, dom_1.html)('h2', 'References'), references])], ''];
|
|
6116
|
-
}, true)))]))), ns => [(0, dom_1.html)('blockquote', ns)]));
|
|
6111
|
+
}, false, true)))]))), ns => [(0, dom_1.html)('blockquote', ns)]));
|
|
6117
6112
|
|
|
6118
6113
|
/***/ },
|
|
6119
6114
|
|
|
@@ -6192,8 +6187,8 @@ const combinator_1 = __webpack_require__(3484);
|
|
|
6192
6187
|
const url_1 = __webpack_require__(2129);
|
|
6193
6188
|
const media_1 = __webpack_require__(7478);
|
|
6194
6189
|
const source_1 = __webpack_require__(8745);
|
|
6195
|
-
exports.shortmedia = (0, combinator_1.constraint)(4 /* State.media */, false, (0, combinator_1.rewrite)((0, combinator_1.open)('!', url_1.url), (0, combinator_1.convert)(source => `!{ ${source.slice(1)} }`, (0, combinator_1.union)([media_1.media]))));
|
|
6196
|
-
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]))));
|
|
6190
|
+
exports.shortmedia = (0, combinator_1.constraint)(4 /* State.media */, false, (0, combinator_1.rewrite)((0, combinator_1.open)('!', url_1.url), (0, combinator_1.convert)(source => `!{ ${source.slice(1)} }`, (0, combinator_1.union)([media_1.media]), false)));
|
|
6191
|
+
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]), false)));
|
|
6197
6192
|
|
|
6198
6193
|
/***/ },
|
|
6199
6194
|
|
|
@@ -6352,7 +6347,7 @@ var blank;
|
|
|
6352
6347
|
blank.start = new RegExp(/^(?:\\?[^\S\r\n]|&IHN;|<wbr[^\S\n]*>)+/.source.replace('IHN', `(?:${normalize_1.invisibleHTMLEntityNames.join('|')})`));
|
|
6353
6348
|
})(blank || (exports.blank = blank = {}));
|
|
6354
6349
|
function visualize(parser) {
|
|
6355
|
-
return (0, combinator_1.union)([(0, combinator_1.convert)(source => source.replace(blank.line, line => line.replace(/[\\&<]/g, `${"\u001B" /* Command.Escape */}$&`)), (0, combinator_1.verify)(parser, (ns, rest) => !rest && hasVisible(ns))), (0, combinator_1.some)((0, combinator_1.union)([source_1.linebreak, source_1.unescsource]))]);
|
|
6350
|
+
return (0, combinator_1.union)([(0, combinator_1.convert)(source => source.replace(blank.line, line => line.replace(/[\\&<]/g, `${"\u001B" /* Command.Escape */}$&`)), (0, combinator_1.verify)(parser, (ns, rest) => !rest && hasVisible(ns)), false), (0, combinator_1.some)((0, combinator_1.union)([source_1.linebreak, source_1.unescsource]))]);
|
|
6356
6351
|
}
|
|
6357
6352
|
exports.visualize = visualize;
|
|
6358
6353
|
function hasVisible(nodes) {
|
|
@@ -6458,7 +6453,7 @@ function trimBlank(parser) {
|
|
|
6458
6453
|
}
|
|
6459
6454
|
exports.trimBlank = trimBlank;
|
|
6460
6455
|
function trimBlankStart(parser) {
|
|
6461
|
-
return (0, combinator_1.convert)(source => source.replace(blank.start, ''), parser);
|
|
6456
|
+
return (0, combinator_1.convert)(source => source.replace(blank.start, ''), parser, true);
|
|
6462
6457
|
}
|
|
6463
6458
|
exports.trimBlankStart = trimBlankStart;
|
|
6464
6459
|
function trimBlankEnd(parser) {
|
|
@@ -6524,7 +6519,7 @@ exports.sidefence = (0, combinator_1.lazy)(() => (0, combinator_1.block)((0, com
|
|
|
6524
6519
|
})])));
|
|
6525
6520
|
const opener = /^(?=\|\|+(?:$|\s))/;
|
|
6526
6521
|
const unindent = source => source.replace(/(?<=^|\n)\|(?:[^\S\n]|(?=\|*(?:$|\s)))|\n$/g, '');
|
|
6527
|
-
const source = (0, combinator_1.lazy)(() => (0, combinator_1.fmap)((0, combinator_1.some)((0, combinator_1.recursion)(1 /* Recursion.block */, (0, combinator_1.union)([(0, combinator_1.focus)(/^(?:\|\|+(?:[^\S\n][^\n]*)?(?:$|\n))+/, (0, combinator_1.convert)(unindent, source, true), false), (0, combinator_1.rewrite)((0, combinator_1.some)(source_1.contentline, opener), (0, combinator_1.convert)(unindent, (0, combinator_1.fmap)(autolink_1.autolink, ns => [(0, dom_1.html)('pre', (0, dom_1.defrag)(ns))]), true))]))), ns => [(0, dom_1.html)('blockquote', ns)]));
|
|
6522
|
+
const source = (0, combinator_1.lazy)(() => (0, combinator_1.fmap)((0, combinator_1.some)((0, combinator_1.recursion)(1 /* Recursion.block */, (0, combinator_1.union)([(0, combinator_1.focus)(/^(?:\|\|+(?:[^\S\n][^\n]*)?(?:$|\n))+/, (0, combinator_1.convert)(unindent, source, false, true), false), (0, combinator_1.rewrite)((0, combinator_1.some)(source_1.contentline, opener), (0, combinator_1.convert)(unindent, (0, combinator_1.fmap)(autolink_1.autolink, ns => [(0, dom_1.html)('pre', (0, dom_1.defrag)(ns))]), false, true))]))), ns => [(0, dom_1.html)('blockquote', ns)]));
|
|
6528
6523
|
|
|
6529
6524
|
/***/ },
|
|
6530
6525
|
|
|
@@ -6539,7 +6534,7 @@ Object.defineProperty(exports, "__esModule", ({
|
|
|
6539
6534
|
}));
|
|
6540
6535
|
exports.convert = void 0;
|
|
6541
6536
|
const parser_1 = __webpack_require__(605);
|
|
6542
|
-
function convert(conv, parser, empty = false) {
|
|
6537
|
+
function convert(conv, parser, continuous, empty = false) {
|
|
6543
6538
|
return ({
|
|
6544
6539
|
source,
|
|
6545
6540
|
context
|
|
@@ -6547,11 +6542,10 @@ function convert(conv, parser, empty = false) {
|
|
|
6547
6542
|
if (source === '') return;
|
|
6548
6543
|
const src = conv(source, context);
|
|
6549
6544
|
if (src === '') return empty ? [[], ''] : undefined;
|
|
6550
|
-
const sub = source.endsWith(src);
|
|
6551
6545
|
const {
|
|
6552
6546
|
backtracks
|
|
6553
6547
|
} = context;
|
|
6554
|
-
context.backtracks =
|
|
6548
|
+
context.backtracks = continuous ? backtracks : {};
|
|
6555
6549
|
const result = parser({
|
|
6556
6550
|
source: src,
|
|
6557
6551
|
context
|
|
@@ -7267,7 +7261,7 @@ exports.fig = (0, combinator_1.block)((0, combinator_1.rewrite)(exports.segment,
|
|
|
7267
7261
|
source,
|
|
7268
7262
|
context
|
|
7269
7263
|
}) ? `${fence}figure ${source.replace(/^(.+\n.+\n)([\S\s]+?)\n?$/, '$1\n$2')}\n${fence}` : `${fence}figure ${source}\n\n${fence}`;
|
|
7270
|
-
}, (0, combinator_1.union)([figure_1.figure])), ([el]) => el.tagName === 'FIGURE')));
|
|
7264
|
+
}, (0, combinator_1.union)([figure_1.figure]), false), ([el]) => el.tagName === 'FIGURE')));
|
|
7271
7265
|
const parser = (0, combinator_1.sequence)([(0, combinator_1.line)((0, combinator_1.close)(label_1.segment, /^(?=\s).*\n/)), (0, combinator_1.line)((0, combinator_1.union)([inline_1.media, inline_1.shortmedia])), (0, combinator_1.some)(source_1.contentline)]);
|
|
7272
7266
|
|
|
7273
7267
|
/***/ },
|
|
@@ -8379,7 +8373,7 @@ const dom_1 = __webpack_require__(394);
|
|
|
8379
8373
|
// cid: YYYY-MMDD-HHMM-SSmmm
|
|
8380
8374
|
// 内部表現はUnixTimeに統一する(時系列順)
|
|
8381
8375
|
// 外部表現は投稿ごとに投稿者の投稿時のタイムゾーンに統一する(非時系列順)
|
|
8382
|
-
exports.anchor = (0, combinator_1.lazy)(() => (0, combinator_1.validate)('>>', (0, combinator_1.focus)(/^>>(?:[a-z][0-9a-z]*(?:-[0-9a-z]+)*\/)?[0-9a-z]+(?:-[0-9a-z]+)*(?![0-9a-z@#:])/i, (0, combinator_1.union)([(0, combinator_1.constraint)(1 /* State.autolink */, false, (0, combinator_1.state)(1 /* State.autolink */, (0, combinator_1.fmap)((0, combinator_1.convert)(source => `[${source}]{ ${source.includes('/') ? `/@${source.slice(2).replace('/', '/timeline?at=')}` : `?at=${source.slice(2)}`} }`, link_1.unsafelink), ([el]) => [(0, dom_1.define)(el, {
|
|
8376
|
+
exports.anchor = (0, combinator_1.lazy)(() => (0, combinator_1.validate)('>>', (0, combinator_1.focus)(/^>>(?:[a-z][0-9a-z]*(?:-[0-9a-z]+)*\/)?[0-9a-z]+(?:-[0-9a-z]+)*(?![0-9a-z@#:])/i, (0, combinator_1.union)([(0, combinator_1.constraint)(1 /* State.autolink */, false, (0, combinator_1.state)(1 /* State.autolink */, (0, combinator_1.fmap)((0, combinator_1.convert)(source => `[${source}]{ ${source.includes('/') ? `/@${source.slice(2).replace('/', '/timeline?at=')}` : `?at=${source.slice(2)}`} }`, link_1.unsafelink, false), ([el]) => [(0, dom_1.define)(el, {
|
|
8383
8377
|
class: 'anchor'
|
|
8384
8378
|
})]))), ({
|
|
8385
8379
|
source
|
|
@@ -8687,7 +8681,7 @@ const link_1 = __webpack_require__(3628);
|
|
|
8687
8681
|
const hashtag_1 = __webpack_require__(5764);
|
|
8688
8682
|
const source_1 = __webpack_require__(8745);
|
|
8689
8683
|
const dom_1 = __webpack_require__(394);
|
|
8690
|
-
exports.hashnum = (0, combinator_1.lazy)(() => (0, combinator_1.rewrite)((0, combinator_1.open)('#', (0, source_1.str)(new RegExp(/^[0-9]{1,9}(?![^\p{C}\p{S}\p{P}\s]|emoji)/u.source.replace(/emoji/, hashtag_1.emoji), 'u'))), (0, combinator_1.union)([(0, combinator_1.constraint)(1 /* State.autolink */, false, (0, combinator_1.state)(1 /* State.autolink */, (0, combinator_1.fmap)((0, combinator_1.convert)(source => `[${source}]{ ${source.slice(1)} }`, link_1.unsafelink), ([el]) => [(0, dom_1.define)(el, {
|
|
8684
|
+
exports.hashnum = (0, combinator_1.lazy)(() => (0, combinator_1.rewrite)((0, combinator_1.open)('#', (0, source_1.str)(new RegExp(/^[0-9]{1,9}(?![^\p{C}\p{S}\p{P}\s]|emoji)/u.source.replace(/emoji/, hashtag_1.emoji), 'u'))), (0, combinator_1.union)([(0, combinator_1.constraint)(1 /* State.autolink */, false, (0, combinator_1.state)(1 /* State.autolink */, (0, combinator_1.fmap)((0, combinator_1.convert)(source => `[${source}]{ ${source.slice(1)} }`, link_1.unsafelink, false), ([el]) => [(0, dom_1.define)(el, {
|
|
8691
8685
|
class: 'hashnum',
|
|
8692
8686
|
href: null
|
|
8693
8687
|
})]))), ({
|
package/markdown.d.ts
CHANGED
|
@@ -587,53 +587,30 @@ export namespace MarkdownParser {
|
|
|
587
587
|
// abc
|
|
588
588
|
Block<'reply'>,
|
|
589
589
|
Parser<HTMLParagraphElement, Context, [
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
]>,
|
|
594
|
-
Parser<HTMLElement | string, Context, [
|
|
595
|
-
ReplyParser.QuoteParser,
|
|
596
|
-
InlineParser,
|
|
597
|
-
]>,
|
|
590
|
+
ReplyParser.CiteParser,
|
|
591
|
+
ReplyParser.QuoteParser,
|
|
592
|
+
InlineParser,
|
|
598
593
|
]> {
|
|
599
594
|
}
|
|
600
595
|
export namespace ReplyParser {
|
|
601
596
|
export interface CiteParser extends
|
|
602
597
|
Block<'reply/cite'>,
|
|
603
598
|
Parser<HTMLSpanElement | HTMLBRElement, Context, [
|
|
604
|
-
|
|
605
|
-
Parser<
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
Parser<HTMLAnchorElement, Context, []>,
|
|
609
|
-
Parser<HTMLAnchorElement, Context, []>,
|
|
610
|
-
]>,
|
|
599
|
+
InlineParser.AutolinkParser.AnchorParser,
|
|
600
|
+
Parser<HTMLAnchorElement, Context, []>,
|
|
601
|
+
Parser<HTMLAnchorElement, Context, []>,
|
|
602
|
+
Parser<string, Context, []>,
|
|
611
603
|
]> {
|
|
612
604
|
}
|
|
613
605
|
export interface QuoteParser extends
|
|
614
606
|
Block<'reply/quote'>,
|
|
615
607
|
Parser<HTMLSpanElement | HTMLBRElement, Context, [
|
|
616
|
-
|
|
617
|
-
|
|
608
|
+
InlineParser.MathParser,
|
|
609
|
+
InlineParser.AutolinkParser,
|
|
610
|
+
SourceParser.LinebreakParser,
|
|
611
|
+
SourceParser.UnescapableSourceParser,
|
|
618
612
|
]> {
|
|
619
613
|
}
|
|
620
|
-
export namespace QuoteParser {
|
|
621
|
-
export interface BlockParser extends
|
|
622
|
-
Block<'reply/quote/block'>,
|
|
623
|
-
Parser<string | HTMLElement, Context, [
|
|
624
|
-
InlineParser.MathParser,
|
|
625
|
-
InlineParser.AutolinkParser,
|
|
626
|
-
SourceParser.LinebreakParser,
|
|
627
|
-
SourceParser.UnescapableSourceParser,
|
|
628
|
-
]> {
|
|
629
|
-
}
|
|
630
|
-
export interface PlaceholderParser extends
|
|
631
|
-
Block<'reply/quote/placeholder'>,
|
|
632
|
-
Parser<string | HTMLElement, Context, [
|
|
633
|
-
SourceParser.StrParser,
|
|
634
|
-
]> {
|
|
635
|
-
}
|
|
636
|
-
}
|
|
637
614
|
}
|
|
638
615
|
export interface ParagraphParser extends
|
|
639
616
|
// abc
|
package/package.json
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { Parser, Ctx, Context, check } from '../../data/parser';
|
|
2
2
|
|
|
3
|
-
export function convert<P extends Parser<unknown>>(conv: (source: string, context: Context<P>) => string, parser: P, empty?: boolean): P;
|
|
4
|
-
export function convert<T>(conv: (source: string, context: Ctx) => string, parser: Parser<T>, empty = false): Parser<T> {
|
|
3
|
+
export function convert<P extends Parser<unknown>>(conv: (source: string, context: Context<P>) => string, parser: P, continuous: boolean, empty?: boolean): P;
|
|
4
|
+
export function convert<T>(conv: (source: string, context: Ctx) => string, parser: Parser<T>, continuous: boolean, empty = false): Parser<T> {
|
|
5
5
|
assert(parser);
|
|
6
6
|
return ({ source, context }) => {
|
|
7
7
|
if (source === '') return;
|
|
8
8
|
const src = conv(source, context);
|
|
9
9
|
if (src === '') return empty ? [[], ''] : undefined;
|
|
10
|
-
const sub = source.endsWith(src);
|
|
11
10
|
const { backtracks } = context;
|
|
12
|
-
|
|
11
|
+
assert(source.endsWith(src) || src.endsWith(source) || !continuous);
|
|
12
|
+
context.backtracks = continuous ? backtracks : {};
|
|
13
13
|
const result = parser({ source: src, context });
|
|
14
14
|
assert(check(src, result));
|
|
15
15
|
context.backtracks = backtracks;
|
|
@@ -3,15 +3,15 @@ import { convert } from './convert';
|
|
|
3
3
|
|
|
4
4
|
export function trim<P extends Parser<unknown>>(parser: P): P;
|
|
5
5
|
export function trim<T>(parser: Parser<T>): Parser<T> {
|
|
6
|
-
return convert(source => source.trim(), parser);
|
|
6
|
+
return convert(source => source.trim(), parser, false);
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
export function trimStart<P extends Parser<unknown>>(parser: P): P;
|
|
10
10
|
export function trimStart<T>(parser: Parser<T>): Parser<T> {
|
|
11
|
-
return convert(source => source.trimStart(), parser);
|
|
11
|
+
return convert(source => source.trimStart(), parser, true);
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
export function trimEnd<P extends Parser<unknown>>(parser: P): P;
|
|
15
15
|
export function trimEnd<T>(parser: Parser<T>): Parser<T> {
|
|
16
|
-
return convert(source => source.trimEnd(), parser);
|
|
16
|
+
return convert(source => source.trimEnd(), parser, false);
|
|
17
17
|
}
|
|
@@ -6,8 +6,10 @@ describe('Unit: parser/autolink', () => {
|
|
|
6
6
|
const parser = (source: string) => autolink({ source, context: {} });
|
|
7
7
|
|
|
8
8
|
it('basic', () => {
|
|
9
|
-
assert.deepStrictEqual(inspect(parser('http://host
|
|
10
|
-
assert.deepStrictEqual(inspect(parser('
|
|
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
|
+
assert.deepStrictEqual(inspect(parser('!http://host)')), [['!', '<a class="url" href="http://host)" target="_blank">http://host)</a>'], '']);
|
|
12
|
+
assert.deepStrictEqual(inspect(parser('!http://host\\')), [['!', '<a class="url" href="http://host\\" target="_blank">http://host\\</a>'], '']);
|
|
11
13
|
assert.deepStrictEqual(inspect(parser('#a')), [['<a class="hashtag" href="/hashtags/a">#a</a>'], '']);
|
|
12
14
|
assert.deepStrictEqual(inspect(parser('@a#b')), [['<a class="channel" href="/@a?ch=b">@a#b</a>'], '']);
|
|
13
15
|
assert.deepStrictEqual(inspect(parser('\\\n')), [['\\', '<br>'], '']);
|
package/src/parser/autolink.ts
CHANGED
|
@@ -41,7 +41,9 @@ describe('Unit: parser/block/blockquote', () => {
|
|
|
41
41
|
assert.deepStrictEqual(inspect(parser('>\n>')), [['<blockquote><pre><br></pre></blockquote>'], '']);
|
|
42
42
|
assert.deepStrictEqual(inspect(parser('>\n> a')), [['<blockquote><pre><br>a</pre></blockquote>'], '']);
|
|
43
43
|
assert.deepStrictEqual(inspect(parser('> http://host')), [['<blockquote><pre><a class="url" href="http://host" target="_blank">http://host</a></pre></blockquote>'], '']);
|
|
44
|
+
assert.deepStrictEqual(inspect(parser('> http://host)')), [['<blockquote><pre><a class="url" href="http://host)" target="_blank">http://host)</a></pre></blockquote>'], '']);
|
|
44
45
|
assert.deepStrictEqual(inspect(parser('> !http://host')), [['<blockquote><pre>!<a class="url" href="http://host" target="_blank">http://host</a></pre></blockquote>'], '']);
|
|
46
|
+
assert.deepStrictEqual(inspect(parser('> !http://host)')), [['<blockquote><pre>!<a class="url" href="http://host)" target="_blank">http://host)</a></pre></blockquote>'], '']);
|
|
45
47
|
assert.deepStrictEqual(inspect(parser('> #a')), [['<blockquote><pre><a class="hashtag" href="/hashtags/a">#a</a></pre></blockquote>'], '']);
|
|
46
48
|
assert.deepStrictEqual(inspect(parser('> @a#b')), [['<blockquote><pre><a class="channel" href="/@a?ch=b">@a#b</a></pre></blockquote>'], '']);
|
|
47
49
|
assert.deepStrictEqual(inspect(parser('> >>1\n> > b')), [['<blockquote><pre><a class="anchor" href="?at=1">>>1</a><br>> b</pre></blockquote>'], '']);
|
|
@@ -23,10 +23,10 @@ const source: BlockquoteParser.SourceParser = lazy(() => fmap(
|
|
|
23
23
|
some(recursion(Recursion.blockquote, union([
|
|
24
24
|
rewrite(
|
|
25
25
|
indent,
|
|
26
|
-
convert(unindent, source, true)),
|
|
26
|
+
convert(unindent, source, false, true)),
|
|
27
27
|
rewrite(
|
|
28
28
|
some(contentline, opener),
|
|
29
|
-
convert(unindent, fmap(autolink, ns => [html('pre', defrag(ns))]), true)),
|
|
29
|
+
convert(unindent, fmap(autolink, ns => [html('pre', defrag(ns))]), false, true)),
|
|
30
30
|
]))),
|
|
31
31
|
ns => [html('blockquote', ns)]));
|
|
32
32
|
|
|
@@ -34,7 +34,7 @@ const markdown: BlockquoteParser.MarkdownParser = lazy(() => fmap(
|
|
|
34
34
|
some(recursion(Recursion.blockquote, union([
|
|
35
35
|
rewrite(
|
|
36
36
|
indent,
|
|
37
|
-
convert(unindent, markdown, true)),
|
|
37
|
+
convert(unindent, markdown, false, true)),
|
|
38
38
|
creation(10,
|
|
39
39
|
rewrite(
|
|
40
40
|
some(contentline, opener),
|
|
@@ -47,6 +47,6 @@ const markdown: BlockquoteParser.MarkdownParser = lazy(() => fmap(
|
|
|
47
47
|
},
|
|
48
48
|
}, context);
|
|
49
49
|
return [[html('section', [document, html('h2', 'References'), references])], ''];
|
|
50
|
-
}, true))),
|
|
50
|
+
}, false, true))),
|
|
51
51
|
]))),
|
|
52
52
|
ns => [html('blockquote', ns)]));
|
|
@@ -38,7 +38,9 @@ describe('Unit: parser/block/codeblock', () => {
|
|
|
38
38
|
assert.deepStrictEqual(inspect(parser('````\n```\n\n````')), [['<pre class="text">```<br></pre>'], '']);
|
|
39
39
|
assert.deepStrictEqual(inspect(parser('```\n\n```\n')), [['<pre class="text"></pre>'], '']);
|
|
40
40
|
assert.deepStrictEqual(inspect(parser('```\nhttp://host\n```')), [['<pre class="text"><a class="url" href="http://host" target="_blank">http://host</a></pre>'], '']);
|
|
41
|
+
assert.deepStrictEqual(inspect(parser('```\nhttp://host)\n```')), [['<pre class="text"><a class="url" href="http://host)" target="_blank">http://host)</a></pre>'], '']);
|
|
41
42
|
assert.deepStrictEqual(inspect(parser('```\n!http://host\n```')), [['<pre class="text">!<a class="url" href="http://host" target="_blank">http://host</a></pre>'], '']);
|
|
43
|
+
assert.deepStrictEqual(inspect(parser('```\n!http://host)\n```')), [['<pre class="text">!<a class="url" href="http://host)" target="_blank">http://host)</a></pre>'], '']);
|
|
42
44
|
assert.deepStrictEqual(inspect(parser('```\n#a\n```')), [['<pre class="text"><a class="hashtag" href="/hashtags/a">#a</a></pre>'], '']);
|
|
43
45
|
assert.deepStrictEqual(inspect(parser('```\n@a#b\n```')), [['<pre class="text"><a class="channel" href="/@a?ch=b">@a#b</a></pre>'], '']);
|
|
44
46
|
assert.deepStrictEqual(inspect(parser(`\`\`\`\n0${'\n'.repeat(300)}\`\`\``), '>'), [['<pre class="text">'], '']);
|
|
@@ -34,7 +34,8 @@ export const fig: FigParser = block(rewrite(segment, verify(convert(
|
|
|
34
34
|
? `${fence}figure ${source.replace(/^(.+\n.+\n)([\S\s]+?)\n?$/, '$1\n$2')}\n${fence}`
|
|
35
35
|
: `${fence}figure ${source}\n\n${fence}`;
|
|
36
36
|
},
|
|
37
|
-
union([figure])
|
|
37
|
+
union([figure]),
|
|
38
|
+
false),
|
|
38
39
|
([el]) => el.tagName === 'FIGURE')));
|
|
39
40
|
|
|
40
41
|
const parser = sequence([
|
|
@@ -65,7 +65,7 @@ export const figure: FigureParser = block(fallback(rewrite(segment, fmap(
|
|
|
65
65
|
emptyline,
|
|
66
66
|
block(visualize(trimBlank(some(inline)))),
|
|
67
67
|
]),
|
|
68
|
-
])),
|
|
68
|
+
]), false),
|
|
69
69
|
([label, param, content, ...caption]: [HTMLAnchorElement, string, ...HTMLElement[]]) => [
|
|
70
70
|
html('figure',
|
|
71
71
|
attributes(label.getAttribute('data-label')!, param, content, caption),
|
|
@@ -116,8 +116,8 @@ const dataline: CellParser.DatalineParser = line(
|
|
|
116
116
|
rewrite(
|
|
117
117
|
contentline,
|
|
118
118
|
union([
|
|
119
|
-
validate(/^!+\s/, convert(source => `:${source}`, data)),
|
|
120
|
-
convert(source => `: ${source}`, data),
|
|
119
|
+
validate(/^!+\s/, convert(source => `:${source}`, data, true)),
|
|
120
|
+
convert(source => `: ${source}`, data, true),
|
|
121
121
|
])));
|
|
122
122
|
|
|
123
123
|
function attributes(source: string): Record<string, string | undefined> {
|
|
@@ -33,11 +33,10 @@ describe('Unit: parser/block/paragraph', () => {
|
|
|
33
33
|
assert.deepStrictEqual(inspect(parser('***a*b\n<wbr>**\nc')), [['<p>**<em>a</em>b<br><wbr>**<br>c</p>'], '']);
|
|
34
34
|
assert.deepStrictEqual(inspect(parser('***a**b\n<wbr>*\nc')), [['<p>*<strong>a</strong>b<br><wbr>*<br>c</p>'], '']);
|
|
35
35
|
assert.deepStrictEqual(inspect(parser('==a\n<wbr>==\nb')), [['<p>==a<br><wbr>==<br>b</p>'], '']);
|
|
36
|
-
assert.deepStrictEqual(inspect(parser('http://host
|
|
37
|
-
assert.deepStrictEqual(inspect(parser('a\nhttp://host
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
//assert.deepStrictEqual(inspect(parser(' !http://host#\\')), [['<p> !<a class="url" href="http://host#" target="_blank">http://host#</a></p>'], '']);
|
|
36
|
+
assert.deepStrictEqual(inspect(parser('http://host)')), [['<p><a class="url" href="http://host)" target="_blank">http://host)</a></p>'], '']);
|
|
37
|
+
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>'], '']);
|
|
38
|
+
assert.deepStrictEqual(inspect(parser('!http://host)')), [['<p>!<a class="url" href="http://host)" target="_blank">http://host)</a></p>'], '']);
|
|
39
|
+
assert.deepStrictEqual(inspect(parser('a\n!http://host) \nb')), [['<p>a<br>!<a class="url" href="http://host)" target="_blank">http://host)</a><br>b</p>'], '']);
|
|
41
40
|
assert.deepStrictEqual(inspect(parser('\ta')), [['<p>\ta</p>'], '']);
|
|
42
41
|
});
|
|
43
42
|
|
|
@@ -14,13 +14,12 @@ describe('Unit: parser/block/reply/cite', () => {
|
|
|
14
14
|
assert.deepStrictEqual(inspect(parser('>>')), undefined);
|
|
15
15
|
assert.deepStrictEqual(inspect(parser('>> ')), undefined);
|
|
16
16
|
assert.deepStrictEqual(inspect(parser('>>0 a')), undefined);
|
|
17
|
-
assert.deepStrictEqual(inspect(parser('>>/')),
|
|
18
|
-
assert.deepStrictEqual(inspect(parser('>>\\')),
|
|
19
|
-
assert.deepStrictEqual(inspect(parser('>>01#')),
|
|
20
|
-
assert.deepStrictEqual(inspect(parser('>>01@')),
|
|
21
|
-
assert.deepStrictEqual(inspect(parser('>>http://')),
|
|
22
|
-
assert.deepStrictEqual(inspect(parser('>>tel:1234567890')),
|
|
23
|
-
assert.deepStrictEqual(inspect(parser('>>..')), undefined);
|
|
17
|
+
assert.deepStrictEqual(inspect(parser('>>/')), [['<span class="cite invalid">>>/</span>', '<br>'], '']);
|
|
18
|
+
assert.deepStrictEqual(inspect(parser('>>\\')), [['<span class="cite invalid">>>\\</span>', '<br>'], '']);
|
|
19
|
+
assert.deepStrictEqual(inspect(parser('>>01#')), [['<span class="cite invalid">>>01#</span>', '<br>'], '']);
|
|
20
|
+
assert.deepStrictEqual(inspect(parser('>>01@')), [['<span class="cite invalid">>>01@</span>', '<br>'], '']);
|
|
21
|
+
assert.deepStrictEqual(inspect(parser('>>http://')), [['<span class="cite invalid">>>http://</span>', '<br>'], '']);
|
|
22
|
+
assert.deepStrictEqual(inspect(parser('>>tel:1234567890')), [['<span class="cite invalid">>>tel:1234567890</span>', '<br>'], '']);
|
|
24
23
|
assert.deepStrictEqual(inspect(parser('>> 0')), undefined);
|
|
25
24
|
assert.deepStrictEqual(inspect(parser(' >>0')), undefined);
|
|
26
25
|
assert.deepStrictEqual(inspect(parser('\\>>0')), undefined);
|
|
@@ -38,15 +37,14 @@ describe('Unit: parser/block/reply/cite', () => {
|
|
|
38
37
|
assert.deepStrictEqual(inspect(parser('>>0\n>>>1')), [['<span class="cite">><a class="anchor" href="?at=0" data-depth="1">>0</a></span>', '<br>', '<span class="cite">>><a class="anchor" href="?at=1" data-depth="2">>1</a></span>', '<br>'], '']);
|
|
39
38
|
assert.deepStrictEqual(inspect(parser('>>>0\n>>')), [['<span class="cite">>><a class="anchor" href="?at=0" data-depth="2">>0</a></span>', '<br>'], '>>']);
|
|
40
39
|
assert.deepStrictEqual(inspect(parser('>>>0\n>>1')), [['<span class="cite">>><a class="anchor" href="?at=0" data-depth="2">>0</a></span>', '<br>', '<span class="cite">><a class="anchor" href="?at=1" data-depth="1">>1</a></span>', '<br>'], '']);
|
|
41
|
-
assert.deepStrictEqual(inspect(parser('>>.')), [['<span class="cite">><a class="anchor" data-depth="1">>.</a></span>', '<br>'], '']);
|
|
42
|
-
assert.deepStrictEqual(inspect(parser('>>. ')), [['<span class="cite">><a class="anchor" data-depth="1">>.</a></span>', '<br>'], '']);
|
|
43
|
-
assert.deepStrictEqual(inspect(parser('>>.\n')), [['<span class="cite">><a class="anchor" data-depth="1">>.</a></span>', '<br>'], '']);
|
|
44
40
|
assert.deepStrictEqual(inspect(parser('>>#')), [['<span class="cite">><a class="anchor" data-depth="1">>#</a></span>', '<br>'], '']);
|
|
41
|
+
assert.deepStrictEqual(inspect(parser('>># ')), [['<span class="cite">><a class="anchor" data-depth="1">>#</a></span>', '<br>'], '']);
|
|
45
42
|
assert.deepStrictEqual(inspect(parser('>>#\n')), [['<span class="cite">><a class="anchor" data-depth="1">>#</a></span>', '<br>'], '']);
|
|
46
43
|
assert.deepStrictEqual(inspect(parser('>>#a')), [['<span class="cite">><a class="anchor" data-depth="1">>#a</a></span>', '<br>'], '']);
|
|
47
44
|
assert.deepStrictEqual(inspect(parser('>>#index::a')), [['<span class="cite">><a class="anchor" data-depth="1">>#index::a</a></span>', '<br>'], '']);
|
|
48
45
|
assert.deepStrictEqual(inspect(parser('>>#:~:text=a')), [['<span class="cite">><a class="anchor" data-depth="1">>#:~:text=a</a></span>', '<br>'], '']);
|
|
49
46
|
assert.deepStrictEqual(inspect(parser('>>http://host')), [['<span class="cite">><a class="anchor" href="http://host" target="_blank" data-depth="1">>http://host</a></span>', '<br>'], '']);
|
|
47
|
+
assert.deepStrictEqual(inspect(parser('>>http://host)')), [['<span class="cite">><a class="anchor" href="http://host)" target="_blank" data-depth="1">>http://host)</a></span>', '<br>'], '']);
|
|
50
48
|
assert.deepStrictEqual(inspect(parser('>>http://host ')), [['<span class="cite">><a class="anchor" href="http://host" target="_blank" data-depth="1">>http://host</a></span>', '<br>'], '']);
|
|
51
49
|
assert.deepStrictEqual(inspect(parser('>>http://host\n')), [['<span class="cite">><a class="anchor" href="http://host" target="_blank" data-depth="1">>http://host</a></span>', '<br>'], '']);
|
|
52
50
|
assert.deepStrictEqual(inspect(parser('>>https://host')), [['<span class="cite">><a class="anchor" href="https://host" target="_blank" data-depth="1">>https://host</a></span>', '<br>'], '']);
|
|
@@ -1,26 +1,39 @@
|
|
|
1
1
|
import { ReplyParser } from '../../block';
|
|
2
|
-
import { union,
|
|
2
|
+
import { union, line, validate, focus, open, fmap } from '../../../combinator';
|
|
3
3
|
import { anchor } from '../../inline/autolink/anchor';
|
|
4
4
|
import { str } from '../../source';
|
|
5
5
|
import { html, define, defrag } from 'typed-dom/dom';
|
|
6
6
|
|
|
7
|
+
export const syntax = /^>*(?=>>[^>\s]\S*[^\S\n]*(?:$|\n))/;
|
|
8
|
+
|
|
7
9
|
export const cite: ReplyParser.CiteParser = line(fmap(validate(
|
|
8
10
|
'>>',
|
|
9
|
-
|
|
10
|
-
str(
|
|
11
|
+
open(
|
|
12
|
+
str(syntax),
|
|
11
13
|
union([
|
|
12
14
|
anchor,
|
|
13
15
|
// Subject page representation.
|
|
14
16
|
// リンクの実装は後で検討
|
|
15
|
-
focus(/^>>\.(?=\s*$)/, () => [[html('a', { class: 'anchor' }, '>>.')], ''], false),
|
|
16
17
|
focus(/^>>#\S*(?=\s*$)/, ({ source }) => [[html('a', { class: 'anchor' }, source)], ''], false),
|
|
17
|
-
focus(/^>>https
|
|
18
|
+
focus(/^>>https?:\/\/\S+(?=\s*$)/, ({ source }) => [[html('a', { class: 'anchor', href: source.slice(2).trimEnd(), target: '_blank' }, source)], ''], false),
|
|
19
|
+
focus(/^>>.+(?=\s*$)/, ({ source }) => [[source], ''], false),
|
|
18
20
|
]),
|
|
19
|
-
|
|
20
|
-
([
|
|
21
|
-
html('span',
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
21
|
+
)),
|
|
22
|
+
([quotes, node]: [string, HTMLElement | string]) => [
|
|
23
|
+
html('span',
|
|
24
|
+
typeof node === 'object'
|
|
25
|
+
? { class: 'cite' }
|
|
26
|
+
: {
|
|
27
|
+
class: 'cite invalid',
|
|
28
|
+
'data-invalid-syntax': 'cite',
|
|
29
|
+
'data-invalid-type': 'syntax',
|
|
30
|
+
'data-invalid-message': 'Invalid syntax',
|
|
31
|
+
},
|
|
32
|
+
defrag([
|
|
33
|
+
`${quotes}>`,
|
|
34
|
+
typeof node === 'object'
|
|
35
|
+
? define(node, { 'data-depth': `${quotes.length + 1}` }, node.innerText.slice(1))
|
|
36
|
+
: node.slice(1),
|
|
37
|
+
])),
|
|
25
38
|
html('br'),
|
|
26
39
|
]));
|
|
@@ -11,22 +11,22 @@ describe('Unit: parser/block/reply/quote', () => {
|
|
|
11
11
|
assert.deepStrictEqual(inspect(parser('>')), undefined);
|
|
12
12
|
assert.deepStrictEqual(inspect(parser('>\n')), undefined);
|
|
13
13
|
assert.deepStrictEqual(inspect(parser('>>')), undefined);
|
|
14
|
-
assert.deepStrictEqual(inspect(parser('>0')),
|
|
14
|
+
assert.deepStrictEqual(inspect(parser('>0')), undefined);
|
|
15
15
|
assert.deepStrictEqual(inspect(parser('>>0')), undefined);
|
|
16
|
-
assert.deepStrictEqual(inspect(parser('>0A')),
|
|
17
|
-
assert.deepStrictEqual(inspect(parser('>>0A')),
|
|
18
|
-
assert.deepStrictEqual(inspect(parser('>0 a')),
|
|
16
|
+
assert.deepStrictEqual(inspect(parser('>0A')), undefined);
|
|
17
|
+
assert.deepStrictEqual(inspect(parser('>>0A')), undefined);
|
|
18
|
+
assert.deepStrictEqual(inspect(parser('>0 a')), undefined);
|
|
19
19
|
assert.deepStrictEqual(inspect(parser('>>0 a')), undefined);
|
|
20
|
-
assert.deepStrictEqual(inspect(parser('>A')),
|
|
21
|
-
assert.deepStrictEqual(inspect(parser('>A 0')),
|
|
22
|
-
assert.deepStrictEqual(inspect(parser('>/')),
|
|
23
|
-
assert.deepStrictEqual(inspect(parser('>\\')),
|
|
24
|
-
assert.deepStrictEqual(inspect(parser('>>01#')),
|
|
25
|
-
assert.deepStrictEqual(inspect(parser('>>01@')),
|
|
26
|
-
assert.deepStrictEqual(inspect(parser('>>https://host')),
|
|
27
|
-
assert.deepStrictEqual(inspect(parser('>>tel:1234567890')),
|
|
28
|
-
assert.deepStrictEqual(inspect(parser('>#a')),
|
|
29
|
-
assert.deepStrictEqual(inspect(parser('>A\n> b')),
|
|
20
|
+
assert.deepStrictEqual(inspect(parser('>A')), undefined);
|
|
21
|
+
assert.deepStrictEqual(inspect(parser('>A 0')), undefined);
|
|
22
|
+
assert.deepStrictEqual(inspect(parser('>/')), undefined);
|
|
23
|
+
assert.deepStrictEqual(inspect(parser('>\\')), undefined);
|
|
24
|
+
assert.deepStrictEqual(inspect(parser('>>01#')), undefined);
|
|
25
|
+
assert.deepStrictEqual(inspect(parser('>>01@')), undefined);
|
|
26
|
+
assert.deepStrictEqual(inspect(parser('>>https://host')), undefined);
|
|
27
|
+
assert.deepStrictEqual(inspect(parser('>>tel:1234567890')), undefined);
|
|
28
|
+
assert.deepStrictEqual(inspect(parser('>#a')), undefined);
|
|
29
|
+
assert.deepStrictEqual(inspect(parser('>A\n> b')), undefined);
|
|
30
30
|
assert.deepStrictEqual(inspect(parser(' > 0')), undefined);
|
|
31
31
|
assert.deepStrictEqual(inspect(parser('\\> 0')), undefined);
|
|
32
32
|
});
|
|
@@ -55,9 +55,10 @@ 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
|
|
59
|
-
assert.deepStrictEqual(inspect(parser('> a\n> http://host
|
|
60
|
-
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
|
+
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)')), [['<span class="quote">> !<a class="url" href="http://host)" target="_blank">http://host)</a></span>', '<br>'], '']);
|
|
61
|
+
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>'], '']);
|
|
61
62
|
});
|
|
62
63
|
|
|
63
64
|
});
|
|
@@ -1,42 +1,27 @@
|
|
|
1
1
|
import { ReplyParser } from '../../block';
|
|
2
|
-
import { union, some, block,
|
|
2
|
+
import { union, some, block, validate, rewrite, convert, lazy, fmap } from '../../../combinator';
|
|
3
3
|
import { math } from '../../inline/math';
|
|
4
4
|
import { autolink } from '../../inline/autolink';
|
|
5
|
-
import { linebreak, unescsource,
|
|
5
|
+
import { linebreak, unescsource, anyline } from '../../source';
|
|
6
6
|
import { html, defrag } from 'typed-dom/dom';
|
|
7
7
|
|
|
8
|
-
export const syntax = /^>+
|
|
8
|
+
export const syntax = /^>+[^\S\n]/;
|
|
9
9
|
|
|
10
10
|
export const quote: ReplyParser.QuoteParser = lazy(() => block(fmap(validate(
|
|
11
11
|
'>',
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
12
|
+
rewrite(
|
|
13
|
+
some(validate(syntax, anyline)),
|
|
14
|
+
convert(
|
|
15
|
+
source => source.replace(/\n$/, '').replace(/(?<=^>+[^\S\n])/mg, '\r'),
|
|
16
|
+
some(union([
|
|
17
|
+
math, // quote補助関数が残した数式をパースする。他の構文で数式を残す場合はソーステキストを直接使用する。
|
|
18
|
+
autolink,
|
|
19
|
+
linebreak,
|
|
20
|
+
unescsource,
|
|
21
|
+
])),
|
|
22
|
+
false))),
|
|
20
23
|
(ns: [string, ...(string | HTMLElement)[]]) => [
|
|
21
|
-
html('span',
|
|
22
|
-
ns.length > 1
|
|
23
|
-
? { class: 'quote' }
|
|
24
|
-
: {
|
|
25
|
-
class: 'quote invalid',
|
|
26
|
-
'data-invalid-syntax': 'quote',
|
|
27
|
-
'data-invalid-type': 'syntax',
|
|
28
|
-
'data-invalid-message': `Missing the whitespace after "${ns[0].split(/[^>]/, 1)[0]}"`,
|
|
29
|
-
},
|
|
30
|
-
defrag(ns)),
|
|
24
|
+
html('span', { class: 'quote' }, defrag(ns)),
|
|
31
25
|
html('br'),
|
|
32
26
|
]),
|
|
33
27
|
false));
|
|
34
|
-
|
|
35
|
-
const qblock: ReplyParser.QuoteParser.BlockParser = convert(
|
|
36
|
-
source => source.replace(/\n$/, '').replace(/(?<=^>+[^\S\n])/mg, '\r'),
|
|
37
|
-
some(union([
|
|
38
|
-
math, // quote補助関数が残した数式をパースする。他の構文で数式を残す場合はソーステキストを直接使用する。
|
|
39
|
-
autolink,
|
|
40
|
-
linebreak,
|
|
41
|
-
unescsource,
|
|
42
|
-
])));
|
|
@@ -6,15 +6,28 @@ describe('Unit: parser/block/reply', () => {
|
|
|
6
6
|
describe('reply', () => {
|
|
7
7
|
const parser = (source: string) => some(reply)({ source, context: {} });
|
|
8
8
|
|
|
9
|
+
it('invalid', () => {
|
|
10
|
+
assert.deepStrictEqual(inspect(parser('>')), undefined);
|
|
11
|
+
assert.deepStrictEqual(inspect(parser('>1')), undefined);
|
|
12
|
+
assert.deepStrictEqual(inspect(parser('>>')), undefined);
|
|
13
|
+
assert.deepStrictEqual(inspect(parser('>>1 a')), undefined);
|
|
14
|
+
assert.deepStrictEqual(inspect(parser('> ')), undefined);
|
|
15
|
+
assert.deepStrictEqual(inspect(parser('> a')), undefined);
|
|
16
|
+
assert.deepStrictEqual(inspect(parser('>\n')), undefined);
|
|
17
|
+
});
|
|
18
|
+
|
|
9
19
|
it('basic', () => {
|
|
10
20
|
assert.deepStrictEqual(inspect(parser('>>1')), [['<p><span class="cite">><a class="anchor" href="?at=1" data-depth="1">>1</a></span></p>'], '']);
|
|
11
21
|
assert.deepStrictEqual(inspect(parser('>>1\na')), [['<p><span class="cite">><a class="anchor" href="?at=1" data-depth="1">>1</a></span><br>a</p>'], '']);
|
|
12
|
-
assert.deepStrictEqual(inspect(parser('>>1\na\n>>2')), [['<p><span class="cite">><a class="anchor" href="?at=1" data-depth="1">>1</a></span><br>a<br><a class="anchor" href="?at=2">>
|
|
22
|
+
assert.deepStrictEqual(inspect(parser('>>1\na\n>>2')), [['<p><span class="cite">><a class="anchor" href="?at=1" data-depth="1">>1</a></span><br>a<br><span class="cite">><a class="anchor" href="?at=2" data-depth="1">>2</a></span></p>'], '']);
|
|
23
|
+
assert.deepStrictEqual(inspect(parser('>>1\na\n>>2 b')), [['<p><span class="cite">><a class="anchor" href="?at=1" data-depth="1">>1</a></span><br>a<br><a class="anchor" href="?at=2">>>2</a> b</p>'], '']);
|
|
24
|
+
assert.deepStrictEqual(inspect(parser('>>1\na\n> b')), [['<p><span class="cite">><a class="anchor" href="?at=1" data-depth="1">>1</a></span><br>a<br><span class="quote">> b</span></p>'], '']);
|
|
13
25
|
assert.deepStrictEqual(inspect(parser('>>1\n>>2')), [['<p><span class="cite">><a class="anchor" href="?at=1" data-depth="1">>1</a></span><br><span class="cite">><a class="anchor" href="?at=2" data-depth="1">>2</a></span></p>'], '']);
|
|
14
26
|
assert.deepStrictEqual(inspect(parser('>>1\n> a')), [['<p><span class="cite">><a class="anchor" href="?at=1" data-depth="1">>1</a></span><br><span class="quote">> a</span></p>'], '']);
|
|
15
27
|
assert.deepStrictEqual(inspect(parser('>>1\n> a\nb')), [['<p><span class="cite">><a class="anchor" href="?at=1" data-depth="1">>1</a></span><br><span class="quote">> a</span><br>b</p>'], '']);
|
|
16
28
|
assert.deepStrictEqual(inspect(parser('>>1\n> a\n>>2')), [['<p><span class="cite">><a class="anchor" href="?at=1" data-depth="1">>1</a></span><br><span class="quote">> a</span><br><span class="cite">><a class="anchor" href="?at=2" data-depth="1">>2</a></span></p>'], '']);
|
|
17
29
|
assert.deepStrictEqual(inspect(parser('>>1\n> a\n>> b')), [['<p><span class="cite">><a class="anchor" href="?at=1" data-depth="1">>1</a></span><br><span class="quote">> a<br>>> b</span></p>'], '']);
|
|
30
|
+
assert.deepStrictEqual(inspect(parser('>>http://host\n>>http://host')), [['<p><span class="cite">><a class="anchor" href="http://host" target="_blank" data-depth="1">>http://host</a></span><br><span class="cite">><a class="anchor" href="http://host" target="_blank" data-depth="1">>http://host</a></span></p>'], '']);
|
|
18
31
|
});
|
|
19
32
|
|
|
20
33
|
});
|
|
@@ -1,33 +1,21 @@
|
|
|
1
1
|
import { ReplyParser } from '../block';
|
|
2
|
-
import {
|
|
3
|
-
import { cite } from './reply/cite';
|
|
4
|
-
import { quote, syntax as
|
|
2
|
+
import { union, some, block, validate, rewrite, fmap } from '../../combinator';
|
|
3
|
+
import { cite, syntax as csyntax } from './reply/cite';
|
|
4
|
+
import { quote, syntax as qsyntax } from './reply/quote';
|
|
5
5
|
import { inline } from '../inline';
|
|
6
6
|
import { anyline } from '../source';
|
|
7
7
|
import { lineable } from '../util';
|
|
8
8
|
import { visualize, trimBlankNodeEnd } from '../visibility';
|
|
9
|
-
import { push } from 'spica/array';
|
|
10
9
|
import { html, defrag } from 'typed-dom/dom';
|
|
11
10
|
|
|
12
|
-
|
|
13
|
-
必ず対象指定から始まる
|
|
14
|
-
対象がページである場合>>.を表現方法とする
|
|
15
|
-
対象をURLで指定すべき(引用ツリーにルートを追加する)場合はない
|
|
16
|
-
対象と引用は1:N(分割)、N:1(統合)のみ可能、N:N(混合)は不可能
|
|
17
|
-
*/
|
|
11
|
+
const delimiter = new RegExp(String.raw`${csyntax.source}|${qsyntax.source}`);
|
|
18
12
|
|
|
19
|
-
export const reply: ReplyParser = block(validate(
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
fmap(rewrite(
|
|
28
|
-
some(anyline, delimiter),
|
|
29
|
-
visualize(lineable(some(inline)))),
|
|
30
|
-
ns => push(ns, [html('br')])),
|
|
31
|
-
])),
|
|
32
|
-
]),
|
|
13
|
+
export const reply: ReplyParser = block(validate(csyntax, fmap(
|
|
14
|
+
some(union([
|
|
15
|
+
cite,
|
|
16
|
+
quote,
|
|
17
|
+
rewrite(
|
|
18
|
+
some(anyline, delimiter),
|
|
19
|
+
visualize(lineable(some(inline), true))),
|
|
20
|
+
])),
|
|
33
21
|
ns => [html('p', trimBlankNodeEnd(defrag(ns)))])));
|
|
@@ -41,7 +41,9 @@ describe('Unit: parser/block/sidefence', () => {
|
|
|
41
41
|
assert.deepStrictEqual(inspect(parser('|\n|')), [['<blockquote class="invalid"><pre><br></pre></blockquote>'], '']);
|
|
42
42
|
assert.deepStrictEqual(inspect(parser('|\n| a')), [['<blockquote class="invalid"><pre><br>a</pre></blockquote>'], '']);
|
|
43
43
|
assert.deepStrictEqual(inspect(parser('| http://host')), [['<blockquote class="invalid"><pre><a class="url" href="http://host" target="_blank">http://host</a></pre></blockquote>'], '']);
|
|
44
|
+
assert.deepStrictEqual(inspect(parser('| http://host)')), [['<blockquote class="invalid"><pre><a class="url" href="http://host)" target="_blank">http://host)</a></pre></blockquote>'], '']);
|
|
44
45
|
assert.deepStrictEqual(inspect(parser('| !http://host')), [['<blockquote class="invalid"><pre>!<a class="url" href="http://host" target="_blank">http://host</a></pre></blockquote>'], '']);
|
|
46
|
+
assert.deepStrictEqual(inspect(parser('| !http://host)')), [['<blockquote class="invalid"><pre>!<a class="url" href="http://host)" target="_blank">http://host)</a></pre></blockquote>'], '']);
|
|
45
47
|
assert.deepStrictEqual(inspect(parser('| #a')), [['<blockquote class="invalid"><pre><a class="hashtag" href="/hashtags/a">#a</a></pre></blockquote>'], '']);
|
|
46
48
|
assert.deepStrictEqual(inspect(parser('| @a#b')), [['<blockquote class="invalid"><pre><a class="channel" href="/@a?ch=b">@a#b</a></pre></blockquote>'], '']);
|
|
47
49
|
assert.deepStrictEqual(inspect(parser('| >>1\n| | b')), [['<blockquote class="invalid"><pre><a class="anchor" href="?at=1">>>1</a><br>| b</pre></blockquote>'], '']);
|
|
@@ -24,9 +24,9 @@ const source: SidefenceParser.SourceParser = lazy(() => fmap(
|
|
|
24
24
|
some(recursion(Recursion.block, union([
|
|
25
25
|
focus(
|
|
26
26
|
/^(?:\|\|+(?:[^\S\n][^\n]*)?(?:$|\n))+/,
|
|
27
|
-
convert(unindent, source, true), false),
|
|
27
|
+
convert(unindent, source, false, true), false),
|
|
28
28
|
rewrite(
|
|
29
29
|
some(contentline, opener),
|
|
30
|
-
convert(unindent, fmap(autolink, ns => [html('pre', defrag(ns))]), true)),
|
|
30
|
+
convert(unindent, fmap(autolink, ns => [html('pre', defrag(ns))]), false, true)),
|
|
31
31
|
]))),
|
|
32
32
|
ns => [html('blockquote', ns)]));
|
package/src/parser/header.ts
CHANGED
|
@@ -21,7 +21,8 @@ export const account: AutolinkParser.AccountParser = lazy(() => rewrite(
|
|
|
21
21
|
? `https://${source.slice(1).replace('/', '/@')}`
|
|
22
22
|
: `/${source}`
|
|
23
23
|
} }`,
|
|
24
|
-
unsafelink
|
|
24
|
+
unsafelink,
|
|
25
|
+
false),
|
|
25
26
|
([el]) => [define(el, { class: 'account' })]))),
|
|
26
27
|
({ source }) => [[source], ''],
|
|
27
28
|
])));
|
|
@@ -24,7 +24,8 @@ export const anchor: AutolinkParser.AnchorParser = lazy(() => validate('>>',
|
|
|
24
24
|
? `/@${source.slice(2).replace('/', '/timeline?at=')}`
|
|
25
25
|
: `?at=${source.slice(2)}`
|
|
26
26
|
} }`,
|
|
27
|
-
unsafelink
|
|
27
|
+
unsafelink,
|
|
28
|
+
false),
|
|
28
29
|
([el]) => [define(el, { class: 'anchor' })]))),
|
|
29
30
|
({ source }) => [[source], ''],
|
|
30
31
|
]))));
|
|
@@ -11,7 +11,8 @@ export const hashnum: AutolinkParser.HashnumParser = lazy(() => rewrite(
|
|
|
11
11
|
union([
|
|
12
12
|
constraint(State.autolink, false, state(State.autolink, fmap(convert(
|
|
13
13
|
source => `[${source}]{ ${source.slice(1)} }`,
|
|
14
|
-
unsafelink
|
|
14
|
+
unsafelink,
|
|
15
|
+
false),
|
|
15
16
|
([el]) => [define(el, { class: 'hashnum', href: null })]))),
|
|
16
17
|
({ source }) => [[source], ''],
|
|
17
18
|
])));
|
|
@@ -20,7 +20,8 @@ export const hashtag: AutolinkParser.HashtagParser = lazy(() => rewrite(
|
|
|
20
20
|
union([
|
|
21
21
|
constraint(State.autolink, false, state(State.autolink, fmap(convert(
|
|
22
22
|
source => `[${source}]{ ${`/hashtags/${source.slice(1)}`} }`,
|
|
23
|
-
unsafelink
|
|
23
|
+
unsafelink,
|
|
24
|
+
false),
|
|
24
25
|
([el]) => [define(el, { class: 'hashtag' })]))),
|
|
25
26
|
({ source }) => [[source], ''],
|
|
26
27
|
])));
|
|
@@ -16,7 +16,8 @@ export const url: AutolinkParser.UrlParser = lazy(() => validate(['http://', 'ht
|
|
|
16
16
|
union([
|
|
17
17
|
constraint(State.autolink, false, state(State.autolink, convert(
|
|
18
18
|
url => `{ ${url} }`,
|
|
19
|
-
unsafelink
|
|
19
|
+
unsafelink,
|
|
20
|
+
false))),
|
|
20
21
|
({ source }) => [[source], ''],
|
|
21
22
|
]))));
|
|
22
23
|
|
|
@@ -29,7 +30,8 @@ export const lineurl: AutolinkParser.UrlParser.LineUrlParser = lazy(() => open(
|
|
|
29
30
|
union([
|
|
30
31
|
constraint(State.autolink, false, state(State.autolink, convert(
|
|
31
32
|
url => `{ ${url} }`,
|
|
32
|
-
unsafelink
|
|
33
|
+
unsafelink,
|
|
34
|
+
false))),
|
|
33
35
|
({ source }) => [[source], ''],
|
|
34
36
|
]),
|
|
35
37
|
]))));
|
|
@@ -9,7 +9,8 @@ export const shortmedia: ShortMediaParser = constraint(State.media, false, rewri
|
|
|
9
9
|
open('!', url),
|
|
10
10
|
convert(
|
|
11
11
|
source => `!{ ${source.slice(1)} }`,
|
|
12
|
-
union([media])
|
|
12
|
+
union([media]),
|
|
13
|
+
false)));
|
|
13
14
|
|
|
14
15
|
export const lineshortmedia: ShortMediaParser.LineShortMediaParser = open(
|
|
15
16
|
linebreak,
|
|
@@ -17,4 +18,5 @@ export const lineshortmedia: ShortMediaParser.LineShortMediaParser = open(
|
|
|
17
18
|
/^!https?:\/\/\S+(?=[^\S\n]*(?:$|\n))/,
|
|
18
19
|
convert(
|
|
19
20
|
source => `!{ ${source.slice(1)} }`,
|
|
20
|
-
union([media])
|
|
21
|
+
union([media]),
|
|
22
|
+
false)));
|
|
@@ -11,7 +11,7 @@ export const template: TemplateParser = lazy(() => surround(
|
|
|
11
11
|
'}}',
|
|
12
12
|
true,
|
|
13
13
|
([, ns = []], rest) => [[html('span', { class: 'template' }, `{{${ns.join('')}}}`)], rest],
|
|
14
|
-
undefined, [3 | Backtrack.linedoublebracket, 1 | Backtrack.lineescbracket]
|
|
14
|
+
undefined, [3 | Backtrack.linedoublebracket, 1 | Backtrack.lineescbracket]));
|
|
15
15
|
|
|
16
16
|
const bracket: TemplateParser.BracketParser = lazy(() => union([
|
|
17
17
|
surround(str('('), recursion(Recursion.terminal, some(union([bracket, escsource]), ')')), str(')'), true,
|
|
@@ -169,6 +169,8 @@ describe('Unit: parser/inline', () => {
|
|
|
169
169
|
assert.deepStrictEqual(inspect(parser('_http://host_')), [['_', '<a class="url" href="http://host" target="_blank">http://host</a>', '_'], '']);
|
|
170
170
|
assert.deepStrictEqual(inspect(parser('*http://host*')), [['<em><a class="url" href="http://host" target="_blank">http://host</a></em>'], '']);
|
|
171
171
|
assert.deepStrictEqual(inspect(parser('(http://host)')), [['<span class="paren">(<a class="url" href="http://host" target="_blank">http://host</a>)</span>'], '']);
|
|
172
|
+
assert.deepStrictEqual(inspect(parser('"http://host"')), [['"', '<a class="url" href="http://host" target="_blank">http://host</a>', '"'], '']);
|
|
173
|
+
assert.deepStrictEqual(inspect(parser('"http://host""')), [['"', '<a class="url" href="http://host" target="_blank">http://host</a>', '"', '"'], '']);
|
|
172
174
|
assert.deepStrictEqual(inspect(parser(' http://host')), [[' ', '<a class="url" href="http://host" target="_blank">http://host</a>'], '']);
|
|
173
175
|
assert.deepStrictEqual(inspect(parser('あhttp://hostい')), [['あ', '<a class="url" href="http://host" target="_blank">http://host</a>', 'い'], '']);
|
|
174
176
|
});
|
package/src/parser/source/str.ts
CHANGED
|
@@ -21,7 +21,8 @@ export function str(pattern: string | RegExp, not?: string): Parser<string, Cont
|
|
|
21
21
|
const m = source.match(pattern);
|
|
22
22
|
count && m && consume(m[0].length, context);
|
|
23
23
|
if (m && not && source.slice(m[0].length, m[0].length + not.length) === not) return;
|
|
24
|
-
|
|
24
|
+
//assert(!m || m[0]);
|
|
25
|
+
return m
|
|
25
26
|
? [[m[0]], source.slice(m[0].length)]
|
|
26
27
|
: undefined;
|
|
27
28
|
};
|
package/src/parser/util.ts
CHANGED
|
@@ -4,9 +4,12 @@ import { Parser, Result, Ctx, Tree, Context, eval, exec } from '../combinator/da
|
|
|
4
4
|
import { convert } from '../combinator';
|
|
5
5
|
import { define } from 'typed-dom/dom';
|
|
6
6
|
|
|
7
|
-
export function lineable<P extends Parser<HTMLElement | string>>(parser: P): P;
|
|
8
|
-
export function lineable<T extends HTMLElement | string>(parser: Parser<T
|
|
9
|
-
return convert(
|
|
7
|
+
export function lineable<P extends Parser<HTMLElement | string>>(parser: P, fillTrailingLinebreak?: boolean): P;
|
|
8
|
+
export function lineable<T extends HTMLElement | string>(parser: Parser<T>, fillTrailingLinebreak = false): Parser<T> {
|
|
9
|
+
return convert(
|
|
10
|
+
source => `\r${source}${fillTrailingLinebreak && source.at(-1) !== '\n' ? '\n' : ''}`,
|
|
11
|
+
parser,
|
|
12
|
+
!fillTrailingLinebreak);
|
|
10
13
|
}
|
|
11
14
|
|
|
12
15
|
export function repeat<P extends Parser<HTMLElement | string>>(symbol: string, parser: P, cons: (nodes: Tree<P>[], context: Context<P>) => Tree<P>[], termination?: (acc: Tree<P>[][], rest: string, prefix: number, postfix: number, state: boolean) => Result<string | Tree<P>>): P;
|
package/src/parser/visibility.ts
CHANGED
|
@@ -23,7 +23,8 @@ export function visualize<T extends HTMLElement | string>(parser: Parser<T>): Pa
|
|
|
23
23
|
return union([
|
|
24
24
|
convert(
|
|
25
25
|
source => source.replace(blank.line, line => line.replace(/[\\&<]/g, `${Command.Escape}$&`)),
|
|
26
|
-
verify(parser, (ns, rest) => !rest && hasVisible(ns))
|
|
26
|
+
verify(parser, (ns, rest) => !rest && hasVisible(ns)),
|
|
27
|
+
false),
|
|
27
28
|
some(union([linebreak, unescsource])),
|
|
28
29
|
]);
|
|
29
30
|
}
|
|
@@ -162,7 +163,8 @@ export function trimBlankStart<P extends Parser<unknown>>(parser: P): P;
|
|
|
162
163
|
export function trimBlankStart<T>(parser: Parser<T>): Parser<T> {
|
|
163
164
|
return convert(
|
|
164
165
|
source => source.replace(blank.start, ''),
|
|
165
|
-
parser
|
|
166
|
+
parser,
|
|
167
|
+
true);
|
|
166
168
|
}
|
|
167
169
|
export function trimBlankEnd<P extends Parser<HTMLElement | string>>(parser: P): P;
|
|
168
170
|
export function trimBlankEnd<T extends HTMLElement | string>(parser: Parser<T>): Parser<T> {
|
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>
|
|
8
|
+
const el = parse('>>1\n> a\n>>?\n> 2\n>>4 `b` ${c}$\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)
|
|
11
|
+
assert.deepStrictEqual(quote('3', range), `>>>1\n>> a\n>>>?\n>> 2\n>>3\n> >>4 \`b\` \${c}$\n> e`);
|
|
12
12
|
});
|
|
13
13
|
|
|
14
14
|
it('adjustment', () => {
|