1
0
Fork 0

Add tables and lists to highlight

This commit is contained in:
Pabloader 2026-03-26 09:14:56 +00:00
parent f3d916982f
commit 5121a8047e
3 changed files with 77 additions and 0 deletions

View File

@ -42,4 +42,33 @@
.header3 { .header3 {
font-size: 1em; font-size: 1em;
}
.table {
border-collapse: collapse;
width: 100%;
margin: 0.5em 0;
}
.table th,
.table td {
border: 1px solid var(--tableBorder, #555);
padding: 0.3em 0.6em;
text-align: left;
}
.table th {
background: var(--tableHeaderBg, #3a3a3a);
font-weight: bold;
}
.list {
margin: 0.4em 0;
padding-left: 1.5em;
}
.hr {
border: none;
border-top: 1px solid var(--hrColor, #555);
margin: 0.5em 0;
} }

View File

@ -1,6 +1,44 @@
import clsx from 'clsx'; import clsx from 'clsx';
import styles from './assets/highlight.module.css'; import styles from './assets/highlight.module.css';
const parseTableRow = (line: string): string[] =>
line.split('|').slice(1, -1).map(cell => cell.trim());
const isSeparatorRow = (line: string): boolean =>
/^\|[\s|:\-]+\|$/.test(line.trim());
export const parseList = (block: string, ordered: boolean): string => {
const marker = ordered ? /^\d+\. / : /^[-+] /;
const items = block.trim().split('\n')
.map(l => `<li>${l.trim().replace(marker, '')}</li>`)
.join('');
const tag = ordered ? 'ol' : 'ul';
return `<${tag} class="${styles.list}">${items}</${tag}>`;
};
export const parseTable = (table: string): string => {
const lines = table.trim().split('\n').map(l => l.trim()).filter(l => l.startsWith('|'));
if (lines.length < 2) return table;
const sepIndex = lines.findIndex(isSeparatorRow);
if (sepIndex === -1) return table;
const headerLines = lines.slice(0, sepIndex);
const bodyLines = lines.slice(sepIndex + 1);
const renderCells = (cells: string[], tag: 'th' | 'td') =>
cells.map(cell => `<${tag}>${cell}</${tag}>`).join('');
const headers = headerLines
.map(l => `<tr>${renderCells(parseTableRow(l), 'th')}</tr>`)
.join('');
const rows = bodyLines
.map(l => `<tr>${renderCells(parseTableRow(l), 'td')}</tr>`)
.join('');
return `<table class="${styles.table}"><thead>${headers}</thead><tbody>${rows}</tbody></table>`;
};
export const highlight = (message: string, keepMarkup = true): string => { export const highlight = (message: string, keepMarkup = true): string => {
let resultHTML = ''; let resultHTML = '';
const tokenRegex = /(\*\*?|"|```|`|(?:^|\n)#{1,3} |\n)/g; const tokenRegex = /(\*\*?|"|```|`|(?:^|\n)#{1,3} |\n)/g;
@ -90,5 +128,12 @@ export const highlight = (message: string, keepMarkup = true): string => {
if (inHeader) resultHTML += '</span>'; if (inHeader) resultHTML += '</span>';
resultHTML += '</span>'.repeat(stack.length); resultHTML += '</span>'.repeat(stack.length);
if (!keepMarkup) {
resultHTML = resultHTML.replace(/((?:(?:^|\n)\|.+)+)/g, match => parseTable(match));
resultHTML = resultHTML.replace(/(^|\n)---(\n|$)/g, (_, pre, post) => `${pre}<hr class="${styles.hr}">${post}`);
resultHTML = resultHTML.replace(/((?:(?:^|\n)[-+] .+)+)/g, match => parseList(match, false));
resultHTML = resultHTML.replace(/((?:(?:^|\n)\d+\. .+)+)/g, match => parseList(match, true));
}
return resultHTML; return resultHTML;
} }

View File

@ -394,6 +394,9 @@ export namespace Tools {
{ name: `character:${c.name}`, content: c.name }, { name: `character:${c.name}`, content: c.name },
{ name: `character:${c.name}`, content: c.shortDescription }, { name: `character:${c.name}`, content: c.shortDescription },
{ name: `character:${c.name}`, content: c.description || '' }, { name: `character:${c.name}`, content: c.description || '' },
...c.relations.map(rel => (
{ name: `character:${c.name}`, content: `relation: ${rel.name} (${rel.relation})` }
)),
]), ]),
...appState.currentStory.locations.flatMap(l => [ ...appState.currentStory.locations.flatMap(l => [
{ name: `location:${l.name}`, content: l.name }, { name: `location:${l.name}`, content: l.name },