Skip to content

Commit 31aea4e

Browse files
committed
Switch docstring directive prefix from @ to %
1 parent ec9a2b2 commit 31aea4e

4 files changed

Lines changed: 97 additions & 87 deletions

File tree

great_docs/_directives.py

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -31,18 +31,18 @@ def __bool__(self) -> bool:
3131
return bool(self.family or self.order is not None or self.seealso or self.nodoc)
3232

3333

34-
# Single-line directive patterns (with @ prefix)
34+
# Single-line directive patterns (with % prefix, no colon)
3535
# Each pattern matches a complete line starting with the directive
3636
DIRECTIVE_PATTERNS = {
37-
"family": re.compile(r"^\s*@family:\s*(.+?)\s*$", re.MULTILINE),
38-
"order": re.compile(r"^\s*@order:\s*(\d+)\s*$", re.MULTILINE),
39-
"seealso": re.compile(r"^\s*@seealso:\s*(.+?)\s*$", re.MULTILINE),
40-
"nodoc": re.compile(r"^\s*@nodoc:\s*(true|yes|1)?\s*$", re.MULTILINE | re.IGNORECASE),
37+
"family": re.compile(r"^\s*%family\s+(.+?)\s*$", re.MULTILINE),
38+
"order": re.compile(r"^\s*%order\s+(\d+)\s*$", re.MULTILINE),
39+
"seealso": re.compile(r"^\s*%seealso\s+(.+?)\s*$", re.MULTILINE),
40+
"nodoc": re.compile(r"^\s*%nodoc(?:\s+(true|yes|1))?\s*$", re.MULTILINE | re.IGNORECASE),
4141
}
4242

4343
# Combined pattern for stripping all directives (matches the whole line including newline)
4444
ALL_DIRECTIVES_PATTERN = re.compile(
45-
r"^\s*@(?:family|order|seealso|nodoc):.*$\n?", re.MULTILINE | re.IGNORECASE
45+
r"^\s*%(?:family|order|seealso|nodoc)(?:\s+.*)?$\n?", re.MULTILINE | re.IGNORECASE
4646
)
4747

4848

