securemark 0.267.0 → 0.268.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 +49 -54
- package/markdown.d.ts +22 -5
- package/package.json +7 -7
- package/src/combinator/control/constraint/block.ts +2 -2
- package/src/combinator/control/constraint/line.ts +2 -2
- package/src/combinator/control/manipulation/fence.ts +4 -4
- package/src/parser/api/bind.ts +1 -1
- package/src/parser/api/parse.ts +1 -1
- package/src/parser/autolink.ts +15 -22
- package/src/parser/block/blockquote.ts +1 -1
- package/src/parser/block/codeblock.ts +2 -2
- package/src/parser/block/olist.test.ts +2 -2
- package/src/parser/block/olist.ts +2 -2
- package/src/parser/block/paragraph.test.ts +3 -0
- package/src/parser/block/reply/cite.ts +1 -2
- package/src/parser/block/reply/quote.test.ts +3 -0
- package/src/parser/block/reply/quote.ts +15 -9
- package/src/parser/block/sidefence.ts +1 -1
- package/src/parser/block/ulist.test.ts +2 -2
- package/src/parser/block/ulist.ts +2 -2
- package/src/parser/inline/extension/index.ts +1 -1
- package/src/parser/inline/extension/indexee.ts +1 -1
- package/src/parser/source/line.ts +3 -3
- package/src/parser/source/str.ts +1 -1
- package/src/parser/util.ts +10 -0
- package/src/parser/visibility.ts +2 -1
- package/src/util/quote.ts +9 -2
package/CHANGELOG.md
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! securemark v0.
|
|
1
|
+
/*! securemark v0.268.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"));
|
|
@@ -2653,7 +2653,7 @@ function block(parser, separation = true) {
|
|
|
2653
2653
|
});
|
|
2654
2654
|
if (result === undefined) return;
|
|
2655
2655
|
const rest = (0, parser_1.exec)(result);
|
|
2656
|
-
if (separation && !(0, line_1.
|
|
2656
|
+
if (separation && !(0, line_1.isBlank)((0, line_1.firstline)(rest))) return;
|
|
2657
2657
|
return rest === '' || source[source.length - rest.length - 1] === '\n' ? result : undefined;
|
|
2658
2658
|
};
|
|
2659
2659
|
}
|
|
@@ -2721,7 +2721,7 @@ exports.verify = verify;
|
|
|
2721
2721
|
Object.defineProperty(exports, "__esModule", ({
|
|
2722
2722
|
value: true
|
|
2723
2723
|
}));
|
|
2724
|
-
exports.
|
|
2724
|
+
exports.isBlank = exports.firstline = exports.line = void 0;
|
|
2725
2725
|
const parser_1 = __webpack_require__(6728);
|
|
2726
2726
|
const memo_1 = __webpack_require__(1090);
|
|
2727
2727
|
function line(parser) {
|
|
@@ -2740,7 +2740,7 @@ function line(parser) {
|
|
|
2740
2740
|
});
|
|
2741
2741
|
context.offset -= source.length - line.length;
|
|
2742
2742
|
if (result === undefined) return;
|
|
2743
|
-
return
|
|
2743
|
+
return isBlank((0, parser_1.exec)(result)) ? [(0, parser_1.eval)(result), source.slice(line.length)] : undefined;
|
|
2744
2744
|
};
|
|
2745
2745
|
}
|
|
2746
2746
|
exports.line = line;
|
|
@@ -2756,10 +2756,10 @@ function firstline(source) {
|
|
|
2756
2756
|
}
|
|
2757
2757
|
}
|
|
2758
2758
|
exports.firstline = firstline;
|
|
2759
|
-
function
|
|
2759
|
+
function isBlank(line) {
|
|
2760
2760
|
return line === '' || line === '\n' || line.trimStart() === '';
|
|
2761
2761
|
}
|
|
2762
|
-
exports.
|
|
2762
|
+
exports.isBlank = isBlank;
|
|
2763
2763
|
|
|
2764
2764
|
/***/ }),
|
|
2765
2765
|
|
|
@@ -2855,20 +2855,20 @@ function fence(opener, limit, separation = true) {
|
|
|
2855
2855
|
if (matches[0].indexOf(delim, delim.length) !== -1) return;
|
|
2856
2856
|
let rest = source.slice(matches[0].length);
|
|
2857
2857
|
// Prevent annoying parsing in editing.
|
|
2858
|
-
if ((0, line_1.
|
|
2858
|
+
if ((0, line_1.isBlank)((0, line_1.firstline)(rest)) && (0, line_1.firstline)(rest.slice((0, line_1.firstline)(rest).length)).trimEnd() !== delim) return;
|
|
2859
2859
|
let block = '';
|
|
2860
2860
|
let closer = '';
|
|
2861
2861
|
let overflow = '';
|
|
2862
2862
|
for (let count = 1;; ++count) {
|
|
2863
2863
|
if (rest === '') break;
|
|
2864
2864
|
const line = (0, line_1.firstline)(rest);
|
|
2865
|
-
if ((closer || count > limit + 1) && (0, line_1.
|
|
2865
|
+
if ((closer || count > limit + 1) && (0, line_1.isBlank)(line)) break;
|
|
2866
2866
|
if (closer) {
|
|
2867
2867
|
overflow += line;
|
|
2868
2868
|
}
|
|
2869
2869
|
if (!closer && count <= limit + 1 && line.slice(0, delim.length) === delim && line.trimEnd() === delim) {
|
|
2870
2870
|
closer = line;
|
|
2871
|
-
if ((0, line_1.
|
|
2871
|
+
if ((0, line_1.isBlank)((0, line_1.firstline)(rest.slice(line.length)))) {
|
|
2872
2872
|
rest = rest.slice(line.length);
|
|
2873
2873
|
break;
|
|
2874
2874
|
}
|
|
@@ -3908,7 +3908,7 @@ function bind(target, settings) {
|
|
|
3908
3908
|
})
|
|
3909
3909
|
};
|
|
3910
3910
|
|
|
3911
|
-
if (context.id?.match(/[^0-9a-z
|
|
3911
|
+
if (context.id?.match(/[^0-9a-z/-]/i)) throw new Error('Invalid ID: ID must be alphanumeric');
|
|
3912
3912
|
if (context.host?.origin === 'null') throw new Error(`Invalid host: ${context.host.href}`);
|
|
3913
3913
|
const blocks = [];
|
|
3914
3914
|
const adds = [];
|
|
@@ -4241,7 +4241,7 @@ function parse(source, opts = {}, context) {
|
|
|
4241
4241
|
})
|
|
4242
4242
|
};
|
|
4243
4243
|
|
|
4244
|
-
if (context.id?.match(/[^0-9a-z
|
|
4244
|
+
if (context.id?.match(/[^0-9a-z/-]/i)) throw new Error('Invalid ID: ID must be alphanumeric');
|
|
4245
4245
|
if (context.host?.origin === 'null') throw new Error(`Invalid host: ${context.host.href}`);
|
|
4246
4246
|
const node = (0, dom_1.frag)();
|
|
4247
4247
|
let index = 0;
|
|
@@ -4274,31 +4274,14 @@ exports.parse = parse;
|
|
|
4274
4274
|
Object.defineProperty(exports, "__esModule", ({
|
|
4275
4275
|
value: true
|
|
4276
4276
|
}));
|
|
4277
|
-
exports.autolink = void 0;
|
|
4277
|
+
exports.lineurl = exports.autolink = void 0;
|
|
4278
4278
|
const combinator_1 = __webpack_require__(2087);
|
|
4279
|
+
const link_1 = __webpack_require__(9628);
|
|
4279
4280
|
const autolink_1 = __webpack_require__(6051);
|
|
4280
4281
|
const source_1 = __webpack_require__(6743);
|
|
4281
|
-
const
|
|
4282
|
-
|
|
4283
|
-
|
|
4284
|
-
context
|
|
4285
|
-
}) => {
|
|
4286
|
-
if (source === '') return;
|
|
4287
|
-
const i = source.search(delimiter);
|
|
4288
|
-
switch (i) {
|
|
4289
|
-
case -1:
|
|
4290
|
-
return [[source], ''];
|
|
4291
|
-
case 0:
|
|
4292
|
-
return parser({
|
|
4293
|
-
source,
|
|
4294
|
-
context
|
|
4295
|
-
});
|
|
4296
|
-
default:
|
|
4297
|
-
return [[source.slice(0, i)], source.slice(i)];
|
|
4298
|
-
}
|
|
4299
|
-
};
|
|
4300
|
-
exports.autolink = autolink;
|
|
4301
|
-
const parser = (0, combinator_1.lazy)(() => (0, combinator_1.union)([autolink_1.autolink, source_1.linebreak, source_1.unescsource]));
|
|
4282
|
+
const util_1 = __webpack_require__(9437);
|
|
4283
|
+
exports.autolink = (0, combinator_1.lazy)(() => (0, combinator_1.some)((0, combinator_1.line)((0, combinator_1.subsequence)([exports.lineurl, (0, combinator_1.some)((0, combinator_1.union)([autolink_1.autolink, source_1.linebreak, source_1.unescsource]))]))));
|
|
4284
|
+
exports.lineurl = (0, combinator_1.lazy)(() => (0, combinator_1.focus)(/^!?https?:\/\/\S+(?=[^\S\n]*(?:$|\n))/, (0, util_1.format)((0, combinator_1.tails)([(0, source_1.str)('!'), link_1.link]))));
|
|
4302
4285
|
|
|
4303
4286
|
/***/ }),
|
|
4304
4287
|
|
|
@@ -4377,7 +4360,7 @@ exports.blockquote = (0, combinator_1.lazy)(() => (0, combinator_1.block)((0, co
|
|
|
4377
4360
|
const opener = /^(?=>>+(?:$|\s))/;
|
|
4378
4361
|
const indent = (0, combinator_1.block)((0, combinator_1.open)(opener, (0, combinator_1.some)(source_1.contentline, /^>(?:$|\s)/)), false);
|
|
4379
4362
|
const unindent = source => source.replace(/(?<=^|\n)>(?:[^\S\n]|(?=>*(?:$|\s)))|\n$/g, '');
|
|
4380
|
-
const source = (0, combinator_1.lazy)(() => (0, combinator_1.fmap)((0, combinator_1.some)((0, combinator_1.creation)(1, false, (0, combinator_1.union)([(0, combinator_1.rewrite)(indent, (0, combinator_1.convert)(unindent, source)), (0, combinator_1.rewrite)((0, combinator_1.some)(source_1.contentline, opener), (0, combinator_1.convert)(unindent, (0, combinator_1.fmap)(
|
|
4363
|
+
const source = (0, combinator_1.lazy)(() => (0, combinator_1.fmap)((0, combinator_1.some)((0, combinator_1.creation)(1, false, (0, combinator_1.union)([(0, combinator_1.rewrite)(indent, (0, combinator_1.convert)(unindent, source)), (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))])))]))), ns => [(0, dom_1.html)('blockquote', ns)]));
|
|
4381
4364
|
const markdown = (0, combinator_1.lazy)(() => (0, combinator_1.fmap)((0, combinator_1.some)((0, combinator_1.creation)(1, false, (0, combinator_1.union)([(0, combinator_1.rewrite)(indent, (0, combinator_1.convert)(unindent, markdown)), (0, combinator_1.creation)(99, false, (0, combinator_1.rewrite)((0, combinator_1.some)(source_1.contentline, opener), (0, combinator_1.convert)(unindent, ({
|
|
4382
4365
|
source,
|
|
4383
4366
|
context
|
|
@@ -4450,7 +4433,7 @@ exports.codeblock = (0, combinator_1.block)((0, combinator_1.validate)('```', (0
|
|
|
4450
4433
|
'data-lang': params.lang || undefined,
|
|
4451
4434
|
'data-line': params.line || undefined,
|
|
4452
4435
|
'data-path': params.path || undefined
|
|
4453
|
-
}, params.lang ? context.caches?.code?.get(`${params.lang ?? ''}\n${body.slice(0, -1)}`)?.cloneNode(true).childNodes || body.slice(0, -1) || undefined : (0, dom_1.defrag)((0, parser_1.eval)((0,
|
|
4436
|
+
}, params.lang ? context.caches?.code?.get(`${params.lang ?? ''}\n${body.slice(0, -1)}`)?.cloneNode(true).childNodes || body.slice(0, -1) || undefined : (0, dom_1.defrag)((0, parser_1.eval)((0, autolink_1.autolink)({
|
|
4454
4437
|
source: body.slice(0, -1),
|
|
4455
4438
|
context
|
|
4456
4439
|
}), [])));
|
|
@@ -5252,7 +5235,7 @@ const openers = {
|
|
|
5252
5235
|
};
|
|
5253
5236
|
exports.olist = (0, combinator_1.lazy)(() => (0, combinator_1.block)((0, combinator_1.validate)(new RegExp([/^([0-9]+|[a-z]+|[A-Z]+)(?:-[0-9]+)*\.(?=[^\S\n]|\n[^\S\n]*\S)/.source, /^\(([0-9]+|[a-z]+)\)(?:-[0-9]+)*(?=[^\S\n]|\n[^\S\n]*\S)/.source].join('|')), (0, combinator_1.state)(8 /* State.media */, exports.olist_))));
|
|
5254
5237
|
exports.olist_ = (0, combinator_1.lazy)(() => (0, combinator_1.block)((0, combinator_1.union)([(0, combinator_1.match)(openers['.'], (0, memoize_1.memoize)(ms => list(type(ms[1]), '.'), ms => type(ms[1]).charCodeAt(0) || 0, [])), (0, combinator_1.match)(openers['('], (0, memoize_1.memoize)(ms => list(type(ms[1]), '('), ms => type(ms[1]).charCodeAt(0) || 0, []))])));
|
|
5255
|
-
const list = (type, form) => (0, combinator_1.fmap)((0, combinator_1.some)((0, combinator_1.creation)(1, false, (0, combinator_1.union)([(0, inline_1.indexee)((0, combinator_1.fmap)((0, combinator_1.fallback)((0, combinator_1.inits)([(0, combinator_1.line)((0, combinator_1.open)(heads[form], (0, combinator_1.subsequence)([ulist_1.checkbox, (0, visibility_1.trimBlank)((0, combinator_1.some)((0, combinator_1.union)([inline_1.indexer, inline_1.inline])))]), true)), (0, combinator_1.indent)((0, combinator_1.union)([ulist_1.ulist_, exports.olist_, ilist_1.ilist_]))]), exports.invalid), ns => [(0, dom_1.html)('li', {
|
|
5238
|
+
const list = (type, form) => (0, combinator_1.fmap)((0, combinator_1.some)((0, combinator_1.creation)(1, false, (0, combinator_1.union)([(0, inline_1.indexee)((0, combinator_1.fmap)((0, combinator_1.fallback)((0, combinator_1.inits)([(0, combinator_1.line)((0, combinator_1.open)(heads[form], (0, combinator_1.subsequence)([ulist_1.checkbox, (0, visibility_1.trimBlank)((0, visibility_1.visualize)((0, combinator_1.some)((0, combinator_1.union)([inline_1.indexer, inline_1.inline]))))]), true)), (0, combinator_1.indent)((0, combinator_1.union)([ulist_1.ulist_, exports.olist_, ilist_1.ilist_]))]), exports.invalid), ns => [(0, dom_1.html)('li', {
|
|
5256
5239
|
'data-marker': ns[0] || undefined
|
|
5257
5240
|
}, (0, dom_1.defrag)((0, ulist_1.fillFirstLine)((0, array_1.shift)(ns)[1])))]), true)]))), es => [format((0, dom_1.html)('ol', es), type, form)]);
|
|
5258
5241
|
const heads = {
|
|
@@ -5425,9 +5408,7 @@ exports.cite = (0, combinator_1.creation)(1, false, (0, combinator_1.line)((0, c
|
|
|
5425
5408
|
source
|
|
5426
5409
|
}) => [[(0, dom_1.html)('a', {
|
|
5427
5410
|
class: 'anchor'
|
|
5428
|
-
}, source)], '']),
|
|
5429
|
-
// Support all domains, but don't support IP(v6) addresses.
|
|
5430
|
-
(0, combinator_1.focus)(/^>>https?:\/\/[^\p{C}\p{S}\p{P}\s]\S*(?=\s*$)/u, ({
|
|
5411
|
+
}, source)], '']), (0, combinator_1.focus)(/^>>https?:\/\/(?:[[]|[^\p{C}\p{S}\p{P}\s])\S*(?=\s*$)/u, ({
|
|
5431
5412
|
source
|
|
5432
5413
|
}) => [[(0, dom_1.html)('a', {
|
|
5433
5414
|
class: 'anchor',
|
|
@@ -5454,8 +5435,9 @@ exports.quote = exports.syntax = void 0;
|
|
|
5454
5435
|
const parser_1 = __webpack_require__(6728);
|
|
5455
5436
|
const combinator_1 = __webpack_require__(2087);
|
|
5456
5437
|
const math_1 = __webpack_require__(8946);
|
|
5438
|
+
const autolink_1 = __webpack_require__(6051);
|
|
5457
5439
|
const source_1 = __webpack_require__(6743);
|
|
5458
|
-
const
|
|
5440
|
+
const autolink_2 = __webpack_require__(7185);
|
|
5459
5441
|
const dom_1 = __webpack_require__(3252);
|
|
5460
5442
|
exports.syntax = /^>+(?=[^\S\n])|^>(?=[^\s>])|^>+(?=[^\s>])(?![0-9a-z]+(?:-[0-9a-z]+)*(?![0-9A-Za-z@#:]))/;
|
|
5461
5443
|
exports.quote = (0, combinator_1.lazy)(() => (0, combinator_1.creation)(1, false, (0, combinator_1.block)((0, combinator_1.fmap)((0, combinator_1.validate)('>', (0, combinator_1.union)([(0, combinator_1.rewrite)((0, combinator_1.some)((0, combinator_1.validate)(new RegExp(exports.syntax.source.split('|')[0]), source_1.anyline)), qblock), (0, combinator_1.rewrite)((0, combinator_1.validate)(new RegExp(exports.syntax.source.split('|').slice(1).join('|')), source_1.anyline), (0, combinator_1.line)((0, combinator_1.union)([(0, source_1.str)(/^.+/)])))])), ns => [(0, dom_1.html)('span', ns.length > 1 ? {
|
|
@@ -5473,8 +5455,8 @@ const qblock = ({
|
|
|
5473
5455
|
source = source.replace(/\n$/, '');
|
|
5474
5456
|
const lines = source.match(/^.*\n?/mg);
|
|
5475
5457
|
const quotes = source.match(/^>+[^\S\n]/mg);
|
|
5476
|
-
const content = lines.reduce((acc, line,
|
|
5477
|
-
const nodes = (0, parser_1.eval)(
|
|
5458
|
+
const content = lines.reduce((acc, line, i) => acc + line.slice(quotes[i].length), '');
|
|
5459
|
+
const nodes = (0, parser_1.eval)(text({
|
|
5478
5460
|
source: content,
|
|
5479
5461
|
context
|
|
5480
5462
|
}), []);
|
|
@@ -5501,7 +5483,7 @@ const qblock = ({
|
|
|
5501
5483
|
nodes.unshift('');
|
|
5502
5484
|
return [nodes, ''];
|
|
5503
5485
|
};
|
|
5504
|
-
const text = (0, combinator_1.union)([math_1.math, autolink_1.autolink]);
|
|
5486
|
+
const text = (0, combinator_1.some)((0, combinator_1.line)((0, combinator_1.subsequence)([autolink_2.lineurl, (0, combinator_1.some)((0, combinator_1.union)([math_1.math, autolink_1.autolink, source_1.linebreak, source_1.unescsource]))])));
|
|
5505
5487
|
|
|
5506
5488
|
/***/ }),
|
|
5507
5489
|
|
|
@@ -5527,7 +5509,7 @@ exports.sidefence = (0, combinator_1.lazy)(() => (0, combinator_1.block)((0, com
|
|
|
5527
5509
|
})])));
|
|
5528
5510
|
const opener = /^(?=\|\|+(?:$|\s))/;
|
|
5529
5511
|
const unindent = source => source.replace(/(?<=^|\n)\|(?:[^\S\n]|(?=\|*(?:$|\s)))|\n$/g, '');
|
|
5530
|
-
const source = (0, combinator_1.lazy)(() => (0, combinator_1.fmap)((0, combinator_1.some)((0, combinator_1.creation)(1, false, (0, combinator_1.union)([(0, combinator_1.focus)(/^(?:\|\|+(?:[^\S\n][^\n]*)?(?:$|\n))+/, (0, combinator_1.convert)(unindent, source)), (0, combinator_1.rewrite)((0, combinator_1.some)(source_1.contentline, opener), (0, combinator_1.convert)(unindent, (0, combinator_1.fmap)(
|
|
5512
|
+
const source = (0, combinator_1.lazy)(() => (0, combinator_1.fmap)((0, combinator_1.some)((0, combinator_1.creation)(1, false, (0, combinator_1.union)([(0, combinator_1.focus)(/^(?:\|\|+(?:[^\S\n][^\n]*)?(?:$|\n))+/, (0, combinator_1.convert)(unindent, source)), (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))])))]))), ns => [(0, dom_1.html)('blockquote', ns)]));
|
|
5531
5513
|
|
|
5532
5514
|
/***/ }),
|
|
5533
5515
|
|
|
@@ -5595,7 +5577,7 @@ const visibility_1 = __webpack_require__(7618);
|
|
|
5595
5577
|
const array_1 = __webpack_require__(8112);
|
|
5596
5578
|
const dom_1 = __webpack_require__(3252);
|
|
5597
5579
|
exports.ulist = (0, combinator_1.lazy)(() => (0, combinator_1.block)((0, combinator_1.validate)(/^-(?=[^\S\n]|\n[^\S\n]*\S)/, (0, combinator_1.state)(8 /* State.media */, exports.ulist_))));
|
|
5598
|
-
exports.ulist_ = (0, combinator_1.lazy)(() => (0, combinator_1.block)((0, combinator_1.fmap)((0, combinator_1.validate)(/^-(?=$|\s)/, (0, combinator_1.some)((0, combinator_1.creation)(1, false, (0, combinator_1.union)([(0, inline_1.indexee)((0, combinator_1.fmap)((0, combinator_1.fallback)((0, combinator_1.inits)([(0, combinator_1.line)((0, combinator_1.open)(/^-(?:$|\s)/, (0, combinator_1.subsequence)([exports.checkbox, (0, visibility_1.trimBlank)((0, combinator_1.some)((0, combinator_1.union)([inline_1.indexer, inline_1.inline])))]), true)), (0, combinator_1.indent)((0, combinator_1.union)([exports.ulist_, olist_1.olist_, ilist_1.ilist_]))]), olist_1.invalid), ns => [(0, dom_1.html)('li', (0, dom_1.defrag)(fillFirstLine(ns)))]), true)])))), es => [format((0, dom_1.html)('ul', es))])));
|
|
5580
|
+
exports.ulist_ = (0, combinator_1.lazy)(() => (0, combinator_1.block)((0, combinator_1.fmap)((0, combinator_1.validate)(/^-(?=$|\s)/, (0, combinator_1.some)((0, combinator_1.creation)(1, false, (0, combinator_1.union)([(0, inline_1.indexee)((0, combinator_1.fmap)((0, combinator_1.fallback)((0, combinator_1.inits)([(0, combinator_1.line)((0, combinator_1.open)(/^-(?:$|\s)/, (0, combinator_1.subsequence)([exports.checkbox, (0, visibility_1.trimBlank)((0, visibility_1.visualize)((0, combinator_1.some)((0, combinator_1.union)([inline_1.indexer, inline_1.inline]))))]), true)), (0, combinator_1.indent)((0, combinator_1.union)([exports.ulist_, olist_1.olist_, ilist_1.ilist_]))]), olist_1.invalid), ns => [(0, dom_1.html)('li', (0, dom_1.defrag)(fillFirstLine(ns)))]), true)])))), es => [format((0, dom_1.html)('ul', es))])));
|
|
5599
5581
|
exports.checkbox = (0, combinator_1.creation)(1, false, (0, combinator_1.focus)(/^\[[xX ]\](?=$|\s)/, ({
|
|
5600
5582
|
source
|
|
5601
5583
|
}) => [[(0, dom_1.html)('span', {
|
|
@@ -6099,7 +6081,7 @@ const indexee_1 = __webpack_require__(1269);
|
|
|
6099
6081
|
const source_1 = __webpack_require__(6743);
|
|
6100
6082
|
const visibility_1 = __webpack_require__(7618);
|
|
6101
6083
|
const dom_1 = __webpack_require__(3252);
|
|
6102
|
-
exports.index = (0, combinator_1.lazy)(() => (0, combinator_1.validate)('[#', (0, combinator_1.fmap)((0, indexee_1.indexee)((0, combinator_1.surround)('[#', (0, combinator_1.constraint)(64 /* State.index */, false, (0, combinator_1.syntax)(128 /* Syntax.index */, 2, 1, 502 /* State.linkers */ | 8 /* State.media */, (0, visibility_1.startTight)((0, combinator_1.open)((0, source_1.stropt)(
|
|
6084
|
+
exports.index = (0, combinator_1.lazy)(() => (0, combinator_1.validate)('[#', (0, combinator_1.fmap)((0, indexee_1.indexee)((0, combinator_1.surround)('[#', (0, combinator_1.constraint)(64 /* State.index */, false, (0, combinator_1.syntax)(128 /* Syntax.index */, 2, 1, 502 /* State.linkers */ | 8 /* State.media */, (0, visibility_1.startTight)((0, combinator_1.open)((0, source_1.stropt)('|'), (0, visibility_1.trimBlankEnd)((0, combinator_1.some)((0, combinator_1.union)([signature, inline_1.inline]), ']', [[/^\\?\n/, 9], [']', 2]])), true)))), ']', false, ([, ns], rest) => [[(0, dom_1.html)('a', (0, dom_1.defrag)(ns))], rest])), ([el]) => [(0, dom_1.define)(el, {
|
|
6103
6085
|
id: el.id ? null : undefined,
|
|
6104
6086
|
class: 'index',
|
|
6105
6087
|
href: el.id ? `#${el.id}` : undefined
|
|
@@ -7376,8 +7358,8 @@ Object.defineProperty(exports, "__esModule", ({
|
|
|
7376
7358
|
exports.contentline = exports.emptyline = exports.anyline = void 0;
|
|
7377
7359
|
const combinator_1 = __webpack_require__(2087);
|
|
7378
7360
|
exports.anyline = (0, combinator_1.line)(() => [[], '']);
|
|
7379
|
-
exports.emptyline = (0, combinator_1.line)(i => (0, combinator_1.
|
|
7380
|
-
exports.contentline = (0, combinator_1.line)(i => !(0, combinator_1.
|
|
7361
|
+
exports.emptyline = (0, combinator_1.line)(i => (0, combinator_1.isBlank)(i.source) ? [[], ''] : undefined);
|
|
7362
|
+
exports.contentline = (0, combinator_1.line)(i => !(0, combinator_1.isBlank)(i.source) ? [[], ''] : undefined);
|
|
7381
7363
|
|
|
7382
7364
|
/***/ }),
|
|
7383
7365
|
|
|
@@ -7414,7 +7396,7 @@ function stropt(pattern) {
|
|
|
7414
7396
|
source
|
|
7415
7397
|
}) => {
|
|
7416
7398
|
if (source === '') return;
|
|
7417
|
-
return source.slice(0, pattern.length) === pattern ? [[pattern], source.slice(pattern.length)] :
|
|
7399
|
+
return source.slice(0, pattern.length) === pattern ? [[pattern], source.slice(pattern.length)] : [[''], source];
|
|
7418
7400
|
}) : (0, combinator_1.creation)(1, false, ({
|
|
7419
7401
|
source
|
|
7420
7402
|
}) => {
|
|
@@ -7529,7 +7511,7 @@ exports.unescsource = (0, combinator_1.creation)(1, false, ({
|
|
|
7529
7511
|
/***/ }),
|
|
7530
7512
|
|
|
7531
7513
|
/***/ 9437:
|
|
7532
|
-
/***/ ((__unused_webpack_module, exports) => {
|
|
7514
|
+
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
7533
7515
|
|
|
7534
7516
|
"use strict";
|
|
7535
7517
|
|
|
@@ -7537,7 +7519,12 @@ exports.unescsource = (0, combinator_1.creation)(1, false, ({
|
|
|
7537
7519
|
Object.defineProperty(exports, "__esModule", ({
|
|
7538
7520
|
value: true
|
|
7539
7521
|
}));
|
|
7540
|
-
exports.stringify = void 0;
|
|
7522
|
+
exports.stringify = exports.format = void 0;
|
|
7523
|
+
const combinator_1 = __webpack_require__(2087);
|
|
7524
|
+
function format(parser) {
|
|
7525
|
+
return (0, combinator_1.convert)(source => source.replace(/(?<=^!?)https?:\/\/(?:[[]|[^\p{C}\p{S}\p{P}\s])\S*(?=[^\S\n]*(?:$|\n))/gm, '{ $& }'), parser);
|
|
7526
|
+
}
|
|
7527
|
+
exports.format = format;
|
|
7541
7528
|
function stringify(nodes) {
|
|
7542
7529
|
let acc = '';
|
|
7543
7530
|
for (let i = 0; i < nodes.length; ++i) {
|
|
@@ -7569,12 +7556,13 @@ const parser_1 = __webpack_require__(6728);
|
|
|
7569
7556
|
const combinator_1 = __webpack_require__(2087);
|
|
7570
7557
|
const htmlentity_1 = __webpack_require__(1562);
|
|
7571
7558
|
const source_1 = __webpack_require__(6743);
|
|
7559
|
+
const util_1 = __webpack_require__(9437);
|
|
7572
7560
|
const normalize_1 = __webpack_require__(185);
|
|
7573
7561
|
const memoize_1 = __webpack_require__(1808);
|
|
7574
7562
|
const array_1 = __webpack_require__(8112);
|
|
7575
7563
|
function visualize(parser) {
|
|
7576
7564
|
const blankline = new RegExp(/^(?:\\$|\\?[^\S\n]|&IHN;|<wbr[^\S\n]*>)+$/.source.replace('IHN', `(?:${normalize_1.invisibleHTMLEntityNames.join('|')})`), 'gm');
|
|
7577
|
-
return (0, combinator_1.union)([(0, combinator_1.convert)(source => source.replace(blankline, line => line.replace(/[\\&<]/g, '\x1B$&')), (0, combinator_1.verify)(parser, (ns, rest, context) => !rest && hasVisible(ns, context))), (0, combinator_1.some)((0, combinator_1.union)([source_1.linebreak, source_1.unescsource]))]);
|
|
7565
|
+
return (0, combinator_1.union)([(0, combinator_1.convert)(source => source.replace(blankline, line => line.replace(/[\\&<]/g, '\x1B$&')), (0, combinator_1.verify)((0, util_1.format)(parser), (ns, rest, context) => !rest && hasVisible(ns, context))), (0, combinator_1.some)((0, combinator_1.union)([source_1.linebreak, source_1.unescsource]))]);
|
|
7578
7566
|
}
|
|
7579
7567
|
exports.visualize = visualize;
|
|
7580
7568
|
function hasVisible(nodes, {
|
|
@@ -8201,7 +8189,7 @@ Object.defineProperty(exports, "__esModule", ({
|
|
|
8201
8189
|
exports.quote = void 0;
|
|
8202
8190
|
const parser_1 = __webpack_require__(6728);
|
|
8203
8191
|
const cite_1 = __webpack_require__(6315);
|
|
8204
|
-
|
|
8192
|
+
//import { url } from '../parser/inline/autolink/url';
|
|
8205
8193
|
function quote(anchor, range) {
|
|
8206
8194
|
if ((0, parser_1.exec)((0, cite_1.cite)({
|
|
8207
8195
|
source: `>>${anchor}`,
|
|
@@ -8215,8 +8203,15 @@ function quote(anchor, range) {
|
|
|
8215
8203
|
switch (true) {
|
|
8216
8204
|
case el.matches('code'):
|
|
8217
8205
|
case el.matches('.math'):
|
|
8218
|
-
|
|
8206
|
+
el.replaceWith(el.getAttribute('data-src'));
|
|
8219
8207
|
continue;
|
|
8208
|
+
//case el.matches('.url'):
|
|
8209
|
+
// if (exec(url({ source: el.getAttribute('href')!, context: {} })) === '') continue;
|
|
8210
|
+
// el.replaceWith(
|
|
8211
|
+
// /[\s{}]/.test(el.getAttribute('href')!)
|
|
8212
|
+
// ? `{ ${el.getAttribute('href')} }`
|
|
8213
|
+
// : `{${el.getAttribute('href')}}`);
|
|
8214
|
+
// continue;
|
|
8220
8215
|
case el.matches('.media'):
|
|
8221
8216
|
el.replaceWith(/[\s{}]/.test(el.getAttribute('data-src')) ? `!{ ${el.getAttribute('data-src')} }` : `!{${el.getAttribute('data-src')}}`);
|
|
8222
8217
|
continue;
|
package/markdown.d.ts
CHANGED
|
@@ -598,8 +598,13 @@ export namespace MarkdownParser {
|
|
|
598
598
|
export interface TextParser extends
|
|
599
599
|
Block<'reply/quote/text'>,
|
|
600
600
|
Parser<string | HTMLElement, Context, [
|
|
601
|
-
|
|
602
|
-
|
|
601
|
+
AutolinkParser.LineUrlParser,
|
|
602
|
+
Parser<string | HTMLElement, Context, [
|
|
603
|
+
InlineParser.MathParser,
|
|
604
|
+
InlineParser.AutolinkParser,
|
|
605
|
+
SourceParser.LinebreakParser,
|
|
606
|
+
SourceParser.UnescapableSourceParser,
|
|
607
|
+
]>,
|
|
603
608
|
]> {
|
|
604
609
|
}
|
|
605
610
|
export interface PlaceholderParser extends
|
|
@@ -1171,11 +1176,23 @@ export namespace MarkdownParser {
|
|
|
1171
1176
|
export interface AutolinkParser extends
|
|
1172
1177
|
Markdown<'autolink'>,
|
|
1173
1178
|
Parser<string | HTMLElement, Context, [
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1179
|
+
AutolinkParser.LineUrlParser,
|
|
1180
|
+
Parser<string | HTMLElement, Context, [
|
|
1181
|
+
InlineParser.AutolinkParser,
|
|
1182
|
+
SourceParser.LinebreakParser,
|
|
1183
|
+
SourceParser.UnescapableSourceParser,
|
|
1184
|
+
]>,
|
|
1177
1185
|
]> {
|
|
1178
1186
|
}
|
|
1187
|
+
export namespace AutolinkParser {
|
|
1188
|
+
export interface LineUrlParser extends
|
|
1189
|
+
Markdown<'autolink/lineurl'>,
|
|
1190
|
+
Parser<string | HTMLElement, Context, [
|
|
1191
|
+
SourceParser.StrParser,
|
|
1192
|
+
InlineParser.LinkParser,
|
|
1193
|
+
]> {
|
|
1194
|
+
}
|
|
1195
|
+
}
|
|
1179
1196
|
export namespace SourceParser {
|
|
1180
1197
|
interface Source<T extends string> extends Markdown<`source/${T}`> { }
|
|
1181
1198
|
export interface TextParser extends
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "securemark",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.268.0",
|
|
4
4
|
"description": "Secure markdown renderer working on browsers for user input data.",
|
|
5
5
|
"private": false,
|
|
6
6
|
"homepage": "https://github.com/falsandtru/securemark",
|
|
@@ -34,13 +34,13 @@
|
|
|
34
34
|
"@types/mocha": "10.0.1",
|
|
35
35
|
"@types/power-assert": "1.5.8",
|
|
36
36
|
"@types/prismjs": "1.26.0",
|
|
37
|
-
"@typescript-eslint/parser": "^5.
|
|
37
|
+
"@typescript-eslint/parser": "^5.52.0",
|
|
38
38
|
"babel-loader": "^9.1.2",
|
|
39
39
|
"babel-plugin-unassert": "^3.2.0",
|
|
40
40
|
"concurrently": "^7.6.0",
|
|
41
|
-
"eslint": "^8.
|
|
42
|
-
"eslint-plugin-redos": "^4.4.
|
|
43
|
-
"eslint-webpack-plugin": "^
|
|
41
|
+
"eslint": "^8.34.0",
|
|
42
|
+
"eslint-plugin-redos": "^4.4.5",
|
|
43
|
+
"eslint-webpack-plugin": "^4.0.0",
|
|
44
44
|
"glob": "^8.1.0",
|
|
45
45
|
"karma": "^6.4.1",
|
|
46
46
|
"karma-chrome-launcher": "^3.1.1",
|
|
@@ -49,12 +49,12 @@
|
|
|
49
49
|
"karma-mocha": "^2.0.1",
|
|
50
50
|
"karma-power-assert": "^1.0.0",
|
|
51
51
|
"mocha": "^10.2.0",
|
|
52
|
-
"npm-check-updates": "^16.
|
|
52
|
+
"npm-check-updates": "^16.7.4",
|
|
53
53
|
"semver": "^7.3.8",
|
|
54
54
|
"spica": "0.0.719",
|
|
55
55
|
"ts-loader": "^9.4.2",
|
|
56
56
|
"typed-dom": "^0.0.315",
|
|
57
|
-
"typescript": "4.9.
|
|
57
|
+
"typescript": "4.9.5",
|
|
58
58
|
"webpack": "^5.75.0",
|
|
59
59
|
"webpack-cli": "^5.0.1",
|
|
60
60
|
"webpack-merge": "^5.8.0"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Parser, exec } from '../../data/parser';
|
|
2
2
|
import { Memo } from '../../data/parser/context/memo';
|
|
3
|
-
import { firstline,
|
|
3
|
+
import { firstline, isBlank } from './line';
|
|
4
4
|
|
|
5
5
|
export function block<P extends Parser<unknown>>(parser: P, separation?: boolean): P;
|
|
6
6
|
export function block<T>(parser: Parser<T>, separation = true): Parser<T> {
|
|
@@ -11,7 +11,7 @@ export function block<T>(parser: Parser<T>, separation = true): Parser<T> {
|
|
|
11
11
|
const result = parser({ source, context });
|
|
12
12
|
if (result === undefined) return;
|
|
13
13
|
const rest = exec(result);
|
|
14
|
-
if (separation && !
|
|
14
|
+
if (separation && !isBlank(firstline(rest))) return;
|
|
15
15
|
assert(rest === '' || source[source.length - rest.length - 1] === '\n');
|
|
16
16
|
return rest === '' || source[source.length - rest.length - 1] === '\n'
|
|
17
17
|
? result
|
|
@@ -14,7 +14,7 @@ export function line<T>(parser: Parser<T>): Parser<T> {
|
|
|
14
14
|
assert(check(line, result));
|
|
15
15
|
context.offset -= source.length - line.length;
|
|
16
16
|
if (result === undefined) return;
|
|
17
|
-
return
|
|
17
|
+
return isBlank(exec(result))
|
|
18
18
|
? [eval(result), source.slice(line.length)]
|
|
19
19
|
: undefined;
|
|
20
20
|
};
|
|
@@ -32,7 +32,7 @@ export function firstline(source: string): string {
|
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
export function
|
|
35
|
+
export function isBlank(line: string): boolean {
|
|
36
36
|
return line === ''
|
|
37
37
|
|| line === '\n'
|
|
38
38
|
|| line.trimStart() === '';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Parser, Ctx } from '../../data/parser';
|
|
2
|
-
import { firstline,
|
|
2
|
+
import { firstline, isBlank } from '../constraint/line';
|
|
3
3
|
import { unshift } from 'spica/array';
|
|
4
4
|
|
|
5
5
|
export function fence<C extends Ctx, D extends Parser<unknown, C>[]>(opener: RegExp, limit: number, separation = true): Parser<string, C, D> {
|
|
@@ -13,20 +13,20 @@ export function fence<C extends Ctx, D extends Parser<unknown, C>[]>(opener: Reg
|
|
|
13
13
|
if (matches[0].indexOf(delim, delim.length) !== -1) return;
|
|
14
14
|
let rest = source.slice(matches[0].length);
|
|
15
15
|
// Prevent annoying parsing in editing.
|
|
16
|
-
if (
|
|
16
|
+
if (isBlank(firstline(rest)) && firstline(rest.slice(firstline(rest).length)).trimEnd() !== delim) return;
|
|
17
17
|
let block = '';
|
|
18
18
|
let closer = '';
|
|
19
19
|
let overflow = '';
|
|
20
20
|
for (let count = 1; ; ++count) {
|
|
21
21
|
if (rest === '') break;
|
|
22
22
|
const line = firstline(rest);
|
|
23
|
-
if ((closer || count > limit + 1) &&
|
|
23
|
+
if ((closer || count > limit + 1) && isBlank(line)) break;
|
|
24
24
|
if(closer) {
|
|
25
25
|
overflow += line;
|
|
26
26
|
}
|
|
27
27
|
if (!closer && count <= limit + 1 && line.slice(0, delim.length) === delim && line.trimEnd() === delim) {
|
|
28
28
|
closer = line;
|
|
29
|
-
if (
|
|
29
|
+
if (isBlank(firstline(rest.slice(line.length)))) {
|
|
30
30
|
rest = rest.slice(line.length);
|
|
31
31
|
break;
|
|
32
32
|
}
|
package/src/parser/api/bind.ts
CHANGED
|
@@ -26,7 +26,7 @@ export function bind(target: DocumentFragment | HTMLElement | ShadowRoot, settin
|
|
|
26
26
|
host: settings.host ?? new ReadonlyURL(location.pathname, location.origin),
|
|
27
27
|
memo: new Memo({ targets: State.backtrackers }),
|
|
28
28
|
};
|
|
29
|
-
if (context.id?.match(/[^0-9a-z
|
|
29
|
+
if (context.id?.match(/[^0-9a-z/-]/i)) throw new Error('Invalid ID: ID must be alphanumeric');
|
|
30
30
|
if (context.host?.origin === 'null') throw new Error(`Invalid host: ${context.host.href}`);
|
|
31
31
|
assert(!settings.id);
|
|
32
32
|
type Block = readonly [segment: string, blocks: readonly HTMLElement[], url: string];
|
package/src/parser/api/parse.ts
CHANGED
|
@@ -32,7 +32,7 @@ export function parse(source: string, opts: Options = {}, context?: MarkdownPars
|
|
|
32
32
|
},
|
|
33
33
|
memo: new Memo({ targets: State.backtrackers }),
|
|
34
34
|
};
|
|
35
|
-
if (context.id?.match(/[^0-9a-z
|
|
35
|
+
if (context.id?.match(/[^0-9a-z/-]/i)) throw new Error('Invalid ID: ID must be alphanumeric');
|
|
36
36
|
if (context.host?.origin === 'null') throw new Error(`Invalid host: ${context.host.href}`);
|
|
37
37
|
const node = frag();
|
|
38
38
|
let index = 0;
|
package/src/parser/autolink.ts
CHANGED
|
@@ -1,28 +1,21 @@
|
|
|
1
1
|
import { MarkdownParser } from '../../markdown';
|
|
2
|
-
import { union, lazy } from '../combinator';
|
|
2
|
+
import { union, tails, subsequence, some, line, focus, lazy } from '../combinator';
|
|
3
|
+
import { link } from './inline/link';
|
|
3
4
|
import { autolink as autolink_ } from './inline/autolink';
|
|
4
|
-
import { linebreak, unescsource } from './source';
|
|
5
|
+
import { linebreak, unescsource, str } from './source';
|
|
6
|
+
import { format } from './util';
|
|
5
7
|
|
|
6
8
|
export import AutolinkParser = MarkdownParser.AutolinkParser;
|
|
7
9
|
|
|
8
|
-
const
|
|
10
|
+
export const autolink: AutolinkParser = lazy(() => some(line(subsequence([
|
|
11
|
+
lineurl,
|
|
12
|
+
some(union([
|
|
13
|
+
autolink_,
|
|
14
|
+
linebreak,
|
|
15
|
+
unescsource,
|
|
16
|
+
])),
|
|
17
|
+
]))));
|
|
9
18
|
|
|
10
|
-
export const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
const i = source.search(delimiter);
|
|
14
|
-
switch (i) {
|
|
15
|
-
case -1:
|
|
16
|
-
return [[source], ''];
|
|
17
|
-
case 0:
|
|
18
|
-
return parser({ source, context });
|
|
19
|
-
default:
|
|
20
|
-
return [[source.slice(0, i)], source.slice(i)];
|
|
21
|
-
}
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
const parser: AutolinkParser = lazy(() => union([
|
|
25
|
-
autolink_,
|
|
26
|
-
linebreak,
|
|
27
|
-
unescsource
|
|
28
|
-
]));
|
|
19
|
+
export const lineurl: AutolinkParser.LineUrlParser = lazy(() => focus(
|
|
20
|
+
/^!?https?:\/\/\S+(?=[^\S\n]*(?:$|\n))/,
|
|
21
|
+
format(tails([str('!'), link]))));
|
|
@@ -25,7 +25,7 @@ const source: BlockquoteParser.SourceParser = lazy(() => fmap(
|
|
|
25
25
|
convert(unindent, source)),
|
|
26
26
|
rewrite(
|
|
27
27
|
some(contentline, opener),
|
|
28
|
-
convert(unindent, fmap(
|
|
28
|
+
convert(unindent, fmap(autolink, ns => [html('pre', defrag(ns))]))),
|
|
29
29
|
]))),
|
|
30
30
|
ns => [html('blockquote', ns)]));
|
|
31
31
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { CodeBlockParser } from '../block';
|
|
2
2
|
import { eval } from '../../combinator/data/parser';
|
|
3
|
-
import {
|
|
3
|
+
import { block, validate, fence, clear, fmap } from '../../combinator';
|
|
4
4
|
import { autolink } from '../autolink';
|
|
5
5
|
import { html, defrag } from 'typed-dom/dom';
|
|
6
6
|
|
|
@@ -69,6 +69,6 @@ export const codeblock: CodeBlockParser = block(validate('```', fmap(
|
|
|
69
69
|
params.lang
|
|
70
70
|
? context.caches?.code?.get(`${params.lang ?? ''}\n${body.slice(0, -1)}`)?.cloneNode(true).childNodes ||
|
|
71
71
|
body.slice(0, -1) || undefined
|
|
72
|
-
: defrag(eval(
|
|
72
|
+
: defrag(eval(autolink({ source: body.slice(0, -1), context }), [])));
|
|
73
73
|
return [el];
|
|
74
74
|
})));
|
|
@@ -37,8 +37,8 @@ describe('Unit: parser/block/olist', () => {
|
|
|
37
37
|
// pending
|
|
38
38
|
assert.deepStrictEqual(inspect(parser('1. ')), [['<ol><li></li></ol>'], '']);
|
|
39
39
|
// filled
|
|
40
|
-
assert.deepStrictEqual(inspect(parser('1. \\')), [['<ol><li
|
|
41
|
-
assert.deepStrictEqual(inspect(parser('1. \\\n')), [['<ol><li
|
|
40
|
+
assert.deepStrictEqual(inspect(parser('1. \\')), [['<ol><li id="index::\\">\\</li></ol>'], '']);
|
|
41
|
+
assert.deepStrictEqual(inspect(parser('1. \\\n')), [['<ol><li id="index::\\">\\</li></ol>'], '']);
|
|
42
42
|
assert.deepStrictEqual(inspect(parser('1. -')), [['<ol><li id="index::-">-</li></ol>'], '']);
|
|
43
43
|
assert.deepStrictEqual(inspect(parser('1. -\n')), [['<ol><li id="index::-">-</li></ol>'], '']);
|
|
44
44
|
// pending
|
|
@@ -6,7 +6,7 @@ import { ilist_ } from './ilist';
|
|
|
6
6
|
import { inline, indexee, indexer } from '../inline';
|
|
7
7
|
import { contentline } from '../source';
|
|
8
8
|
import { State } from '../context';
|
|
9
|
-
import { trimBlank } from '../visibility';
|
|
9
|
+
import { visualize, trimBlank } from '../visibility';
|
|
10
10
|
import { memoize } from 'spica/memoize';
|
|
11
11
|
import { shift } from 'spica/array';
|
|
12
12
|
import { html, define, defrag } from 'typed-dom/dom';
|
|
@@ -37,7 +37,7 @@ const list = (type: string, form: string): OListParser.ListParser => fmap(
|
|
|
37
37
|
some(creation(1, false, union([
|
|
38
38
|
indexee(fmap(fallback(
|
|
39
39
|
inits([
|
|
40
|
-
line(open(heads[form], subsequence([checkbox, trimBlank(some(union([indexer, inline])))]), true)),
|
|
40
|
+
line(open(heads[form], subsequence([checkbox, trimBlank(visualize(some(union([indexer, inline]))))]), true)),
|
|
41
41
|
indent(union([ulist_, olist_, ilist_])),
|
|
42
42
|
]),
|
|
43
43
|
invalid),
|
|
@@ -30,6 +30,9 @@ describe('Unit: parser/block/paragraph', () => {
|
|
|
30
30
|
assert.deepStrictEqual(inspect(parser('_a\n<wbr>_\nb')), [['<p>_a<br><wbr>_<br>b</p>'], '']);
|
|
31
31
|
assert.deepStrictEqual(inspect(parser('*a\n<wbr>*\nb')), [['<p>*a<br><wbr>*<br>b</p>'], '']);
|
|
32
32
|
assert.deepStrictEqual(inspect(parser('==a\n<wbr>==\nb')), [['<p>==a<br><wbr>==<br>b</p>'], '']);
|
|
33
|
+
assert.deepStrictEqual(inspect(parser('http://host#!')), [['<p><a class="url" href="http://host#!" target="_blank">http://host#!</a></p>'], '']);
|
|
34
|
+
assert.deepStrictEqual(inspect(parser('a\nhttp://host#\\ \nb')), [['<p>a<br><a class="url" href="http://host#\\" target="_blank">http://host#\\</a><br>b</p>'], '']);
|
|
35
|
+
assert.deepStrictEqual(inspect(parser('!http://host#!')), [['<p><a href="http://host#!" target="_blank"><img class="media" data-src="http://host#!" alt=""></a></p>'], '']);
|
|
33
36
|
assert.deepStrictEqual(inspect(parser('\ta')), [['<p>\ta</p>'], '']);
|
|
34
37
|
});
|
|
35
38
|
|
|
@@ -14,8 +14,7 @@ export const cite: ReplyParser.CiteParser = creation(1, false, line(fmap(validat
|
|
|
14
14
|
// リンクの実装は後で検討
|
|
15
15
|
focus(/^>>\.(?=\s*$)/, () => [[html('a', { class: 'anchor' }, '>>.')], '']),
|
|
16
16
|
focus(/^>>#\S*(?=\s*$)/, ({ source }) => [[html('a', { class: 'anchor' }, source)], '']),
|
|
17
|
-
|
|
18
|
-
focus(/^>>https?:\/\/[^\p{C}\p{S}\p{P}\s]\S*(?=\s*$)/u, ({ source }) => [[html('a', { class: 'anchor', href: source.slice(2).trimEnd(), target: '_blank' }, source)], '']),
|
|
17
|
+
focus(/^>>https?:\/\/(?:[[]|[^\p{C}\p{S}\p{P}\s])\S*(?=\s*$)/u, ({ source }) => [[html('a', { class: 'anchor', href: source.slice(2).trimEnd(), target: '_blank' }, source)], '']),
|
|
19
18
|
]),
|
|
20
19
|
]))),
|
|
21
20
|
([el, quotes = '']: [HTMLElement, string?]) => [
|
|
@@ -55,6 +55,9 @@ describe('Unit: parser/block/reply/quote', () => {
|
|
|
55
55
|
assert.deepStrictEqual(inspect(parser('> $-a, $-b')), [['<span class="quote">> $-a, $-b</span>', '<br>'], '']);
|
|
56
56
|
assert.deepStrictEqual(inspect(parser('> $a=b$')), [['<span class="quote">> <span class="math" translate="no" data-src="$a=b$">$a=b$</span></span>', '<br>'], '']);
|
|
57
57
|
assert.deepStrictEqual(inspect(parser('> ${a}$')), [['<span class="quote">> <span class="math" translate="no" data-src="${a}$">${a}$</span></span>', '<br>'], '']);
|
|
58
|
+
assert.deepStrictEqual(inspect(parser('> http://host#!')), [['<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>'], '']);
|
|
58
61
|
});
|
|
59
62
|
|
|
60
63
|
});
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { ReplyParser } from '../../block';
|
|
2
2
|
import { eval } from '../../../combinator/data/parser';
|
|
3
|
-
import { union, some, creation, block, line, validate, rewrite, lazy, fmap } from '../../../combinator';
|
|
3
|
+
import { union, subsequence, some, creation, block, line, validate, rewrite, lazy, fmap } from '../../../combinator';
|
|
4
4
|
import { math } from '../../inline/math';
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
5
|
+
import { autolink } from '../../inline/autolink';
|
|
6
|
+
import { linebreak, unescsource, str, anyline } from '../../source';
|
|
7
|
+
import { lineurl } from '../../autolink';
|
|
7
8
|
import { html, defrag } from 'typed-dom/dom';
|
|
8
9
|
|
|
9
10
|
export const syntax = /^>+(?=[^\S\n])|^>(?=[^\s>])|^>+(?=[^\s>])(?![0-9a-z]+(?:-[0-9a-z]+)*(?![0-9A-Za-z@#:]))/;
|
|
@@ -40,8 +41,8 @@ const qblock: ReplyParser.QuoteParser.BlockParser = ({ source, context }) => {
|
|
|
40
41
|
const quotes = source.match(/^>+[^\S\n]/mg)!;
|
|
41
42
|
assert(quotes);
|
|
42
43
|
assert(quotes.length > 0);
|
|
43
|
-
const content = lines.reduce((acc, line,
|
|
44
|
-
const nodes = eval(
|
|
44
|
+
const content = lines.reduce((acc, line, i) => acc + line.slice(quotes[i].length), '');
|
|
45
|
+
const nodes = eval(text({ source: content, context }), []);
|
|
45
46
|
nodes.unshift(quotes.shift()!);
|
|
46
47
|
for (let i = 0; i < nodes.length; ++i) {
|
|
47
48
|
const child = nodes[i] as string | Text | Element;
|
|
@@ -71,7 +72,12 @@ const qblock: ReplyParser.QuoteParser.BlockParser = ({ source, context }) => {
|
|
|
71
72
|
return [nodes, ''];
|
|
72
73
|
};
|
|
73
74
|
|
|
74
|
-
const text: ReplyParser.QuoteParser.TextParser =
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
75
|
+
const text: ReplyParser.QuoteParser.TextParser = some(line(subsequence([
|
|
76
|
+
lineurl,
|
|
77
|
+
some(union([
|
|
78
|
+
math, // quote補助関数が残した数式をパースする。他の構文で数式を残す場合はソーステキストを直接使用する。
|
|
79
|
+
autolink,
|
|
80
|
+
linebreak,
|
|
81
|
+
unescsource,
|
|
82
|
+
])),
|
|
83
|
+
])));
|
|
@@ -26,6 +26,6 @@ const source: SidefenceParser.SourceParser = lazy(() => fmap(
|
|
|
26
26
|
convert(unindent, source)),
|
|
27
27
|
rewrite(
|
|
28
28
|
some(contentline, opener),
|
|
29
|
-
convert(unindent, fmap(
|
|
29
|
+
convert(unindent, fmap(autolink, ns => [html('pre', defrag(ns))]))),
|
|
30
30
|
]))),
|
|
31
31
|
ns => [html('blockquote', ns)]));
|
|
@@ -26,8 +26,8 @@ describe('Unit: parser/block/ulist', () => {
|
|
|
26
26
|
// pending
|
|
27
27
|
assert.deepStrictEqual(inspect(parser('- ')), [['<ul><li></li></ul>'], '']);
|
|
28
28
|
// filled
|
|
29
|
-
assert.deepStrictEqual(inspect(parser('- \\')), [['<ul><li
|
|
30
|
-
assert.deepStrictEqual(inspect(parser('- \\\n')), [['<ul><li
|
|
29
|
+
assert.deepStrictEqual(inspect(parser('- \\')), [['<ul><li id="index::\\">\\</li></ul>'], '']);
|
|
30
|
+
assert.deepStrictEqual(inspect(parser('- \\\n')), [['<ul><li id="index::\\">\\</li></ul>'], '']);
|
|
31
31
|
assert.deepStrictEqual(inspect(parser('- -')), [['<ul><li id="index::-">-</li></ul>'], '']);
|
|
32
32
|
assert.deepStrictEqual(inspect(parser('- -\n')), [['<ul><li id="index::-">-</li></ul>'], '']);
|
|
33
33
|
});
|
|
@@ -4,7 +4,7 @@ import { olist_, invalid } from './olist';
|
|
|
4
4
|
import { ilist_ } from './ilist';
|
|
5
5
|
import { inline, indexer, indexee } from '../inline';
|
|
6
6
|
import { State } from '../context';
|
|
7
|
-
import { trimBlank } from '../visibility';
|
|
7
|
+
import { visualize, trimBlank } from '../visibility';
|
|
8
8
|
import { unshift } from 'spica/array';
|
|
9
9
|
import { html, defrag } from 'typed-dom/dom';
|
|
10
10
|
|
|
@@ -18,7 +18,7 @@ export const ulist_: UListParser = lazy(() => block(fmap(validate(
|
|
|
18
18
|
some(creation(1, false, union([
|
|
19
19
|
indexee(fmap(fallback(
|
|
20
20
|
inits([
|
|
21
|
-
line(open(/^-(?:$|\s)/, subsequence([checkbox, trimBlank(some(union([indexer, inline])))]), true)),
|
|
21
|
+
line(open(/^-(?:$|\s)/, subsequence([checkbox, trimBlank(visualize(some(union([indexer, inline]))))]), true)),
|
|
22
22
|
indent(union([ulist_, olist_, ilist_])),
|
|
23
23
|
]),
|
|
24
24
|
invalid),
|
|
@@ -14,7 +14,7 @@ export const index: IndexParser = lazy(() => validate('[#', fmap(indexee(surroun
|
|
|
14
14
|
constraint(State.index, false,
|
|
15
15
|
syntax(Syntax.index, 2, 1, State.linkers | State.media,
|
|
16
16
|
startTight(
|
|
17
|
-
open(stropt(
|
|
17
|
+
open(stropt('|'), trimBlankEnd(some(union([
|
|
18
18
|
signature,
|
|
19
19
|
inline,
|
|
20
20
|
]), ']', [[/^\\?\n/, 9], [']', 2]])), true)))),
|
|
@@ -9,7 +9,7 @@ export function indexee(parser: Parser<HTMLElement, MarkdownParser.Context>, opt
|
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
export function identity(id: string | undefined, text: string, name: 'index' | 'mark' = 'index'): string | undefined {
|
|
12
|
-
assert(!id?.match(/[^0-9a-z
|
|
12
|
+
assert(!id?.match(/[^0-9a-z/-]/i));
|
|
13
13
|
assert(!text.includes('\n'));
|
|
14
14
|
if (id === '') return undefined;
|
|
15
15
|
text &&= text.trim().replace(/\s+/g, '_');
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AnyLineParser, EmptyLineParser, ContentLineParser } from '../source';
|
|
2
|
-
import { line,
|
|
2
|
+
import { line, isBlank } from '../../combinator';
|
|
3
3
|
|
|
4
4
|
export const anyline: AnyLineParser = line(() => [[], '']);
|
|
5
|
-
export const emptyline: EmptyLineParser = line(i =>
|
|
6
|
-
export const contentline: ContentLineParser = line(i => !
|
|
5
|
+
export const emptyline: EmptyLineParser = line(i => isBlank(i.source) ? [[], ''] : undefined);
|
|
6
|
+
export const contentline: ContentLineParser = line(i => !isBlank(i.source) ? [[], ''] : undefined);
|
package/src/parser/source/str.ts
CHANGED
|
@@ -31,7 +31,7 @@ export function stropt(pattern: string | RegExp): Parser<string, Context<StrPars
|
|
|
31
31
|
if (source === '') return;
|
|
32
32
|
return source.slice(0, pattern.length) === pattern
|
|
33
33
|
? [[pattern], source.slice(pattern.length)]
|
|
34
|
-
:
|
|
34
|
+
: [[''], source];
|
|
35
35
|
})
|
|
36
36
|
: creation(1, false, ({ source }) => {
|
|
37
37
|
if (source === '') return;
|
package/src/parser/util.ts
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
import { Parser } from '../combinator/data/parser';
|
|
2
|
+
import { convert } from '../combinator';
|
|
3
|
+
|
|
4
|
+
export function format<P extends Parser<HTMLElement | string>>(parser: P): P;
|
|
5
|
+
export function format<T extends HTMLElement | string>(parser: Parser<T>): Parser<T> {
|
|
6
|
+
return convert(
|
|
7
|
+
source => source.replace(/(?<=^!?)https?:\/\/(?:[[]|[^\p{C}\p{S}\p{P}\s])\S*(?=[^\S\n]*(?:$|\n))/gm, '{ $& }'),
|
|
8
|
+
parser);
|
|
9
|
+
}
|
|
10
|
+
|
|
1
11
|
export function stringify(nodes: readonly (HTMLElement | string)[]): string {
|
|
2
12
|
let acc = '';
|
|
3
13
|
for (let i = 0; i < nodes.length; ++i) {
|
package/src/parser/visibility.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { union, some, verify, convert, fmap } from '../combinator';
|
|
|
4
4
|
import { unsafehtmlentity } from './inline/htmlentity';
|
|
5
5
|
import { linebreak, unescsource } from './source';
|
|
6
6
|
import { State } from './context';
|
|
7
|
+
import { format } from './util';
|
|
7
8
|
import { invisibleHTMLEntityNames } from './api/normalize';
|
|
8
9
|
import { reduce } from 'spica/memoize';
|
|
9
10
|
import { push } from 'spica/array';
|
|
@@ -16,7 +17,7 @@ export function visualize<T extends HTMLElement | string>(parser: Parser<T>): Pa
|
|
|
16
17
|
return union([
|
|
17
18
|
convert(
|
|
18
19
|
source => source.replace(blankline, line => line.replace(/[\\&<]/g, '\x1B$&')),
|
|
19
|
-
verify(parser, (ns, rest, context) => !rest && hasVisible(ns, context))),
|
|
20
|
+
verify(format(parser), (ns, rest, context) => !rest && hasVisible(ns, context))),
|
|
20
21
|
some(union([linebreak, unescsource])),
|
|
21
22
|
]);
|
|
22
23
|
}
|
package/src/util/quote.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { exec } from '../combinator/data/parser';
|
|
2
2
|
import { cite } from '../parser/block/reply/cite';
|
|
3
|
-
import {
|
|
3
|
+
//import { url } from '../parser/inline/autolink/url';
|
|
4
4
|
|
|
5
5
|
export function quote(anchor: string, range: Range): string {
|
|
6
6
|
if (exec(cite({ source: `>>${anchor}`, context: {} })) !== '') throw new Error(`Invalid anchor: ${anchor}`);
|
|
@@ -13,8 +13,15 @@ export function quote(anchor: string, range: Range): string {
|
|
|
13
13
|
switch (true) {
|
|
14
14
|
case el.matches('code'):
|
|
15
15
|
case el.matches('.math'):
|
|
16
|
-
|
|
16
|
+
el.replaceWith(el.getAttribute('data-src')!);
|
|
17
17
|
continue;
|
|
18
|
+
//case el.matches('.url'):
|
|
19
|
+
// if (exec(url({ source: el.getAttribute('href')!, context: {} })) === '') continue;
|
|
20
|
+
// el.replaceWith(
|
|
21
|
+
// /[\s{}]/.test(el.getAttribute('href')!)
|
|
22
|
+
// ? `{ ${el.getAttribute('href')} }`
|
|
23
|
+
// : `{${el.getAttribute('href')}}`);
|
|
24
|
+
// continue;
|
|
18
25
|
case el.matches('.media'):
|
|
19
26
|
el.replaceWith(
|
|
20
27
|
/[\s{}]/.test(el.getAttribute('data-src')!)
|