Skip to content

Commit 2d56b2d

Browse files
committed
fix:1.3.6 (c)
抑制了用户escape后报tag未闭合的错的问题
1 parent 62c21d5 commit 2d56b2d

2 files changed

Lines changed: 53 additions & 14 deletions

File tree

src/structural.ts

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1136,37 +1136,49 @@ const parseNodesWithFactory = <TNode extends StructuralNode | IndexedStructuralN
11361136
child.contentEndI = closeStart;
11371137
return true;
11381138
};
1139+
1140+
const hasEscapedFullCloseAtEof = (frame: ParseFrame): boolean => {
1141+
if (frame.inlineCloseToken !== endTag) return false;
1142+
const escapedEndTag = escapeChar + endTag;
1143+
const escapedStart = frame.textEnd - escapedEndTag.length;
1144+
return escapedStart >= frame.argStartI && frame.text.startsWith(escapedEndTag, escapedStart);
1145+
};
1146+
11391147
const tryFinalizeFrameAtEof = (frame: ParseFrame): boolean => {
11401148
if (frame.i < frame.textEnd) return false;
11411149

11421150
if (frame.inlineCloseToken !== null) {
1151+
const escapedFullCloseAtEof = hasEscapedFullCloseAtEof(frame);
11431152
// inline 帧走到文本末尾仍未关闭 → 未闭合错误
11441153
// 这里不要整段吞掉:只把 tag 头回退成普通文本,并把父帧 i 放回 argStart。
11451154
// 后续正文会继续在父帧里按正常字符流扫描,这是老版本错误恢复语义。
1146-
emitError(
1147-
tracker,
1148-
onError,
1149-
frame.implicitInlineShorthand ? "SHORTHAND_NOT_CLOSED" : "INLINE_NOT_CLOSED",
1150-
frame.text,
1151-
frame.tagStartI,
1152-
frame.argStartI - frame.tagOpenPos,
1153-
emittedErrorKeys,
1154-
);
1155+
if (!escapedFullCloseAtEof) {
1156+
emitError(
1157+
tracker,
1158+
onError,
1159+
frame.implicitInlineShorthand ? "SHORTHAND_NOT_CLOSED" : "INLINE_NOT_CLOSED",
1160+
frame.text,
1161+
frame.tagStartI,
1162+
frame.argStartI - frame.tagOpenPos,
1163+
emittedErrorKeys,
1164+
);
1165+
}
11551166
stack.pop();
11561167
const parent = stack[frame.parentIndex];
1168+
const fallbackScanStart = escapedFullCloseAtEof ? frame.textEnd : frame.argStartI;
11571169
const eofOwnership = resolveShorthandOwnership({
11581170
phase: "eof",
11591171
frame,
11601172
parent: parent ?? null,
11611173
});
11621174
if (eofOwnership === "defer-parent") {
1163-
appendBuf(parent, frame.tagStartI, frame.argStartI);
1164-
parent.i = frame.argStartI;
1175+
appendBuf(parent, frame.tagStartI, fallbackScanStart);
1176+
parent.i = fallbackScanStart;
11651177
return true;
11661178
}
11671179

1168-
appendBuf(parent, frame.tagStartI, frame.argStartI);
1169-
parent.i = frame.argStartI;
1180+
appendBuf(parent, frame.tagStartI, fallbackScanStart);
1181+
parent.i = fallbackScanStart;
11701182
return true;
11711183
}
11721184

tests/orderTiming.test.ts

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import assert from "node:assert/strict";
22
import type { GoldenCase } from "./testHarness.ts";
33
import { runGoldenCases } from "./testHarness.ts";
4-
import { createSimpleInlineHandlers, parseRichText, materializeTextTokens } from "../src/index.ts";
4+
import { createSimpleInlineHandlers, createSyntax, parseRichText, materializeTextTokens } from "../src/index.ts";
55

66
const cases: GoldenCase[] = [
77
{
@@ -72,6 +72,33 @@ const cases: GoldenCase[] = [
7272
assert.deepEqual(codes, ["INLINE_NOT_CLOSED"]);
7373
},
7474
},
75+
{
76+
name: "[Order/onError] 参数尾部为被转义完整闭合符时 -> 不应报未闭合或意外闭合",
77+
run() {
78+
const syntax = createSyntax({
79+
tagPrefix: "=",
80+
tagOpen: "<",
81+
tagClose: ">",
82+
tagDivider: "|",
83+
endTag: ">=",
84+
rawOpen: ">%",
85+
blockOpen: ">*",
86+
rawClose: "%",
87+
blockClose: "*",
88+
escapeChar: "~",
89+
});
90+
const input = "=bold<~>=";
91+
const codes: string[] = [];
92+
const result = parseRichText(input, {
93+
syntax,
94+
handlers: createSimpleInlineHandlers(["bold"]),
95+
onError: (error) => codes.push(error.code),
96+
});
97+
98+
assert.deepEqual(codes, []);
99+
assert.equal(materializeTextTokens(result).map((token) => token.value ?? "").join(""), input);
100+
},
101+
},
75102
{
76103
name: "[Order/onError] parseRichText raw 未闭合 -> 应保持 1.1.3 的错误基线",
77104
run() {

0 commit comments

Comments
 (0)