@@ -65,9 +65,9 @@ def extract_directives(docstring: str | None) -> DocDirectives:
6565
>>> doc = '''
6666
... Short description.
6767
...
68-
... @family: Family Name
69-
... @order: 1
70-
... @seealso: func_a, func_b
68+
... %family Family Name
69+
... %order 1
70+
... %seealso func_a, func_b
7171
...
7272
... Parameters
7373
... ----------
@@ -86,20 +86,20 @@ def extract_directives(docstring: str | None) -> DocDirectives:
8686
if not docstring:
8787
return directives
8888

89-
# Extract @family
89+
# Extract %family
9090
if match := DIRECTIVE_PATTERNS["family"].search(docstring):
9191
directives.family = match.group(1).strip()
9292

93-
# Extract @order
93+
# Extract %order
9494
if match := DIRECTIVE_PATTERNS["order"].search(docstring):
9595
directives.order = int(match.group(1))
9696

97-
# Extract @seealso (comma-separated list)
97+
# Extract %seealso (comma-separated list)
9898
if match := DIRECTIVE_PATTERNS["seealso"].search(docstring):
9999
items = [item.strip() for item in match.group(1).split(",")]
100100
directives.seealso = [item for item in items if item]
101101

102-
# Extract @nodoc
102+
# Extract %nodoc
103103
if DIRECTIVE_PATTERNS["nodoc"].search(docstring):
104104
directives.nodoc = True
105105

@@ -122,15 +122,15 @@ def strip_directives(docstring: str | None) -> str:
122122
Returns
123123
-------
124124
str
125-
The docstring with all @directive: lines removed.
125+
The docstring with all %directive lines removed.
126126
127127
Examples
128128
--------
129129
>>> doc = '''
130130
... Short description.
131131
...
132-
... @family: Family Name
133-
... @order: 1
132+
... %family Family Name
133+
... %order 1
134134
...
135135
... Parameters
136136
... ----------
@@ -168,7 +168,7 @@ def has_directives(docstring: str | None) -> bool:
168168
Returns
169169
-------
170170
bool
171-
True if any @directive: pattern is found.
171+
True if any %directive pattern is found.
172172
"""
173173
if not docstring:
174174
return False

great_docs/assets/post-render.py

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -152,29 +152,39 @@ def reformat_signature(match):
152152

153153
def strip_directives_from_html(html_content):
154154
"""
155-
Remove Great Docs @directive: lines from rendered HTML.
155+
Remove Great Docs %directive lines from rendered HTML.
156156
157-
Directives like @family:, @order:, @seealso:, and @nodoc: are used for
157+
Directives like %family, %order, %seealso, and %nodoc are used for
158158
organizing documentation but should not appear in the final rendered output.
159159
This function removes them as a safety net after quartodoc rendering.
160160
"""
161-
# Pattern matches directive lines that may appear in HTML
162-
# They could be plain text, inside <p> tags, or other HTML elements
163-
# Match: optional whitespace, @directive:, value, end of line
164-
directive_pattern = re.compile(
165-
r"^\s*@(?:family|order|seealso|nodoc):\s*.*$\n?",
161+
# Match directives wrapped in <p> tags
162+
# e.g., <p>%family Something</p>
163+
p_directive_pattern = re.compile(
164+
r"<p>\s*%(?:family|order|seealso|nodoc)(?:\s+[^<]*)?\s*</p>\s*\n?",
165+
re.IGNORECASE,
166+
)
167+
168+
# Match standalone directive lines (plain text)
169+
# e.g., %family Something
170+
standalone_directive_pattern = re.compile(
171+
r"^\s*%(?:family|order|seealso|nodoc)(?:\s+.*)?\s*$\n?",
166172
re.MULTILINE | re.IGNORECASE,
167173
)
168174

169-
# Also match directives that got wrapped in <p> tags
170-
# e.g., <p>@family: Something</p>
171-
p_directive_pattern = re.compile(
172-
r"<p>\s*@(?:family|order|seealso|nodoc):\s*[^<]*</p>\s*\n?",
175+
# Match directives that might be inline within text
176+
inline_directive_pattern = re.compile(
177+
r"%(?:family|order|seealso|nodoc)(?:\s+[^\n<]*)?",
173178
re.IGNORECASE,
174179
)
175180

176-
cleaned = directive_pattern.sub("", html_content)
177-
cleaned = p_directive_pattern.sub("", cleaned)
181+
# Apply patterns in order of specificity
182+
cleaned = p_directive_pattern.sub("", html_content)
183+
cleaned = standalone_directive_pattern.sub("", cleaned)
184+
cleaned = inline_directive_pattern.sub("", cleaned)
185+
186+
# Clean up any resulting empty paragraphs
187+
cleaned = re.sub(r"<p>\s*</p>\s*\n?", "", cleaned)
178188

179189
return cleaned
180190

great_docs/cli.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -145,13 +145,13 @@ def preview(project_path, docs_dir):
145145
"--verbose",
146146
"-v",
147147
is_flag=True,
148-
help="Show detailed information including @seealso and @order values",
148+
help="Show detailed information including %seealso and %order values",
149149
)
150150
def scan(project_path, docs_dir, verbose):
151-
"""Scan docstrings for @family directives and preview API organization.
151+
"""Scan docstrings for %family directives and preview API organization.
152152
153-
This command analyzes your package's docstrings to find @family, @order,
154-
@seealso, and @nodoc directives, then shows how the API reference would
153+
This command analyzes your package's docstrings to find %family, %order,
154+
%seealso, and %nodoc directives, then shows how the API reference would
155155
be organized.
156156
157157
Use this to preview your documentation structure before building.
@@ -173,11 +173,11 @@ def scan(project_path, docs_dir, verbose):
173173
directive_map = docs._extract_all_directives(importable_name)
174174

175175
if not directive_map:
176-
click.echo("No @family directives found in docstrings.")
176+
click.echo("No %family directives found in docstrings.")
177177
click.echo("\nTo organize your API documentation, add directives to your docstrings:")
178-
click.echo(" @family: Family Name")
179-
click.echo(" @order: 1")
180-
click.echo(" @seealso: other_func, AnotherClass")
178+
click.echo(" %family Family Name")
179+
click.echo(" %order 1")
180+
click.echo(" %seealso other_func, AnotherClass")
181181
sys.exit(0)
182182

183183
# Group by family
@@ -216,16 +216,16 @@ def scan(project_path, docs_dir, verbose):
216216

217217
click.echo(f"\n {family_name} ({len(items)} item(s)):")
218218
for item in items:
219-
order_str = f" [@order: {item['order']}]" if item["order"] is not None else ""
219+
order_str = f" [%order {item['order']}]" if item["order"] is not None else ""
220220
click.echo(f" • {item['name']}{order_str}")
221221

222222
if verbose and item["seealso"]:
223223
seealso_str = ", ".join(item["seealso"])
224-
click.echo(f" └─ @seealso: {seealso_str}")
224+
click.echo(f" └─ %seealso {seealso_str}")
225225

226226
# Show nodoc items
227227
if nodoc_items:
228-
click.echo(f"\n🚫 Excluded (@nodoc): {len(nodoc_items)} item(s)")
228+
click.echo(f"\n🚫 Excluded (%nodoc): {len(nodoc_items)} item(s)")
229229
if verbose:
230230
for item in sorted(nodoc_items):
231231
click.echo(f" • {item}")

0 commit comments

Comments
 (0)