Skip to content

Commit 06d0172

Browse files
committed
feat: add subtitle option to section
1 parent 671cf1f commit 06d0172

File tree

4 files changed

+75
-11
lines changed

4 files changed

+75
-11
lines changed

quartodoc/layout.py

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ class Section(_Structural):
5858
kind:
5959
title:
6060
Title of the section on the index.
61+
subtitle:
62+
Subtitle of the section on the index. Note that either title or subtitle,
63+
but not both, may be set.
6164
desc:
6265
Description of the section on the index.
6366
package:
@@ -67,10 +70,22 @@ class Section(_Structural):
6770
"""
6871

6972
kind: Literal["section"] = "section"
70-
title: str
71-
desc: str
73+
title: Optional[str] = None
74+
subtitle: Optional[str] = None
75+
desc: Optional[str] = None
7276
package: Union[str, None, MISSING] = MISSING()
73-
contents: ContentList
77+
contents: Optional[ContentList] = None
78+
79+
def __init__(self, **data):
80+
super().__init__(**data)
81+
82+
# TODO: should these be a custom type? Or can we use pydantic's ValidationError?
83+
if self.title is None and self.subtitle is None and self.contents is None:
84+
raise ValueError(
85+
"Section must specify a title, subtitle, or contents field"
86+
)
87+
elif self.title is not None and self.subtitle is not None:
88+
raise ValueError("Section cannot specify both title and subtitle fields.")
7489

7590

7691
class SummaryDetails(_Base):

quartodoc/renderers/md_renderer.py

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -528,16 +528,23 @@ def summarize(self, el: layout.Layout):
528528

529529
@dispatch
530530
def summarize(self, el: layout.Section):
531-
header = f"## {el.title}\n\n{el.desc}"
531+
desc = f"\n\n{el.desc}" if el.desc is not None else ""
532+
if el.title is not None:
533+
header = f"## {el.title}{desc}"
534+
elif el.subtitle is not None:
535+
header = f"### {el.subtitle}{desc}"
532536

533-
thead = "| | |\n| --- | --- |"
537+
if el.contents:
538+
thead = "| | |\n| --- | --- |"
534539

535-
rendered = []
536-
for child in el.contents:
537-
rendered.append(self.summarize(child))
540+
rendered = []
541+
for child in el.contents:
542+
rendered.append(self.summarize(child))
538543

539-
str_func_table = "\n".join([thead, *rendered])
540-
return f"{header}\n\n{str_func_table}"
544+
str_func_table = "\n".join([thead, *rendered])
545+
return f"{header}\n\n{str_func_table}"
546+
547+
return header
541548

542549
@dispatch
543550
def summarize(self, el: layout.Page):

quartodoc/tests/test_layout.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,17 @@ def test_layout_from_config(cfg, res):
2727

2828
layout = Layout(sections=[cfg])
2929
assert layout.sections[0] == res
30+
31+
32+
@pytest.mark.parametrize(
33+
"kwargs, msg_part",
34+
[
35+
({}, "must specify a title, subtitle, or contents field"),
36+
({"title": "x", "subtitle": "y"}, "cannot specify both"),
37+
],
38+
)
39+
def test_section_validation_fails(kwargs, msg_part):
40+
with pytest.raises(ValueError) as exc_info:
41+
Section(**kwargs)
42+
43+
assert msg_part in exc_info.value.args[0]

quartodoc/tests/test_renderers.py

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
import griffe.docstrings.dataclasses as ds
33

44
from quartodoc.renderers import MdRenderer
5-
from quartodoc import get_object
5+
from quartodoc import layout
6+
from quartodoc import get_object, blueprint
67

78

89
@pytest.fixture
@@ -60,3 +61,30 @@ def test_render_table_description_interlink(renderer, pair):
6061

6162
res = renderer.render(pars)
6263
assert interlink in res
64+
65+
66+
@pytest.mark.parametrize(
67+
"section, dst",
68+
[
69+
(layout.Section(title="abc"), "## abc"),
70+
(layout.Section(subtitle="abc"), "### abc"),
71+
(layout.Section(title="abc", desc="zzz"), "## abc\n\nzzz"),
72+
(layout.Section(subtitle="abc", desc="zzz"), "### abc\n\nzzz"),
73+
],
74+
)
75+
def test_render_summarize_section_title(renderer, section, dst):
76+
res = renderer.summarize(section)
77+
78+
assert res == dst
79+
80+
81+
def test_render_summarize_section_contents(renderer):
82+
obj = blueprint(layout.Auto(name="a_func", package="quartodoc.tests.example"))
83+
section = layout.Section(title="abc", desc="zzz", contents=[obj])
84+
res = renderer.summarize(section)
85+
86+
table = (
87+
"| | |\n| --- | --- |\n"
88+
"| [a_func](#quartodoc.tests.example.a_func) | A function |"
89+
)
90+
assert res == f"## abc\n\nzzz\n\n{table}"

0 commit comments

Comments
 (0)