API Documentation Generator
Run ID: 69cc4f688f41b62a970c28222026-03-31Development
PantheraHive BOS
BOS Dashboard

API Documentation Generator: Architectural Plan

This document outlines the proposed architecture for a professional API Documentation Generator. The goal is to create a robust, flexible, and extensible system capable of generating comprehensive API documentation, including endpoint descriptions, request/response examples, authentication guides, and SDK usage examples.


1. Introduction & Core Objectives

The API Documentation Generator aims to streamline the process of creating and maintaining high-quality API documentation. It will support various input formats, generate multiple output types, and provide features for customization and extensibility.

Core Objectives:


2. High-Level Architecture Overview

The generator will follow a modular, pipeline-based architecture, separating concerns into distinct layers: Input, Processing, and Output.

text • 1,314 chars
+-------------------+     +-------------------------+     +-------------------+
|   Input Sources   |     |    Processing Engine    |     |    Output Layer   |
| (API Definitions) |     | (Internal Data Model &  |     | (Renderers/Targets)|
+-------------------+     |     Transformation)     |     +-------------------+
        |                 +-------------------------+                 |
        v                             ^                             v
+-------------------+                 |                 +-------------------+
|  Parser Modules   |                 |                 | Template Engine   |
| (OpenAPI, RAML,   |                 |                 | (Markdown, HTML,  |
| Code Annotations) |                 |                 | Static Site Gen)  |
+-------------------+                 |                 +-------------------+
        |                             |                             |
        v                             |                             v
+-----------------------------------------------------------------------------+
|                                Core Orchestrator / CLI                       |
| (User Configuration, Workflow Management, Plugin/Extension Management)      |
+-----------------------------------------------------------------------------+
Sandboxed live preview

3. Detailed Component Breakdown

3.1. Input Layer: API Definition Parsers

This layer is responsible for ingesting API definitions from various sources and converting them into a standardized internal data model.

  • OpenAPI/Swagger Parser:

* Functionality: Reads swagger.json, openapi.yaml, or openapi.json files.

* Features: Handles OpenAPI 2.0 (Swagger) and 3.x specifications. Validates input against schema.

* Output: Converts to the Generator's Internal API Data Model.

  • RAML Parser:

* Functionality: Reads .raml files.

* Features: Supports RAML 0.8 and 1.0.

* Output: Converts to the Generator's Internal API Data Model.

  • API Blueprint Parser (Optional, Phase 2):

* Functionality: Reads .apib files.

* Output: Converts to the Generator's Internal API Data Model.

  • Code Annotation Parser (Optional, Phase 3):

* Functionality: Scans source code (e.g., JSDoc, PHPDoc, GoDoc, JavaDoc with specific tags) to extract API endpoint information.

* Features: Language-specific parsers. Requires defined annotation standards.

* Output: Converts to the Generator's Internal API Data Model.

  • Custom Input Processor (Extensibility Point):

* Functionality: Allows users to define custom input formats or integrate with proprietary API definition systems via a plugin interface.

3.2. Core Processing Engine

This is the heart of the generator, responsible for holding the parsed API data, enriching it, and preparing it for rendering.

  • Internal API Data Model:

* Structure: A language-agnostic, hierarchical data structure representing all aspects of an API (e.g., API -> Tags -> Endpoints -> Methods -> Parameters, Request Bodies, Responses, Schemas, Security Schemes).

* Attributes: Includes all relevant metadata (descriptions, examples, types, formats, constraints, authentication requirements).

* Design Principle: Decoupled from any specific input or output format to ensure flexibility.

  • Data Enrichment & Transformation Module:

* Functionality:

* Example Generation: Automatically generates realistic request/response examples based on schemas (e.g., using Faker libraries).

* SDK Snippet Generation: Translates API definitions into code snippets for various languages (e.g., curl, Python, JavaScript, Ruby, Java).

* Markdown/HTML Sanitization: Cleans and formats descriptions for consistent rendering.

* Cross-referencing: Resolves internal links and references within the API definition.

* Content Augmentation: Allows injection of custom Markdown files, images, or additional narrative content not present in the API definition (e.g., "Getting Started" guides, "Troubleshooting").

  • Validation & Error Handling:

* Functionality: Validates the internal data model for completeness and consistency. Reports errors clearly to the user.

3.3. Output Layer: Documentation Renderers & Targets

This layer takes the processed internal data model and renders it into various human-readable documentation formats.

  • Templating Engine:

* Functionality: Uses a flexible templating language (e.g., Handlebars, Jinja2, Liquid) to generate documentation based on predefined or custom templates.

* Features: Supports conditional logic, loops, partials, and data access from the Internal API Data Model.

  • Renderer Modules:

* Static HTML Renderer:

* Functionality: Generates a set of interlinked HTML files, CSS, and JavaScript for a modern, navigable documentation website.

* Features: Search functionality, responsive design, syntax highlighting, interactive request/response examples (e.g., "Try it out" buttons).

* Targets: Standalone HTML site, integration with static site generators (e.g., Jekyll, Hugo, Next.js).

