"""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.""" 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("