diff --git a/docs/API_DOCUMENTATION.md b/docs/API_DOCUMENTATION.md new file mode 100644 index 00000000000..e591009984d --- /dev/null +++ b/docs/API_DOCUMENTATION.md @@ -0,0 +1,223 @@ +# UI5 API Documentation Generation Guide + +## Overview + +This guide explains how to generate and use API documentation from UI5 projects, specifically addressing the `build jsdoc` task and the generated `api.json` files. + +## Understanding the Two Documentation Formats + +The UI5 tooling supports two complementary approaches to API documentation: + +### 1. JSDoc HTML Output (Classic Documentation) + +**What it is:** Standard HTML documentation pages generated using JSDoc with custom UI5 plugins and templates. + +**When to use:** +- Quick local documentation browsing +- Internal company documentation portals +- Offline documentation packages +- CI/CD pipelines requiring HTML artifacts + +**How to generate:** +```bash +# For this monorepo +npm run jsdoc-generate + +# For your UI5 library project +ui5 build --all +``` + +**Output location:** `site/api/` directory containing a complete HTML documentation site. + +### 2. API JSON Format (UI5 SDK Integration) + +**What it is:** Structured JSON metadata (`api.json`) following the UI5 API schema, designed for consumption by the official UI5 SDK API reference viewer. + +**When to use:** +- Integration with the official UI5 SDK documentation +- Custom API tooling that consumes structured metadata +- Programmatic API analysis +- Building custom documentation UIs + +**How to generate:** +```bash +# During library build with jsdoc enabled +ui5 build jsdoc + +# The output will be at: +# dist/test-resources//designtime/api.json +``` + +## Working with `api.json` Files + +### Option A: Convert to Simple HTML (Quick & Easy) + +We've added a lightweight converter tool that transforms `api.json` into browsable HTML: + +```bash +# Using the npm script (for workspace-level docs) +npm run apijson-to-html + +# Or directly with custom paths +node tools/convert-apijson-to-html.cjs path/to/api.json output/docs.html +``` + +**Benefits:** +- Zero dependencies beyond Node.js +- Single self-contained HTML file +- Works offline +- Easy to host on any web server + +**Limitations:** +- Simplified UI compared to official UI5 SDK +- No advanced features like inheritance diagrams +- Basic styling only + +See [tools/README.md](tools/README.md) for detailed usage instructions. + +### Option B: Integrate with UI5 SDK API Reference Viewer + +The official UI5 SDK includes an API reference viewer (`apiref`) that provides the full-featured UI5 documentation experience. + +**Steps:** +1. Generate your library's `api.json` using `ui5 build jsdoc` +2. The UI5 builder can combine multiple library `api.json` files using the SDK transformation task +3. Host the combined `api.json` with the UI5 apiref viewer application +4. Configure the apiref viewer to load your custom libraries + +**Note:** This requires access to or hosting of the UI5 SDK infrastructure. For internal use, you may need to set up a custom instance. + +### Option C: Use Standard JSDoc HTML Output + +The simplest approach for most use cases: + +```bash +npm run jsdoc-generate +``` + +This generates complete HTML documentation using: +- The JSDoc engine with UI5-specific plugins +- Custom UI5 templates that understand UI5 semantics +- The Docdash theme (configurable) + +**Output:** `site/api/index.html` and related files + +**To view:** +```bash +# Open in browser +open site/api/index.html + +# Or serve with a local web server +npx http-server site -p 8080 +npx serve site +``` + +## Recommended Workflow for Internal Documentation + +For hosting internal API documentation of custom UI5 libraries: + +### Setup +1. Enable JSDoc generation in your `ui5.yaml`: +```yaml +builder: + jsdoc: + enabled: true +``` + +2. Add proper JSDoc comments to your code following UI5 conventions: +```javascript +/** + * A custom UI5 control for data visualization + * + * @class + * @extends sap.ui.core.Control + * @public + * @alias company.custom.DataChart + */ +``` + +### Build & Generate +```bash +# Build your library with docs +ui5 build jsdoc + +# Option 1: Use the generated api.json with our converter +node tools/convert-apijson-to-html.cjs \ + dist/test-resources/company/custom/designtime/api.json \ + docs/api.html + +# Option 2: Generate full JSDoc HTML (if configured) +npm run jsdoc-generate +``` + +### Host +```bash +# Deploy the generated HTML to your internal docs server +# Examples: +# - Copy to internal web server +# - Deploy to GitHub Pages +# - Use Netlify/Vercel for static hosting +# - Integrate with company documentation portal +``` + +## Configuration Files + +- **jsdoc.json** - JSDoc configuration for local development +- **jsdoc-workspace.json** - JSDoc configuration for workspace/monorepo mode +- **jsdoc-plugin.cjs** - Custom JSDoc plugin for handling UI5-specific syntax +- **packages/builder/lib/processors/jsdoc/** - UI5 builder's JSDoc processing pipeline + +## Future Plans + +There are no current plans in the public roadmap to add HTML output directly to the `build jsdoc` task, as: +1. The standard JSDoc tooling already provides HTML generation +2. The `api.json` format serves the specific purpose of SDK integration +3. Custom HTML generation can be achieved via the converter tool or standard JSDoc + +However, the converter tool (`tools/convert-apijson-to-html.cjs`) provides a pragmatic solution for quick HTML generation from `api.json` files. + +## Common Use Cases + +### Use Case 1: Quick Local Documentation +```bash +npm run jsdoc-generate +open site/api/index.html +``` + +### Use Case 2: Internal Company API Portal +```bash +ui5 build jsdoc +node tools/convert-apijson-to-html.cjs \ + dist/test-resources/*/designtime/api.json \ + company-portal/api-docs.html +# Deploy company-portal/ to internal server +``` + +### Use Case 3: CI/CD Documentation Pipeline +```yaml +# .github/workflows/docs.yml +- name: Generate API Docs + run: | + npm run jsdoc-generate + npm run apijson-to-html + +- name: Deploy to GitHub Pages + uses: peaceiris/actions-gh-pages@v3 + with: + publish_dir: ./site +``` + +## Additional Resources + +- [UI5 Tooling Documentation](https://sap.github.io/ui5-tooling/) +- [JSDoc Official Documentation](https://jsdoc.app/) +- [UI5 SDK (for reference)](https://ui5.sap.com/) +- [tools/README.md](tools/README.md) - Converter tool documentation +- [Contributing Guidelines](CONTRIBUTING.md) + +## Questions & Support + +For questions about UI5 Tooling: +- [Stack Overflow - ui5-cli tag](https://stackoverflow.com/questions/tagged/ui5-cli) +- [OpenUI5 Slack #tooling channel](https://ui5-slack-invite.cfapps.eu10.hana.ondemand.com) +- [GitHub Issues](https://github.com/UI5/cli/issues) diff --git a/package.json b/package.json index 4d7c7af0e31..04d5288d513 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "unit": "npm run unit --workspaces", "coverage": "npm run coverage --workspaces", "jsdoc": "npm run jsdoc-generate && open-cli site/api/index.html", + "apijson-to-html": "node ./tools/convert-apijson-to-html.cjs workspace/apiref/api.json site/api/index.html", "jsdoc-generate": "node ./scripts/isWorkspace.js && npm run jsdoc-generate-workspace || npm run jsdoc-generate-local", "jsdoc-generate-local": "jsdoc -c ./jsdoc.json -t $(node -p 'path.dirname(require.resolve(\"docdash\"))') ./ || (echo 'Error during JSDoc generation! Check log.' && exit 1)", "jsdoc-generate-workspace": "jsdoc -c ./jsdoc-workspace.json -t $(node -p 'path.dirname(require.resolve(\"docdash\"))') ../ || (echo 'Error during JSDoc generation! Check log.' && exit 1)", diff --git a/tools/README.md b/tools/README.md new file mode 100644 index 00000000000..36021d92d0b --- /dev/null +++ b/tools/README.md @@ -0,0 +1,101 @@ +# UI5 CLI Tools + +This directory contains utility scripts for the UI5 CLI project. + +## convert-apijson-to-html.cjs + +A lightweight, dependency-free Node.js script that converts UI5-style `api.json` files into simple, browsable HTML documentation. + +### Purpose + +The UI5 builder's `jsdoc` task generates API metadata in JSON format (`api.json`). While this format is designed for consumption by the official UI5 SDK API reference viewer, you may want to quickly generate standalone HTML documentation for: + +- Internal company API documentation hosting +- Quick local browsing without setting up the full UI5 SDK infrastructure +- CI/CD pipelines that need HTML output +- Offline documentation packages + +### Usage + +**Basic usage:** +```bash +node tools/convert-apijson-to-html.cjs [output.html] +``` + +**Via npm script (recommended):** +```bash +npm run apijson-to-html +``` + +This will convert `workspace/apiref/api.json` to `site/api/index.html`. + +**Custom paths:** +```bash +node tools/convert-apijson-to-html.cjs my-library/api.json docs/api.html +``` + +### Output + +The script generates a single, self-contained HTML file with: +- Table of contents sidebar +- All modules, classes, interfaces, and enums +- Properties and methods with type information +- Code examples (if present in the api.json) +- Clean, responsive styling +- No external dependencies + +### Workflow Integration + +**Option 1: After UI5 build** +```bash +# Generate your UI5 library with jsdoc enabled +ui5 build jsdoc + +# Convert the generated api.json to HTML +node tools/convert-apijson-to-html.cjs dist/test-resources/your-lib/designtime/api.json docs/api.html +``` + +**Option 2: Workspace-level documentation** +After running the UI5 builder's SDK transformation (which combines multiple library api.json files): +```bash +npm run apijson-to-html +``` + +### Serving the Generated HTML + +Use any static file server: +```bash +# Using http-server +npx http-server site -p 8080 + +# Using serve +npx serve site + +# Or open directly in browser +open site/api/index.html +``` + +### Limitations + +This converter is intentionally simple and focused. It does **not**: +- Replicate the full UI5 SDK API reference UI styling +- Generate complex inheritance diagrams +- Provide advanced search functionality +- Support all possible api.json schema variations + +For the full official UI5 API reference experience, integrate your `api.json` files with the UI5 SDK API reference viewer. + +### Extending the Converter + +The script is designed to be easily extensible. Common enhancements: +- Add cross-reference links between classes +- Include inheritance chains +- Generate a search index +- Add syntax highlighting for code examples +- Customize the CSS styling +- Support additional metadata fields + +### See Also + +- [UI5 Builder JSDoc Documentation](../packages/builder/README.md) +- [Contributing Guidelines](../CONTRIBUTING.md) diff --git a/tools/convert-apijson-to-html.cjs b/tools/convert-apijson-to-html.cjs new file mode 100755 index 00000000000..1be56bb17e2 --- /dev/null +++ b/tools/convert-apijson-to-html.cjs @@ -0,0 +1,114 @@ +#!/usr/bin/env node +/* + * Minimal converter: turn a UI5-style api.json into a simple static HTML reference. + * Usage: node tools/convert-apijson-to-html.cjs [output.html] + * + * This is intentionally small and dependency-free. It produces a basic Table of Contents + * and a simple rendering of entities (modules/classes/interfaces) with properties and methods. + * + * Extend as needed (links, inheritance, examples). + */ +const fs = require("fs"); +const path = require("path"); + +function usage() { + console.error("Usage: node tools/convert-apijson-to-html.cjs [out.html]"); + process.exit(2); +} + +const src = process.argv[2]; +const out = process.argv[3] || "apiref.html"; +if (!src) usage(); +if (!fs.existsSync(src)) { + console.error("Input file not found:", src); + process.exit(3); +} + +let data; +try { + data = JSON.parse(fs.readFileSync(src, "utf8")); +} catch (err) { + console.error("Failed to read/parse JSON:", err.message); + process.exit(4); +} + +// Helper to safely get arrays +const arr = (v) => Array.isArray(v) ? v : []; + +// Normalize entities from commonly used fields in various api.json shapes +const entities = []; +if (Array.isArray(data.modules)) entities.push(...data.modules.map((e) => ({...e, kind: "module"}))); +if (Array.isArray(data.classes)) entities.push(...data.classes.map((e) => ({...e, kind: "class"}))); +if (Array.isArray(data.interfaces)) entities.push(...data.interfaces.map((e) => ({...e, kind: "interface"}))); +if (Array.isArray(data.enums)) entities.push(...data.enums.map((e) => ({...e, kind: "enum"}))); + +// Fallback: sometimes top-level 'symbols' or 'apis' might exist +if (Array.isArray(data.symbols)) entities.push(...data.symbols.map((e) => ({...e, kind: e.kind || "symbol"}))); + +function escapeHtml(s) { + if (!s && s !== 0) return ""; + return String(s).replace(/&/g, "&").replace(//g, ">"); +} + +function renderEntity(e) { + const title = e.name || e.fullName || "(unknown)"; + const desc = e.description || e.summary || ""; + const props = arr(e.properties).map((p) => `
  • ${escapeHtml(p.name)}${p.type? " (" + escapeHtml(p.type) + ")" : ""} — ${escapeHtml(p.description || "")}
  • `).join("\n"); + const methods = arr(e.methods).map((m) => { + const params = arr(m.params).map((p) => escapeHtml(p.name) + (p.type ? ": " + escapeHtml(p.type) : "")).join(", "); + return `
  • ${escapeHtml(m.name)}(${params})${m.returns ? " → " + escapeHtml(JSON.stringify(m.returns)) + "" : ""} — ${escapeHtml(m.description || "")}
  • `; + }).join("\n"); + const examples = (arr(e.examples).map((ex) => `
    ${escapeHtml(ex)}
    `).join("\n")) || ""; + return `
    +

    ${escapeHtml(title)} ${escapeHtml(e.kind || "")}

    +

    ${escapeHtml(desc)}

    + ${props ? "

    Properties

      " + props + "
    " : ""} + ${methods ? "

    Methods

      " + methods + "
    " : ""} + ${examples ? "

    Examples

    " + examples : ""} +
    `; +} + +const toc = entities.map((e) => `
  • ${escapeHtml(e.name || e.fullName)} ${escapeHtml(e.kind || "")}
  • `).join("\n"); +const body = entities.map(renderEntity).join("\n"); + +const title = escapeHtml(data.name || data.title || "API Reference"); +const html = ` + + + + + ${title} + + + +
    +

    ${title}

    +
    +
    +
    + ${body || "

    No API entities found in this api.json.

    "} +
    + +
    + +`; + +// Ensure output directory exists +const outDir = path.dirname(out); +if (outDir && !fs.existsSync(outDir)) fs.mkdirSync(outDir, {recursive: true}); +fs.writeFileSync(out, html, "utf8"); +console.log("Wrote", out);