import os import shutil import subprocess import sys import yaml import re # Configuration ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) BUILD_DIR = os.path.join(ROOT_DIR, "_site_src") DOCS_DIR = os.path.join(BUILD_DIR, "docs") MKDOCS_CONFIG = os.path.join(ROOT_DIR, "mkdocs.yml") GEMINI_CLI = os.path.join(ROOT_DIR, ".gemini", "gemini_cli.py") def clean_build_dir(): if os.path.exists(BUILD_DIR): try: shutil.rmtree(BUILD_DIR) except Exception as e: print(f"Warning cleaning build dir: {e}") os.makedirs(DOCS_DIR, exist_ok=True) def clean_folder_name(name): # Converts 'documentacao zammad' to 'Zammad' # Converts 'documentacao backup-restore' to 'Backup Restore' if name.startswith("documentacao "): name = name.replace("documentacao ", "") # Capitalize words return name.title() def process_markdown_content(content): # Remove the Manual Revision History Block # Look for ## 1. HISTÓRICO DE REVISÃO until the next ## header # Pattern: ## 1. HISTÓRICO... (anything until next ## or end) pattern = r"## 1\. HISTÓRICO DE REVISÃO.*?(?=## |\Z)" content = re.sub(pattern, "", content, flags=re.DOTALL) # Also strip any numbering from H2 headers if needed, but user might want them. return content def copy_manuals(): print("Copying manuals to build directory...") # Find all 'documentacao *' folders for item in os.listdir(ROOT_DIR): if os.path.isdir(os.path.join(ROOT_DIR, item)) and item.startswith("documentacao"): src_path = os.path.join(ROOT_DIR, item) # Nice name for the folder clean_name = clean_folder_name(item) dst_path = os.path.join(DOCS_DIR, clean_name) print(f"Processing {item} -> {clean_name}") shutil.copytree(src_path, dst_path, dirs_exist_ok=True) # Post-process files in the new destination for root, dirs, files in os.walk(dst_path): for file in files: if file.lower().endswith('.md'): # Inject PDF Link + Strip Revision History full_path = os.path.join(root, file) # Generate/Check PDF name pdf_name = file.rsplit('.', 1)[0] + ".pdf" try: with open(full_path, 'r', encoding='utf-8') as f: content = f.read() modified_content = process_markdown_content(content) # Add PDF Button display_name = "Baixar PDF" link = f'[:material-file-pdf-box: {display_name}](./{pdf_name}){{ .md-button .md-button--primary .download-pdf-btn }}\n\n' # Insert link after header or at top if modified_content.startswith("---"): # Split frontmatter parts = modified_content.split("---", 2) if len(parts) >= 3: parts[2] = link + parts[2] modified_content = "---".join(parts) else: modified_content = link + modified_content else: # Try to find H1 if "# " in modified_content: modified_content = modified_content.replace("\n# ", f"\n{link}\n# ", 1) # Put before? No, after is better. # Actually, let's put it AT THE TOP of content, below title if possible. # Simple regex replace for first H1 modified_content = re.sub(r'(^# .+)', r'\1\n\n' + link, modified_content, count=1, flags=re.MULTILINE) else: modified_content = link + modified_content with open(full_path, 'w', encoding='utf-8') as f: f.write(modified_content) except Exception as e: print(f"Error processing {file}: {e}") # Copy contents of 'assets' folder in root to 'docs/assets' root_assets = os.path.join(ROOT_DIR, "assets") docs_assets = os.path.join(DOCS_DIR, "assets") if os.path.exists(root_assets): print(f"Copying root assets from {root_assets} to {docs_assets}") shutil.copytree(root_assets, docs_assets, dirs_exist_ok=True) def create_index(): print("Creating index.md from README.md...") readme_path = os.path.join(ROOT_DIR, "README.md") if not os.path.exists(readme_path): print("README.md not found, creating basic index.") return with open(readme_path, 'r', encoding='utf-8') as f: content = f.read() # We need to fix links like [Title](documentacao%20folder/file.md) # to work in the site structure: [Title](./Folder/file.md) # The folders in site are cleaned via clean_folder_name(item) def fix_link(match): label = match.group(1) path = match.group(2) # Unquote path import urllib.parse raw_path = urllib.parse.unquote(path) if "documentacao " in raw_path: # documentacao zammad/[Nível 1]...md -> Zammad/[Nível 1]...md parts = raw_path.split("/", 1) if len(parts) == 2: clean_folder = clean_folder_name(parts[0]) # Remove .md if it's there to let awesome-pages handle it? # Actually, link should point to the .md or .html. # MkDocs converts .md to .html but relative links inside MD work. new_path = f"./{clean_folder}/{parts[1]}" return f"[[{label}]]({urllib.parse.quote(new_path)})" return match.group(0) # Use a greedy regex for the path part (.*) to handle parentheses in filenames. # Since each link is on its own line in the checklist, this is safe. content = re.sub(r"\[\[(.*?)\]\]\((.*)\)", fix_link, content) # Also fix relative image paths if any (assets/logo.png -> ./assets/logo.png) content = content.replace("](assets/", "](./assets/") with open(os.path.join(DOCS_DIR, "index.md"), 'w', encoding='utf-8') as f: f.write(content) def generate_pdfs(): print("Generating PDFs...") # Call gemini_cli batch_convert on the DOCS_DIR # We need to make sure we use the same python env subprocess.check_call([sys.executable, GEMINI_CLI, "batch-convert", DOCS_DIR]) def build_mkdocs(): print("Building MkDocs site...") # Load base config # Use unsafe_load to handle !!python tags with open(os.path.join(ROOT_DIR, "mkdocs.yml"), "r") as f: base_config = yaml.unsafe_load(f) # Update config to point to our source folder # IMPORTANT: We use relative path so MkDocs can find it from ROOT base_config["docs_dir"] = "_site_src/docs" base_config["site_dir"] = "_site_src/site" # Ensure extra_css is copied extra_css_src = os.path.join(ROOT_DIR, ".gemini", "stylesheets") extra_css_dst = os.path.join(DOCS_DIR, "stylesheets") if os.path.exists(extra_css_src): shutil.copytree(extra_css_src, extra_css_dst, dirs_exist_ok=True) # Write temporary config in ROOT (so it sees .git) temp_config_path = os.path.join(ROOT_DIR, "mkdocs_generated.yml") with open(temp_config_path, "w") as f: yaml.dump(base_config, f) # Run build using the generated config in ROOT subprocess.check_call(["mkdocs", "build", "-f", "mkdocs_generated.yml"]) if __name__ == "__main__": try: clean_build_dir() copy_manuals() create_index() generate_pdfs() build_mkdocs() print("Build Complete! Site is in _site_src/site") except Exception as e: print(f"Build Failed: {e}") # print stack trace import traceback traceback.print_exc() sys.exit(1)