mirror of
https://github.com/ArthurSonzogni/FTXUI.git
synced 2025-09-23 05:18:08 +08:00
Compare commits
2 Commits
main
...
multiversi
Author | SHA1 | Date | |
---|---|---|---|
![]() |
fd37efb131 | ||
![]() |
3765249e87 |
16
.github/workflows/documentation.yaml
vendored
16
.github/workflows/documentation.yaml
vendored
@@ -12,6 +12,10 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- name: "Checkout repository"
|
- name: "Checkout repository"
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
fetch-depth: 0 # Need full history.
|
||||||
|
fetch-tags: true # Need tags.
|
||||||
|
|
||||||
|
|
||||||
- name: "Install cmake"
|
- name: "Install cmake"
|
||||||
uses: lukka/get-cmake@latest
|
uses: lukka/get-cmake@latest
|
||||||
@@ -30,19 +34,23 @@ jobs:
|
|||||||
sudo apt-get install graphviz;
|
sudo apt-get install graphviz;
|
||||||
|
|
||||||
- name: "Build documentation"
|
- name: "Build documentation"
|
||||||
|
run: |
|
||||||
|
python3 ./tools/build_multiversion_doc.py
|
||||||
|
|
||||||
|
- name: "Build examples"
|
||||||
run: >
|
run: >
|
||||||
|
mkdir -p multiversion_docs/main/examples;
|
||||||
mkdir build;
|
mkdir build;
|
||||||
cd build;
|
cd build;
|
||||||
emcmake cmake ..
|
emcmake cmake ..
|
||||||
-DCMAKE_BUILD_TYPE=Release
|
-DCMAKE_BUILD_TYPE=Release
|
||||||
-DFTXUI_BUILD_DOCS=ON
|
-DFTXUI_BUILD_DOCS=OFF
|
||||||
-DFTXUI_BUILD_EXAMPLES=ON
|
-DFTXUI_BUILD_EXAMPLES=ON
|
||||||
-DFTXUI_BUILD_TESTS=OFF
|
-DFTXUI_BUILD_TESTS=OFF
|
||||||
-DFTXUI_BUILD_TESTS_FUZZER=OFF
|
-DFTXUI_BUILD_TESTS_FUZZER=OFF
|
||||||
-DFTXUI_ENABLE_INSTALL=OFF
|
-DFTXUI_ENABLE_INSTALL=OFF
|
||||||
-DFTXUI_DEV_WARNINGS=OFF;
|
-DFTXUI_DEV_WARNINGS=OFF;
|
||||||
cmake --build . --target doc;
|
cmake --build . --target doc;
|
||||||
cmake --build . ;
|
|
||||||
rsync -amv
|
rsync -amv
|
||||||
--include='*/'
|
--include='*/'
|
||||||
--include='*.html'
|
--include='*.html'
|
||||||
@@ -52,13 +60,13 @@ jobs:
|
|||||||
--include='*.wasm'
|
--include='*.wasm'
|
||||||
--exclude='*'
|
--exclude='*'
|
||||||
examples
|
examples
|
||||||
doc/doxygen/html;
|
../multiversion_docs/main/examples;
|
||||||
|
|
||||||
- name: "Deploy"
|
- name: "Deploy"
|
||||||
uses: peaceiris/actions-gh-pages@v3
|
uses: peaceiris/actions-gh-pages@v3
|
||||||
with:
|
with:
|
||||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
publish_dir: build/doc/doxygen/html/
|
publish_dir: multiversion_docs
|
||||||
enable_jekyll: false
|
enable_jekyll: false
|
||||||
allow_empty_commit: false
|
allow_empty_commit: false
|
||||||
force_orphan: true
|
force_orphan: true
|
||||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@@ -70,5 +70,6 @@ out/
|
|||||||
|
|
||||||
# tools directory:
|
# tools directory:
|
||||||
!tools/**/*.sh
|
!tools/**/*.sh
|
||||||
|
!tools/**/*.py
|
||||||
!tools/**/*.cpp
|
!tools/**/*.cpp
|
||||||
build/
|
build/
|
||||||
|
@@ -2,16 +2,9 @@
|
|||||||
<!-- start footer part -->
|
<!-- start footer part -->
|
||||||
<!--BEGIN GENERATE_TREEVIEW-->
|
<!--BEGIN GENERATE_TREEVIEW-->
|
||||||
<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
|
<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
|
||||||
<ul>
|
|
||||||
$navpath
|
|
||||||
<li class="footer">$generatedby <a href="https://www.doxygen.org/index.html"><img class="footer" src="$relpath^doxygen.svg" width="104" height="31" alt="doxygen"/></a> $doxygenversion </li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
</div>
|
||||||
<!--END GENERATE_TREEVIEW-->
|
<!--END GENERATE_TREEVIEW-->
|
||||||
<!--BEGIN !GENERATE_TREEVIEW-->
|
<!--BEGIN !GENERATE_TREEVIEW-->
|
||||||
<hr class="footer"/><address class="footer"><small>
|
|
||||||
$generatedby <a href="https://www.doxygen.org/index.html"><img class="footer" src="$relpath^doxygen.svg" width="104" height="31" alt="doxygen"/></a> $doxygenversion
|
|
||||||
</small></address>
|
|
||||||
<!--END !GENERATE_TREEVIEW-->
|
<!--END !GENERATE_TREEVIEW-->
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
222
tools/build_multiversion_doc.py
Executable file
222
tools/build_multiversion_doc.py
Executable file
@@ -0,0 +1,222 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
import shutil
|
||||||
|
import tempfile
|
||||||
|
import json
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import List, Dict
|
||||||
|
|
||||||
|
class VersionInfo:
|
||||||
|
"""A structure to hold all information about a single documentation version."""
|
||||||
|
def __init__(self, name: str, is_main: bool, output_root: Path):
|
||||||
|
self.name = name
|
||||||
|
self.is_main = is_main
|
||||||
|
# Destination directory for the built docs, relative to the output root.
|
||||||
|
self.dest_dir = output_root if is_main else output_root / "en" / name
|
||||||
|
# The path to this version's index.html, relative to the output root.
|
||||||
|
self.index_path_from_root = self.dest_dir / "index.html"
|
||||||
|
|
||||||
|
def __repr__(self) -> str:
|
||||||
|
return f"VersionInfo(name='{self.name}', dest_dir='{self.dest_dir}')"
|
||||||
|
|
||||||
|
def run_command(command: List[str], check: bool = True, cwd: Path = None):
|
||||||
|
"""
|
||||||
|
Runs a command, prints its output, and handles errors.
|
||||||
|
"""
|
||||||
|
command_str = ' '.join(command)
|
||||||
|
print(f"Executing: {command_str} in {cwd or Path.cwd()}")
|
||||||
|
try:
|
||||||
|
# Using capture_output=True to get stdout/stderr
|
||||||
|
result = subprocess.run(
|
||||||
|
command,
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
check=check,
|
||||||
|
cwd=cwd
|
||||||
|
)
|
||||||
|
if result.stdout:
|
||||||
|
print(result.stdout)
|
||||||
|
if result.stderr:
|
||||||
|
print(result.stderr)
|
||||||
|
return result
|
||||||
|
except subprocess.CalledProcessError as e:
|
||||||
|
print(f"ERROR: Command failed with exit code {e.returncode}")
|
||||||
|
print(f"Command: {command_str}")
|
||||||
|
if e.stdout:
|
||||||
|
print("--- STDOUT ---")
|
||||||
|
print(e.stdout)
|
||||||
|
if e.stderr:
|
||||||
|
print("--- STDERR ---")
|
||||||
|
print(e.stderr)
|
||||||
|
raise # Re-raise the exception to halt the script
|
||||||
|
|
||||||
|
def get_version_switcher_js(
|
||||||
|
current_version: VersionInfo,
|
||||||
|
all_versions: List[VersionInfo],
|
||||||
|
current_html_file: Path
|
||||||
|
) -> str:
|
||||||
|
"""
|
||||||
|
Generates the JavaScript for the version switcher dropdown.
|
||||||
|
|
||||||
|
This version pre-calculates the relative path from the current HTML file
|
||||||
|
to the index.html of every other version, simplifying the JS logic.
|
||||||
|
"""
|
||||||
|
version_names = [v.name for v in all_versions]
|
||||||
|
|
||||||
|
# Create a dictionary mapping version names to their relative URLs.
|
||||||
|
relative_paths: Dict[str, str] = {}
|
||||||
|
for version in all_versions:
|
||||||
|
# Calculate the relative path from the *parent directory* of the current HTML file
|
||||||
|
# to the target version's index.html.
|
||||||
|
path = os.path.relpath(version.index_path_from_root, current_html_file.parent)
|
||||||
|
relative_paths[version.name] = path
|
||||||
|
|
||||||
|
# Use json.dumps for safe serialization of data into JavaScript.
|
||||||
|
versions_json = json.dumps(version_names)
|
||||||
|
paths_json = json.dumps(relative_paths)
|
||||||
|
current_version_json = json.dumps(current_version.name)
|
||||||
|
|
||||||
|
return f"""
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {{
|
||||||
|
const projectNumber = document.getElementById('projectnumber');
|
||||||
|
if (!projectNumber) {{
|
||||||
|
console.warn('Doxygen element with ID "projectnumber" not found. Cannot add version switcher.');
|
||||||
|
return;
|
||||||
|
}}
|
||||||
|
|
||||||
|
const versions = {versions_json};
|
||||||
|
const version_paths = {paths_json};
|
||||||
|
const currentVersion = {current_version_json};
|
||||||
|
|
||||||
|
// Sort versions: 'main' first, then others numerically descending.
|
||||||
|
versions.sort((a, b) => {{
|
||||||
|
if (a === 'main') return -1;
|
||||||
|
if (b === 'main') return 1;
|
||||||
|
return b.localeCompare(a, undefined, {{ numeric: true, sensitivity: 'base' }});
|
||||||
|
}});
|
||||||
|
|
||||||
|
const select = document.createElement('select');
|
||||||
|
select.onchange = function() {{
|
||||||
|
const selectedVersion = this.value;
|
||||||
|
// Navigate directly to the pre-calculated relative path.
|
||||||
|
if (selectedVersion !== currentVersion) {{
|
||||||
|
window.location.href = version_paths[selectedVersion];
|
||||||
|
}}
|
||||||
|
}};
|
||||||
|
|
||||||
|
versions.forEach(v => {{
|
||||||
|
const option = document.createElement('option');
|
||||||
|
option.value = v;
|
||||||
|
option.textContent = v;
|
||||||
|
if (v === currentVersion) {{
|
||||||
|
option.selected = true;
|
||||||
|
}}
|
||||||
|
select.appendChild(option);
|
||||||
|
}});
|
||||||
|
|
||||||
|
// Replace the Doxygen project number element with our dropdown.
|
||||||
|
projectNumber.replaceWith(select);
|
||||||
|
|
||||||
|
// Apply some styling to make it look good.
|
||||||
|
Object.assign(select.style, {{
|
||||||
|
backgroundColor: 'rgba(0, 0, 0, 0.8)',
|
||||||
|
color: 'white',
|
||||||
|
border: '1px solid rgba(255, 255, 255, 0.2)',
|
||||||
|
padding: '5px',
|
||||||
|
borderRadius: '5px',
|
||||||
|
fontSize: '14px',
|
||||||
|
fontFamily: 'inherit',
|
||||||
|
marginLeft: '10px',
|
||||||
|
cursor: 'pointer'
|
||||||
|
}});
|
||||||
|
}});
|
||||||
|
"""
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""Main function to build multi-version documentation."""
|
||||||
|
root_dir = Path.cwd()
|
||||||
|
output_dir = root_dir / "multiversion_docs"
|
||||||
|
|
||||||
|
print("--- 1. Cleaning up old documentation ---")
|
||||||
|
if output_dir.exists():
|
||||||
|
shutil.rmtree(output_dir)
|
||||||
|
output_dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
print("--- 2. Getting versions from git ---")
|
||||||
|
git_tags_result = run_command(["git", "tag", "--list", "v*"])
|
||||||
|
# Create a list of version names, starting with 'main'.
|
||||||
|
version_names = ["main"] + sorted(
|
||||||
|
git_tags_result.stdout.splitlines(),
|
||||||
|
reverse=True
|
||||||
|
)
|
||||||
|
# For demonstration, limit the number of versions. Remove this in production.
|
||||||
|
version_names = version_names[:4]
|
||||||
|
print(f"Versions to build: {', '.join(version_names)}")
|
||||||
|
|
||||||
|
# Pre-compute all version information and paths.
|
||||||
|
versions = [
|
||||||
|
VersionInfo(name, name == "main", output_dir)
|
||||||
|
for name in version_names
|
||||||
|
]
|
||||||
|
|
||||||
|
with tempfile.TemporaryDirectory() as build_dir_str:
|
||||||
|
build_dir = Path(build_dir_str)
|
||||||
|
# --- 3. Build documentation for each version ---
|
||||||
|
for version in versions:
|
||||||
|
print(f"\n--- Building docs for version: {version.name} ---")
|
||||||
|
|
||||||
|
# Create a temporary directory for this version's source code.
|
||||||
|
version_src_dir = build_dir / f"src_{version.name}"
|
||||||
|
version_src_dir.mkdir()
|
||||||
|
|
||||||
|
# Check out the version's source code from git.
|
||||||
|
archive_path = version_src_dir / "source.tar"
|
||||||
|
run_command([
|
||||||
|
"git", "archive", version.name,
|
||||||
|
"--format=tar", f"--output={archive_path}"
|
||||||
|
])
|
||||||
|
run_command(["tar", "-xf", str(archive_path)], cwd=version_src_dir)
|
||||||
|
archive_path.unlink()
|
||||||
|
|
||||||
|
# Configure and build the docs using CMake.
|
||||||
|
version_build_dir = build_dir / f"build_{version.name}"
|
||||||
|
version_build_dir.mkdir()
|
||||||
|
run_command([
|
||||||
|
"cmake", str(version_src_dir), "-DFTXUI_BUILD_DOCS=ON"
|
||||||
|
], cwd=version_build_dir)
|
||||||
|
run_command(["make", "doc"], cwd=version_build_dir)
|
||||||
|
|
||||||
|
# Copy the generated HTML files to the final destination.
|
||||||
|
doxygen_html_dir = version_build_dir / "doc" / "doxygen" / "html"
|
||||||
|
if not doxygen_html_dir.is_dir():
|
||||||
|
print(f"FATAL: Doxygen HTML output not found for version {version.name}")
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
print(f"Copying files to: {version.dest_dir}")
|
||||||
|
shutil.copytree(doxygen_html_dir, version.dest_dir, dirs_exist_ok=True)
|
||||||
|
|
||||||
|
# --- 4. Inject version switcher into all HTML files ---
|
||||||
|
print("\n--- Injecting version switcher JavaScript ---")
|
||||||
|
for version in versions:
|
||||||
|
if not version.dest_dir.exists():
|
||||||
|
print(f"Warning: Destination directory for {version.name} does not exist. Skipping JS injection.")
|
||||||
|
continue
|
||||||
|
|
||||||
|
print(f"Processing HTML files in: {version.dest_dir}")
|
||||||
|
for html_file in version.dest_dir.rglob("*.html"):
|
||||||
|
js_script = get_version_switcher_js(version, versions, html_file)
|
||||||
|
script_tag = f'<script>{js_script}</script>'
|
||||||
|
|
||||||
|
content = html_file.read_text(encoding='utf-8')
|
||||||
|
# Inject the script right before the closing body tag.
|
||||||
|
new_content = content.replace("</body>", f"{script_tag}\n</body>")
|
||||||
|
html_file.write_text(new_content, encoding='utf-8')
|
||||||
|
|
||||||
|
print("\n--- 5. Finalizing ---")
|
||||||
|
print("Multi-version documentation generated successfully!")
|
||||||
|
print(f"Output located in: {output_dir.resolve()}")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
Reference in New Issue
Block a user