bst-docs 0.0.2__tar.gz → 0.0.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {bst_docs-0.0.2 → bst_docs-0.0.3}/LICENSE +0 -1
- {bst_docs-0.0.2 → bst_docs-0.0.3}/PKG-INFO +1 -1
- {bst_docs-0.0.2 → bst_docs-0.0.3}/bst_docs/build.py +23 -2
- {bst_docs-0.0.2 → bst_docs-0.0.3}/bst_docs/element.py +36 -27
- bst_docs-0.0.3/bst_docs/render.py +115 -0
- {bst_docs-0.0.2 → bst_docs-0.0.3}/bst_docs.egg-info/PKG-INFO +1 -1
- {bst_docs-0.0.2 → bst_docs-0.0.3}/pyproject.toml +1 -1
- bst_docs-0.0.2/bst_docs/render.py +0 -87
- {bst_docs-0.0.2 → bst_docs-0.0.3}/README.md +0 -0
- {bst_docs-0.0.2 → bst_docs-0.0.3}/bst_docs/__init__.py +0 -0
- {bst_docs-0.0.2 → bst_docs-0.0.3}/bst_docs/__main__.py +0 -0
- {bst_docs-0.0.2 → bst_docs-0.0.3}/bst_docs/load_contents.py +0 -0
- {bst_docs-0.0.2 → bst_docs-0.0.3}/bst_docs.egg-info/SOURCES.txt +0 -0
- {bst_docs-0.0.2 → bst_docs-0.0.3}/bst_docs.egg-info/dependency_links.txt +0 -0
- {bst_docs-0.0.2 → bst_docs-0.0.3}/bst_docs.egg-info/entry_points.txt +0 -0
- {bst_docs-0.0.2 → bst_docs-0.0.3}/bst_docs.egg-info/requires.txt +0 -0
- {bst_docs-0.0.2 → bst_docs-0.0.3}/bst_docs.egg-info/top_level.txt +0 -0
- {bst_docs-0.0.2 → bst_docs-0.0.3}/setup.cfg +0 -0
|
@@ -5,4 +5,3 @@ Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
|
5
5
|
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
6
6
|
|
|
7
7
|
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
8
|
-
|
|
@@ -8,6 +8,7 @@ import click
|
|
|
8
8
|
import tqdm
|
|
9
9
|
|
|
10
10
|
from bst_docs.load_contents import load_project
|
|
11
|
+
from bst_docs.render import RenderConfig
|
|
11
12
|
|
|
12
13
|
|
|
13
14
|
@click.command()
|
|
@@ -38,6 +39,24 @@ from bst_docs.load_contents import load_project
|
|
|
38
39
|
" otherwise pure Commonmark markdown will be used"
|
|
39
40
|
),
|
|
40
41
|
)
|
|
42
|
+
@click.option(
|
|
43
|
+
"--html-links",
|
|
44
|
+
default=False,
|
|
45
|
+
required=False,
|
|
46
|
+
help=(
|
|
47
|
+
"If true, markdown link extensions will be converted to .html"
|
|
48
|
+
" and html elements will be enabled"
|
|
49
|
+
),
|
|
50
|
+
)
|
|
51
|
+
@click.option(
|
|
52
|
+
"--all-html-fixes",
|
|
53
|
+
default=False,
|
|
54
|
+
required=False,
|
|
55
|
+
help=(
|
|
56
|
+
"If true, all html level fixes will be applied"
|
|
57
|
+
" This is designed for when html rendering will be done after the fact"
|
|
58
|
+
),
|
|
59
|
+
)
|
|
41
60
|
@click.argument("path", default=".")
|
|
42
61
|
def build(
|
|
43
62
|
path: str,
|
|
@@ -45,7 +64,9 @@ def build(
|
|
|
45
64
|
**kwargs: str,
|
|
46
65
|
) -> None:
|
|
47
66
|
"""Generate documentation for a BuildStream project."""
|
|
48
|
-
|
|
67
|
+
config = RenderConfig(
|
|
68
|
+
**kwargs,
|
|
69
|
+
)
|
|
49
70
|
|
|
50
71
|
if kwargs.get("clean"):
|
|
51
72
|
shutil.rmtree(".cache")
|
|
@@ -70,7 +91,7 @@ def build(
|
|
|
70
91
|
except StopIteration:
|
|
71
92
|
logging.warning(str(f"Unfound dependency {dep} for {f.name}"))
|
|
72
93
|
for f in tqdm.tqdm(files, "Writing Output"):
|
|
73
|
-
f.write_file(dst,
|
|
94
|
+
f.write_file(dst, config=config)
|
|
74
95
|
|
|
75
96
|
|
|
76
97
|
if __name__ == "__main__":
|
|
@@ -8,7 +8,12 @@ from pathlib import Path
|
|
|
8
8
|
|
|
9
9
|
import mdformat
|
|
10
10
|
|
|
11
|
-
from bst_docs.render import
|
|
11
|
+
from bst_docs.render import (
|
|
12
|
+
RenderConfig,
|
|
13
|
+
add_summary_block,
|
|
14
|
+
render_code_section,
|
|
15
|
+
render_value,
|
|
16
|
+
)
|
|
12
17
|
|
|
13
18
|
|
|
14
19
|
# TODO: replace this with builstream element
|
|
@@ -71,7 +76,7 @@ class Element:
|
|
|
71
76
|
def _format_link_list(
|
|
72
77
|
self,
|
|
73
78
|
depend_kind: str,
|
|
74
|
-
|
|
79
|
+
config: RenderConfig,
|
|
75
80
|
depends_dict: dict,
|
|
76
81
|
) -> str:
|
|
77
82
|
"""Format a dependency list as HTML or Markdown links."""
|
|
@@ -79,6 +84,8 @@ class Element:
|
|
|
79
84
|
if not depend_items:
|
|
80
85
|
return ""
|
|
81
86
|
|
|
87
|
+
link_ext = ".html" if config.use_html_exts else ".md"
|
|
88
|
+
|
|
82
89
|
link_list = []
|
|
83
90
|
for item in depend_items:
|
|
84
91
|
rendered = ""
|
|
@@ -88,25 +95,27 @@ class Element:
|
|
|
88
95
|
rel_path = os.path.relpath(
|
|
89
96
|
(self.element_base / item),
|
|
90
97
|
self.absolute_path.parent,
|
|
91
|
-
).replace(".bst",
|
|
98
|
+
).replace(".bst", link_ext)
|
|
92
99
|
rendered = (
|
|
93
100
|
(
|
|
94
101
|
f'<a href="{rel_path}">{item}</a>'
|
|
95
|
-
if use_html
|
|
102
|
+
if config.use_html
|
|
96
103
|
else f"[{item}]({rel_path})"
|
|
97
104
|
)
|
|
98
105
|
if ":" not in item
|
|
99
|
-
else render_value(item)
|
|
106
|
+
else render_value(item, config)
|
|
100
107
|
)
|
|
101
108
|
case _others:
|
|
102
|
-
rendered = render_value(item)
|
|
103
|
-
link_list.append(
|
|
109
|
+
rendered = render_value(item, config)
|
|
110
|
+
link_list.append(
|
|
111
|
+
f"<li>{rendered}</li>" if config.use_html else f"- {rendered}",
|
|
112
|
+
)
|
|
104
113
|
content = (
|
|
105
114
|
f"<ul>\n{'\n'.join(link_list)}\n<ul>" # no hard tabs
|
|
106
|
-
if use_html
|
|
115
|
+
if config.use_html
|
|
107
116
|
else "\n".join(link_list)
|
|
108
117
|
)
|
|
109
|
-
return add_summary_block(depend_kind.title(), content,
|
|
118
|
+
return add_summary_block(depend_kind.title(), content, config)
|
|
110
119
|
|
|
111
120
|
def all_dependencies(self) -> dict[str, list]:
|
|
112
121
|
"""All dependencies of this element."""
|
|
@@ -115,16 +124,16 @@ class Element:
|
|
|
115
124
|
output[depend_kind] = self._conf.get(depend_kind, [])
|
|
116
125
|
return output
|
|
117
126
|
|
|
118
|
-
def _render_field(self, element: str,
|
|
127
|
+
def _render_field(self, element: str, config: RenderConfig) -> str:
|
|
119
128
|
"""Render a named configuration field as a section."""
|
|
120
129
|
return (
|
|
121
130
|
f"## {element.title()}\n\n"
|
|
122
|
-
+ render_value(self._conf.get(element, {}),
|
|
131
|
+
+ render_value(self._conf.get(element, {}), config)
|
|
123
132
|
if self._conf.get(element, {})
|
|
124
133
|
else ""
|
|
125
134
|
)
|
|
126
135
|
|
|
127
|
-
def summary_page(self,
|
|
136
|
+
def summary_page(self, config: RenderConfig) -> str:
|
|
128
137
|
"""Generate the full summary page content for this element."""
|
|
129
138
|
return f"""
|
|
130
139
|
# {Path(self.name).name}
|
|
@@ -134,33 +143,33 @@ class Element:
|
|
|
134
143
|
|
|
135
144
|
## Dependencies
|
|
136
145
|
|
|
137
|
-
{self._format_link_list("depends",
|
|
138
|
-
{self._format_link_list("build-depends",
|
|
139
|
-
{self._format_link_list("runtime-depends",
|
|
146
|
+
{self._format_link_list("depends", config, self._conf)}
|
|
147
|
+
{self._format_link_list("build-depends", config, self._conf)}
|
|
148
|
+
{self._format_link_list("runtime-depends", config, self._conf)}
|
|
140
149
|
|
|
141
150
|
## Dependants
|
|
142
|
-
{self._format_link_list("depends",
|
|
143
|
-
{self._format_link_list("build-depends",
|
|
144
|
-
{self._format_link_list("runtime-depends",
|
|
151
|
+
{self._format_link_list("depends", config, self.dependants)}
|
|
152
|
+
{self._format_link_list("build-depends", config, self.dependants)}
|
|
153
|
+
{self._format_link_list("runtime-depends", config, self.dependants)}
|
|
145
154
|
|
|
146
|
-
{self._render_field("variables",
|
|
147
|
-
{self._render_field("environment",
|
|
148
|
-
{self._render_field("environment-nocache",
|
|
149
|
-
{self._render_field("config",
|
|
150
|
-
{self._render_field("public",
|
|
151
|
-
{self._render_field("sources",
|
|
155
|
+
{self._render_field("variables", config)}
|
|
156
|
+
{self._render_field("environment", config)}
|
|
157
|
+
{self._render_field("environment-nocache", config)}
|
|
158
|
+
{self._render_field("config", config)}
|
|
159
|
+
{self._render_field("public", config)}
|
|
160
|
+
{self._render_field("sources", config)}
|
|
152
161
|
|
|
153
162
|
## Raw Content
|
|
154
163
|
|
|
155
|
-
{add_summary_block("Raw Text", render_code_section(self.raw,
|
|
164
|
+
{add_summary_block("Raw Text", render_code_section(self.raw, config), config)}
|
|
156
165
|
|
|
157
166
|
"""
|
|
158
167
|
|
|
159
|
-
def write_file(self, parent: Path,
|
|
168
|
+
def write_file(self, parent: Path, config: RenderConfig) -> None:
|
|
160
169
|
"""Write the rendered summary page to disk."""
|
|
161
170
|
dst = parent / self.doc_path
|
|
162
171
|
dst.parent.mkdir(parents=True, exist_ok=True)
|
|
163
|
-
text = self.summary_page(
|
|
172
|
+
text = self.summary_page(config)
|
|
164
173
|
text = mdformat.text(text).replace("\t", " ")
|
|
165
174
|
dst.write_text(text)
|
|
166
175
|
logging.debug("Logged element % to %", self.name, dst)
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"""Rendering utilities for HTML and Markdown output."""
|
|
2
|
+
|
|
3
|
+
import dataclasses
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@dataclasses.dataclass
|
|
8
|
+
class RenderConfig:
|
|
9
|
+
"""Configuration for rendering output."""
|
|
10
|
+
|
|
11
|
+
all_html_fixes: bool
|
|
12
|
+
use_html: bool
|
|
13
|
+
use_html_exts: bool
|
|
14
|
+
|
|
15
|
+
def __init__(self, **kwargs: str) -> None:
|
|
16
|
+
"""Initialize RenderConfig."""
|
|
17
|
+
self.all_html_fixes = bool(kwargs.get("all-html-fixes", False))
|
|
18
|
+
self.use_html_exts = self.all_html_fixes or bool(
|
|
19
|
+
kwargs.get("use-html-exts", False),
|
|
20
|
+
)
|
|
21
|
+
self.use_html = self.all_html_fixes or bool(
|
|
22
|
+
kwargs.get("html-elements", False),
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def html_ul_from_list(list_obj: list, config: RenderConfig) -> str:
|
|
27
|
+
"""Render a list as an HTML unordered list."""
|
|
28
|
+
return f"""
|
|
29
|
+
<ul>
|
|
30
|
+
{"\n".join(f"<li>{render_value(x, config)}</li>" for x in list_obj)}
|
|
31
|
+
</ul>
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def html_br_from_list(list_obj: list, config: RenderConfig) -> str:
|
|
36
|
+
"""Render a list with HTML line breaks."""
|
|
37
|
+
return f"""
|
|
38
|
+
{"\n<br />".join(render_value(x, config) for x in list_obj)}
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def html_table_from_dict(d: dict, config: RenderConfig) -> str:
|
|
43
|
+
"""Render a dictionary as an HTML table."""
|
|
44
|
+
table_elements: str = "\n".join(
|
|
45
|
+
f"<tr><td>{key}</td><td>{render_value(val, config)}</td></tr>"
|
|
46
|
+
for key, val in d.items()
|
|
47
|
+
)
|
|
48
|
+
return f"""
|
|
49
|
+
<table>
|
|
50
|
+
{table_elements}
|
|
51
|
+
</table>
|
|
52
|
+
"""
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def md_table_from_dict(d: dict) -> str:
|
|
56
|
+
"""Render a dictionary as a Markdown table."""
|
|
57
|
+
return f"""
|
|
58
|
+
| | |
|
|
59
|
+
|--|--|
|
|
60
|
+
{"\n".join(f"|{key}|{val!s}|" for key, val in d.items())}
|
|
61
|
+
"""
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def render_value(
|
|
65
|
+
v: Any, # noqa: ANN401
|
|
66
|
+
config: RenderConfig,
|
|
67
|
+
) -> str:
|
|
68
|
+
"""Render a value (dict, list, or scalar) as HTML or Markdown."""
|
|
69
|
+
out = ""
|
|
70
|
+
match v:
|
|
71
|
+
case dict():
|
|
72
|
+
out = (
|
|
73
|
+
html_table_from_dict(v, config)
|
|
74
|
+
if config.use_html
|
|
75
|
+
else md_table_from_dict(v)
|
|
76
|
+
)
|
|
77
|
+
case list() | set():
|
|
78
|
+
out = (
|
|
79
|
+
(
|
|
80
|
+
html_ul_from_list(v, config)
|
|
81
|
+
if v and not isinstance(v[0], dict)
|
|
82
|
+
else html_br_from_list(v, config)
|
|
83
|
+
)
|
|
84
|
+
if config.use_html
|
|
85
|
+
else "\n- ".join(render_value(x, config) for x in v)
|
|
86
|
+
)
|
|
87
|
+
case _others:
|
|
88
|
+
out = (
|
|
89
|
+
f"<code>{str(v).strip().replace('\n', '</br>')}</code>"
|
|
90
|
+
if config.use_html
|
|
91
|
+
else f"`{str(v).strip()}`"
|
|
92
|
+
)
|
|
93
|
+
return out
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def add_summary_block(summary: str, content: str, config: RenderConfig) -> str:
|
|
97
|
+
"""Wrap content in an HTML details/summary block or plain text."""
|
|
98
|
+
if not config.use_html:
|
|
99
|
+
return summary + "\n" + content
|
|
100
|
+
return f"""
|
|
101
|
+
<details open>
|
|
102
|
+
<summary>{summary}</summary>
|
|
103
|
+
{content}
|
|
104
|
+
</details>
|
|
105
|
+
"""
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def render_code_section(content: str, config: RenderConfig) -> str:
|
|
109
|
+
"""Render a multiline code block."""
|
|
110
|
+
output = content
|
|
111
|
+
if config.use_html:
|
|
112
|
+
output = f"<pre><code>{content}</code></pre>"
|
|
113
|
+
else:
|
|
114
|
+
output = f"```\n{content.replace('```', r'\`\`\`')}\n```"
|
|
115
|
+
return output
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
"""Rendering utilities for HTML and Markdown output."""
|
|
2
|
-
|
|
3
|
-
from typing import Any
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
def html_ul_from_list(list_obj: list) -> str:
|
|
7
|
-
"""Render a list as an HTML unordered list."""
|
|
8
|
-
return f"""
|
|
9
|
-
<ul>
|
|
10
|
-
{"\n".join(f"<li>{render_value(x)}</li>" for x in list_obj)}
|
|
11
|
-
</ul>
|
|
12
|
-
"""
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
def html_br_from_list(list_obj: list) -> str:
|
|
16
|
-
"""Render a list with HTML line breaks."""
|
|
17
|
-
return f"""
|
|
18
|
-
{"\n<br />".join(render_value(x, True) for x in list_obj)}
|
|
19
|
-
"""
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
def html_table_from_dict(d: dict) -> str:
|
|
23
|
-
"""Render a dictionary as an HTML table."""
|
|
24
|
-
table_elements: str = "\n".join(
|
|
25
|
-
f"<tr><td>{key}</td><td>{render_value(val)}</td></tr>" for key, val in d.items()
|
|
26
|
-
)
|
|
27
|
-
return f"""
|
|
28
|
-
<table>
|
|
29
|
-
{table_elements}
|
|
30
|
-
</table>
|
|
31
|
-
"""
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
def md_table_from_dict(d: dict) -> str:
|
|
35
|
-
"""Render a dictionary as a Markdown table."""
|
|
36
|
-
return f"""
|
|
37
|
-
| | |
|
|
38
|
-
|--|--|
|
|
39
|
-
{"\n".join(f"|{key}|{val!s}|" for key, val in d.items())}
|
|
40
|
-
"""
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
def render_value(v: Any, use_html: bool = True) -> str: # noqa: ANN401
|
|
44
|
-
"""Render a value (dict, list, or scalar) as HTML or Markdown."""
|
|
45
|
-
out = ""
|
|
46
|
-
match v:
|
|
47
|
-
case dict():
|
|
48
|
-
out = html_table_from_dict(v) if use_html else md_table_from_dict(v)
|
|
49
|
-
case list() | set():
|
|
50
|
-
out = (
|
|
51
|
-
(
|
|
52
|
-
html_ul_from_list(v)
|
|
53
|
-
if v and not isinstance(v[0], dict)
|
|
54
|
-
else html_br_from_list(v)
|
|
55
|
-
)
|
|
56
|
-
if use_html
|
|
57
|
-
else "\n- ".join(render_value(x, use_html) for x in v)
|
|
58
|
-
)
|
|
59
|
-
case _others:
|
|
60
|
-
out = (
|
|
61
|
-
f"<code>{str(v).strip().replace('\n', '</br>')}</code>"
|
|
62
|
-
if use_html
|
|
63
|
-
else f"`{str(v).strip()}`"
|
|
64
|
-
)
|
|
65
|
-
return out
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
def add_summary_block(summary: str, content: str, use_html: bool) -> str:
|
|
69
|
-
"""Wrap content in an HTML details/summary block or plain text."""
|
|
70
|
-
if not use_html:
|
|
71
|
-
return summary + "\n" + content
|
|
72
|
-
return f"""
|
|
73
|
-
<details>
|
|
74
|
-
<summary>{summary}</summary>
|
|
75
|
-
{content}
|
|
76
|
-
</details>
|
|
77
|
-
"""
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
def render_code_section(content: str, use_html: bool) -> str:
|
|
81
|
-
"""Render a multiline code block."""
|
|
82
|
-
output = content
|
|
83
|
-
if use_html:
|
|
84
|
-
output = f"<pre><code>{content}</code></pre>"
|
|
85
|
-
else:
|
|
86
|
-
output = f"```\n{content.replace('```', r'\`\`\`')}\n```"
|
|
87
|
-
return output
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|