docs: add mintlify export + JSX balance checks to docs_check.py; run on PRs

This commit is contained in:
KaifAhmad1
2026-06-20 16:28:02 +05:30
parent ce8344aa73
commit 59aa3f1d86
3 changed files with 71 additions and 3 deletions
+3
View File
@@ -33,6 +33,9 @@ jobs:
- uses: actions/setup-python@v5
with:
python-version: '3.11'
- uses: actions/setup-node@v6
with:
node-version: '20'
- run: python docs_check.py
deploy:
+1 -3
View File
@@ -3,9 +3,7 @@ title: "Changelog"
description: "Release history for Semantica. All notable changes by version."
---
<Note>
The latest stable release is **v0.5.0**. Changes listed under **Unreleased** are merged to `main` but not yet published to PyPI.
</Note>
The latest stable release is **v0.5.0**. Changes listed under **Unreleased** are merged to `main` but not yet published to PyPI.
---
+67
View File
@@ -5,6 +5,7 @@ import glob
import json
import os
import re
import subprocess
import sys
from typing import Any, Callable, cast
@@ -195,6 +196,72 @@ def _() -> list[str]:
return [m for m in modules if m not in index]
# ── 9. JSX component tags are balanced in every page ─────────────────────────
@check("All Mintlify JSX component tags are balanced")
def _() -> list[str]:
# Paired block-level components that must open and close.
COMPONENTS = [
"AccordionGroup", "Accordion", "Steps", "Step",
"CodeGroup", "Tabs", "Tab", "CardGroup", "Card",
"Expandable",
]
issues: list[str] = []
for fpath in ALL_MD:
content = read(fpath)
lines = content.splitlines()
for comp in COMPONENTS:
# Count opening and closing tags (ignore self-closing <Comp />)
opens = len(re.findall(rf"<{comp}[\s>]", content))
closes = len(re.findall(rf"</{comp}>", content))
if opens != closes:
issues.append(
f"{fpath}: <{comp}> opened {opens}x but closed {closes}x"
)
# Check code fences are balanced (odd fence count = unclosed block)
fence_count = sum(
1 for ln in lines if ln.strip().startswith("```")
)
if fence_count % 2 != 0:
issues.append(f"{fpath}: odd number of ``` fences — unclosed code block")
return issues
# ── 10. Mintlify export succeeds (requires Node.js / npx) ────────────────────
@check("Mintlify export builds without errors")
def _() -> list[str]:
npx = "npx.cmd" if sys.platform == "win32" else "npx"
try:
result = subprocess.run(
[npx, "--yes", "mintlify@4.2.632", "export", "--output", "export_ci_check.zip"],
cwd=DOCS,
capture_output=True,
text=True,
timeout=300,
)
# Clean up zip regardless of outcome
zip_path = os.path.join(DOCS, "export_ci_check.zip")
if os.path.exists(zip_path):
os.remove(zip_path)
combined = (result.stdout or "") + (result.stderr or "")
if result.returncode != 0:
# On Windows, npm cleanup raises EPERM on temp dirs — not a real
# export failure. Treat as a skip rather than a hard failure.
if sys.platform == "win32" and "EPERM" in combined and \
"could not be generated" not in combined:
return [] # Windows temp-cleanup noise; real CI runs on Linux
# Surface the last 20 lines so the failing page error is visible
tail = "\n".join(combined.strip().splitlines()[-20:])
return [f"mintlify export failed (exit {result.returncode}):\n{tail}"]
return []
except FileNotFoundError:
return ["npx not found — skipping Mintlify export check (Node.js required)"]
except subprocess.TimeoutExpired:
return ["mintlify export timed out after 300 s"]
# ── Summary ───────────────────────────────────────────────────────────────────
_print_summary(failures)
if failures: