feat: add buildmanual target, faker demo, subprocess examples, and contributing sidebar to manual
Add Makefile buildmanual target for manual generation and include faker_demo.wren, subprocess_async_demo.wren, subprocess_concurrent_demo.wren, and subprocess_fiber_demo.wren example scripts. Update manual sidebar across api pages to link new web-server tutorial and contributing section with module architecture, pure-wren/c-backed modules, foreign classes, async patterns, testing, and documentation pages.
This commit is contained in:
Executable
+115
@@ -0,0 +1,115 @@
|
||||
#!/usr/bin/env python3
|
||||
# retoor <retoor@molodetz.nl>
|
||||
|
||||
import json
|
||||
import re
|
||||
import shutil
|
||||
import yaml
|
||||
from pathlib import Path
|
||||
from jinja2 import Environment, FileSystemLoader, ChoiceLoader
|
||||
|
||||
|
||||
class ManualBuilder:
|
||||
def __init__(self):
|
||||
self.root = Path(__file__).parent.parent
|
||||
self.src = self.root / 'manual_src'
|
||||
self.output = self.root / 'bin' / 'manual'
|
||||
self.site = self.load_yaml('data/site.yaml')
|
||||
self.nav = self.load_yaml('data/navigation.yaml')
|
||||
|
||||
templates_loader = FileSystemLoader(str(self.src / 'templates'))
|
||||
pages_loader = FileSystemLoader(str(self.src))
|
||||
|
||||
self.env = Environment(
|
||||
loader=ChoiceLoader([templates_loader, pages_loader]),
|
||||
trim_blocks=True,
|
||||
lstrip_blocks=True
|
||||
)
|
||||
|
||||
self.env.globals.update({
|
||||
'site': self.site,
|
||||
'nav': self.nav
|
||||
})
|
||||
|
||||
def load_yaml(self, path):
|
||||
with open(self.src / path) as f:
|
||||
return yaml.safe_load(f)
|
||||
|
||||
def build(self):
|
||||
if self.output.exists():
|
||||
shutil.rmtree(self.output)
|
||||
self.output.mkdir(parents=True)
|
||||
|
||||
search_index = self.build_search_index()
|
||||
self.env.globals['search_index_json'] = json.dumps(search_index)
|
||||
|
||||
self.build_pages()
|
||||
self.copy_static()
|
||||
|
||||
print(f"Built manual to {self.output}")
|
||||
|
||||
def build_pages(self):
|
||||
pages_dir = self.src / 'pages'
|
||||
for html_file in pages_dir.rglob('*.html'):
|
||||
rel_path = html_file.relative_to(pages_dir)
|
||||
self.build_page(html_file, rel_path)
|
||||
|
||||
def build_page(self, src_path, rel_path):
|
||||
template_path = f'pages/{rel_path}'
|
||||
template = self.env.get_template(template_path)
|
||||
|
||||
depth = len(rel_path.parts) - 1
|
||||
static_prefix = '../' * depth if depth > 0 else './'
|
||||
|
||||
html = template.render(
|
||||
current_path=str(rel_path),
|
||||
static_prefix=static_prefix,
|
||||
depth=depth
|
||||
)
|
||||
|
||||
out_path = self.output / rel_path
|
||||
out_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
out_path.write_text(html)
|
||||
print(f" {rel_path}")
|
||||
|
||||
def copy_static(self):
|
||||
static_src = self.src / 'static'
|
||||
for item in static_src.rglob('*'):
|
||||
if item.is_file():
|
||||
rel = item.relative_to(static_src)
|
||||
dest = self.output / rel
|
||||
dest.parent.mkdir(parents=True, exist_ok=True)
|
||||
shutil.copy2(item, dest)
|
||||
|
||||
def build_search_index(self):
|
||||
index = {'pages': []}
|
||||
|
||||
for section in self.nav['sections']:
|
||||
section_title = section['title']
|
||||
section_dir = section['directory']
|
||||
|
||||
for page in section.get('pages', []):
|
||||
url = f"{section_dir}/{page['file']}.html"
|
||||
index['pages'].append({
|
||||
'url': url,
|
||||
'title': page['title'],
|
||||
'section': section_title,
|
||||
'description': page.get('description', ''),
|
||||
'methods': page.get('methods', []),
|
||||
'content': ''
|
||||
})
|
||||
|
||||
(self.output / 'search-index.json').write_text(
|
||||
json.dumps(index, indent=2)
|
||||
)
|
||||
|
||||
return index
|
||||
|
||||
|
||||
def main():
|
||||
builder = ManualBuilder()
|
||||
builder.build()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in New Issue
Block a user