"""Long lists as one filterable table, each row opening to its details. MAME's card pages read 13,000 to 16,000 words, one card after another, before a reader found the archive they came for. Here each entry is one row: its name, the facts that tell rows apart, and the full card in a closed block under the name. The table is written as HTML so the block can hold the card's Markdown. It carries what rehype-stack-tables.mjs gives a Markdown table: `data-rb-stack` (one block per row on a phone) and the filter box above, which site.ts wires. Without JavaScript the rows show and every block opens. A closed block stays in the page, so the browser's find and the site search still reach every name it holds. """ from __future__ import annotations import html from dataclasses import dataclass, field import sitemarkup as markup # rehype-stack-tables.mjs RECORD_ROWS: from this many rows a table has a # filter box, and its stacked labels are written by site.ts, not the build. RECORD_ROWS = 20 # filterPlaceholder in rehype-stack-tables.mjs: the column names offered. PLACEHOLDER_COLUMNS = 4 @dataclass class Row: """One entry: ``title`` is the inline HTML of its name (a heading, so the site search lands on it), ``body`` the Markdown lines shown when the row opens, ``cells`` the HTML of the other columns.""" title: str body: list[str] cells: list[str] = field(default_factory=list) def filter_placeholder(labels: list[str]) -> str: """"File, contents, status..." as rehype-stack-tables.mjs words it.""" words = [label for label in labels if label][:PLACEHOLDER_COLUMNS] if not words: return "Type to filter..." lowered = [word if index == 0 or not (word[:1].isupper() and word[1:2].islower()) else word[0].lower() + word[1:] for index, word in enumerate(words)] return f"{', '.join(lowered)}..." def filter_box(ident: str, heading: str, labels: list[str], rows: int, noun: str = "rows") -> str: """The filter box rehype-stack-tables.mjs writes above a long table. It is `hidden` until site.ts wires it: without the script it filters nothing, so a reader with no JavaScript, a text dump and the search skip it while the rows stay. retrobios.css keeps its room meanwhile, so the table does not move when it shows. The count is the input's description, and spaces keep label, field and count apart in any text read from the HTML.""" return ( f'
| {html.escape(label)} | ' lines.extend(["", f"||
|---|---|---|
| ", ' ', f" ", "{row.title}", "", *row.body, "", " | "])
else:
lines.append(f"{row.title} | ") for column in keep[1:]: label = (f' data-label="{html.escape(short[keep.index(column)])}"' if len(rows) < RECORD_ROWS else "") ignored = "" if heads[column] in searched else f" {skip}" lines.append(f"{row.cells[column - 1] or '-'} | ") lines.append("