UNPKG

rapidoc

Version:

RapiDoc - Open API spec viewer with built in console

371 lines (281 loc) • 20.8 kB
<p align="center"> <img alt="RapiDoc logo" src="https://github.com/rapi-doc/RapiDoc/blob/master/logo.png" width="80px" /> </p> <p align="center"> <img src="https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square"/> </p> # RapiDoc **Custom Element for OpenAPI / Swagger Spec Viewing** RapiDoc is a fast, responsive, and customizable Web Component that renders beautiful, interactive API documentation from OpenAPI (Swagger) specifications. --- ## Features - **OpenAPI Support:** Full support for OpenAPI 3.0.x, 3.1.x, and Swagger 2.0. - **Framework Agnostic:** Works with plain HTML, React, Vue, Angular, Svelte, or Lit. - **Built-in API Console:** Call and test APIs directly from the documentation. - **Usability First:** - Models and examples expanded by default — no endless clicking to reveal schemas. - Pre-populated sample data in request fields. - Side-by-side request and response view for quick comparison. - **Branding & Theming:** - Dark and Light themes out of the box. - Easily customizable brand colors, typography, logos, and header styling. - **Customizable Layouts:** - Three distinct rendering styles: `read`, `view`, and `focused`. - Inject custom content using web component slots (`fixed-header`, `overview`, `servers`, `auth`). - **Fast & Lightweight:** Built using [Lit](https://lit.dev/) with zero unnecessary overhead. --- ## Quick Usage Include the script in your HTML page and use the `<rapi-doc>` custom element: ```html <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <script type="module" src="https://unpkg.com/rapidoc/dist/rapidoc-min.js"></script> </head> <body> <rapi-doc spec-url="https://petstore.swagger.io/v2/swagger.json" theme="dark" render-style="read" ></rapi-doc> </body> </html> ``` --- ## Repository Architecture This repository is a monorepo built on **npm workspaces** (`packages/*` and `docs`): ```text rapidoc/ ├── packages/ │ ├── rapidoc/ # Core web component library (npm "rapidoc"): <rapi-doc>, <rapi-doc-mini> │ │ ├── src/ # Lit 3 source; each folder has a README.md contract │ │ ├── dist/ # rapidoc-min.js and rapidoc-flow-min.js ("rapidoc/flow"), both for browsers │ │ ├── vite.config.mjs # Browser bundle build │ │ └── vite.config.flow.mjs # <rapi-flow> bundle build │ │ │ ├── rapidoc-prerender/ # @rapidoc/prerender: build-time renderer (pre-rendered <rapi-doc>, sidebar HTML) for Node │ ├── rapidoc-mcp/ # @rapidoc/mcp: MCP manifest builder, runtime and project writer for Node │ │ │ ├── rapidoc-cli/ # @rapidoc/cli, the `rapidoc` command: init, dev, build, serve, mock, validate, migrate │ ├── rapidoc-portal/ # @rapidoc/portal: docs-as-code developer portal for OpenAPI and Markdoc (Astro) │ ├── rapidoc-server/ # @rapidoc/server: serves a built portal with OpenID Connect sign-in and access rules │ ├── rapidoc-mock/ # @rapidoc/mock: mock server for a portal's APIs, with OAuth scope checks │ └── create-rapidoc/ # create-rapidoc: scaffolds a new portal (npm create rapidoc) │ ├── docs/ # Astro + Starlight documentation and showcase site (GitHub Pages) │ ├── src/ │ │ ├── content/docs/ # Documentation pages │ │ ├── pages/examples/ # Public showcase pages │ │ ├── pages/tests/ # Internal test and edge-case pages │ │ └── page-data/ # YAML data for attribute tables and the example list │ ├── public/ │ │ ├── specs/ # Public showcase specs (used by /examples) │ │ └── specs-test/ # Internal edge-case specs │ │ └── parser/ # Malformed and invalid specs for validation tests │ ├── generated-docs/ # Committed build of the site; the docs build refreshes only its rapidoc-min.js │ └── astro.config.mjs # Astro site configuration │ ├── tests/ # See tests/README.md │ ├── unit/ # Node test runner: parser, schema, templates, static renderer │ ├── component/ # Lit component tests │ ├── e2e/ # Functional tests in a headless browser (playwright-core) │ ├── perf/ # Spec parsing and rendering benchmarks │ ├── fixtures/ # Shared specs and the HTML test harness │ └── helpers/ # Test server and browser helpers │ ├── scripts/ # Build info capture, demo prerender, test loader ├── docker/ # Dockerfile and Nginx config for hosting RapiDoc ├── brand/ # Logo SVGs and usage notes ├── package.json # Monorepo root: npm workspaces (packages/*, docs) and scripts ├── AGENTS.md # Guidance for contributors and coding agents └── README.md ``` --- ## Development & Build Instructions ### Prerequisites - **Node.js**: `>= 22.12.0` (or [Bun](https://bun.sh/)) - **npm** (or `bun`) ### 1. Installation Clone the repository and install dependencies across all workspaces: ```bash git clone https://github.com/rapi-doc/RapiDoc.git cd RapiDoc npm install ``` ### 2. Development Server & Live Debugging Start the local documentation and interactive examples showcase: ```bash # Start dev server (http://localhost:4321) npm run dev # Stop background dev server npm run stop ``` - Open `http://localhost:4321` in your browser. - **Live Unminified ES Modules:** In development mode (`npm run dev`), the Astro dev server bypasses pre-compiled production bundles and serves live ES modules directly from `packages/rapidoc/src/index.js`. - **Full DevTools & Console Visibility:** All `console.log`, `console.warn`, `console.error`, and `debugger` breakpoints remain completely intact with original file names and exact line numbers (e.g., `rapidoc.js:516`). - **Instant Browser Reloading:** Component changes in `packages/rapidoc/src/` trigger immediate hot reloads without waiting for a full Rollup/Vite compilation cycle. --- ### 3. Build Process & Workspace Integration This monorepo contains multiple packages: the core Web Component library (**`packages/rapidoc`**) and the documentation showcase site (**`docs`**). The build system coordinates them as follows: #### Core Library Production Build (`npm run build:rapidoc`) - **Workspace:** `packages/rapidoc` - **Output:** `packages/rapidoc/dist/rapidoc-min.js` - Compiles the RapiDoc custom element in library mode using [Vite 6](https://vitejs.dev/). - Inlines and bundles runtime dependencies (`lit`, `@scalar/openapi-parser`, `marked`, `microlighter`, `github-slugger`) into a standalone bundle with **zero runtime external dependencies**. - Minifies Lit templates using `@lit-labs/rollup-plugin-minify-html-literals`. - Strips `console.*` and `debugger` calls via a custom esbuild transform for optimal performance and clean production distribution. - Injects the license and version header banner. #### Core Library Development Build (`npm run build:rapidoc:dev`) - **Workspace:** `packages/rapidoc` - **Output:** `packages/rapidoc/dist/rapidoc-min.js` + `packages/rapidoc/dist/rapidoc-min.js.map` - Compiles the standalone library bundle with `mode: 'development'`. - Disables template and esbuild minification, preserves all `console` and `debugger` statements, and emits full external source maps. - Useful when you need to test the bundled `<rapi-doc>` script tag artifact in external standalone HTML pages or apps with full DevTools logging. #### Full Monorepo Build (`npm run build`) - **Scope:** Root monorepo - Sequentially executes `npm run build:rapidoc` followed by `npm run build:docs`. --- ### 4. How Astro Docs Consumes RapiDoc (`rapidoc-min.js`) Astro documentation and example pages include the component via `<script type="module" src="/rapidoc/rapidoc-min.js"></script>`. How this URL is resolved depends on whether you are developing locally or generating a production build: 1. **During Local Development (`npm run dev`):** - The Astro dev server middleware (in `docs/astro.config.mjs`) **intercepts** all requests for `/rapidoc/rapidoc-min.js` (and `/rapidoc/rapidoc.js`). - Instead of reading any pre-built static file, it directly imports and serves `packages/rapidoc/src/index.js` live through Vite's module pipeline. - You get instant HMR, unminified source code, active `console.*` logging, and sourcemaps with exact line numbers in browser DevTools. Neither `dist/` nor `generated-docs/` is served during development. 2. **During Production Site Build (`npm run build:docs` / `npm run build`):** - The custom `build-rapidoc` Vite plugin in `docs/astro.config.mjs` runs during build initialization: 1. It verifies that `packages/rapidoc/dist/rapidoc-min.js` is compiled (triggering a Vite library build if missing). 2. It copies `packages/rapidoc/dist/rapidoc-min.js` into **`docs/dist/rapidoc/rapidoc-min.js`**, so that the static site deployed to GitHub Pages serves the production bundle. 3. If the local **`docs/generated-docs/`** directory exists, it also synchronizes `rapidoc-min.js` into **`docs/generated-docs/rapidoc/rapidoc-min.js`** to keep the static snapshot folder up to date with the newly built component. --- ### 5. NPM Command Reference All primary commands can be run from the root of the repository: #### Development & Live Preview | Command | Workspace | Description | | ----------------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------- | | `npm run dev` | `docs` | Launches Astro documentation & showcase dev server (`http://localhost:4321`) with live unminified RapiDoc ESM directly from source. | | `npm run stop` | `docs` | Terminates background Astro dev server processes. | | `npm run preview` | `docs` | Previews the production build of the documentation site (`docs/dist`) locally. | #### Building | Command | Workspace | Description | | --------------------------- | --------- | --------------------------------------------------------------------------------------------------------- | | `npm run build` | Monorepo | Sequentially builds production RapiDoc library bundle and the Astro documentation site. | | `npm run build:rapidoc` | `rapidoc` | Compiles production, minified Web Component bundle to `packages/rapidoc/dist/rapidoc-min.js`. | | `npm run build:rapidoc:dev` | `rapidoc` | Compiles unminified Web Component bundle with source maps & console logs to `packages/rapidoc/dist/`. | | `npm run build:docs` | `docs` | Builds the production Astro documentation site into `docs/dist/` (and syncs bundle to `generated-docs/`). | | `npm run build:size` | `rapidoc` | Builds RapiDoc with `ANALYZE=true` and opens an interactive bundle visualizer (`dist/stats.html`). | #### Testing & Benchmarks | Command | Workspace | Description | | --------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------ | | `npm run test:unit` | Monorepo | Runs Node.js native unit tests (`tests/unit/*.test.js`) for schema parsers and AST converters. | | `npm run test:perf` | Monorepo | Runs spec parsing, circular ref, and dereferencing benchmarks (`tests/perf/benchmark.js`). | | `npm run test:render` | Monorepo | Measures headless browser rendering performance across render styles using Puppeteer (`tests/perf/render-benchmark.js`). | #### Code Quality & Formatting | Command | Workspace | Description | | -------------------- | --------- | -------------------------------------------------------------------------------------- | | `npm run lint` | Monorepo | Runs oxlint (default rules, no config) across packages, docs, tests and scripts. | | `npm run format` | Monorepo | Checks formatting with oxfmt (default style) across packages, docs, tests and scripts. | | `npm run format-fix` | Monorepo | Formats the same files with oxfmt. | #### Publishing | Command | Workspace | Description | | ------------------------- | --------- | ---------------------------------------------------- | | `npm run publish:rapidoc` | `rapidoc` | Publishes the `rapidoc` package to the npm registry. | --- ## Documentation Site & GitHub Pages Deployment The documentation site is built with modern **Astro** using clean, extensionless URLs (`/api`, `/examples`, `/list`, `/quickstart`). ### Deployment via GitHub Actions When code is pushed to `master` or `main`, the [deploy-docs.yml](file:///Users/mrin/work/rapidoc/.github/workflows/deploy-docs.yml) GitHub Action automatically: 1. Compiles the `rapidoc` library bundle (`packages/rapidoc/dist/rapidoc-min.js`). 2. Builds the Astro documentation site into `docs/dist/` (`npm run build`). 3. Deploys the static output directory (`docs/dist/`) directly to **GitHub Pages** using `@actions/deploy-pages`. > **Note on GitHub Pages Configuration:** > In repository settings under **Settings → Pages**, set **Source** to **GitHub Actions**. This keeps the repository clean by eliminating the need to commit compiled static HTML files into git branches. --- ## Specs Organization OpenAPI specs are organized inside `docs/public/` based on their visibility and purpose: - **`docs/public/specs/`**: Public showcase specs referenced in `docs/src/page-data/example-list.yaml` and displayed on `rapidocui.com` (e.g., `petstore.yaml`, `code-highlight.yaml`, `auth.yaml`). - **`docs/public/specs-test/`**: Internal edge-case and boundary specs used for UI verification and regression tests (e.g., `circular-refs.yaml`, `xxx-of-combinations.yaml`). - **`docs/public/specs-test/parser/`**: Malformed or invalid specs used to test CLI validation and error reporting (e.g., `invalid-syntax.yaml`, `missing-info.yaml`, `broken-ref.yaml`). --- ## Roadmap - [x] Modernize project dependencies (Vite + Astro + Node 22+) - [x] Restructure as a multi-package Monorepo - [ ] Build `rapidoc-cli` for OpenAPI linting and local zero-config previews - [x] Build `rapidoc-portal`, a docs-as-code developer portal, with sign-in (`rapidoc-server`) and mocking (`rapidoc-mock`) - [ ] Automated visual regression testing suite with Playwright - [ ] Web Content Accessibility Guidelines (WCAG 2.1) compliance enhancements --- ## Architecture Contract What this package exposes, what must stay true, and what touches the outside world. Each folder under `src/` has its own `README.md` contract with the detail; this section covers the package as a whole. ### Overview `packages/rapidoc` is a Lit 3 web component library built by Vite into two ES module bundles. It has no runtime dependencies: its libraries are `devDependencies` bundled into those files. Each build writes `dist/<bundle>.LICENSE.txt`, the list of bundled packages with their versions and license notices, and the bundle's banner names it: - `dist/rapidoc-min.js` (`vite.config.mjs`, entry `src/index.js`): registers `<rapi-doc>`, `<rapi-doc-mini>` and `<oauth-receiver>` on import. Production builds are minified, carry the license banner, and have `console.*` and `debugger` removed. - `dist/rapidoc-flow-min.js` (`vite.config.flow.mjs`, entry `src/flow.js`), exported as `rapidoc/flow`: registers `<rapi-flow>`, the Arazzo workflow diagram, with the workflow runtime that runs them in the browser. It bundles its own copy of Lit and `yaml`, so pages that do not load it pay nothing; `rapidoc-min.js` carries no Arazzo runtime. Two Node packages are built from this source: `@rapidoc/prerender` (`packages/rapidoc-prerender`), the build-time renderer that renders these templates and components to HTML, and `@rapidoc/mcp` (`packages/rapidoc-mcp`), the MCP code in `src/utils/` (`mcp-generator.js`, `mcp/`, `arazzo/`). Nothing in `src/` imports either package. ```text spec-url / inline spec ──▶ utils/spec-parser.js ProcessSpec (load, upgrade, dereference, group) │ └─ dispatches before-render on the host ▼ resolvedSpec <rapi-doc> (src/rapidoc.ts) ──▶ templates/ ──▶ components/ (<api-request>, <api-response>, schema views) ├── events: spec-loaded, nav-active-change (components: before-try, after-try, request-aborted) └── utils/mock-interceptor.js patches fetch / XMLHttpRequest while mock-server="true" @rapidoc/prerender ──▶ the same templates and components, serialized by its serializer.js renderTemplateToString (no DOM) ``` ### Folder Contracts - [`src/`](./src/README.md): the three custom elements and the bundle entry. - [`src/components/`](./src/components/README.md): nested elements for request, response and schema panels. - [`src/templates/`](./src/templates/README.md): Lit `html` functions bound to the host. - [`src/utils/`](./src/utils/README.md): spec pipeline, stable anchors, schema, request and mock helpers; [`utils/mcp/`](./src/utils/mcp/README.md) for the MCP manifest, runtime and exported project; [`utils/arazzo/`](./src/utils/arazzo/README.md) for Arazzo workflow diagrams. - [`src/styles/`](./src/styles/README.md): stylesheets and the theme-token contract. - [`../rapidoc-prerender/src/`](../rapidoc-prerender/src/README.md): the `@rapidoc/prerender` renderer, a separate package that renders this folder's templates. ### Global Invariants - **No runtime dependencies for browser users**: everything is bundled into `dist/rapidoc-min.js`. - **One spec shape**: `ProcessSpec` never rejects. It resolves to the parsed spec (`info`, `tags`, `tagGroups`, `components`, `securitySchemes`, `servers`, ...) or to a result with `specLoadError: true`, and templates, components and the static renderer all read it as `this.resolvedSpec`. - **Stable anchors**: operation ids come from `utils/slugger.js` `OperationSlugger`; the static sidebar and `@rapidoc/portal` depend on them and on `nav-active-change`, so changing the rules is a breaking change (see `src/utils/README.md`). - **Boolean-like attributes are strings** (`allow-try="false"`) and are compared as strings. - **Semantic headings and parts**, **theme tokens** and **DSD hydration** follow `packages/rapidoc/AGENTS.md` §5 and are checked by `tests/unit/semantic-markup.test.js` and `tests/unit/css-variables.test.js`. - **Markdown** passes through `utils/sanitize.js` before `unsafeHTML`. In Node there is no `DOMParser`, so the static renderer's markdown is not sanitized. ### Global Side Effects - **Network**: spec and external `$ref` fetches, Try requests from `<api-request>`, OAuth token requests and the sign-in popup. - **Global patching**: the mock server replaces `window.fetch` and three `XMLHttpRequest` prototype methods and restores them on disable; importing `@rapidoc/prerender` installs or wraps `customElements.define`; importing the elements configures the global `marked` instance. - **Storage and messaging**: `localStorage["rapidoc"]` with `persist-auth="true"`; OAuth replies via `window.opener.postMessage` and a `BroadcastChannel`. - **URL and history**: `<rapi-doc>` replaces the location hash when `update-route="true"`; `bindNavBar` pushes or replaces history for portal sidebars. ### Verification From the monorepo root: `npm run test:unit`, then `npm run lint` and `npm run format-fix`. After any change under `src/`, run `npm run build:rapidoc`; never restore `dist/rapidoc-min.js` from git. --- ## License MIT © [Mrinmoy Majumdar](https://github.com/mrin9)