* Markdown Renderer:

* Functionality: Generates API documentation in Markdown format, suitable for READMEs, Wikis, or integration into existing Markdown-based documentation systems.

* Features: Customizable Markdown flavors (GitHub Flavored Markdown, CommonMark).

* PDF/Print Renderer (Optional, Phase 2):

* Functionality: Generates print-ready PDF documents from the internal data model, potentially via HTML to PDF conversion tools (e.g., Puppeteer, wkhtmltopdf).

* Postman Collection Exporter (Optional, Phase 2):

* Functionality: Exports the API definition into a Postman Collection JSON format, allowing users to import and test the API directly in Postman.

  • Asset Management:

* Functionality: Copies static assets (CSS, JS, images, fonts) to the output directory.

3.4. User Interface & Core Orchestrator

This component manages the overall workflow, configuration, and user interaction.

  • Command Line Interface (CLI):

* Functionality: Primary interface for users to configure and run the generator.

* Commands: generate (main generation command), init (create config file), validate (validate API definition), list-templates, install-plugin.

* Configuration: Reads configuration from a config.yaml or config.json file (input source, output path, template selection, customization options).

  • Plugin/Extension Management:

* Functionality: Provides hooks and an API for users to extend the generator's capabilities (e.g., custom parsers, custom renderers, pre/post-processing steps).

* Mechanism: Supports loading external modules/scripts.


4. Key Technologies & Frameworks (Potential Recommendations)

  • Core Language: Python (for its rich ecosystem, data processing capabilities, and text manipulation) or Node.js (for its strong CLI tools, web focus, and templating engines).
  • CLI Framework: Click (Python) or Commander.js / Yargs (Node.js).
  • API Specification Parsers:

* OpenAPI: pyopenapi / connexion (Python), swagger-parser / oas-parser (Node.js).

* RAML: raml-js-parser-2 (Node.js), raml-parser (Python).

  • Templating Engines: Jinja2 (Python) or Handlebars.js / Nunjucks (Node.js).
  • Static Site Generation (for HTML output): Integration with MkDocs (Python), Docsify.js, Docusaurus (Node.js/React).
  • Markdown Processing: Markdown / Mistune (Python), marked (Node.js).
  • Schema Faker: Faker library (Python/Node.js) for example generation.
  • Code Generation (SDK snippets): openapi-generator-cli (can be integrated as a dependency or inspiration for custom snippet generation logic).

5. Scalability, Extensibility & Security Considerations

  • Scalability:

* The modular design allows components to be swapped or updated independently.

* Processing of large API definitions should be optimized (e.g., lazy loading, efficient data structures).

* The generator will be primarily a CLI tool, making it inherently scalable for local execution or CI/CD pipelines.

  • Extensibility:

* Plugin Architecture: Clearly defined interfaces for custom parsers, renderers, data transformers, and template helpers.

* Custom Templates: Users can provide their own templates to control the look and feel entirely.

* Configuration Overrides: All aspects should be configurable via CLI arguments or configuration files.

  • Security:

* Input Validation: Robust validation of API definition files to prevent injection of malicious content into the generated documentation.

* Output Sanitization: Ensure all user-provided descriptions and examples are properly sanitized before rendering to HTML to prevent XSS attacks.

* No Runtime Execution: The generator will primarily process static API definitions; it will not execute API calls unless explicitly configured for "Try it out" features, which would require careful sandboxing.

Sensitive Data: The generator should not store or process sensitive API keys or credentials unless explicitly required for describing* authentication methods, and never hardcode them into generated examples.


6. Milestones for Architectural Development

These milestones focus on establishing the core architecture and foundational components.

  • Milestone 1: Core Data Model & OpenAPI Parser (Weeks 1-3)

* Define the complete Internal API Data Model structure.

* Implement an OpenAPI 3.x parser to ingest a basic API definition.

* Develop basic CLI for input file selection.

* Deliverable: A functional parser that can convert an OpenAPI 3.x spec into the internal data model.

  • Milestone 2: Basic Markdown Renderer & Templating (Weeks 4-6)

* Integrate a templating engine.

* Create a basic set of Markdown templates for endpoints, parameters, and responses.

* Implement a Markdown renderer to generate a single Markdown file.

* Deliverable: Ability to generate a basic Markdown file from an OpenAPI spec.

  • Milestone 3: HTML Renderer & Customization (Weeks 7-9)

* Develop a static HTML renderer with basic navigation and styling.

* Implement configuration options for output path and template selection.

* Add basic example generation (e.g., curl command) based on the schema.

* Deliverable: A functional CLI tool that generates a multi-page HTML documentation site from an OpenAPI spec.

  • Milestone 4: Extensibility & Plugin Hooks (Weeks 10-12)

* Design and implement a plugin interface for custom renderers or data transformers.

* Refine error handling and reporting mechanisms.

* Deliverable: A stable architectural core with defined extension points, ready for feature expansion.


gemini Output

As a professional AI assistant within PantheraHive, I am executing Step 2 of 3 for the "API Documentation Generator" workflow. This step focuses on generating the core code for professional API documentation.

