securemark 0.298.3 → 0.298.4
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/design.md +1 -5
- package/dist/index.js +64 -71
- package/package.json +1 -1
- package/src/parser/api/bind.ts +13 -16
- package/src/parser/api/parse.test.ts +7 -10
- package/src/parser/api/parse.ts +24 -27
- package/src/parser/block/heading.test.ts +2 -2
- package/src/parser/block/table.test.ts +1 -1
- package/src/parser/block.ts +63 -80
- package/src/parser/context.ts +20 -0
- package/src/parser/inline/annotation.test.ts +19 -19
- package/src/parser/inline/annotation.ts +10 -7
- package/src/parser/inline/bracket.test.ts +11 -11
- package/src/parser/inline/bracket.ts +7 -16
- package/src/parser/inline/emphasis.test.ts +2 -2
- package/src/parser/inline/emstrong.test.ts +3 -3
- package/src/parser/inline/extension/index.test.ts +1 -1
- package/src/parser/inline/italic.test.ts +1 -1
- package/src/parser/inline/link.test.ts +1 -1
- package/src/parser/inline/reference.test.ts +1 -1
- package/src/parser/inline/strong.test.ts +2 -2
- package/src/parser/inline.test.ts +14 -14
- package/src/parser/segment.ts +6 -9
package/CHANGELOG.md
CHANGED
package/design.md
CHANGED
|
@@ -300,11 +300,7 @@ Securemarkはスーパークラス構文が解析に失敗した入力をサブ
|
|
|
300
300
|
|
|
301
301
|
### 実行性能
|
|
302
302
|
|
|
303
|
-
構文数と使用記号数が大きく異なるため単純な比較はできないが直接比較してもにブラウザによるHTML
|
|
304
|
-
|
|
305
|
-
そのほかブラウザの以下の欠陥および低速性により速度低下が生じており今後のブラウザの改善が求められる。
|
|
306
|
-
|
|
307
|
-
- IntersectionObserverが描画完了前に交差を計算するためすべて同時発火する欠陥
|
|
303
|
+
構文数と使用記号数が大きく異なるため単純な比較はできないが直接比較してもにブラウザによるHTMLパース時間を含めた速度差はCommonMarkの1/3、CommonMarkの問題の解決を試みたdjotと同等程度でありすでに十分高速である。
|
|
308
304
|
|
|
309
305
|
### 最適化
|
|
310
306
|
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! securemark v0.298.
|
|
1
|
+
/*! securemark v0.298.4 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"));
|
|
@@ -4163,12 +4163,12 @@ const note_1 = __webpack_require__(165);
|
|
|
4163
4163
|
const url_1 = __webpack_require__(1904);
|
|
4164
4164
|
const array_1 = __webpack_require__(6876);
|
|
4165
4165
|
function bind(target, settings) {
|
|
4166
|
-
const
|
|
4166
|
+
const options = {
|
|
4167
4167
|
...settings,
|
|
4168
4168
|
host: settings.host ?? new url_1.ReadonlyURL(location.pathname, location.origin)
|
|
4169
|
-
}
|
|
4170
|
-
if (
|
|
4171
|
-
if (
|
|
4169
|
+
};
|
|
4170
|
+
if (options.id?.match(/[^0-9a-z/-]/i)) throw new Error('Invalid ID: ID must be alphanumeric');
|
|
4171
|
+
if (options.host?.origin === 'null') throw new Error(`Invalid host: ${options.host.href}`);
|
|
4172
4172
|
const blocks = [];
|
|
4173
4173
|
const adds = [];
|
|
4174
4174
|
const dels = [];
|
|
@@ -4183,11 +4183,11 @@ function bind(target, settings) {
|
|
|
4183
4183
|
if (settings.chunk && revision) throw new Error('Chunks cannot be updated');
|
|
4184
4184
|
const url = (0, header_1.headers)(source).find(field => field.toLowerCase().startsWith('url:'))?.slice(4).trim() ?? '';
|
|
4185
4185
|
// @ts-expect-error
|
|
4186
|
-
|
|
4186
|
+
options.url = url ? new url_1.ReadonlyURL(url) : undefined;
|
|
4187
4187
|
const rev = revision = Symbol();
|
|
4188
4188
|
const sourceSegments = [];
|
|
4189
4189
|
const sourceSegmentAttrs = [];
|
|
4190
|
-
for (const [seg, attr] of (0, segment_1.segment)(source,
|
|
4190
|
+
for (const [seg, attr] of (0, segment_1.segment)(source, true)) {
|
|
4191
4191
|
sourceSegments.push(seg);
|
|
4192
4192
|
sourceSegmentAttrs.push(attr);
|
|
4193
4193
|
yield {
|
|
@@ -4210,15 +4210,15 @@ function bind(target, settings) {
|
|
|
4210
4210
|
const base = next(head);
|
|
4211
4211
|
let index = head;
|
|
4212
4212
|
// @ts-expect-error
|
|
4213
|
-
|
|
4213
|
+
options.header = true;
|
|
4214
4214
|
for (; index < sourceSegments.length - last; ++index) {
|
|
4215
4215
|
const seg = sourceSegments[index];
|
|
4216
|
-
|
|
4217
|
-
const es = (0, block_1.block)((0, parser_1.input)(seg, new context_1.Context(
|
|
4216
|
+
options.segment = sourceSegmentAttrs[index] | 1 /* Segment.write */;
|
|
4217
|
+
const es = (0, block_1.block)((0, parser_1.input)(seg, new context_1.Context(options))).foldl((acc, {
|
|
4218
4218
|
value
|
|
4219
4219
|
}) => void acc.push(value) || acc, []);
|
|
4220
4220
|
// @ts-expect-error
|
|
4221
|
-
|
|
4221
|
+
options.header = false;
|
|
4222
4222
|
blocks.length === index ? blocks.push([seg, es, url]) : blocks.splice(index, 0, [seg, es, url]);
|
|
4223
4223
|
if (es.length === 0) continue;
|
|
4224
4224
|
// All deletion processes always run after all addition processes have done.
|
|
@@ -4272,7 +4272,7 @@ function bind(target, settings) {
|
|
|
4272
4272
|
if (rev !== revision) return yield {
|
|
4273
4273
|
type: 'cancel'
|
|
4274
4274
|
};
|
|
4275
|
-
for (const el of (0, figure_1.figure)(next(0)?.parentNode ?? target, settings.notes,
|
|
4275
|
+
for (const el of (0, figure_1.figure)(next(0)?.parentNode ?? target, settings.notes, options)) {
|
|
4276
4276
|
el ? yield {
|
|
4277
4277
|
type: 'figure',
|
|
4278
4278
|
value: el
|
|
@@ -4283,7 +4283,7 @@ function bind(target, settings) {
|
|
|
4283
4283
|
type: 'cancel'
|
|
4284
4284
|
};
|
|
4285
4285
|
}
|
|
4286
|
-
for (const el of (0, note_1.note)(next(0)?.parentNode ?? target, settings.notes,
|
|
4286
|
+
for (const el of (0, note_1.note)(next(0)?.parentNode ?? target, settings.notes, options, bottom)) {
|
|
4287
4287
|
el ? yield {
|
|
4288
4288
|
type: 'note',
|
|
4289
4289
|
value: el
|
|
@@ -4512,34 +4512,34 @@ const figure_1 = __webpack_require__(1657);
|
|
|
4512
4512
|
const note_1 = __webpack_require__(165);
|
|
4513
4513
|
const url_1 = __webpack_require__(1904);
|
|
4514
4514
|
const dom_1 = __webpack_require__(394);
|
|
4515
|
-
function parse(source,
|
|
4515
|
+
function parse(source, opts = {}, options) {
|
|
4516
4516
|
const url = (0, header_1.headers)(source).find(field => field.toLowerCase().startsWith('url:'))?.slice(4).trim() ?? '';
|
|
4517
|
-
|
|
4518
|
-
host:
|
|
4519
|
-
url: url ? new url_1.ReadonlyURL(url) :
|
|
4520
|
-
id:
|
|
4521
|
-
local:
|
|
4522
|
-
caches:
|
|
4523
|
-
resources:
|
|
4524
|
-
}
|
|
4525
|
-
if (
|
|
4526
|
-
if (
|
|
4517
|
+
options = {
|
|
4518
|
+
host: opts.host ?? options?.host ?? new url_1.ReadonlyURL(location.pathname, location.origin),
|
|
4519
|
+
url: url ? new url_1.ReadonlyURL(url) : options?.url,
|
|
4520
|
+
id: opts.id ?? options?.id,
|
|
4521
|
+
local: opts.local ?? options?.local ?? false,
|
|
4522
|
+
caches: options?.caches,
|
|
4523
|
+
resources: options?.resources
|
|
4524
|
+
};
|
|
4525
|
+
if (options.id?.match(/[^0-9a-z/-]/i)) throw new Error('Invalid ID: ID must be alphanumeric');
|
|
4526
|
+
if (options.host?.origin === 'null') throw new Error(`Invalid host: ${options.host.href}`);
|
|
4527
4527
|
const node = (0, dom_1.frag)();
|
|
4528
4528
|
// @ts-expect-error
|
|
4529
|
-
|
|
4530
|
-
for (const [seg, attr] of (0, segment_1.segment)(source, !
|
|
4531
|
-
|
|
4532
|
-
const es = (0, block_1.block)((0, parser_1.input)(seg, new context_1.Context(
|
|
4529
|
+
options.header = true;
|
|
4530
|
+
for (const [seg, attr] of (0, segment_1.segment)(source, !options.local)) {
|
|
4531
|
+
options.segment = attr | 1 /* Segment.write */;
|
|
4532
|
+
const es = (0, block_1.block)((0, parser_1.input)(seg, new context_1.Context(options))).foldl((acc, {
|
|
4533
4533
|
value
|
|
4534
4534
|
}) => void acc.push(value) || acc, []);
|
|
4535
4535
|
// @ts-expect-error
|
|
4536
|
-
|
|
4536
|
+
options.header = false;
|
|
4537
4537
|
if (es.length === 0) continue;
|
|
4538
4538
|
node.append(...es);
|
|
4539
4539
|
}
|
|
4540
|
-
if (
|
|
4541
|
-
for (const _ of (0, figure_1.figure)(node,
|
|
4542
|
-
for (const _ of (0, note_1.note)(node,
|
|
4540
|
+
if (opts.test) return node;
|
|
4541
|
+
for (const _ of (0, figure_1.figure)(node, opts.notes, options));
|
|
4542
|
+
for (const _ of (0, note_1.note)(node, opts.notes, options));
|
|
4543
4543
|
return node;
|
|
4544
4544
|
}
|
|
4545
4545
|
exports.parse = parse;
|
|
@@ -4575,7 +4575,6 @@ Object.defineProperty(exports, "__esModule", ({
|
|
|
4575
4575
|
exports.block = void 0;
|
|
4576
4576
|
const parser_1 = __webpack_require__(605);
|
|
4577
4577
|
const combinator_1 = __webpack_require__(3484);
|
|
4578
|
-
const segment_1 = __webpack_require__(3967);
|
|
4579
4578
|
const header_1 = __webpack_require__(3009);
|
|
4580
4579
|
const source_1 = __webpack_require__(8745);
|
|
4581
4580
|
const pagebreak_1 = __webpack_require__(2946);
|
|
@@ -4598,13 +4597,7 @@ const reply_1 = __webpack_require__(3832);
|
|
|
4598
4597
|
const paragraph_1 = __webpack_require__(4330);
|
|
4599
4598
|
const random_1 = __webpack_require__(3158);
|
|
4600
4599
|
const dom_1 = __webpack_require__(394);
|
|
4601
|
-
exports.block = (0, combinator_1.
|
|
4602
|
-
resources: {
|
|
4603
|
-
// バックトラックのせいで文字数制限を受けないようにする。
|
|
4604
|
-
clock: segment_1.MAX_SEGMENT_SIZE * 6 + 1,
|
|
4605
|
-
recursions: [5 || 0 /* Recursion.block */, 20 || 0 /* Recursion.blockquote */, 40 || 0 /* Recursion.listitem */, 20 || 0 /* Recursion.inline */, 20 || 0 /* Recursion.annotation */, 20 || 0 /* Recursion.bracket */, 20 || 0 /* Recursion.terminal */]
|
|
4606
|
-
}
|
|
4607
|
-
}, error((0, combinator_1.union)([source_1.emptysegment, input => {
|
|
4600
|
+
exports.block = error((0, combinator_1.union)([source_1.emptysegment, input => {
|
|
4608
4601
|
const {
|
|
4609
4602
|
source,
|
|
4610
4603
|
position,
|
|
@@ -4665,7 +4658,7 @@ exports.block = (0, combinator_1.reset)({
|
|
|
4665
4658
|
default:
|
|
4666
4659
|
if ('0' <= char && char <= '9') return (0, olist_1.olist)(input);
|
|
4667
4660
|
}
|
|
4668
|
-
}, paragraph_1.paragraph]))
|
|
4661
|
+
}, paragraph_1.paragraph]));
|
|
4669
4662
|
function error(parser) {
|
|
4670
4663
|
const reg = new RegExp(String.raw`^${"\u0007" /* Command.Error */}[^\r\n]*\r?\n`);
|
|
4671
4664
|
return (0, combinator_1.recover)(parser, ({
|
|
@@ -6011,8 +6004,10 @@ function format(list) {
|
|
|
6011
6004
|
Object.defineProperty(exports, "__esModule", ({
|
|
6012
6005
|
value: true
|
|
6013
6006
|
}));
|
|
6014
|
-
exports.CmdRegExp = exports.Context = void 0;
|
|
6007
|
+
exports.CmdRegExp = exports.Context = exports.MAX_INPUT_SIZE = exports.MAX_SEGMENT_SIZE = void 0;
|
|
6015
6008
|
const parser_1 = __webpack_require__(605);
|
|
6009
|
+
exports.MAX_SEGMENT_SIZE = 100_000; // 100,000 bytes (Max value size of FDB)
|
|
6010
|
+
exports.MAX_INPUT_SIZE = exports.MAX_SEGMENT_SIZE * 10;
|
|
6016
6011
|
class Context extends parser_1.Context {
|
|
6017
6012
|
constructor(options = {}) {
|
|
6018
6013
|
super(options);
|
|
@@ -6028,6 +6023,11 @@ class Context extends parser_1.Context {
|
|
|
6028
6023
|
id,
|
|
6029
6024
|
caches
|
|
6030
6025
|
} = options;
|
|
6026
|
+
this.resources ??= {
|
|
6027
|
+
// バックトラックのせいで文字数制限を受けないようにする。
|
|
6028
|
+
clock: exports.MAX_SEGMENT_SIZE * (6 + 1),
|
|
6029
|
+
recursions: [5 || 0 /* Recursion.block */, 20 || 0 /* Recursion.blockquote */, 40 || 0 /* Recursion.listitem */, 20 || 0 /* Recursion.inline */, 20 || 0 /* Recursion.annotation */, 20 || 0 /* Recursion.bracket */, 20 || 0 /* Recursion.terminal */]
|
|
6030
|
+
};
|
|
6031
6031
|
this.segment = segment ?? 0 /* Segment.unknown */;
|
|
6032
6032
|
this.local = local ?? false;
|
|
6033
6033
|
this.sequential = sequential ?? false;
|
|
@@ -6303,9 +6303,9 @@ exports.annotation = (0, combinator_1.lazy)(() => (0, combinator_1.constraint)(1
|
|
|
6303
6303
|
ns.unshift(new parser_1.Node('('));
|
|
6304
6304
|
ns.push(new parser_1.Node(')'));
|
|
6305
6305
|
return new parser_1.List([new parser_1.Node((0, dom_1.html)('span', {
|
|
6306
|
-
class:
|
|
6306
|
+
class: (0, bracket_1.bracketname)(context, 1, 1)
|
|
6307
6307
|
}, ['(', (0, dom_1.html)('span', {
|
|
6308
|
-
class:
|
|
6308
|
+
class: (0, bracket_1.bracketname)(context, 2, 2)
|
|
6309
6309
|
}, (0, dom_1.defrag)((0, util_1.unwrap)(ns))), ')']))]);
|
|
6310
6310
|
}
|
|
6311
6311
|
const depth = MAX_DEPTH - (resources?.recursions[4 /* Recursion.annotation */] ?? resources?.recursions.at(-1) ?? MAX_DEPTH);
|
|
@@ -6344,7 +6344,7 @@ exports.annotation = (0, combinator_1.lazy)(() => (0, combinator_1.constraint)(1
|
|
|
6344
6344
|
context.position += 1;
|
|
6345
6345
|
recursion.add(depth);
|
|
6346
6346
|
return new parser_1.List([new parser_1.Node((0, dom_1.html)('span', {
|
|
6347
|
-
class: '
|
|
6347
|
+
class: 'paren'
|
|
6348
6348
|
}, ['(', (0, dom_1.html)('sup', {
|
|
6349
6349
|
class: 'annotation'
|
|
6350
6350
|
}, [(0, dom_1.html)('span', bs.head.value.childNodes)])]))]);
|
|
@@ -6353,7 +6353,7 @@ exports.annotation = (0, combinator_1.lazy)(() => (0, combinator_1.constraint)(1
|
|
|
6353
6353
|
context.position += 1;
|
|
6354
6354
|
recursion.add(depth);
|
|
6355
6355
|
return new parser_1.List([new parser_1.Node((0, dom_1.html)('span', {
|
|
6356
|
-
class: '
|
|
6356
|
+
class: 'paren'
|
|
6357
6357
|
}, ['(', (0, dom_1.html)('sup', {
|
|
6358
6358
|
class: 'annotation'
|
|
6359
6359
|
}, [(0, dom_1.html)('span', [bs.head.value])])]))]);
|
|
@@ -6367,7 +6367,7 @@ exports.annotation = (0, combinator_1.lazy)(() => (0, combinator_1.constraint)(1
|
|
|
6367
6367
|
context.range += 1;
|
|
6368
6368
|
}
|
|
6369
6369
|
bs = new parser_1.List([new parser_1.Node((0, dom_1.html)('span', {
|
|
6370
|
-
class: (0, bracket_1.bracketname)(context,
|
|
6370
|
+
class: (0, bracket_1.bracketname)(context, 2, context.position - position)
|
|
6371
6371
|
}, (0, dom_1.defrag)((0, util_1.unwrap)(bs))))]);
|
|
6372
6372
|
bs.unshift(new parser_1.Node('('));
|
|
6373
6373
|
const cs = parser(context);
|
|
@@ -6375,9 +6375,10 @@ exports.annotation = (0, combinator_1.lazy)(() => (0, combinator_1.constraint)(1
|
|
|
6375
6375
|
cs && bs.import(cs);
|
|
6376
6376
|
bs.push(new parser_1.Node(')'));
|
|
6377
6377
|
context.position += 1;
|
|
6378
|
+
context.range += 1;
|
|
6378
6379
|
}
|
|
6379
6380
|
return new parser_1.List([new parser_1.Node((0, dom_1.html)('span', {
|
|
6380
|
-
class:
|
|
6381
|
+
class: (0, bracket_1.bracketname)(context, 1, context.position - position)
|
|
6381
6382
|
}, (0, dom_1.defrag)((0, util_1.unwrap)(bs))))]);
|
|
6382
6383
|
})));
|
|
6383
6384
|
const parser = (0, combinator_1.lazy)(() => (0, combinator_1.precedence)(1, (0, combinator_1.some)(inline_1.inline, ')', [[')', 1]])));
|
|
@@ -6664,7 +6665,7 @@ const bracket = (0, combinator_1.lazy)(() => (0, combinator_1.union)([(0, combin
|
|
|
6664
6665
|
Object.defineProperty(exports, "__esModule", ({
|
|
6665
6666
|
value: true
|
|
6666
6667
|
}));
|
|
6667
|
-
exports.bracket = exports.bracketname =
|
|
6668
|
+
exports.bracket = exports.bracketname = void 0;
|
|
6668
6669
|
const parser_1 = __webpack_require__(605);
|
|
6669
6670
|
const combinator_1 = __webpack_require__(3484);
|
|
6670
6671
|
const inline_1 = __webpack_require__(7973);
|
|
@@ -6672,17 +6673,12 @@ const link_1 = __webpack_require__(3628);
|
|
|
6672
6673
|
const source_1 = __webpack_require__(8745);
|
|
6673
6674
|
const util_1 = __webpack_require__(4992);
|
|
6674
6675
|
const dom_1 = __webpack_require__(394);
|
|
6675
|
-
|
|
6676
|
-
const indexF = new RegExp(exports.indexA.source.replace(', ', '[,、]').replace(/[09AZaz.]|\-(?!\w)/g, c => String.fromCodePoint(c.codePointAt(0) + 0xFEE0)), '');
|
|
6677
|
-
function bracketname(context, syntax, opener, closer) {
|
|
6676
|
+
function bracketname(context, opener, closer) {
|
|
6678
6677
|
const {
|
|
6679
|
-
source,
|
|
6680
|
-
position,
|
|
6681
6678
|
range,
|
|
6682
6679
|
linebreak
|
|
6683
6680
|
} = context;
|
|
6684
|
-
|
|
6685
|
-
return range - opener - closer === 0 || linebreak === 0 && range - opener - closer <= 16 && syntax.test(source.slice(position - range + opener, position - closer)) ? 'paren' : 'bracket';
|
|
6681
|
+
return range - opener - closer === 0 || linebreak === 0 && range - opener - closer <= 16 ? 'paren' : 'bracket';
|
|
6686
6682
|
}
|
|
6687
6683
|
exports.bracketname = bracketname;
|
|
6688
6684
|
exports.bracket = (0, combinator_1.lazy)(() => (0, combinator_1.union)([input => {
|
|
@@ -6708,14 +6704,14 @@ exports.bracket = (0, combinator_1.lazy)(() => (0, combinator_1.union)([input =>
|
|
|
6708
6704
|
}
|
|
6709
6705
|
}]));
|
|
6710
6706
|
const p1 = (0, combinator_1.lazy)(() => (0, combinator_1.surround)((0, source_1.str)('('), (0, combinator_1.precedence)(1, (0, combinator_1.recursion)(5 /* Recursion.bracket */, (0, combinator_1.some)(inline_1.inline, ')', [[')', 1]]))), (0, source_1.str)(')'), true, [], ([as, bs = new parser_1.List(), cs], context) => new parser_1.List([new parser_1.Node((0, dom_1.html)('span', {
|
|
6711
|
-
class: bracketname(context,
|
|
6707
|
+
class: bracketname(context, 1, 1)
|
|
6712
6708
|
}, (0, dom_1.defrag)((0, util_1.unwrap)(as.import(bs).import(cs)))))]), ([as, bs = new parser_1.List()], context) => new parser_1.List([new parser_1.Node((0, dom_1.html)('span', {
|
|
6713
|
-
class: bracketname(context,
|
|
6709
|
+
class: bracketname(context, 1, 0)
|
|
6714
6710
|
}, (0, dom_1.defrag)((0, util_1.unwrap)(as.import(bs)))))])));
|
|
6715
6711
|
const p2 = (0, combinator_1.lazy)(() => (0, combinator_1.surround)((0, source_1.str)('('), (0, combinator_1.precedence)(1, (0, combinator_1.recursion)(5 /* Recursion.bracket */, (0, combinator_1.some)(inline_1.inline, ')', [[')', 1]]))), (0, source_1.str)(')'), true, [], ([as, bs = new parser_1.List(), cs], context) => new parser_1.List([new parser_1.Node((0, dom_1.html)('span', {
|
|
6716
|
-
class: bracketname(context,
|
|
6712
|
+
class: bracketname(context, 1, 1)
|
|
6717
6713
|
}, (0, dom_1.defrag)((0, util_1.unwrap)(as.import(bs).import(cs)))))]), ([as, bs = new parser_1.List()], context) => new parser_1.List([new parser_1.Node((0, dom_1.html)('span', {
|
|
6718
|
-
class: bracketname(context,
|
|
6714
|
+
class: bracketname(context, 1, 0)
|
|
6719
6715
|
}, (0, dom_1.defrag)((0, util_1.unwrap)(as.import(bs)))))])));
|
|
6720
6716
|
const s1 = (0, combinator_1.lazy)(() => (0, combinator_1.surround)((0, source_1.str)('['), (0, combinator_1.precedence)(1, (0, combinator_1.recursion)(5 /* Recursion.bracket */, (0, combinator_1.some)(inline_1.inline, ']', [[']', 1]]))), (0, source_1.str)(']'), true, [2 | 4 /* Backtrack.common */], ([as, bs = new parser_1.List(), cs], context) => {
|
|
6721
6717
|
const {
|
|
@@ -8419,7 +8415,7 @@ function* proc(note, defs) {
|
|
|
8419
8415
|
Object.defineProperty(exports, "__esModule", ({
|
|
8420
8416
|
value: true
|
|
8421
8417
|
}));
|
|
8422
|
-
exports.
|
|
8418
|
+
exports.segment = void 0;
|
|
8423
8419
|
const context_1 = __webpack_require__(8669);
|
|
8424
8420
|
const combinator_1 = __webpack_require__(3484);
|
|
8425
8421
|
const heading_1 = __webpack_require__(2778);
|
|
@@ -8428,9 +8424,7 @@ const mathblock_1 = __webpack_require__(4903);
|
|
|
8428
8424
|
const extension_1 = __webpack_require__(6193);
|
|
8429
8425
|
const source_1 = __webpack_require__(8745);
|
|
8430
8426
|
const api_1 = __webpack_require__(5886);
|
|
8431
|
-
|
|
8432
|
-
exports.MAX_INPUT_SIZE = exports.MAX_SEGMENT_SIZE * 10;
|
|
8433
|
-
const parser = (0, combinator_1.union)([(0, combinator_1.some)(source_1.emptysegment, exports.MAX_SEGMENT_SIZE + 1), input => {
|
|
8427
|
+
const parser = (0, combinator_1.union)([(0, combinator_1.some)(source_1.emptysegment, context_1.MAX_SEGMENT_SIZE + 1), input => {
|
|
8434
8428
|
const {
|
|
8435
8429
|
source,
|
|
8436
8430
|
position
|
|
@@ -8452,22 +8446,22 @@ const parser = (0, combinator_1.union)([(0, combinator_1.some)(source_1.emptyseg
|
|
|
8452
8446
|
case '#':
|
|
8453
8447
|
return (0, heading_1.segment)(input);
|
|
8454
8448
|
}
|
|
8455
|
-
}, (0, combinator_1.some)(source_1.contentline,
|
|
8449
|
+
}, (0, combinator_1.some)(source_1.contentline, context_1.MAX_SEGMENT_SIZE + 1)]);
|
|
8456
8450
|
function* segment(source, initial = true) {
|
|
8457
|
-
if (initial && !validate(source,
|
|
8458
|
-
for (let position = 0
|
|
8451
|
+
if (initial && !validate(source, context_1.MAX_INPUT_SIZE)) return yield [`${"\u0007" /* Command.Error */}Too large input over ${context_1.MAX_INPUT_SIZE.toLocaleString('en')} bytes.\n${source.slice(0, 1001)}`, 0 /* Segment.unknown */];
|
|
8452
|
+
for (let position = 0, len = source.length; position < len;) {
|
|
8459
8453
|
const context = new context_1.Context({
|
|
8460
8454
|
source,
|
|
8461
8455
|
position
|
|
8462
8456
|
});
|
|
8463
8457
|
const result = parser(context);
|
|
8464
|
-
const segs = result.length
|
|
8458
|
+
const segs = result.length === 0 ? [source.slice(position, context.position)] : result.foldl((acc, {
|
|
8465
8459
|
value
|
|
8466
|
-
}) =>
|
|
8460
|
+
}) => (acc.push(value), acc), []);
|
|
8467
8461
|
position = context.position;
|
|
8468
8462
|
for (let i = 0; i < segs.length; ++i) {
|
|
8469
8463
|
const seg = segs[i];
|
|
8470
|
-
initial && !validate(seg,
|
|
8464
|
+
initial && !validate(seg, context_1.MAX_SEGMENT_SIZE) ? yield [`${"\u0007" /* Command.Error */}Too large segment over ${context_1.MAX_SEGMENT_SIZE.toLocaleString('en')} bytes.\n${seg}`, 0 /* Segment.unknown */] : yield [initial ? (0, api_1.normalize)(seg) : seg, context.segment];
|
|
8471
8465
|
}
|
|
8472
8466
|
}
|
|
8473
8467
|
}
|
|
@@ -8475,7 +8469,6 @@ exports.segment = segment;
|
|
|
8475
8469
|
function validate(source, size) {
|
|
8476
8470
|
return source.length <= size / 2 || source.length <= size && new Blob([source]).size <= size;
|
|
8477
8471
|
}
|
|
8478
|
-
exports.validate = validate;
|
|
8479
8472
|
|
|
8480
8473
|
/***/ },
|
|
8481
8474
|
|
package/package.json
CHANGED
package/src/parser/api/bind.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ParserSettings, Progress } from '../../..';
|
|
2
|
-
import { Context, Segment } from '../context';
|
|
2
|
+
import { Context, Options, Segment } from '../context';
|
|
3
3
|
import { input } from '../../combinator/data/parser';
|
|
4
4
|
import { segment } from '../segment';
|
|
5
5
|
import { block } from '../block';
|
|
@@ -17,15 +17,12 @@ export function bind(target: DocumentFragment | HTMLElement | ShadowRoot, settin
|
|
|
17
17
|
nearest: (position: number) => HTMLElement | undefined;
|
|
18
18
|
index: (block: HTMLElement) => number;
|
|
19
19
|
} {
|
|
20
|
-
const
|
|
20
|
+
const options: Options = {
|
|
21
21
|
...settings,
|
|
22
22
|
host: settings.host ?? new ReadonlyURL(location.pathname, location.origin),
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
assert(!context.state);
|
|
27
|
-
if (context.id?.match(/[^0-9a-z/-]/i)) throw new Error('Invalid ID: ID must be alphanumeric');
|
|
28
|
-
if (context.host?.origin === 'null') throw new Error(`Invalid host: ${context.host.href}`);
|
|
23
|
+
};
|
|
24
|
+
if (options.id?.match(/[^0-9a-z/-]/i)) throw new Error('Invalid ID: ID must be alphanumeric');
|
|
25
|
+
if (options.host?.origin === 'null') throw new Error(`Invalid host: ${options.host.href}`);
|
|
29
26
|
type Block = readonly [segment: string, blocks: readonly HTMLElement[], url: string];
|
|
30
27
|
const blocks: Block[] = [];
|
|
31
28
|
const adds: (readonly [HTMLElement, Node | null])[] = [];
|
|
@@ -42,11 +39,11 @@ export function bind(target: DocumentFragment | HTMLElement | ShadowRoot, settin
|
|
|
42
39
|
if (settings.chunk && revision) throw new Error('Chunks cannot be updated');
|
|
43
40
|
const url = headers(source).find(field => field.toLowerCase().startsWith('url:'))?.slice(4).trim() ?? '';
|
|
44
41
|
// @ts-expect-error
|
|
45
|
-
|
|
42
|
+
options.url = url ? new ReadonlyURL(url as ':') : undefined;
|
|
46
43
|
const rev = revision = Symbol();
|
|
47
44
|
const sourceSegments: string[] = [];
|
|
48
45
|
const sourceSegmentAttrs: Segment[] = [];
|
|
49
|
-
for (const [seg, attr] of segment(source,
|
|
46
|
+
for (const [seg, attr] of segment(source, true)) {
|
|
50
47
|
sourceSegments.push(seg);
|
|
51
48
|
sourceSegmentAttrs.push(attr);
|
|
52
49
|
yield { type: 'segment', value: seg };
|
|
@@ -71,15 +68,15 @@ export function bind(target: DocumentFragment | HTMLElement | ShadowRoot, settin
|
|
|
71
68
|
const base = next(head);
|
|
72
69
|
let index = head;
|
|
73
70
|
// @ts-expect-error
|
|
74
|
-
|
|
71
|
+
options.header = true;
|
|
75
72
|
for (; index < sourceSegments.length - last; ++index) {
|
|
76
73
|
assert(rev === revision);
|
|
77
74
|
const seg = sourceSegments[index];
|
|
78
|
-
|
|
79
|
-
const es = block(input(seg, new Context(
|
|
75
|
+
options.segment = sourceSegmentAttrs[index] | Segment.write;
|
|
76
|
+
const es = block(input(seg, new Context(options)))!
|
|
80
77
|
.foldl<HTMLElement[]>((acc, { value }) => void acc.push(value) || acc, []);
|
|
81
78
|
// @ts-expect-error
|
|
82
|
-
|
|
79
|
+
options.header = false;
|
|
83
80
|
blocks.length === index
|
|
84
81
|
? blocks.push([seg, es, url])
|
|
85
82
|
: blocks.splice(index, 0, [seg, es, url]);
|
|
@@ -124,14 +121,14 @@ export function bind(target: DocumentFragment | HTMLElement | ShadowRoot, settin
|
|
|
124
121
|
}
|
|
125
122
|
yield { type: 'break' };
|
|
126
123
|
if (rev !== revision) return yield { type: 'cancel' };
|
|
127
|
-
for (const el of figure(next(0)?.parentNode ?? target, settings.notes,
|
|
124
|
+
for (const el of figure(next(0)?.parentNode ?? target, settings.notes, options)) {
|
|
128
125
|
assert(rev === revision);
|
|
129
126
|
el
|
|
130
127
|
? yield { type: 'figure', value: el }
|
|
131
128
|
: yield { type: 'break' };
|
|
132
129
|
if (rev !== revision) return yield { type: 'cancel' };
|
|
133
130
|
}
|
|
134
|
-
for (const el of note(next(0)?.parentNode ?? target, settings.notes,
|
|
131
|
+
for (const el of note(next(0)?.parentNode ?? target, settings.notes, options, bottom)) {
|
|
135
132
|
assert(rev === revision);
|
|
136
133
|
el
|
|
137
134
|
? yield { type: 'note', value: el }
|
|
@@ -306,15 +306,6 @@ describe('Unit: parser/api/parse', () => {
|
|
|
306
306
|
// '<h1 id="error:rnd" class="error">Error: Too much recursion</h1>',
|
|
307
307
|
// `<pre class="error" translate="no">${'{ '.repeat(21)}0</pre>`,
|
|
308
308
|
// ]);
|
|
309
|
-
assert.deepStrictEqual(
|
|
310
|
-
[...parse(`${'('.repeat(20)}0`).children].map(el => el.outerHTML),
|
|
311
|
-
[`<p>${'<span class="bracket">('.repeat(19)}<span class="paren">(0</span>${'</span>'.repeat(19)}</p>`]);
|
|
312
|
-
assert.deepStrictEqual(
|
|
313
|
-
[...parse(`${'('.repeat(21)}0`).children].map(el => el.outerHTML.replace(/:\w+/, ':rnd')),
|
|
314
|
-
[
|
|
315
|
-
'<h1 id="error:rnd" class="error">Error: Too much recursion</h1>',
|
|
316
|
-
`<pre class="error" translate="no">${'('.repeat(21)}0</pre>`,
|
|
317
|
-
]);
|
|
318
309
|
assert.deepStrictEqual(
|
|
319
310
|
[...parse(`${'['.repeat(20)}0`).children].map(el => el.outerHTML),
|
|
320
311
|
[`<p>${'['.repeat(20)}0</p>`]);
|
|
@@ -324,6 +315,12 @@ describe('Unit: parser/api/parse', () => {
|
|
|
324
315
|
'<h1 id="error:rnd" class="error">Error: Too much recursion</h1>',
|
|
325
316
|
`<pre class="error" translate="no">${'['.repeat(21)}0</pre>`,
|
|
326
317
|
]);
|
|
318
|
+
assert.deepStrictEqual(
|
|
319
|
+
[...parse(`${'('.repeat(20)}0`).children].map(el => el.tagName),
|
|
320
|
+
['P']);
|
|
321
|
+
assert.deepStrictEqual(
|
|
322
|
+
[...parse(`${'('.repeat(21)}0`).children].map(el => el.tagName),
|
|
323
|
+
['H1', 'PRE']);
|
|
327
324
|
assert.deepStrictEqual(
|
|
328
325
|
[...parse(`${'(('.repeat(2)}0${'))'.repeat(2)}`).children].map(el => el.tagName),
|
|
329
326
|
['P', 'OL']);
|
|
@@ -398,7 +395,7 @@ describe('Unit: parser/api/parse', () => {
|
|
|
398
395
|
});
|
|
399
396
|
|
|
400
397
|
it('backtrack 1', () => {
|
|
401
|
-
// 最悪計算量での実行速度はCommonMarkの公式JS実装の32nに対して
|
|
398
|
+
// 最悪計算量での実行速度はCommonMarkの公式JS実装の32nに対して1-4倍程度。
|
|
402
399
|
// 5n = reference + link + url/math + ruby + text
|
|
403
400
|
assert.deepStrictEqual(
|
|
404
401
|
[...parse(`((([[[[#$[${'.'.repeat(19998)}`, {}, new Context({ resources: { clock: 100000, recursions: [100] } })).children]
|
package/src/parser/api/parse.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ParserOptions } from '../../..';
|
|
2
2
|
import { input } from '../../combinator/data/parser';
|
|
3
|
-
import { Context, Segment } from '../context';
|
|
3
|
+
import { Context, Options, Segment } from '../context';
|
|
4
4
|
import { segment } from '../segment';
|
|
5
5
|
import { block } from '../block';
|
|
6
6
|
import { headers } from './header';
|
|
@@ -9,43 +9,40 @@ import { note } from '../processor/note';
|
|
|
9
9
|
import { ReadonlyURL } from 'spica/url';
|
|
10
10
|
import { frag } from 'typed-dom/dom';
|
|
11
11
|
|
|
12
|
-
interface
|
|
12
|
+
interface Opts extends ParserOptions {
|
|
13
13
|
readonly local?: boolean;
|
|
14
14
|
readonly test?: boolean;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
export function parse(source: string,
|
|
17
|
+
export function parse(source: string, opts: Opts = {}, options?: Options): DocumentFragment {
|
|
18
18
|
const url = headers(source).find(field => field.toLowerCase().startsWith('url:'))?.slice(4).trim() ?? '';
|
|
19
|
-
|
|
20
|
-
host:
|
|
21
|
-
url: url ? new ReadonlyURL(url as ':') :
|
|
22
|
-
id:
|
|
23
|
-
local:
|
|
24
|
-
caches:
|
|
25
|
-
resources:
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
assert(!context.state);
|
|
30
|
-
if (context.id?.match(/[^0-9a-z/-]/i)) throw new Error('Invalid ID: ID must be alphanumeric');
|
|
31
|
-
if (context.host?.origin === 'null') throw new Error(`Invalid host: ${context.host.href}`);
|
|
19
|
+
options = {
|
|
20
|
+
host: opts.host ?? options?.host ?? new ReadonlyURL(location.pathname, location.origin),
|
|
21
|
+
url: url ? new ReadonlyURL(url as ':') : options?.url,
|
|
22
|
+
id: opts.id ?? options?.id,
|
|
23
|
+
local: opts.local ?? options?.local ?? false,
|
|
24
|
+
caches: options?.caches,
|
|
25
|
+
resources: options?.resources,
|
|
26
|
+
};
|
|
27
|
+
if (options.id?.match(/[^0-9a-z/-]/i)) throw new Error('Invalid ID: ID must be alphanumeric');
|
|
28
|
+
if (options.host?.origin === 'null') throw new Error(`Invalid host: ${options.host.href}`);
|
|
32
29
|
const node = frag();
|
|
33
30
|
// @ts-expect-error
|
|
34
|
-
|
|
35
|
-
for (const [seg, attr] of segment(source, !
|
|
36
|
-
|
|
37
|
-
const es = block(input(seg, new Context(
|
|
31
|
+
options.header = true;
|
|
32
|
+
for (const [seg, attr] of segment(source, !options.local)) {
|
|
33
|
+
options.segment = attr | Segment.write;
|
|
34
|
+
const es = block(input(seg, new Context(options)))!
|
|
38
35
|
.foldl<HTMLElement[]>((acc, { value }) => void acc.push(value) || acc, [])
|
|
39
36
|
// @ts-expect-error
|
|
40
|
-
|
|
37
|
+
options.header = false;
|
|
41
38
|
if (es.length === 0) continue;
|
|
42
39
|
node.append(...es);
|
|
43
40
|
}
|
|
44
|
-
assert(
|
|
45
|
-
if (
|
|
46
|
-
for (const _ of figure(node,
|
|
47
|
-
for (const _ of note(node,
|
|
48
|
-
assert(
|
|
49
|
-
assert(
|
|
41
|
+
assert(opts.id !== '' || !node.querySelector('[id], .index[href], .label[href], .annotation > a[href], .reference > a[href]'));
|
|
42
|
+
if (opts.test) return node;
|
|
43
|
+
for (const _ of figure(node, opts.notes, options));
|
|
44
|
+
for (const _ of note(node, opts.notes, options));
|
|
45
|
+
assert(opts.id !== '' || !node.querySelector('[id], .index[href], .label[href], .annotation > a[href], .reference > a[href]'));
|
|
46
|
+
assert(opts.id !== '' || !opts.notes?.references.querySelector('[id], .index[href], .label[href]'));
|
|
50
47
|
return node;
|
|
51
48
|
}
|
|
@@ -44,8 +44,8 @@ describe('Unit: parser/block/heading', () => {
|
|
|
44
44
|
assert.deepStrictEqual(inspect(parser, input('## http://host', new Context())), [['<h2 id="index::http://host"><a class="url" href="http://host" target="_blank">http://host</a></h2>'], '']);
|
|
45
45
|
assert.deepStrictEqual(inspect(parser, input('# !http://host', new Context())), [['<h1 id="index::!http://host">!http://host</h1>'], '']);
|
|
46
46
|
assert.deepStrictEqual(inspect(parser, input('## !http://host', new Context())), [['<h2 id="index::!http://host">!<a class="url" href="http://host" target="_blank">http://host</a></h2>'], '']);
|
|
47
|
-
assert.deepStrictEqual(inspect(parser, input('# a((b))', new Context())), [['<h1 id="index::a((b))">a<span class="
|
|
48
|
-
assert.deepStrictEqual(inspect(parser, input('## a((b))', new Context())), [['<h2 id="index::a((b))">a<span class="
|
|
47
|
+
assert.deepStrictEqual(inspect(parser, input('# a((b))', new Context())), [['<h1 id="index::a((b))">a<span class="paren">(<span class="paren">(b)</span>)</span></h1>'], '']);
|
|
48
|
+
assert.deepStrictEqual(inspect(parser, input('## a((b))', new Context())), [['<h2 id="index::a((b))">a<span class="paren">(<span class="paren">(b)</span>)</span></h2>'], '']);
|
|
49
49
|
assert.deepStrictEqual(inspect(parser, input('# a[[b]]', new Context())), [['<h1 id="index::a[[b]]">a[[b]]</h1>'], '']);
|
|
50
50
|
assert.deepStrictEqual(inspect(parser, input('## a[[b]]', new Context())), [['<h2 id="index::a[[b]]">a[[b]]</h2>'], '']);
|
|
51
51
|
assert.deepStrictEqual(inspect(parser, input('###### a', new Context())), [['<h6 id="index::a">a</h6>'], '']);
|
|
@@ -33,7 +33,7 @@ describe('Unit: parser/block/table', () => {
|
|
|
33
33
|
assert.deepStrictEqual(inspect(parser, input('|||\n|-|-|\n|||', new Context())), [['<table><thead><tr><th></th><th></th></tr></thead><tbody><tr><td></td><td></td></tr></tbody></table>'], '']);
|
|
34
34
|
assert.deepStrictEqual(inspect(parser, input('|"|\n|-\n|', new Context())), [['<table><thead><tr><th>"</th></tr></thead><tbody><tr></tr></tbody></table>'], '']);
|
|
35
35
|
assert.deepStrictEqual(inspect(parser, input('|`|`|\n|-\n|', new Context())), [['<table><thead><tr><th><code data-src="`|`">|</code></th></tr></thead><tbody><tr></tr></tbody></table>'], '']);
|
|
36
|
-
assert.deepStrictEqual(inspect(parser, input('|((|\n|-\n|', new Context())), [['<table><thead><tr><th><span class="
|
|
36
|
+
assert.deepStrictEqual(inspect(parser, input('|((|\n|-\n|', new Context())), [['<table><thead><tr><th><span class="paren">(<span class="paren">(</span></span></th></tr></thead><tbody><tr></tr></tbody></table>'], '']);
|
|
37
37
|
assert.deepStrictEqual(inspect(parser, input('|a|b|\n|-|-|\n|1|2|', new Context())), [['<table><thead><tr><th>a</th><th>b</th></tr></thead><tbody><tr><td>1</td><td>2</td></tr></tbody></table>'], '']);
|
|
38
38
|
assert.deepStrictEqual(inspect(parser, input('|a|b\n|-|-\n|1|2', new Context())), [['<table><thead><tr><th>a</th><th>b</th></tr></thead><tbody><tr><td>1</td><td>2</td></tr></tbody></table>'], '']);
|
|
39
39
|
assert.deepStrictEqual(inspect(parser, input('|a|\n|-|\n|1|', new Context())), [['<table><thead><tr><th>a</th></tr></thead><tbody><tr><td>1</td></tr></tbody></table>'], '']);
|