securemark 0.260.4 → 0.260.5
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 +75 -43
- package/markdown.d.ts +2 -2
- package/package.json +1 -1
- package/src/combinator/data/parser/context/memo.ts +4 -0
- package/src/combinator/data/parser/context.ts +25 -16
- package/src/combinator/data/parser.ts +0 -1
- package/src/parser/api/bind.ts +2 -1
- package/src/parser/api/parse.ts +2 -1
- package/src/parser/context.ts +8 -7
- package/src/parser/inline/autolink.ts +1 -1
- package/src/parser/inline/extension/index.ts +1 -1
- package/src/parser/inline/link.ts +2 -2
- package/src/parser/inline/media.ts +2 -2
- package/src/parser/inline/ruby.ts +10 -6
- package/src/parser/inline/template.ts +1 -1
package/CHANGELOG.md
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! securemark v0.260.
|
|
1
|
+
/*! securemark v0.260.5 https://github.com/falsandtru/securemark | (c) 2017, falsandtru | UNLICENSED License */
|
|
2
2
|
(function webpackUniversalModuleDefinition(root, factory) {
|
|
3
3
|
if(typeof exports === 'object' && typeof module === 'object')
|
|
4
4
|
module.exports = factory(require("DOMPurify"), require("Prism"));
|
|
@@ -2888,12 +2888,16 @@ const parser_1 = __webpack_require__(6728);
|
|
|
2888
2888
|
const memo_1 = __webpack_require__(1090);
|
|
2889
2889
|
|
|
2890
2890
|
function reset(base, parser) {
|
|
2891
|
+
if (!('memo' in base)) {
|
|
2892
|
+
base.memo = global_1.undefined;
|
|
2893
|
+
}
|
|
2894
|
+
|
|
2891
2895
|
const changes = global_1.Object.entries(base);
|
|
2892
2896
|
const values = (0, global_1.Array)(changes.length);
|
|
2893
2897
|
return ({
|
|
2894
2898
|
source,
|
|
2895
2899
|
context
|
|
2896
|
-
}) => apply(parser, source, (0, alias_1.ObjectCreate)(context), changes, values);
|
|
2900
|
+
}) => apply(parser, source, (0, alias_1.ObjectCreate)(context), changes, values, true);
|
|
2897
2901
|
}
|
|
2898
2902
|
|
|
2899
2903
|
exports.reset = reset;
|
|
@@ -2909,18 +2913,25 @@ function context(base, parser) {
|
|
|
2909
2913
|
|
|
2910
2914
|
exports.context = context;
|
|
2911
2915
|
|
|
2912
|
-
function apply(parser, source, context, changes, values) {
|
|
2916
|
+
function apply(parser, source, context, changes, values, reset = false) {
|
|
2913
2917
|
if (context) for (let i = 0; i < changes.length; ++i) {
|
|
2914
2918
|
const change = changes[i];
|
|
2915
2919
|
const prop = change[0];
|
|
2916
2920
|
|
|
2917
2921
|
switch (prop) {
|
|
2918
2922
|
case 'resources':
|
|
2919
|
-
if (
|
|
2920
|
-
|
|
2923
|
+
if (!reset) break;
|
|
2924
|
+
if (prop in context && !(0, alias_1.hasOwnProperty)(context, prop)) break;
|
|
2921
2925
|
context[prop] = (0, alias_1.ObjectCreate)(change[1]);
|
|
2922
2926
|
break;
|
|
2923
2927
|
|
|
2928
|
+
case 'memo':
|
|
2929
|
+
if (!reset) break;
|
|
2930
|
+
context.memo = new memo_1.Memo({
|
|
2931
|
+
targets: context.memo?.targets
|
|
2932
|
+
});
|
|
2933
|
+
break;
|
|
2934
|
+
|
|
2924
2935
|
default:
|
|
2925
2936
|
values[i] = context[prop];
|
|
2926
2937
|
context[prop] = change[1];
|
|
@@ -2935,8 +2946,11 @@ function apply(parser, source, context, changes, values) {
|
|
|
2935
2946
|
const prop = change[0];
|
|
2936
2947
|
|
|
2937
2948
|
switch (prop) {
|
|
2938
|
-
case 'resources':
|
|
2939
|
-
|
|
2949
|
+
case 'resources': // @ts-expect-error
|
|
2950
|
+
|
|
2951
|
+
case 'memo':
|
|
2952
|
+
if (!reset) break;
|
|
2953
|
+
// fallthrough
|
|
2940
2954
|
|
|
2941
2955
|
default:
|
|
2942
2956
|
context[prop] = values[i];
|
|
@@ -2953,26 +2967,25 @@ function syntax(syntax, prec, cost, state, parser) {
|
|
|
2953
2967
|
}) => {
|
|
2954
2968
|
if (source === '') return;
|
|
2955
2969
|
const memo = context.memo ??= new memo_1.Memo();
|
|
2956
|
-
context.memorable ??= ~0;
|
|
2957
2970
|
context.offset ??= 0;
|
|
2958
2971
|
const position = source.length + context.offset;
|
|
2959
|
-
const
|
|
2960
|
-
const
|
|
2961
|
-
const cache = syntax && memo.get(position, syntax,
|
|
2972
|
+
const stateOuter = context.state ?? 0;
|
|
2973
|
+
const stateInner = context.state = stateOuter | state;
|
|
2974
|
+
const cache = syntax && stateInner & memo.targets && memo.get(position, syntax, stateInner);
|
|
2962
2975
|
const result = cache ? cache.length === 0 ? global_1.undefined : [cache[0], source.slice(cache[1])] : parser({
|
|
2963
2976
|
source,
|
|
2964
2977
|
context
|
|
2965
2978
|
});
|
|
2966
2979
|
|
|
2967
|
-
if (syntax &&
|
|
2968
|
-
cache ?? memo.set(position, syntax,
|
|
2980
|
+
if (syntax && stateOuter & memo.targets) {
|
|
2981
|
+
cache ?? memo.set(position, syntax, stateInner, (0, parser_1.eval)(result), source.length - (0, parser_1.exec)(result, '').length);
|
|
2969
2982
|
}
|
|
2970
2983
|
|
|
2971
|
-
if (result && !
|
|
2984
|
+
if (result && !stateOuter && memo.length >= position + 2) {
|
|
2972
2985
|
memo.clear(position + 2);
|
|
2973
2986
|
}
|
|
2974
2987
|
|
|
2975
|
-
context.state =
|
|
2988
|
+
context.state = stateOuter;
|
|
2976
2989
|
return result;
|
|
2977
2990
|
}));
|
|
2978
2991
|
}
|
|
@@ -3200,8 +3213,11 @@ Object.defineProperty(exports, "__esModule", ({
|
|
|
3200
3213
|
exports.Memo = void 0;
|
|
3201
3214
|
|
|
3202
3215
|
class Memo {
|
|
3203
|
-
constructor(
|
|
3216
|
+
constructor({
|
|
3217
|
+
targets = ~0
|
|
3218
|
+
} = {}) {
|
|
3204
3219
|
this.memory = [];
|
|
3220
|
+
this.targets = targets;
|
|
3205
3221
|
}
|
|
3206
3222
|
|
|
3207
3223
|
get length() {
|
|
@@ -3595,6 +3611,8 @@ const global_1 = __webpack_require__(4128);
|
|
|
3595
3611
|
|
|
3596
3612
|
const parser_1 = __webpack_require__(6728);
|
|
3597
3613
|
|
|
3614
|
+
const memo_1 = __webpack_require__(1090);
|
|
3615
|
+
|
|
3598
3616
|
const segment_1 = __webpack_require__(9002);
|
|
3599
3617
|
|
|
3600
3618
|
const header_1 = __webpack_require__(5702);
|
|
@@ -3616,9 +3634,11 @@ const array_1 = __webpack_require__(8112);
|
|
|
3616
3634
|
function bind(target, settings) {
|
|
3617
3635
|
let context = { ...settings,
|
|
3618
3636
|
host: settings.host ?? new url_1.ReadonlyURL(global_1.location.pathname, global_1.location.origin),
|
|
3619
|
-
|
|
3620
|
-
|
|
3637
|
+
memo: new memo_1.Memo({
|
|
3638
|
+
targets: 236
|
|
3639
|
+
/* State.backtrackers */
|
|
3621
3640
|
|
|
3641
|
+
})
|
|
3622
3642
|
};
|
|
3623
3643
|
if (context.host?.origin === 'null') throw new Error(`Invalid host: ${context.host.href}`);
|
|
3624
3644
|
const blocks = [];
|
|
@@ -3958,6 +3978,8 @@ const global_1 = __webpack_require__(4128);
|
|
|
3958
3978
|
|
|
3959
3979
|
const parser_1 = __webpack_require__(6728);
|
|
3960
3980
|
|
|
3981
|
+
const memo_1 = __webpack_require__(1090);
|
|
3982
|
+
|
|
3961
3983
|
const segment_1 = __webpack_require__(9002);
|
|
3962
3984
|
|
|
3963
3985
|
const header_1 = __webpack_require__(5702);
|
|
@@ -3988,9 +4010,11 @@ function parse(source, opts = {}, context) {
|
|
|
3988
4010
|
...(context?.resources && {
|
|
3989
4011
|
resources: context.resources
|
|
3990
4012
|
}),
|
|
3991
|
-
|
|
3992
|
-
|
|
4013
|
+
memo: new memo_1.Memo({
|
|
4014
|
+
targets: 236
|
|
4015
|
+
/* State.backtrackers */
|
|
3993
4016
|
|
|
4017
|
+
})
|
|
3994
4018
|
};
|
|
3995
4019
|
if (context.host?.origin === 'null') throw new Error(`Invalid host: ${context.host.href}`);
|
|
3996
4020
|
const node = (0, dom_1.frag)();
|
|
@@ -5948,8 +5972,8 @@ exports.autolink = (0, combinator_1.fmap)((0, combinator_1.validate)(/^(?:[@#>0-
|
|
|
5948
5972
|
/* State.autolink */
|
|
5949
5973
|
, false, (0, combinator_1.syntax)(2
|
|
5950
5974
|
/* Syntax.autolink */
|
|
5951
|
-
, 1, 1,
|
|
5952
|
-
/* State.
|
|
5975
|
+
, 1, 1, ~1
|
|
5976
|
+
/* State.shortcut */
|
|
5953
5977
|
, (0, combinator_1.some)((0, combinator_1.union)([url_1.url, email_1.email, // Escape unmatched email-like strings.
|
|
5954
5978
|
(0, source_1.str)(/^[0-9a-z]+(?:[.+_-][0-9a-z]+)*(?:@(?:[0-9a-z]+(?:[.-][0-9a-z]+)*)?)*/i), channel_1.channel, account_1.account, // Escape unmatched account-like strings.
|
|
5955
5979
|
(0, source_1.str)(/^@+[0-9a-z]*(?:-[0-9a-z]+)*/i), // Escape invalid leading characters.
|
|
@@ -6502,10 +6526,12 @@ const dom_1 = __webpack_require__(3252);
|
|
|
6502
6526
|
|
|
6503
6527
|
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)(32
|
|
6504
6528
|
/* State.index */
|
|
6505
|
-
, false, (0, combinator_1.syntax)(
|
|
6529
|
+
, false, (0, combinator_1.syntax)(2048
|
|
6506
6530
|
/* Syntax.index */
|
|
6507
|
-
, 2, 1,
|
|
6508
|
-
/* State.
|
|
6531
|
+
, 2, 1, 250
|
|
6532
|
+
/* State.linkers */
|
|
6533
|
+
| 4
|
|
6534
|
+
/* State.media */
|
|
6509
6535
|
, (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, {
|
|
6510
6536
|
id: el.id ? null : global_1.undefined,
|
|
6511
6537
|
class: 'index',
|
|
@@ -6707,7 +6733,7 @@ const array_1 = __webpack_require__(8112); // Don't use the symbols already used
|
|
|
6707
6733
|
// All syntax surrounded by square brackets shouldn't contain line breaks.
|
|
6708
6734
|
|
|
6709
6735
|
|
|
6710
|
-
exports.placeholder = (0, combinator_1.lazy)(() => (0, combinator_1.validate)(['[:', '[^'], (0, combinator_1.surround)((0, source_1.str)(/^\[[:^]/), (0, combinator_1.syntax)(
|
|
6736
|
+
exports.placeholder = (0, combinator_1.lazy)(() => (0, combinator_1.validate)(['[:', '[^'], (0, combinator_1.surround)((0, source_1.str)(/^\[[:^]/), (0, combinator_1.syntax)(1024
|
|
6711
6737
|
/* Syntax.placeholder */
|
|
6712
6738
|
, 2, 1, 0
|
|
6713
6739
|
/* State.none */
|
|
@@ -6928,8 +6954,10 @@ const textlink = (0, combinator_1.lazy)(() => (0, combinator_1.constraint)(8
|
|
|
6928
6954
|
/* State.link */
|
|
6929
6955
|
, false, (0, combinator_1.syntax)(256
|
|
6930
6956
|
/* Syntax.link */
|
|
6931
|
-
, 2, 10,
|
|
6932
|
-
/* State.
|
|
6957
|
+
, 2, 10, 250
|
|
6958
|
+
/* State.linkers */
|
|
6959
|
+
| 4
|
|
6960
|
+
/* State.media */
|
|
6933
6961
|
, (0, combinator_1.bind)((0, combinator_1.reverse)((0, combinator_1.tails)([(0, combinator_1.dup)((0, combinator_1.surround)('[', (0, combinator_1.some)((0, combinator_1.union)([inline_1.inline]), ']', [[/^\\?\n/, 9], [']', 2]]), ']', true)), (0, combinator_1.dup)((0, combinator_1.surround)(/^{(?![{}])/, (0, combinator_1.inits)([exports.uri, (0, combinator_1.some)(exports.option)]), /^[^\S\n]*}/))])), ([params, content = []], rest, context) => {
|
|
6934
6962
|
return parse(content, params, rest, context);
|
|
6935
6963
|
}))));
|
|
@@ -6939,10 +6967,8 @@ const medialink = (0, combinator_1.lazy)(() => (0, combinator_1.constraint)(8
|
|
|
6939
6967
|
/* State.media */
|
|
6940
6968
|
, false, (0, combinator_1.syntax)(256
|
|
6941
6969
|
/* Syntax.link */
|
|
6942
|
-
, 2, 10,
|
|
6943
|
-
/* State.
|
|
6944
|
-
^ 4
|
|
6945
|
-
/* State.media */
|
|
6970
|
+
, 2, 10, 250
|
|
6971
|
+
/* State.linkers */
|
|
6946
6972
|
, (0, combinator_1.bind)((0, combinator_1.reverse)((0, combinator_1.sequence)([(0, combinator_1.dup)((0, combinator_1.surround)('[', (0, combinator_1.union)([inline_1.media, inline_1.shortmedia]), ']')), (0, combinator_1.dup)((0, combinator_1.surround)(/^{(?![{}])/, (0, combinator_1.inits)([exports.uri, (0, combinator_1.some)(exports.option)]), /^[^\S\n]*}/))])), ([params, content = []], rest, context) => parse(content, params, rest, context)))));
|
|
6947
6973
|
exports.unsafelink = (0, combinator_1.lazy)(() => (0, combinator_1.creation)(10, (0, combinator_1.precedence)(2, (0, combinator_1.bind)((0, combinator_1.reverse)((0, combinator_1.tails)([(0, combinator_1.dup)((0, combinator_1.surround)('[', (0, combinator_1.some)((0, combinator_1.union)([source_1.unescsource]), ']'), ']')), (0, combinator_1.dup)((0, combinator_1.surround)(/^{(?![{}])/, (0, combinator_1.inits)([exports.uri, (0, combinator_1.some)(exports.option)]), /^[^\S\n]*}/))])), ([params, content = []], rest, context) => parse(content, params, rest, context)))));
|
|
6948
6974
|
exports.uri = (0, combinator_1.union)([(0, combinator_1.open)(/^[^\S\n]+/, (0, source_1.str)(/^\S+/)), (0, source_1.str)(/^[^\s{}]+/)]);
|
|
@@ -7172,8 +7198,8 @@ exports.media = (0, combinator_1.lazy)(() => (0, combinator_1.validate)(['![', '
|
|
|
7172
7198
|
/* State.media */
|
|
7173
7199
|
, false, (0, combinator_1.syntax)(64
|
|
7174
7200
|
/* Syntax.media */
|
|
7175
|
-
, 2, 10,
|
|
7176
|
-
/* State.
|
|
7201
|
+
, 2, 10, ~8
|
|
7202
|
+
/* State.link */
|
|
7177
7203
|
, (0, combinator_1.bind)((0, combinator_1.verify)((0, combinator_1.fmap)((0, combinator_1.tails)([(0, combinator_1.dup)((0, combinator_1.surround)('[', (0, combinator_1.some)((0, combinator_1.union)([htmlentity_1.unsafehtmlentity, bracket, source_1.txt]), ']', [[/^\\?\n/, 9]]), ']', true)), (0, combinator_1.dup)((0, combinator_1.surround)(/^{(?![{}])/, (0, combinator_1.inits)([link_1.uri, (0, combinator_1.some)(option)]), /^[^\S\n]*}/))]), ([as, bs]) => bs ? [[as.join('').trim() || as.join('')], bs] : [[''], as]), ([[text]]) => text === '' || text.trim() !== ''), ([[text], params], rest, context) => {
|
|
7178
7204
|
const INSECURE_URI = params.shift();
|
|
7179
7205
|
const url = new url_1.ReadonlyURL((0, link_1.resolve)(INSECURE_URI, context.host ?? global_1.location, context.url ?? context.host ?? global_1.location), context.host?.href || global_1.location.href);
|
|
@@ -7195,7 +7221,7 @@ exports.media = (0, combinator_1.lazy)(() => (0, combinator_1.validate)(['![', '
|
|
|
7195
7221
|
if (context.state & 8
|
|
7196
7222
|
/* State.link */
|
|
7197
7223
|
) return [[el], rest];
|
|
7198
|
-
if (cache && cache.tagName !== 'IMG') return (0, combinator_1.creation)(10,
|
|
7224
|
+
if (cache && cache.tagName !== 'IMG') return (0, combinator_1.creation)(10, _ => [[el], rest])({
|
|
7199
7225
|
source: '!',
|
|
7200
7226
|
context
|
|
7201
7227
|
});
|
|
@@ -7279,7 +7305,7 @@ const dom_1 = __webpack_require__(3252);
|
|
|
7279
7305
|
|
|
7280
7306
|
exports.reference = (0, combinator_1.lazy)(() => (0, combinator_1.surround)('[[', (0, combinator_1.constraint)(64
|
|
7281
7307
|
/* State.reference */
|
|
7282
|
-
, false, (0, combinator_1.syntax)(
|
|
7308
|
+
, false, (0, combinator_1.syntax)(8192
|
|
7283
7309
|
/* Syntax.reference */
|
|
7284
7310
|
, 6, 1, 128
|
|
7285
7311
|
/* State.annotation */
|
|
@@ -7335,11 +7361,17 @@ const dom_1 = __webpack_require__(3252);
|
|
|
7335
7361
|
|
|
7336
7362
|
const array_1 = __webpack_require__(8112);
|
|
7337
7363
|
|
|
7338
|
-
exports.ruby = (0, combinator_1.lazy)(() => (0, combinator_1.validate)('[', (0, combinator_1.syntax)(
|
|
7339
|
-
/* Syntax.
|
|
7340
|
-
, 2, 1,
|
|
7341
|
-
/* State.
|
|
7342
|
-
, (0, combinator_1.fmap)((0, combinator_1.verify)((0, combinator_1.sequence)([(0, combinator_1.surround)('[', (0,
|
|
7364
|
+
exports.ruby = (0, combinator_1.lazy)(() => (0, combinator_1.validate)('[', (0, combinator_1.syntax)(512
|
|
7365
|
+
/* Syntax.ruby */
|
|
7366
|
+
, 2, 1, -1
|
|
7367
|
+
/* State.all */
|
|
7368
|
+
, (0, combinator_1.fmap)((0, combinator_1.verify)((0, combinator_1.fmap)((0, combinator_1.sequence)([(0, combinator_1.surround)('[', (0, source_1.str)(/^(?:\\[^\n]|[^\\[\](){}"\n])+/), ']'), (0, combinator_1.surround)('(', (0, source_1.str)(/^(?:\\[^\n]|[^\\[\](){}"\n])+/), ')')]), ([texts, rubies], _, context) => [(0, parser_1.eval)(text({
|
|
7369
|
+
source: texts,
|
|
7370
|
+
context
|
|
7371
|
+
}), [])[0] ?? '', (0, parser_1.eval)(text({
|
|
7372
|
+
source: rubies,
|
|
7373
|
+
context
|
|
7374
|
+
}), [])[0] ?? '']), ([texts, rubies]) => texts && rubies && (0, visibility_1.isStartTightNodes)(texts)), ([texts, rubies]) => {
|
|
7343
7375
|
texts[texts.length - 1] === '' && texts.pop();
|
|
7344
7376
|
|
|
7345
7377
|
switch (true) {
|
|
@@ -7499,8 +7531,8 @@ const array_1 = __webpack_require__(8112);
|
|
|
7499
7531
|
|
|
7500
7532
|
exports.template = (0, combinator_1.lazy)(() => (0, combinator_1.surround)('{{', (0, combinator_1.syntax)(0
|
|
7501
7533
|
/* Syntax.none */
|
|
7502
|
-
, 2, 1,
|
|
7503
|
-
/* State.
|
|
7534
|
+
, 2, 1, -1
|
|
7535
|
+
/* State.all */
|
|
7504
7536
|
, (0, combinator_1.some)((0, combinator_1.union)([bracket, source_1.escsource]), '}')), '}}', true, ([, ns = []], rest) => [[(0, dom_1.html)('span', {
|
|
7505
7537
|
class: 'template'
|
|
7506
7538
|
}, `{{${ns.join('').replace(/\x1B/g, '')}}}`)], rest]));
|
package/markdown.d.ts
CHANGED
|
@@ -829,8 +829,8 @@ export namespace MarkdownParser {
|
|
|
829
829
|
// [AB](a b)
|
|
830
830
|
Inline<'ruby'>,
|
|
831
831
|
Parser<HTMLElement, Context, [
|
|
832
|
-
|
|
833
|
-
|
|
832
|
+
SourceParser.StrParser,
|
|
833
|
+
SourceParser.StrParser,
|
|
834
834
|
]> {
|
|
835
835
|
}
|
|
836
836
|
export namespace RubyParser {
|
package/package.json
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
export class Memo {
|
|
2
|
+
constructor({ targets = ~0 } = {}) {
|
|
3
|
+
this.targets = targets;
|
|
4
|
+
}
|
|
5
|
+
public readonly targets: number;
|
|
2
6
|
private readonly memory: Record<string, readonly [any[], number] | readonly []>[/* pos */] = [];
|
|
3
7
|
public get length(): number {
|
|
4
8
|
return this.memory.length;
|
|
@@ -5,12 +5,15 @@ import { Memo } from './context/memo';
|
|
|
5
5
|
|
|
6
6
|
export function reset<P extends Parser<unknown>>(base: Context<P>, parser: P): P;
|
|
7
7
|
export function reset<T>(base: Ctx, parser: Parser<T>): Parser<T> {
|
|
8
|
+
if (!('memo' in base)) {
|
|
9
|
+
base.memo = undefined;
|
|
10
|
+
}
|
|
8
11
|
assert(Object.getPrototypeOf(base) === Object.prototype);
|
|
9
12
|
assert(Object.freeze(base));
|
|
10
13
|
const changes = Object.entries(base);
|
|
11
14
|
const values = Array(changes.length);
|
|
12
15
|
return ({ source, context }) =>
|
|
13
|
-
apply(parser, source, ObjectCreate(context), changes, values);
|
|
16
|
+
apply(parser, source, ObjectCreate(context), changes, values, true);
|
|
14
17
|
}
|
|
15
18
|
|
|
16
19
|
export function context<P extends Parser<unknown>>(base: Context<P>, parser: P): P;
|
|
@@ -23,18 +26,22 @@ export function context<T>(base: Ctx, parser: Parser<T>): Parser<T> {
|
|
|
23
26
|
apply(parser, source, context, changes, values);
|
|
24
27
|
}
|
|
25
28
|
|
|
26
|
-
function apply<P extends Parser<unknown>>(parser: P, source: string, context: Context<P>, changes: [string, any][], values: any[]): Result<Tree<P>>;
|
|
27
|
-
function apply<T>(parser: Parser<T>, source: string, context: Ctx, changes: [string, any][], values: any[]): Result<T> {
|
|
29
|
+
function apply<P extends Parser<unknown>>(parser: P, source: string, context: Context<P>, changes: [string, any][], values: any[], reset?: boolean): Result<Tree<P>>;
|
|
30
|
+
function apply<T>(parser: Parser<T>, source: string, context: Ctx, changes: [string, any][], values: any[], reset = false): Result<T> {
|
|
28
31
|
if (context) for (let i = 0; i < changes.length; ++i) {
|
|
29
32
|
const change = changes[i];
|
|
30
33
|
const prop = change[0];
|
|
31
34
|
switch (prop) {
|
|
32
35
|
case 'resources':
|
|
36
|
+
if (!reset) break;
|
|
33
37
|
assert(typeof change[1] === 'object');
|
|
34
38
|
assert(context[prop] || !(prop in context));
|
|
35
39
|
if (prop in context && !hasOwnProperty(context, prop)) break;
|
|
36
|
-
|
|
37
|
-
|
|
40
|
+
context[prop as string] = ObjectCreate(change[1]);
|
|
41
|
+
break;
|
|
42
|
+
case 'memo':
|
|
43
|
+
if (!reset) break;
|
|
44
|
+
context.memo = new Memo({ targets: context.memo?.targets });
|
|
38
45
|
break;
|
|
39
46
|
default:
|
|
40
47
|
values[i] = context[prop];
|
|
@@ -47,7 +54,10 @@ function apply<T>(parser: Parser<T>, source: string, context: Ctx, changes: [str
|
|
|
47
54
|
const prop = change[0];
|
|
48
55
|
switch (prop) {
|
|
49
56
|
case 'resources':
|
|
50
|
-
|
|
57
|
+
// @ts-expect-error
|
|
58
|
+
case 'memo':
|
|
59
|
+
if (!reset) break;
|
|
60
|
+
// fallthrough
|
|
51
61
|
default:
|
|
52
62
|
context[prop] = values[i];
|
|
53
63
|
values[i] = undefined;
|
|
@@ -61,26 +71,25 @@ export function syntax<T>(syntax: number, prec: number, cost: number, state: num
|
|
|
61
71
|
return creation(cost, precedence(prec, ({ source, context }) => {
|
|
62
72
|
if (source === '') return;
|
|
63
73
|
const memo = context.memo ??= new Memo();
|
|
64
|
-
context.memorable ??= ~0;
|
|
65
74
|
context.offset ??= 0;
|
|
66
75
|
const position = source.length + context.offset!;
|
|
67
|
-
const
|
|
68
|
-
const
|
|
69
|
-
const cache = syntax && memo.get(position, syntax,
|
|
76
|
+
const stateOuter = context.state ?? 0;
|
|
77
|
+
const stateInner = context.state = stateOuter | state;
|
|
78
|
+
const cache = syntax && stateInner & memo.targets && memo.get(position, syntax, stateInner);
|
|
70
79
|
const result: Result<T> = cache
|
|
71
80
|
? cache.length === 0
|
|
72
81
|
? undefined
|
|
73
82
|
: [cache[0], source.slice(cache[1])]
|
|
74
83
|
: parser!({ source, context });
|
|
75
|
-
if (syntax &&
|
|
76
|
-
cache ?? memo.set(position, syntax,
|
|
77
|
-
assert.deepStrictEqual(cache && cache, cache && memo.get(position, syntax,
|
|
84
|
+
if (syntax && stateOuter & memo.targets) {
|
|
85
|
+
cache ?? memo.set(position, syntax, stateInner, eval(result), source.length - exec(result, '').length);
|
|
86
|
+
assert.deepStrictEqual(cache && cache, cache && memo.get(position, syntax, stateInner));
|
|
78
87
|
}
|
|
79
|
-
if (result && !
|
|
80
|
-
assert(!(
|
|
88
|
+
if (result && !stateOuter && memo.length! >= position + 2) {
|
|
89
|
+
assert(!(stateOuter & memo.targets));
|
|
81
90
|
memo.clear(position + 2);
|
|
82
91
|
}
|
|
83
|
-
context.state =
|
|
92
|
+
context.state = stateOuter;
|
|
84
93
|
return result;
|
|
85
94
|
}));
|
|
86
95
|
}
|
package/src/parser/api/bind.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { undefined, location } from 'spica/global';
|
|
|
2
2
|
import { ParserSettings, Progress } from '../../..';
|
|
3
3
|
import { MarkdownParser } from '../../../markdown';
|
|
4
4
|
import { eval } from '../../combinator/data/parser';
|
|
5
|
+
import { Memo } from '../../combinator/data/parser/context/memo';
|
|
5
6
|
import { segment, validate, MAX_INPUT_SIZE } from '../segment';
|
|
6
7
|
import { header } from '../header';
|
|
7
8
|
import { block } from '../block';
|
|
@@ -24,7 +25,7 @@ export function bind(target: DocumentFragment | HTMLElement | ShadowRoot, settin
|
|
|
24
25
|
let context: MarkdownParser.Context = {
|
|
25
26
|
...settings,
|
|
26
27
|
host: settings.host ?? new ReadonlyURL(location.pathname, location.origin),
|
|
27
|
-
|
|
28
|
+
memo: new Memo({ targets: State.backtrackers }),
|
|
28
29
|
};
|
|
29
30
|
if (context.host?.origin === 'null') throw new Error(`Invalid host: ${context.host.href}`);
|
|
30
31
|
assert(!settings.id);
|
package/src/parser/api/parse.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { location } from 'spica/global';
|
|
|
2
2
|
import { ParserOptions } from '../../..';
|
|
3
3
|
import { MarkdownParser } from '../../../markdown';
|
|
4
4
|
import { eval } from '../../combinator/data/parser';
|
|
5
|
+
import { Memo } from '../../combinator/data/parser/context/memo';
|
|
5
6
|
import { segment, validate, MAX_SEGMENT_SIZE } from '../segment';
|
|
6
7
|
import { header } from '../header';
|
|
7
8
|
import { block } from '../block';
|
|
@@ -30,7 +31,7 @@ export function parse(source: string, opts: Options = {}, context?: MarkdownPars
|
|
|
30
31
|
...context?.resources && {
|
|
31
32
|
resources: context.resources,
|
|
32
33
|
},
|
|
33
|
-
|
|
34
|
+
memo: new Memo({ targets: State.backtrackers }),
|
|
34
35
|
};
|
|
35
36
|
if (context.host?.origin === 'null') throw new Error(`Invalid host: ${context.host.href}`);
|
|
36
37
|
const node = frag();
|
package/src/parser/context.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
export const enum Syntax {
|
|
2
|
-
reference = 1 <<
|
|
3
|
-
comment = 1 <<
|
|
4
|
-
index = 1 <<
|
|
5
|
-
placeholder = 1 <<
|
|
2
|
+
reference = 1 << 13,
|
|
3
|
+
comment = 1 << 12,
|
|
4
|
+
index = 1 << 11,
|
|
5
|
+
placeholder = 1 << 10,
|
|
6
|
+
ruby = 1 << 9,
|
|
6
7
|
link = 1 << 8,
|
|
7
8
|
bracket = 1 << 7,
|
|
8
9
|
media = 1 << 6,
|
|
@@ -25,15 +26,15 @@ export const enum State {
|
|
|
25
26
|
autolink = 1 << 1,
|
|
26
27
|
shortcut = 1 << 0,
|
|
27
28
|
none = 0,
|
|
28
|
-
|
|
29
|
+
all = ~0,
|
|
30
|
+
linkers = 0
|
|
29
31
|
| State.annotation
|
|
30
32
|
| State.reference
|
|
31
33
|
| State.index
|
|
32
34
|
| State.label
|
|
33
35
|
| State.link
|
|
34
|
-
| State.media
|
|
35
36
|
| State.autolink,
|
|
36
|
-
|
|
37
|
+
backtrackers = 0
|
|
37
38
|
| State.annotation
|
|
38
39
|
| State.reference
|
|
39
40
|
| State.index
|
|
@@ -14,7 +14,7 @@ import { stringify } from '../util';
|
|
|
14
14
|
export const autolink: AutolinkParser = fmap(
|
|
15
15
|
validate(/^(?:[@#>0-9a-z]|\S[#>])/i,
|
|
16
16
|
constraint(State.autolink, false,
|
|
17
|
-
syntax(Syntax.autolink, 1, 1, State.
|
|
17
|
+
syntax(Syntax.autolink, 1, 1, ~State.shortcut,
|
|
18
18
|
some(union([
|
|
19
19
|
url,
|
|
20
20
|
email,
|
|
@@ -13,7 +13,7 @@ import IndexParser = ExtensionParser.IndexParser;
|
|
|
13
13
|
export const index: IndexParser = lazy(() => validate('[#', fmap(indexee(surround(
|
|
14
14
|
'[#',
|
|
15
15
|
constraint(State.index, false,
|
|
16
|
-
syntax(Syntax.index, 2, 1, State.
|
|
16
|
+
syntax(Syntax.index, 2, 1, State.linkers | State.media,
|
|
17
17
|
startTight(
|
|
18
18
|
open(stropt(/^\|?/), trimBlankEnd(some(union([
|
|
19
19
|
signature,
|
|
@@ -25,7 +25,7 @@ export const link: LinkParser = lazy(() => validate(['[', '{'], union([
|
|
|
25
25
|
|
|
26
26
|
const textlink: LinkParser.TextLinkParser = lazy(() =>
|
|
27
27
|
constraint(State.link, false,
|
|
28
|
-
syntax(Syntax.link, 2, 10, State.
|
|
28
|
+
syntax(Syntax.link, 2, 10, State.linkers | State.media,
|
|
29
29
|
bind(reverse(tails([
|
|
30
30
|
dup(surround(
|
|
31
31
|
'[',
|
|
@@ -41,7 +41,7 @@ const textlink: LinkParser.TextLinkParser = lazy(() =>
|
|
|
41
41
|
|
|
42
42
|
const medialink: LinkParser.MediaLinkParser = lazy(() =>
|
|
43
43
|
constraint(State.link | State.media, false,
|
|
44
|
-
syntax(Syntax.link, 2, 10, State.
|
|
44
|
+
syntax(Syntax.link, 2, 10, State.linkers,
|
|
45
45
|
bind(reverse(sequence([
|
|
46
46
|
dup(surround(
|
|
47
47
|
'[',
|
|
@@ -21,7 +21,7 @@ Object.setPrototypeOf(optspec, null);
|
|
|
21
21
|
export const media: MediaParser = lazy(() => validate(['![', '!{'], open(
|
|
22
22
|
'!',
|
|
23
23
|
constraint(State.media, false,
|
|
24
|
-
syntax(Syntax.media, 2, 10, State.
|
|
24
|
+
syntax(Syntax.media, 2, 10, ~State.link,
|
|
25
25
|
bind(verify(fmap(tails([
|
|
26
26
|
dup(surround(
|
|
27
27
|
'[',
|
|
@@ -55,7 +55,7 @@ export const media: MediaParser = lazy(() => validate(['![', '!{'], open(
|
|
|
55
55
|
el.style.aspectRatio = el.getAttribute('aspect-ratio')!;
|
|
56
56
|
}
|
|
57
57
|
if (context.state! & State.link) return [[el], rest];
|
|
58
|
-
if (cache && cache.tagName !== 'IMG') return creation(10,
|
|
58
|
+
if (cache && cache.tagName !== 'IMG') return creation(10, _ => [[el!], rest])({ source: '!', context });
|
|
59
59
|
return fmap(
|
|
60
60
|
unsafelink as MediaParser,
|
|
61
61
|
([link]) => [define(link, { class: null, target: '_blank' }, [el])])
|
|
@@ -1,20 +1,24 @@
|
|
|
1
1
|
import { undefined } from 'spica/global';
|
|
2
2
|
import { RubyParser } from '../inline';
|
|
3
3
|
import { eval, exec } from '../../combinator/data/parser';
|
|
4
|
-
import { sequence, syntax, creation, validate, verify,
|
|
4
|
+
import { sequence, syntax, creation, validate, verify, surround, lazy, fmap } from '../../combinator';
|
|
5
5
|
import { unsafehtmlentity } from './htmlentity';
|
|
6
|
-
import { text as txt } from '../source';
|
|
6
|
+
import { text as txt, str } from '../source';
|
|
7
7
|
import { Syntax, State } from '../context';
|
|
8
8
|
import { isStartTightNodes } from '../visibility';
|
|
9
9
|
import { html, defrag } from 'typed-dom/dom';
|
|
10
10
|
import { unshift, push } from 'spica/array';
|
|
11
11
|
|
|
12
|
-
export const ruby: RubyParser = lazy(() => validate('[', syntax(Syntax.
|
|
12
|
+
export const ruby: RubyParser = lazy(() => validate('[', syntax(Syntax.ruby, 2, 1, State.all, fmap(verify(fmap(
|
|
13
13
|
sequence([
|
|
14
|
-
surround('[',
|
|
15
|
-
surround('(',
|
|
14
|
+
surround('[', str(/^(?:\\[^\n]|[^\\[\](){}"\n])+/), ']'),
|
|
15
|
+
surround('(', str(/^(?:\\[^\n]|[^\\[\](){}"\n])+/), ')'),
|
|
16
16
|
]),
|
|
17
|
-
([texts]) =>
|
|
17
|
+
([texts, rubies], _, context) => [
|
|
18
|
+
eval(text({ source: texts, context }), [])[0] ?? '',
|
|
19
|
+
eval(text({ source: rubies, context }), [])[0] ?? '',
|
|
20
|
+
]),
|
|
21
|
+
([texts, rubies]) => texts && rubies && isStartTightNodes(texts)),
|
|
18
22
|
([texts, rubies]) => {
|
|
19
23
|
texts[texts.length - 1] === '' && texts.pop();
|
|
20
24
|
switch (true) {
|
|
@@ -7,7 +7,7 @@ import { html } from 'typed-dom/dom';
|
|
|
7
7
|
import { unshift } from 'spica/array';
|
|
8
8
|
|
|
9
9
|
export const template: TemplateParser = lazy(() => surround(
|
|
10
|
-
'{{', syntax(Syntax.none, 2, 1, State.
|
|
10
|
+
'{{', syntax(Syntax.none, 2, 1, State.all, some(union([bracket, escsource]), '}')), '}}', true,
|
|
11
11
|
([, ns = []], rest) => [[html('span', { class: 'template' }, `{{${ns.join('').replace(/\x1B/g, '')}}}`)], rest]));
|
|
12
12
|
|
|
13
13
|
const bracket: TemplateParser.BracketParser = lazy(() => creation(union([
|