mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-06 01:01:35 +00:00
fix: preserve markdown formatting around media attachments (#116786)
Co-authored-by: Peter Steinberger <steipete@macos.shared>
This commit is contained in:
committed by
GitHub
parent
82231b425b
commit
b4e10e8a90
@@ -205,6 +205,22 @@ describe("parseInlineDirectives", () => {
|
||||
expect(result.text).toBe(["~~~python", " x = 1", " y = 2", "~~~"].join("\n"));
|
||||
});
|
||||
|
||||
test.each([
|
||||
[
|
||||
"a false closing marker",
|
||||
["```python", "value = 'a b'", "``` not a close", "x = 'c d'", "```"],
|
||||
],
|
||||
["an unclosed fence", ["```python", "value = 'a b'", "x = 'c d'"]],
|
||||
["an indented closing fence", ["```python", "value = 'a b'", " ```"]],
|
||||
])("preserves canonical code fences with %s after removing directives", (_name, lines) => {
|
||||
const code = lines.join("\n");
|
||||
const result = parseInlineDirectives(`[[reply_to_current]]\n[[audio_as_voice]]\n${code}`);
|
||||
|
||||
expect(result.hasReplyTag).toBe(true);
|
||||
expect(result.audioAsVoice).toBe(true);
|
||||
expect(result.text).toBe(code);
|
||||
});
|
||||
|
||||
test("normalizes plain text without directives using code-fence awareness", () => {
|
||||
const input = "plain text with extra spaces\n\n```\n code preserved\n```";
|
||||
const result = parseInlineDirectives(input);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { expectDefined } from "@openclaw/normalization-core";
|
||||
// Directive tag helpers parse inline directive tags from user text.
|
||||
import { normalizeOptionalString } from "@openclaw/normalization-core/string-coerce";
|
||||
import { parseFenceSpans } from "../../packages/markdown-core/src/fences.js";
|
||||
|
||||
export type InlineDirectiveParseResult = {
|
||||
text: string;
|
||||
@@ -47,13 +48,19 @@ function normalizeDirectiveWhitespace(text: string): string {
|
||||
const blockSentinel = createBlockSentinel(text);
|
||||
const blockPlaceholderRe = new RegExp(`${blockSentinel}(\\d+)${blockSentinel}`, "g");
|
||||
const blocks: string[] = [];
|
||||
const masked = text.replace(
|
||||
/(`{3,}|~{3,})[^\n]*\n[\s\S]*?\n\1[^\n]*|(?:(?:^|\n)(?: |\t)[^\n]*)+/gm,
|
||||
(block) => {
|
||||
blocks.push(block);
|
||||
return `${blockSentinel}${blocks.length - 1}${blockSentinel}`;
|
||||
},
|
||||
);
|
||||
const fenceSpans = text.includes("```") || text.includes("~~~") ? parseFenceSpans(text) : [];
|
||||
let masked = "";
|
||||
let cursor = 0;
|
||||
// The canonical scanner keeps false closers, indented closers, and open fences intact.
|
||||
for (const span of fenceSpans) {
|
||||
blocks.push(text.slice(span.start, span.end));
|
||||
masked += `${text.slice(cursor, span.start)}${blockSentinel}${blocks.length - 1}${blockSentinel}`;
|
||||
cursor = span.end;
|
||||
}
|
||||
masked = `${masked}${text.slice(cursor)}`.replace(/(?:(?:^|\n)(?: |\t)[^\n]*)+/gm, (block) => {
|
||||
blocks.push(block);
|
||||
return `${blockSentinel}${blocks.length - 1}${blockSentinel}`;
|
||||
});
|
||||
|
||||
const normalized = masked
|
||||
.replace(/\r\n/g, "\n")
|
||||
|
||||
Reference in New Issue
Block a user