{"_id":"@api-common/spectral-reporter","_rev":"2-6d85ada6bf9e61d8f480b245a85b06df","name":"@api-common/spectral-reporter","dist-tags":{"latest":"0.2.0"},"versions":{"0.1.0":{"name":"@api-common/spectral-reporter","version":"0.1.0","keywords":["spectral","openapi","asyncapi","api-governance","linting","reporter","htmlextra","html-report","api-commons"],"author":{"url":"https://apievangelist.com","name":"API Evangelist"},"license":"Apache-2.0","_id":"@api-common/spectral-reporter@0.1.0","maintainers":[{"name":"api-commons","email":"info@apicommons.org"}],"homepage":"https://reporter.apicommons.org","bugs":{"url":"https://github.com/api-commons/spectral-reporter/issues"},"bin":{"spectral-reporter":"bin/cli.js"},"dist":{"shasum":"5894a0bbd1f5e0e64d4fae64fb65d7bb87d0f2ff","tarball":"https://registry.npmjs.org/@api-common/spectral-reporter/-/spectral-reporter-0.1.0.tgz","fileCount":6,"integrity":"sha512-yq3sAUgE3iMg28On6S5zAuQApMkkW6DuG+l3pV2t81NFcv5jOtPpa2Z1VyywgOfgrL2WuiZkbmjgvYZOYMAcFA==","signatures":[{"sig":"MEUCIGPx3ltY0NrJKfl0Qz1rhgT5otn4Doe6r4yryYGdT2CJAiEAjqWg7FiK6IyOKgdL7YtPSIeADZOeVKdkFsYI7B9kKE8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":49003},"type":"module","engines":{"node":">=18"},"exports":{".":"./src/render-report.js"},"gitHead":"ae6feac96b0c598a3e6e51b635f9a842e3afb4f9","scripts":{"cli":"node bin/cli.js","dev":"vite","test":"node --test","build":"vite build","preview":"vite preview","build:site":"vite build"},"_npmUser":{"name":"api-commons","email":"info@apicommons.org"},"repository":{"url":"git+https://github.com/api-commons/spectral-reporter.git","type":"git"},"_npmVersion":"11.6.2","description":"Turn Stoplight Spectral lint output into a rich, standalone HTML API governance report — inspired by newman-reporter-htmlextra. An API Commons tool.","directories":{},"_nodeVersion":"25.2.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^5.4.11","typescript":"^5.7.2"},"_npmOperationalInternal":{"tmp":"tmp/spectral-reporter_0.1.0_1783109066199_0.6031481500044809","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@api-common/spectral-reporter","version":"0.2.0","description":"Turn Stoplight Spectral lint output into a rich, standalone HTML API governance report — inspired by newman-reporter-htmlextra. An API Commons tool.","type":"module","license":"Apache-2.0","author":{"name":"API Evangelist","url":"https://apievangelist.com"},"homepage":"https://reporter.apicommons.org","repository":{"type":"git","url":"git+https://github.com/api-commons/spectral-reporter.git"},"bugs":{"url":"https://github.com/api-commons/spectral-reporter/issues"},"keywords":["spectral","openapi","asyncapi","api-governance","linting","reporter","htmlextra","html-report","sarif","code-scanning","trends","api-commons"],"bin":{"spectral-reporter":"bin/cli.js"},"exports":{".":"./src/render-report.js","./trends":"./src/render-trends.js","./sarif":"./src/to-sarif.js"},"engines":{"node":">=18"},"scripts":{"test":"node --test","dev":"vite","build:site":"vite build","build":"vite build","preview":"vite preview","cli":"node bin/cli.js"},"devDependencies":{"typescript":"^5.7.2","vite":"^5.4.11"},"publishConfig":{"access":"public"},"gitHead":"31746b2a52b42852de532822d25b35bf5c981cd0","_id":"@api-common/spectral-reporter@0.2.0","_nodeVersion":"25.2.1","_npmVersion":"11.6.2","dist":{"integrity":"sha512-qL0ORoH4F+QWkkY8qiW7fYdVvMYLtZ+siTqbiDsWNVcZdDaq3iXTa6/qxUe4O4wdbHtjEyXH8zQ1Qdg1d6lMjA==","shasum":"121be8f464b0346665dbbed76e7b2b13f77f0f31","tarball":"https://registry.npmjs.org/@api-common/spectral-reporter/-/spectral-reporter-0.2.0.tgz","fileCount":13,"unpackedSize":111634,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCnChJLwi04cMrkfPbCCQ3gDhoOLt3+OBLdXMRqyt2BdgIgXMHqXIGzypxa7Ug/jN7bb+w1iC+3saBYo/qj/jdx4Tg="}]},"_npmUser":{"name":"api-commons","email":"info@apicommons.org"},"directories":{},"maintainers":[{"name":"api-commons","email":"info@apicommons.org"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/spectral-reporter_0.2.0_1783113465443_0.23071354737299155"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-03T20:04:25.991Z","modified":"2026-07-03T21:17:45.711Z","0.1.0":"2026-07-03T20:04:26.338Z","0.2.0":"2026-07-03T21:17:45.590Z"},"bugs":{"url":"https://github.com/api-commons/spectral-reporter/issues"},"author":{"name":"API Evangelist","url":"https://apievangelist.com"},"license":"Apache-2.0","homepage":"https://reporter.apicommons.org","keywords":["spectral","openapi","asyncapi","api-governance","linting","reporter","htmlextra","html-report","sarif","code-scanning","trends","api-commons"],"repository":{"type":"git","url":"git+https://github.com/api-commons/spectral-reporter.git"},"description":"Turn Stoplight Spectral lint output into a rich, standalone HTML API governance report — inspired by newman-reporter-htmlextra. An API Commons tool.","maintainers":[{"name":"api-commons","email":"info@apicommons.org"}],"readme":"# Spectral Reporter\n\n**Turn [Stoplight Spectral](https://github.com/stoplightio/spectral) lint output into a rich, standalone HTML API governance report.**\n\n`@api-common/spectral-reporter` is a post-processor: you feed it Spectral's JSON\noutput and it emits one self-contained HTML file — inline CSS and JS, no external\nor CDN requests — that you can open offline or attach to a CI run. It is directly\ninspired by Danny Dainton's\n[**newman-reporter-htmlextra**](https://github.com/DannyDainton/newman-reporter-htmlextra),\nwhich does the same thing for Postman/Newman runs.\n\nLive demo and landing page: **[reporter.apicommons.org](https://reporter.apicommons.org)**\n\nOne of the [API Commons tools](https://apicommons.org/tools/), alongside\n[API Validator](https://validator.apicommons.org),\n[API Discovery](https://discover.apicommons.org),\n[API Documentation](https://documentation.apicommons.org),\n[API Reusability](https://reusability.apicommons.org), and\n[MCP Install](https://install.apicommons.org).\n\n## What's in the report\n\n- **Pass/fail governance banner** — fails if there are any errors.\n- **Severity stat tiles** — Errors / Warnings / Info / Hints, with reserved,\n  always-labelled status colors (never color alone).\n- **Group-by toggle** — regroup findings by rule, file, or severity.\n- **Search + severity filter chips** — filter the whole report client-side.\n- **Per-issue rows** — severity chip, rule code, message, file basename,\n  `line:character`; expand a row to see the JSON `path` and source.\n- **Top-offending rules & files** — mini bar-rankings so you know where to start.\n- Responsive, respects `prefers-reduced-motion`, visible focus states, light/dark.\n\n## Install & usage\n\nRun it with no install:\n\n```bash\n# From a Spectral JSON results file\nnpx @api-common/spectral-reporter spectral-results.json -o governance-report.html\n\n# Or pipe straight from Spectral\nspectral lint -f json openapi.yaml | npx @api-common/spectral-reporter -o report.html\n```\n\nOr add it to a project:\n\n```bash\nnpm install --save-dev @api-common/spectral-reporter\n```\n\n### Input\n\nSpectral's `--format json` / `-f json` output — a JSON array of findings:\n\n```json\n[\n  { \"code\": \"operation-operationId\",\n    \"path\": [\"paths\", \"/pets\", \"get\", \"operationId\"],\n    \"message\": \"Operation must have \\\"operationId\\\".\",\n    \"severity\": 1,\n    \"range\": { \"start\": { \"line\": 10, \"character\": 6 }, \"end\": { \"line\": 12, \"character\": 20 } },\n    \"source\": \"/abs/path/openapi.yaml\" }\n]\n```\n\nSeverity integers: **0 = error, 1 = warn, 2 = info, 3 = hint**. Missing\n`source`/`range`, empty arrays (a clean run renders a celebratory \"0 issues\"\nreport), and multiple source files are all handled.\n\n### Flags\n\n| Flag | Description |\n| --- | --- |\n| `-o, --output <file>` | Output path — HTML report, trend report, or SARIF (default `spectral-report.html`) |\n| `--sarif <file>` | Also write **SARIF 2.1.0** (for GitHub code scanning) |\n| `--format <html\\|sarif>` | `sarif` writes SARIF to `-o` / default instead of HTML |\n| `--history <dir>` | Render a **trend report** across dated JSON runs in `<dir>` |\n| `--trends` | Force trend mode (auto-detected when multiple inputs are given) |\n| `--totals <file>` | Positive-rule sidecar → adds a **compliance scoreboard** |\n| `--title <text>` | Report title (default `API Governance Report`) |\n| `--dark` | Force the dark theme |\n| `--open` | Best-effort open the report in your browser |\n| `-h, --help` | Show help |\n| `--version` | Print version |\n\n## SARIF output — upload findings to GitHub code scanning\n\nThe research found only **3.4%** of API teams surface governance findings in\nGitHub code scanning. `--sarif` closes that gap: it converts Spectral's JSON to\n[**SARIF 2.1.0**](https://sarifweb.azurewebsites.net/) — distinct rules become\n`tool.driver.rules`, each finding becomes a `result` (with `ruleId`, a `level`\nmapped from severity, and `locations` from `source` + `range`). Severity maps as\n**error → error, warn → warning, info/hint → note**; Spectral's 0-based\nline/character ranges are converted to SARIF's 1-based regions.\n\n```bash\n# Write SARIF only (nothing else) — ideal in a pipe\nspectral lint -f json openapi.yaml | npx @api-common/spectral-reporter --sarif results.sarif\n\n# Or write BOTH the HTML report and SARIF by also giving -o\nnpx @api-common/spectral-reporter spectral.json --sarif results.sarif -o report.html\n```\n\nIn GitHub Actions, hand the file to `github/codeql-action/upload-sarif` so\nfindings show up on the Security tab and inline on pull requests:\n\n```yaml\n- name: Spectral → SARIF\n  run: |\n    npx @stoplight/spectral-cli lint -f json openapi.yaml > spectral.json || true\n    npx @api-common/spectral-reporter spectral.json --sarif results.sarif\n- uses: github/codeql-action/upload-sarif@v3\n  with:\n    sarif_file: results.sarif\n```\n\n## Trend / history reports\n\nFeed the reporter **multiple runs** and it renders a trend scoreboard — total\nfindings over time, a per-severity trend, and which rules **improved** or\n**regressed** — the \"82% comply, up from 71% last quarter\" view.\n\n```bash\n# A directory of dated JSON runs (e.g. 2026-Q1.json, 2026-Q2.json …), sorted by name\nnpx @api-common/spectral-reporter --history runs/ -o trend-report.html\n\n# …or pass the run files positionally, oldest → newest (trend mode auto-detects)\nnpx @api-common/spectral-reporter q1.json q2.json q3.json -o trend-report.html\n```\n\nEach run file is ordinary Spectral `-f json` output; the filename (minus\nextension) becomes the run's label on the chart.\n\n## Positive-rule framing — report progress, not just deficits\n\nRaw Spectral JSON only lists **violations**, so it can never say \"82% of\noperations carry a unique id.\" Supply an optional **totals sidecar** with\n`--totals` and the report adds a compliance scoreboard beside the violation\nlist. It degrades gracefully — omit the sidecar and you get the deficit-only\nreport exactly as before.\n\nThe sidecar is per-rule `{ checked, passed, failed }`. `passed` defaults to\n`checked − failed` and `failed` to `checked − passed`, so you only need two of\nthe three:\n\n```json\n{\n  \"rules\": {\n    \"operation-operationId\":        { \"checked\": 42, \"passed\": 34, \"failed\": 8 },\n    \"operation-operationId-unique\":  { \"checked\": 42, \"passed\": 41 },\n    \"info-license\":                  { \"checked\": 6,  \"failed\": 5 }\n  }\n}\n```\n\nAn array form (`[{ \"rule\": \"…\", \"checked\": …, \"passed\": … }, …]`) is accepted too.\n\n```bash\nnpx @api-common/spectral-reporter results.json --totals totals.json -o report.html\n```\n\n### In GitHub Actions\n\n```yaml\n- name: Lint & report\n  run: |\n    npx @stoplight/spectral-cli lint -f json openapi.yaml > spectral.json || true\n    npx @api-common/spectral-reporter spectral.json -o governance-report.html\n- uses: actions/upload-artifact@v4\n  with:\n    name: api-governance-report\n    path: governance-report.html\n```\n\n(The `|| true` keeps the step from failing before the report is generated; gate\nthe build on the report's contents or Spectral's own exit code as you prefer.)\n\n## Use the renderer directly\n\nThe HTML rendering is a pure, dependency-free function shared verbatim by the\nCLI and the web demo:\n\n```js\nimport { renderReport } from '@api-common/spectral-reporter';\n\nconst html = renderReport(spectralResults, {\n  title: 'My API Governance Report',\n  dark: false,\n  generatedAt: new Date().toISOString(),\n  totals: { rules: { 'operation-operationId': { checked: 42, passed: 34 } } }, // optional\n});\n```\n\nThe trend renderer and the SARIF converter are the same pure, dependency-free\nmodules the CLI and the demo use, exported as subpaths:\n\n```js\nimport { renderTrends } from '@api-common/spectral-reporter/trends';\nimport { toSarif }      from '@api-common/spectral-reporter/sarif';\n\nconst trendHtml = renderTrends([\n  { label: '2026-Q1', results: q1 },\n  { label: '2026-Q2', results: q2 },\n], { generatedAt: new Date().toISOString() });\n\nconst sarifLog = toSarif(spectralResults); // a SARIF 2.1.0 log object\n```\n\n## Develop / run locally\n\n```bash\nnpm install\nnpm test            # node:test unit tests for the renderer\nnpm run cli fixtures/spectral-results.json -o /tmp/report.html   # try the CLI\nnpm run dev         # the landing + live demo site (Vite) at localhost:5173\nnpm run build       # build the static site into dist/ (what Pages deploys)\n```\n\nThe demo and the CLI import the same `src/render-report.js`, so what you preview\nand download on the site is byte-for-byte what CI produces.\n\n## TODOs (for the human picking this up)\n\n- [ ] **Review + `npm publish` v0.2.0.** The repo is public and `0.1.0` is on\n      npm; the SARIF / trends / positive-rule work is committed locally on\n      `main` and left for a human to review, bump, and publish. (scope\n      `@api-common` is singular — `@api-commons` was taken.)\n- [ ] **DNS**: confirm `reporter.apicommons.org` points at GitHub Pages.\n- [ ] Add screenshots / social card to this README and the landing page.\n\n## License\n\n[Apache-2.0](./LICENSE) — free and open. A project of\n[API Evangelist](https://apievangelist.com), maintained under\n[API Commons](https://apicommons.org). API Evangelist offers expert\n[governance services](https://apievangelist.com/services/) when you want help.\n","readmeFilename":"README.md"}