mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-19 06:37:28 +00:00
Merged via /review-pr -> /prepare-pr -> /merge-pr.
Prepared head SHA: 4a967c51f5
Co-authored-by: lailoo <20536249+lailoo@users.noreply.github.com>
Co-authored-by: sebslight <19554889+sebslight@users.noreply.github.com>
Reviewed-by: @sebslight
This commit is contained in:
@@ -6,6 +6,7 @@ Docs: https://docs.openclaw.ai
|
|||||||
|
|
||||||
### Changes
|
### Changes
|
||||||
|
|
||||||
|
- Telegram: render blockquotes as native `<blockquote>` tags instead of stripping them. (#14608)
|
||||||
- Version alignment: bump manifests and package versions to `2026.2.10`; keep `appcast.xml` unchanged until the next macOS release cut.
|
- Version alignment: bump manifests and package versions to `2026.2.10`; keep `appcast.xml` unchanged until the next macOS release cut.
|
||||||
- CLI: add `openclaw logs --local-time` to display log timestamps in local timezone. (#13818) Thanks @xialonglee.
|
- CLI: add `openclaw logs --local-time` to display log timestamps in local timezone. (#13818) Thanks @xialonglee.
|
||||||
- Config: avoid redacting `maxTokens`-like fields during config snapshot redaction, preventing round-trip validation failures in `/config`. (#14006) Thanks @constansino.
|
- Config: avoid redacting `maxTokens`-like fields during config snapshot redaction, preventing round-trip validation failures in `/config`. (#14006) Thanks @constansino.
|
||||||
|
|||||||
@@ -24,7 +24,14 @@ type MarkdownToken = {
|
|||||||
attrGet?: (name: string) => string | null;
|
attrGet?: (name: string) => string | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type MarkdownStyle = "bold" | "italic" | "strikethrough" | "code" | "code_block" | "spoiler";
|
export type MarkdownStyle =
|
||||||
|
| "bold"
|
||||||
|
| "italic"
|
||||||
|
| "strikethrough"
|
||||||
|
| "code"
|
||||||
|
| "code_block"
|
||||||
|
| "spoiler"
|
||||||
|
| "blockquote";
|
||||||
|
|
||||||
export type MarkdownStyleSpan = {
|
export type MarkdownStyleSpan = {
|
||||||
start: number;
|
start: number;
|
||||||
@@ -578,8 +585,10 @@ function renderTokens(tokens: MarkdownToken[], state: RenderState): void {
|
|||||||
if (state.blockquotePrefix) {
|
if (state.blockquotePrefix) {
|
||||||
state.text += state.blockquotePrefix;
|
state.text += state.blockquotePrefix;
|
||||||
}
|
}
|
||||||
|
openStyle(state, "blockquote");
|
||||||
break;
|
break;
|
||||||
case "blockquote_close":
|
case "blockquote_close":
|
||||||
|
closeStyle(state, "blockquote");
|
||||||
state.text += "\n";
|
state.text += "\n";
|
||||||
break;
|
break;
|
||||||
case "bullet_list_open":
|
case "bullet_list_open":
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ export type RenderOptions = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const STYLE_ORDER: MarkdownStyle[] = [
|
const STYLE_ORDER: MarkdownStyle[] = [
|
||||||
|
"blockquote",
|
||||||
"code_block",
|
"code_block",
|
||||||
"code",
|
"code",
|
||||||
"bold",
|
"bold",
|
||||||
|
|||||||
@@ -37,9 +37,35 @@ describe("markdownToTelegramHtml", () => {
|
|||||||
expect(res).toBe("2. two\n3. three");
|
expect(res).toBe("2. two\n3. three");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("flattens headings and blockquotes", () => {
|
it("flattens headings", () => {
|
||||||
const res = markdownToTelegramHtml("# Title\n\n> Quote");
|
const res = markdownToTelegramHtml("# Title");
|
||||||
expect(res).toBe("Title\n\nQuote");
|
expect(res).toBe("Title");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("renders blockquotes as native Telegram blockquote tags", () => {
|
||||||
|
const res = markdownToTelegramHtml("> Quote");
|
||||||
|
expect(res).toContain("<blockquote>");
|
||||||
|
expect(res).toContain("Quote");
|
||||||
|
expect(res).toContain("</blockquote>");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("renders blockquotes with inline formatting", () => {
|
||||||
|
const res = markdownToTelegramHtml("> **bold** quote");
|
||||||
|
expect(res).toContain("<blockquote>");
|
||||||
|
expect(res).toContain("<b>bold</b>");
|
||||||
|
expect(res).toContain("</blockquote>");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("renders multiline blockquotes as a single Telegram blockquote", () => {
|
||||||
|
const res = markdownToTelegramHtml("> first\n> second");
|
||||||
|
expect(res).toBe("<blockquote>first\nsecond</blockquote>");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("renders separated quoted paragraphs as distinct blockquotes", () => {
|
||||||
|
const res = markdownToTelegramHtml("> first\n\n> second");
|
||||||
|
expect(res).toContain("<blockquote>first");
|
||||||
|
expect(res).toContain("<blockquote>second</blockquote>");
|
||||||
|
expect(res.match(/<blockquote>/g)).toHaveLength(2);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("renders fenced code blocks", () => {
|
it("renders fenced code blocks", () => {
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ function renderTelegramHtml(ir: MarkdownIR): string {
|
|||||||
code: { open: "<code>", close: "</code>" },
|
code: { open: "<code>", close: "</code>" },
|
||||||
code_block: { open: "<pre><code>", close: "</code></pre>" },
|
code_block: { open: "<pre><code>", close: "</code></pre>" },
|
||||||
spoiler: { open: "<tg-spoiler>", close: "</tg-spoiler>" },
|
spoiler: { open: "<tg-spoiler>", close: "</tg-spoiler>" },
|
||||||
|
blockquote: { open: "<blockquote>", close: "</blockquote>" },
|
||||||
},
|
},
|
||||||
escapeText: escapeHtml,
|
escapeText: escapeHtml,
|
||||||
buildLink: buildTelegramLink,
|
buildLink: buildTelegramLink,
|
||||||
|
|||||||
Reference in New Issue
Block a user