securemark 0.280.1 → 0.280.2
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 +32 -54
- package/markdown.d.ts +6 -0
- package/package.json +1 -1
- package/src/combinator/data/parser/context/delimiter.ts +3 -3
- package/src/combinator/data/parser/context/memo.ts +9 -5
- package/src/combinator/data/parser/context.ts +21 -27
- package/src/parser/api/bind.ts +1 -3
- package/src/parser/api/parse.test.ts +10 -2
- package/src/parser/api/parse.ts +2 -6
- package/src/parser/block.ts +5 -3
- package/src/parser/inline/bracket.ts +18 -0
- package/src/parser/source/text.ts +1 -1
package/CHANGELOG.md
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! securemark v0.280.
|
|
1
|
+
/*! securemark v0.280.2 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"));
|
|
@@ -3325,9 +3325,6 @@ const alias_1 = __webpack_require__(5406);
|
|
|
3325
3325
|
const parser_1 = __webpack_require__(6728);
|
|
3326
3326
|
const memo_1 = __webpack_require__(1090);
|
|
3327
3327
|
function reset(base, parser) {
|
|
3328
|
-
if (!('memo' in base)) {
|
|
3329
|
-
base.memo = undefined;
|
|
3330
|
-
}
|
|
3331
3328
|
const changes = Object.entries(base);
|
|
3332
3329
|
const values = Array(changes.length);
|
|
3333
3330
|
return ({
|
|
@@ -3346,44 +3343,33 @@ function context(base, parser) {
|
|
|
3346
3343
|
}
|
|
3347
3344
|
exports.context = context;
|
|
3348
3345
|
function apply(parser, source, context, changes, values, reset = false) {
|
|
3349
|
-
|
|
3346
|
+
for (let i = 0; i < changes.length; ++i) {
|
|
3350
3347
|
const change = changes[i];
|
|
3351
3348
|
const prop = change[0];
|
|
3352
3349
|
switch (prop) {
|
|
3353
3350
|
case 'resources':
|
|
3354
|
-
|
|
3355
|
-
|
|
3356
|
-
context[prop] = (0, alias_1.ObjectCreate)(change[1]);
|
|
3357
|
-
break;
|
|
3358
|
-
// @ts-expect-error
|
|
3359
|
-
case 'memo':
|
|
3360
|
-
if (!reset) break;
|
|
3361
|
-
context.memo = new memo_1.Memo({
|
|
3362
|
-
targets: context.memo?.targets
|
|
3363
|
-
});
|
|
3364
|
-
// fallthrough
|
|
3365
|
-
default:
|
|
3366
|
-
values[i] = context[prop];
|
|
3367
|
-
context[prop] = change[1];
|
|
3351
|
+
context[prop] ??= (0, alias_1.ObjectCreate)(change[1]);
|
|
3352
|
+
continue;
|
|
3368
3353
|
}
|
|
3354
|
+
values[i] = context[prop];
|
|
3355
|
+
context[prop] = change[1];
|
|
3369
3356
|
}
|
|
3370
3357
|
const result = parser({
|
|
3371
3358
|
source,
|
|
3372
3359
|
context
|
|
3373
3360
|
});
|
|
3374
|
-
|
|
3361
|
+
for (let i = 0; i < changes.length; ++i) {
|
|
3375
3362
|
const change = changes[i];
|
|
3376
3363
|
const prop = change[0];
|
|
3377
3364
|
switch (prop) {
|
|
3378
3365
|
case 'resources':
|
|
3379
|
-
|
|
3366
|
+
break;
|
|
3380
3367
|
case 'memo':
|
|
3381
|
-
|
|
3382
|
-
|
|
3383
|
-
default:
|
|
3384
|
-
context[prop] = values[i];
|
|
3385
|
-
values[i] = undefined;
|
|
3368
|
+
context.memo.clear();
|
|
3369
|
+
break;
|
|
3386
3370
|
}
|
|
3371
|
+
context[prop] = values[i];
|
|
3372
|
+
values[i] = undefined;
|
|
3387
3373
|
}
|
|
3388
3374
|
return result;
|
|
3389
3375
|
}
|
|
@@ -3407,7 +3393,7 @@ function syntax(syntax, prec, state, parser) {
|
|
|
3407
3393
|
cache ?? memo.set(position, syntax, stateInner, (0, parser_1.eval)(result), source.length - (0, parser_1.exec)(result, '').length);
|
|
3408
3394
|
}
|
|
3409
3395
|
if (result && !stateOuter && memo.length >= position + 2) {
|
|
3410
|
-
memo.
|
|
3396
|
+
memo.resize(position + 2);
|
|
3411
3397
|
}
|
|
3412
3398
|
context.state = stateOuter;
|
|
3413
3399
|
return result;
|
|
@@ -3557,7 +3543,7 @@ class Delimiters {
|
|
|
3557
3543
|
const {
|
|
3558
3544
|
signature,
|
|
3559
3545
|
matcher,
|
|
3560
|
-
precedence
|
|
3546
|
+
precedence
|
|
3561
3547
|
} = delims[i];
|
|
3562
3548
|
const stack = registry(signature);
|
|
3563
3549
|
const index = stack[0]?.index ?? delimiters.length;
|
|
@@ -3576,7 +3562,7 @@ class Delimiters {
|
|
|
3576
3562
|
}
|
|
3577
3563
|
}
|
|
3578
3564
|
}
|
|
3579
|
-
pop(count
|
|
3565
|
+
pop(count) {
|
|
3580
3566
|
const {
|
|
3581
3567
|
registry,
|
|
3582
3568
|
delimiters,
|
|
@@ -3640,9 +3626,8 @@ Object.defineProperty(exports, "__esModule", ({
|
|
|
3640
3626
|
}));
|
|
3641
3627
|
exports.Memo = void 0;
|
|
3642
3628
|
class Memo {
|
|
3643
|
-
constructor({
|
|
3644
|
-
targets =
|
|
3645
|
-
} = {}) {
|
|
3629
|
+
constructor(targets = ~0) {
|
|
3630
|
+
this.targets = targets;
|
|
3646
3631
|
this.memory = [];
|
|
3647
3632
|
this.targets = targets;
|
|
3648
3633
|
}
|
|
@@ -3660,15 +3645,18 @@ class Memo {
|
|
|
3660
3645
|
//console.log('set', position, syntax, state, record[syntax]?.[state]);
|
|
3661
3646
|
}
|
|
3662
3647
|
|
|
3663
|
-
|
|
3648
|
+
resize(position) {
|
|
3664
3649
|
const memory = this.memory;
|
|
3665
3650
|
for (let len = memory.length, i = position; i < len; ++i) {
|
|
3666
3651
|
memory.pop();
|
|
3667
3652
|
}
|
|
3668
|
-
//console.log('
|
|
3653
|
+
//console.log('resize', position + 1);
|
|
3669
3654
|
}
|
|
3670
|
-
}
|
|
3671
3655
|
|
|
3656
|
+
clear() {
|
|
3657
|
+
this.memory = [];
|
|
3658
|
+
}
|
|
3659
|
+
}
|
|
3672
3660
|
exports.Memo = Memo;
|
|
3673
3661
|
|
|
3674
3662
|
/***/ }),
|
|
@@ -3972,7 +3960,6 @@ Object.defineProperty(exports, "__esModule", ({
|
|
|
3972
3960
|
}));
|
|
3973
3961
|
exports.bind = void 0;
|
|
3974
3962
|
const parser_1 = __webpack_require__(6728);
|
|
3975
|
-
const memo_1 = __webpack_require__(1090);
|
|
3976
3963
|
const segment_1 = __webpack_require__(9002);
|
|
3977
3964
|
const header_1 = __webpack_require__(5702);
|
|
3978
3965
|
const block_1 = __webpack_require__(4032);
|
|
@@ -3985,12 +3972,8 @@ const array_1 = __webpack_require__(8112);
|
|
|
3985
3972
|
function bind(target, settings) {
|
|
3986
3973
|
let context = {
|
|
3987
3974
|
...settings,
|
|
3988
|
-
host: settings.host ?? new url_1.ReadonlyURL(location.pathname, location.origin)
|
|
3989
|
-
memo: new memo_1.Memo({
|
|
3990
|
-
targets: 472 /* State.backtrackers */
|
|
3991
|
-
})
|
|
3975
|
+
host: settings.host ?? new url_1.ReadonlyURL(location.pathname, location.origin)
|
|
3992
3976
|
};
|
|
3993
|
-
|
|
3994
3977
|
if (context.id?.match(/[^0-9a-z/-]/i)) throw new Error('Invalid ID: ID must be alphanumeric');
|
|
3995
3978
|
if (context.host?.origin === 'null') throw new Error(`Invalid host: ${context.host.href}`);
|
|
3996
3979
|
const blocks = [];
|
|
@@ -4297,7 +4280,6 @@ Object.defineProperty(exports, "__esModule", ({
|
|
|
4297
4280
|
}));
|
|
4298
4281
|
exports.parse = void 0;
|
|
4299
4282
|
const parser_1 = __webpack_require__(6728);
|
|
4300
|
-
const memo_1 = __webpack_require__(1090);
|
|
4301
4283
|
const segment_1 = __webpack_require__(9002);
|
|
4302
4284
|
const header_1 = __webpack_require__(5702);
|
|
4303
4285
|
const block_1 = __webpack_require__(4032);
|
|
@@ -4316,14 +4298,8 @@ function parse(source, opts = {}, context) {
|
|
|
4316
4298
|
url: url ? new url_1.ReadonlyURL(url) : context?.url,
|
|
4317
4299
|
id: opts.id ?? context?.id,
|
|
4318
4300
|
caches: context?.caches,
|
|
4319
|
-
|
|
4320
|
-
resources: context.resources
|
|
4321
|
-
}),
|
|
4322
|
-
memo: new memo_1.Memo({
|
|
4323
|
-
targets: 472 /* State.backtrackers */
|
|
4324
|
-
})
|
|
4301
|
+
resources: context?.resources
|
|
4325
4302
|
};
|
|
4326
|
-
|
|
4327
4303
|
if (context.id?.match(/[^0-9a-z/-]/i)) throw new Error('Invalid ID: ID must be alphanumeric');
|
|
4328
4304
|
if (context.host?.origin === 'null') throw new Error(`Invalid host: ${context.host.href}`);
|
|
4329
4305
|
const node = (0, dom_1.frag)();
|
|
@@ -4376,6 +4352,7 @@ Object.defineProperty(exports, "__esModule", ({
|
|
|
4376
4352
|
}));
|
|
4377
4353
|
exports.block = void 0;
|
|
4378
4354
|
const combinator_1 = __webpack_require__(2087);
|
|
4355
|
+
const memo_1 = __webpack_require__(1090);
|
|
4379
4356
|
const source_1 = __webpack_require__(6743);
|
|
4380
4357
|
const pagebreak_1 = __webpack_require__(4107);
|
|
4381
4358
|
const heading_1 = __webpack_require__(4623);
|
|
@@ -4394,12 +4371,13 @@ const reply_1 = __webpack_require__(9978);
|
|
|
4394
4371
|
const paragraph_1 = __webpack_require__(6457);
|
|
4395
4372
|
const random_1 = __webpack_require__(7325);
|
|
4396
4373
|
const dom_1 = __webpack_require__(3252);
|
|
4397
|
-
exports.block = (0, combinator_1.creation)(0, false,
|
|
4374
|
+
exports.block = (0, combinator_1.creation)(0, false, (0, combinator_1.reset)({
|
|
4398
4375
|
resources: {
|
|
4399
4376
|
clock: 20000,
|
|
4400
4377
|
recursion: 20 + 1
|
|
4401
|
-
}
|
|
4402
|
-
|
|
4378
|
+
},
|
|
4379
|
+
memo: new memo_1.Memo(472 /* State.backtrackers */)
|
|
4380
|
+
}, error((0, combinator_1.union)([source_1.emptyline, pagebreak_1.pagebreak, heading_1.heading, ulist_1.ulist, olist_1.olist, ilist_1.ilist, dlist_1.dlist, table_1.table, codeblock_1.codeblock, mathblock_1.mathblock, extension_1.extension, sidefence_1.sidefence, blockquote_1.blockquote, mediablock_1.mediablock, reply_1.reply, paragraph_1.paragraph]))));
|
|
4403
4381
|
function error(parser) {
|
|
4404
4382
|
return (0, combinator_1.recover)((0, combinator_1.fallback)((0, combinator_1.open)('\x07', ({
|
|
4405
4383
|
source
|
|
@@ -6084,7 +6062,7 @@ exports.bracket = (0, combinator_1.lazy)(() => (0, combinator_1.union)([(0, comb
|
|
|
6084
6062
|
class: 'paren'
|
|
6085
6063
|
}, (0, dom_1.defrag)((0, array_1.push)((0, array_1.unshift)(as, bs), cs)))], rest], ([as, bs = []], rest) => [(0, array_1.unshift)(as, bs), rest]), (0, combinator_1.surround)((0, source_1.str)('('), (0, combinator_1.creation)((0, combinator_1.syntax)(0 /* Syntax.none */, 2, 0 /* State.none */, (0, source_1.str)(new RegExp(index.source.replace(', ', '[,、]').replace(/[09AZaz.]|\-(?!\w)/g, c => c.trimStart() && String.fromCharCode(c.charCodeAt(0) + 0xFEE0)))))), (0, source_1.str)(')')), (0, combinator_1.surround)((0, source_1.str)('('), (0, combinator_1.creation)((0, combinator_1.syntax)(8 /* Syntax.bracket */, 2, 0 /* State.none */, (0, combinator_1.some)(inline_1.inline, ')', [[/^\\?\n/, 3], [')', 2]]))), (0, source_1.str)(')'), true, ([as, bs = [], cs], rest) => [[(0, dom_1.html)('span', {
|
|
6086
6064
|
class: 'paren'
|
|
6087
|
-
}, (0, dom_1.defrag)((0, array_1.push)((0, array_1.unshift)(as, bs), cs)))], rest], ([as, bs = []], rest) => [(0, array_1.unshift)(as, bs), rest]), (0, combinator_1.surround)((0, source_1.str)('['), (0, combinator_1.creation)((0, combinator_1.syntax)(8 /* Syntax.bracket */, 2, 0 /* State.none */, (0, combinator_1.some)(inline_1.inline, ']', [[/^\\?\n/, 3], [']', 2]]))), (0, source_1.str)(']'), true, undefined, ([as, bs = []], rest) => [(0, array_1.unshift)(as, bs), rest]), (0, combinator_1.surround)((0, source_1.str)('{'), (0, combinator_1.creation)((0, combinator_1.syntax)(8 /* Syntax.bracket */, 2, 0 /* State.none */, (0, combinator_1.some)(inline_1.inline, '}', [[/^\\?\n/, 3], ['}', 2]]))), (0, source_1.str)('}'), true, undefined, ([as, bs = []], rest) => [(0, array_1.unshift)(as, bs), rest]), (0, combinator_1.surround)((0, source_1.str)('"'), (0, combinator_1.creation)((0, combinator_1.syntax)(0 /* Syntax.none */, 3, 0 /* State.none */, (0, combinator_1.some)(inline_1.inline, '"', [[/^\\?\n/, 4], ['"', 3]]))), (0, source_1.str)('"'), true, undefined, ([as, bs = []], rest) => [(0, array_1.unshift)(as, bs), rest])]));
|
|
6065
|
+
}, (0, dom_1.defrag)((0, array_1.push)((0, array_1.unshift)(as, bs), cs)))], rest], ([as, bs = []], rest) => [(0, array_1.unshift)(as, bs), rest]), (0, combinator_1.surround)((0, source_1.str)('['), (0, combinator_1.creation)((0, combinator_1.syntax)(8 /* Syntax.bracket */, 2, 0 /* State.none */, (0, combinator_1.some)(inline_1.inline, ']', [[/^\\?\n/, 3], [']', 2]]))), (0, source_1.str)(']'), true, undefined, ([as, bs = []], rest) => [(0, array_1.unshift)(as, bs), rest]), (0, combinator_1.surround)((0, source_1.str)('['), (0, combinator_1.creation)((0, combinator_1.syntax)(8 /* Syntax.bracket */, 2, 0 /* State.none */, (0, combinator_1.some)(inline_1.inline, ']', [[/^\\?\n/, 3], [']', 2]]))), (0, source_1.str)(']'), true, undefined, ([as, bs = []], rest) => [(0, array_1.unshift)(as, bs), rest]), (0, combinator_1.surround)((0, source_1.str)('{'), (0, combinator_1.creation)((0, combinator_1.syntax)(8 /* Syntax.bracket */, 2, 0 /* State.none */, (0, combinator_1.some)(inline_1.inline, '}', [[/^\\?\n/, 3], ['}', 2]]))), (0, source_1.str)('}'), true, undefined, ([as, bs = []], rest) => [(0, array_1.unshift)(as, bs), rest]), (0, combinator_1.surround)((0, source_1.str)('{'), (0, combinator_1.creation)((0, combinator_1.syntax)(8 /* Syntax.bracket */, 2, 0 /* State.none */, (0, combinator_1.some)(inline_1.inline, '}', [[/^\\?\n/, 3], ['}', 2]]))), (0, source_1.str)('}'), true, undefined, ([as, bs = []], rest) => [(0, array_1.unshift)(as, bs), rest]), (0, combinator_1.surround)((0, source_1.str)('"'), (0, combinator_1.creation)((0, combinator_1.syntax)(0 /* Syntax.none */, 3, 0 /* State.none */, (0, combinator_1.some)(inline_1.inline, '"', [[/^\\?\n/, 4], ['"', 3]]))), (0, source_1.str)('"'), true, undefined, ([as, bs = []], rest) => [(0, array_1.unshift)(as, bs), rest]), (0, combinator_1.surround)((0, source_1.str)('“'), (0, combinator_1.creation)((0, combinator_1.syntax)(0 /* Syntax.none */, 3, 0 /* State.none */, (0, combinator_1.some)(inline_1.inline, '”', [[/^\\?\n/, 4], ['”', 3]]))), (0, source_1.str)('”'), true, undefined, ([as, bs = []], rest) => [(0, array_1.unshift)(as, bs), rest]), (0, combinator_1.surround)((0, source_1.str)('‘'), (0, combinator_1.creation)((0, combinator_1.syntax)(0 /* Syntax.none */, 3, 0 /* State.none */, (0, combinator_1.some)(inline_1.inline, '’', [[/^\\?\n/, 4], ['’', 3]]))), (0, source_1.str)('’'), true, undefined, ([as, bs = []], rest) => [(0, array_1.unshift)(as, bs), rest]), (0, combinator_1.surround)((0, source_1.str)('「'), (0, combinator_1.creation)((0, combinator_1.syntax)(0 /* Syntax.none */, 3, 0 /* State.none */, (0, combinator_1.some)(inline_1.inline, '」', [[/^\\?\n/, 4], ['」', 3]]))), (0, source_1.str)('」'), true, undefined, ([as, bs = []], rest) => [(0, array_1.unshift)(as, bs), rest]), (0, combinator_1.surround)((0, source_1.str)('『'), (0, combinator_1.creation)((0, combinator_1.syntax)(0 /* Syntax.none */, 3, 0 /* State.none */, (0, combinator_1.some)(inline_1.inline, '』', [[/^\\?\n/, 4], ['』', 3]]))), (0, source_1.str)('』'), true, undefined, ([as, bs = []], rest) => [(0, array_1.unshift)(as, bs), rest])]));
|
|
6088
6066
|
|
|
6089
6067
|
/***/ }),
|
|
6090
6068
|
|
|
@@ -7582,7 +7560,7 @@ exports.isAlphanumeric = exports.linebreak = exports.txt = exports.text = export
|
|
|
7582
7560
|
const combinator_1 = __webpack_require__(2087);
|
|
7583
7561
|
const str_1 = __webpack_require__(2790);
|
|
7584
7562
|
const dom_1 = __webpack_require__(3252);
|
|
7585
|
-
exports.delimiter = /[\s\x00-\x7F
|
|
7563
|
+
exports.delimiter = /[\s\x00-\x7F()[]{}“”‘’「」『』]|\S[#>]/u;
|
|
7586
7564
|
exports.nonWhitespace = /[\S\n]|$/u;
|
|
7587
7565
|
exports.nonAlphanumeric = /[^0-9A-Za-z]|\S[#>]|$/u;
|
|
7588
7566
|
const repeat = (0, str_1.str)(/^(.)\1*/);
|
package/markdown.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -37,12 +37,12 @@ export class Delimiters {
|
|
|
37
37
|
delims: readonly {
|
|
38
38
|
readonly signature: string;
|
|
39
39
|
readonly matcher: (source: string) => boolean | undefined;
|
|
40
|
-
readonly precedence
|
|
40
|
+
readonly precedence: number;
|
|
41
41
|
}[]
|
|
42
42
|
): void {
|
|
43
43
|
const { registry, delimiters, order } = this;
|
|
44
44
|
for (let i = 0; i < delims.length; ++i) {
|
|
45
|
-
const { signature, matcher, precedence
|
|
45
|
+
const { signature, matcher, precedence } = delims[i];
|
|
46
46
|
const stack = registry(signature);
|
|
47
47
|
const index = stack[0]?.index ?? delimiters.length;
|
|
48
48
|
if (stack.length === 0 || precedence > delimiters[index].precedence) {
|
|
@@ -61,7 +61,7 @@ export class Delimiters {
|
|
|
61
61
|
}
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
|
-
public pop(count
|
|
64
|
+
public pop(count: number): void {
|
|
65
65
|
assert(count > 0);
|
|
66
66
|
const { registry, delimiters, order } = this;
|
|
67
67
|
for (let i = 0; i < count; ++i) {
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
export class Memo {
|
|
2
|
-
constructor(
|
|
2
|
+
constructor(
|
|
3
|
+
public readonly targets = ~0,
|
|
4
|
+
) {
|
|
3
5
|
this.targets = targets;
|
|
4
6
|
}
|
|
5
|
-
|
|
6
|
-
private readonly memory: Record<number, Record<number, readonly [any[], number] | readonly []>>[/* pos */] = [];
|
|
7
|
+
private memory: Record<number, Record<number, readonly [any[], number] | readonly []>>[/* pos */] = [];
|
|
7
8
|
public get length(): number {
|
|
8
9
|
return this.memory.length;
|
|
9
10
|
}
|
|
@@ -32,11 +33,14 @@ export class Memo {
|
|
|
32
33
|
: [];
|
|
33
34
|
//console.log('set', position, syntax, state, record[syntax]?.[state]);
|
|
34
35
|
}
|
|
35
|
-
public
|
|
36
|
+
public resize(position: number): void {
|
|
36
37
|
const memory = this.memory;
|
|
37
38
|
for (let len = memory.length, i = position; i < len; ++i) {
|
|
38
39
|
memory.pop();
|
|
39
40
|
}
|
|
40
|
-
//console.log('
|
|
41
|
+
//console.log('resize', position + 1);
|
|
42
|
+
}
|
|
43
|
+
public clear(): void {
|
|
44
|
+
this.memory = [];
|
|
41
45
|
}
|
|
42
46
|
}
|
|
@@ -1,12 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ObjectCreate } from 'spica/alias';
|
|
2
2
|
import { Parser, Result, Ctx, Tree, Context, eval, exec } from '../../data/parser';
|
|
3
3
|
import { Memo } from './context/memo';
|
|
4
4
|
|
|
5
5
|
export function reset<P extends Parser<unknown>>(base: Context<P>, parser: P): P;
|
|
6
6
|
export function reset<T>(base: Ctx, parser: Parser<T>): Parser<T> {
|
|
7
|
-
if (!('memo' in base)) {
|
|
8
|
-
base.memo = undefined;
|
|
9
|
-
}
|
|
10
7
|
assert(Object.getPrototypeOf(base) === Object.prototype);
|
|
11
8
|
assert(Object.freeze(base));
|
|
12
9
|
const changes = Object.entries(base);
|
|
@@ -27,41 +24,38 @@ export function context<T>(base: Ctx, parser: Parser<T>): Parser<T> {
|
|
|
27
24
|
|
|
28
25
|
function apply<P extends Parser<unknown>>(parser: P, source: string, context: Context<P>, changes: readonly [string, unknown][], values: unknown[], reset?: boolean): Result<Tree<P>>;
|
|
29
26
|
function apply<T>(parser: Parser<T>, source: string, context: Ctx, changes: readonly [string, unknown][], values: unknown[], reset = false): Result<T> {
|
|
30
|
-
|
|
27
|
+
for (let i = 0; i < changes.length; ++i) {
|
|
31
28
|
const change = changes[i];
|
|
32
29
|
const prop = change[0];
|
|
33
30
|
switch (prop) {
|
|
34
31
|
case 'resources':
|
|
35
|
-
|
|
36
|
-
assert(
|
|
37
|
-
assert(
|
|
38
|
-
|
|
39
|
-
context
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
if (!reset) break;
|
|
44
|
-
context.memo = new Memo({ targets: context.memo?.targets });
|
|
45
|
-
// fallthrough
|
|
46
|
-
default:
|
|
47
|
-
values[i] = context[prop];
|
|
48
|
-
context[prop] = change[1];
|
|
32
|
+
assert(reset);
|
|
33
|
+
assert(!context.offset);
|
|
34
|
+
assert(!context.precedence);
|
|
35
|
+
assert(!context.delimiters);
|
|
36
|
+
assert(!context.state);
|
|
37
|
+
assert(!context.memo);
|
|
38
|
+
context[prop as string] ??= ObjectCreate(change[1] as object);
|
|
39
|
+
continue;
|
|
49
40
|
}
|
|
41
|
+
values[i] = context[prop];
|
|
42
|
+
context[prop] = change[1];
|
|
50
43
|
}
|
|
51
44
|
const result = parser({ source, context });
|
|
52
|
-
|
|
45
|
+
for (let i = 0; i < changes.length; ++i) {
|
|
53
46
|
const change = changes[i];
|
|
54
47
|
const prop = change[0];
|
|
55
48
|
switch (prop) {
|
|
56
49
|
case 'resources':
|
|
57
|
-
|
|
50
|
+
assert(reset);
|
|
51
|
+
break;
|
|
58
52
|
case 'memo':
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
context[prop] = values[i];
|
|
63
|
-
values[i] = undefined;
|
|
53
|
+
assert(reset);
|
|
54
|
+
context.memo!.clear();
|
|
55
|
+
break;
|
|
64
56
|
}
|
|
57
|
+
context[prop] = values[i];
|
|
58
|
+
values[i] = undefined;
|
|
65
59
|
}
|
|
66
60
|
return result;
|
|
67
61
|
}
|
|
@@ -87,7 +81,7 @@ export function syntax<T>(syntax: number, prec: number, state: number, parser?:
|
|
|
87
81
|
}
|
|
88
82
|
if (result && !stateOuter && memo.length! >= position + 2) {
|
|
89
83
|
assert(!(stateOuter & memo.targets));
|
|
90
|
-
memo.
|
|
84
|
+
memo.resize(position + 2);
|
|
91
85
|
}
|
|
92
86
|
context.state = stateOuter;
|
|
93
87
|
return result;
|
package/src/parser/api/bind.ts
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import { ParserSettings, Progress } from '../../..';
|
|
2
2
|
import { MarkdownParser } from '../../../markdown';
|
|
3
3
|
import { eval } from '../../combinator/data/parser';
|
|
4
|
-
import { Memo } from '../../combinator/data/parser/context/memo';
|
|
5
4
|
import { segment, validate, MAX_INPUT_SIZE } from '../segment';
|
|
6
5
|
import { header } from '../header';
|
|
7
6
|
import { block } from '../block';
|
|
8
|
-
import { State } from '../context';
|
|
9
7
|
import { normalize } from './normalize';
|
|
10
8
|
import { headers } from './header';
|
|
11
9
|
import { figure } from '../processor/figure';
|
|
@@ -24,12 +22,12 @@ export function bind(target: DocumentFragment | HTMLElement | ShadowRoot, settin
|
|
|
24
22
|
let context: MarkdownParser.Context = {
|
|
25
23
|
...settings,
|
|
26
24
|
host: settings.host ?? new ReadonlyURL(location.pathname, location.origin),
|
|
27
|
-
memo: new Memo({ targets: State.backtrackers }),
|
|
28
25
|
};
|
|
29
26
|
assert(!context.offset);
|
|
30
27
|
assert(!context.precedence);
|
|
31
28
|
assert(!context.delimiters);
|
|
32
29
|
assert(!context.state);
|
|
30
|
+
assert(!context.memo);
|
|
33
31
|
if (context.id?.match(/[^0-9a-z/-]/i)) throw new Error('Invalid ID: ID must be alphanumeric');
|
|
34
32
|
if (context.host?.origin === 'null') throw new Error(`Invalid host: ${context.host.href}`);
|
|
35
33
|
type Block = readonly [segment: string, blocks: readonly HTMLElement[], url: string];
|
|
@@ -333,7 +333,6 @@ describe('Unit: parser/api/parse', () => {
|
|
|
333
333
|
|
|
334
334
|
it('creation', function () {
|
|
335
335
|
this.timeout(5000);
|
|
336
|
-
// 実測500ms程度
|
|
337
336
|
assert.deepStrictEqual(
|
|
338
337
|
[...parse('.'.repeat(20000)).children].map(el => el.outerHTML),
|
|
339
338
|
[`<p>${'.'.repeat(20000)}</p>`]);
|
|
@@ -341,7 +340,6 @@ describe('Unit: parser/api/parse', () => {
|
|
|
341
340
|
|
|
342
341
|
it('creation error', function () {
|
|
343
342
|
this.timeout(5000);
|
|
344
|
-
// 実測500ms程度
|
|
345
343
|
assert.deepStrictEqual(
|
|
346
344
|
[...parse('.'.repeat(20001)).children].map(el => el.outerHTML.replace(/:\w+/, ':rnd')),
|
|
347
345
|
[
|
|
@@ -350,6 +348,16 @@ describe('Unit: parser/api/parse', () => {
|
|
|
350
348
|
]);
|
|
351
349
|
});
|
|
352
350
|
|
|
351
|
+
it('recovery', function () {
|
|
352
|
+
this.timeout(5000);
|
|
353
|
+
assert.deepStrictEqual(
|
|
354
|
+
[...parse(`!>> ${'['.repeat(20)}${'{a}'.repeat(518)}\n> ${'{a}'.repeat(4)}\n\na`).children].map(el => el.outerHTML),
|
|
355
|
+
[
|
|
356
|
+
`<blockquote><blockquote><section><p>${'['.repeat(20)}${'<a class="url" href="a">a</a>'.repeat(518)}</p><h2>References</h2><ol class="references"></ol></section></blockquote><section><h1 class="error">Error: Too many creations</h1><pre class="error" translate="no">{a}{a}{a}{a}</pre><h2>References</h2><ol class="references"></ol></section></blockquote>`,
|
|
357
|
+
'<p>a</p>',
|
|
358
|
+
]);
|
|
359
|
+
});
|
|
360
|
+
|
|
353
361
|
});
|
|
354
362
|
|
|
355
363
|
});
|
package/src/parser/api/parse.ts
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import { ParserOptions } from '../../..';
|
|
2
2
|
import { MarkdownParser } from '../../../markdown';
|
|
3
3
|
import { eval } from '../../combinator/data/parser';
|
|
4
|
-
import { Memo } from '../../combinator/data/parser/context/memo';
|
|
5
4
|
import { segment, validate, MAX_SEGMENT_SIZE } from '../segment';
|
|
6
5
|
import { header } from '../header';
|
|
7
6
|
import { block } from '../block';
|
|
8
|
-
import { State } from '../context';
|
|
9
7
|
import { normalize } from './normalize';
|
|
10
8
|
import { headers } from './header';
|
|
11
9
|
import { figure } from '../processor/figure';
|
|
@@ -26,15 +24,13 @@ export function parse(source: string, opts: Options = {}, context?: MarkdownPars
|
|
|
26
24
|
url: url ? new ReadonlyURL(url as ':') : context?.url,
|
|
27
25
|
id: opts.id ?? context?.id,
|
|
28
26
|
caches: context?.caches,
|
|
29
|
-
|
|
30
|
-
resources: context.resources,
|
|
31
|
-
},
|
|
32
|
-
memo: new Memo({ targets: State.backtrackers }),
|
|
27
|
+
resources: context?.resources,
|
|
33
28
|
};
|
|
34
29
|
assert(!context.offset);
|
|
35
30
|
assert(!context.precedence);
|
|
36
31
|
assert(!context.delimiters);
|
|
37
32
|
assert(!context.state);
|
|
33
|
+
assert(!context.memo);
|
|
38
34
|
if (context.id?.match(/[^0-9a-z/-]/i)) throw new Error('Invalid ID: ID must be alphanumeric');
|
|
39
35
|
if (context.host?.origin === 'null') throw new Error(`Invalid host: ${context.host.href}`);
|
|
40
36
|
const node = frag();
|
package/src/parser/block.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { MarkdownParser } from '../../markdown';
|
|
2
2
|
import { union, reset, creation, open, fallback, recover } from '../combinator';
|
|
3
|
+
import { Memo } from '../combinator/data/parser/context/memo';
|
|
3
4
|
import { emptyline } from './source';
|
|
4
5
|
import { pagebreak } from './block/pagebreak';
|
|
5
6
|
import { heading } from './block/heading';
|
|
@@ -16,6 +17,7 @@ import { blockquote } from './block/blockquote';
|
|
|
16
17
|
import { mediablock } from './block/mediablock';
|
|
17
18
|
import { reply } from './block/reply';
|
|
18
19
|
import { paragraph } from './block/paragraph';
|
|
20
|
+
import { State } from './context';
|
|
19
21
|
import { rnd0Z } from 'spica/random';
|
|
20
22
|
import { html } from 'typed-dom/dom';
|
|
21
23
|
|
|
@@ -36,9 +38,9 @@ export import MediaBlockParser = BlockParser.MediaBlockParser;
|
|
|
36
38
|
export import ReplyParser = BlockParser.ReplyParser;
|
|
37
39
|
export import ParagraphParser = BlockParser.ParagraphParser;
|
|
38
40
|
|
|
39
|
-
export const block: BlockParser = creation(0, false,
|
|
40
|
-
reset({ resources: { clock: 20000, recursion: 20 + 1 } },
|
|
41
|
-
union([
|
|
41
|
+
export const block: BlockParser = creation(0, false,
|
|
42
|
+
reset({ resources: { clock: 20000, recursion: 20 + 1 }, memo: new Memo(State.backtrackers) },
|
|
43
|
+
error(union([
|
|
42
44
|
emptyline,
|
|
43
45
|
pagebreak,
|
|
44
46
|
heading,
|
|
@@ -20,10 +20,28 @@ export const bracket: BracketParser = lazy(() => union([
|
|
|
20
20
|
surround(str('['), creation(syntax(Syntax.bracket, 2, State.none, some(inline, ']', [[/^\\?\n/, 3], [']', 2]]))), str(']'), true,
|
|
21
21
|
undefined,
|
|
22
22
|
([as, bs = []], rest) => [unshift(as, bs), rest]),
|
|
23
|
+
surround(str('['), creation(syntax(Syntax.bracket, 2, State.none, some(inline, ']', [[/^\\?\n/, 3], [']', 2]]))), str(']'), true,
|
|
24
|
+
undefined,
|
|
25
|
+
([as, bs = []], rest) => [unshift(as, bs), rest]),
|
|
23
26
|
surround(str('{'), creation(syntax(Syntax.bracket, 2, State.none, some(inline, '}', [[/^\\?\n/, 3], ['}', 2]]))), str('}'), true,
|
|
24
27
|
undefined,
|
|
25
28
|
([as, bs = []], rest) => [unshift(as, bs), rest]),
|
|
29
|
+
surround(str('{'), creation(syntax(Syntax.bracket, 2, State.none, some(inline, '}', [[/^\\?\n/, 3], ['}', 2]]))), str('}'), true,
|
|
30
|
+
undefined,
|
|
31
|
+
([as, bs = []], rest) => [unshift(as, bs), rest]),
|
|
26
32
|
surround(str('"'), creation(syntax(Syntax.none, 3, State.none, some(inline, '"', [[/^\\?\n/, 4], ['"', 3]]))), str('"'), true,
|
|
27
33
|
undefined,
|
|
28
34
|
([as, bs = []], rest) => [unshift(as, bs), rest]),
|
|
35
|
+
surround(str('“'), creation(syntax(Syntax.none, 3, State.none, some(inline, '”', [[/^\\?\n/, 4], ['”', 3]]))), str('”'), true,
|
|
36
|
+
undefined,
|
|
37
|
+
([as, bs = []], rest) => [unshift(as, bs), rest]),
|
|
38
|
+
surround(str('‘'), creation(syntax(Syntax.none, 3, State.none, some(inline, '’', [[/^\\?\n/, 4], ['’', 3]]))), str('’'), true,
|
|
39
|
+
undefined,
|
|
40
|
+
([as, bs = []], rest) => [unshift(as, bs), rest]),
|
|
41
|
+
surround(str('「'), creation(syntax(Syntax.none, 3, State.none, some(inline, '」', [[/^\\?\n/, 4], ['」', 3]]))), str('」'), true,
|
|
42
|
+
undefined,
|
|
43
|
+
([as, bs = []], rest) => [unshift(as, bs), rest]),
|
|
44
|
+
surround(str('『'), creation(syntax(Syntax.none, 3, State.none, some(inline, '』', [[/^\\?\n/, 4], ['』', 3]]))), str('』'), true,
|
|
45
|
+
undefined,
|
|
46
|
+
([as, bs = []], rest) => [unshift(as, bs), rest]),
|
|
29
47
|
]));
|
|
@@ -3,7 +3,7 @@ import { union, creation, focus } from '../../combinator';
|
|
|
3
3
|
import { str } from './str';
|
|
4
4
|
import { html } from 'typed-dom/dom';
|
|
5
5
|
|
|
6
|
-
export const delimiter = /[\s\x00-\x7F
|
|
6
|
+
export const delimiter = /[\s\x00-\x7F()[]{}“”‘’「」『』]|\S[#>]/u;
|
|
7
7
|
export const nonWhitespace = /[\S\n]|$/u;
|
|
8
8
|
export const nonAlphanumeric = /[^0-9A-Za-z]|\S[#>]|$/u;
|
|
9
9
|
const repeat = str(/^(.)\1*/);
|