diff --git a/extensions/zalouser/src/text-styles.test.ts b/extensions/zalouser/src/text-styles.test.ts index 28fb23be058..c8f5f50bd3d 100644 --- a/extensions/zalouser/src/text-styles.test.ts +++ b/extensions/zalouser/src/text-styles.test.ts @@ -90,6 +90,27 @@ describe("parseZalouserTextStyles", () => { }); }); + it("treats indented blockquotes as quoted lines", () => { + expect(parseZalouserTextStyles(" > quoted")).toEqual({ + text: "quoted", + styles: [{ start: 0, len: 6, st: TextStyle.Indent, indentSize: 1 }], + }); + }); + + it("treats indented quoted fences as literal code blocks", () => { + expect(parseZalouserTextStyles(" > ```\n > *cmd*\n > ```")).toEqual({ + text: "*cmd*", + styles: [], + }); + }); + + it("preserves inner quote markers inside quoted fenced code blocks", () => { + expect(parseZalouserTextStyles("> ```\n>> prompt\n> ```")).toEqual({ + text: "> prompt", + styles: [], + }); + }); + it("keeps unmatched fences literal", () => { expect(parseZalouserTextStyles("```python")).toEqual({ text: "```python", diff --git a/extensions/zalouser/src/text-styles.ts b/extensions/zalouser/src/text-styles.ts index 3d6fbda8807..91d93b2e6f8 100644 --- a/extensions/zalouser/src/text-styles.ts +++ b/extensions/zalouser/src/text-styles.ts @@ -113,7 +113,10 @@ export function parseZalouserTextStyles(input: string): { text: string; styles: const { text: unquotedLine, indent: baseIndent } = stripQuotePrefix(rawLine); if (activeFence) { - const codeLine = activeFence.quoteIndent > 0 ? unquotedLine : rawLine; + const codeLine = + activeFence.quoteIndent > 0 + ? stripQuotePrefix(rawLine, activeFence.quoteIndent).text + : rawLine; if (isClosingFence(codeLine, activeFence)) { activeFence = null; continue; @@ -293,7 +296,8 @@ function clampIndent(spaceCount: number): number { function hasClosingFence(lines: string[], startIndex: number, fence: ActiveFence): boolean { for (let index = startIndex; index < lines.length; index += 1) { - const candidate = fence.quoteIndent > 0 ? stripQuotePrefix(lines[index]).text : lines[index]; + const candidate = + fence.quoteIndent > 0 ? stripQuotePrefix(lines[index], fence.quoteIndent).text : lines[index]; if (isClosingFence(candidate, fence)) { return true; } @@ -323,14 +327,23 @@ function resolveOpeningFence(line: string): ActiveFence | null { }; } -function stripQuotePrefix(line: string): { text: string; indent: number } { - const match = line.match(/^(>+)\s?(.*)$/); +function stripQuotePrefix( + line: string, + maxDepth = Number.POSITIVE_INFINITY, +): { text: string; indent: number } { + const match = line.match(/^([ ]{0,3})(>+)( ?)(.*)$/); if (!match) { 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: match[2], - indent: Math.min(5, match[1].length), + text: remainingText, + indent: Math.min(5, removedDepth), }; }