Skip to content

Commit a4518c0

Browse files
committed
Füge Unterstützung für Tabellen im GitHub-Flavored Markdown hinzu
1 parent 1431465 commit a4518c0

2 files changed

Lines changed: 123 additions & 0 deletions

File tree

popup/popup.css

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -670,6 +670,39 @@ body {
670670
margin: 12px 0;
671671
}
672672

673+
/* Tables */
674+
.message-body table.md-table {
675+
border-collapse: collapse;
676+
margin: 10px 0;
677+
font-size: 0.95em;
678+
border: 1px solid var(--color-border);
679+
border-radius: var(--radius-sm);
680+
display: block;
681+
max-width: 100%;
682+
overflow-x: auto;
683+
}
684+
685+
.message-body table.md-table th,
686+
.message-body table.md-table td {
687+
border: 1px solid var(--color-border);
688+
padding: 6px 10px;
689+
text-align: left;
690+
vertical-align: top;
691+
}
692+
693+
.message-body table.md-table thead {
694+
background: var(--color-bg-tertiary);
695+
}
696+
697+
.message-body table.md-table th {
698+
font-weight: 600;
699+
color: var(--color-text-primary);
700+
}
701+
702+
.message-body table.md-table tbody tr:nth-child(even) {
703+
background: var(--color-bg-secondary);
704+
}
705+
673706
/* Inline Code */
674707
.message-body code:not(pre code) {
675708
background: var(--color-bg-tertiary);

popup/popup.js

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -674,6 +674,90 @@
674674
return id;
675675
});
676676

677+
// Tables (GitHub-Flavored Markdown) — must run before lists/inline so cell
678+
// content isn't mangled by line-based transforms.
679+
const tables = [];
680+
const parseTableRow = (line) => {
681+
let s = line.trim();
682+
if (s.startsWith("|")) s = s.slice(1);
683+
if (s.endsWith("|")) s = s.slice(0, -1);
684+
return s.split("|").map((c) => c.trim());
685+
};
686+
const renderInlineMd = (text) => {
687+
const codes = [];
688+
let out = text.replace(/`([^`]+)`/g, (_, c) => {
689+
const id = `__TBLCODE_${codes.length}__`;
690+
codes.push(`<code>${escapeHtml(c)}</code>`);
691+
return id;
692+
});
693+
out = out.replace(/\*\*\*(.+?)\*\*\*/g, "<strong><em>$1</em></strong>");
694+
out = out.replace(/\*\*(.+?)\*\*/g, "<strong>$1</strong>");
695+
out = out.replace(/\*(.+?)\*/g, "<em>$1</em>");
696+
out = out.replace(/~~(.+?)~~/g, "<del>$1</del>");
697+
out = out.replace(
698+
/\[([^\]]+)\]\(([^)]+)\)/g,
699+
'<a href="$2" target="_blank" rel="noopener">$1</a>',
700+
);
701+
codes.forEach((c, i) => {
702+
out = out.replace(`__TBLCODE_${i}__`, c);
703+
});
704+
return out;
705+
};
706+
const sepRe = /^\s*\|?\s*:?-+:?\s*(\|\s*:?-+:?\s*)+\|?\s*$/;
707+
const tblLines = html.split("\n");
708+
const cleanedLines = [];
709+
let tli = 0;
710+
while (tli < tblLines.length) {
711+
const line = tblLines[tli];
712+
const next = tblLines[tli + 1];
713+
if (next !== undefined && line.includes("|") && sepRe.test(next)) {
714+
const headerCells = parseTableRow(line);
715+
const aligns = parseTableRow(next).map((c) => {
716+
const l = c.startsWith(":");
717+
const r = c.endsWith(":");
718+
if (l && r) return "center";
719+
if (r) return "right";
720+
if (l) return "left";
721+
return null;
722+
});
723+
const bodyRows = [];
724+
let bj = tli + 2;
725+
while (
726+
bj < tblLines.length &&
727+
tblLines[bj].includes("|") &&
728+
tblLines[bj].trim() !== ""
729+
) {
730+
bodyRows.push(parseTableRow(tblLines[bj]));
731+
bj++;
732+
}
733+
let tableHtml = '<table class="md-table"><thead><tr>';
734+
headerCells.forEach((c, idx) => {
735+
const a = aligns[idx] ? ` style="text-align:${aligns[idx]}"` : "";
736+
tableHtml += `<th${a}>${renderInlineMd(c)}</th>`;
737+
});
738+
tableHtml += "</tr></thead><tbody>";
739+
bodyRows.forEach((row) => {
740+
tableHtml += "<tr>";
741+
for (let k = 0; k < headerCells.length; k++) {
742+
const c = row[k] !== undefined ? row[k] : "";
743+
const a = aligns[k] ? ` style="text-align:${aligns[k]}"` : "";
744+
tableHtml += `<td${a}>${renderInlineMd(c)}</td>`;
745+
}
746+
tableHtml += "</tr>";
747+
});
748+
tableHtml += "</tbody></table>";
749+
750+
const id = `__TABLE_${tables.length}__`;
751+
tables.push(tableHtml);
752+
cleanedLines.push(id);
753+
tli = bj;
754+
} else {
755+
cleanedLines.push(line);
756+
tli++;
757+
}
758+
}
759+
html = cleanedLines.join("\n");
760+
677761
// Inline code (protect from other processing)
678762
const inlineCodes = [];
679763
html = html.replace(/`([^`]+)`/g, (_, code) => {
@@ -728,6 +812,7 @@
728812
block.startsWith("<blockquote") ||
729813
block.startsWith("<hr") ||
730814
block.startsWith("__CODE_") ||
815+
block.startsWith("__TABLE_") ||
731816
block.startsWith("<div") ||
732817
block.startsWith("<li")
733818
) {
@@ -747,6 +832,11 @@
747832
html = html.replace(`__CODE_${i}__`, block);
748833
});
749834

835+
// Restore tables
836+
tables.forEach((tbl, i) => {
837+
html = html.replace(`__TABLE_${i}__`, tbl);
838+
});
839+
750840
return html;
751841
}
752842

0 commit comments

Comments
 (0)