refactor: md-table body column gen
This commit is contained in:
parent
617fd17def
commit
0261061bcb
|
|
@ -1,8 +1,9 @@
|
||||||
import { Marked, type MarkedExtension, type Tokens } from 'marked';
|
import { Marked, type MarkedExtension } from 'marked';
|
||||||
import {createDirectives, presetDirectiveConfigs} from 'marked-directive';
|
import {createDirectives, presetDirectiveConfigs} from 'marked-directive';
|
||||||
import yaml from 'js-yaml';
|
import yaml from 'js-yaml';
|
||||||
import markedAlert from "marked-alert";
|
import markedAlert from "marked-alert";
|
||||||
import markedMermaid from "./mermaid";
|
import markedMermaid from "./mermaid";
|
||||||
|
import markedTable from "./table";
|
||||||
import {gfmHeadingId} from "marked-gfm-heading-id";
|
import {gfmHeadingId} from "marked-gfm-heading-id";
|
||||||
|
|
||||||
let globalIconPrefix: string | undefined = undefined;
|
let globalIconPrefix: string | undefined = undefined;
|
||||||
|
|
@ -15,32 +16,12 @@ function overrideIconPrefix(path?: string){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 将表格数据转换为 CSV 格式字符串
|
|
||||||
* @param headers 表头数组
|
|
||||||
* @param rows 表格数据行
|
|
||||||
* @returns CSV 格式字符串
|
|
||||||
*/
|
|
||||||
function tableToCSV(headers: string[], rows: string[][]): string {
|
|
||||||
const escapeCell = (cell: string) => {
|
|
||||||
// 如果单元格包含逗号、换行或引号,需要转义
|
|
||||||
if (cell.includes(',') || cell.includes('\n') || cell.includes('"')) {
|
|
||||||
return `"${cell.replace(/"/g, '""')}"`;
|
|
||||||
}
|
|
||||||
return cell;
|
|
||||||
};
|
|
||||||
|
|
||||||
const headerLine = headers.map(escapeCell).join(',');
|
|
||||||
const dataLines = rows.map(row => row.map(escapeCell).join(','));
|
|
||||||
|
|
||||||
return [headerLine, ...dataLines].join('\n');
|
|
||||||
}
|
|
||||||
|
|
||||||
// 使用 marked-directive 来支持指令语法
|
// 使用 marked-directive 来支持指令语法
|
||||||
const marked = new Marked()
|
const marked = new Marked()
|
||||||
.use(gfmHeadingId())
|
.use(gfmHeadingId())
|
||||||
.use(markedAlert())
|
.use(markedAlert())
|
||||||
.use(markedMermaid())
|
.use(markedMermaid())
|
||||||
|
.use(markedTable())
|
||||||
.use(createDirectives([
|
.use(createDirectives([
|
||||||
...presetDirectiveConfigs,
|
...presetDirectiveConfigs,
|
||||||
{
|
{
|
||||||
|
|
@ -121,36 +102,6 @@ const marked = new Marked()
|
||||||
}]
|
}]
|
||||||
});
|
});
|
||||||
|
|
||||||
// 覆盖默认的 table renderer 以支持自动转换
|
|
||||||
marked.use({
|
|
||||||
renderer: {
|
|
||||||
table(token: Tokens.Table) {
|
|
||||||
// 检查表头是否包含 md-table-label
|
|
||||||
const header = token.header;
|
|
||||||
const labelIndex = header.findIndex(cell => cell.text === 'md-table-label');
|
|
||||||
|
|
||||||
if (labelIndex !== -1) {
|
|
||||||
// 将 md-table-label 列转换为 label
|
|
||||||
const headers = header.map(cell => cell.text === 'md-table-label' ? 'label' : cell.text);
|
|
||||||
|
|
||||||
// 转换所有行
|
|
||||||
const rows = token.rows.map(row =>
|
|
||||||
row.map(cell => cell.text)
|
|
||||||
);
|
|
||||||
|
|
||||||
// 生成 CSV 数据
|
|
||||||
const csvData = tableToCSV(headers, rows);
|
|
||||||
|
|
||||||
// 渲染为 md-table 组件,内联 CSV 数据
|
|
||||||
return `<md-table>${csvData}</md-table>\n`;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 默认表格渲染 - 使用 marked 默认行为
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} as MarkedExtension);
|
|
||||||
|
|
||||||
export function parseMarkdown(content: string, iconPrefix?: string): string {
|
export function parseMarkdown(content: string, iconPrefix?: string): string {
|
||||||
using prefix = overrideIconPrefix(iconPrefix);
|
using prefix = overrideIconPrefix(iconPrefix);
|
||||||
return marked.parse(content.trimStart()) as string;
|
return marked.parse(content.trimStart()) as string;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,65 @@
|
||||||
|
import type { MarkedExtension, Tokens } from "marked";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将表格数据转换为 CSV 格式字符串
|
||||||
|
* @param headers 表头数组
|
||||||
|
* @param rows 表格数据行
|
||||||
|
* @returns CSV 格式字符串
|
||||||
|
*/
|
||||||
|
function tableToCSV(headers: string[], rows: string[][]): string {
|
||||||
|
const escapeCell = (cell: string) => {
|
||||||
|
// 如果单元格包含逗号、换行或引号,需要转义
|
||||||
|
if (cell.includes(',') || cell.includes('\n') || cell.includes('"')) {
|
||||||
|
return `"${cell.replace(/"/g, '""')}"`;
|
||||||
|
}
|
||||||
|
return cell;
|
||||||
|
};
|
||||||
|
|
||||||
|
const headerLine = headers.map(escapeCell).join(',');
|
||||||
|
const dataLines = rows.map(row => row.map(escapeCell).join(','));
|
||||||
|
|
||||||
|
return [headerLine, ...dataLines].join('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function markedTable(): MarkedExtension {
|
||||||
|
return {
|
||||||
|
renderer: {
|
||||||
|
table(token: Tokens.Table) {
|
||||||
|
// 检查表头是否包含 md-table-label
|
||||||
|
const header = token.header;
|
||||||
|
const labelIndex = header.findIndex(cell => cell.text === 'md-table-label');
|
||||||
|
|
||||||
|
// 默认表格渲染 - 使用 marked 默认行为
|
||||||
|
if(labelIndex === -1) return false;
|
||||||
|
|
||||||
|
const headers = token.header.map(cell => cell.text);
|
||||||
|
headers[labelIndex] = 'label';
|
||||||
|
const rows = token.rows.map(row => row.map(cell => cell.text));
|
||||||
|
|
||||||
|
if(header.findIndex(header => header.text === 'body') < 0){
|
||||||
|
// 收集所有非 label 列的表头
|
||||||
|
const bodyColumns = header
|
||||||
|
.filter(cell => cell.text !== 'md-table-label')
|
||||||
|
.map(cell => cell.text);
|
||||||
|
|
||||||
|
// 构建 body 列的模板:**列名**:{{列名}}\n\n
|
||||||
|
const bodyTemplate = bodyColumns
|
||||||
|
.map(col => `**${col}**:{{${col}}}`)
|
||||||
|
.join('\n\n');
|
||||||
|
|
||||||
|
headers.push('body');
|
||||||
|
rows.forEach(row => {
|
||||||
|
row.push(bodyTemplate);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成 CSV 数据
|
||||||
|
const csvData = tableToCSV(headers, rows);
|
||||||
|
|
||||||
|
// 渲染为 md-table 组件,内联 CSV 数据
|
||||||
|
console.log(csvData)
|
||||||
|
return `<md-table>${csvData}</md-table>\n`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue