mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-10 10:40:42 +00:00
Merged via squash.
Prepared head SHA: b7d336b296
Co-authored-by: omarshahine <10343873+omarshahine@users.noreply.github.com>
Co-authored-by: omarshahine <10343873+omarshahine@users.noreply.github.com>
Reviewed-by: @omarshahine
100 lines
3.8 KiB
TypeScript
100 lines
3.8 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { extractMarkdownFormatRuns } from "./markdown-format.js";
|
|
|
|
describe("extractMarkdownFormatRuns", () => {
|
|
it("returns the text unchanged when there is no markdown", () => {
|
|
const { text, ranges } = extractMarkdownFormatRuns("plain text reply");
|
|
expect(text).toBe("plain text reply");
|
|
expect(ranges).toEqual([]);
|
|
});
|
|
|
|
it("extracts a bold span", () => {
|
|
const { text, ranges } = extractMarkdownFormatRuns("**bold** text");
|
|
expect(text).toBe("bold text");
|
|
expect(ranges).toEqual([{ start: 0, length: 4, styles: ["bold"] }]);
|
|
});
|
|
|
|
it("extracts mixed bold and italic", () => {
|
|
const { text, ranges } = extractMarkdownFormatRuns("**hi** and *there*");
|
|
expect(text).toBe("hi and there");
|
|
expect(ranges).toEqual([
|
|
{ start: 0, length: 2, styles: ["bold"] },
|
|
{ start: 7, length: 5, styles: ["italic"] },
|
|
]);
|
|
});
|
|
|
|
it("extracts underline and strikethrough", () => {
|
|
const { text, ranges } = extractMarkdownFormatRuns("__under__ and ~~strike~~");
|
|
expect(text).toBe("under and strike");
|
|
expect(ranges).toEqual([
|
|
{ start: 0, length: 5, styles: ["underline"] },
|
|
{ start: 10, length: 6, styles: ["strikethrough"] },
|
|
]);
|
|
});
|
|
|
|
it("respects word boundaries on single-underscore italics", () => {
|
|
const { text, ranges } = extractMarkdownFormatRuns("snake_case_var ok");
|
|
expect(text).toBe("snake_case_var ok");
|
|
expect(ranges).toEqual([]);
|
|
});
|
|
|
|
it("treats single-underscore as italic when surrounded by whitespace", () => {
|
|
const { text, ranges } = extractMarkdownFormatRuns("a _word_ b");
|
|
expect(text).toBe("a word b");
|
|
expect(ranges).toEqual([{ start: 2, length: 4, styles: ["italic"] }]);
|
|
});
|
|
|
|
it("does not treat empty marker pairs as formatting", () => {
|
|
const { text, ranges } = extractMarkdownFormatRuns("** ** literal");
|
|
expect(text).toBe("** ** literal");
|
|
expect(ranges).toEqual([]);
|
|
});
|
|
|
|
it("leaves a lone asterisk alone", () => {
|
|
const { text, ranges } = extractMarkdownFormatRuns("price * quantity");
|
|
expect(text).toBe("price * quantity");
|
|
expect(ranges).toEqual([]);
|
|
});
|
|
|
|
it("computes ranges in output coordinates, not input", () => {
|
|
const { text, ranges } = extractMarkdownFormatRuns("a **b** c **d** e");
|
|
expect(text).toBe("a b c d e");
|
|
expect(ranges).toEqual([
|
|
{ start: 2, length: 1, styles: ["bold"] },
|
|
{ start: 6, length: 1, styles: ["bold"] },
|
|
]);
|
|
});
|
|
|
|
it("parses ***triple-marker*** as bold + italic over the same span", () => {
|
|
const { text, ranges } = extractMarkdownFormatRuns("***hi***");
|
|
expect(text).toBe("hi");
|
|
// Compound marker emits both styles over the same span.
|
|
expect(ranges).toEqual([
|
|
{ start: 0, length: 2, styles: ["bold"] },
|
|
{ start: 0, length: 2, styles: ["italic"] },
|
|
]);
|
|
});
|
|
|
|
it("parses **bold _and underline_ together** as nested ranges", () => {
|
|
const { text, ranges } = extractMarkdownFormatRuns("**bold _and underline_ together**");
|
|
expect(text).toBe("bold and underline together");
|
|
// Inner italic-via-_ at offset 5, length 13; outer bold over the full span.
|
|
expect(ranges).toEqual([
|
|
{ start: 5, length: 13, styles: ["italic"] },
|
|
{ start: 0, length: 27, styles: ["bold"] },
|
|
]);
|
|
});
|
|
|
|
it("respects word boundaries on double-underscore underline", () => {
|
|
const { text, ranges } = extractMarkdownFormatRuns("def __init__(self):");
|
|
expect(text).toBe("def __init__(self):");
|
|
expect(ranges).toEqual([]);
|
|
});
|
|
|
|
it("does not leak literal asterisks from triple markers when intent is unclear", () => {
|
|
// `***bold***` should never produce a bare `*` in the output text.
|
|
const { text } = extractMarkdownFormatRuns("hello ***world***");
|
|
expect(text).not.toMatch(/\*/);
|
|
});
|
|
});
|