diff --git a/CONTENT_BRIDGE.md b/CONTENT_BRIDGE.md
index d150738..bf89930 100644
--- a/CONTENT_BRIDGE.md
+++ b/CONTENT_BRIDGE.md
@@ -286,7 +286,8 @@ The data file should contain either a top-level array or an object with an
`items` array. The `src` path is resolved relative to the Markdown file. Use
`columns` to control the visible columns, `headers` to rename table headers,
`link` to choose the column that should link through the row's `link` field,
-and `number` to prefix that linked column with a row number such as `slno`.
+and `number` to prefix and sort that linked column by a row number such as
+`slno`.
In Obsidian this remains a readable code fence next to the data file. In Astro
it becomes static HTML enhanced with local search and sort. In PDF it becomes a
diff --git a/docs/PARSER.md b/docs/PARSER.md
index b78ae17..4baef0c 100644
--- a/docs/PARSER.md
+++ b/docs/PARSER.md
@@ -344,7 +344,7 @@ Attributes:
| `headers="key:Label,..."` | Optional | Human-readable labels for selected columns. |
| `link="title"` | Optional | Column whose value links through the row's URL field. |
| `url="link"` | Optional | URL field used by the linked column; defaults to `link`. |
-| `number="slno"` | Optional | Prefix the linked column with a row number field. |
+| `number="slno"` | Optional | Prefix and sort the linked column by a row number field. |
| `caption="Resources"` | Optional | Visible toolbar title and accessible table caption. |
| `search="false"` | Optional | Disable local table search; enabled by default. |
| `sort="false"` | Optional | Disable sortable headers; enabled by default. |
diff --git a/sites/art/src/remark/semantic-blocks.mjs b/sites/art/src/remark/semantic-blocks.mjs
index a8afdbd..23809f1 100644
--- a/sites/art/src/remark/semantic-blocks.mjs
+++ b/sites/art/src/remark/semantic-blocks.mjs
@@ -220,19 +220,25 @@ function displayValue(value) {
return VALUE_LABELS[value] || value;
}
+function numberLabel(row, field) {
+ if (!field) return "";
+ const value = row[field];
+ if (value === undefined || value === null || value === "") return "";
+ return String(value).padStart(2, "0");
+}
+
function renderCell(row, column, options) {
const raw = row[column] ?? "";
const display = displayValue(raw);
- const sortValue = attribute(sortText(display));
+ const numberPrefix =
+ column === options.linkColumn ? numberLabel(row, options.numberField) : "";
+ const sortValue = attribute(
+ [numberPrefix, sortText(display)].filter(Boolean).join(" "),
+ );
const cellAttrs = `data-column="${attribute(column)}" data-sort-value="${sortValue}"`;
if (column === options.linkColumn && row[options.urlField]) {
- const numberValue = row[options.numberField];
- const numberLabel =
- numberValue === undefined || numberValue === null || numberValue === ""
- ? ""
- : String(numberValue).padStart(2, "0");
- const prefix = options.numberField && numberLabel ? `${numberLabel}. ` : "";
+ const prefix = numberPrefix ? `${numberPrefix}. ` : "";
return `
${escapeHtml(prefix)}${inlineMarkup(display)} | `;
}
diff --git a/sites/poetry/src/remark/semantic-blocks.mjs b/sites/poetry/src/remark/semantic-blocks.mjs
index a8afdbd..23809f1 100644
--- a/sites/poetry/src/remark/semantic-blocks.mjs
+++ b/sites/poetry/src/remark/semantic-blocks.mjs
@@ -220,19 +220,25 @@ function displayValue(value) {
return VALUE_LABELS[value] || value;
}
+function numberLabel(row, field) {
+ if (!field) return "";
+ const value = row[field];
+ if (value === undefined || value === null || value === "") return "";
+ return String(value).padStart(2, "0");
+}
+
function renderCell(row, column, options) {
const raw = row[column] ?? "";
const display = displayValue(raw);
- const sortValue = attribute(sortText(display));
+ const numberPrefix =
+ column === options.linkColumn ? numberLabel(row, options.numberField) : "";
+ const sortValue = attribute(
+ [numberPrefix, sortText(display)].filter(Boolean).join(" "),
+ );
const cellAttrs = `data-column="${attribute(column)}" data-sort-value="${sortValue}"`;
if (column === options.linkColumn && row[options.urlField]) {
- const numberValue = row[options.numberField];
- const numberLabel =
- numberValue === undefined || numberValue === null || numberValue === ""
- ? ""
- : String(numberValue).padStart(2, "0");
- const prefix = options.numberField && numberLabel ? `${numberLabel}. ` : "";
+ const prefix = numberPrefix ? `${numberPrefix}. ` : "";
return `${escapeHtml(prefix)}${inlineMarkup(display)} | `;
}
diff --git a/sites/puzzles/src/remark/semantic-blocks.mjs b/sites/puzzles/src/remark/semantic-blocks.mjs
index a8afdbd..23809f1 100644
--- a/sites/puzzles/src/remark/semantic-blocks.mjs
+++ b/sites/puzzles/src/remark/semantic-blocks.mjs
@@ -220,19 +220,25 @@ function displayValue(value) {
return VALUE_LABELS[value] || value;
}
+function numberLabel(row, field) {
+ if (!field) return "";
+ const value = row[field];
+ if (value === undefined || value === null || value === "") return "";
+ return String(value).padStart(2, "0");
+}
+
function renderCell(row, column, options) {
const raw = row[column] ?? "";
const display = displayValue(raw);
- const sortValue = attribute(sortText(display));
+ const numberPrefix =
+ column === options.linkColumn ? numberLabel(row, options.numberField) : "";
+ const sortValue = attribute(
+ [numberPrefix, sortText(display)].filter(Boolean).join(" "),
+ );
const cellAttrs = `data-column="${attribute(column)}" data-sort-value="${sortValue}"`;
if (column === options.linkColumn && row[options.urlField]) {
- const numberValue = row[options.numberField];
- const numberLabel =
- numberValue === undefined || numberValue === null || numberValue === ""
- ? ""
- : String(numberValue).padStart(2, "0");
- const prefix = options.numberField && numberLabel ? `${numberLabel}. ` : "";
+ const prefix = numberPrefix ? `${numberPrefix}. ` : "";
return `${escapeHtml(prefix)}${inlineMarkup(display)} | `;
}
diff --git a/sites/reflections/src/remark/semantic-blocks.mjs b/sites/reflections/src/remark/semantic-blocks.mjs
index a8afdbd..23809f1 100644
--- a/sites/reflections/src/remark/semantic-blocks.mjs
+++ b/sites/reflections/src/remark/semantic-blocks.mjs
@@ -220,19 +220,25 @@ function displayValue(value) {
return VALUE_LABELS[value] || value;
}
+function numberLabel(row, field) {
+ if (!field) return "";
+ const value = row[field];
+ if (value === undefined || value === null || value === "") return "";
+ return String(value).padStart(2, "0");
+}
+
function renderCell(row, column, options) {
const raw = row[column] ?? "";
const display = displayValue(raw);
- const sortValue = attribute(sortText(display));
+ const numberPrefix =
+ column === options.linkColumn ? numberLabel(row, options.numberField) : "";
+ const sortValue = attribute(
+ [numberPrefix, sortText(display)].filter(Boolean).join(" "),
+ );
const cellAttrs = `data-column="${attribute(column)}" data-sort-value="${sortValue}"`;
if (column === options.linkColumn && row[options.urlField]) {
- const numberValue = row[options.numberField];
- const numberLabel =
- numberValue === undefined || numberValue === null || numberValue === ""
- ? ""
- : String(numberValue).padStart(2, "0");
- const prefix = options.numberField && numberLabel ? `${numberLabel}. ` : "";
+ const prefix = numberPrefix ? `${numberPrefix}. ` : "";
return `${escapeHtml(prefix)}${inlineMarkup(display)} | `;
}
diff --git a/sites/research/src/remark/semantic-blocks.mjs b/sites/research/src/remark/semantic-blocks.mjs
index a8afdbd..23809f1 100644
--- a/sites/research/src/remark/semantic-blocks.mjs
+++ b/sites/research/src/remark/semantic-blocks.mjs
@@ -220,19 +220,25 @@ function displayValue(value) {
return VALUE_LABELS[value] || value;
}
+function numberLabel(row, field) {
+ if (!field) return "";
+ const value = row[field];
+ if (value === undefined || value === null || value === "") return "";
+ return String(value).padStart(2, "0");
+}
+
function renderCell(row, column, options) {
const raw = row[column] ?? "";
const display = displayValue(raw);
- const sortValue = attribute(sortText(display));
+ const numberPrefix =
+ column === options.linkColumn ? numberLabel(row, options.numberField) : "";
+ const sortValue = attribute(
+ [numberPrefix, sortText(display)].filter(Boolean).join(" "),
+ );
const cellAttrs = `data-column="${attribute(column)}" data-sort-value="${sortValue}"`;
if (column === options.linkColumn && row[options.urlField]) {
- const numberValue = row[options.numberField];
- const numberLabel =
- numberValue === undefined || numberValue === null || numberValue === ""
- ? ""
- : String(numberValue).padStart(2, "0");
- const prefix = options.numberField && numberLabel ? `${numberLabel}. ` : "";
+ const prefix = numberPrefix ? `${numberPrefix}. ` : "";
return `${escapeHtml(prefix)}${inlineMarkup(display)} | `;
}
diff --git a/sites/reviews/src/remark/semantic-blocks.mjs b/sites/reviews/src/remark/semantic-blocks.mjs
index a8afdbd..23809f1 100644
--- a/sites/reviews/src/remark/semantic-blocks.mjs
+++ b/sites/reviews/src/remark/semantic-blocks.mjs
@@ -220,19 +220,25 @@ function displayValue(value) {
return VALUE_LABELS[value] || value;
}
+function numberLabel(row, field) {
+ if (!field) return "";
+ const value = row[field];
+ if (value === undefined || value === null || value === "") return "";
+ return String(value).padStart(2, "0");
+}
+
function renderCell(row, column, options) {
const raw = row[column] ?? "";
const display = displayValue(raw);
- const sortValue = attribute(sortText(display));
+ const numberPrefix =
+ column === options.linkColumn ? numberLabel(row, options.numberField) : "";
+ const sortValue = attribute(
+ [numberPrefix, sortText(display)].filter(Boolean).join(" "),
+ );
const cellAttrs = `data-column="${attribute(column)}" data-sort-value="${sortValue}"`;
if (column === options.linkColumn && row[options.urlField]) {
- const numberValue = row[options.numberField];
- const numberLabel =
- numberValue === undefined || numberValue === null || numberValue === ""
- ? ""
- : String(numberValue).padStart(2, "0");
- const prefix = options.numberField && numberLabel ? `${numberLabel}. ` : "";
+ const prefix = numberPrefix ? `${numberPrefix}. ` : "";
return `${escapeHtml(prefix)}${inlineMarkup(display)} | `;
}
diff --git a/sites/vibes/src/remark/semantic-blocks.mjs b/sites/vibes/src/remark/semantic-blocks.mjs
index a8afdbd..23809f1 100644
--- a/sites/vibes/src/remark/semantic-blocks.mjs
+++ b/sites/vibes/src/remark/semantic-blocks.mjs
@@ -220,19 +220,25 @@ function displayValue(value) {
return VALUE_LABELS[value] || value;
}
+function numberLabel(row, field) {
+ if (!field) return "";
+ const value = row[field];
+ if (value === undefined || value === null || value === "") return "";
+ return String(value).padStart(2, "0");
+}
+
function renderCell(row, column, options) {
const raw = row[column] ?? "";
const display = displayValue(raw);
- const sortValue = attribute(sortText(display));
+ const numberPrefix =
+ column === options.linkColumn ? numberLabel(row, options.numberField) : "";
+ const sortValue = attribute(
+ [numberPrefix, sortText(display)].filter(Boolean).join(" "),
+ );
const cellAttrs = `data-column="${attribute(column)}" data-sort-value="${sortValue}"`;
if (column === options.linkColumn && row[options.urlField]) {
- const numberValue = row[options.numberField];
- const numberLabel =
- numberValue === undefined || numberValue === null || numberValue === ""
- ? ""
- : String(numberValue).padStart(2, "0");
- const prefix = options.numberField && numberLabel ? `${numberLabel}. ` : "";
+ const prefix = numberPrefix ? `${numberPrefix}. ` : "";
return `${escapeHtml(prefix)}${inlineMarkup(display)} | `;
}