fix(ui): preserve user ordered-list markers (closes #5013)
This commit is contained in:
@@ -2,6 +2,10 @@
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Added
|
||||
|
||||
- Added an opt-in Markdown renderer option to preserve source ordered-list markers for transcript rendering ([#5013](https://github.com/earendil-works/pi/issues/5013)).
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed `Shift+Enter` in Apple Terminal by detecting local macOS modifier state when Terminal.app sends plain Return.
|
||||
|
||||
@@ -70,6 +70,11 @@ export interface MarkdownTheme {
|
||||
codeBlockIndent?: string;
|
||||
}
|
||||
|
||||
export interface MarkdownOptions {
|
||||
/** Preserve source ordered-list markers instead of normalizing them from the list start. */
|
||||
preserveOrderedListMarkers?: boolean;
|
||||
}
|
||||
|
||||
interface InlineStyleContext {
|
||||
applyText: (text: string) => string;
|
||||
stylePrefix: string;
|
||||
@@ -81,6 +86,7 @@ export class Markdown implements Component {
|
||||
private paddingY: number; // Top/bottom padding
|
||||
private defaultTextStyle?: DefaultTextStyle;
|
||||
private theme: MarkdownTheme;
|
||||
private options: MarkdownOptions;
|
||||
private defaultStylePrefix?: string;
|
||||
|
||||
// Cache for rendered output
|
||||
@@ -94,12 +100,14 @@ export class Markdown implements Component {
|
||||
paddingY: number,
|
||||
theme: MarkdownTheme,
|
||||
defaultTextStyle?: DefaultTextStyle,
|
||||
options?: MarkdownOptions,
|
||||
) {
|
||||
this.text = text;
|
||||
this.paddingX = paddingX;
|
||||
this.paddingY = paddingY;
|
||||
this.theme = theme;
|
||||
this.defaultTextStyle = defaultTextStyle;
|
||||
this.options = options ? { ...options } : {};
|
||||
}
|
||||
|
||||
setText(text: string): void {
|
||||
@@ -548,6 +556,11 @@ export class Markdown implements Component {
|
||||
return result;
|
||||
}
|
||||
|
||||
private getOrderedListMarker(item: Tokens.ListItem): string | undefined {
|
||||
const match = /^(?: {0,3})(\d{1,9}[.)])[ \t]+/.exec(item.raw);
|
||||
return match ? `${match[1]} ` : undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render a list with proper nesting support
|
||||
*/
|
||||
@@ -559,7 +572,11 @@ export class Markdown implements Component {
|
||||
|
||||
for (let i = 0; i < token.items.length; i++) {
|
||||
const item = token.items[i];
|
||||
const bullet = token.ordered ? `${startNumber + i}. ` : "- ";
|
||||
const bullet = token.ordered
|
||||
? this.options.preserveOrderedListMarkers
|
||||
? (this.getOrderedListMarker(item) ?? `${startNumber + i}. `)
|
||||
: `${startNumber + i}. `
|
||||
: "- ";
|
||||
const taskMarker = item.task ? `[${item.checked ? "x" : " "}] ` : "";
|
||||
const marker = bullet + taskMarker;
|
||||
const firstPrefix = indent + this.theme.listBullet(marker);
|
||||
|
||||
@@ -15,7 +15,7 @@ export { Editor, type EditorOptions, type EditorTheme } from "./components/edito
|
||||
export { Image, type ImageOptions, type ImageTheme } from "./components/image.ts";
|
||||
export { Input } from "./components/input.ts";
|
||||
export { Loader, type LoaderIndicatorOptions } from "./components/loader.ts";
|
||||
export { type DefaultTextStyle, Markdown, type MarkdownTheme } from "./components/markdown.ts";
|
||||
export { type DefaultTextStyle, Markdown, type MarkdownOptions, type MarkdownTheme } from "./components/markdown.ts";
|
||||
export {
|
||||
type SelectItem,
|
||||
SelectList,
|
||||
|
||||
@@ -104,6 +104,31 @@ describe("Markdown component", () => {
|
||||
assert.ok(plainLines.some((line) => line.includes("2. Second")));
|
||||
});
|
||||
|
||||
it("should normalize ordered list markers by default", () => {
|
||||
const markdown = new Markdown("1. alpha\n1. beta\n1. gamma", 0, 0, defaultMarkdownTheme);
|
||||
|
||||
const lines = markdown.render(80).map((line) => stripAnsi(line).trimEnd());
|
||||
|
||||
assert.deepStrictEqual(lines, ["1. alpha", "2. beta", "3. gamma"]);
|
||||
});
|
||||
|
||||
it("should preserve source ordered list markers when configured", () => {
|
||||
const markdown = new Markdown(
|
||||
" 4. forth\n 3. third\n\n10) ten\n7) seven",
|
||||
0,
|
||||
0,
|
||||
defaultMarkdownTheme,
|
||||
undefined,
|
||||
{
|
||||
preserveOrderedListMarkers: true,
|
||||
},
|
||||
);
|
||||
|
||||
const lines = markdown.render(80).map((line) => stripAnsi(line).trimEnd());
|
||||
|
||||
assert.deepStrictEqual(lines, ["4. forth", "3. third", "", "10) ten", "7) seven"]);
|
||||
});
|
||||
|
||||
it("should render mixed ordered and unordered nested lists", () => {
|
||||
const markdown = new Markdown(
|
||||
`1. Ordered item
|
||||
|
||||
Reference in New Issue
Block a user