-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.html
More file actions
269 lines (251 loc) · 17.5 KB
/
Copy pathindex.html
File metadata and controls
269 lines (251 loc) · 17.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>API Validator — Spectral-powered API governance</title>
<meta name="description" content="Lint OpenAPI, AsyncAPI, Arazzo, and JSON Schema in the browser with Spectral rules. Search GitHub/GitLab/Bitbucket for real artifacts, edit the ruleset, and commit or PR back to Git. No backend — tokens stay in your browser." />
<link rel="icon" href="/favicon.svg" type="image/svg+xml" />
<!-- Google tag (gtag.js) — API Commons -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-WNSPT4B4S8"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-WNSPT4B4S8');
</script>
</head>
<body>
<header class="topbar">
<div class="brand">
<strong>API Validator</strong>
<span class="tag">validator.apicommons.org</span>
</div>
<nav>
<a href="https://apicommons.org/tools/" target="_blank" rel="noopener">API Commons</a>
<a class="btn-yellow" href="https://github.com/api-commons/api-validator/fork" target="_blank" rel="noopener" title="Fork this project on GitHub">
<svg viewBox="0 0 16 16" aria-hidden="true"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8Z"/></svg>
Fork on GitHub
</a>
<button id="engage-ae" class="btn-yellow" type="button" title="Work with API Evangelist on governance, reusability, and more">Get Help</button>
<a id="run-local" class="btn-yellow" href="/api-validator.zip" download="api-validator.zip" title="Download the built app as a zip and run it on your own machine">Run Locally</a>
<button id="download-apisjson" class="btn-yellow" type="button" title="Assemble all saved artifacts into an APIs.json (YAML) and download">Download as APIs.json</button>
<button id="reset-storage" class="btn-yellow" type="button" title="Clear all saved artifacts and rules stored in this browser">Reset</button>
</nav>
</header>
<main class="layout">
<section class="pane">
<div class="artifact-toolbar">
<select id="artifact-type" class="art-select" aria-label="Artifact type"></select>
<select id="source-select" class="art-select" aria-label="Search source" title="Where to search (toggle sources in Config)"></select>
<div class="search-wrap">
<input id="artifact-search" type="search" placeholder="Search…" autocomplete="off" />
<button id="artifact-search-btn" title="Search">Search</button>
<div id="search-results" class="search-results" hidden></div>
</div>
<div class="lang-toggle" role="group" aria-label="Editor format">
<button id="lang-yaml" class="active" type="button">YAML</button>
<button id="lang-json" type="button">JSON</button>
</div>
<button id="doc-upload" class="upload-btn" type="button" title="Upload a YAML or JSON artifact from your computer">Upload</button>
<input id="doc-file" type="file" accept=".yaml,.yml,.json,.md,.txt,application/json,text/yaml" hidden />
<button id="doc-save" class="save-btn" type="button" title="Save to this browser's local storage">Save</button>
</div>
<div id="doc-status" class="muted small doc-status"></div>
<div id="doc-editor" class="editor"></div>
</section>
<section class="pane">
<div class="tabs" role="tablist">
<button class="tab active" data-tab="results" type="button">Results</button>
<button class="tab" data-tab="ruleset" type="button">Rules</button>
<button class="tab" data-tab="docs" type="button">Docs</button>
<button class="tab" data-tab="utilities" type="button">Utilities</button>
<button class="tab" data-tab="saved" type="button">Saved Artifacts <span class="badge" id="saved-count">0</span></button>
<button class="tab" data-tab="rules" type="button">Saved Rules <span class="badge" id="rules-count">0</span></button>
<button class="tab" data-tab="repos" type="button">Repos <span class="badge" id="repos-count">0</span></button>
<button class="tab" data-tab="config" type="button">Config</button>
<button class="tab" data-tab="about" type="button">About</button>
</div>
<div class="tag-filter" id="tag-filter" hidden>
<details id="filter-details">
<summary>
<span class="filter-summary-label">Filter by tag</span>
<span class="filter-active" id="filter-active"></span>
</summary>
<div class="filter-facets" id="filter-facets"></div>
</details>
<button class="filter-clear" id="filter-clear" type="button" hidden>clear</button>
</div>
<div class="tab-panel" id="tab-results">
<div class="rules-meta muted small">
<span id="active-count">0</span> rules active ·
<span id="result-count">—</span> ·
<span class="hint-text">click a result to edit its rule</span>
</div>
<div id="results"></div>
</div>
<div class="tab-panel" id="tab-ruleset" hidden>
<p class="saved-notice">
Enable or disable any rule — disabled rules are skipped whenever you lint that artifact
type (stored in this browser). Grouped by artifact.
</p>
<div id="ruleset-list"></div>
</div>
<div class="tab-panel" id="tab-docs" hidden>
<div class="repos-add docs-bar">
<span class="muted small">Live documentation for the <strong>current document</strong></span>
<button id="docs-download-html" class="save-btn" type="button" title="Download as a standalone HTML page">Download HTML</button>
<button id="docs-download-md" class="upload-btn" type="button" title="Download as a Markdown file">Download Markdown</button>
<button id="docs-print" class="upload-btn" type="button" title="Open a printable view (Save as PDF)">Print</button>
</div>
<div id="docs-view" class="doc-view"></div>
</div>
<div class="tab-panel" id="tab-utilities" hidden>
<p class="saved-notice">
Apply a transformation to the <strong>current document</strong>, grouped by artifact type.
Some create new entries in Saved Artifacts; the primary document is always kept. More functions coming.
</p>
<div id="utilities-status" class="muted small"></div>
<div id="utilities-list"></div>
</div>
<div class="tab-panel" id="tab-saved" hidden>
<p class="saved-notice">
Your documents autosave to this browser's local storage as you edit — no account needed.
They'll <strong>disappear if you clear your browser cache</strong>. Commit or open a PR to save one
to a repo from the Repos tab (needs a GitHub token).
</p>
<div class="repos-add saved-git-bar">
<span class="muted small">Commit / PR to</span>
<select id="saved-repo-select" title="Target repo — manage the list in the Repos tab"></select>
<span id="saved-git-status" class="muted small"></span>
</div>
<ul id="saved-list" class="store-list"></ul>
</div>
<div class="tab-panel" id="tab-rules" hidden>
<p class="saved-notice">
Rules you save here <strong>override the built-in rule of the same name</strong> when linting, and
persist in this browser. Remove one to revert to the original. Edit a rule from any result to save it.
</p>
<ul id="saved-rules-list" class="store-list"></ul>
</div>
<div class="tab-panel" id="tab-repos" hidden>
<p class="saved-notice">
Add the GitHub repos you work with — stored in this browser and offered wherever you commit or
open a PR (saving artifacts & rulesets to Git is coming soon). Needs a GitHub token (Config).
</p>
<div class="repos-add">
<select id="repo-picker" aria-label="Accessible repositories"></select>
<button id="repo-refresh" type="button" title="Reload your repos from GitHub">↻</button>
<button id="repo-add" class="save-btn" type="button">Add</button>
</div>
<ul id="repos-list" class="store-list"></ul>
</div>
<div class="tab-panel" id="tab-config" hidden>
<p class="saved-notice">
Stored <strong>only in this browser's local storage</strong> (cleared by Reset or clearing your cache).
These power code search across Git hosts and saving artifacts & rules to Git.
Nothing is sent anywhere until you use those features.
</p>
<div class="config-scroll">
<details class="rule-group config-group" open>
<summary><span class="group-name">Search sources</span></summary>
<div class="config-fields">
<p class="config-note">Where Search looks for artifacts. GitHub is on by default; GitLab & Bitbucket need their tokens below.</p>
<label class="src-toggle"><input type="checkbox" id="src-github" checked> GitHub</label>
<label class="src-toggle"><input type="checkbox" id="src-gitlab"> GitLab</label>
<label class="src-toggle"><input type="checkbox" id="src-bitbucket"> Bitbucket</label>
</div>
</details>
<details class="rule-group config-group" open>
<summary><span class="group-name">Git tokens</span></summary>
<div class="config-fields">
<div class="config-field">
<div class="config-label"><label for="cfg-github">GitHub personal access token</label>
<a class="config-help" href="https://github.com/settings/tokens" target="_blank" rel="noopener">create a token ↗</a></div>
<input type="password" id="cfg-github" autocomplete="off" spellcheck="false" placeholder="ghp_…">
</div>
<div class="config-field">
<div class="config-label"><label for="cfg-gitlab">GitLab personal access token</label>
<a class="config-help" href="https://gitlab.com/-/user_settings/personal_access_tokens" target="_blank" rel="noopener">create a token ↗</a></div>
<input type="password" id="cfg-gitlab" autocomplete="off" spellcheck="false" placeholder="glpat-…">
</div>
<div class="config-field">
<div class="config-label"><label for="cfg-bitbucketUser">Bitbucket username</label></div>
<input type="text" id="cfg-bitbucketUser" autocomplete="off" spellcheck="false" placeholder="workspace / username">
</div>
<div class="config-field">
<div class="config-label"><label for="cfg-bitbucket">Bitbucket app password</label>
<a class="config-help" href="https://bitbucket.org/account/settings/app-passwords/" target="_blank" rel="noopener">create one ↗</a></div>
<input type="password" id="cfg-bitbucket" autocomplete="off" spellcheck="false" placeholder="app password">
</div>
</div>
</details>
<label class="config-show"><input type="checkbox" id="cfg-show"> Show values</label>
</div>
</div>
<div class="tab-panel" id="tab-about" hidden>
<div class="about">
<h2>API Validator</h2>
<p class="about-lede">A browser-first API governance tool. Lint <strong>OpenAPI, AsyncAPI, Arazzo, and JSON Schema</strong> against a best-of-breed ruleset powered by <a href="https://github.com/stoplightio/spectral" target="_blank" rel="noopener">Spectral</a> — entirely in your browser. No backend and no accounts; your tokens and documents never leave this page.</p>
<h3>What you can do</h3>
<ul class="about-list">
<li><strong>Search & load</strong> real artifacts from <strong>GitHub / GitLab / Bitbucket</strong> with your own token, or <strong>upload</strong> a file from disk.</li>
<li><strong>Edit</strong> in a Monaco editor with a YAML ⇄ JSON toggle.</li>
<li><strong>Lint</strong> against curated rules; every finding links to its rule, which you can retune (severity, message, description) or disable — overrides persist in your browser.</li>
<li><strong>Document</strong> — generate readable docs for the current artifact and download them as HTML or Markdown.</li>
<li><strong>Transform</strong> — bundle <code>$ref</code>s, componentize, split by tag/channel/workflow, migrate JSON Schema drafts, and more.</li>
<li><strong>Save & ship</strong> — autosave locally, roll everything into an <strong>APIs.json 0.21</strong> index, or commit / open a PR to a repo.</li>
<li><strong>Run offline</strong> — download the whole app as a single self-contained file (the “Run Locally” button).</li>
</ul>
<h3>Engine & scope</h3>
<p>Powered by the published <code>@stoplight/spectral-*</code> engine, running fully client-side. OpenAPI and AsyncAPI extend Spectral’s built-in <code>spectral:oas</code> / <code>spectral:asyncapi</code> rulesets; Arazzo and JSON Schema are linted by curated inline rules. Scope is deliberately narrow — four artifact types, kept simple.</p>
<h3>Rules & credits</h3>
<p>The best-of-breed ruleset is compiled from the first-party <a href="https://github.com/api-evangelist/rules" target="_blank" rel="noopener">API Evangelist</a> OpenAPI governance ruleset plus public, redistribution-compatible Spectral rulesets — <strong>SPS Commerce, Adidas, Trimble, Paystack, DigitalOcean, Microcks, Baloise, Team Digitale, and Schwarz IT</strong> (all Apache-2.0 or MIT). Full attribution and vendored licenses are in <a href="https://github.com/api-commons/api-validator/blob/main/THIRD_PARTY_NOTICES.md" target="_blank" rel="noopener">THIRD_PARTY_NOTICES</a>.</p>
<h3>Part of API Commons</h3>
<p>One of the <a href="https://apicommons.org/tools/" target="_blank" rel="noopener">API Commons tools</a>, alongside API Discovery, API Documentation, API Reusability, and MCP Install — all browser-first and free to fork.</p>
<div class="about-links">
<a class="btn-yellow" href="https://github.com/api-commons/api-validator" target="_blank" rel="noopener">GitHub ↗</a>
<a class="btn-yellow" href="https://apicommons.org/tools/" target="_blank" rel="noopener">API Commons ↗</a>
<a class="btn-yellow" href="https://apievangelist.com/services/" target="_blank" rel="noopener">Governance services ↗</a>
</div>
<p class="about-foot">A project of <a href="https://apievangelist.com" target="_blank" rel="noopener">API Evangelist</a>, maintained openly under <a href="https://apicommons.org" target="_blank" rel="noopener">API Commons</a>. Open source and free to fork; API Evangelist offers expert governance services when you want help.</p>
</div>
</div>
</section>
</main>
<div id="modal" class="modal" hidden>
<div class="modal-card">
<div class="modal-head">
<span id="modal-title">Edit rule</span>
<button id="modal-close" aria-label="Close">×</button>
</div>
<p id="rule-note" class="muted small"></p>
<div class="rule-fields">
<label class="rule-field">
<span class="rf-label">Severity</span>
<select id="rule-severity">
<option value="error">error</option>
<option value="warn">warn</option>
<option value="info">info</option>
<option value="hint">hint</option>
</select>
</label>
<label class="rule-field">
<span class="rf-label">Message <span id="rf-message-note" class="rf-note"></span></span>
<input id="rule-message" type="text" autocomplete="off" spellcheck="false" placeholder="Text shown on each finding" />
</label>
<label class="rule-field">
<span class="rf-label">Description <span id="rf-desc-note" class="rf-note"></span></span>
<textarea id="rule-description" rows="3" spellcheck="false" placeholder="What this rule checks (shown in the tooltip)"></textarea>
</label>
</div>
<div class="modal-actions">
<button id="rule-apply" class="primary">Apply & lint</button>
<button id="rule-reset">Reset to default</button>
<button id="rule-disable">Disable rule</button>
</div>
</div>
</div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>