fix: improve markdown rendering with proper wide character support
This commit is contained in:
parent
91175c70b6
commit
af52e89928
2 changed files with 29 additions and 12 deletions
|
|
@ -48,10 +48,12 @@ export default class Renderer {
|
||||||
|
|
||||||
private checkContainment(text: string, pipe: WriteStream = process.stdout) {
|
private checkContainment(text: string, pipe: WriteStream = process.stdout) {
|
||||||
const [columns, rows] = pipe.getWindowSize();
|
const [columns, rows] = pipe.getWindowSize();
|
||||||
this.charsSinceNL += text.length;
|
this.charsSinceNL += Bun.stringWidth(text);
|
||||||
if (text.includes("\n")) {
|
if (text.includes("\n")) {
|
||||||
this.lineCount += text.match(/\n/g)?.length ?? 1;
|
this.lineCount += text.match(/\n/g)?.length ?? 1;
|
||||||
this.charsSinceNL = text.length - text.lastIndexOf("\n") - 1;
|
this.charsSinceNL =
|
||||||
|
Bun.stringWidth(text) -
|
||||||
|
Bun.stringWidth(text.slice(0, text.lastIndexOf("\n")));
|
||||||
} else if (this.charsSinceNL > columns) {
|
} else if (this.charsSinceNL > columns) {
|
||||||
this.lineCount++;
|
this.lineCount++;
|
||||||
this.charsSinceNL = this.charsSinceNL - columns;
|
this.charsSinceNL = this.charsSinceNL - columns;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { Table } from "@cliffy/table";
|
import { Cell, Table } from "@cliffy/table";
|
||||||
import chalk from "chalk";
|
import chalk from "chalk";
|
||||||
import {
|
import {
|
||||||
type BundledLanguage,
|
type BundledLanguage,
|
||||||
|
|
@ -12,6 +12,12 @@ import { codeToANSI } from "./codeToANSI";
|
||||||
let highlighter: HighlighterGeneric<BundledLanguage, BundledTheme> | undefined;
|
let highlighter: HighlighterGeneric<BundledLanguage, BundledTheme> | undefined;
|
||||||
let highligherLangs = "";
|
let highligherLangs = "";
|
||||||
|
|
||||||
|
class SWCell extends Cell {
|
||||||
|
public override get length() {
|
||||||
|
return Bun.stringWidth(this.toString(), { ambiguousIsNarrow: true });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export async function renderMarkdown(
|
export async function renderMarkdown(
|
||||||
text: PromiseLike<string> | string,
|
text: PromiseLike<string> | string,
|
||||||
columns: number,
|
columns: number,
|
||||||
|
|
@ -32,8 +38,8 @@ export async function renderMarkdown(
|
||||||
} catch {}
|
} catch {}
|
||||||
}
|
}
|
||||||
|
|
||||||
let header: string[] = [];
|
let header: SWCell[] = [];
|
||||||
let body: string[][] = [];
|
let body: SWCell[][] = [];
|
||||||
|
|
||||||
const rendered = Bun.markdown.render(md, {
|
const rendered = Bun.markdown.render(md, {
|
||||||
heading: (children, { level }) => {
|
heading: (children, { level }) => {
|
||||||
|
|
@ -58,7 +64,8 @@ export async function renderMarkdown(
|
||||||
const lines = Bun.wrapAnsi(`\n${children.trim()}`, columns - 2, {
|
const lines = Bun.wrapAnsi(`\n${children.trim()}`, columns - 2, {
|
||||||
trim: false,
|
trim: false,
|
||||||
})
|
})
|
||||||
.replace(/\n([a-zA-Z-_]+)\n/g, "\n$1")
|
.replace(/\n(\s?[a-zA-Z_-]+\s?)\n/g, "\n$1")
|
||||||
|
.replace(/\n+/g, "\n")
|
||||||
.concat("\n")
|
.concat("\n")
|
||||||
.split("\n");
|
.split("\n");
|
||||||
const toRender = lines
|
const toRender = lines
|
||||||
|
|
@ -86,7 +93,7 @@ export async function renderMarkdown(
|
||||||
list: (children, { depth }) => {
|
list: (children, { depth }) => {
|
||||||
const trimmed = children
|
const trimmed = children
|
||||||
.replace(/\n+/g, "\n")
|
.replace(/\n+/g, "\n")
|
||||||
.replace(/\n([a-zA-Z-_]+)\n/g, "\n$1");
|
.replace(/\n(\s?[a-zA-Z_-]+\s?)\n/g, "\n$1");
|
||||||
return depth === 0 ? `${trimmed}\n` : `\n${trimmed}`;
|
return depth === 0 ? `${trimmed}\n` : `\n${trimmed}`;
|
||||||
},
|
},
|
||||||
listItem: (children, { index, depth, ordered, start, checked }) => {
|
listItem: (children, { index, depth, ordered, start, checked }) => {
|
||||||
|
|
@ -113,20 +120,28 @@ export async function renderMarkdown(
|
||||||
.header(header)
|
.header(header)
|
||||||
.body(body)
|
.body(body)
|
||||||
.border()
|
.border()
|
||||||
.maxColWidth(Math.floor(columns / header.length) - header.length)
|
.maxColWidth(
|
||||||
|
Math.floor(columns / header.length) - Math.floor(header.length / 2),
|
||||||
|
)
|
||||||
.toString();
|
.toString();
|
||||||
header = [];
|
header = [];
|
||||||
body = [];
|
body = [];
|
||||||
return `${table}\n\n`;
|
return `${table}\n\n`;
|
||||||
},
|
},
|
||||||
tr: (children) => {
|
tr: (children) => {
|
||||||
if (children) body.push(children.split(":tablesep:").slice(1));
|
if (!children) return;
|
||||||
return "";
|
body.push(
|
||||||
|
children
|
||||||
|
.split(":tablesep:")
|
||||||
|
.slice(1)
|
||||||
|
.map((value) => new SWCell(value)),
|
||||||
|
);
|
||||||
|
return null;
|
||||||
},
|
},
|
||||||
td: (children) => `:tablesep:${children}`,
|
td: (children) => `:tablesep:${children}`,
|
||||||
th: (children) => {
|
th: (children) => {
|
||||||
header.push(chalk.red(children));
|
header.push(new SWCell(chalk.red(children)));
|
||||||
return "";
|
return null;
|
||||||
},
|
},
|
||||||
strong: (children) => chalk.bold(children),
|
strong: (children) => chalk.bold(children),
|
||||||
emphasis: (children) => chalk.italic(children),
|
emphasis: (children) => chalk.italic(children),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue