markdown tables headings have scope of col; raw html tables are not changed

This commit is contained in:
Adam Teichert
2025-12-16 13:02:24 -07:00
parent e07d0a6e47
commit e9f33e0174
2 changed files with 63 additions and 0 deletions

View File

@@ -34,4 +34,53 @@ describe('markdownToHtmlNoImages', () => {
const html = markdownToHtmlNoImages(markdown);
expect(html).toMatch(/<table>\s*<caption style="color:red">My Table<\/caption>/);
});
it('adds scope="col" to table headers', () => {
const markdown = `
| Header 1 | Header 2 |
| --- | --- |
| Cell 1 | Cell 2 |`;
const html = markdownToHtmlNoImages(markdown);
expect(html).toContain('<th scope="col">Header 1</th>');
expect(html).toContain('<th scope="col">Header 2</th>');
});
it('does not add an extra empty header row', () => {
const markdown = `
| Header |
| --- |
| Cell |`;
const html = markdownToHtmlNoImages(markdown);
expect(html).not.toContain('<th scope="col"></th>');
const thCount = (html.match(/<th scope="col"/g) || []).length;
expect(thCount).toBe(1);
});
it('does not add scope="col" to raw HTML tables', () => {
const markdown = `
<table>
<thead>
<tr>
<th>Raw Header</th>
</tr>
</thead>
<tbody>
<tr>
<td>Raw Cell</td>
</tr>
</tbody>
</table>
| MD Header |
| --- |
| MD Cell |`;
const html = markdownToHtmlNoImages(markdown);
// Raw table should be untouched (or at least not have scope="col" added if it wasn't there)
expect(html).toContain('<th>Raw Header</th>');
expect(html).not.toContain('<th scope="col">Raw Header</th>');
// Markdown table should have scope="col"
expect(html).toContain('<th scope="col">MD Header</th>');
});
});

View File

@@ -47,6 +47,20 @@ marked.use(
marked.use({ extensions: [mermaidExtension] });
// We use a custom renderer instead of a regex replace because regex is too aggressive.
// It would add scope="col" to raw HTML tables (which we want to leave alone).
// The renderer only applies to markdown tables.
marked.use({
renderer: {
tablecell({ text, header, align }) {
const type = header ? "th" : "td";
const alignAttr = align ? ` align="${align}"` : "";
const scopeAttr = header ? ' scope="col"' : "";
return `<${type}${scopeAttr}${alignAttr}>${text}</${type}>\n`;
},
},
});
export function extractImageSources(htmlString: string) {
const srcUrls = [];
const regex = /<img[^>]+src=["']?([^"'>]+)["']?/g;