refactor: simplify spark button injection logic

Update the spark button injection to use `data-spark` slugs on
`md-table` elements instead of manual table parsing. This improves
reliability by leveraging the slug generated during markdown
rendering.
This commit is contained in:
2026-07-07 21:44:00 +08:00
parent 56af7dea42
commit 6b3a915350
2 changed files with 91 additions and 88 deletions
+14 -32
View File
@@ -183,8 +183,6 @@ const LINK_SVG =
// ---- Spark button (tables) ----
const DICE_HEADER_RE = /^d\d+$/i;
function injectSparkButtons(
root: Element,
normalizedPath: string,
@@ -196,40 +194,24 @@ function injectSparkButtons(
);
if (pageTables.length === 0) return;
const tables = root.querySelectorAll("table");
tables.forEach((table) => {
// Find the first header row — check thead first, then first tr
const thead = table.querySelector("thead");
const firstRow =
thead?.rows[0] ??
table.querySelector("tbody tr:first-child, tr:first-child");
if (!firstRow || !(firstRow instanceof HTMLTableRowElement)) return;
// Spark tables are rendered as <md-table data-spark="columnSlug">
const sparkTables = root.querySelectorAll("md-table[data-spark]");
sparkTables.forEach((el) => {
const colSlug = el.getAttribute("data-spark");
if (!colSlug) return;
const firstCell = firstRow.cells[0];
if (!firstCell) return;
const firstHeader = firstCell.textContent?.trim() ?? "";
if (!DICE_HEADER_RE.test(firstHeader)) return;
// Collect data headers from the remaining cells
const dataHeaders: string[] = [];
for (let i = 1; i < firstRow.cells.length; i++) {
const text = firstRow.cells[i].textContent?.trim() ?? "";
if (text) dataHeaders.push(text);
}
// Match against completions: find the spark table with matching
// notation and data headers (order matters)
const match = pageTables.find(
(st) =>
st.notation.toLowerCase() === firstHeader.toLowerCase() &&
st.headers.length === dataHeaders.length &&
st.headers.every((h, i) => h === dataHeaders[i]),
);
// Find the matching completions entry by column slug
const match = pageTables.find((st) => {
// st.slug is the combined slug (pageName-columnSlug);
// colSlug is just the column part. Match by checking if
// the combined slug ends with the column slug.
return st.slug.endsWith(`-${colSlug}`);
});
if (!match) return;
// Inject the spark button
// Inject the spark button into the <md-table> wrapper
const btn = createSparkButton(match.slug);
const wrapper = table.parentElement;
const wrapper = el.parentElement;
if (wrapper) {
wrapper.style.position = "relative";
wrapper.classList.add("group");