fix(utils): excluded ASCII replacements inside HTML comments
- Added an HTML comment state tracker to prompt formatting. - Updated ASCII symbol replacement to skip substitutions inside `<!-- ... -->` comment blocks across lines. - Added tests that preserved comment text while converting symbols outside comments.
This commit is contained in:
@@ -54,4 +54,28 @@ describe("prompt.format renderPhase", () => {
|
||||
'|`cat <<\'EOF\' > file`|`write(path="file", content="…")`|\n|`sed -i \'s/old/new/\' file`|`edit(path="file", edits=[…])`|',
|
||||
);
|
||||
});
|
||||
test("does not mutate HTML comment markers when replacing ascii symbols", () => {
|
||||
const input = "<!-- Hidden continuation steer. role=user, suppressed from visible transcript. -->";
|
||||
const output = prompt.format(input, {
|
||||
renderPhase: "pre-render",
|
||||
replaceAsciiSymbols: true,
|
||||
});
|
||||
expect(output).toBe(input);
|
||||
});
|
||||
test("replaces arrows outside but not inside HTML comments", () => {
|
||||
const input = "<!-- -> in comment -->\nvalue -> value";
|
||||
const output = prompt.format(input, {
|
||||
renderPhase: "pre-render",
|
||||
replaceAsciiSymbols: true,
|
||||
});
|
||||
expect(output).toBe("<!-- -> in comment -->\nvalue → value");
|
||||
});
|
||||
test("handles multi-line HTML comments", () => {
|
||||
const input = "<!--\nA -> B\n-->";
|
||||
const output = prompt.format(input, {
|
||||
renderPhase: "pre-render",
|
||||
replaceAsciiSymbols: true,
|
||||
});
|
||||
expect(output).toBe("<!--\nA -> B\n-->");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -66,6 +66,13 @@ function compactTableSep(line: string): string {
|
||||
return `|${normalized.join("|")}|`;
|
||||
}
|
||||
|
||||
const HTML_COMMENT_OPEN = "<!--";
|
||||
const HTML_COMMENT_CLOSE = "-->";
|
||||
|
||||
type HtmlCommentState = {
|
||||
inHtmlComment: boolean;
|
||||
};
|
||||
|
||||
function replaceCommonAsciiSymbols(line: string): string {
|
||||
return line
|
||||
.replace(/\.{3}/g, "…")
|
||||
@@ -77,6 +84,54 @@ function replaceCommonAsciiSymbols(line: string): string {
|
||||
.replace(/>=/g, "≥");
|
||||
}
|
||||
|
||||
function replaceCommonAsciiSymbolsOutsideHtmlComments(
|
||||
line: string,
|
||||
state: HtmlCommentState,
|
||||
): string {
|
||||
if (
|
||||
!state.inHtmlComment &&
|
||||
!line.includes(HTML_COMMENT_OPEN) &&
|
||||
!line.includes(HTML_COMMENT_CLOSE)
|
||||
) {
|
||||
return replaceCommonAsciiSymbols(line);
|
||||
}
|
||||
|
||||
let result = "";
|
||||
let cursor = 0;
|
||||
|
||||
while (cursor < line.length) {
|
||||
if (state.inHtmlComment) {
|
||||
const closeIndex = line.indexOf(HTML_COMMENT_CLOSE, cursor);
|
||||
if (closeIndex === -1) {
|
||||
return result + line.slice(cursor);
|
||||
}
|
||||
result += line.slice(cursor, closeIndex + HTML_COMMENT_CLOSE.length);
|
||||
cursor = closeIndex + HTML_COMMENT_CLOSE.length;
|
||||
state.inHtmlComment = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
const openIndex = line.indexOf(HTML_COMMENT_OPEN, cursor);
|
||||
if (openIndex === -1) {
|
||||
result += replaceCommonAsciiSymbols(line.slice(cursor));
|
||||
return result;
|
||||
}
|
||||
|
||||
result += replaceCommonAsciiSymbols(line.slice(cursor, openIndex));
|
||||
const closeIndex = line.indexOf(HTML_COMMENT_CLOSE, openIndex + HTML_COMMENT_OPEN.length);
|
||||
if (closeIndex === -1) {
|
||||
result += line.slice(openIndex);
|
||||
state.inHtmlComment = true;
|
||||
return result;
|
||||
}
|
||||
|
||||
result += line.slice(openIndex, closeIndex + HTML_COMMENT_CLOSE.length);
|
||||
cursor = closeIndex + HTML_COMMENT_CLOSE.length;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
export function format(content: string, options: PromptFormatOptions = {}): string {
|
||||
const {
|
||||
renderPhase = "post-render",
|
||||
@@ -87,6 +142,8 @@ export function format(content: string, options: PromptFormatOptions = {}): stri
|
||||
const lines = content.split("\n");
|
||||
const result: string[] = [];
|
||||
let inCodeBlock = false;
|
||||
|
||||
const htmlCommentState: HtmlCommentState = { inHtmlComment: false };
|
||||
const topLevelTags: string[] = [];
|
||||
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
@@ -104,7 +161,7 @@ export function format(content: string, options: PromptFormatOptions = {}): stri
|
||||
}
|
||||
|
||||
if (replaceAsciiSymbols) {
|
||||
line = replaceCommonAsciiSymbols(line);
|
||||
line = replaceCommonAsciiSymbolsOutsideHtmlComments(line, htmlCommentState);
|
||||
}
|
||||
trimmedStart = line.trimStart();
|
||||
const trimmed = line.trim();
|
||||
|
||||
Reference in New Issue
Block a user