Skip to content

Commit

Permalink
[Docs] Generate initial mkdocs site with static pages (#1108)
Browse files Browse the repository at this point in the history
* Move _blogs directory inside the docs directory

* Add mkdocs to the project

* Add quick start guide

* Update styles for home page

* WIP

* Include static pages in mkdocs site

* Add announcement bar

* Polish build scripts

* Add deploy GH action

* Polishing

* Fix asset path in home page

* Fix failing test
  • Loading branch information
harishmohanraj authored Feb 24, 2025
1 parent 1792140 commit 5eb753c
Show file tree
Hide file tree
Showing 175 changed files with 2,652 additions and 114 deletions.
105 changes: 28 additions & 77 deletions .github/workflows/deploy-website.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
name: Deploy Redirect Page
name: Deploy MkDocs to GitHub Pages

on:
push:
branches: [main]
paths:
- "autogen/**"
- "website/**"
- ".github/workflows/deploy-website.yml"
- ".github/workflows/docs-check-broken-links.yml"
- "scripts/broken-links-check.sh"
- "scripts/docs_build_mkdocs.sh"
- "scripts/docs_serve_mkdocs.sh"
- ".muffet-excluded-links.txt"
workflow_dispatch:
permissions:
contents: write
Expand All @@ -15,90 +22,34 @@ jobs:
# Step 1: Check out the repository
- name: Checkout repository
uses: actions/checkout@v4
with:
lfs: true
fetch-depth: 0

# Step 2: Create redirect HTML files
- name: Create redirect HTML
run: |
mkdir -p dist
# Homepage redirect
cat > dist/index.html << 'EOF'
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="refresh" content="0; url=https://docs.ag2.ai">
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-M24T8371GM"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-M24T8371GM');
</script>
<script>
setTimeout(function() {
window.location.href = "https://docs.ag2.ai";
}, 500);
</script>
<title>Page Redirection</title>
</head>
<body>
If you are not redirected automatically, follow this <a href="https://docs.ag2.ai">link to the new documentation</a>.
</body>
</html>
EOF
# Deep link handling
cat > dist/404.html << 'EOF'
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-M24T8371GM"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-M24T8371GM');
</script>
<script>
const newDomain = 'https://docs.ag2.ai';
let path = window.location.pathname;
const hash = window.location.hash;
// Remove /ag2/ prefix and trailing slash
path = path.replace(/^\/ag2\//, '/').replace(/\/$/, "");
// Transform blog and talks URLs
if (path.includes('/blog/') || path.includes('/talks/')) {
const afterPrefix = path.split(/\/(blog|talks)\//)[2];
const transformed = afterPrefix.replace(/\//g, '-');
path = path.replace(afterPrefix, transformed);
}
// Handle -index and create final URL with hash
const redirectUrl = (newDomain + path).replace(/-index$/, "/index") + hash;
- uses: astral-sh/setup-uv@v5
with:
version: "latest"
- uses: actions/setup-python@v5
with:
python-version: 3.x

setTimeout(function() {
window.location.href = redirectUrl;
}, 500);
</script>
<title>Page Redirection</title>
</head>
<body>
If you are not redirected automatically, follow this <a href="https://docs.ag2.ai">link to the new documentation</a>.
</body>
</html>
EOF
# Step 3: Build MkDocs
- name: Build documentation
run: |
uv venv
. .venv/bin/activate
uv pip install -e ".[docs]"
./scripts/docs_build_mkdocs.sh
ls -la ./website/mkdocs/site
working-directory: .

# Step 3: Deploy to gh-pages branch
- name: Deploy to GitHub Pages
uses: peaceiris/actions-gh-pages@v4
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./dist
publish_dir: ./website/mkdocs/site
force_orphan: true
user_name: 'github-actions[bot]'
user_email: 'github-actions[bot]@users.noreply.github.com'
commit_message: 'Deploy redirect page'
commit_message: 'Deploy MkDocs site to GitHub pages'
1 change: 1 addition & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ repos:
- id: check-added-large-files
- id: check-ast
- id: check-yaml
exclude: 'website/mkdocs/mkdocs.yml'
- id: check-toml
- id: check-json
exclude: |
Expand Down
26 changes: 13 additions & 13 deletions .secrets.baseline
Original file line number Diff line number Diff line change
Expand Up @@ -1197,72 +1197,72 @@
"is_secret": false
}
],
"website/_blogs/2023-07-14-Local-LLMs/index.mdx": [
"website/docs/_blogs/2023-07-14-Local-LLMs/index.mdx": [
{
"type": "Secret Keyword",
"filename": "website/_blogs/2023-07-14-Local-LLMs/index.mdx",
"filename": "website/docs/_blogs/2023-07-14-Local-LLMs/index.mdx",
"hashed_secret": "eef19c54306daa69eda49c0272623bdb5e2b341f",
"is_verified": false,
"line_number": 83,
"is_secret": false
}
],
"website/_blogs/2023-10-18-RetrieveChat/index.mdx": [
"website/docs/_blogs/2023-10-18-RetrieveChat/index.mdx": [
{
"type": "Secret Keyword",
"filename": "website/_blogs/2023-10-18-RetrieveChat/index.mdx",
"filename": "website/docs/_blogs/2023-10-18-RetrieveChat/index.mdx",
"hashed_secret": "1e3667aaaaa887721550cf5cc8a0c5c5760810ed",
"is_verified": false,
"line_number": 155,
"is_secret": false
}
],
"website/_blogs/2023-11-26-Agent-AutoBuild/index.mdx": [
"website/docs/_blogs/2023-11-26-Agent-AutoBuild/index.mdx": [
{
"type": "Base64 High Entropy String",
"filename": "website/_blogs/2023-11-26-Agent-AutoBuild/index.mdx",
"filename": "website/docs/_blogs/2023-11-26-Agent-AutoBuild/index.mdx",
"hashed_secret": "76c1da7555caa23cfbad2a5a25caa463e8a81b30",
"is_verified": false,
"line_number": 46,
"is_secret": false
},
{
"type": "Secret Keyword",
"filename": "website/_blogs/2023-11-26-Agent-AutoBuild/index.mdx",
"filename": "website/docs/_blogs/2023-11-26-Agent-AutoBuild/index.mdx",
"hashed_secret": "5bc604777adb22ae457a5473c397202e00689e23",
"is_verified": false,
"line_number": 174,
"is_secret": false
}
],
"website/_blogs/2024-06-24-AltModels-Classes/index.mdx": [
"website/docs/_blogs/2024-06-24-AltModels-Classes/index.mdx": [
{
"type": "Secret Keyword",
"filename": "website/_blogs/2024-06-24-AltModels-Classes/index.mdx",
"filename": "website/docs/_blogs/2024-06-24-AltModels-Classes/index.mdx",
"hashed_secret": "7d80773e54e49b5cc36d28a4a7baf9fff268491e",
"is_verified": false,
"line_number": 89,
"is_secret": false
},
{
"type": "Secret Keyword",
"filename": "website/_blogs/2024-06-24-AltModels-Classes/index.mdx",
"filename": "website/docs/_blogs/2024-06-24-AltModels-Classes/index.mdx",
"hashed_secret": "5f7eb17aeb646b3cda7af7c395fc9e291c62273e",
"is_verified": false,
"line_number": 94,
"is_secret": false
},
{
"type": "Secret Keyword",
"filename": "website/_blogs/2024-06-24-AltModels-Classes/index.mdx",
"filename": "website/docs/_blogs/2024-06-24-AltModels-Classes/index.mdx",
"hashed_secret": "9918921badd6ab97ccf2355ca3dda0fefbf79d03",
"is_verified": false,
"line_number": 99,
"is_secret": false
},
{
"type": "Secret Keyword",
"filename": "website/_blogs/2024-06-24-AltModels-Classes/index.mdx",
"filename": "website/docs/_blogs/2024-06-24-AltModels-Classes/index.mdx",
"hashed_secret": "2da1eec5f20a39f9f7b1449ea3f3ad0abc84642c",
"is_verified": false,
"line_number": 104,
Expand Down Expand Up @@ -1541,7 +1541,7 @@
"filename": "website/docs/user-guide/models/vLLM.mdx",
"hashed_secret": "aa572c1a118d643cfe6442e2ab56f7f3bb5d63d2",
"is_verified": false,
"line_number": 90,
"line_number": 91,
"is_secret": false
}
],
Expand Down
157 changes: 157 additions & 0 deletions autogen/_website/generate_mkdocs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
# Copyright (c) 2023 - 2025, AG2ai, Inc., AG2ai open-source projects maintainers and core contributors
#
# SPDX-License-Identifier: Apache-2.0


import json
import re
import shutil
from pathlib import Path

from ..import_utils import optional_import_block, require_optional_import
from .utils import NavigationGroup, copy_files, get_git_tracked_and_untracked_files_in_directory

with optional_import_block():
from jinja2 import Template


def filter_excluded_files(files: list[Path], exclusion_list: list[str], website_dir: Path) -> list[Path]:
return [
file
for file in files
if not any(str(file.relative_to(website_dir)).startswith(excl) for excl in exclusion_list)
]


def copy_file(file: Path, mkdocs_output_dir: Path) -> None:
dest = mkdocs_output_dir / file.relative_to(file.parents[1])
dest.parent.mkdir(parents=True, exist_ok=True)
shutil.copy2(file, dest)


def transform_content_for_mkdocs(content: str) -> str:
# Transform admonitions (Tip, Warning, Note)
tag_mappings = {
"Tip": "tip",
"Warning": "warning",
"Note": "note",
"Danger": "danger",
}
for html_tag, mkdocs_type in tag_mappings.items():
pattern = f"<{html_tag}>(.*?)</{html_tag}>"

def replacement(match):
inner_content = match.group(1).strip()
return f"!!! {mkdocs_type}\n {inner_content}"

content = re.sub(pattern, replacement, content, flags=re.DOTALL)

# Clean up style tags with double curly braces
style_pattern = r"style\s*=\s*{{\s*([^}]+)\s*}}"

def style_replacement(match):
style_content = match.group(1).strip()
return f"style={{ {style_content} }}"

content = re.sub(style_pattern, style_replacement, content)

return content


def process_and_copy_files(input_dir: Path, output_dir: Path, files: list[Path]) -> None:
for file in files:
if file.suffix == ".mdx":
content = file.read_text()
processed_content = transform_content_for_mkdocs(content)
dest = output_dir / file.relative_to(input_dir).with_suffix(".md")
dest.parent.mkdir(parents=True, exist_ok=True)
dest.write_text(processed_content)
else:
copy_files(input_dir, output_dir, [file])
# copy_file(file, output_dir)


def format_title(title: str, keywords: dict[str, str]) -> str:
"""Format a page title with proper capitalization for special keywords."""
words = title.replace("-", " ").title().split()
return " ".join(keywords.get(word, word) for word in words)


def format_page_entry(page_path: str, indent: str, keywords: dict[str, str]) -> str:
"""Format a single page entry as either a parenthesized path or a markdown link."""
path = f"{page_path}.md"
title = format_title(Path(page_path).name, keywords)
return f"{indent} - [{title}]({path})"


def format_navigation(nav: list[NavigationGroup], depth: int = 0, keywords: dict[str, str] = None) -> str:
"""
Recursively format navigation structure into markdown-style nested list.
Args:
nav: List of navigation items with groups and pages
depth: Current indentation depth
keywords: Dictionary of special case word capitalizations
Returns:
Formatted navigation as a string
"""
if keywords is None:
keywords = {
"Ag2": "AG2",
"Rag": "RAG",
"Llm": "LLM",
}

indent = " " * depth
result = []

for item in nav:
# Add group header
result.append(f"{indent}- {item['group']}")

# Process each page
for page in item["pages"]:
if isinstance(page, dict):
# Handle nested navigation groups
result.append(format_navigation([page], depth + 1, keywords))
else:
# Handle individual pages
result.append(format_page_entry(page, indent, keywords))

return "\n".join(result)


@require_optional_import("jinja2", "docs")
def generate_mkdocs_navigation(website_dir: Path, mkdocs_root_dir: Path, nav_exclusions: list[str]) -> None:
mintlify_nav_template_path = website_dir / "mint-json-template.json.jinja"
mkdocs_nav_path = mkdocs_root_dir / "docs" / "navigation_template.txt"
summary_md_path = mkdocs_root_dir / "docs" / "SUMMARY.md"

mintlify_json = json.loads(Template(mintlify_nav_template_path.read_text(encoding="utf-8")).render())
mintlify_nav = mintlify_json["navigation"]
filtered_nav = [item for item in mintlify_nav if item["group"] not in nav_exclusions]

mkdocs_nav_content = "---\nsearch:\n exclude: true\n---\n" + format_navigation(filtered_nav) + "\n"
mkdocs_nav_path.write_text(mkdocs_nav_content)
summary_md_path.write_text(mkdocs_nav_content)


def main() -> None:
root_dir = Path(__file__).resolve().parents[2]
website_dir = root_dir / "website"

mint_inpur_dir = website_dir / "docs"

mkdocs_root_dir = website_dir / "mkdocs"
mkdocs_output_dir = mkdocs_root_dir / "docs" / "docs"

exclusion_list = ["docs/_blogs", "docs/home", "docs/.gitignore", "docs/use-cases"]
nav_exclusions = ["Use Cases"]

files_to_copy = get_git_tracked_and_untracked_files_in_directory(mint_inpur_dir)
filtered_files = filter_excluded_files(files_to_copy, exclusion_list, website_dir)

process_and_copy_files(mint_inpur_dir, mkdocs_output_dir, filtered_files)

generate_mkdocs_navigation(website_dir, mkdocs_root_dir, nav_exclusions)
Loading

0 comments on commit 5eb753c

Please sign in to comment.