Skip to content

Commit 5ed1430

Browse files
authored
Merge pull request #367 from machow/fix-anchors-strip
Fix: make header css classes more robust by stripping non-alphanumerics
2 parents 75c8477 + 487640d commit 5ed1430

File tree

5 files changed

+47
-8
lines changed

5 files changed

+47
-8
lines changed

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ include = ["quartodoc"]
99

1010
[tool.pytest.ini_options]
1111
markers = []
12-
testpaths = ["quartodoc/tests"]
12+
testpaths = ["quartodoc"]
1313

1414
[project]
1515
name = "quartodoc"

quartodoc/ast.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -375,10 +375,10 @@ def preview(
375375
>>> obj = get_object("quartodoc", "get_object")
376376
377377
>>> preview(obj.docstring.parsed)
378-
...
378+
...
379379
380380
>>> preview(obj)
381-
...
381+
...
382382
383383
"""
384384

quartodoc/renderers/md_renderer.py

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from __future__ import annotations
22

33
import black
4+
import re
45
import quartodoc.ast as qast
56

67
from contextlib import contextmanager
@@ -26,6 +27,28 @@ def _has_attr_section(el: dc.Docstring | None):
2627
return any([isinstance(x, ds.DocstringSectionAttributes) for x in el.parsed])
2728

2829

30+
def _sanitize_title(title: str):
31+
"""Replace characters so that title can be used as an anchor, by
32+
33+
Approach:
34+
* replace spaces with -, then
35+
* stripping non alphanumeric characters
36+
37+
Examples
38+
--------
39+
40+
>>> _sanitize_title("a b c")
41+
'a-b-c'
42+
>>> _sanitize_title("a b! c")
43+
'a-b-c'
44+
>>> _sanitize_title("a`b`c{")
45+
'abc'
46+
47+
"""
48+
49+
return re.sub(r"[^a-zA-Z0-9-]+", "", title.replace(" ", "-"))
50+
51+
2952
@dataclass
3053
class ParamRow:
3154
name: str | None
@@ -269,10 +292,11 @@ def render_header(self, el: layout.Doc) -> str:
269292

270293
@dispatch
271294
def render_header(self, el: ds.DocstringSection) -> str:
272-
title = el.title or el.kind.value
273-
_classes = [".doc-section", ".doc-section-" + title.replace(" ", "-")]
295+
title = el.title or el.kind.value.title()
296+
anchor_part = _sanitize_title(title.lower())
297+
_classes = [".doc-section", f".doc-section-{anchor_part}"]
274298
_str_classes = " ".join(_classes)
275-
return f"{'#' * self.crnt_header_level} {title.title()} {{{_str_classes}}}"
299+
return f"{'#' * self.crnt_header_level} {title} {{{_str_classes}}}"
276300

277301
# render method -----------------------------------------------------------
278302

quartodoc/tests/__snapshots__/test_renderers.ambr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,7 @@
398398
| a | int | The a parameter. | _required_ |
399399
| b | str | The b parameter. | _required_ |
400400

401-
## Custom Admonition {.doc-section .doc-section-Custom-Admonition}
401+
## Custom Admonition {.doc-section .doc-section-custom-admonition}
402402

403403
Some text.
404404
'''
@@ -420,7 +420,7 @@
420420
| a | | The a parameter. | _required_ |
421421
| b | str | The b parameter. | _required_ |
422422

423-
## Custom Admonition {.doc-section .doc-section-Custom-Admonition}
423+
## Custom Admonition {.doc-section .doc-section-custom-admonition}
424424

425425
Some text.
426426
'''

quartodoc/tests/test_renderers.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ def renderer():
1818
return MdRenderer()
1919

2020

21+
# Smaller parts ----------------------------------------------------------------
22+
23+
2124
def test_render_param_kwargs(renderer):
2225
f = get_object("quartodoc.tests.example_signature.no_annotations")
2326
res = renderer.render(f.parameters)
@@ -126,6 +129,18 @@ def test_render_doc_section_admonition(renderer):
126129
assert res == "quartodoc.tests.example: Method for doing a thing"
127130

128131

132+
def test_render_doc_section_header_anchor(renderer):
133+
section = ds.DocstringSection(title="a `chaotic` {.title}")
134+
135+
dst = "# a `chaotic` {.title} {.doc-section .doc-section-a-chaotic-title}"
136+
137+
assert renderer.render_header(section) == dst
138+
139+
140+
# Big pieces -------------------------------------------------------------------
141+
# These are mostly snapshots
142+
143+
129144
@pytest.mark.parametrize("children", ["embedded", "flat", "linked"])
130145
def test_render_doc_module(snapshot, renderer, children):
131146
bp = blueprint(Auto(name="quartodoc.tests.example", children=children))

0 commit comments

Comments
 (0)