162 lines
4.8 KiB
Python
162 lines
4.8 KiB
Python
import logging
|
|
import os
|
|
import re
|
|
import subprocess
|
|
from functools import lru_cache
|
|
from http.server import HTTPServer, SimpleHTTPRequestHandler
|
|
from importlib import metadata
|
|
from pathlib import Path
|
|
|
|
import mkdocs.utils
|
|
import typer
|
|
from jinja2 import Template
|
|
|
|
logging.basicConfig(level=logging.INFO)
|
|
|
|
mkdocs_name = "mkdocs.yml"
|
|
en_docs_path = Path("")
|
|
|
|
app = typer.Typer()
|
|
|
|
|
|
@lru_cache
|
|
def is_mkdocs_insiders() -> bool:
|
|
version = metadata.version("mkdocs-material")
|
|
return "insiders" in version
|
|
|
|
|
|
@app.callback()
|
|
def callback() -> None:
|
|
if is_mkdocs_insiders():
|
|
os.environ["INSIDERS_FILE"] = "./mkdocs.insiders.yml"
|
|
# For MacOS with insiders and Cairo
|
|
os.environ["DYLD_FALLBACK_LIBRARY_PATH"] = "/opt/homebrew/lib"
|
|
|
|
|
|
index_sponsors_template = """
|
|
{% if sponsors %}
|
|
{% for sponsor in sponsors.gold -%}
|
|
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}"></a>
|
|
{% endfor -%}
|
|
{%- for sponsor in sponsors.silver -%}
|
|
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}"></a>
|
|
{% endfor %}
|
|
{% endif %}
|
|
"""
|
|
|
|
|
|
def generate_readme_content() -> str:
|
|
en_index = en_docs_path / "docs" / "index.md"
|
|
content = en_index.read_text("utf-8")
|
|
match_pre = re.search(r"</style>\n\n", content)
|
|
match_start = re.search(r"<!-- sponsors -->", content)
|
|
match_end = re.search(r"<!-- /sponsors -->", content)
|
|
sponsors_data_path = en_docs_path / "data" / "sponsors.yml"
|
|
sponsors = mkdocs.utils.yaml_load(sponsors_data_path.read_text(encoding="utf-8"))
|
|
if not (match_start and match_end):
|
|
raise RuntimeError("Couldn't auto-generate sponsors section")
|
|
if not match_pre:
|
|
raise RuntimeError("Couldn't find pre section (<style>) in index.md")
|
|
frontmatter_end = match_pre.end()
|
|
pre_end = match_start.end()
|
|
post_start = match_end.start()
|
|
template = Template(index_sponsors_template)
|
|
message = template.render(sponsors=sponsors)
|
|
pre_content = content[frontmatter_end:pre_end]
|
|
post_content = content[post_start:]
|
|
new_content = pre_content + message + post_content
|
|
# Remove content between <!-- only-mkdocs --> and <!-- /only-mkdocs -->
|
|
new_content = re.sub(
|
|
r"<!-- only-mkdocs -->.*?<!-- /only-mkdocs -->",
|
|
"",
|
|
new_content,
|
|
flags=re.DOTALL,
|
|
)
|
|
return new_content
|
|
|
|
|
|
@app.command()
|
|
def generate_readme() -> None:
|
|
"""
|
|
Generate README.md content from main index.md
|
|
"""
|
|
typer.echo("Generating README")
|
|
readme_path = Path("README.md")
|
|
new_content = generate_readme_content()
|
|
readme_path.write_text(new_content, encoding="utf-8")
|
|
|
|
|
|
@app.command()
|
|
def verify_readme() -> None:
|
|
"""
|
|
Verify README.md content from main index.md
|
|
"""
|
|
typer.echo("Verifying README")
|
|
readme_path = Path("README.md")
|
|
generated_content = generate_readme_content()
|
|
readme_content = readme_path.read_text("utf-8")
|
|
if generated_content != readme_content:
|
|
typer.secho(
|
|
"README.md outdated from the latest index.md", color=typer.colors.RED
|
|
)
|
|
raise typer.Abort()
|
|
typer.echo("Valid README ✅")
|
|
|
|
|
|
@app.command()
|
|
def live(dirty: bool = False) -> None:
|
|
"""
|
|
Serve with livereload a docs site for a specific language.
|
|
|
|
This only shows the actual translated files, not the placeholders created with
|
|
build-all.
|
|
|
|
Takes an optional LANG argument with the name of the language to serve, by default
|
|
en.
|
|
"""
|
|
# Enable line numbers during local development to make it easier to highlight
|
|
args = ["mkdocs", "serve", "--dev-addr", "127.0.0.1:8008"]
|
|
if dirty:
|
|
args.append("--dirty")
|
|
subprocess.run(args, env={**os.environ, "LINENUMS": "true"}, check=True)
|
|
|
|
|
|
@app.command()
|
|
def build() -> None:
|
|
"""
|
|
Build the docs.
|
|
"""
|
|
insiders_env_file = os.environ.get("INSIDERS_FILE")
|
|
print(f"Insiders file {insiders_env_file}")
|
|
if is_mkdocs_insiders():
|
|
print("Using insiders")
|
|
print("Building docs")
|
|
subprocess.run(["mkdocs", "build"], check=True)
|
|
typer.secho("Successfully built docs", color=typer.colors.GREEN)
|
|
|
|
|
|
@app.command()
|
|
def serve() -> None:
|
|
"""
|
|
A quick server to preview a built site.
|
|
|
|
For development, prefer the command live (or just mkdocs serve).
|
|
|
|
This is here only to preview the documentation site.
|
|
|
|
Make sure you run the build command first.
|
|
"""
|
|
typer.echo("Warning: this is a very simple server.")
|
|
typer.echo("For development, use the command live instead.")
|
|
typer.echo("This is here only to preview the documentation site.")
|
|
typer.echo("Make sure you run the build command first.")
|
|
os.chdir("site")
|
|
server_address = ("", 8008)
|
|
server = HTTPServer(server_address, SimpleHTTPRequestHandler)
|
|
typer.echo("Serving at: http://127.0.0.1:8008")
|
|
server.serve_forever()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
app()
|