Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ instance/

# pdoc documentation
/doc
/docusaurus

# PyBuilder
.pybuilder/
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ format_check = "scripts:run_format_check"
lint = "scripts:run_linter"
fix_lint = "scripts:run_linter_fix"
generate_docs = "scripts:generate_docs"
generate_docusaurus = "scripts:generate_docusaurus"
update_client = "scripts:update_client"
room_manager = "scripts:start_room_manager"

Expand Down
82 changes: 80 additions & 2 deletions scripts.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import os
import re
import shutil
import subprocess
import sys
Expand Down Expand Up @@ -55,6 +56,12 @@ def run_linter_fix():


def generate_docs():
here = Path(__file__).parent
input = here / "doc"

if input.exists():
shutil.rmtree(input)

check_exit_code(
"pdoc \
--include-undocumented \
Expand All @@ -64,8 +71,6 @@ def generate_docs():
-o doc \
fishjam"
)
here = Path(__file__).parent
input = here / "doc"
input_images = here / "images"
out = here / "docs" / "api"
out_images = here / "docs" / "api" / "images"
Expand All @@ -81,6 +86,79 @@ def generate_docs():
f.rename(f.with_suffix(".md"))


def clean_mdx_content(content: str) -> str:
parts = re.split(r"(```[\s\S]*?```)", content)

cleaned_parts = []
for part in parts:
if part.startswith("```"):
text = (
part.replace("&lt;", "<")
.replace("&gt;", ">")
.replace("&#39;", "'")
.replace("builtins.", "")
.replace("fishjam.api._client.", "")
.replace("fishjam.api._fishjam_client.", "")
.replace("fishjam.events._protos.fishjam.", "")
.replace("fishjam._openapi_client.models.peer.", "")
.replace("fishjam._openapi_client.models.peer_metadata.", "")
.replace("fishjam._openapi_client.models.peer_status.", "")
.replace("fishjam._openapi_client.models.peer_type.", "")
.replace("fishjam._openapi_client.models.room_config.", "")
.replace("fishjam._openapi_client.models.room_config_room_type.", "")
.replace("fishjam._openapi_client.models.room_config_video_codec.", "")
.replace("fishjam._openapi_client.models.subscriptions.", "")
.replace("fishjam._openapi_client.models.subscribe_mode.", "")
.replace("fishjam._openapi_client.models.track.", "")
.replace("fishjam._openapi_client.types.", "")
)
cleaned_parts.append(text)
else:
text = part.replace("{", "\\{").replace("}", "\\}")
cleaned_parts.append(text)

return "".join(cleaned_parts)


def generate_docusaurus():
here = Path(__file__).parent
input = here / "doc"
out = here / "docusaurus"

if input.exists():
shutil.rmtree(input)
if out.exists():
shutil.rmtree(out)

check_exit_code(
"pdoc \
--include-undocumented \
-t templates/docusaurus \
-o doc \
fishjam"
)
try:
os.remove(input / "index.html")
except FileNotFoundError:
pass

out.mkdir(parents=True, exist_ok=True)

for f in input.glob("**/*.html"):
content = f.read_text(encoding="utf-8")
safe_content = clean_mdx_content(content)
rel_path = f.relative_to(input)
dest_path = out / rel_path.with_suffix(".md")
dest_path.parent.mkdir(parents=True, exist_ok=True)

dest_path.write_text(safe_content, encoding="utf-8")

fishjam_dir = out / "fishjam"
submodules_dir = out / "submodules"

fishjam_dir.rename(submodules_dir)


def update_client():
if len(sys.argv) < 2:
raise RuntimeError("Missing fishjam openapi.yaml raw url positional argument")
Expand Down
7 changes: 7 additions & 0 deletions templates/docusaurus/frame.html.jinja2
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
title: {{ module.name }}
sidebar_label: {{ module.name.split(".")[-1] }}
custom_edit_url: null
---

{% block content %}{% endblock %}
144 changes: 144 additions & 0 deletions templates/docusaurus/module.html.jinja2
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
{% extends "frame.html.jinja2" %}

{% block content %}
# {{ module.name }}

{% block module_info %}
{% if module.docstring and ".. include::" not in module.docstring %}
{{ module.docstring | safe }}
{% endif %}
{% endblock %}

{% block nav_submodules %}
{% if module.submodules %}
## Submodules
{% for submodule in module.submodules if is_public(submodule) | trim %}
- [{{ submodule.name }}](submodules/{{ submodule.name }})
{% endfor %}
{% endif %}
{% endblock %}

