stream-markdown-parser 0.0.73 → 0.0.75
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/dist/index.d.ts.map +1 -1
- package/dist/index.js +742 -173
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -601,7 +601,7 @@ var require_markdown_it_task_checkbox = /* @__PURE__ */ __commonJS({ "../../node
|
|
|
601
601
|
}) });
|
|
602
602
|
|
|
603
603
|
//#endregion
|
|
604
|
-
//#region ../../node_modules/.pnpm/markdown-it-ts@0.0.
|
|
604
|
+
//#region ../../node_modules/.pnpm/markdown-it-ts@0.0.9/node_modules/markdown-it-ts/dist/chunk-Bp6m_JJh.js
|
|
605
605
|
var import_markdown_it_task_checkbox = /* @__PURE__ */ __toESM(require_markdown_it_task_checkbox(), 1);
|
|
606
606
|
var __defProp = Object.defineProperty;
|
|
607
607
|
var __export = (all) => {
|
|
@@ -2187,7 +2187,7 @@ var require_punycode = /* @__PURE__ */ __commonJS({ "../../node_modules/.pnpm/pu
|
|
|
2187
2187
|
}) });
|
|
2188
2188
|
|
|
2189
2189
|
//#endregion
|
|
2190
|
-
//#region ../../node_modules/.pnpm/markdown-it-ts@0.0.
|
|
2190
|
+
//#region ../../node_modules/.pnpm/markdown-it-ts@0.0.9/node_modules/markdown-it-ts/dist/index.js
|
|
2191
2191
|
var import_punycode = /* @__PURE__ */ __toESM(require_punycode(), 1);
|
|
2192
2192
|
var utils_exports = /* @__PURE__ */ __export({
|
|
2193
2193
|
arrayReplaceAt: () => arrayReplaceAt,
|
|
@@ -2445,10 +2445,23 @@ function parseLinkDestination(str, start, max) {
|
|
|
2445
2445
|
return result;
|
|
2446
2446
|
}
|
|
2447
2447
|
var parse_link_destination_default = parseLinkDestination;
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2448
|
+
const FALLBACK_TO_INLINE_SCAN = -2;
|
|
2449
|
+
function scanPlainLinkLabel(src, start, max) {
|
|
2450
|
+
let pos = start + 1;
|
|
2451
|
+
while (pos < max) {
|
|
2452
|
+
const marker = src.charCodeAt(pos);
|
|
2453
|
+
if (marker === 93) return pos;
|
|
2454
|
+
if (marker === 92) {
|
|
2455
|
+
pos += 2;
|
|
2456
|
+
continue;
|
|
2457
|
+
}
|
|
2458
|
+
if (marker === 96 || marker === 60) return FALLBACK_TO_INLINE_SCAN;
|
|
2459
|
+
if (marker === 33 && pos + 1 < max && src.charCodeAt(pos + 1) === 91) return FALLBACK_TO_INLINE_SCAN;
|
|
2460
|
+
if (marker === 91) return FALLBACK_TO_INLINE_SCAN;
|
|
2461
|
+
pos++;
|
|
2462
|
+
}
|
|
2463
|
+
return -1;
|
|
2464
|
+
}
|
|
2452
2465
|
function parseLinkLabel(state, start, disableNested) {
|
|
2453
2466
|
let level = 1;
|
|
2454
2467
|
let found = false;
|
|
@@ -2457,7 +2470,15 @@ function parseLinkLabel(state, start, disableNested) {
|
|
|
2457
2470
|
const src = state.src;
|
|
2458
2471
|
const max = state.posMax;
|
|
2459
2472
|
const oldPos = state.pos;
|
|
2460
|
-
const
|
|
2473
|
+
const noCloseFrom = state.__mdtsLinkLabelNoCloseFrom;
|
|
2474
|
+
if (typeof noCloseFrom === "number" && start + 1 >= noCloseFrom) return -1;
|
|
2475
|
+
const nextClose = src.indexOf("]", start + 1);
|
|
2476
|
+
if (nextClose < 0 || nextClose >= max) {
|
|
2477
|
+
state.__mdtsLinkLabelNoCloseFrom = start + 1;
|
|
2478
|
+
return -1;
|
|
2479
|
+
}
|
|
2480
|
+
const fastLabelEnd = scanPlainLinkLabel(src, start, max);
|
|
2481
|
+
if (fastLabelEnd !== FALLBACK_TO_INLINE_SCAN) return fastLabelEnd;
|
|
2461
2482
|
state.pos = start + 1;
|
|
2462
2483
|
while (state.pos < max) {
|
|
2463
2484
|
marker = src.charCodeAt(state.pos);
|
|
@@ -2469,7 +2490,7 @@ function parseLinkLabel(state, start, disableNested) {
|
|
|
2469
2490
|
}
|
|
2470
2491
|
}
|
|
2471
2492
|
prevPos = state.pos;
|
|
2472
|
-
inline
|
|
2493
|
+
state.md.inline.skipToken(state);
|
|
2473
2494
|
if (marker === 91) {
|
|
2474
2495
|
if (prevPos === state.pos - 1) level++;
|
|
2475
2496
|
else if (disableNested) {
|
|
@@ -2600,6 +2621,12 @@ function normalizeLinkText(url) {
|
|
|
2600
2621
|
}
|
|
2601
2622
|
return decode_default(format(parsed), `${decode_default.defaultChars}%`);
|
|
2602
2623
|
}
|
|
2624
|
+
function setStrategyDiagnostics(env, info) {
|
|
2625
|
+
if (!env) return;
|
|
2626
|
+
try {
|
|
2627
|
+
env.__mdtsStrategyInfo = info;
|
|
2628
|
+
} catch {}
|
|
2629
|
+
}
|
|
2603
2630
|
/**
|
|
2604
2631
|
* class Token
|
|
2605
2632
|
*
|
|
@@ -2787,42 +2814,22 @@ function block(state) {
|
|
|
2787
2814
|
/**
|
|
2788
2815
|
* Process autolinks '<protocol:...>'
|
|
2789
2816
|
*/
|
|
2790
|
-
const EMAIL_RE = /^[
|
|
2791
|
-
|
|
2792
|
-
const lc = ch | 32;
|
|
2793
|
-
return lc >= 97 && lc <= 122;
|
|
2794
|
-
}
|
|
2795
|
-
function isAutolinkScheme(src, start, end) {
|
|
2796
|
-
const len = end - start;
|
|
2797
|
-
if (len < 2 || len > 32 || !isAsciiLetter$2(src.charCodeAt(start))) return false;
|
|
2798
|
-
for (let pos = start + 1; pos < end; pos++) {
|
|
2799
|
-
const ch = src.charCodeAt(pos);
|
|
2800
|
-
if (ch >= 48 && ch <= 57 || ch >= 65 && ch <= 90 || ch >= 97 && ch <= 122 || ch === 43 || ch === 45 || ch === 46) continue;
|
|
2801
|
-
return false;
|
|
2802
|
-
}
|
|
2803
|
-
return true;
|
|
2804
|
-
}
|
|
2817
|
+
const EMAIL_RE = /^([a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*)$/;
|
|
2818
|
+
const AUTOLINK_RE = /^([a-zA-Z][a-zA-Z0-9+.-]{1,31}):([^<>\x00-\x20]*)$/;
|
|
2805
2819
|
function autolink(state, silent) {
|
|
2806
2820
|
let pos = state.pos;
|
|
2807
2821
|
const src = state.src;
|
|
2808
2822
|
if (src.charCodeAt(pos) !== 60) return false;
|
|
2809
2823
|
const start = pos;
|
|
2810
2824
|
const max = state.posMax;
|
|
2811
|
-
let colonPos = -1;
|
|
2812
|
-
let hasAt = false;
|
|
2813
2825
|
for (;;) {
|
|
2814
2826
|
if (++pos >= max) return false;
|
|
2815
2827
|
const ch = src.charCodeAt(pos);
|
|
2816
2828
|
if (ch === 60) return false;
|
|
2817
2829
|
if (ch === 62) break;
|
|
2818
|
-
|
|
2819
|
-
|
|
2820
|
-
|
|
2821
|
-
} else if (ch === 64) hasAt = true;
|
|
2822
|
-
}
|
|
2823
|
-
if (colonPos < 0 && !hasAt) return false;
|
|
2824
|
-
if (colonPos > start + 2 && isAutolinkScheme(src, start + 1, colonPos)) {
|
|
2825
|
-
const url = src.slice(start + 1, pos);
|
|
2830
|
+
}
|
|
2831
|
+
const url = src.slice(start + 1, pos);
|
|
2832
|
+
if (AUTOLINK_RE.test(url)) {
|
|
2826
2833
|
const fullUrl = state.md.normalizeLink(url);
|
|
2827
2834
|
if (!state.md.validateLink(fullUrl)) return false;
|
|
2828
2835
|
if (!silent) {
|
|
@@ -2830,18 +2837,16 @@ function autolink(state, silent) {
|
|
|
2830
2837
|
token_o.attrs = [["href", fullUrl]];
|
|
2831
2838
|
token_o.markup = "autolink";
|
|
2832
2839
|
token_o.info = "auto";
|
|
2833
|
-
const token_t = state.
|
|
2840
|
+
const token_t = state.push("text", "", 0);
|
|
2834
2841
|
token_t.content = state.md.normalizeLinkText(url);
|
|
2835
2842
|
const token_c = state.push("link_close", "a", -1);
|
|
2836
2843
|
token_c.markup = "autolink";
|
|
2837
2844
|
token_c.info = "auto";
|
|
2838
2845
|
}
|
|
2839
|
-
state.pos
|
|
2846
|
+
state.pos += url.length + 2;
|
|
2840
2847
|
return true;
|
|
2841
2848
|
}
|
|
2842
|
-
if (
|
|
2843
|
-
const url = src.slice(start + 1, pos);
|
|
2844
|
-
if (!EMAIL_RE.test(url)) return false;
|
|
2849
|
+
if (EMAIL_RE.test(url)) {
|
|
2845
2850
|
const fullUrl = state.md.normalizeLink(`mailto:${url}`);
|
|
2846
2851
|
if (!state.md.validateLink(fullUrl)) return false;
|
|
2847
2852
|
if (!silent) {
|
|
@@ -2849,13 +2854,13 @@ function autolink(state, silent) {
|
|
|
2849
2854
|
token_o.attrs = [["href", fullUrl]];
|
|
2850
2855
|
token_o.markup = "autolink";
|
|
2851
2856
|
token_o.info = "auto";
|
|
2852
|
-
const token_t = state.
|
|
2857
|
+
const token_t = state.push("text", "", 0);
|
|
2853
2858
|
token_t.content = state.md.normalizeLinkText(url);
|
|
2854
2859
|
const token_c = state.push("link_close", "a", -1);
|
|
2855
2860
|
token_c.markup = "autolink";
|
|
2856
2861
|
token_c.info = "auto";
|
|
2857
2862
|
}
|
|
2858
|
-
state.pos
|
|
2863
|
+
state.pos += url.length + 2;
|
|
2859
2864
|
return true;
|
|
2860
2865
|
}
|
|
2861
2866
|
return false;
|
|
@@ -3641,9 +3646,11 @@ var text_default = text;
|
|
|
3641
3646
|
var InlineRuler = class {
|
|
3642
3647
|
rules = [];
|
|
3643
3648
|
cache = null;
|
|
3649
|
+
namedCache = null;
|
|
3644
3650
|
version = 0;
|
|
3645
3651
|
invalidateCache() {
|
|
3646
3652
|
this.cache = null;
|
|
3653
|
+
this.namedCache = null;
|
|
3647
3654
|
this.version++;
|
|
3648
3655
|
}
|
|
3649
3656
|
/**
|
|
@@ -3743,6 +3750,11 @@ var InlineRuler = class {
|
|
|
3743
3750
|
if (!this.cache) this.compileCache();
|
|
3744
3751
|
return this.cache.get(chain) ?? [];
|
|
3745
3752
|
}
|
|
3753
|
+
getNamedRules(chainName) {
|
|
3754
|
+
const chain = chainName || "";
|
|
3755
|
+
if (!this.namedCache) this.compileCache();
|
|
3756
|
+
return this.namedCache.get(chain) ?? [];
|
|
3757
|
+
}
|
|
3746
3758
|
compileCache() {
|
|
3747
3759
|
const chains = new Set([""]);
|
|
3748
3760
|
for (const rule of this.rules) {
|
|
@@ -3750,16 +3762,24 @@ var InlineRuler = class {
|
|
|
3750
3762
|
if (rule.alt) for (const alt of rule.alt) chains.add(alt);
|
|
3751
3763
|
}
|
|
3752
3764
|
const cache = /* @__PURE__ */ new Map();
|
|
3765
|
+
const namedCache = /* @__PURE__ */ new Map();
|
|
3753
3766
|
for (const chain of chains) {
|
|
3754
3767
|
const bucket = [];
|
|
3768
|
+
const namedBucket = [];
|
|
3755
3769
|
for (const rule of this.rules) {
|
|
3756
3770
|
if (!rule.enabled) continue;
|
|
3757
3771
|
if (chain !== "" && !rule.alt?.includes(chain)) continue;
|
|
3758
3772
|
bucket.push(rule.fn);
|
|
3773
|
+
namedBucket.push({
|
|
3774
|
+
name: rule.name,
|
|
3775
|
+
fn: rule.fn
|
|
3776
|
+
});
|
|
3759
3777
|
}
|
|
3760
3778
|
cache.set(chain, bucket);
|
|
3779
|
+
namedCache.set(chain, namedBucket);
|
|
3761
3780
|
}
|
|
3762
3781
|
this.cache = cache;
|
|
3782
|
+
this.namedCache = namedCache;
|
|
3763
3783
|
}
|
|
3764
3784
|
};
|
|
3765
3785
|
/**
|
|
@@ -3871,6 +3891,78 @@ var StateInline = class {
|
|
|
3871
3891
|
}
|
|
3872
3892
|
};
|
|
3873
3893
|
StateInline.prototype.Token = Token;
|
|
3894
|
+
function now() {
|
|
3895
|
+
if (typeof performance !== "undefined" && typeof performance.now === "function") return performance.now();
|
|
3896
|
+
return Date.now();
|
|
3897
|
+
}
|
|
3898
|
+
function median(values) {
|
|
3899
|
+
if (values.length === 0) return 0;
|
|
3900
|
+
const sorted = values.slice().sort((a, b) => a - b);
|
|
3901
|
+
const mid = Math.floor(sorted.length / 2);
|
|
3902
|
+
return sorted.length % 2 === 0 ? (sorted[mid - 1] + sorted[mid]) / 2 : sorted[mid];
|
|
3903
|
+
}
|
|
3904
|
+
function createRecord(chain, name) {
|
|
3905
|
+
return {
|
|
3906
|
+
chain,
|
|
3907
|
+
name,
|
|
3908
|
+
calls: 0,
|
|
3909
|
+
hits: 0,
|
|
3910
|
+
inclusiveMs: 0,
|
|
3911
|
+
medianMs: 0,
|
|
3912
|
+
maxMs: 0,
|
|
3913
|
+
normalCalls: 0,
|
|
3914
|
+
normalHits: 0,
|
|
3915
|
+
silentCalls: 0,
|
|
3916
|
+
silentHits: 0,
|
|
3917
|
+
samples: []
|
|
3918
|
+
};
|
|
3919
|
+
}
|
|
3920
|
+
function getRuleProfile(env) {
|
|
3921
|
+
const carrier = env;
|
|
3922
|
+
if (!carrier) return null;
|
|
3923
|
+
if (carrier.__mdtsRuleProfile) return carrier.__mdtsRuleProfile;
|
|
3924
|
+
if (!carrier.__mdtsProfileRules) return null;
|
|
3925
|
+
const meta = carrier.__mdtsProfileRules === true ? {} : carrier.__mdtsProfileRules;
|
|
3926
|
+
const session = {
|
|
3927
|
+
enabled: true,
|
|
3928
|
+
fixture: meta.fixture,
|
|
3929
|
+
mode: meta.mode,
|
|
3930
|
+
startedAt: now(),
|
|
3931
|
+
records: Object.create(null)
|
|
3932
|
+
};
|
|
3933
|
+
carrier.__mdtsRuleProfile = session;
|
|
3934
|
+
return session;
|
|
3935
|
+
}
|
|
3936
|
+
function recordRuleInvocation(env, chain, name, durationMs, hit, silent) {
|
|
3937
|
+
const session = getRuleProfile(env);
|
|
3938
|
+
if (!session) return;
|
|
3939
|
+
const key = `${chain}:${name}`;
|
|
3940
|
+
const record = session.records[key] ?? (session.records[key] = createRecord(chain, name));
|
|
3941
|
+
record.calls++;
|
|
3942
|
+
record.inclusiveMs += durationMs;
|
|
3943
|
+
if (durationMs > record.maxMs) record.maxMs = durationMs;
|
|
3944
|
+
record.samples.push(durationMs);
|
|
3945
|
+
if (silent) {
|
|
3946
|
+
record.silentCalls++;
|
|
3947
|
+
if (hit) record.silentHits++;
|
|
3948
|
+
} else {
|
|
3949
|
+
record.normalCalls++;
|
|
3950
|
+
if (hit) record.normalHits++;
|
|
3951
|
+
}
|
|
3952
|
+
if (hit) record.hits++;
|
|
3953
|
+
session.completedAt = now();
|
|
3954
|
+
}
|
|
3955
|
+
function finalizeRuleProfile(env) {
|
|
3956
|
+
const session = getRuleProfile(env);
|
|
3957
|
+
if (!session) return null;
|
|
3958
|
+
const records = Object.keys(session.records);
|
|
3959
|
+
for (let i = 0; i < records.length; i++) {
|
|
3960
|
+
const record = session.records[records[i]];
|
|
3961
|
+
record.medianMs = median(record.samples);
|
|
3962
|
+
}
|
|
3963
|
+
session.completedAt = now();
|
|
3964
|
+
return session;
|
|
3965
|
+
}
|
|
3874
3966
|
/**
|
|
3875
3967
|
* ParserInline - inline parser with Ruler-based rule management
|
|
3876
3968
|
*/
|
|
@@ -3939,9 +4031,11 @@ var ParserInline = class {
|
|
|
3939
4031
|
skipToken(state) {
|
|
3940
4032
|
const pos = state.pos;
|
|
3941
4033
|
const rules = this.getRules();
|
|
4034
|
+
const namedRules = this.ruler.getNamedRules("");
|
|
3942
4035
|
const len = rules.length;
|
|
3943
4036
|
const cache = state.cache;
|
|
3944
4037
|
const cached = cache[pos];
|
|
4038
|
+
const shouldProfile = !!state.env && (Object.prototype.hasOwnProperty.call(state.env, "__mdtsRuleProfile") || Object.prototype.hasOwnProperty.call(state.env, "__mdtsProfileRules"));
|
|
3945
4039
|
if (cached !== void 0) {
|
|
3946
4040
|
state.pos = cached;
|
|
3947
4041
|
return;
|
|
@@ -3949,7 +4043,13 @@ var ParserInline = class {
|
|
|
3949
4043
|
let ok = false;
|
|
3950
4044
|
if (state.level < state.maxNesting) for (let i = 0; i < len; i++) {
|
|
3951
4045
|
state.level++;
|
|
3952
|
-
ok = rules[i](state, true);
|
|
4046
|
+
if (!shouldProfile) ok = rules[i](state, true);
|
|
4047
|
+
else {
|
|
4048
|
+
const startedAt = typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
|
|
4049
|
+
ok = namedRules[i].fn(state, true);
|
|
4050
|
+
const endedAt = typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
|
|
4051
|
+
recordRuleInvocation(state.env, "inline", namedRules[i].name, endedAt - startedAt, !!ok, true);
|
|
4052
|
+
}
|
|
3953
4053
|
state.level--;
|
|
3954
4054
|
if (ok) {
|
|
3955
4055
|
if (pos >= state.pos) throw new Error("inline rule didn't increment state.pos");
|
|
@@ -3965,13 +4065,21 @@ var ParserInline = class {
|
|
|
3965
4065
|
*/
|
|
3966
4066
|
tokenize(state) {
|
|
3967
4067
|
const rules = this.getRules();
|
|
4068
|
+
const namedRules = this.ruler.getNamedRules("");
|
|
3968
4069
|
const len = rules.length;
|
|
3969
4070
|
const end = state.posMax;
|
|
4071
|
+
const shouldProfile = !!state.env && (Object.prototype.hasOwnProperty.call(state.env, "__mdtsRuleProfile") || Object.prototype.hasOwnProperty.call(state.env, "__mdtsProfileRules"));
|
|
3970
4072
|
while (state.pos < end) {
|
|
3971
4073
|
const prevPos = state.pos;
|
|
3972
4074
|
let ok = false;
|
|
3973
4075
|
if (state.level < state.maxNesting) for (let i = 0; i < len; i++) {
|
|
3974
|
-
ok = rules[i](state, false);
|
|
4076
|
+
if (!shouldProfile) ok = rules[i](state, false);
|
|
4077
|
+
else {
|
|
4078
|
+
const startedAt = typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
|
|
4079
|
+
ok = namedRules[i].fn(state, false);
|
|
4080
|
+
const endedAt = typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
|
|
4081
|
+
recordRuleInvocation(state.env, "inline", namedRules[i].name, endedAt - startedAt, !!ok, false);
|
|
4082
|
+
}
|
|
3975
4083
|
if (ok) {
|
|
3976
4084
|
if (prevPos >= state.pos) throw new Error("inline rule didn't increment state.pos");
|
|
3977
4085
|
break;
|
|
@@ -4001,8 +4109,16 @@ var ParserInline = class {
|
|
|
4001
4109
|
const state = new StateInline(src, md, env, outTokens);
|
|
4002
4110
|
this.tokenize(state);
|
|
4003
4111
|
const rules2 = this.getRules2();
|
|
4112
|
+
const namedRules2 = this.ruler2.getNamedRules("");
|
|
4004
4113
|
const len = rules2.length;
|
|
4005
|
-
|
|
4114
|
+
const shouldProfile = !!state.env && (Object.prototype.hasOwnProperty.call(state.env, "__mdtsRuleProfile") || Object.prototype.hasOwnProperty.call(state.env, "__mdtsProfileRules"));
|
|
4115
|
+
for (let i = 0; i < len; i++) if (!shouldProfile) rules2[i](state, false);
|
|
4116
|
+
else {
|
|
4117
|
+
const startedAt = typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
|
|
4118
|
+
namedRules2[i].fn(state, false);
|
|
4119
|
+
const endedAt = typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
|
|
4120
|
+
recordRuleInvocation(state.env, "inline2", namedRules2[i].name, endedAt - startedAt, true, false);
|
|
4121
|
+
}
|
|
4006
4122
|
}
|
|
4007
4123
|
parse(str, md, env, outTokens) {
|
|
4008
4124
|
this.parseSource(str, md, env, outTokens);
|
|
@@ -4199,8 +4315,10 @@ function replacements(state) {
|
|
|
4199
4315
|
var CoreRuler = class {
|
|
4200
4316
|
rules = [];
|
|
4201
4317
|
cache = null;
|
|
4318
|
+
namedCache = null;
|
|
4202
4319
|
invalidateCache() {
|
|
4203
4320
|
this.cache = null;
|
|
4321
|
+
this.namedCache = null;
|
|
4204
4322
|
}
|
|
4205
4323
|
push(name, fn) {
|
|
4206
4324
|
const idx = this.rules.findIndex((r) => r.name === name);
|
|
@@ -4290,11 +4408,19 @@ var CoreRuler = class {
|
|
|
4290
4408
|
}
|
|
4291
4409
|
compileCache() {
|
|
4292
4410
|
this.cache = this.rules.filter((r) => r.enabled).map((r) => r.fn);
|
|
4411
|
+
this.namedCache = this.rules.filter((r) => r.enabled).map((r) => ({
|
|
4412
|
+
name: r.name,
|
|
4413
|
+
fn: r.fn
|
|
4414
|
+
}));
|
|
4293
4415
|
}
|
|
4294
4416
|
getRules(_chainName = "") {
|
|
4295
4417
|
if (!this.cache) this.compileCache();
|
|
4296
4418
|
return this.cache;
|
|
4297
4419
|
}
|
|
4420
|
+
getNamedRules(_chainName = "") {
|
|
4421
|
+
if (!this.namedCache) this.compileCache();
|
|
4422
|
+
return this.namedCache;
|
|
4423
|
+
}
|
|
4298
4424
|
};
|
|
4299
4425
|
const QUOTE_TEST_RE = /['"]/;
|
|
4300
4426
|
const QUOTE_RE = /['"]/g;
|
|
@@ -4449,7 +4575,7 @@ function blockquote(state, startLine, endLine, silent) {
|
|
|
4449
4575
|
const oldBSCount = [];
|
|
4450
4576
|
const oldSCount = [];
|
|
4451
4577
|
const oldTShift = [];
|
|
4452
|
-
const terminatorRules = state.md.block.ruler.
|
|
4578
|
+
const terminatorRules = state.md.block.ruler.getRulesForState(state, "blockquote");
|
|
4453
4579
|
const oldParentType = state.parentType;
|
|
4454
4580
|
state.parentType = "blockquote";
|
|
4455
4581
|
let lastLineEmpty = false;
|
|
@@ -4839,19 +4965,46 @@ function html_block(state, startLine, endLine, silent) {
|
|
|
4839
4965
|
token.content = state.getLines(startLine, nextLine, state.blkIndent, true);
|
|
4840
4966
|
return true;
|
|
4841
4967
|
}
|
|
4968
|
+
function hasPipeOnLine(src, start, max) {
|
|
4969
|
+
for (let pos = start; pos < max; pos++) if (src.charCodeAt(pos) === 124) return true;
|
|
4970
|
+
return false;
|
|
4971
|
+
}
|
|
4972
|
+
function canUseParagraphTerminatorFastPath(state) {
|
|
4973
|
+
const ruler = state?.md?.block?.ruler;
|
|
4974
|
+
if (!ruler) return false;
|
|
4975
|
+
return ruler.version === ruler.__mdtsDefaultVersion;
|
|
4976
|
+
}
|
|
4977
|
+
function couldTerminateParagraph(src, start, max) {
|
|
4978
|
+
if (start >= max) return false;
|
|
4979
|
+
const marker = src.charCodeAt(start);
|
|
4980
|
+
switch (marker) {
|
|
4981
|
+
case 35:
|
|
4982
|
+
case 42:
|
|
4983
|
+
case 43:
|
|
4984
|
+
case 45:
|
|
4985
|
+
case 60:
|
|
4986
|
+
case 62:
|
|
4987
|
+
case 95:
|
|
4988
|
+
case 96:
|
|
4989
|
+
case 126: return true;
|
|
4990
|
+
}
|
|
4991
|
+
if (marker >= 48 && marker <= 57) return true;
|
|
4992
|
+
return hasPipeOnLine(src, start, max);
|
|
4993
|
+
}
|
|
4842
4994
|
const HEADING_TAGS = [
|
|
4843
4995
|
"",
|
|
4844
4996
|
"h1",
|
|
4845
4997
|
"h2"
|
|
4846
4998
|
];
|
|
4847
4999
|
function lheading(state, startLine, endLine) {
|
|
4848
|
-
const terminatorRules = state.md.block.ruler.
|
|
5000
|
+
const terminatorRules = state.md.block.ruler.getRulesForState(state, "paragraph");
|
|
4849
5001
|
const src = state.src;
|
|
4850
5002
|
const bMarks = state.bMarks;
|
|
4851
5003
|
const tShift = state.tShift;
|
|
4852
5004
|
const eMarks = state.eMarks;
|
|
4853
5005
|
const sCount = state.sCount;
|
|
4854
5006
|
const blkIndent = state.blkIndent;
|
|
5007
|
+
const canUseFastTerminatorHint = canUseParagraphTerminatorFastPath(state);
|
|
4855
5008
|
if (sCount[startLine] - blkIndent >= 4) return false;
|
|
4856
5009
|
const oldParentType = state.parentType;
|
|
4857
5010
|
state.parentType = "paragraph";
|
|
@@ -4883,6 +5036,7 @@ function lheading(state, startLine, endLine) {
|
|
|
4883
5036
|
}
|
|
4884
5037
|
}
|
|
4885
5038
|
if (sCount[nextLine] < 0) continue;
|
|
5039
|
+
if (canUseFastTerminatorHint && !couldTerminateParagraph(src, lineStart, max)) continue;
|
|
4886
5040
|
let terminate = false;
|
|
4887
5041
|
for (let i = 0, l = terminatorRules.length; i < l; i++) if (terminatorRules[i](state, nextLine, endLine, true)) {
|
|
4888
5042
|
terminate = true;
|
|
@@ -5054,7 +5208,7 @@ function list(state, startLine, endLine, silent) {
|
|
|
5054
5208
|
state.tokens[state.tokens.length - 1].markup = markerMarkup;
|
|
5055
5209
|
let prevEmptyEnd = false;
|
|
5056
5210
|
const listTokIdx = state.tokens.length - 1;
|
|
5057
|
-
const terminatorRules = state.md.block.ruler.
|
|
5211
|
+
const terminatorRules = state.md.block.ruler.getRulesForState(state, "list");
|
|
5058
5212
|
const oldParentType = state.parentType;
|
|
5059
5213
|
state.parentType = "list";
|
|
5060
5214
|
while (nextLine < endLine) {
|
|
@@ -5160,7 +5314,7 @@ function isSpace$3(code$1) {
|
|
|
5160
5314
|
return code$1 === 9 || code$1 === 32;
|
|
5161
5315
|
}
|
|
5162
5316
|
function paragraph(state, startLine, endLine) {
|
|
5163
|
-
const terminatorRules = state.md.block.ruler.
|
|
5317
|
+
const terminatorRules = state.md.block.ruler.getRulesForState(state, "paragraph");
|
|
5164
5318
|
const oldParentType = state.parentType;
|
|
5165
5319
|
const src = state.src;
|
|
5166
5320
|
const bMarks = state.bMarks;
|
|
@@ -5168,34 +5322,35 @@ function paragraph(state, startLine, endLine) {
|
|
|
5168
5322
|
const eMarks = state.eMarks;
|
|
5169
5323
|
const sCount = state.sCount;
|
|
5170
5324
|
const blkIndent = state.blkIndent;
|
|
5325
|
+
const canUseFastTerminatorHint = canUseParagraphTerminatorFastPath(state);
|
|
5171
5326
|
let nextLine = startLine + 1;
|
|
5172
5327
|
state.parentType = "paragraph";
|
|
5173
5328
|
for (; nextLine < endLine && !state.isEmpty(nextLine); nextLine++) {
|
|
5174
5329
|
if (sCount[nextLine] - blkIndent > 3) continue;
|
|
5175
5330
|
if (sCount[nextLine] < 0) continue;
|
|
5176
5331
|
if (oldParentType === "list" && sCount[nextLine] >= blkIndent) {
|
|
5177
|
-
const start = bMarks[nextLine] + tShift[nextLine];
|
|
5178
|
-
const max = eMarks[nextLine];
|
|
5179
|
-
if (start < max) {
|
|
5180
|
-
const marker = src.charCodeAt(start);
|
|
5332
|
+
const start$1 = bMarks[nextLine] + tShift[nextLine];
|
|
5333
|
+
const max$1 = eMarks[nextLine];
|
|
5334
|
+
if (start$1 < max$1) {
|
|
5335
|
+
const marker = src.charCodeAt(start$1);
|
|
5181
5336
|
if (marker === 42 || marker === 45 || marker === 43) {
|
|
5182
|
-
if (start + 1 >= max || isSpace$3(src.charCodeAt(start + 1))) break;
|
|
5183
|
-
} else if (marker >= 48 && marker <= 57 && start + 1 < max) {
|
|
5184
|
-
let pos = start + 1;
|
|
5337
|
+
if (start$1 + 1 >= max$1 || isSpace$3(src.charCodeAt(start$1 + 1))) break;
|
|
5338
|
+
} else if (marker >= 48 && marker <= 57 && start$1 + 1 < max$1) {
|
|
5339
|
+
let pos = start$1 + 1;
|
|
5185
5340
|
for (;;) {
|
|
5186
|
-
if (pos >= max) {
|
|
5341
|
+
if (pos >= max$1) {
|
|
5187
5342
|
pos = -1;
|
|
5188
5343
|
break;
|
|
5189
5344
|
}
|
|
5190
5345
|
const ch = src.charCodeAt(pos++);
|
|
5191
5346
|
if (ch >= 48 && ch <= 57) {
|
|
5192
|
-
if (pos - start >= 10) {
|
|
5347
|
+
if (pos - start$1 >= 10) {
|
|
5193
5348
|
pos = -1;
|
|
5194
5349
|
break;
|
|
5195
5350
|
}
|
|
5196
5351
|
continue;
|
|
5197
5352
|
}
|
|
5198
|
-
if ((ch === 41 || ch === 46) && (pos >= max || isSpace$3(src.charCodeAt(pos)))) break;
|
|
5353
|
+
if ((ch === 41 || ch === 46) && (pos >= max$1 || isSpace$3(src.charCodeAt(pos)))) break;
|
|
5199
5354
|
pos = -1;
|
|
5200
5355
|
break;
|
|
5201
5356
|
}
|
|
@@ -5203,6 +5358,9 @@ function paragraph(state, startLine, endLine) {
|
|
|
5203
5358
|
}
|
|
5204
5359
|
}
|
|
5205
5360
|
}
|
|
5361
|
+
const start = bMarks[nextLine] + tShift[nextLine];
|
|
5362
|
+
const max = eMarks[nextLine];
|
|
5363
|
+
if (canUseFastTerminatorHint && !couldTerminateParagraph(src, start, max)) continue;
|
|
5206
5364
|
let terminate = false;
|
|
5207
5365
|
for (let i = 0, l = terminatorRules.length; i < l; i++) if (terminatorRules[i](state, nextLine, endLine, true)) {
|
|
5208
5366
|
terminate = true;
|
|
@@ -5233,7 +5391,7 @@ function reference(state, startLine, _endLine, silent) {
|
|
|
5233
5391
|
let pos = state.bMarks[startLine] + state.tShift[startLine];
|
|
5234
5392
|
let max = state.eMarks[startLine];
|
|
5235
5393
|
let nextLine = startLine + 1;
|
|
5236
|
-
const terminatorRules = state.md.block.ruler.
|
|
5394
|
+
const terminatorRules = state.md.block.ruler.getRulesForState(state, "reference");
|
|
5237
5395
|
if (state.sCount[startLine] - state.blkIndent >= 4) return false;
|
|
5238
5396
|
if (state.src.charCodeAt(pos) !== 91) return false;
|
|
5239
5397
|
function getNextLine(nextLine$1) {
|
|
@@ -5444,7 +5602,7 @@ function table(state, startLine, endLine, silent) {
|
|
|
5444
5602
|
if (silent) return true;
|
|
5445
5603
|
const oldParentType = state.parentType;
|
|
5446
5604
|
state.parentType = "table";
|
|
5447
|
-
const terminatorRules = state.md.block.ruler.
|
|
5605
|
+
const terminatorRules = state.md.block.ruler.getRulesForState(state, "blockquote");
|
|
5448
5606
|
const token_to = state.push("table_open", "table", 1);
|
|
5449
5607
|
const tableLines = [startLine, 0];
|
|
5450
5608
|
token_to.map = tableLines;
|
|
@@ -5506,15 +5664,14 @@ function table(state, startLine, endLine, silent) {
|
|
|
5506
5664
|
state.line = nextLine;
|
|
5507
5665
|
return true;
|
|
5508
5666
|
}
|
|
5509
|
-
/**
|
|
5510
|
-
* Block-level rule management with Ruler pattern
|
|
5511
|
-
*/
|
|
5512
5667
|
var BlockRuler = class {
|
|
5513
5668
|
_rules = [];
|
|
5514
5669
|
cache = null;
|
|
5670
|
+
namedCache = null;
|
|
5515
5671
|
version = 0;
|
|
5516
5672
|
invalidateCache() {
|
|
5517
5673
|
this.cache = null;
|
|
5674
|
+
this.namedCache = null;
|
|
5518
5675
|
this.version++;
|
|
5519
5676
|
}
|
|
5520
5677
|
push(name, fn, options) {
|
|
@@ -5557,6 +5714,24 @@ var BlockRuler = class {
|
|
|
5557
5714
|
if (!this.cache) this.compileCache();
|
|
5558
5715
|
return this.cache[chain] ?? [];
|
|
5559
5716
|
}
|
|
5717
|
+
getNamedRules(chainName) {
|
|
5718
|
+
const chain = chainName || "";
|
|
5719
|
+
if (!this.namedCache) this.compileCache();
|
|
5720
|
+
return this.namedCache[chain] ?? [];
|
|
5721
|
+
}
|
|
5722
|
+
getRulesForState(state, chainName) {
|
|
5723
|
+
const env = state?.env;
|
|
5724
|
+
if (!(!!env && (Object.prototype.hasOwnProperty.call(env, "__mdtsRuleProfile") || Object.prototype.hasOwnProperty.call(env, "__mdtsProfileRules")))) return this.getRules(chainName);
|
|
5725
|
+
return this.getNamedRules(chainName).map(({ name, fn }) => {
|
|
5726
|
+
return (currentState, startLine, endLine, silent) => {
|
|
5727
|
+
const startedAt = typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
|
|
5728
|
+
const ok = fn(currentState, startLine, endLine, silent);
|
|
5729
|
+
const endedAt = typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
|
|
5730
|
+
recordRuleInvocation(currentState?.env, "block", name, endedAt - startedAt, ok, !!silent);
|
|
5731
|
+
return ok;
|
|
5732
|
+
};
|
|
5733
|
+
});
|
|
5734
|
+
}
|
|
5560
5735
|
at(name, fn, options) {
|
|
5561
5736
|
const index = this._rules.findIndex((r) => r.name === name);
|
|
5562
5737
|
if (index === -1) throw new Error(`Parser rule not found: ${name}`);
|
|
@@ -5617,16 +5792,24 @@ var BlockRuler = class {
|
|
|
5617
5792
|
for (const alt of rule.alt) chains.add(alt);
|
|
5618
5793
|
}
|
|
5619
5794
|
const cache = Object.create(null);
|
|
5795
|
+
const namedCache = Object.create(null);
|
|
5620
5796
|
for (const chain of chains) {
|
|
5621
5797
|
const bucket = [];
|
|
5798
|
+
const namedBucket = [];
|
|
5622
5799
|
for (const rule of this._rules) {
|
|
5623
5800
|
if (!rule.enabled) continue;
|
|
5624
5801
|
if (chain !== "" && !rule.alt.includes(chain)) continue;
|
|
5625
5802
|
bucket.push(rule.fn);
|
|
5803
|
+
namedBucket.push({
|
|
5804
|
+
name: rule.name,
|
|
5805
|
+
fn: rule.fn
|
|
5806
|
+
});
|
|
5626
5807
|
}
|
|
5627
5808
|
cache[chain] = bucket;
|
|
5809
|
+
namedCache[chain] = namedBucket;
|
|
5628
5810
|
}
|
|
5629
5811
|
this.cache = cache;
|
|
5812
|
+
this.namedCache = namedCache;
|
|
5630
5813
|
}
|
|
5631
5814
|
};
|
|
5632
5815
|
function isSpace(code$1) {
|
|
@@ -5871,12 +6054,14 @@ var ParserBlock = class {
|
|
|
5871
6054
|
constructor() {
|
|
5872
6055
|
this.ruler = new BlockRuler();
|
|
5873
6056
|
for (let i = 0; i < _rules.length; i++) this.ruler.push(_rules[i][0], _rules[i][1], { alt: (_rules[i][2] || []).slice() });
|
|
6057
|
+
this.ruler.__mdtsDefaultVersion = this.ruler.version;
|
|
5874
6058
|
}
|
|
5875
6059
|
/**
|
|
5876
6060
|
* Generate tokens for input range
|
|
5877
6061
|
*/
|
|
5878
6062
|
tokenize(state, startLine, endLine) {
|
|
5879
6063
|
const rules = this.getRules();
|
|
6064
|
+
const namedRules = this.ruler.getNamedRules("");
|
|
5880
6065
|
const len = rules.length;
|
|
5881
6066
|
const maxNesting = state.md.options.maxNesting;
|
|
5882
6067
|
const bMarks = state.bMarks;
|
|
@@ -5885,6 +6070,7 @@ var ParserBlock = class {
|
|
|
5885
6070
|
const sCount = state.sCount;
|
|
5886
6071
|
let line = startLine;
|
|
5887
6072
|
let hasEmptyLines = false;
|
|
6073
|
+
const shouldProfile = !!state.env && (Object.prototype.hasOwnProperty.call(state.env, "__mdtsRuleProfile") || Object.prototype.hasOwnProperty.call(state.env, "__mdtsProfileRules"));
|
|
5888
6074
|
while (line < endLine) {
|
|
5889
6075
|
while (line < endLine && bMarks[line] + tShift[line] >= eMarks[line]) line++;
|
|
5890
6076
|
state.line = line;
|
|
@@ -5897,7 +6083,13 @@ var ParserBlock = class {
|
|
|
5897
6083
|
const prevLine = state.line;
|
|
5898
6084
|
let ok = false;
|
|
5899
6085
|
for (let i = 0; i < len; i++) {
|
|
5900
|
-
ok = rules[i](state, line, endLine, false);
|
|
6086
|
+
if (!shouldProfile) ok = rules[i](state, line, endLine, false);
|
|
6087
|
+
else {
|
|
6088
|
+
const startedAt = typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
|
|
6089
|
+
ok = namedRules[i].fn(state, line, endLine, false);
|
|
6090
|
+
const endedAt = typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
|
|
6091
|
+
recordRuleInvocation(state.env, "block", namedRules[i].name, endedAt - startedAt, ok, false);
|
|
6092
|
+
}
|
|
5901
6093
|
if (ok) {
|
|
5902
6094
|
if (prevLine >= state.line) throw new Error("block rule didn't increment state.line");
|
|
5903
6095
|
break;
|
|
@@ -6019,7 +6211,19 @@ var ParserCore = class {
|
|
|
6019
6211
|
}
|
|
6020
6212
|
process(state) {
|
|
6021
6213
|
const rules = this.cachedCoreRules ?? (this.cachedCoreRules = this.ruler.getRules(""));
|
|
6022
|
-
|
|
6214
|
+
const namedRules = this.ruler.getNamedRules("");
|
|
6215
|
+
const shouldProfile = !!state.env && (Object.prototype.hasOwnProperty.call(state.env, "__mdtsRuleProfile") || Object.prototype.hasOwnProperty.call(state.env, "__mdtsProfileRules"));
|
|
6216
|
+
for (let i = 0; i < rules.length; i++) {
|
|
6217
|
+
if (!shouldProfile) {
|
|
6218
|
+
rules[i](state);
|
|
6219
|
+
continue;
|
|
6220
|
+
}
|
|
6221
|
+
const startedAt = typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
|
|
6222
|
+
namedRules[i].fn(state);
|
|
6223
|
+
const endedAt = typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
|
|
6224
|
+
recordRuleInvocation(state.env, "core", namedRules[i].name, endedAt - startedAt, true, false);
|
|
6225
|
+
}
|
|
6226
|
+
finalizeRuleProfile(state.env);
|
|
6023
6227
|
}
|
|
6024
6228
|
parseSource(src, env = {}, md) {
|
|
6025
6229
|
if (typeof src !== "string" && hasNormalizationChars(src)) return this.parse(sourceToString(src), env, md);
|
|
@@ -7065,8 +7269,8 @@ const FULL_DISCRETE_RECOMMENDATIONS = [
|
|
|
7065
7269
|
{
|
|
7066
7270
|
max: 5e5,
|
|
7067
7271
|
strategy: "discrete",
|
|
7068
|
-
maxChunkChars:
|
|
7069
|
-
maxChunkLines:
|
|
7272
|
+
maxChunkChars: 64e3,
|
|
7273
|
+
maxChunkLines: 700,
|
|
7070
7274
|
maxChunks: 16,
|
|
7071
7275
|
notes: "<=500k"
|
|
7072
7276
|
},
|
|
@@ -7091,26 +7295,34 @@ const STREAM_DISCRETE_RECOMMENDATIONS = [
|
|
|
7091
7295
|
{
|
|
7092
7296
|
max: 2e4,
|
|
7093
7297
|
strategy: "discrete",
|
|
7094
|
-
maxChunkChars:
|
|
7298
|
+
maxChunkChars: 2e4,
|
|
7095
7299
|
maxChunkLines: 200,
|
|
7096
|
-
maxChunks:
|
|
7300
|
+
maxChunks: 24,
|
|
7097
7301
|
notes: "<=20k"
|
|
7098
7302
|
},
|
|
7099
7303
|
{
|
|
7100
|
-
max:
|
|
7304
|
+
max: 1e5,
|
|
7101
7305
|
strategy: "discrete",
|
|
7102
|
-
maxChunkChars:
|
|
7103
|
-
maxChunkLines:
|
|
7104
|
-
maxChunks:
|
|
7105
|
-
notes: "<=
|
|
7306
|
+
maxChunkChars: 2e4,
|
|
7307
|
+
maxChunkLines: 200,
|
|
7308
|
+
maxChunks: 24,
|
|
7309
|
+
notes: "<=100k"
|
|
7106
7310
|
},
|
|
7107
7311
|
{
|
|
7108
7312
|
max: 5e5,
|
|
7109
7313
|
strategy: "discrete",
|
|
7110
|
-
maxChunkChars:
|
|
7111
|
-
maxChunkLines:
|
|
7112
|
-
maxChunks:
|
|
7314
|
+
maxChunkChars: 64e3,
|
|
7315
|
+
maxChunkLines: 700,
|
|
7316
|
+
maxChunks: 32,
|
|
7113
7317
|
notes: "<=500k"
|
|
7318
|
+
},
|
|
7319
|
+
{
|
|
7320
|
+
max: 5e6,
|
|
7321
|
+
strategy: "discrete",
|
|
7322
|
+
maxChunkChars: 64e3,
|
|
7323
|
+
maxChunkLines: 700,
|
|
7324
|
+
maxChunks: 32,
|
|
7325
|
+
notes: "<=5M"
|
|
7114
7326
|
}
|
|
7115
7327
|
];
|
|
7116
7328
|
function toRecommendation(fenceAware, discrete) {
|
|
@@ -7166,10 +7378,10 @@ function recommendStreamChunkStrategy(sizeChars, sizeLines = Math.max(0, sizeCha
|
|
|
7166
7378
|
break;
|
|
7167
7379
|
}
|
|
7168
7380
|
}
|
|
7169
|
-
if (sizeChars >
|
|
7381
|
+
if (sizeChars > 5e6) return {
|
|
7170
7382
|
strategy: "plain",
|
|
7171
7383
|
fenceAware,
|
|
7172
|
-
notes: ">
|
|
7384
|
+
notes: ">5M plain"
|
|
7173
7385
|
};
|
|
7174
7386
|
if (adaptive) return {
|
|
7175
7387
|
strategy: "adaptive",
|
|
@@ -7584,6 +7796,7 @@ function makeEmptyStats() {
|
|
|
7584
7796
|
total: 0,
|
|
7585
7797
|
cacheHits: 0,
|
|
7586
7798
|
appendHits: 0,
|
|
7799
|
+
unboundedAppendHits: 0,
|
|
7587
7800
|
tailHits: 0,
|
|
7588
7801
|
fullParses: 0,
|
|
7589
7802
|
resets: 0,
|
|
@@ -7596,12 +7809,16 @@ var StreamParser = class {
|
|
|
7596
7809
|
cache = null;
|
|
7597
7810
|
stats = makeEmptyStats();
|
|
7598
7811
|
MIN_SIZE_FOR_OPTIMIZATION = 1e3;
|
|
7599
|
-
DEFAULT_SKIP_CACHE_CHARS =
|
|
7600
|
-
DEFAULT_SKIP_CACHE_LINES =
|
|
7812
|
+
DEFAULT_SKIP_CACHE_CHARS = 1e6;
|
|
7813
|
+
DEFAULT_SKIP_CACHE_LINES = 1e5;
|
|
7814
|
+
IMPLICIT_STREAM_CHUNK_MIN_CHARS = 16e4;
|
|
7601
7815
|
MIN_LIST_LINES_FOR_MERGE = 80;
|
|
7602
7816
|
MIN_LIST_CHARS_FOR_MERGE = 800;
|
|
7603
7817
|
MIN_TABLE_LINES_FOR_MERGE = 48;
|
|
7604
7818
|
MIN_TABLE_CHARS_FOR_MERGE = 1200;
|
|
7819
|
+
MIN_UNBOUNDED_APPEND_TOTAL_CHARS = 5e5;
|
|
7820
|
+
MIN_UNBOUNDED_APPEND_CHARS = 64e3;
|
|
7821
|
+
MIN_UNBOUNDED_APPEND_LINES = 700;
|
|
7605
7822
|
constructor(core) {
|
|
7606
7823
|
this.core = core;
|
|
7607
7824
|
}
|
|
@@ -7620,7 +7837,10 @@ var StreamParser = class {
|
|
|
7620
7837
|
const cached = this.cache;
|
|
7621
7838
|
if (!cached || envProvided && envProvided !== cached.env) {
|
|
7622
7839
|
const workingEnv = envProvided ?? {};
|
|
7623
|
-
const
|
|
7840
|
+
const explicitChunkFallbackSetting$1 = !!md.__explicitStreamChunkFallbackSetting;
|
|
7841
|
+
const wantsChunking$1 = !!md.options?.streamChunkedFallback;
|
|
7842
|
+
const allowImplicitChunk$1 = !explicitChunkFallbackSetting$1;
|
|
7843
|
+
const chunkedEnabled$1 = wantsChunking$1 || allowImplicitChunk$1;
|
|
7624
7844
|
const chunkAdaptive$1 = md.options?.streamChunkAdaptive !== false;
|
|
7625
7845
|
const targetChunks$1 = md.options?.streamChunkTargetChunks ?? 8;
|
|
7626
7846
|
const chunkSizeCharsCfg$1 = md.options?.streamChunkSizeChars;
|
|
@@ -7642,6 +7862,12 @@ var StreamParser = class {
|
|
|
7642
7862
|
this.stats.total += 1;
|
|
7643
7863
|
this.stats.fullParses += 1;
|
|
7644
7864
|
this.stats.lastMode = "full";
|
|
7865
|
+
setStrategyDiagnostics(workingEnv, {
|
|
7866
|
+
area: "stream",
|
|
7867
|
+
path: "stream-full",
|
|
7868
|
+
reason: "skip-cache-large-one-shot",
|
|
7869
|
+
unbounded: !!workingEnv.__mdtsUnboundedInfo
|
|
7870
|
+
});
|
|
7645
7871
|
return parsed$2.tokens;
|
|
7646
7872
|
} else if (chunkedEnabled$1) {
|
|
7647
7873
|
const clamp$1 = (v, lo, hi) => v < lo ? lo : v > hi ? hi : v;
|
|
@@ -7651,7 +7877,8 @@ var StreamParser = class {
|
|
|
7651
7877
|
const useLines = recommendation?.maxChunkLines ?? (chunkAdaptive$1 ? clamp$1(Math.ceil(srcLineCount / targetChunks$1), 150, 700) : chunkSizeLinesCfg$1 ?? 200);
|
|
7652
7878
|
const useMaxChunks = recommendation?.maxChunks ?? (chunkAdaptive$1 ? clamp$1(Math.ceil(src.length / 64e3), targetChunks$1, 32) : chunkMaxChunksCfg$1);
|
|
7653
7879
|
const hasTrailingNewline = src.length > 0 && src.charCodeAt(src.length - 1) === 10;
|
|
7654
|
-
|
|
7880
|
+
const shouldAutoChunk = allowImplicitChunk$1 && src.length >= this.IMPLICIT_STREAM_CHUNK_MIN_CHARS && recommendation?.strategy !== "plain";
|
|
7881
|
+
if ((wantsChunking$1 || shouldAutoChunk) && (src.length >= useChars * 2 || srcLineCount >= useLines * 2) && hasTrailingNewline) {
|
|
7655
7882
|
const tokens = chunkedParse(md, src, workingEnv, {
|
|
7656
7883
|
maxChunkChars: useChars,
|
|
7657
7884
|
maxChunkLines: useLines,
|
|
@@ -7669,6 +7896,12 @@ var StreamParser = class {
|
|
|
7669
7896
|
this.stats.total += 1;
|
|
7670
7897
|
this.stats.chunkedParses = (this.stats.chunkedParses || 0) + 1;
|
|
7671
7898
|
this.stats.lastMode = "chunked";
|
|
7899
|
+
setStrategyDiagnostics(workingEnv, {
|
|
7900
|
+
area: "stream",
|
|
7901
|
+
path: "stream-chunked",
|
|
7902
|
+
chunked: true,
|
|
7903
|
+
reason: wantsChunking$1 ? "explicit-initial-large-doc" : "default-initial-large-doc"
|
|
7904
|
+
});
|
|
7672
7905
|
return tokens;
|
|
7673
7906
|
}
|
|
7674
7907
|
}
|
|
@@ -7685,12 +7918,23 @@ var StreamParser = class {
|
|
|
7685
7918
|
this.stats.total += 1;
|
|
7686
7919
|
this.stats.fullParses += 1;
|
|
7687
7920
|
this.stats.lastMode = "full";
|
|
7921
|
+
setStrategyDiagnostics(workingEnv, {
|
|
7922
|
+
area: "stream",
|
|
7923
|
+
path: "stream-full",
|
|
7924
|
+
reason: "initial-parse",
|
|
7925
|
+
unbounded: !!workingEnv.__mdtsUnboundedInfo
|
|
7926
|
+
});
|
|
7688
7927
|
return parsed$1.tokens;
|
|
7689
7928
|
}
|
|
7690
7929
|
if (src === cached.src) {
|
|
7691
7930
|
this.stats.total += 1;
|
|
7692
7931
|
this.stats.cacheHits += 1;
|
|
7693
7932
|
this.stats.lastMode = "cache";
|
|
7933
|
+
setStrategyDiagnostics(cached.env, {
|
|
7934
|
+
area: "stream",
|
|
7935
|
+
path: "stream-cache",
|
|
7936
|
+
reason: "same-source"
|
|
7937
|
+
});
|
|
7694
7938
|
return cached.tokens;
|
|
7695
7939
|
}
|
|
7696
7940
|
const threshold = md.options?.streamOptimizationMinSize ?? this.MIN_SIZE_FOR_OPTIMIZATION;
|
|
@@ -7710,6 +7954,12 @@ var StreamParser = class {
|
|
|
7710
7954
|
this.stats.total += 1;
|
|
7711
7955
|
this.stats.fullParses += 1;
|
|
7712
7956
|
this.stats.lastMode = "full";
|
|
7957
|
+
setStrategyDiagnostics(fallbackEnv$1, {
|
|
7958
|
+
area: "stream",
|
|
7959
|
+
path: "stream-full",
|
|
7960
|
+
reason: "small-non-append",
|
|
7961
|
+
unbounded: !!fallbackEnv$1.__mdtsUnboundedInfo
|
|
7962
|
+
});
|
|
7713
7963
|
return nextTokens$1;
|
|
7714
7964
|
}
|
|
7715
7965
|
const appended = this.getAppendedSegment(cached.src, src);
|
|
@@ -7819,6 +8069,7 @@ var StreamParser = class {
|
|
|
7819
8069
|
return appendedLineCount;
|
|
7820
8070
|
};
|
|
7821
8071
|
const canDirectParseAppend = this.canDirectlyParseAppend(cached);
|
|
8072
|
+
const useUnboundedAppend = canDirectParseAppend && this.shouldUseUnboundedAppend(src, cached, appended);
|
|
7822
8073
|
let shouldAttemptContext = false;
|
|
7823
8074
|
if (!canDirectParseAppend) switch (ctxStrategy) {
|
|
7824
8075
|
case "lines":
|
|
@@ -7854,10 +8105,15 @@ var StreamParser = class {
|
|
|
7854
8105
|
}
|
|
7855
8106
|
} else appendedState = null;
|
|
7856
8107
|
if (!appendedState) {
|
|
7857
|
-
const simpleState = this.core.parse(appended, cached.env, md);
|
|
7858
8108
|
const lineOffset = cachedLineCount;
|
|
7859
|
-
if (
|
|
7860
|
-
|
|
8109
|
+
if (useUnboundedAppend) {
|
|
8110
|
+
appendedState = { tokens: parseStringUnbounded(md, appended, cached.env, { mode: "stream" }) };
|
|
8111
|
+
if (lineOffset > 0) this.shiftTokenLines(appendedState.tokens, lineOffset);
|
|
8112
|
+
} else {
|
|
8113
|
+
const simpleState = this.core.parse(appended, cached.env, md);
|
|
8114
|
+
if (lineOffset > 0) this.shiftTokenLines(simpleState.tokens, lineOffset);
|
|
8115
|
+
appendedState = simpleState;
|
|
8116
|
+
}
|
|
7861
8117
|
}
|
|
7862
8118
|
if (cached.tokens.length > 0 && appendedState.tokens.length > 0) {
|
|
7863
8119
|
const lastCached = cached.tokens[cached.tokens.length - 1];
|
|
@@ -7866,7 +8122,7 @@ var StreamParser = class {
|
|
|
7866
8122
|
if (lastCached.type === "inline" && firstApp.type === "inline") {
|
|
7867
8123
|
if (firstApp.children && firstApp.children.length > 0) {
|
|
7868
8124
|
if (!lastCached.children) lastCached.children = [];
|
|
7869
|
-
lastCached.children
|
|
8125
|
+
this.appendTokens(lastCached.children, firstApp.children);
|
|
7870
8126
|
}
|
|
7871
8127
|
lastCached.content = (lastCached.content || "") + (firstApp.content || "");
|
|
7872
8128
|
appendedState.tokens.shift();
|
|
@@ -7901,7 +8157,7 @@ var StreamParser = class {
|
|
|
7901
8157
|
}
|
|
7902
8158
|
}
|
|
7903
8159
|
if (dup > 0) a.splice(0, dup);
|
|
7904
|
-
if (a.length > 0) cached.tokens
|
|
8160
|
+
if (a.length > 0) this.appendTokens(cached.tokens, a);
|
|
7905
8161
|
}
|
|
7906
8162
|
cached.src = src;
|
|
7907
8163
|
cached.lineCount = cachedLineCount + (appendedLineCount ?? countLines(appended));
|
|
@@ -7918,7 +8174,14 @@ var StreamParser = class {
|
|
|
7918
8174
|
} else cached.lastSegment = void 0;
|
|
7919
8175
|
this.stats.total += 1;
|
|
7920
8176
|
this.stats.appendHits += 1;
|
|
8177
|
+
if (useUnboundedAppend) this.stats.unboundedAppendHits = (this.stats.unboundedAppendHits || 0) + 1;
|
|
7921
8178
|
this.stats.lastMode = "append";
|
|
8179
|
+
setStrategyDiagnostics(cached.env, {
|
|
8180
|
+
area: "stream",
|
|
8181
|
+
path: useUnboundedAppend ? "stream-unbounded-append" : "stream-append",
|
|
8182
|
+
reason: useUnboundedAppend ? "large-delta" : "safe-append",
|
|
8183
|
+
unbounded: useUnboundedAppend
|
|
8184
|
+
});
|
|
7922
8185
|
return cached.tokens;
|
|
7923
8186
|
}
|
|
7924
8187
|
const fallbackEnv = envProvided ?? cached.env;
|
|
@@ -7927,9 +8190,17 @@ var StreamParser = class {
|
|
|
7927
8190
|
this.stats.total += 1;
|
|
7928
8191
|
this.stats.tailHits += 1;
|
|
7929
8192
|
this.stats.lastMode = "tail";
|
|
8193
|
+
setStrategyDiagnostics(fallbackEnv, {
|
|
8194
|
+
area: "stream",
|
|
8195
|
+
path: "stream-tail",
|
|
8196
|
+
reason: "tail-reparse"
|
|
8197
|
+
});
|
|
7930
8198
|
return tailReparsed;
|
|
7931
8199
|
}
|
|
7932
|
-
const
|
|
8200
|
+
const explicitChunkFallbackSetting = !!md.__explicitStreamChunkFallbackSetting;
|
|
8201
|
+
const wantsChunking = !!md.options?.streamChunkedFallback;
|
|
8202
|
+
const allowImplicitChunk = !explicitChunkFallbackSetting && !appended;
|
|
8203
|
+
const chunkedEnabled = wantsChunking || allowImplicitChunk;
|
|
7933
8204
|
const chunkAdaptive = md.options?.streamChunkAdaptive !== false;
|
|
7934
8205
|
const targetChunks = md.options?.streamChunkTargetChunks ?? 8;
|
|
7935
8206
|
const chunkSizeCharsCfg = md.options?.streamChunkSizeChars;
|
|
@@ -7947,7 +8218,8 @@ var StreamParser = class {
|
|
|
7947
8218
|
const useLines = recommendation?.maxChunkLines ?? (chunkAdaptive ? clamp$1(Math.ceil(srcLineCount2 / targetChunks), 150, 700) : chunkSizeLinesCfg ?? 200);
|
|
7948
8219
|
const useMaxChunks = recommendation?.maxChunks ?? (chunkAdaptive ? clamp$1(Math.ceil(src.length / 64e3), targetChunks, 32) : chunkMaxChunksCfg);
|
|
7949
8220
|
const hasTrailingNewline2 = src.length > 0 && src.charCodeAt(src.length - 1) === 10;
|
|
7950
|
-
|
|
8221
|
+
const shouldAutoChunk = allowImplicitChunk && src.length >= this.IMPLICIT_STREAM_CHUNK_MIN_CHARS && recommendation?.strategy !== "plain";
|
|
8222
|
+
if ((wantsChunking || shouldAutoChunk) && (src.length >= useChars * 2 || srcLineCount2 >= useLines * 2) && hasTrailingNewline2) {
|
|
7951
8223
|
const tokens = chunkedParse(md, src, fallbackEnv, {
|
|
7952
8224
|
maxChunkChars: useChars,
|
|
7953
8225
|
maxChunkLines: useLines,
|
|
@@ -7965,6 +8237,12 @@ var StreamParser = class {
|
|
|
7965
8237
|
this.stats.total += 1;
|
|
7966
8238
|
this.stats.chunkedParses = (this.stats.chunkedParses || 0) + 1;
|
|
7967
8239
|
this.stats.lastMode = "chunked";
|
|
8240
|
+
setStrategyDiagnostics(fallbackEnv, {
|
|
8241
|
+
area: "stream",
|
|
8242
|
+
path: "stream-chunked",
|
|
8243
|
+
chunked: true,
|
|
8244
|
+
reason: wantsChunking ? "explicit-fallback-large-doc" : "default-fallback-large-doc"
|
|
8245
|
+
});
|
|
7968
8246
|
return tokens;
|
|
7969
8247
|
}
|
|
7970
8248
|
}
|
|
@@ -7982,21 +8260,43 @@ var StreamParser = class {
|
|
|
7982
8260
|
this.stats.total += 1;
|
|
7983
8261
|
this.stats.fullParses += 1;
|
|
7984
8262
|
this.stats.lastMode = "full";
|
|
8263
|
+
setStrategyDiagnostics(fallbackEnv, {
|
|
8264
|
+
area: "stream",
|
|
8265
|
+
path: "stream-full",
|
|
8266
|
+
reason: "fallback-full",
|
|
8267
|
+
unbounded: !!fallbackEnv.__mdtsUnboundedInfo
|
|
8268
|
+
});
|
|
7985
8269
|
return nextTokens;
|
|
7986
8270
|
}
|
|
7987
8271
|
parseFullDocument(src, env, md, knownLineCount, needLineCount = true) {
|
|
7988
8272
|
const autoUnboundedDecision = getAutoUnboundedDecision(md, src.length, knownLineCount);
|
|
7989
|
-
if (autoUnboundedDecision === "yes")
|
|
7990
|
-
|
|
7991
|
-
|
|
7992
|
-
|
|
8273
|
+
if (autoUnboundedDecision === "yes") {
|
|
8274
|
+
setStrategyDiagnostics(env, {
|
|
8275
|
+
area: "stream",
|
|
8276
|
+
path: "stream-full",
|
|
8277
|
+
reason: "auto-unbounded-char-threshold",
|
|
8278
|
+
unbounded: true
|
|
8279
|
+
});
|
|
8280
|
+
return {
|
|
8281
|
+
tokens: parseStringUnbounded(md, src, env),
|
|
8282
|
+
lineCount: knownLineCount ?? (needLineCount ? countLines(src) : 0)
|
|
8283
|
+
};
|
|
8284
|
+
}
|
|
7993
8285
|
let lineCount = knownLineCount;
|
|
7994
8286
|
if (autoUnboundedDecision === "need-lines") {
|
|
7995
8287
|
lineCount = countLines(src);
|
|
7996
|
-
if (shouldAutoUseUnbounded(md, src.length, lineCount))
|
|
7997
|
-
|
|
7998
|
-
|
|
7999
|
-
|
|
8288
|
+
if (shouldAutoUseUnbounded(md, src.length, lineCount)) {
|
|
8289
|
+
setStrategyDiagnostics(env, {
|
|
8290
|
+
area: "stream",
|
|
8291
|
+
path: "stream-full",
|
|
8292
|
+
reason: "auto-unbounded-line-threshold",
|
|
8293
|
+
unbounded: true
|
|
8294
|
+
});
|
|
8295
|
+
return {
|
|
8296
|
+
tokens: parseStringUnbounded(md, src, env),
|
|
8297
|
+
lineCount
|
|
8298
|
+
};
|
|
8299
|
+
}
|
|
8000
8300
|
}
|
|
8001
8301
|
if (lineCount === void 0) lineCount = needLineCount ? countLines(src) : 0;
|
|
8002
8302
|
return {
|
|
@@ -8004,6 +8304,12 @@ var StreamParser = class {
|
|
|
8004
8304
|
lineCount
|
|
8005
8305
|
};
|
|
8006
8306
|
}
|
|
8307
|
+
shouldUseUnboundedAppend(src, _cached, appended) {
|
|
8308
|
+
if (!appended) return false;
|
|
8309
|
+
if (src.length < this.MIN_UNBOUNDED_APPEND_TOTAL_CHARS && appended.length < this.MIN_UNBOUNDED_APPEND_CHARS) return false;
|
|
8310
|
+
if (appended.length >= this.MIN_UNBOUNDED_APPEND_CHARS) return true;
|
|
8311
|
+
return countLines(appended) >= this.MIN_UNBOUNDED_APPEND_LINES;
|
|
8312
|
+
}
|
|
8007
8313
|
getAppendedSegment(prev, next) {
|
|
8008
8314
|
if (!next.startsWith(prev)) return null;
|
|
8009
8315
|
if (!prev.endsWith("\n")) return null;
|
|
@@ -8052,7 +8358,7 @@ var StreamParser = class {
|
|
|
8052
8358
|
cached.src = src;
|
|
8053
8359
|
cached.env = env;
|
|
8054
8360
|
cached.tokens.length = lastSegment.tokenStart;
|
|
8055
|
-
cached.tokens
|
|
8361
|
+
this.appendTokens(cached.tokens, tailState.tokens);
|
|
8056
8362
|
cached.lineCount = countLines(src);
|
|
8057
8363
|
if (localLastSegment) cached.lastSegment = {
|
|
8058
8364
|
tokenStart: lastSegment.tokenStart + localLastSegment.tokenStart,
|
|
@@ -8118,6 +8424,9 @@ var StreamParser = class {
|
|
|
8118
8424
|
getStats() {
|
|
8119
8425
|
return { ...this.stats };
|
|
8120
8426
|
}
|
|
8427
|
+
appendTokens(target, source) {
|
|
8428
|
+
for (let i = 0; i < source.length; i++) target.push(source[i]);
|
|
8429
|
+
}
|
|
8121
8430
|
updateCacheLineCount(cache, lineCount) {
|
|
8122
8431
|
cache.lineCount = lineCount ?? countLines(cache.src);
|
|
8123
8432
|
cache.lastSegment = void 0;
|
|
@@ -8431,6 +8740,9 @@ function hasExplicitChunkOverride(presetOptions, userOptions, keys) {
|
|
|
8431
8740
|
}
|
|
8432
8741
|
return false;
|
|
8433
8742
|
}
|
|
8743
|
+
function hasExplicitOption(presetOptions, userOptions, key) {
|
|
8744
|
+
return !!userOptions && Object.prototype.hasOwnProperty.call(userOptions, key) || !!presetOptions && Object.prototype.hasOwnProperty.call(presetOptions, key);
|
|
8745
|
+
}
|
|
8434
8746
|
function markdownIt(presetName, options) {
|
|
8435
8747
|
let opts = {
|
|
8436
8748
|
html: false,
|
|
@@ -8451,8 +8763,8 @@ function markdownIt(presetName, options) {
|
|
|
8451
8763
|
streamChunkAdaptive: true,
|
|
8452
8764
|
streamChunkTargetChunks: 8,
|
|
8453
8765
|
streamChunkMaxChunks: void 0,
|
|
8454
|
-
streamSkipCacheAboveChars:
|
|
8455
|
-
streamSkipCacheAboveLines:
|
|
8766
|
+
streamSkipCacheAboveChars: 1e6,
|
|
8767
|
+
streamSkipCacheAboveLines: 1e5,
|
|
8456
8768
|
fullChunkedFallback: false,
|
|
8457
8769
|
fullChunkThresholdChars: 2e4,
|
|
8458
8770
|
fullChunkThresholdLines: 400,
|
|
@@ -8511,6 +8823,8 @@ function markdownIt(presetName, options) {
|
|
|
8511
8823
|
"streamChunkSizeLines",
|
|
8512
8824
|
"streamChunkMaxChunks"
|
|
8513
8825
|
]);
|
|
8826
|
+
let explicitFullChunkFallbackSetting = hasExplicitOption(preset?.options, userOptions, "fullChunkedFallback");
|
|
8827
|
+
let explicitStreamChunkFallbackSetting = hasExplicitOption(preset?.options, userOptions, "streamChunkedFallback");
|
|
8514
8828
|
const core = new ParserCore();
|
|
8515
8829
|
let renderer = null;
|
|
8516
8830
|
const getRenderer = () => {
|
|
@@ -8552,6 +8866,8 @@ function markdownIt(presetName, options) {
|
|
|
8552
8866
|
options: opts,
|
|
8553
8867
|
__explicitFullChunkConfig: explicitFullChunkConfig,
|
|
8554
8868
|
__explicitStreamChunkConfig: explicitStreamChunkConfig,
|
|
8869
|
+
__explicitFullChunkFallbackSetting: explicitFullChunkFallbackSetting,
|
|
8870
|
+
__explicitStreamChunkFallbackSetting: explicitStreamChunkFallbackSetting,
|
|
8555
8871
|
set(newOpts) {
|
|
8556
8872
|
this.options = {
|
|
8557
8873
|
...this.options,
|
|
@@ -8565,6 +8881,14 @@ function markdownIt(presetName, options) {
|
|
|
8565
8881
|
explicitStreamChunkConfig = true;
|
|
8566
8882
|
this.__explicitStreamChunkConfig = true;
|
|
8567
8883
|
}
|
|
8884
|
+
if (Object.prototype.hasOwnProperty.call(newOpts, "fullChunkedFallback")) {
|
|
8885
|
+
explicitFullChunkFallbackSetting = true;
|
|
8886
|
+
this.__explicitFullChunkFallbackSetting = true;
|
|
8887
|
+
}
|
|
8888
|
+
if (Object.prototype.hasOwnProperty.call(newOpts, "streamChunkedFallback")) {
|
|
8889
|
+
explicitStreamChunkFallbackSetting = true;
|
|
8890
|
+
this.__explicitStreamChunkFallbackSetting = true;
|
|
8891
|
+
}
|
|
8568
8892
|
if (renderer) renderer.set(newOpts);
|
|
8569
8893
|
if (typeof newOpts.stream === "boolean") {
|
|
8570
8894
|
this.stream.enabled = newOpts.stream;
|
|
@@ -8657,20 +8981,38 @@ function markdownIt(presetName, options) {
|
|
|
8657
8981
|
helpers: { ...helpers_exports },
|
|
8658
8982
|
parse(src, env = {}) {
|
|
8659
8983
|
if (typeof src !== "string") throw new TypeError("Input data should be a String");
|
|
8984
|
+
let countedLines;
|
|
8660
8985
|
if (!this.stream.enabled && !this.options.fullChunkedFallback) {
|
|
8661
8986
|
const autoUnboundedDecision = getAutoUnboundedDecision(this, src.length);
|
|
8662
|
-
if (autoUnboundedDecision === "yes")
|
|
8663
|
-
|
|
8664
|
-
|
|
8987
|
+
if (autoUnboundedDecision === "yes") {
|
|
8988
|
+
setStrategyDiagnostics(env, {
|
|
8989
|
+
area: "parse",
|
|
8990
|
+
path: "auto-unbounded",
|
|
8991
|
+
unbounded: true,
|
|
8992
|
+
reason: "char-threshold"
|
|
8993
|
+
});
|
|
8994
|
+
return parseStringUnbounded(this, src, env);
|
|
8995
|
+
}
|
|
8996
|
+
if (autoUnboundedDecision === "need-lines") countedLines = countLines(src);
|
|
8665
8997
|
}
|
|
8666
8998
|
if (!this.stream.enabled) {
|
|
8667
8999
|
const chars = src.length;
|
|
8668
|
-
|
|
8669
|
-
|
|
8670
|
-
|
|
8671
|
-
|
|
8672
|
-
|
|
8673
|
-
|
|
9000
|
+
const lines = countedLines ?? countLines(src);
|
|
9001
|
+
const auto = this.options.autoTuneChunks !== false;
|
|
9002
|
+
const userForcedChunk = explicitFullChunkConfig;
|
|
9003
|
+
const allowImplicitChunk = !explicitFullChunkFallbackSetting;
|
|
9004
|
+
const wantsChunking = !!this.options.fullChunkedFallback;
|
|
9005
|
+
const shouldAutoChunk = allowImplicitChunk && chars >= 2e5;
|
|
9006
|
+
const autoRecommendation = auto && !userForcedChunk ? recommendFullChunkStrategy(chars, lines, this.options) : null;
|
|
9007
|
+
if (wantsChunking || shouldAutoChunk) {
|
|
9008
|
+
if (wantsChunking ? chars >= (this.options.fullChunkThresholdChars ?? 2e4) || lines >= (this.options.fullChunkThresholdLines ?? 400) : shouldAutoChunk) {
|
|
9009
|
+
if (autoRecommendation && autoRecommendation.strategy !== "plain") {
|
|
9010
|
+
setStrategyDiagnostics(env, {
|
|
9011
|
+
area: "parse",
|
|
9012
|
+
path: "full-chunk",
|
|
9013
|
+
chunked: true,
|
|
9014
|
+
reason: wantsChunking ? "explicit-full-chunk" : "default-large-string"
|
|
9015
|
+
});
|
|
8674
9016
|
return chunkedParse(this, src, env, {
|
|
8675
9017
|
maxChunkChars: autoRecommendation.maxChunkChars,
|
|
8676
9018
|
maxChunkLines: autoRecommendation.maxChunkLines,
|
|
@@ -8678,23 +9020,45 @@ function markdownIt(presetName, options) {
|
|
|
8678
9020
|
maxChunks: autoRecommendation.maxChunks
|
|
8679
9021
|
});
|
|
8680
9022
|
}
|
|
8681
|
-
|
|
8682
|
-
|
|
8683
|
-
|
|
8684
|
-
|
|
8685
|
-
|
|
8686
|
-
|
|
8687
|
-
|
|
8688
|
-
|
|
8689
|
-
|
|
8690
|
-
|
|
8691
|
-
|
|
8692
|
-
|
|
8693
|
-
|
|
8694
|
-
|
|
9023
|
+
if (wantsChunking) {
|
|
9024
|
+
const clamp$1 = (v, lo, hi) => v < lo ? lo : v > hi ? hi : v;
|
|
9025
|
+
const adaptive = this.options.fullChunkAdaptive !== false;
|
|
9026
|
+
const target = this.options.fullChunkTargetChunks ?? 8;
|
|
9027
|
+
const dynMaxChunkChars = clamp$1(Math.ceil(chars / target), 8e3, 64e3);
|
|
9028
|
+
const dynMaxChunkLines = clamp$1(Math.ceil(lines / target), 150, 700);
|
|
9029
|
+
const maxChunkChars = adaptive ? dynMaxChunkChars : this.options.fullChunkSizeChars ?? 1e4;
|
|
9030
|
+
const maxChunkLines = adaptive ? dynMaxChunkLines : this.options.fullChunkSizeLines ?? 200;
|
|
9031
|
+
const maxChunks = adaptive ? clamp$1(Math.ceil(chars / 64e3), target, 32) : this.options.fullChunkMaxChunks;
|
|
9032
|
+
setStrategyDiagnostics(env, {
|
|
9033
|
+
area: "parse",
|
|
9034
|
+
path: "full-chunk",
|
|
9035
|
+
chunked: true,
|
|
9036
|
+
reason: "explicit-full-chunk"
|
|
9037
|
+
});
|
|
9038
|
+
return chunkedParse(this, src, env, {
|
|
9039
|
+
maxChunkChars,
|
|
9040
|
+
maxChunkLines,
|
|
9041
|
+
fenceAware: this.options.fullChunkFenceAware ?? true,
|
|
9042
|
+
maxChunks
|
|
9043
|
+
});
|
|
9044
|
+
}
|
|
8695
9045
|
}
|
|
8696
9046
|
}
|
|
9047
|
+
if (countedLines !== void 0 && shouldAutoUseUnbounded(this, chars, lines)) {
|
|
9048
|
+
setStrategyDiagnostics(env, {
|
|
9049
|
+
area: "parse",
|
|
9050
|
+
path: "auto-unbounded",
|
|
9051
|
+
unbounded: true,
|
|
9052
|
+
reason: "line-threshold"
|
|
9053
|
+
});
|
|
9054
|
+
return parseStringUnbounded(this, src, env);
|
|
9055
|
+
}
|
|
8697
9056
|
}
|
|
9057
|
+
setStrategyDiagnostics(env, {
|
|
9058
|
+
area: "parse",
|
|
9059
|
+
path: "plain",
|
|
9060
|
+
reason: "default-plain"
|
|
9061
|
+
});
|
|
8698
9062
|
return core.parse(src, env, this).tokens;
|
|
8699
9063
|
},
|
|
8700
9064
|
parseIterable(chunks, env = {}) {
|
|
@@ -8734,6 +9098,7 @@ function markdownIt(presetName, options) {
|
|
|
8734
9098
|
total: 0,
|
|
8735
9099
|
cacheHits: 0,
|
|
8736
9100
|
appendHits: 0,
|
|
9101
|
+
unboundedAppendHits: 0,
|
|
8737
9102
|
tailHits: 0,
|
|
8738
9103
|
fullParses: 0,
|
|
8739
9104
|
resets: 0,
|
|
@@ -9132,7 +9497,93 @@ const OPEN_TAG_RE = /<([A-Z][\w-]*)(?=[\s/>]|$)/gi;
|
|
|
9132
9497
|
const CLOSE_TAG_RE = /<\/\s*([A-Z][\w-]*)(?=[\s/>]|$)/gi;
|
|
9133
9498
|
const TAG_NAME_AT_START_RE = /^<\s*(?:\/\s*)?([A-Z][\w-]*)/i;
|
|
9134
9499
|
const STRICT_OPEN_TAG_NAME_AT_START_RE = /^<\s*([A-Z][\w:-]*)(?=[\s/>]|$)/i;
|
|
9135
|
-
function
|
|
9500
|
+
function getHtmlInlineTagName(content) {
|
|
9501
|
+
return (content.match(TAG_NAME_AT_START_RE)?.[1] ?? "").toLowerCase();
|
|
9502
|
+
}
|
|
9503
|
+
function isHtmlInlineClosingTag(content) {
|
|
9504
|
+
return /^\s*<\s*\//.test(content);
|
|
9505
|
+
}
|
|
9506
|
+
function isSelfClosingHtmlInline(content, tag) {
|
|
9507
|
+
return VOID_TAGS$2.has(tag) || /\/\s*>\s*$/.test(content);
|
|
9508
|
+
}
|
|
9509
|
+
function escapeRegex$1(value) {
|
|
9510
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
9511
|
+
}
|
|
9512
|
+
function findMatchingCloseChildIndex(children, tag) {
|
|
9513
|
+
let depth = 0;
|
|
9514
|
+
for (let index = 0; index < children.length; index++) {
|
|
9515
|
+
const child = children[index];
|
|
9516
|
+
if (!child || child.type !== "html_inline") continue;
|
|
9517
|
+
const content = String(child.content ?? "");
|
|
9518
|
+
const childTag = getHtmlInlineTagName(content);
|
|
9519
|
+
if (childTag !== tag) continue;
|
|
9520
|
+
if (isHtmlInlineClosingTag(content)) {
|
|
9521
|
+
if (depth === 0) return index;
|
|
9522
|
+
depth--;
|
|
9523
|
+
continue;
|
|
9524
|
+
}
|
|
9525
|
+
if (!isSelfClosingHtmlInline(content, childTag)) depth++;
|
|
9526
|
+
}
|
|
9527
|
+
return -1;
|
|
9528
|
+
}
|
|
9529
|
+
function getTrailingOpenDepth(children, tag) {
|
|
9530
|
+
let depth = 0;
|
|
9531
|
+
for (const child of children) {
|
|
9532
|
+
if (!child || child.type !== "html_inline") continue;
|
|
9533
|
+
const content = String(child.content ?? "");
|
|
9534
|
+
const childTag = getHtmlInlineTagName(content);
|
|
9535
|
+
if (childTag !== tag) continue;
|
|
9536
|
+
if (isHtmlInlineClosingTag(content)) {
|
|
9537
|
+
if (depth > 0) depth--;
|
|
9538
|
+
continue;
|
|
9539
|
+
}
|
|
9540
|
+
if (!isSelfClosingHtmlInline(content, childTag)) depth++;
|
|
9541
|
+
}
|
|
9542
|
+
return depth;
|
|
9543
|
+
}
|
|
9544
|
+
function findMatchingCloseRangeInHtml(content, tag, startIndex = 0) {
|
|
9545
|
+
const tokenRe = new RegExp(String.raw`<\s*(\/?)\s*${escapeRegex$1(tag)}(?=[\s>/])[^>]*>`, "gi");
|
|
9546
|
+
tokenRe.lastIndex = Math.max(0, startIndex);
|
|
9547
|
+
let depth = 0;
|
|
9548
|
+
let match;
|
|
9549
|
+
while ((match = tokenRe.exec(content)) !== null) {
|
|
9550
|
+
const raw = match[0] ?? "";
|
|
9551
|
+
const closing = !!match[1];
|
|
9552
|
+
const selfClosing = !closing && /\/\s*>$/.test(raw);
|
|
9553
|
+
if (closing) {
|
|
9554
|
+
if (depth === 0) return {
|
|
9555
|
+
start: match.index,
|
|
9556
|
+
end: match.index + raw.length
|
|
9557
|
+
};
|
|
9558
|
+
depth--;
|
|
9559
|
+
continue;
|
|
9560
|
+
}
|
|
9561
|
+
if (!selfClosing) depth++;
|
|
9562
|
+
}
|
|
9563
|
+
return null;
|
|
9564
|
+
}
|
|
9565
|
+
function findMatchingCloseOffsetInHtml(content, tag, startIndex = 0) {
|
|
9566
|
+
const range = findMatchingCloseRangeInHtml(content, tag, startIndex);
|
|
9567
|
+
if (!range) return -1;
|
|
9568
|
+
return range.end;
|
|
9569
|
+
}
|
|
9570
|
+
function getTrailingCustomTagDepthInHtml(content, tag) {
|
|
9571
|
+
const tokenRe = new RegExp(String.raw`<\s*(\/?)\s*${escapeRegex$1(tag)}(?=[\s>/])[^>]*>`, "gi");
|
|
9572
|
+
let depth = 0;
|
|
9573
|
+
let match;
|
|
9574
|
+
while ((match = tokenRe.exec(content)) !== null) {
|
|
9575
|
+
const raw = match[0] ?? "";
|
|
9576
|
+
const closing = !!match[1];
|
|
9577
|
+
const selfClosing = !closing && /\/\s*>$/.test(raw);
|
|
9578
|
+
if (closing) {
|
|
9579
|
+
if (depth > 0) depth--;
|
|
9580
|
+
continue;
|
|
9581
|
+
}
|
|
9582
|
+
if (!selfClosing) depth++;
|
|
9583
|
+
}
|
|
9584
|
+
return depth;
|
|
9585
|
+
}
|
|
9586
|
+
function findTagCloseIndexOutsideQuotes$2(html) {
|
|
9136
9587
|
let inSingle = false;
|
|
9137
9588
|
let inDouble = false;
|
|
9138
9589
|
for (let i = 0; i < html.length; i++) {
|
|
@@ -9176,7 +9627,7 @@ function findFirstIncompleteTag(content, tagSet) {
|
|
|
9176
9627
|
if (idx < 0) continue;
|
|
9177
9628
|
const tag = (m[1] ?? "").toLowerCase();
|
|
9178
9629
|
if (!isCommonHtmlTagOrPrefix(tag, tagSet)) continue;
|
|
9179
|
-
if (findTagCloseIndexOutsideQuotes$
|
|
9630
|
+
if (findTagCloseIndexOutsideQuotes$2(content.slice(idx)) !== -1) continue;
|
|
9180
9631
|
if (!first || idx < first.index) first = {
|
|
9181
9632
|
index: idx,
|
|
9182
9633
|
tag,
|
|
@@ -9188,7 +9639,7 @@ function findFirstIncompleteTag(content, tagSet) {
|
|
|
9188
9639
|
if (idx < 0) continue;
|
|
9189
9640
|
const tag = (m[1] ?? "").toLowerCase();
|
|
9190
9641
|
if (!isCommonHtmlTagOrPrefix(tag, tagSet)) continue;
|
|
9191
|
-
if (findTagCloseIndexOutsideQuotes$
|
|
9642
|
+
if (findTagCloseIndexOutsideQuotes$2(content.slice(idx)) !== -1) continue;
|
|
9192
9643
|
if (!first || idx < first.index) first = {
|
|
9193
9644
|
index: idx,
|
|
9194
9645
|
tag,
|
|
@@ -9254,7 +9705,7 @@ function fixStreamingHtmlInlineChildren(children, tagSet) {
|
|
|
9254
9705
|
cursor = lt + 1;
|
|
9255
9706
|
continue;
|
|
9256
9707
|
}
|
|
9257
|
-
const closeIdx = findTagCloseIndexOutsideQuotes$
|
|
9708
|
+
const closeIdx = findTagCloseIndexOutsideQuotes$2(sub);
|
|
9258
9709
|
if (closeIdx === -1) {
|
|
9259
9710
|
pushTextPart("<", baseToken);
|
|
9260
9711
|
cursor = lt + 1;
|
|
@@ -9292,7 +9743,7 @@ function fixStreamingHtmlInlineChildren(children, tagSet) {
|
|
|
9292
9743
|
if (pending) {
|
|
9293
9744
|
pending.buffer += tokenToRaw$1(child);
|
|
9294
9745
|
pendingAtEnd = pending.buffer;
|
|
9295
|
-
const closeIdx = findTagCloseIndexOutsideQuotes$
|
|
9746
|
+
const closeIdx = findTagCloseIndexOutsideQuotes$2(pending.buffer);
|
|
9296
9747
|
if (closeIdx === -1) continue;
|
|
9297
9748
|
const tagChunk = pending.buffer.slice(0, closeIdx + 1);
|
|
9298
9749
|
const afterChunk = pending.buffer.slice(closeIdx + 1);
|
|
@@ -9310,7 +9761,7 @@ function fixStreamingHtmlInlineChildren(children, tagSet) {
|
|
|
9310
9761
|
if (child.type === "html_inline") {
|
|
9311
9762
|
const content = tokenToRaw$1(child);
|
|
9312
9763
|
const tagName = (content.match(TAG_NAME_AT_START_RE)?.[1] ?? "").toLowerCase();
|
|
9313
|
-
if (tagName && tagSet.has(tagName) && findTagCloseIndexOutsideQuotes$
|
|
9764
|
+
if (tagName && tagSet.has(tagName) && findTagCloseIndexOutsideQuotes$2(content) === -1) {
|
|
9314
9765
|
pending = {
|
|
9315
9766
|
tag: tagName,
|
|
9316
9767
|
buffer: content,
|
|
@@ -9357,6 +9808,7 @@ function applyFixHtmlInlineTokens(md, options = {}) {
|
|
|
9357
9808
|
customTagSet.add(name);
|
|
9358
9809
|
autoCloseInlineTagSet.add(name);
|
|
9359
9810
|
}
|
|
9811
|
+
const shouldMergeHtmlBlockTag = (tag) => customTagSet.has(tag) || !commonHtmlTags.has(tag);
|
|
9360
9812
|
md.core.ruler.after("inline", "fix_html_inline_streaming", (state) => {
|
|
9361
9813
|
const toks = state.tokens ?? [];
|
|
9362
9814
|
for (const t of toks) {
|
|
@@ -9399,15 +9851,13 @@ function applyFixHtmlInlineTokens(md, options = {}) {
|
|
|
9399
9851
|
continue;
|
|
9400
9852
|
}
|
|
9401
9853
|
const chunk = String(t.content ?? t.raw ?? "");
|
|
9402
|
-
const
|
|
9403
|
-
const
|
|
9404
|
-
const isClosingTag$1 = !!closeMatch;
|
|
9854
|
+
const closeEnd = chunk ? findMatchingCloseOffsetInHtml(chunk, openTag) : -1;
|
|
9855
|
+
const isClosingTag$1 = closeEnd !== -1;
|
|
9405
9856
|
if (chunk) {
|
|
9406
9857
|
const openToken = toks[openIndex];
|
|
9407
|
-
if (
|
|
9408
|
-
const
|
|
9409
|
-
const
|
|
9410
|
-
const after = chunk.slice(end);
|
|
9858
|
+
if (closeEnd !== -1) {
|
|
9859
|
+
const before = chunk.slice(0, closeEnd);
|
|
9860
|
+
const after = chunk.slice(closeEnd);
|
|
9411
9861
|
openToken.content = `${String(openToken.content || "")}\n${before}`;
|
|
9412
9862
|
openToken.loading = false;
|
|
9413
9863
|
const afterTrimmed = after.replace(/^\s+/, "");
|
|
@@ -9441,11 +9891,10 @@ function applyFixHtmlInlineTokens(md, options = {}) {
|
|
|
9441
9891
|
const rawContent = String(t.content || "");
|
|
9442
9892
|
const tag = (rawContent.match(/<\s*(?:\/\s*)?([^\s>/]+)/)?.[1] ?? "").toLowerCase();
|
|
9443
9893
|
const isClosingTag$1 = /^\s*<\s*\//.test(rawContent);
|
|
9444
|
-
if (!tag || !
|
|
9894
|
+
if (!tag || !shouldMergeHtmlBlockTag(tag)) continue;
|
|
9445
9895
|
if (!isClosingTag$1) {
|
|
9446
9896
|
if (tag) {
|
|
9447
|
-
|
|
9448
|
-
if (!new RegExp(`^\\s*<\\s*${tag}\\b[^>]*\\/\\s*>`, "i").test(rawContent) && !closeRe.test(rawContent)) tagStack.push([tag, i]);
|
|
9897
|
+
if (!new RegExp(`^\\s*<\\s*${tag}\\b[^>]*\\/\\s*>`, "i").test(rawContent) && getTrailingCustomTagDepthInHtml(rawContent, tag) > 0) tagStack.push([tag, i]);
|
|
9449
9898
|
}
|
|
9450
9899
|
} else if (tagStack.length > 0 && tag && tagStack[tagStack.length - 1][0] === tag) {
|
|
9451
9900
|
const [, openIndex] = tagStack[tagStack.length - 1];
|
|
@@ -9515,15 +9964,11 @@ function applyFixHtmlInlineTokens(md, options = {}) {
|
|
|
9515
9964
|
continue;
|
|
9516
9965
|
}
|
|
9517
9966
|
if (tok.type !== "inline") continue;
|
|
9518
|
-
const children = Array.isArray(tok.children) ? tok.children : [];
|
|
9519
|
-
const closeChildIndex = children.
|
|
9520
|
-
if (!c || c.type !== "html_inline") return false;
|
|
9521
|
-
const cContent = String(c.content ?? "");
|
|
9522
|
-
return /^\s*<\s*\//.test(cContent) && cContent.toLowerCase().includes(top.tag);
|
|
9523
|
-
});
|
|
9967
|
+
const children$1 = Array.isArray(tok.children) ? tok.children : [];
|
|
9968
|
+
const closeChildIndex = findMatchingCloseChildIndex(children$1, top.tag);
|
|
9524
9969
|
if (closeChildIndex !== -1) {
|
|
9525
|
-
const beforeChildren = children.slice(0, closeChildIndex + 1);
|
|
9526
|
-
const afterChildren = children.slice(closeChildIndex + 1);
|
|
9970
|
+
const beforeChildren = children$1.slice(0, closeChildIndex + 1);
|
|
9971
|
+
const afterChildren = children$1.slice(closeChildIndex + 1);
|
|
9527
9972
|
const beforeText = beforeChildren.map((c) => String(c?.content ?? c?.raw ?? "")).join("");
|
|
9528
9973
|
openTok.content = `${String(openTok.content ?? "")}\n${beforeText}`;
|
|
9529
9974
|
if (Array.isArray(openTok.children)) openTok.children.push(...beforeChildren);
|
|
@@ -9566,13 +10011,14 @@ function applyFixHtmlInlineTokens(md, options = {}) {
|
|
|
9566
10011
|
continue;
|
|
9567
10012
|
}
|
|
9568
10013
|
openTok.content = `${String(openTok.content ?? "")}\n${content}`;
|
|
9569
|
-
if (Array.isArray(openTok.children)) openTok.children.push(...children);
|
|
10014
|
+
if (Array.isArray(openTok.children)) openTok.children.push(...children$1);
|
|
9570
10015
|
toks.splice(i, 1);
|
|
9571
10016
|
i--;
|
|
9572
10017
|
continue;
|
|
9573
10018
|
}
|
|
9574
10019
|
if (tok.type !== "inline") continue;
|
|
9575
|
-
|
|
10020
|
+
const children = Array.isArray(tok.children) ? tok.children : [];
|
|
10021
|
+
for (const tag of customTagSet) if ((children.length ? getTrailingOpenDepth(children, tag) : getOpenRe(tag).test(content) && !getCloseRe(tag).test(content) ? 1 : 0) > 0) {
|
|
9576
10022
|
stack.push({
|
|
9577
10023
|
tag,
|
|
9578
10024
|
index: i
|
|
@@ -9606,15 +10052,14 @@ function applyFixHtmlInlineTokens(md, options = {}) {
|
|
|
9606
10052
|
}
|
|
9607
10053
|
if (customTagSet.has(tag)) {
|
|
9608
10054
|
const raw$2 = String(t.content ?? "");
|
|
9609
|
-
const
|
|
9610
|
-
|
|
9611
|
-
|
|
9612
|
-
const endTagIndex$1 =
|
|
9613
|
-
const closeLen$1 =
|
|
10055
|
+
const openEnd = findTagCloseIndexOutsideQuotes$2(raw$2);
|
|
10056
|
+
const closeRange = openEnd === -1 ? null : findMatchingCloseRangeInHtml(raw$2, tag, openEnd + 1);
|
|
10057
|
+
t.loading = !!closeRange ? false : t.loading !== void 0 ? t.loading : true;
|
|
10058
|
+
const endTagIndex$1 = closeRange?.start ?? -1;
|
|
10059
|
+
const closeLen$1 = closeRange ? closeRange.end - closeRange.start : 0;
|
|
9614
10060
|
if (endTagIndex$1 !== -1) {
|
|
9615
10061
|
const rawForNode = raw$2.slice(0, endTagIndex$1 + closeLen$1);
|
|
9616
10062
|
let inner = "";
|
|
9617
|
-
const openEnd = findTagCloseIndexOutsideQuotes$1(raw$2);
|
|
9618
10063
|
if (openEnd !== -1 && openEnd < endTagIndex$1) inner = raw$2.slice(openEnd + 1, endTagIndex$1);
|
|
9619
10064
|
t.children = [{
|
|
9620
10065
|
type: tag,
|
|
@@ -10128,7 +10573,7 @@ function fixLinkToken(tokens) {
|
|
|
10128
10573
|
tokens[i - 1].content = "";
|
|
10129
10574
|
}
|
|
10130
10575
|
}
|
|
10131
|
-
if (curToken.type === "link_close" && curToken.nesting === -1 && tokens[i + 1]?.type === "text" && tokens[i - 1]?.type === "text") {
|
|
10576
|
+
if (curToken.type === "link_close" && curToken.nesting === -1 && tokens[i - 2]?.type === "link_open" && tokens[i + 1]?.type === "text" && tokens[i - 1]?.type === "text") {
|
|
10132
10577
|
const text$1 = tokens[i - 1].content || "";
|
|
10133
10578
|
const attrs = tokens[i - 2].attrs || [];
|
|
10134
10579
|
const href = attrs.find((a) => a[0] === "href")?.[1] || "";
|
|
@@ -13677,7 +14122,57 @@ const VOID_TAGS = new Set([
|
|
|
13677
14122
|
"track",
|
|
13678
14123
|
"wbr"
|
|
13679
14124
|
]);
|
|
13680
|
-
|
|
14125
|
+
function findTagCloseIndexOutsideQuotes$1(input) {
|
|
14126
|
+
let inSingle = false;
|
|
14127
|
+
let inDouble = false;
|
|
14128
|
+
for (let i = 0; i < input.length; i++) {
|
|
14129
|
+
const ch = input[i];
|
|
14130
|
+
if (ch === "\\") {
|
|
14131
|
+
i++;
|
|
14132
|
+
continue;
|
|
14133
|
+
}
|
|
14134
|
+
if (!inDouble && ch === "'") {
|
|
14135
|
+
inSingle = !inSingle;
|
|
14136
|
+
continue;
|
|
14137
|
+
}
|
|
14138
|
+
if (!inSingle && ch === "\"") {
|
|
14139
|
+
inDouble = !inDouble;
|
|
14140
|
+
continue;
|
|
14141
|
+
}
|
|
14142
|
+
if (!inSingle && !inDouble && ch === ">") return i;
|
|
14143
|
+
}
|
|
14144
|
+
return -1;
|
|
14145
|
+
}
|
|
14146
|
+
function findMatchingCloseTagEnd(rawHtml, tag, startIndex) {
|
|
14147
|
+
const lowerTag = tag.toLowerCase();
|
|
14148
|
+
const openTagRe = new RegExp(String.raw`^<\s*${lowerTag}(?=\s|>|/)`, "i");
|
|
14149
|
+
const closeTagRe = new RegExp(String.raw`^<\s*\/\s*${lowerTag}(?=\s|>)`, "i");
|
|
14150
|
+
let depth = 0;
|
|
14151
|
+
let index = Math.max(0, startIndex);
|
|
14152
|
+
while (index < rawHtml.length) {
|
|
14153
|
+
const lt = rawHtml.indexOf("<", index);
|
|
14154
|
+
if (lt === -1) return -1;
|
|
14155
|
+
const slice = rawHtml.slice(lt);
|
|
14156
|
+
if (closeTagRe.test(slice)) {
|
|
14157
|
+
const endRel = findTagCloseIndexOutsideQuotes$1(slice);
|
|
14158
|
+
if (endRel === -1) return -1;
|
|
14159
|
+
if (depth === 0) return lt + endRel + 1;
|
|
14160
|
+
depth--;
|
|
14161
|
+
index = lt + endRel + 1;
|
|
14162
|
+
continue;
|
|
14163
|
+
}
|
|
14164
|
+
if (openTagRe.test(slice)) {
|
|
14165
|
+
const endRel = findTagCloseIndexOutsideQuotes$1(slice);
|
|
14166
|
+
if (endRel === -1) return -1;
|
|
14167
|
+
const rawTag = slice.slice(0, endRel + 1);
|
|
14168
|
+
if (!/\/\s*>$/.test(rawTag)) depth++;
|
|
14169
|
+
index = lt + endRel + 1;
|
|
14170
|
+
continue;
|
|
14171
|
+
}
|
|
14172
|
+
index = lt + 1;
|
|
14173
|
+
}
|
|
14174
|
+
return -1;
|
|
14175
|
+
}
|
|
13681
14176
|
function parseHtmlBlock(token) {
|
|
13682
14177
|
const raw = String(token.content ?? "");
|
|
13683
14178
|
if (/^\s*<!--/.test(raw) || /^\s*<!/.test(raw) || /^\s*<\?/.test(raw)) return {
|
|
@@ -13695,14 +14190,11 @@ function parseHtmlBlock(token) {
|
|
|
13695
14190
|
tag: "",
|
|
13696
14191
|
loading: false
|
|
13697
14192
|
};
|
|
13698
|
-
const
|
|
14193
|
+
const openEnd = findTagCloseIndexOutsideQuotes$1(raw);
|
|
14194
|
+
const openTag = openEnd === -1 ? raw : raw.slice(0, openEnd + 1);
|
|
14195
|
+
const selfClosing = openEnd !== -1 && /\/\s*>$/.test(openTag);
|
|
13699
14196
|
const isVoid = VOID_TAGS.has(tag);
|
|
13700
|
-
|
|
13701
|
-
if (!closeRe) {
|
|
13702
|
-
closeRe = new RegExp(`<\\s*\\/\\s*${tag}\\s*>`, "i");
|
|
13703
|
-
CLOSE_TAG_RE_CACHE.set(tag, closeRe);
|
|
13704
|
-
}
|
|
13705
|
-
const hasClosing = closeRe.test(raw);
|
|
14197
|
+
const hasClosing = (openEnd === -1 ? -1 : findMatchingCloseTagEnd(raw, tag, openEnd + 1)) !== -1;
|
|
13706
14198
|
const loading = !(isVoid || selfClosing || hasClosing);
|
|
13707
14199
|
return {
|
|
13708
14200
|
type: "html_block",
|
|
@@ -13932,6 +14424,43 @@ function stripTrailingPartialClosingTag(inner, tag) {
|
|
|
13932
14424
|
const re = new RegExp(String.raw`[\t ]*<\s*\/\s*${tag}[^>]*$`, "i");
|
|
13933
14425
|
return inner.replace(re, "");
|
|
13934
14426
|
}
|
|
14427
|
+
function escapeRegex(value) {
|
|
14428
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
14429
|
+
}
|
|
14430
|
+
function findMatchingCloseTagRange(rawHtml, tag, startIndex) {
|
|
14431
|
+
if (!rawHtml || !tag) return null;
|
|
14432
|
+
const lowerTag = tag.toLowerCase();
|
|
14433
|
+
const openTagRe = new RegExp(String.raw`^<\s*${escapeRegex(lowerTag)}(?=\s|>|/)`, "i");
|
|
14434
|
+
const closeTagRe = new RegExp(String.raw`^<\s*\/\s*${escapeRegex(lowerTag)}(?=\s|>)`, "i");
|
|
14435
|
+
let depth = 0;
|
|
14436
|
+
let index = Math.max(0, startIndex);
|
|
14437
|
+
while (index < rawHtml.length) {
|
|
14438
|
+
const lt = rawHtml.indexOf("<", index);
|
|
14439
|
+
if (lt === -1) break;
|
|
14440
|
+
const slice = rawHtml.slice(lt);
|
|
14441
|
+
if (closeTagRe.test(slice)) {
|
|
14442
|
+
const endRel = findTagCloseIndexOutsideQuotes(slice);
|
|
14443
|
+
if (endRel === -1) return null;
|
|
14444
|
+
if (depth === 0) return {
|
|
14445
|
+
start: lt,
|
|
14446
|
+
end: lt + endRel + 1
|
|
14447
|
+
};
|
|
14448
|
+
depth--;
|
|
14449
|
+
index = lt + endRel + 1;
|
|
14450
|
+
continue;
|
|
14451
|
+
}
|
|
14452
|
+
if (openTagRe.test(slice)) {
|
|
14453
|
+
const endRel = findTagCloseIndexOutsideQuotes(slice);
|
|
14454
|
+
if (endRel === -1) return null;
|
|
14455
|
+
const raw = slice.slice(0, endRel + 1);
|
|
14456
|
+
if (!/\/\s*>$/.test(raw)) depth++;
|
|
14457
|
+
index = lt + endRel + 1;
|
|
14458
|
+
continue;
|
|
14459
|
+
}
|
|
14460
|
+
index = lt + 1;
|
|
14461
|
+
}
|
|
14462
|
+
return null;
|
|
14463
|
+
}
|
|
13935
14464
|
function findNextCustomHtmlBlockFromSource(source, tag, startIndex) {
|
|
13936
14465
|
if (!source || !tag) return null;
|
|
13937
14466
|
const lowerTag = tag.toLowerCase();
|
|
@@ -14037,16 +14566,17 @@ function parseBasicBlockToken(tokens, index, options) {
|
|
|
14037
14566
|
const mappedLineStart = Array.isArray(token.map) ? lineToIndex(source, Number(token.map?.[0] ?? 0)) : 0;
|
|
14038
14567
|
const fromSource = findNextCustomHtmlBlockFromSource(source, tag, Math.max(clampNonNegative(cursor), clampNonNegative(mappedLineStart)));
|
|
14039
14568
|
if (fromSource) options.__customHtmlBlockCursor = fromSource.end;
|
|
14040
|
-
const rawHtml = String(fromSource?.raw ?? htmlBlockNode.
|
|
14569
|
+
const rawHtml = String(fromSource?.raw ?? htmlBlockNode.raw ?? "");
|
|
14041
14570
|
const openEnd = findTagCloseIndexOutsideQuotes(rawHtml);
|
|
14042
|
-
const
|
|
14043
|
-
const
|
|
14571
|
+
const openTag = openEnd !== -1 ? rawHtml.slice(0, openEnd + 1) : rawHtml;
|
|
14572
|
+
const selfClosing = openEnd !== -1 && /\/\s*>\s*$/.test(openTag);
|
|
14573
|
+
const closeRange = openEnd === -1 ? null : findMatchingCloseTagRange(rawHtml, tag, openEnd + 1);
|
|
14574
|
+
const closeIndex = closeRange?.start ?? -1;
|
|
14044
14575
|
let inner = "";
|
|
14045
14576
|
if (openEnd !== -1) if (closeIndex !== -1 && openEnd < closeIndex) inner = rawHtml.slice(openEnd + 1, closeIndex);
|
|
14046
14577
|
else inner = rawHtml.slice(openEnd + 1);
|
|
14047
14578
|
if (closeIndex === -1) inner = stripTrailingPartialClosingTag(inner, tag);
|
|
14048
14579
|
const attrs = [];
|
|
14049
|
-
const openTag = openEnd !== -1 ? rawHtml.slice(0, openEnd + 1) : rawHtml;
|
|
14050
14580
|
const attrRegex = /\s([\w:-]+)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s"'>]+)))?/g;
|
|
14051
14581
|
let m;
|
|
14052
14582
|
while ((m = attrRegex.exec(openTag)) !== null) {
|
|
@@ -14055,12 +14585,13 @@ function parseBasicBlockToken(tokens, index, options) {
|
|
|
14055
14585
|
const value = m[2] || m[3] || m[4] || "";
|
|
14056
14586
|
attrs.push([name, value]);
|
|
14057
14587
|
}
|
|
14588
|
+
const loading = !options?.final && !selfClosing && closeRange == null;
|
|
14058
14589
|
return [{
|
|
14059
14590
|
type: tag,
|
|
14060
14591
|
tag,
|
|
14061
14592
|
content: stripWrapperNewlines(inner),
|
|
14062
14593
|
raw: String(fromSource?.raw ?? htmlBlockNode.raw ?? rawHtml),
|
|
14063
|
-
loading
|
|
14594
|
+
loading,
|
|
14064
14595
|
attrs: attrs.length ? attrs : void 0
|
|
14065
14596
|
}, index + 1];
|
|
14066
14597
|
}
|
|
@@ -14455,7 +14986,7 @@ function ensureBlankLineBeforeInlineMultilineCustomHtmlBlocks(markdown, tags) {
|
|
|
14455
14986
|
}
|
|
14456
14987
|
return false;
|
|
14457
14988
|
};
|
|
14458
|
-
const findTagCloseIndexOutsideQuotes$
|
|
14989
|
+
const findTagCloseIndexOutsideQuotes$3 = (input) => {
|
|
14459
14990
|
let inSingle = false;
|
|
14460
14991
|
let inDouble = false;
|
|
14461
14992
|
for (let i = 0; i < input.length; i++) {
|
|
@@ -14504,7 +15035,7 @@ function ensureBlankLineBeforeInlineMultilineCustomHtmlBlocks(markdown, tags) {
|
|
|
14504
15035
|
i++;
|
|
14505
15036
|
continue;
|
|
14506
15037
|
}
|
|
14507
|
-
const closeIdxRel = findTagCloseIndexOutsideQuotes$
|
|
15038
|
+
const closeIdxRel = findTagCloseIndexOutsideQuotes$3(line.slice(i));
|
|
14508
15039
|
if (closeIdxRel === -1) {
|
|
14509
15040
|
hasRenderablePrefix = true;
|
|
14510
15041
|
i++;
|
|
@@ -14608,6 +15139,27 @@ function normalizeCustomHtmlOpeningTagSameLine(markdown, tags) {
|
|
|
14608
15139
|
while (i < s.length && isIndentWs(s[i])) i++;
|
|
14609
15140
|
return s.slice(i);
|
|
14610
15141
|
};
|
|
15142
|
+
const findTagCloseIndexOutsideQuotes$3 = (input) => {
|
|
15143
|
+
let inSingle = false;
|
|
15144
|
+
let inDouble = false;
|
|
15145
|
+
for (let i = 0; i < input.length; i++) {
|
|
15146
|
+
const ch = input[i];
|
|
15147
|
+
if (ch === "\\") {
|
|
15148
|
+
i++;
|
|
15149
|
+
continue;
|
|
15150
|
+
}
|
|
15151
|
+
if (!inDouble && ch === "'") {
|
|
15152
|
+
inSingle = !inSingle;
|
|
15153
|
+
continue;
|
|
15154
|
+
}
|
|
15155
|
+
if (!inSingle && ch === "\"") {
|
|
15156
|
+
inDouble = !inDouble;
|
|
15157
|
+
continue;
|
|
15158
|
+
}
|
|
15159
|
+
if (!inSingle && !inDouble && ch === ">") return i;
|
|
15160
|
+
}
|
|
15161
|
+
return -1;
|
|
15162
|
+
};
|
|
14611
15163
|
const hasClosingTagOnLine = (line, from, tag) => {
|
|
14612
15164
|
const lowerTag = tag.toLowerCase();
|
|
14613
15165
|
let pos = line.indexOf("<", from);
|
|
@@ -14659,8 +15211,9 @@ function normalizeCustomHtmlOpeningTagSameLine(markdown, tags) {
|
|
|
14659
15211
|
if (i === nameStart) return line;
|
|
14660
15212
|
const tagName = line.slice(nameStart, i).toLowerCase();
|
|
14661
15213
|
if (!tagSet.has(tagName)) return line;
|
|
14662
|
-
const
|
|
14663
|
-
if (
|
|
15214
|
+
const gtRel = findTagCloseIndexOutsideQuotes$3(line.slice(i));
|
|
15215
|
+
if (gtRel === -1) return line;
|
|
15216
|
+
const gt = i + gtRel;
|
|
14664
15217
|
if (hasClosingTagOnLine(line, gt + 1, tagName)) return line;
|
|
14665
15218
|
const rest = trimStartIndentWs(line.slice(gt + 1));
|
|
14666
15219
|
if (!rest) return line;
|
|
@@ -15102,6 +15655,22 @@ function parseMarkdownToStructure(markdown, md, options = {}) {
|
|
|
15102
15655
|
else result = postResult;
|
|
15103
15656
|
}
|
|
15104
15657
|
}
|
|
15658
|
+
if (isFinal) {
|
|
15659
|
+
const seen = /* @__PURE__ */ new WeakSet();
|
|
15660
|
+
const finalizeHtmlBlockLoading = (value) => {
|
|
15661
|
+
if (!value || typeof value !== "object") return;
|
|
15662
|
+
if (seen.has(value)) return;
|
|
15663
|
+
seen.add(value);
|
|
15664
|
+
if (Array.isArray(value)) {
|
|
15665
|
+
for (const item of value) finalizeHtmlBlockLoading(item);
|
|
15666
|
+
return;
|
|
15667
|
+
}
|
|
15668
|
+
const node = value;
|
|
15669
|
+
if (node.type === "html_block" && node.loading === true) node.loading = false;
|
|
15670
|
+
for (const child of Object.values(node)) finalizeHtmlBlockLoading(child);
|
|
15671
|
+
};
|
|
15672
|
+
finalizeHtmlBlockLoading(result);
|
|
15673
|
+
}
|
|
15105
15674
|
if (options.debug) console.log("Parsed Markdown Tree Structure:", result);
|
|
15106
15675
|
return result;
|
|
15107
15676
|
}
|