mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-12 07:20:45 +00:00
fix(zalouser): preserve quoted markdown blocks
This commit is contained in:
@@ -97,6 +97,13 @@ describe("parseZalouserTextStyles", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("treats spaced nested blockquotes as deeper quoted lines", () => {
|
||||
expect(parseZalouserTextStyles("> > quoted")).toEqual({
|
||||
text: "quoted",
|
||||
styles: [{ start: 0, len: 6, st: TextStyle.Indent, indentSize: 2 }],
|
||||
});
|
||||
});
|
||||
|
||||
it("treats indented quoted fences as literal code blocks", () => {
|
||||
expect(parseZalouserTextStyles(" > ```\n > *cmd*\n > ```")).toEqual({
|
||||
text: "*cmd*",
|
||||
@@ -104,6 +111,13 @@ describe("parseZalouserTextStyles", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("treats spaced nested quoted fences as literal code blocks", () => {
|
||||
expect(parseZalouserTextStyles("> > ```\n> > code\n> > ```")).toEqual({
|
||||
text: "code",
|
||||
styles: [],
|
||||
});
|
||||
});
|
||||
|
||||
it("preserves inner quote markers inside quoted fenced code blocks", () => {
|
||||
expect(parseZalouserTextStyles("> ```\n>> prompt\n> ```")).toEqual({
|
||||
text: "> prompt",
|
||||
@@ -111,6 +125,17 @@ describe("parseZalouserTextStyles", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("keeps quote indentation on heading lines", () => {
|
||||
expect(parseZalouserTextStyles("> # Title")).toEqual({
|
||||
text: "Title",
|
||||
styles: [
|
||||
{ start: 0, len: 5, st: TextStyle.Bold },
|
||||
{ start: 0, len: 5, st: TextStyle.Big },
|
||||
{ start: 0, len: 5, st: TextStyle.Indent, indentSize: 1 },
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it("keeps unmatched fences literal", () => {
|
||||
expect(parseZalouserTextStyles("```python")).toEqual({
|
||||
text: "```python",
|
||||
@@ -150,4 +175,11 @@ describe("parseZalouserTextStyles", () => {
|
||||
styles: [],
|
||||
});
|
||||
});
|
||||
|
||||
it("keeps indented code blocks literal", () => {
|
||||
expect(parseZalouserTextStyles(" *cmd*")).toEqual({
|
||||
text: "\u00A0\u00A0\u00A0\u00A0*cmd*",
|
||||
styles: [],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -143,14 +143,33 @@ export function parseZalouserTextStyles(input: string): { text: string; styles:
|
||||
continue;
|
||||
}
|
||||
|
||||
const outputLineIndex = processedLines.length;
|
||||
if (isIndentedCodeBlockLine(line)) {
|
||||
if (baseIndent > 0) {
|
||||
lineStyles.push({
|
||||
lineIndex: outputLineIndex,
|
||||
style: TextStyle.Indent,
|
||||
indentSize: baseIndent,
|
||||
});
|
||||
}
|
||||
processedLines.push(escapeLiteralText(normalizeCodeBlockLeadingWhitespace(line), escapeMap));
|
||||
continue;
|
||||
}
|
||||
|
||||
const headingMatch = line.match(/^(#{1,4})\s(.*)$/);
|
||||
if (headingMatch) {
|
||||
const outputLineIndex = processedLines.length;
|
||||
const depth = headingMatch[1].length;
|
||||
lineStyles.push({ lineIndex: outputLineIndex, style: TextStyle.Bold });
|
||||
if (depth === 1) {
|
||||
lineStyles.push({ lineIndex: outputLineIndex, style: TextStyle.Big });
|
||||
}
|
||||
if (baseIndent > 0) {
|
||||
lineStyles.push({
|
||||
lineIndex: outputLineIndex,
|
||||
style: TextStyle.Indent,
|
||||
indentSize: baseIndent,
|
||||
});
|
||||
}
|
||||
processedLines.push(headingMatch[2]);
|
||||
continue;
|
||||
}
|
||||
@@ -163,7 +182,6 @@ export function parseZalouserTextStyles(input: string): { text: string; styles:
|
||||
content = indentMatch[2];
|
||||
}
|
||||
const totalIndent = Math.min(5, baseIndent + indentLevel);
|
||||
const outputLineIndex = processedLines.length;
|
||||
|
||||
if (/^[-*+]\s\[[ xX]\]\s/.test(content)) {
|
||||
if (totalIndent > 0) {
|
||||
@@ -331,18 +349,27 @@ function stripQuotePrefix(
|
||||
line: string,
|
||||
maxDepth = Number.POSITIVE_INFINITY,
|
||||
): { text: string; indent: number } {
|
||||
const match = line.match(/^([ ]{0,3})(>+)( ?)(.*)$/);
|
||||
if (!match) {
|
||||
let cursor = 0;
|
||||
while (cursor < line.length && cursor < 3 && line[cursor] === " ") {
|
||||
cursor += 1;
|
||||
}
|
||||
|
||||
let removedDepth = 0;
|
||||
let consumedCursor = cursor;
|
||||
while (removedDepth < maxDepth && consumedCursor < line.length && line[consumedCursor] === ">") {
|
||||
removedDepth += 1;
|
||||
consumedCursor += 1;
|
||||
if (line[consumedCursor] === " ") {
|
||||
consumedCursor += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (removedDepth === 0) {
|
||||
return { text: line, indent: 0 };
|
||||
}
|
||||
|
||||
const removedDepth = Math.min(match[2].length, maxDepth);
|
||||
const remainingMarkers = match[2].slice(removedDepth);
|
||||
const remainingText =
|
||||
remainingMarkers.length > 0 ? `${remainingMarkers}${match[3]}${match[4]}` : match[4];
|
||||
|
||||
return {
|
||||
text: remainingText,
|
||||
text: line.slice(consumedCursor),
|
||||
indent: Math.min(5, removedDepth),
|
||||
};
|
||||
}
|
||||
@@ -468,6 +495,10 @@ function normalizeCodeBlockLeadingWhitespace(line: string): string {
|
||||
);
|
||||
}
|
||||
|
||||
function isIndentedCodeBlockLine(line: string): boolean {
|
||||
return /^(?: {4,}|\t)/.test(line);
|
||||
}
|
||||
|
||||
function stripCodeFenceIndent(line: string, indent: number): string {
|
||||
let consumed = 0;
|
||||
let cursor = 0;
|
||||
|
||||
Reference in New Issue
Block a user