The most effective and industry-standard way to generate comprehensive API documentation that includes endpoint descriptions, request/response examples, and authentication guides is by producing an OpenAPI (formerly Swagger) Specification. This machine-readable format can then be used by various tools (like Swagger UI, ReDoc, Postman) to render interactive and visually appealing documentation.

Below is a detailed, professional OpenAPI 3.0.0 specification for a hypothetical "Product Catalog API". This specification serves as the foundational "code" for your API documentation.


API Documentation Generator: Generated OpenAPI Specification

This output provides

gemini Output

API Documentation: Product Management Service API

Date: October 26, 2023

Version: 1.0.0


1. Introduction

Welcome to the documentation for the Product Management Service API. This API provides a robust and intuitive set of endpoints to manage product information, including creation, retrieval, updates, and deletion of products, categories, and inventory details. It is designed for developers who need to integrate product data into their applications, e-commerce platforms, or internal systems.

Our API follows RESTful principles, uses JSON for request and response bodies, and relies on API Key authentication for secure access. This documentation will guide you through setting up your environment, authenticating your requests, understanding our data models, and interacting with all available endpoints.

2. Getting Started

To begin using the Product Management Service API, follow these quick steps:

  1. Obtain an API Key: Register on our [Developer Portal](https://developer.example.com/register) to generate your unique API Key.
  2. Understand Authentication: Familiarize yourself with how to include your API Key in your requests (see Section 3).
  3. Explore Endpoints: Review the available API endpoints and their functionalities (see Section 7).
  4. Make Your First Request: Use the provided examples to make a test call to the API.

3. Authentication

The Product Management Service API uses API Key authentication to secure access to its resources. Your API Key must be included in the X-API-Key HTTP header for every request.

How to Authenticate:

  • Header Name: X-API-Key
  • Header Value: Your unique API Key (e.g., your_api_key_1234567890)

Example:


GET /products HTTP/1.1
Host: api.example.com
X-API-Key: your_api_key_1234567890

Security Best Practices:

  • Keep your API Key confidential. Do not expose it in client-side code, public repositories, or unsecured environments.
  • Use environment variables or secure configuration management systems to store and access your API Key in server-side applications.
  • Regenerate your API Key immediately if you suspect it has been compromised.

4. Base URL

All requests to the Product Management Service API should be prefixed with the following base URL:

https://api.example.com/v1

Example:

To access the products endpoint, you would make a request to:

https://api.example.com/v1/products

5. Rate Limiting

To ensure fair usage and maintain API stability, the Product Management Service API enforces rate limits.

  • Limit: 100 requests per minute per API Key.
  • Exceeding the Limit: If you exceed the rate limit, the API will return a 429 Too Many Requests HTTP status code.
  • Headers: The following headers are included in every response to help you manage your request volume:

* X-RateLimit-Limit: The maximum number of requests allowed in the current window.

* X-RateLimit-Remaining: The number of requests remaining in the current window.

* X-RateLimit-Reset: The UTC timestamp (in seconds since epoch) when the current rate limit window resets.

Please design your applications to handle 429 responses gracefully, implementing retries with exponential backoff if necessary.

6. Error Handling

The API uses standard HTTP status codes to indicate the success or failure of an API request. In case of an error, the API will return a JSON object containing an error code and a descriptive message.

| HTTP Status Code | Description | Error Object Example |

| :--------------- | :------------------------------------------- | :------------------------------------------------- |

| 200 OK | Request successful. | N/A (successful response body) |

| 201 Created | Resource successfully created. | N/A (successful response body) |

| 204 No Content | Request successful, no content to return. | N/A |

| 400 Bad Request| Invalid request payload or parameters. | { "code": "INVALID_INPUT", "message": "Product name is required." } |

| 401 Unauthorized| Missing or invalid API Key. | { "code": "UNAUTHORIZED", "message": "Invalid or missing API Key." } |

| 403 Forbidden | API Key lacks permissions for this action. | { "code": "FORBIDDEN", "message": "Access denied for this resource." } |

| 404 Not Found | The requested resource does not exist. | { "code": "NOT_FOUND", "message": "Product with ID '123' not found." } |

| 405 Method Not Allowed| The HTTP method used is not supported for the resource. | { "code": "METHOD_NOT_ALLOWED", "message": "GET method not supported for this endpoint." } |

| 409 Conflict | Resource conflict (e.g., trying to create a resource that already exists with a unique identifier). | { "code": "RESOURCE_CONFLICT", "message": "Product with SKU 'PROD-001' already exists." } |

| 429 Too Many Requests| Rate limit exceeded. | { "code": "RATE_LIMIT_EXCEEDED", "message": "Too many requests. Please try again later." } |

| 500 Internal Server Error| An unexpected error occurred on the server. | { "code": "INTERNAL_SERVER_ERROR", "message": "An unexpected error occurred. Please try again or contact support." } |

7. Data Formats

All requests and responses use JSON (JavaScript Object Notation) format.

  • Request Headers: When sending a request body, ensure your Content-Type header is set to application/json.
  • Response Headers: The API will always respond with a Content-Type header of application/json.

8. API Endpoints

This section details all available API endpoints. Each endpoint description includes its HTTP method, path, purpose, parameters, and examples for requests and responses.

8.1. Products

##### 8.1.1. Get All Products

Retrieves a list of all products. Supports pagination and filtering.

  • HTTP Method: GET
  • Path: /products

Parameters:

| Name | Type | Location | Required | Description | Example |

| :-------- | :------- | :------- | :------- | :------------------------------------------------------------- | :-------- |

| limit | integer| Query | Optional | Maximum number of products to return (default: 10, max: 100). | ?limit=20 |

| offset | integer| Query | Optional | Number of products to skip for pagination (default: 0). | ?offset=20 |

| category| string | Query | Optional | Filter products by category name. | ?category=Electronics |

| status | string | Query | Optional | Filter products by status (active, inactive, draft). | ?status=active |

Request Example (cURL):


curl -X GET \
  'https://api.example.com/v1/products?limit=5&category=Electronics' \
  -H 'X-API-Key: your_api_key_1234567890'

Request Example (Python):


import requests

api_key = "your_api_key_1234567890"
base_url = "https://api.example.com/v1"

headers = {
    "X-API-Key": api_key,
    "Content-Type": "application/json"
}
params = {
    "limit": 5,
    "category": "Electronics"
}

response = requests.get(f"{base_url}/products", headers=headers, params=params)

if response.status_code == 200:
    print(response.json())
else:
    print(f"Error: {response.status_code} - {response.json()}")

Successful Response Example (200 OK):


[
  {
    "id": "prod_abc123",
    "sku": "ELC-TV-001",
    "name": "Smart LED TV 55-inch",
    "description": "High-definition 4K Smart TV with HDR support.",
    "price": 799.99,
    "currency": "USD",
    "category": "Electronics",
    "status": "active",
    "stock_quantity": 50,
    "created_at": "2023-01-15T10:00:00Z",
    "updated_at": "2023-10-20T14:30:00Z"
  },
  {
    "id": "prod_def456",
    "sku": "ELC-PHONE-007",
    "name": "Smartphone X Pro",
    "description": "Next-gen smartphone with advanced camera and long-lasting battery.",
    "price": 1099.00,
    "currency": "USD",
    "category": "Electronics",
    "status": "active",
    "stock_quantity": 120,
    "created_at": "2023-03-01T09:00:00Z",
    "updated_at": "2023-10-25T11:00:00Z"
  }
]

Error Response Example (401 Unauthorized):


{
  "code": "UNAUTHORIZED",
  "message": "Invalid or missing API Key."
}

##### 8.1.2. Get Product by ID

Retrieves details for a specific product using its unique identifier.

  • HTTP Method: GET
  • Path: /products/{product_id}

Parameters:

| Name | Type | Location | Required | Description | Example |

| :----------- | :------- | :------- | :------- | :--------------------------- | :---------------- |

| product_id | string | Path | Yes | The unique ID of the product.| prod_abc123 |

Request Example (cURL):


curl -X GET \
  'https://api.example.com/v1/products/prod_abc123' \
  -H 'X-API-Key: your_api_key_1234567890'

Successful Response Example (200 OK):


{
  "id": "prod_abc123",
  "sku": "ELC-TV-001",
  "name": "Smart LED TV 55-inch",
  "description": "High-definition 4K Smart TV with HDR support.",
  "price": 799.99,
  "currency": "USD",
  "category": "Electronics",
  "status": "active",
  "stock_quantity": 50,
  "created_at": "2023-01-15T10:00:00Z",
  "updated_at": "2023-10-20T14:30:00Z"
}

Error Response Example (404 Not Found):


{
  "code": "NOT_FOUND",
  "message": "Product with ID 'prod_xyz789' not found."
}

##### 8.1.3. Create New Product

Creates a new product entry in the system.

  • HTTP Method: POST
  • Path: /products

Parameters (Request Body):

| Name | Type | Required | Description | Example |

| :--------------- | :------- | :------- | :------------------------------------------------------------- | :--------------------------------------------------- |

| sku | string | Yes | Unique Stock Keeping Unit for the product. | "NEW-PROD-001" |

| name | string | Yes | Name of the product. | "Wireless Bluetooth Earbuds" |

| description | string | Optional | Detailed description of the product. | "Noise-cancelling earbuds with 24hr battery life." |

| price | number | Yes | Price of the product. | 49.99 |

| currency | string | Yes | Currency code (e.g., USD, EUR). | "USD" |

| category | string | Optional | Product category. | "Audio" |

| status | string | Optional | Product status (active, inactive, draft). Default is draft. | "active" |

| stock_quantity | integer| Optional | Initial stock quantity. Default is 0. | 200 |

Request Example (cURL):


curl -X POST \
  'https://api.example.com/v1/products' \
  -H 'X-API-Key: your_api_key_1234567890' \
api_documentation_generator.txt
Download source file
Copy all content
Full output as text
Download ZIP
IDE-ready project ZIP
Copy share link
Permanent URL for this run
Get Embed Code
Embed this result on any website
Print / Save PDF
Use browser print dialog
\n\n\n"); var hasSrcMain=Object.keys(extracted).some(function(k){return k.indexOf("src/main")>=0;}); if(!hasSrcMain) zip.file(folder+"src/main."+ext,"import React from 'react'\nimport ReactDOM from 'react-dom/client'\nimport App from './App'\nimport './index.css'\n\nReactDOM.createRoot(document.getElementById('root')!).render(\n \n \n \n)\n"); var hasSrcApp=Object.keys(extracted).some(function(k){return k==="src/App."+ext||k==="App."+ext;}); if(!hasSrcApp) zip.file(folder+"src/App."+ext,"import React from 'react'\nimport './App.css'\n\nfunction App(){\n return(\n
\n
\n

"+slugTitle(pn)+"

\n

Built with PantheraHive BOS

\n
\n
\n )\n}\nexport default App\n"); zip.file(folder+"src/index.css","*{margin:0;padding:0;box-sizing:border-box}\nbody{font-family:system-ui,-apple-system,sans-serif;background:#f0f2f5;color:#1a1a2e}\n.app{min-height:100vh;display:flex;flex-direction:column}\n.app-header{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;padding:40px}\nh1{font-size:2.5rem;font-weight:700}\n"); zip.file(folder+"src/App.css",""); zip.file(folder+"src/components/.gitkeep",""); zip.file(folder+"src/pages/.gitkeep",""); zip.file(folder+"src/hooks/.gitkeep",""); Object.keys(extracted).forEach(function(p){ var fp=p.startsWith("src/")?p:"src/"+p; zip.file(folder+fp,extracted[p]); }); zip.file(folder+"README.md","# "+slugTitle(pn)+"\n\nGenerated by PantheraHive BOS.\n\n## Setup\n\`\`\`bash\nnpm install\nnpm run dev\n\`\`\`\n\n## Build\n\`\`\`bash\nnpm run build\n\`\`\`\n\n## Open in IDE\nOpen the project folder in VS Code or WebStorm.\n"); zip.file(folder+".gitignore","node_modules/\ndist/\n.env\n.DS_Store\n*.local\n"); } /* --- Vue (Vite + Composition API + TypeScript) --- */ function buildVue(zip,folder,app,code,panelTxt){ var pn=pkgName(app); var C=cc(pn); var extracted=extractCode(panelTxt); zip.file(folder+"package.json",'{\n "name": "'+pn+'",\n "version": "0.0.0",\n "type": "module",\n "scripts": {\n "dev": "vite",\n "build": "vue-tsc -b && vite build",\n "preview": "vite preview"\n },\n "dependencies": {\n "vue": "^3.5.13",\n "vue-router": "^4.4.5",\n "pinia": "^2.3.0",\n "axios": "^1.7.9"\n },\n "devDependencies": {\n "@vitejs/plugin-vue": "^5.2.1",\n "typescript": "~5.7.3",\n "vite": "^6.0.5",\n "vue-tsc": "^2.2.0"\n }\n}\n'); zip.file(folder+"vite.config.ts","import { defineConfig } from 'vite'\nimport vue from '@vitejs/plugin-vue'\nimport { resolve } from 'path'\n\nexport default defineConfig({\n plugins: [vue()],\n resolve: { alias: { '@': resolve(__dirname,'src') } }\n})\n"); zip.file(folder+"tsconfig.json",'{"files":[],"references":[{"path":"./tsconfig.app.json"},{"path":"./tsconfig.node.json"}]}\n'); zip.file(folder+"tsconfig.app.json",'{\n "compilerOptions":{\n "target":"ES2020","useDefineForClassFields":true,"module":"ESNext","lib":["ES2020","DOM","DOM.Iterable"],\n "skipLibCheck":true,"moduleResolution":"bundler","allowImportingTsExtensions":true,\n "isolatedModules":true,"moduleDetection":"force","noEmit":true,"jsxImportSource":"vue",\n "strict":true,"paths":{"@/*":["./src/*"]}\n },\n "include":["src/**/*.ts","src/**/*.d.ts","src/**/*.tsx","src/**/*.vue"]\n}\n'); zip.file(folder+"env.d.ts","/// \n"); zip.file(folder+"index.html","\n\n\n \n \n "+slugTitle(pn)+"\n\n\n
\n \n\n\n"); var hasMain=Object.keys(extracted).some(function(k){return k==="src/main.ts"||k==="main.ts";}); if(!hasMain) zip.file(folder+"src/main.ts","import { createApp } from 'vue'\nimport { createPinia } from 'pinia'\nimport App from './App.vue'\nimport './assets/main.css'\n\nconst app = createApp(App)\napp.use(createPinia())\napp.mount('#app')\n"); var hasApp=Object.keys(extracted).some(function(k){return k.indexOf("App.vue")>=0;}); if(!hasApp) zip.file(folder+"src/App.vue","\n\n\n\n\n"); zip.file(folder+"src/assets/main.css","*{margin:0;padding:0;box-sizing:border-box}body{font-family:system-ui,sans-serif;background:#fff;color:#213547}\n"); zip.file(folder+"src/components/.gitkeep",""); zip.file(folder+"src/views/.gitkeep",""); zip.file(folder+"src/stores/.gitkeep",""); Object.keys(extracted).forEach(function(p){ var fp=p.startsWith("src/")?p:"src/"+p; zip.file(folder+fp,extracted[p]); }); zip.file(folder+"README.md","# "+slugTitle(pn)+"\n\nGenerated by PantheraHive BOS.\n\n## Setup\n\`\`\`bash\nnpm install\nnpm run dev\n\`\`\`\n\n## Build\n\`\`\`bash\nnpm run build\n\`\`\`\n\nOpen in VS Code or WebStorm.\n"); zip.file(folder+".gitignore","node_modules/\ndist/\n.env\n.DS_Store\n*.local\n"); } /* --- Angular (v19 standalone) --- */ function buildAngular(zip,folder,app,code,panelTxt){ var pn=pkgName(app); var C=cc(pn); var sel=pn.replace(/_/g,"-"); var extracted=extractCode(panelTxt); zip.file(folder+"package.json",'{\n "name": "'+pn+'",\n "version": "0.0.0",\n "scripts": {\n "ng": "ng",\n "start": "ng serve",\n "build": "ng build",\n "test": "ng test"\n },\n "dependencies": {\n "@angular/animations": "^19.0.0",\n "@angular/common": "^19.0.0",\n "@angular/compiler": "^19.0.0",\n "@angular/core": "^19.0.0",\n "@angular/forms": "^19.0.0",\n "@angular/platform-browser": "^19.0.0",\n "@angular/platform-browser-dynamic": "^19.0.0",\n "@angular/router": "^19.0.0",\n "rxjs": "~7.8.0",\n "tslib": "^2.3.0",\n "zone.js": "~0.15.0"\n },\n "devDependencies": {\n "@angular-devkit/build-angular": "^19.0.0",\n "@angular/cli": "^19.0.0",\n "@angular/compiler-cli": "^19.0.0",\n "typescript": "~5.6.0"\n }\n}\n'); zip.file(folder+"angular.json",'{\n "$schema": "./node_modules/@angular/cli/lib/config/schema.json",\n "version": 1,\n "newProjectRoot": "projects",\n "projects": {\n "'+pn+'": {\n "projectType": "application",\n "root": "",\n "sourceRoot": "src",\n "prefix": "app",\n "architect": {\n "build": {\n "builder": "@angular-devkit/build-angular:application",\n "options": {\n "outputPath": "dist/'+pn+'",\n "index": "src/index.html",\n "browser": "src/main.ts",\n "tsConfig": "tsconfig.app.json",\n "styles": ["src/styles.css"],\n "scripts": []\n }\n },\n "serve": {"builder":"@angular-devkit/build-angular:dev-server","configurations":{"production":{"buildTarget":"'+pn+':build:production"},"development":{"buildTarget":"'+pn+':build:development"}},"defaultConfiguration":"development"}\n }\n }\n }\n}\n'); zip.file(folder+"tsconfig.json",'{\n "compileOnSave": false,\n "compilerOptions": {"baseUrl":"./","outDir":"./dist/out-tsc","forceConsistentCasingInFileNames":true,"strict":true,"noImplicitOverride":true,"noPropertyAccessFromIndexSignature":true,"noImplicitReturns":true,"noFallthroughCasesInSwitch":true,"paths":{"@/*":["src/*"]},"skipLibCheck":true,"esModuleInterop":true,"sourceMap":true,"declaration":false,"experimentalDecorators":true,"moduleResolution":"bundler","importHelpers":true,"target":"ES2022","module":"ES2022","useDefineForClassFields":false,"lib":["ES2022","dom"]},\n "references":[{"path":"./tsconfig.app.json"}]\n}\n'); zip.file(folder+"tsconfig.app.json",'{\n "extends":"./tsconfig.json",\n "compilerOptions":{"outDir":"./dist/out-tsc","types":[]},\n "files":["src/main.ts"],\n "include":["src/**/*.d.ts"]\n}\n'); zip.file(folder+"src/index.html","\n\n\n \n "+slugTitle(pn)+"\n \n \n \n\n\n \n\n\n"); zip.file(folder+"src/main.ts","import { bootstrapApplication } from '@angular/platform-browser';\nimport { appConfig } from './app/app.config';\nimport { AppComponent } from './app/app.component';\n\nbootstrapApplication(AppComponent, appConfig)\n .catch(err => console.error(err));\n"); zip.file(folder+"src/styles.css","* { margin: 0; padding: 0; box-sizing: border-box; }\nbody { font-family: system-ui, -apple-system, sans-serif; background: #f9fafb; color: #111827; }\n"); var hasComp=Object.keys(extracted).some(function(k){return k.indexOf("app.component")>=0;}); if(!hasComp){ zip.file(folder+"src/app/app.component.ts","import { Component } from '@angular/core';\nimport { RouterOutlet } from '@angular/router';\n\n@Component({\n selector: 'app-root',\n standalone: true,\n imports: [RouterOutlet],\n templateUrl: './app.component.html',\n styleUrl: './app.component.css'\n})\nexport class AppComponent {\n title = '"+pn+"';\n}\n"); zip.file(folder+"src/app/app.component.html","
\n
\n

"+slugTitle(pn)+"

\n

Built with PantheraHive BOS

\n
\n \n
\n"); zip.file(folder+"src/app/app.component.css",".app-header{display:flex;flex-direction:column;align-items:center;justify-content:center;min-height:60vh;gap:16px}h1{font-size:2.5rem;font-weight:700;color:#6366f1}\n"); } zip.file(folder+"src/app/app.config.ts","import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';\nimport { provideRouter } from '@angular/router';\nimport { routes } from './app.routes';\n\nexport const appConfig: ApplicationConfig = {\n providers: [\n provideZoneChangeDetection({ eventCoalescing: true }),\n provideRouter(routes)\n ]\n};\n"); zip.file(folder+"src/app/app.routes.ts","import { Routes } from '@angular/router';\n\nexport const routes: Routes = [];\n"); Object.keys(extracted).forEach(function(p){ var fp=p.startsWith("src/")?p:"src/"+p; zip.file(folder+fp,extracted[p]); }); zip.file(folder+"README.md","# "+slugTitle(pn)+"\n\nGenerated by PantheraHive BOS.\n\n## Setup\n\`\`\`bash\nnpm install\nng serve\n# or: npm start\n\`\`\`\n\n## Build\n\`\`\`bash\nng build\n\`\`\`\n\nOpen in VS Code with Angular Language Service extension.\n"); zip.file(folder+".gitignore","node_modules/\ndist/\n.env\n.DS_Store\n*.local\n.angular/\n"); } /* --- Python --- */ function buildPython(zip,folder,app,code){ var title=slugTitle(app); var pn=pkgName(app); var src=code.replace(/^\`\`\`[\w]*\n?/m,"").replace(/\n?\`\`\`$/m,"").trim(); var reqMap={"numpy":"numpy","pandas":"pandas","sklearn":"scikit-learn","tensorflow":"tensorflow","torch":"torch","flask":"flask","fastapi":"fastapi","uvicorn":"uvicorn","requests":"requests","sqlalchemy":"sqlalchemy","pydantic":"pydantic","dotenv":"python-dotenv","PIL":"Pillow","cv2":"opencv-python","matplotlib":"matplotlib","seaborn":"seaborn","scipy":"scipy"}; var reqs=[]; Object.keys(reqMap).forEach(function(k){if(src.indexOf("import "+k)>=0||src.indexOf("from "+k)>=0)reqs.push(reqMap[k]);}); var reqsTxt=reqs.length?reqs.join("\n"):"# add dependencies here\n"; zip.file(folder+"main.py",src||"# "+title+"\n# Generated by PantheraHive BOS\n\nprint(title+\" loaded\")\n"); zip.file(folder+"requirements.txt",reqsTxt); zip.file(folder+".env.example","# Environment variables\n"); zip.file(folder+"README.md","# "+title+"\n\nGenerated by PantheraHive BOS.\n\n## Setup\n\`\`\`bash\npython3 -m venv .venv\nsource .venv/bin/activate\npip install -r requirements.txt\n\`\`\`\n\n## Run\n\`\`\`bash\npython main.py\n\`\`\`\n"); zip.file(folder+".gitignore",".venv/\n__pycache__/\n*.pyc\n.env\n.DS_Store\n"); } /* --- Node.js --- */ function buildNode(zip,folder,app,code){ var title=slugTitle(app); var pn=pkgName(app); var src=code.replace(/^\`\`\`[\w]*\n?/m,"").replace(/\n?\`\`\`$/m,"").trim(); var depMap={"mongoose":"^8.0.0","dotenv":"^16.4.5","axios":"^1.7.9","cors":"^2.8.5","bcryptjs":"^2.4.3","jsonwebtoken":"^9.0.2","socket.io":"^4.7.4","uuid":"^9.0.1","zod":"^3.22.4","express":"^4.18.2"}; var deps={}; Object.keys(depMap).forEach(function(k){if(src.indexOf(k)>=0)deps[k]=depMap[k];}); if(!deps["express"])deps["express"]="^4.18.2"; var pkgJson=JSON.stringify({"name":pn,"version":"1.0.0","main":"src/index.js","scripts":{"start":"node src/index.js","dev":"nodemon src/index.js"},"dependencies":deps,"devDependencies":{"nodemon":"^3.0.3"}},null,2)+"\n"; zip.file(folder+"package.json",pkgJson); var fallback="const express=require(\"express\");\nconst app=express();\napp.use(express.json());\n\napp.get(\"/\",(req,res)=>{\n res.json({message:\""+title+" API\"});\n});\n\nconst PORT=process.env.PORT||3000;\napp.listen(PORT,()=>console.log(\"Server on port \"+PORT));\n"; zip.file(folder+"src/index.js",src||fallback); zip.file(folder+".env.example","PORT=3000\n"); zip.file(folder+".gitignore","node_modules/\n.env\n.DS_Store\n"); zip.file(folder+"README.md","# "+title+"\n\nGenerated by PantheraHive BOS.\n\n## Setup\n\`\`\`bash\nnpm install\n\`\`\`\n\n## Run\n\`\`\`bash\nnpm run dev\n\`\`\`\n"); } /* --- Vanilla HTML --- */ function buildVanillaHtml(zip,folder,app,code){ var title=slugTitle(app); var isFullDoc=code.trim().toLowerCase().indexOf("=0||code.trim().toLowerCase().indexOf("=0; var indexHtml=isFullDoc?code:"\n\n\n\n\n"+title+"\n\n\n\n"+code+"\n\n\n\n"; zip.file(folder+"index.html",indexHtml); zip.file(folder+"style.css","/* "+title+" — styles */\n*{margin:0;padding:0;box-sizing:border-box}\nbody{font-family:system-ui,-apple-system,sans-serif;background:#fff;color:#1a1a2e}\n"); zip.file(folder+"script.js","/* "+title+" — scripts */\n"); zip.file(folder+"assets/.gitkeep",""); zip.file(folder+"README.md","# "+title+"\n\nGenerated by PantheraHive BOS.\n\n## Open\nDouble-click \`index.html\` in your browser.\n\nOr serve locally:\n\`\`\`bash\nnpx serve .\n# or\npython3 -m http.server 3000\n\`\`\`\n"); zip.file(folder+".gitignore",".DS_Store\nnode_modules/\n.env\n"); } /* ===== MAIN ===== */ var sc=document.createElement("script"); sc.src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js"; sc.onerror=function(){ if(lbl)lbl.textContent="Download ZIP"; alert("JSZip load failed — check connection."); }; sc.onload=function(){ var zip=new JSZip(); var base=(_phFname||"output").replace(/\.[^.]+$/,""); var app=base.toLowerCase().replace(/[^a-z0-9]+/g,"_").replace(/^_+|_+$/g,"")||"my_app"; var folder=app+"/"; var vc=document.getElementById("panel-content"); var panelTxt=vc?(vc.innerText||vc.textContent||""):""; var lang=detectLang(_phCode,panelTxt); if(_phIsHtml){ buildVanillaHtml(zip,folder,app,_phCode); } else if(lang==="flutter"){ buildFlutter(zip,folder,app,_phCode,panelTxt); } else if(lang==="react-native"){ buildReactNative(zip,folder,app,_phCode,panelTxt); } else if(lang==="swift"){ buildSwift(zip,folder,app,_phCode,panelTxt); } else if(lang==="kotlin"){ buildKotlin(zip,folder,app,_phCode,panelTxt); } else if(lang==="react"){ buildReact(zip,folder,app,_phCode,panelTxt); } else if(lang==="vue"){ buildVue(zip,folder,app,_phCode,panelTxt); } else if(lang==="angular"){ buildAngular(zip,folder,app,_phCode,panelTxt); } else if(lang==="python"){ buildPython(zip,folder,app,_phCode); } else if(lang==="node"){ buildNode(zip,folder,app,_phCode); } else { /* Document/content workflow */ var title=app.replace(/_/g," "); var md=_phAll||_phCode||panelTxt||"No content"; zip.file(folder+app+".md",md); var h=""+title+""; h+="

"+title+"

"; var hc=md.replace(/&/g,"&").replace(//g,">"); hc=hc.replace(/^### (.+)$/gm,"

$1

"); hc=hc.replace(/^## (.+)$/gm,"

$1

"); hc=hc.replace(/^# (.+)$/gm,"

$1

"); hc=hc.replace(/\*\*(.+?)\*\*/g,"$1"); hc=hc.replace(/\n{2,}/g,"

"); h+="

"+hc+"

Generated by PantheraHive BOS
"; zip.file(folder+app+".html",h); zip.file(folder+"README.md","# "+title+"\n\nGenerated by PantheraHive BOS.\n\nFiles:\n- "+app+".md (Markdown)\n- "+app+".html (styled HTML)\n"); } zip.generateAsync({type:"blob"}).then(function(blob){ var a=document.createElement("a"); a.href=URL.createObjectURL(blob); a.download=app+".zip"; a.click(); URL.revokeObjectURL(a.href); if(lbl)lbl.textContent="Download ZIP"; }); }; document.head.appendChild(sc); } function phShare(){navigator.clipboard.writeText(window.location.href).then(function(){var el=document.getElementById("ph-share-lbl");if(el){el.textContent="Link copied!";setTimeout(function(){el.textContent="Copy share link";},2500);}});}function phEmbed(){var runId=window.location.pathname.split("/").pop().replace(".html","");var embedUrl="https://pantherahive.com/embed/"+runId;var code='';navigator.clipboard.writeText(code).then(function(){var el=document.getElementById("ph-embed-lbl");if(el){el.textContent="Embed code copied!";setTimeout(function(){el.textContent="Get Embed Code";},2500);}});}