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}\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.") # Basic index fallback dirs = [d for d in os.listdir(DOCS_DIR) if os.path.isdir(os.path.join(DOCS_DIR, d)) and d != "assets"] dirs.sort() content = "# Base de Conhecimento - iT Guys\n\n## Manuais Disponíveis\n\n" content += "\n".join([f"- [{d}](./{d}/)" for d in dirs]) with open(os.path.join(DOCS_DIR, "index.md"), 'w', encoding='utf-8') as f: f.write(content) return with open(readme_path, 'r', encoding='utf-8') as f: content = f.read() # Build a map of all .md files in DOCS_DIR # Format: { "filename_no_ext": "relative/path/to/file.md" } file_map = {} for root, dirs, files in os.walk(DOCS_DIR): for file in files: if file.lower().endswith('.md') and file.lower() != 'index.md': filename_no_ext = os.path.splitext(file)[0] rel_path = os.path.relpath(os.path.join(root, file), DOCS_DIR) file_map[filename_no_ext.strip().lower()] = rel_path.replace("\\", "/") # Regex to find checklist items: - [x] [Nível X] Title # We want to capture the status [x] or [ ] and the title [Nível X] Title def replace_with_link(match): status = match.group(1) title = match.group(2).strip() # Try to find the title in our file map # We need to be careful with exact matches key = title.lower() if key in file_map: return f"- [{status}] [{title}]({file_map[key]})" else: # Try matching without Nivel prefix if it fails? # No, keep it strict or try cleaning. # Example: [Nível 2] Interfaces, Vlans E Lagg return f"- [{status}] {title} (Arquivo não encontrado)" # Regex pattern: - \[(x| )\] (.*) # Match lines starting with - [x] or - [ ] pattern = r"^- \[(x| )\] (.*)" new_content = re.sub(pattern, replace_with_link, content, flags=re.MULTILINE) with open(os.path.join(DOCS_DIR, "index.md"), 'w', encoding='utf-8') as f: f.write(new_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)