manuais-e-documentacao-itguys/.gemini/build_site.py

208 lines
8.7 KiB
Python

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'<a class="md-button md-button--primary download-pdf-btn" href="./{pdf_name}">:material-file-pdf-box: {display_name}</a>\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)