{% block module_contents %}
{% for m in module.flattened_own_members if is_public(m) | trim %}
## {{ m.name }}
{{ member(m) }}
{% if m.kind == "class" %}
{% for cm in m.own_members if cm.kind != "class" and is_public(cm) | trim %}
### {{ cm.name }}
{{ member(cm) }}
{% endfor %}
{% set inherited_members = inherited(m) | trim %}
{% if inherited_members %}
#### Inherited Members
{{ inherited_members }}
{% endif %}
{% endif %}
---
{% endfor %}
{% endblock %}
{% endblock content %}

{#
=========================================================================
HELPER MACROS (Markdown Version)
=========================================================================
#}

{% defaultmacro default_value(var) -%}
{% if var.default_value_str and "object object" not in var.default_value_str %}
= {{ var.default_value_str | safe }}
{% endif %}
{% enddefaultmacro %}

{% defaultmacro annotation(var) %}
{% if var.annotation_str %}{{ var.annotation_str }}{% endif %}
{% enddefaultmacro %}

{% defaultmacro function(fn) -%}
{% if fn.name == "__init__" %}
def {{ fn.qualname.split(".")[-1] }}{{ fn.signature_without_self | string | safe }}
{% else %}
def {{ fn.name }}{{ fn.signature | string | safe }}
{% endif %}
{% enddefaultmacro %}

{% defaultmacro variable(var) -%}
{{ var.name }}{{ annotation(var) }}{{ default_value(var) }}
{% enddefaultmacro %}

{% defaultmacro class_bases(cls) %}
{%- if cls.bases -%}
(
{%- for base in cls.bases -%}
{%- if base is mapping or base is iterable and base is not string -%}
{{ base[-1] }}
{%- else -%}
{{ base }}
{%- endif -%}
{%- if loop.nextitem %}, {% endif %}
{%- endfor -%}
)
{%- endif -%}
{% enddefaultmacro %}

{% defaultmacro class(cls) -%}
class {{ cls.qualname }}{{ class_bases(cls) }}:
{% enddefaultmacro %}

{% defaultmacro member(doc) %}
```python
{% if doc.kind == "class" %}{{ class(doc) }}{% elif doc.kind == "function" %}{{ function(doc) }}{% else %}{{ variable(doc) }}{% endif %}
```
{{ doc.docstring | safe }}
{% enddefaultmacro %}

{% defaultmacro is_public(doc) %}
{% if not include_undocumented and not doc.docstring %}
{% elif doc.docstring and "@private" in doc.docstring %}
{% elif doc.name == "__init__" and (doc.docstring or (doc.kind == "function" and doc.signature_without_self.parameters)) %}
true
{% elif doc.name == "__doc__" %}
{% elif doc.kind == "variable" and doc.is_typevar and not doc.docstring %}
{% elif doc.kind == "module" and doc.fullname not in all_modules %}
{% elif (doc.qualname or doc.name) is in(module.obj.__all__ or []) %}
true
{% elif not doc.name.startswith("_") %}
true
{% endif %}
{% enddefaultmacro %}

{% defaultmacro inherited(cls) %}
{% set ignored_bases = ["str", "object", "int", "float", "bool", "list", "dict", "tuple", "set", "exception", "baseexception"] %}
{% for base, members in cls.inherited_members.items() %}
{% set base_name = base.name if base.name is defined else base %}
{% if base_name is mapping or base_name is iterable and base_name is not string %}
{% set base_name = base_name[-1] %}
{% endif %}

{% if base_name | lower not in ignored_bases %}

{% set member_list %}
{% for m in members if is_public(m) | trim %}
* `{{ m.name }}`
{% endfor %}
{% endset %}

{% if member_list | trim %}
* **{{ base_name }}**:
{{ member_list }}
{% endif %}

{% endif %}
{% endfor %}
{% enddefaultmacro %}

{# Empty macros to prevent errors from unused calls in default logic #}
{% defaultmacro bases(cls) %}{% enddefaultmacro %}
{% defaultmacro decorators(doc) %}{% enddefaultmacro %}
{% defaultmacro submodule(mod) %}{% enddefaultmacro %}
{% defaultmacro docstring(var) %}{% enddefaultmacro %}
{% defaultmacro nav_members(members) %}{% enddefaultmacro %}
{% defaultmacro view_source_state(doc) %}{% enddefaultmacro %}
{% defaultmacro view_source_button(doc) %}{% enddefaultmacro %}
{% defaultmacro view_source_code(doc) %}{% enddefaultmacro %}
{% defaultmacro module_name() %}{% enddefaultmacro %}
2 changes: 2 additions & 0 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading