@erenthedeveloper0/zen-openapi 0.1.0-alpha.1 → 0.1.0-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +9 -4
- package/dist/plugin.js.map +1 -1
- package/dist/ui.d.ts.map +1 -1
- package/dist/ui.js +1 -6
- package/dist/ui.js.map +1 -1
- package/package.json +2 -2
- package/src/plugin.ts +12 -7
- package/src/ui.ts +1 -8
package/dist/plugin.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAwB,MAAM,
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAwB,MAAM,EAAY,MAAM,6BAA6B,CAAA;AAEzF,OAAO,EAAmB,KAAK,cAAc,EAAE,KAAK,aAAa,EAAE,MAAM,eAAe,CAAA;AAIxF;;;;;;;;GAQG;AAEH,MAAM,WAAW,oBAAqB,SAAQ,cAAc;IAC1D,wEAAwE;IACxE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,SAAS,CAAA;IAC1C,iEAAiE;IACjE,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,SAAS,CAAA;IACxC;;;;;;OAMG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;IACrC,8EAA8E;IAC9E,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,aAAa,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,SAAS,CAAA;CACpF;AASD,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,oBAAoB,EAAE,EAAE,CAkEzD,CAAA"}
|
package/dist/plugin.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BootError, definePlugin } from '@erenthedeveloper0/zen-core';
|
|
1
|
+
import { BootError, definePlugin, unsafeHtml } from '@erenthedeveloper0/zen-core';
|
|
2
2
|
import { openapiDocument } from "./document.js";
|
|
3
3
|
import { renderReference } from "./ui.js";
|
|
4
4
|
export const openapiPlugin = definePlugin({
|
|
@@ -7,7 +7,7 @@ export const openapiPlugin = definePlugin({
|
|
|
7
7
|
setup(app, options) {
|
|
8
8
|
const jsonPath = options.json === undefined ? '/openapi.json' : options.json;
|
|
9
9
|
const uiPath = options.ui === undefined ? '/docs' : options.ui;
|
|
10
|
-
const served = { result: null, json: '{}', etag: '', html: '' };
|
|
10
|
+
const served = { result: null, json: '{}', etag: '', html: unsafeHtml('') };
|
|
11
11
|
if (jsonPath !== false) {
|
|
12
12
|
app.route({
|
|
13
13
|
method: 'GET',
|
|
@@ -40,9 +40,14 @@ export const openapiPlugin = definePlugin({
|
|
|
40
40
|
served.result = result;
|
|
41
41
|
served.json = JSON.stringify(result.document, null, 2);
|
|
42
42
|
served.etag = weakEtag(served.json);
|
|
43
|
-
|
|
43
|
+
// `unsafeHtml`, once, at boot: the page inlines the document in a JSON
|
|
44
|
+
// island and a script, which `html` rightly refuses to fill from holes,
|
|
45
|
+
// and `renderReference` escapes both itself (`<` as `<` in the
|
|
46
|
+
// island, every text value through `escapeHtml`). The mark is the
|
|
47
|
+
// statement that it did, made where a reviewer can check it (§19.5).
|
|
48
|
+
served.html = unsafeHtml(uiPath === false
|
|
44
49
|
? ''
|
|
45
|
-
: renderReference(result.document, { jsonPath: jsonPath === false ? null : jsonPath });
|
|
50
|
+
: renderReference(result.document, { jsonPath: jsonPath === false ? null : jsonPath }));
|
|
46
51
|
if (options.strict === true && result.diagnostics.length > 0) {
|
|
47
52
|
throw new BootError(result.diagnostics.map(toBootDiagnostic));
|
|
48
53
|
}
|
package/dist/plugin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAA;
|
|
1
|
+
{"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"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"}
|
package/dist/ui.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../src/ui.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../src/ui.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAEjD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,eAAe,EAAE,OAAO,GAAE;IAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;CAAuB,GAAG,MAAM,CA6B5H"}
|
package/dist/ui.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { escapeHtml } from '@erenthedeveloper0/zen-core';
|
|
1
2
|
/**
|
|
2
3
|
* A self-contained API reference — rfcs/0001 §29.2.
|
|
3
4
|
*
|
|
@@ -41,12 +42,6 @@ export function renderReference(document, options = { jsonPath: null }) {
|
|
|
41
42
|
</html>
|
|
42
43
|
`;
|
|
43
44
|
}
|
|
44
|
-
function escapeHtml(raw) {
|
|
45
|
-
return raw.replace(/[&<>"']/g, (char) => HTML_ESCAPES[char] ?? char);
|
|
46
|
-
}
|
|
47
|
-
const HTML_ESCAPES = {
|
|
48
|
-
'&': '&', '<': '<', '>': '>', '"': '"', "'": ''',
|
|
49
|
-
};
|
|
50
45
|
const STYLE = `
|
|
51
46
|
:root{--bg:#fff;--fg:#1a1a1a;--muted:#666;--line:#e3e3e3;--code:#f6f6f7;--accent:#3060d0}
|
|
52
47
|
@media(prefers-color-scheme:dark){:root{--bg:#16171a;--fg:#e8e8ea;--muted:#9a9aa2;--line:#2c2d33;--code:#1e1f24;--accent:#7aa2f7}}
|
package/dist/ui.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ui.js","sourceRoot":"","sources":["../src/ui.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ui.js","sourceRoot":"","sources":["../src/ui.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAA;AAGxD;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,eAAe,CAAC,QAAyB,EAAE,UAAuC,EAAE,QAAQ,EAAE,IAAI,EAAE;IAClH,MAAM,KAAK,GAAG,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAC7C,6EAA6E;IAC7E,wEAAwE;IACxE,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,SAAS,CAAC,CAAA;IACjE,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,KAAK,IAAI;QACxC,CAAC,CAAC,EAAE;QACJ,CAAC,CAAC,8BAA8B,UAAU,CAAC,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAA;IAElF,OAAO;;;;;;SAMA,KAAK;SACL,KAAK;;;;QAIN,KAAK;wBACW,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,QAAQ;;;4CAGxB,OAAO;UACzC,MAAM;;;CAGf,CAAA;AACD,CAAC;AAED,MAAM,KAAK,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+Bb,CAAA;AAED,MAAM,MAAM,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6Gd,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@erenthedeveloper0/zen-openapi",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.2",
|
|
4
4
|
"description": "Zen OpenAPI: the application graph as an OAS 3.1 document, $ref deduplication, breaking-change detection and a dependency-free viewer.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"openapi",
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
"test": "node --test \"test/**/*.test.ts\""
|
|
53
53
|
},
|
|
54
54
|
"dependencies": {
|
|
55
|
-
"@erenthedeveloper0/zen-core": "0.1.0-alpha.
|
|
55
|
+
"@erenthedeveloper0/zen-core": "0.1.0-alpha.2"
|
|
56
56
|
},
|
|
57
57
|
"peerDependencies": {
|
|
58
58
|
"typescript": ">=5.0"
|
package/src/plugin.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { AppGraph, Diagnostic, Plugin } from '@erenthedeveloper0/zen-core'
|
|
2
|
-
import { BootError, definePlugin } from '@erenthedeveloper0/zen-core'
|
|
1
|
+
import type { AppGraph, Diagnostic, Plugin, SafeHtml } from '@erenthedeveloper0/zen-core'
|
|
2
|
+
import { BootError, definePlugin, unsafeHtml } from '@erenthedeveloper0/zen-core'
|
|
3
3
|
import { openapiDocument, type OpenApiOptions, type OpenApiResult } from './document.ts'
|
|
4
4
|
import type { DocDiagnostic } from './schema.ts'
|
|
5
5
|
import { renderReference } from './ui.ts'
|
|
@@ -35,7 +35,7 @@ interface Served {
|
|
|
35
35
|
result: OpenApiResult | null
|
|
36
36
|
json: string
|
|
37
37
|
etag: string
|
|
38
|
-
html:
|
|
38
|
+
html: SafeHtml
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
export const openapiPlugin: Plugin<OpenApiPluginOptions, {}> = definePlugin<OpenApiPluginOptions, {}>({
|
|
@@ -45,7 +45,7 @@ export const openapiPlugin: Plugin<OpenApiPluginOptions, {}> = definePlugin<Open
|
|
|
45
45
|
setup(app, options) {
|
|
46
46
|
const jsonPath = options.json === undefined ? '/openapi.json' : options.json
|
|
47
47
|
const uiPath = options.ui === undefined ? '/docs' : options.ui
|
|
48
|
-
const served: Served = { result: null, json: '{}', etag: '', html: '' }
|
|
48
|
+
const served: Served = { result: null, json: '{}', etag: '', html: unsafeHtml('') }
|
|
49
49
|
|
|
50
50
|
if (jsonPath !== false) {
|
|
51
51
|
app.route({
|
|
@@ -80,9 +80,14 @@ export const openapiPlugin: Plugin<OpenApiPluginOptions, {}> = definePlugin<Open
|
|
|
80
80
|
served.result = result
|
|
81
81
|
served.json = JSON.stringify(result.document, null, 2)
|
|
82
82
|
served.etag = weakEtag(served.json)
|
|
83
|
-
|
|
83
|
+
// `unsafeHtml`, once, at boot: the page inlines the document in a JSON
|
|
84
|
+
// island and a script, which `html` rightly refuses to fill from holes,
|
|
85
|
+
// and `renderReference` escapes both itself (`<` as `<` in the
|
|
86
|
+
// island, every text value through `escapeHtml`). The mark is the
|
|
87
|
+
// statement that it did, made where a reviewer can check it (§19.5).
|
|
88
|
+
served.html = unsafeHtml(uiPath === false
|
|
84
89
|
? ''
|
|
85
|
-
: renderReference(result.document, { jsonPath: jsonPath === false ? null : jsonPath })
|
|
90
|
+
: renderReference(result.document, { jsonPath: jsonPath === false ? null : jsonPath }))
|
|
86
91
|
|
|
87
92
|
if (options.strict === true && result.diagnostics.length > 0) {
|
|
88
93
|
throw new BootError(result.diagnostics.map(toBootDiagnostic))
|
|
@@ -106,7 +111,7 @@ interface DocsContext {
|
|
|
106
111
|
readonly headers: Readonly<Record<string, string | undefined>>
|
|
107
112
|
empty(status?: 204 | 205 | 304): unknown
|
|
108
113
|
text(body: string, init?: { media?: string; headers?: Record<string, string> }): unknown
|
|
109
|
-
html(body:
|
|
114
|
+
html(body: SafeHtml): unknown
|
|
110
115
|
}
|
|
111
116
|
|
|
112
117
|
function toBootDiagnostic(diagnostic: DocDiagnostic): Diagnostic {
|
package/src/ui.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { escapeHtml } from '@erenthedeveloper0/zen-core'
|
|
1
2
|
import type { OpenApiDocument } from './types.ts'
|
|
2
3
|
|
|
3
4
|
/**
|
|
@@ -45,14 +46,6 @@ export function renderReference(document: OpenApiDocument, options: { jsonPath:
|
|
|
45
46
|
`
|
|
46
47
|
}
|
|
47
48
|
|
|
48
|
-
function escapeHtml(raw: string): string {
|
|
49
|
-
return raw.replace(/[&<>"']/g, (char) => HTML_ESCAPES[char] ?? char)
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const HTML_ESCAPES: Readonly<Record<string, string>> = {
|
|
53
|
-
'&': '&', '<': '<', '>': '>', '"': '"', "'": ''',
|
|
54
|
-
}
|
|
55
|
-
|
|
56
49
|
const STYLE = `
|
|
57
50
|
:root{--bg:#fff;--fg:#1a1a1a;--muted:#666;--line:#e3e3e3;--code:#f6f6f7;--accent:#3060d0}
|
|
58
51
|
@media(prefers-color-scheme:dark){:root{--bg:#16171a;--fg:#e8e8ea;--muted:#9a9aa2;--line:#2c2d33;--code:#1e1f24;--accent:#7aa2f7}}
|