feat(docs): add _as_aside detector for LABEL: callout paragraphs
This commit is contained in:
@@ -385,6 +385,32 @@ def _prettify_block(block: list[str], entry_name: str | None) -> str:
|
||||
return "\n\n".join(chunk for chunk in out if chunk.strip())
|
||||
|
||||
|
||||
ASIDE_LABELS: dict[str, tuple[str, str, str | None]] = {
|
||||
"NOTE": ("note", "Note", None),
|
||||
"IMPORTANT": ("note", "Important", "star"),
|
||||
"TIP": ("tip", "Tip", None),
|
||||
"HINT": ("tip", "Hint", "question-circle"),
|
||||
"WARNING": ("caution", "Warning", "warning"),
|
||||
"CAUTION": ("caution", "Caution", None),
|
||||
"DANGER": ("danger", "Danger", None),
|
||||
}
|
||||
ASIDE_RE = re.compile(rf"^({'|'.join(ASIDE_LABELS)}):\s*(.*)$")
|
||||
|
||||
|
||||
def _as_aside(para: list[str]) -> str | None:
|
||||
"""Render a `LABEL: ...` flat paragraph as a Starlight <Aside>, else None."""
|
||||
m = ASIDE_RE.match(para[0])
|
||||
if not m:
|
||||
return None
|
||||
label, rest = m.groups()
|
||||
aside_type, title, icon = ASIDE_LABELS[label]
|
||||
body = "\n".join(([rest] if rest else []) + para[1:])
|
||||
attrs = f'type="{aside_type}" title="{title}"'
|
||||
if icon:
|
||||
attrs += f' icon="{icon}"'
|
||||
return f"<Aside {attrs}>\n{body}\n</Aside>"
|
||||
|
||||
|
||||
def prettify(body: str, entry_name: str | None = None) -> str:
|
||||
"""Rewrite a body's indented code blocks for the website.
|
||||
|
||||
|
||||
@@ -538,6 +538,60 @@ def test_prettify_titles_paths_and_commented_examples():
|
||||
)
|
||||
|
||||
|
||||
def test_as_aside_converts_a_single_line_label():
|
||||
"""A `LABEL: text` line becomes a titled <Aside> with the label's type."""
|
||||
import build_manual
|
||||
|
||||
out = build_manual._as_aside(["TIP: Use `-h` on any function for its help text."])
|
||||
assert out == (
|
||||
'<Aside type="tip" title="Tip">\n'
|
||||
"Use `-h` on any function for its help text.\n"
|
||||
"</Aside>"
|
||||
), f"unexpected aside output:\n{out}"
|
||||
|
||||
|
||||
def test_as_aside_converts_a_label_and_list():
|
||||
"""A label line immediately followed by a list becomes one aside body."""
|
||||
import build_manual
|
||||
|
||||
out = build_manual._as_aside(
|
||||
[
|
||||
"NOTE:",
|
||||
" - Command shadows react immediately.",
|
||||
" - conf.d-level components take effect in new shells.",
|
||||
]
|
||||
)
|
||||
assert out == (
|
||||
'<Aside type="note" title="Note">\n'
|
||||
" - Command shadows react immediately.\n"
|
||||
" - conf.d-level components take effect in new shells.\n"
|
||||
"</Aside>"
|
||||
), f"unexpected aside output:\n{out}"
|
||||
|
||||
|
||||
def test_as_aside_adds_icon_only_where_types_collide():
|
||||
"""WARNING and CAUTION share the `caution` type; only WARNING gets an icon."""
|
||||
import build_manual
|
||||
|
||||
warning = build_manual._as_aside(["WARNING: Deletes files permanently."])
|
||||
caution = build_manual._as_aside(["CAUTION: Slow on large trees."])
|
||||
assert 'icon="warning"' in warning, f"WARNING lost its icon override:\n{warning}"
|
||||
assert "icon=" not in caution, f"CAUTION should use its type's default icon:\n{caution}"
|
||||
|
||||
|
||||
def test_as_aside_rejects_non_label_paragraphs():
|
||||
"""Only the closed set of 7 labels triggers an aside; other WORD: prose does not."""
|
||||
import build_manual
|
||||
|
||||
cases = {
|
||||
"Example prefix": ["Example:", "rm file.txt"],
|
||||
"sentence with a colon": ["Options: pass one of the flags below."],
|
||||
"lowercase label": ["note: this should not become an aside"],
|
||||
}
|
||||
for label, para in cases.items():
|
||||
assert build_manual._as_aside(para) is None, f"{label} was wrongly asided"
|
||||
|
||||
|
||||
def test_prettify_is_site_only():
|
||||
"""The SSOT keeps the indented form the man-page pipeline depends on."""
|
||||
import build_manual
|
||||
|
||||
Reference in New Issue
Block a user