mirror of
https://github.com/elyby/docs.git
synced 2024-12-23 13:39:58 +05:30
5cebcf8abe
- removed all translations and used Russian as the base language - integrated crowdin - new multilang site layout - upgraded sphinx - fixed search, now it correctly handles articles language
170 lines
5.7 KiB
Python
Executable File
170 lines
5.7 KiB
Python
Executable File
#!/usr/bin/env python
|
|
|
|
import os
|
|
import re
|
|
import shutil
|
|
import subprocess
|
|
import sys
|
|
|
|
from glob import glob
|
|
from pathlib import Path
|
|
from lxml import html, etree
|
|
|
|
base_lang: str = "ru"
|
|
build_dir: str = "build"
|
|
per_lang_static: list[str] = [
|
|
r"documentation_options\.js",
|
|
r"language_data\.js",
|
|
r"^(?!basic)\w+-stemmer\.js",
|
|
r"translations\.js",
|
|
]
|
|
|
|
# Cleanup
|
|
shutil.rmtree(build_dir, True)
|
|
os.mkdir(build_dir)
|
|
|
|
# Build languages
|
|
def sphinx_build(lang: str) -> None:
|
|
subprocess.run([
|
|
sys.executable, "-m", "sphinx",
|
|
"-b", "html",
|
|
"-D", f"language={lang}",
|
|
"source",
|
|
f"{build_dir}/{lang}",
|
|
])
|
|
|
|
languages: list[str] = [base_lang]
|
|
if os.path.isdir("locale"):
|
|
languages += os.listdir("locale")
|
|
|
|
index_page_lang: str = "en" if "en" in languages else base_lang
|
|
|
|
for lang in languages:
|
|
sphinx_build(lang)
|
|
|
|
# Extract common assets
|
|
for i, lang in enumerate(languages):
|
|
if i == 0:
|
|
os.rename(f"{build_dir}/{lang}/_downloads", f"{build_dir}/_downloads")
|
|
os.rename(f"{build_dir}/{lang}/_images", f"{build_dir}/_images")
|
|
os.rename(f"{build_dir}/{lang}/CNAME", f"{build_dir}/CNAME")
|
|
os.rename(f"{build_dir}/{lang}/.nojekyll", f"{build_dir}/.nojekyll")
|
|
else:
|
|
shutil.rmtree(f"{build_dir}/{lang}/_downloads")
|
|
shutil.rmtree(f"{build_dir}/{lang}/_images")
|
|
os.remove(f"{build_dir}/{lang}/CNAME")
|
|
os.remove(f"{build_dir}/{lang}/.nojekyll")
|
|
|
|
for static_file in glob(f"{build_dir}/{lang}/_static/**/*", recursive=True):
|
|
if not os.path.isfile(static_file):
|
|
continue
|
|
|
|
relative_path = static_file.removeprefix(f"{build_dir}/{lang}/_static/")
|
|
matched: bool = False
|
|
for pattern in per_lang_static:
|
|
if re.match(pattern, relative_path):
|
|
matched = True
|
|
break
|
|
|
|
# I have no idea how to make "continue 2" from the loop above so...
|
|
if matched:
|
|
continue
|
|
|
|
dir = os.path.dirname(relative_path)
|
|
os.makedirs(f"{build_dir}/_static/{dir}", exist_ok=True)
|
|
os.rename(static_file, f"{build_dir}/_static/{relative_path}")
|
|
|
|
shutil.rmtree(f"{build_dir}/{lang}/_sources")
|
|
shutil.rmtree(f"{build_dir}/{lang}/.doctrees")
|
|
os.remove(f"{build_dir}/{lang}/.buildinfo")
|
|
os.remove(f"{build_dir}/{lang}/objects.inv")
|
|
|
|
# Convert all relative routes into absolute
|
|
def make_links_absolute(file_path: str, link: str) -> str:
|
|
# Skip local anchor links
|
|
if link.startswith("#"):
|
|
return link
|
|
|
|
# Skip external links (including links without protocol "//ely.by")
|
|
if link.startswith("//") or re.match(r"^https?://", link):
|
|
return link
|
|
|
|
if ".html" in link:
|
|
working_directory = os.getcwd()
|
|
os.chdir(Path(file_path).parent.absolute())
|
|
resolved = str(Path(link).resolve())
|
|
os.chdir(working_directory)
|
|
|
|
link = resolved.removeprefix(f"{working_directory}/{build_dir}")
|
|
link = link.replace("\\", "/") # fix for the Windows
|
|
|
|
return link
|
|
|
|
# Other links are links to some static assets
|
|
# There is no need to resolve relative links since _static is placed in the root directory,
|
|
# so after removing all ../ parts we can safely append / to make the path absolute
|
|
while link.startswith("../"):
|
|
link = link.removeprefix("../")
|
|
|
|
no_static_link = link.removeprefix("_static/")
|
|
for pattern in per_lang_static:
|
|
if re.match(pattern, no_static_link):
|
|
lang = re.match(fr"^{build_dir}/(\w+)/", file_path).group(1)
|
|
|
|
return f"/{lang}/{link}"
|
|
|
|
return f"/{link}"
|
|
|
|
for file in glob(f"{build_dir}/**/*.html", recursive=True):
|
|
tree = html.parse(file) # type: etree._ElementTree
|
|
root = tree.getroot() # type: html.HtmlElement
|
|
|
|
root.rewrite_links(lambda link: make_links_absolute(file, link))
|
|
|
|
tree.write(file, method="html", encoding="UTF-8")
|
|
|
|
# Create index.html for the site root
|
|
shutil.copyfile(f"{build_dir}/{index_page_lang}/index.html", f"{build_dir}/index.html")
|
|
index_file_tree = html.parse(f"{build_dir}/index.html") # type: etree._ElementTree
|
|
index_file_root = index_file_tree.getroot() # type: html.HtmlElement
|
|
index_file_last_toctree = index_file_root.find_class("toctree-wrapper")[0] # type: html.HtmlElement
|
|
|
|
for lang in languages:
|
|
if lang == index_page_lang:
|
|
continue
|
|
|
|
tree = html.parse(f"{build_dir}/{lang}/index.html") # type: etree._ElementTree
|
|
root = tree.getroot() # type: html.HtmlElement
|
|
|
|
toctree = root.find_class("toctree-wrapper")[0] # type: html.HtmlElement
|
|
index_file_last_toctree.addnext(toctree)
|
|
|
|
index_file_last_toctree = index_file_root.find_class("toctree-wrapper")[-1] # type: html.HtmlElement
|
|
|
|
index_file_tree.write(f"{build_dir}/index.html", method="html", encoding="UTF-8")
|
|
|
|
# Add cross-lang links to the sidebar
|
|
sidebar_menus: dict[str, html.HtmlElement] = {}
|
|
for lang in languages:
|
|
tree = html.parse(f"{build_dir}/{lang}/index.html") # type: etree._ElementTree
|
|
root = tree.getroot() # type: html.HtmlElement
|
|
|
|
sidebar_menus[lang] = root.find_class("wy-menu")[0]
|
|
|
|
for file in glob(f"{build_dir}/**/*.html") + [f"{build_dir}/index.html"]:
|
|
result = re.match(fr"^{build_dir}/(\w+)/", file)
|
|
lang: str = result.group(1) if result is not None else index_page_lang
|
|
|
|
tree = html.parse(file) # type: etree._ElementTree
|
|
root = tree.getroot() # type: html.HtmlElement
|
|
|
|
sidebar_menu_last = root.find_class("wy-menu")[0] # type: html.HtmlElement
|
|
for menuLang in sidebar_menus:
|
|
if menuLang == lang:
|
|
continue
|
|
|
|
sidebar_menu_last.addnext(sidebar_menus[menuLang])
|
|
sidebar_menu_last = root.find_class("wy-menu")[-1] # type: html.HtmlElement
|
|
|
|
tree.write(file, method="html", encoding="UTF-8")
|