Spaces:
Sleeping
Sleeping
| """DocForge routes β generate full documentation for any GitHub repo.""" | |
| import json | |
| import os | |
| from flask import (Blueprint, render_template, request, jsonify, | |
| current_app, Response) | |
| from .github_fetcher import (parse_repo_url, get_repo_info, | |
| get_file_tree, fetch_key_files) | |
| from .doc_generator import (generate_readme, generate_architecture, | |
| generate_api_docs) | |
| from .db import get_db, upsert_repo, upsert_doc, get_docs, list_recent | |
| bp = Blueprint("doc_forge", __name__, template_folder="templates") | |
| def _db(): | |
| db_path = os.path.join(os.path.dirname(current_app.root_path), "docforge.db") | |
| return get_db(db_path) | |
| # ββ Pages ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| def index(): | |
| db = _db() | |
| recent = list_recent(db) | |
| return render_template("doc_forge/index.html", recent=recent) | |
| def docs_view(owner, repo): | |
| db = _db() | |
| data = get_docs(db, owner, repo) | |
| if not data: | |
| return render_template("doc_forge/index.html", recent=list_recent(db), | |
| error=f"No docs found for {owner}/{repo}. Generate them first.") | |
| return render_template("doc_forge/docs.html", owner=owner, repo=repo, data=data) | |
| # ββ API ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| def analyze(): | |
| """Step 1: fetch repo metadata + file tree. Returns info without generating docs.""" | |
| body = request.get_json(silent=True) or {} | |
| url = (body.get("url") or "").strip() | |
| if not url: | |
| return jsonify({"error": "repo_url is required"}), 400 | |
| try: | |
| owner, repo = parse_repo_url(url) | |
| info = get_repo_info(owner, repo) | |
| tree = get_file_tree(owner, repo, info["default_branch"]) | |
| return jsonify({ | |
| "owner": owner, "repo": repo, | |
| "info": info, "file_count": len(tree), | |
| "tree_preview": tree[:20], | |
| }) | |
| except Exception as exc: | |
| return jsonify({"error": str(exc)}), 400 | |
| def generate(): | |
| """Step 2: generate all docs for a repo.""" | |
| body = request.get_json(silent=True) or {} | |
| url = (body.get("url") or "").strip() | |
| types = body.get("types", ["readme", "architecture", "api"]) | |
| if not url: | |
| return jsonify({"error": "url is required"}), 400 | |
| try: | |
| owner, repo = parse_repo_url(url) | |
| info = get_repo_info(owner, repo) | |
| tree = get_file_tree(owner, repo, info["default_branch"]) | |
| files = fetch_key_files(owner, repo, tree, info["default_branch"]) | |
| db = _db() | |
| repo_id = upsert_repo(db, owner, repo, info, tree) | |
| results = {} | |
| if "readme" in types: | |
| readme = generate_readme(info, tree, files) | |
| upsert_doc(db, repo_id, "readme", readme) | |
| results["readme"] = readme | |
| if "architecture" in types: | |
| arch = generate_architecture(info, tree, files) | |
| upsert_doc(db, repo_id, "architecture", arch) | |
| results["architecture"] = arch | |
| if "api" in types: | |
| api_docs = generate_api_docs(info, tree, files) | |
| upsert_doc(db, repo_id, "api", api_docs) | |
| results["api"] = api_docs | |
| return jsonify({"owner": owner, "repo": repo, "info": info, "docs": results}) | |
| except Exception as exc: | |
| return jsonify({"error": str(exc)}), 500 | |
| def download(owner, repo, doc_type): | |
| """Download a generated doc as a file.""" | |
| db = _db() | |
| data = get_docs(db, owner, repo) | |
| if not data or doc_type not in data: | |
| return jsonify({"error": "not found"}), 404 | |
| content = data[doc_type] | |
| if doc_type == "readme": | |
| text = content.get("readme", "") | |
| filename = "README.md" | |
| mime = "text/markdown" | |
| else: | |
| text = json.dumps(content, indent=2, ensure_ascii=False) | |
| filename = f"{doc_type}.json" | |
| mime = "application/json" | |
| return Response(text, mimetype=mime, | |
| headers={"Content-Disposition": f'attachment; filename="{filename}"'}) | |
| def recent(): | |
| db = _db() | |
| return jsonify(list_recent(db)) | |