@scalar/import 0.4.3 → 0.4.4
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/CHANGELOG.md +10 -0
- package/package.json +4 -4
- package/dist/get-configuration-attribute.test.js +0 -33
- package/dist/get-configuration-attribute.test.js.map +0 -7
- package/dist/get-content-of-script-tag.test.js +0 -33
- package/dist/get-content-of-script-tag.test.js.map +0 -7
- package/dist/resolve.test.js +0 -1050
- package/dist/resolve.test.js.map +0 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# @scalar/import
|
|
2
2
|
|
|
3
|
+
## 0.4.4
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies [1e87feb]
|
|
8
|
+
- Updated dependencies [1e87feb]
|
|
9
|
+
- Updated dependencies [cad6277]
|
|
10
|
+
- @scalar/openapi-parser@0.13.0
|
|
11
|
+
- @scalar/oas-utils@0.4.0
|
|
12
|
+
|
|
3
13
|
## 0.4.3
|
|
4
14
|
|
|
5
15
|
### Patch Changes
|
package/package.json
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"postman",
|
|
17
17
|
"scalar"
|
|
18
18
|
],
|
|
19
|
-
"version": "0.4.
|
|
19
|
+
"version": "0.4.4",
|
|
20
20
|
"engines": {
|
|
21
21
|
"node": ">=20"
|
|
22
22
|
},
|
|
@@ -36,12 +36,12 @@
|
|
|
36
36
|
"module": "dist/index.js",
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"yaml": "^2.4.5",
|
|
39
|
-
"@scalar/oas-utils": "0.
|
|
40
|
-
"@scalar/openapi-parser": "0.
|
|
39
|
+
"@scalar/oas-utils": "0.4.0",
|
|
40
|
+
"@scalar/openapi-parser": "0.13.0"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"vite": "5.4.19",
|
|
44
|
-
"@scalar/build-tooling": "0.2.
|
|
44
|
+
"@scalar/build-tooling": "0.2.1"
|
|
45
45
|
},
|
|
46
46
|
"scripts": {
|
|
47
47
|
"build": "scalar-build-esbuild",
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from "vitest";
|
|
2
|
-
import { getConfigurationAttribute } from "./resolve.js";
|
|
3
|
-
describe("getConfigurationAttribute", () => {
|
|
4
|
-
it("returns the configuration attribute with double quotes", () => {
|
|
5
|
-
const html = `<script id="api-reference" data-configuration="{"spec":{"content":"foo"}}"><\/script>`;
|
|
6
|
-
const result = getConfigurationAttribute(html);
|
|
7
|
-
expect(result).toBe("{"spec":{"content":"foo"}}");
|
|
8
|
-
});
|
|
9
|
-
it("returns the configuration attribute with single quotes", () => {
|
|
10
|
-
const html = `<script id='api-reference' data-configuration='{"spec":{"content":"foo"}}'><\/script>`;
|
|
11
|
-
const result = getConfigurationAttribute(html);
|
|
12
|
-
expect(result).toBe("{"spec":{"content":"foo"}}");
|
|
13
|
-
});
|
|
14
|
-
it("returns undefined if no configuration attribute is present", () => {
|
|
15
|
-
const html = `<script id="api-reference"><\/script>`;
|
|
16
|
-
const result = getConfigurationAttribute(html);
|
|
17
|
-
expect(result).toBeUndefined();
|
|
18
|
-
});
|
|
19
|
-
it("returns undefined for non-matching script tags", () => {
|
|
20
|
-
const html = `<script data-other-attribute="value" data-configuration="{"spec":{"content":"foo"}}"><\/script>`;
|
|
21
|
-
const result = getConfigurationAttribute(html);
|
|
22
|
-
expect(result).toBeUndefined();
|
|
23
|
-
});
|
|
24
|
-
it("handles multiple script tags and returns the first match", () => {
|
|
25
|
-
const html = `
|
|
26
|
-
<script id="api-reference" data-configuration="{"spec":{"content":"first"}}"><\/script>
|
|
27
|
-
<script id="api-reference" data-configuration="{"spec":{"content":"second"}}"><\/script>
|
|
28
|
-
`;
|
|
29
|
-
const result = getConfigurationAttribute(html);
|
|
30
|
-
expect(result).toBe("{"spec":{"content":"first"}}");
|
|
31
|
-
});
|
|
32
|
-
});
|
|
33
|
-
//# sourceMappingURL=get-configuration-attribute.test.js.map
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../src/get-configuration-attribute.test.ts"],
|
|
4
|
-
"sourcesContent": ["import { describe, expect, it } from 'vitest'\n\nimport { getConfigurationAttribute } from './resolve'\n\ndescribe('getConfigurationAttribute', () => {\n it('returns the configuration attribute with double quotes', () => {\n const html = `<script id=\"api-reference\" data-configuration=\"{"spec":{"content":"foo"}}\"></script>`\n const result = getConfigurationAttribute(html)\n expect(result).toBe('{"spec":{"content":"foo"}}')\n })\n\n it('returns the configuration attribute with single quotes', () => {\n const html = `<script id='api-reference' data-configuration='{"spec":{"content":"foo"}}'></script>`\n const result = getConfigurationAttribute(html)\n expect(result).toBe('{"spec":{"content":"foo"}}')\n })\n\n it('returns undefined if no configuration attribute is present', () => {\n const html = `<script id=\"api-reference\"></script>`\n const result = getConfigurationAttribute(html)\n expect(result).toBeUndefined()\n })\n\n it('returns undefined for non-matching script tags', () => {\n const html = `<script data-other-attribute=\"value\" data-configuration=\"{"spec":{"content":"foo"}}\"></script>`\n const result = getConfigurationAttribute(html)\n expect(result).toBeUndefined()\n })\n\n it('handles multiple script tags and returns the first match', () => {\n const html = `\n <script id=\"api-reference\" data-configuration=\"{"spec":{"content":"first"}}\"></script>\n <script id=\"api-reference\" data-configuration=\"{"spec":{"content":"second"}}\"></script>\n `\n const result = getConfigurationAttribute(html)\n expect(result).toBe('{"spec":{"content":"first"}}')\n })\n})\n"],
|
|
5
|
-
"mappings": "AAAA,SAAS,UAAU,QAAQ,UAAU;AAErC,SAAS,iCAAiC;AAE1C,SAAS,6BAA6B,MAAM;AAC1C,KAAG,0DAA0D,MAAM;AACjE,UAAM,OAAO;AACb,UAAM,SAAS,0BAA0B,IAAI;AAC7C,WAAO,MAAM,EAAE,KAAK,0DAA0D;AAAA,EAChF,CAAC;AAED,KAAG,0DAA0D,MAAM;AACjE,UAAM,OAAO;AACb,UAAM,SAAS,0BAA0B,IAAI;AAC7C,WAAO,MAAM,EAAE,KAAK,0DAA0D;AAAA,EAChF,CAAC;AAED,KAAG,8DAA8D,MAAM;AACrE,UAAM,OAAO;AACb,UAAM,SAAS,0BAA0B,IAAI;AAC7C,WAAO,MAAM,EAAE,cAAc;AAAA,EAC/B,CAAC;AAED,KAAG,kDAAkD,MAAM;AACzD,UAAM,OAAO;AACb,UAAM,SAAS,0BAA0B,IAAI;AAC7C,WAAO,MAAM,EAAE,cAAc;AAAA,EAC/B,CAAC;AAED,KAAG,4DAA4D,MAAM;AACnE,UAAM,OAAO;AAAA;AAAA;AAAA;AAIb,UAAM,SAAS,0BAA0B,IAAI;AAC7C,WAAO,MAAM,EAAE,KAAK,4DAA4D;AAAA,EAClF,CAAC;AACH,CAAC;",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from "vitest";
|
|
2
|
-
import { getContentOfScriptTag } from "./resolve.js";
|
|
3
|
-
describe("getContentOfScriptTag", () => {
|
|
4
|
-
it("returns the content of the script tag", () => {
|
|
5
|
-
const html = '<script id="api-reference">console.log("Hello, world!");<\/script>';
|
|
6
|
-
expect(getContentOfScriptTag(html)).toBe('console.log("Hello, world!");');
|
|
7
|
-
});
|
|
8
|
-
it("works with single quotes", () => {
|
|
9
|
-
const html = `<script id='api-reference'>console.log("Hello, world!");<\/script>`;
|
|
10
|
-
expect(getContentOfScriptTag(html)).toBe('console.log("Hello, world!");');
|
|
11
|
-
});
|
|
12
|
-
it("ignores HTML characters inside the attributes", () => {
|
|
13
|
-
const html = `<!DOCTYPE html>
|
|
14
|
-
<html>
|
|
15
|
-
<head>
|
|
16
|
-
<title>Scalar API Reference</title>
|
|
17
|
-
<meta charset="utf-8" />
|
|
18
|
-
<meta
|
|
19
|
-
name="viewport"
|
|
20
|
-
content="width=device-width, initial-scale=1" />
|
|
21
|
-
<style>
|
|
22
|
-
null
|
|
23
|
-
</style>
|
|
24
|
-
</head>
|
|
25
|
-
<body>
|
|
26
|
-
<script src="https://cdn.jsdelivr.net/npm/@scalar/api-reference"><\/script>
|
|
27
|
-
<script id="api-reference" type="application/json" data-configuration="foo<br>bar">console.log("Hello, world!");<\/script>
|
|
28
|
-
</body>
|
|
29
|
-
</html>`;
|
|
30
|
-
expect(getContentOfScriptTag(html)).toBe('console.log("Hello, world!");');
|
|
31
|
-
});
|
|
32
|
-
});
|
|
33
|
-
//# sourceMappingURL=get-content-of-script-tag.test.js.map
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../src/get-content-of-script-tag.test.ts"],
|
|
4
|
-
"sourcesContent": ["import { describe, expect, it } from 'vitest'\n\nimport { getContentOfScriptTag } from './resolve'\n\ndescribe('getContentOfScriptTag', () => {\n it('returns the content of the script tag', () => {\n const html = '<script id=\"api-reference\">console.log(\"Hello, world!\");</script>'\n expect(getContentOfScriptTag(html)).toBe('console.log(\"Hello, world!\");')\n })\n\n it('works with single quotes', () => {\n const html = `<script id='api-reference'>console.log(\"Hello, world!\");</script>`\n expect(getContentOfScriptTag(html)).toBe('console.log(\"Hello, world!\");')\n })\n\n it('ignores HTML characters inside the attributes', () => {\n // HTML tags inside the attributes\n const html = `<!DOCTYPE html>\n <html>\n <head>\n <title>Scalar API Reference</title>\n <meta charset=\"utf-8\" />\n <meta\n name=\"viewport\"\n content=\"width=device-width, initial-scale=1\" />\n <style>\n null\n </style>\n </head>\n <body>\n <script src=\"https://cdn.jsdelivr.net/npm/@scalar/api-reference\"></script>\n <script id=\"api-reference\" type=\"application/json\" data-configuration=\"foo<br>bar\">console.log(\"Hello, world!\");</script>\n </body>\n </html>`\n\n expect(getContentOfScriptTag(html)).toBe('console.log(\"Hello, world!\");')\n })\n})\n"],
|
|
5
|
-
"mappings": "AAAA,SAAS,UAAU,QAAQ,UAAU;AAErC,SAAS,6BAA6B;AAEtC,SAAS,yBAAyB,MAAM;AACtC,KAAG,yCAAyC,MAAM;AAChD,UAAM,OAAO;AACb,WAAO,sBAAsB,IAAI,CAAC,EAAE,KAAK,+BAA+B;AAAA,EAC1E,CAAC;AAED,KAAG,4BAA4B,MAAM;AACnC,UAAM,OAAO;AACb,WAAO,sBAAsB,IAAI,CAAC,EAAE,KAAK,+BAA+B;AAAA,EAC1E,CAAC;AAED,KAAG,iDAAiD,MAAM;AAExD,UAAM,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAkBb,WAAO,sBAAsB,IAAI,CAAC,EAAE,KAAK,+BAA+B;AAAA,EAC1E,CAAC;AACH,CAAC;",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
package/dist/resolve.test.js
DELETED
|
@@ -1,1050 +0,0 @@
|
|
|
1
|
-
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
|
-
import { resolve } from "./resolve.js";
|
|
3
|
-
global.fetch = vi.fn();
|
|
4
|
-
function createFetchResponse(data, headers = {}) {
|
|
5
|
-
return {
|
|
6
|
-
ok: true,
|
|
7
|
-
text: () => new Promise((r) => r(data)),
|
|
8
|
-
headers: new Headers(headers)
|
|
9
|
-
};
|
|
10
|
-
}
|
|
11
|
-
describe("resolve", () => {
|
|
12
|
-
beforeEach(() => {
|
|
13
|
-
global.fetch.mockReset();
|
|
14
|
-
});
|
|
15
|
-
it("returns JSON urls", async () => {
|
|
16
|
-
const result = await resolve("https://cdn.jsdelivr.net/npm/@scalar/galaxy/dist/latest.json");
|
|
17
|
-
expect(result).toBe("https://cdn.jsdelivr.net/npm/@scalar/galaxy/dist/latest.json");
|
|
18
|
-
});
|
|
19
|
-
it("returns YAML urls", async () => {
|
|
20
|
-
const result = await resolve("https://cdn.jsdelivr.net/npm/@scalar/galaxy/dist/latest.yaml");
|
|
21
|
-
expect(result).toBe("https://cdn.jsdelivr.net/npm/@scalar/galaxy/dist/latest.yaml");
|
|
22
|
-
const otherResult = await resolve("https://cdn.jsdelivr.net/npm/@scalar/galaxy/dist/latest.yml");
|
|
23
|
-
expect(otherResult).toBe("https://cdn.jsdelivr.net/npm/@scalar/galaxy/dist/latest.yml");
|
|
24
|
-
});
|
|
25
|
-
it("finds URLs from sandbox URL", async () => {
|
|
26
|
-
const result = await resolve("https://sandbox.scalar.com/p/GcxDQ");
|
|
27
|
-
expect(result).toBe("https://sandbox.scalar.com/files/GcxDQ/openapi.yaml");
|
|
28
|
-
const otherResult = await resolve("https://sandbox.scalar.com/e/GcxDQ");
|
|
29
|
-
expect(otherResult).toBe("https://sandbox.scalar.com/files/GcxDQ/openapi.yaml");
|
|
30
|
-
});
|
|
31
|
-
it("finds URL in the CDN example", async () => {
|
|
32
|
-
const html = `<!doctype html>
|
|
33
|
-
<html>
|
|
34
|
-
<head>
|
|
35
|
-
<title>Scalar API Reference</title>
|
|
36
|
-
<meta charset="utf-8" />
|
|
37
|
-
<meta
|
|
38
|
-
name="viewport"
|
|
39
|
-
content="width=device-width, initial-scale=1" />
|
|
40
|
-
</head>
|
|
41
|
-
<body>
|
|
42
|
-
<script
|
|
43
|
-
id="api-reference"
|
|
44
|
-
data-url="https://cdn.jsdelivr.net/npm/@scalar/galaxy/dist/latest.yaml"><\/script>
|
|
45
|
-
<script src="https://cdn.jsdelivr.net/npm/@scalar/api-reference"><\/script>
|
|
46
|
-
</body>
|
|
47
|
-
</html>`;
|
|
48
|
-
fetch.mockResolvedValue(createFetchResponse(html));
|
|
49
|
-
const result = await resolve("https://example.com/reference");
|
|
50
|
-
expect(result).toBe("https://cdn.jsdelivr.net/npm/@scalar/galaxy/dist/latest.yaml");
|
|
51
|
-
});
|
|
52
|
-
it("works with single quote data attributes", async () => {
|
|
53
|
-
const html = `<!doctype html>
|
|
54
|
-
<html>
|
|
55
|
-
<head>
|
|
56
|
-
<title>Scalar API Reference</title>
|
|
57
|
-
<meta charset="utf-8" />
|
|
58
|
-
<meta
|
|
59
|
-
name="viewport"
|
|
60
|
-
content="width=device-width, initial-scale=1" />
|
|
61
|
-
</head>
|
|
62
|
-
<body>
|
|
63
|
-
<script
|
|
64
|
-
id="api-reference"
|
|
65
|
-
data-url='https://cdn.jsdelivr.net/npm/@scalar/galaxy/dist/latest.yaml'><\/script>
|
|
66
|
-
<script src="https://cdn.jsdelivr.net/npm/@scalar/api-reference"><\/script>
|
|
67
|
-
</body>
|
|
68
|
-
</html>`;
|
|
69
|
-
fetch.mockResolvedValue(createFetchResponse(html));
|
|
70
|
-
const result = await resolve("https://example.com/reference");
|
|
71
|
-
expect(result).toBe("https://cdn.jsdelivr.net/npm/@scalar/galaxy/dist/latest.yaml");
|
|
72
|
-
});
|
|
73
|
-
it("returns absolute URLs", async () => {
|
|
74
|
-
const html = `<!doctype html>
|
|
75
|
-
<html>
|
|
76
|
-
<head>
|
|
77
|
-
<title>Scalar API Reference</title>
|
|
78
|
-
<meta charset="utf-8" />
|
|
79
|
-
<meta
|
|
80
|
-
name="viewport"
|
|
81
|
-
content="width=device-width, initial-scale=1" />
|
|
82
|
-
</head>
|
|
83
|
-
<body>
|
|
84
|
-
<div data-url="/not-what-we-are-looking-for" id="foobar" />
|
|
85
|
-
<script
|
|
86
|
-
id="api-reference"
|
|
87
|
-
data-url="/openapi.yaml"><\/script>
|
|
88
|
-
<script src="https://cdn.jsdelivr.net/npm/@scalar/api-reference"><\/script>
|
|
89
|
-
</body>
|
|
90
|
-
</html>`;
|
|
91
|
-
fetch.mockResolvedValue(createFetchResponse(html));
|
|
92
|
-
const result = await resolve("https://example.com/reference");
|
|
93
|
-
expect(result).toBe("https://example.com/openapi.yaml");
|
|
94
|
-
});
|
|
95
|
-
it("returns absolute URLs based on the X-Forwarded-Host header", async () => {
|
|
96
|
-
const html = `<!doctype html>
|
|
97
|
-
<html>
|
|
98
|
-
<head>
|
|
99
|
-
<title>Scalar API Reference</title>
|
|
100
|
-
<meta charset="utf-8" />
|
|
101
|
-
<meta
|
|
102
|
-
name="viewport"
|
|
103
|
-
content="width=device-width, initial-scale=1" />
|
|
104
|
-
</head>
|
|
105
|
-
<body>
|
|
106
|
-
<div data-url="/not-what-we-are-looking-for" id="foobar" />
|
|
107
|
-
<script
|
|
108
|
-
id="api-reference"
|
|
109
|
-
data-url="../openapi.yaml"><\/script>
|
|
110
|
-
<script src="https://cdn.jsdelivr.net/npm/@scalar/api-reference"><\/script>
|
|
111
|
-
</body>
|
|
112
|
-
</html>`;
|
|
113
|
-
fetch.mockResolvedValue(
|
|
114
|
-
createFetchResponse(html, {
|
|
115
|
-
"X-Forwarded-Host": "https://example.com/somewhere/else/"
|
|
116
|
-
})
|
|
117
|
-
);
|
|
118
|
-
const result = await resolve("https://example.com/reference");
|
|
119
|
-
expect(result).toBe("https://example.com/somewhere/openapi.yaml");
|
|
120
|
-
});
|
|
121
|
-
it("finds URLs in some wrangled configuration object", async () => {
|
|
122
|
-
const html = `<!DOCTYPE html>
|
|
123
|
-
<html>
|
|
124
|
-
<head>
|
|
125
|
-
<title>Hono API Reference Demo</title>
|
|
126
|
-
<meta charset="utf-8" />
|
|
127
|
-
<meta
|
|
128
|
-
name="viewport"
|
|
129
|
-
content="width=device-width, initial-scale=1" />
|
|
130
|
-
</head>
|
|
131
|
-
<body>
|
|
132
|
-
|
|
133
|
-
<script
|
|
134
|
-
id="api-reference"
|
|
135
|
-
type="application/json"
|
|
136
|
-
data-configuration="{&quot;spec&quot;:{&quot;url&quot;:&quot;/openapi.yaml&quot;},&quot;pageTitle&quot;:&quot;Hono API Reference Demo&quot;}">
|
|
137
|
-
|
|
138
|
-
<\/script>
|
|
139
|
-
<script src="https://cdn.jsdelivr.net/npm/@scalar/api-reference"><\/script>
|
|
140
|
-
|
|
141
|
-
</body>
|
|
142
|
-
</html>`;
|
|
143
|
-
fetch.mockResolvedValue(createFetchResponse(html));
|
|
144
|
-
const result = await resolve("https://example.com/reference");
|
|
145
|
-
expect(result).toBe("https://example.com/openapi.yaml");
|
|
146
|
-
});
|
|
147
|
-
it("finds URLs in redoc HTML", async () => {
|
|
148
|
-
const html = `<!DOCTYPE html>
|
|
149
|
-
<html>
|
|
150
|
-
<head>
|
|
151
|
-
<title>Redoc</title>
|
|
152
|
-
<meta charset="utf-8"/>
|
|
153
|
-
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
154
|
-
<link href="https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700" rel="stylesheet">
|
|
155
|
-
</head>
|
|
156
|
-
<body>
|
|
157
|
-
<redoc spec-url='https://cdn.jsdelivr.net/npm/@scalar/galaxy/dist/latest.yaml'></redoc>
|
|
158
|
-
<script src="https://cdn.redoc.ly/redoc/latest/bundles/redoc.standalone.js"> <\/script>
|
|
159
|
-
</body>
|
|
160
|
-
</html>`;
|
|
161
|
-
fetch.mockResolvedValue(createFetchResponse(html));
|
|
162
|
-
const result = await resolve("https://example.com/reference");
|
|
163
|
-
expect(result).toBe("https://cdn.jsdelivr.net/npm/@scalar/galaxy/dist/latest.yaml");
|
|
164
|
-
});
|
|
165
|
-
it("finds embedded OpenAPI documents", async () => {
|
|
166
|
-
const html = `<!DOCTYPE html>
|
|
167
|
-
<html>
|
|
168
|
-
<head />
|
|
169
|
-
<body>
|
|
170
|
-
<script
|
|
171
|
-
id="api-reference"
|
|
172
|
-
type="application/json"
|
|
173
|
-
data-configuration="{"spec":{"content":{"openapi":"3.0.0","paths":{"/":{"get":{"operationId":"AppController_getHello","parameters":[],"responses":{"200":{"description":""}}}}},"info":{"title":"Cats example","description":"The cats API description","version":"1.0","contact":{}},"tags":[{"name":"cats","description":""}],"servers":[],"components":{"schemas":{}}}}}">{"openapi":"3.0.0","paths":{"/":{"get":{"operationId":"AppController_getHello","parameters":[],"responses":{"200":{"description":""}}}}},"info":{"title":"Cats example","description":"The cats API description","version":"1.0","contact":{}},"tags":[{"name":"cats","description":""}],"servers":[],"components":{"schemas":{}}}<\/script>
|
|
174
|
-
<script src="https://cdn.jsdelivr.net/npm/@scalar/api-reference"><\/script>
|
|
175
|
-
</body>
|
|
176
|
-
</html>
|
|
177
|
-
`;
|
|
178
|
-
fetch.mockResolvedValue(createFetchResponse(html));
|
|
179
|
-
const result = await resolve("https://example.com/reference");
|
|
180
|
-
expect(result).toStrictEqual({
|
|
181
|
-
openapi: "3.0.0",
|
|
182
|
-
paths: {
|
|
183
|
-
"/": {
|
|
184
|
-
get: {
|
|
185
|
-
operationId: "AppController_getHello",
|
|
186
|
-
parameters: [],
|
|
187
|
-
responses: { "200": { description: "" } }
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
},
|
|
191
|
-
info: {
|
|
192
|
-
title: "Cats example",
|
|
193
|
-
description: "The cats API description",
|
|
194
|
-
version: "1.0",
|
|
195
|
-
contact: {}
|
|
196
|
-
},
|
|
197
|
-
tags: [{ name: "cats", description: "" }],
|
|
198
|
-
servers: [],
|
|
199
|
-
components: { schemas: {} }
|
|
200
|
-
});
|
|
201
|
-
});
|
|
202
|
-
it("finds embedded OpenAPI documents, even if they contain HTML tags", async () => {
|
|
203
|
-
const html = `<!DOCTYPE html>
|
|
204
|
-
<html>
|
|
205
|
-
<head />
|
|
206
|
-
<body>
|
|
207
|
-
<script
|
|
208
|
-
id="api-reference"
|
|
209
|
-
type="application/json"
|
|
210
|
-
data-configuration="{"spec":{"content":{"openapi":"3.0.0","paths":{"/":{"get":{"operationId":"AppController_getHello","parameters":[],"responses":{"200":{"description":""}}}}},"info":{"title":"Cats example","description":"The cats<br>API description","version":"1.0","contact":{}},"tags":[{"name":"cats","description":""}],"servers":[],"components":{"schemas":{}}}}}"><\/script>
|
|
211
|
-
<script src="https://cdn.jsdelivr.net/npm/@scalar/api-reference"><\/script>
|
|
212
|
-
</body>
|
|
213
|
-
</html>
|
|
214
|
-
`;
|
|
215
|
-
fetch.mockResolvedValue(createFetchResponse(html));
|
|
216
|
-
const result = await resolve("https://example.com/reference");
|
|
217
|
-
expect(result).toStrictEqual({
|
|
218
|
-
openapi: "3.0.0",
|
|
219
|
-
paths: {
|
|
220
|
-
"/": {
|
|
221
|
-
get: {
|
|
222
|
-
operationId: "AppController_getHello",
|
|
223
|
-
parameters: [],
|
|
224
|
-
responses: { "200": { description: "" } }
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
},
|
|
228
|
-
info: {
|
|
229
|
-
title: "Cats example",
|
|
230
|
-
description: "The cats<br>API description",
|
|
231
|
-
version: "1.0",
|
|
232
|
-
contact: {}
|
|
233
|
-
},
|
|
234
|
-
tags: [{ name: "cats", description: "" }],
|
|
235
|
-
servers: [],
|
|
236
|
-
components: { schemas: {} }
|
|
237
|
-
});
|
|
238
|
-
});
|
|
239
|
-
it("finds embedded OpenAPI document URLs (JSON)", async () => {
|
|
240
|
-
const html = `<!DOCTYPE html>
|
|
241
|
-
<html>
|
|
242
|
-
<head />
|
|
243
|
-
<body>
|
|
244
|
-
<script
|
|
245
|
-
id="api-reference"
|
|
246
|
-
type="application/json"
|
|
247
|
-
data-configuration="{"spec":{"url":"/openapi.json"}}">
|
|
248
|
-
<\/script>
|
|
249
|
-
<script src="https://cdn.jsdelivr.net/npm/@scalar/api-reference"><\/script>
|
|
250
|
-
</body>
|
|
251
|
-
</html>
|
|
252
|
-
`;
|
|
253
|
-
fetch.mockResolvedValue(createFetchResponse(html));
|
|
254
|
-
const result = await resolve("https://example.com/reference");
|
|
255
|
-
expect(result).toBe("https://example.com/openapi.json");
|
|
256
|
-
});
|
|
257
|
-
it("finds embedded OpenAPI document URLs (JSON) unescaped", async () => {
|
|
258
|
-
const html = `<!DOCTYPE html>
|
|
259
|
-
<html>
|
|
260
|
-
<head />
|
|
261
|
-
<body>
|
|
262
|
-
<script
|
|
263
|
-
id="api-reference"
|
|
264
|
-
type="application/json"
|
|
265
|
-
data-configuration='{"url":"/openapi.yaml","hideClientButton":false,"showSidebar":true,"theme":"default","_integration":"hono","layout":"modern","isEditable":false,"hideModels":false,"hideDownloadButton":false,"hideTestRequestButton":false,"hideSearch":false,"hideDarkModeToggle":false,"withDefaultFonts":true}'><\/script>
|
|
266
|
-
<script src="https://cdn.jsdelivr.net/npm/@scalar/api-reference"><\/script>
|
|
267
|
-
</body>
|
|
268
|
-
</html>
|
|
269
|
-
`;
|
|
270
|
-
fetch.mockResolvedValue(createFetchResponse(html));
|
|
271
|
-
const result = await resolve("https://example.com/reference");
|
|
272
|
-
expect(result).toBe("https://example.com/openapi.yaml");
|
|
273
|
-
});
|
|
274
|
-
it("finds embedded OpenAPI documents (YAML)", async () => {
|
|
275
|
-
const html = `<!DOCTYPE html>
|
|
276
|
-
<html>
|
|
277
|
-
<head />
|
|
278
|
-
<body>
|
|
279
|
-
|
|
280
|
-
<script
|
|
281
|
-
id="api-reference"
|
|
282
|
-
type="application/json"
|
|
283
|
-
data-configuration="{&quot;_integration&quot;:&quot;hono&quot;,&quot;spec&quot;:{&quot;content&quot;:&quot;openapi: 3.1.0
|
|
284
|
-
info:
|
|
285
|
-
title: Scalar Galaxy
|
|
286
|
-
description: |
|
|
287
|
-
The Scalar Galaxy is an example OpenAPI specification to test OpenAPI tools and libraries. It\u2019s a fictional universe with fictional planets and fictional data. Get all the data for [all planets](#tag/planets/GET/planets).
|
|
288
|
-
|
|
289
|
-
## Resources
|
|
290
|
-
|
|
291
|
-
* https://github.com/scalar/scalar
|
|
292
|
-
* https://github.com/OAI/OpenAPI-Specification
|
|
293
|
-
* https://scalar.com
|
|
294
|
-
|
|
295
|
-
## Markdown Support
|
|
296
|
-
|
|
297
|
-
All descriptions *can* contain ~~tons of text~~ **Markdown**. [If GitHub supports the syntax](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax), chances are we\u2019re supporting it, too. You can even create [internal links to reference endpoints](#tag/authentication/POST/user/signup).
|
|
298
|
-
|
|
299
|
-
<details>
|
|
300
|
-
<summary>Examples</summary>
|
|
301
|
-
|
|
302
|
-
**Blockquotes**
|
|
303
|
-
|
|
304
|
-
> I love OpenAPI. <3
|
|
305
|
-
|
|
306
|
-
**Tables**
|
|
307
|
-
|
|
308
|
-
| Feature | Availability |
|
|
309
|
-
| ---------------- | ------------ |
|
|
310
|
-
| Markdown Support | \u2713 |
|
|
311
|
-
|
|
312
|
-
**Accordion**
|
|
313
|
-
|
|
314
|
-
\`\`\`html
|
|
315
|
-
<details>
|
|
316
|
-
<summary>Using Details Tags</summary>
|
|
317
|
-
<p>HTML Example</p>
|
|
318
|
-
</details>
|
|
319
|
-
\`\`\`
|
|
320
|
-
|
|
321
|
-
**Images**
|
|
322
|
-
|
|
323
|
-
Yes, there\u2019s support for images, too!
|
|
324
|
-
|
|
325
|
-

|
|
326
|
-
|
|
327
|
-
</details>
|
|
328
|
-
version: 1.0.0
|
|
329
|
-
contact:
|
|
330
|
-
name: Marc from Scalar
|
|
331
|
-
url: https://scalar.com
|
|
332
|
-
email: marc@scalar.com
|
|
333
|
-
servers:
|
|
334
|
-
- url: https://galaxy.scalar.com
|
|
335
|
-
- url: '{protocol}://void.scalar.com/{path}'
|
|
336
|
-
description: Responds with your request data
|
|
337
|
-
variables:
|
|
338
|
-
protocol:
|
|
339
|
-
enum:
|
|
340
|
-
- https
|
|
341
|
-
default: https
|
|
342
|
-
path:
|
|
343
|
-
default: ''
|
|
344
|
-
security:
|
|
345
|
-
- bearerAuth: []
|
|
346
|
-
- basicAuth: []
|
|
347
|
-
- apiKeyQuery: []
|
|
348
|
-
- apiKeyHeader: []
|
|
349
|
-
- apiKeyCookie: []
|
|
350
|
-
- oAuth2: []
|
|
351
|
-
tags:
|
|
352
|
-
- name: Authentication
|
|
353
|
-
description:
|
|
354
|
-
Some endpoints are public, but some require authentication. We provide
|
|
355
|
-
all the required endpoints to create an account and authorize yourself.
|
|
356
|
-
- name: Planets
|
|
357
|
-
description: Everything about planets
|
|
358
|
-
paths:
|
|
359
|
-
'/planets':
|
|
360
|
-
get:
|
|
361
|
-
tags:
|
|
362
|
-
- Planets
|
|
363
|
-
summary: Get all planets
|
|
364
|
-
description: It\u2019s easy to say you know them all, but do you really? Retrieve all the planets and check whether you missed one.
|
|
365
|
-
operationId: getAllData
|
|
366
|
-
security:
|
|
367
|
-
- {}
|
|
368
|
-
parameters:
|
|
369
|
-
- '$ref': '#/components/parameters/limit'
|
|
370
|
-
- '$ref': '#/components/parameters/offset'
|
|
371
|
-
responses:
|
|
372
|
-
'200':
|
|
373
|
-
description: OK
|
|
374
|
-
content:
|
|
375
|
-
application/json:
|
|
376
|
-
schema:
|
|
377
|
-
allOf:
|
|
378
|
-
- type: object
|
|
379
|
-
properties:
|
|
380
|
-
data:
|
|
381
|
-
type: array
|
|
382
|
-
items:
|
|
383
|
-
'$ref': '#/components/schemas/Planet'
|
|
384
|
-
- '$ref': '#/components/schemas/PaginatedResource'
|
|
385
|
-
post:
|
|
386
|
-
tags:
|
|
387
|
-
- Planets
|
|
388
|
-
summary: Create a planet
|
|
389
|
-
description: Time to play god and create a new planet. What do you think? Ah, don\u2019t think too much. What could go wrong anyway?
|
|
390
|
-
operationId: createPlanet
|
|
391
|
-
requestBody:
|
|
392
|
-
description: Planet
|
|
393
|
-
content:
|
|
394
|
-
application/json:
|
|
395
|
-
schema:
|
|
396
|
-
'$ref': '#/components/schemas/Planet'
|
|
397
|
-
responses:
|
|
398
|
-
'201':
|
|
399
|
-
description: Created
|
|
400
|
-
content:
|
|
401
|
-
application/json:
|
|
402
|
-
schema:
|
|
403
|
-
'$ref': '#/components/schemas/Planet'
|
|
404
|
-
'400':
|
|
405
|
-
description: Bad Request
|
|
406
|
-
content:
|
|
407
|
-
application/json:
|
|
408
|
-
schema:
|
|
409
|
-
'$ref': '#/components/responses/BadRequest'
|
|
410
|
-
'403':
|
|
411
|
-
description: Forbidden
|
|
412
|
-
content:
|
|
413
|
-
application/json:
|
|
414
|
-
schema:
|
|
415
|
-
'$ref': '#/components/responses/Forbidden'
|
|
416
|
-
'/planets/{planetId}':
|
|
417
|
-
get:
|
|
418
|
-
tags:
|
|
419
|
-
- Planets
|
|
420
|
-
summary: Get a planet
|
|
421
|
-
description: You\u2019ll better learn a little bit more about the planets. It might come in handy once space travel is available for everyone.
|
|
422
|
-
operationId: getPlanet
|
|
423
|
-
security:
|
|
424
|
-
- {}
|
|
425
|
-
parameters:
|
|
426
|
-
- '$ref': '#/components/parameters/planetId'
|
|
427
|
-
responses:
|
|
428
|
-
'200':
|
|
429
|
-
description: Planet Found
|
|
430
|
-
content:
|
|
431
|
-
application/json:
|
|
432
|
-
schema:
|
|
433
|
-
'$ref': '#/components/schemas/Planet'
|
|
434
|
-
'404':
|
|
435
|
-
description: Planet Not Found
|
|
436
|
-
content:
|
|
437
|
-
application/json:
|
|
438
|
-
schema:
|
|
439
|
-
'$ref': '#/components/responses/NotFound'
|
|
440
|
-
put:
|
|
441
|
-
tags:
|
|
442
|
-
- Planets
|
|
443
|
-
summary: Update a planet
|
|
444
|
-
description: Sometimes you make mistakes, that\u2019s fine. No worries, you can update all planets.
|
|
445
|
-
operationId: updatePlanet
|
|
446
|
-
requestBody:
|
|
447
|
-
description: New information about the planet
|
|
448
|
-
content:
|
|
449
|
-
application/json:
|
|
450
|
-
schema:
|
|
451
|
-
'$ref': '#/components/schemas/Planet'
|
|
452
|
-
parameters:
|
|
453
|
-
- '$ref': '#/components/parameters/planetId'
|
|
454
|
-
responses:
|
|
455
|
-
'200':
|
|
456
|
-
description: OK
|
|
457
|
-
content:
|
|
458
|
-
application/json:
|
|
459
|
-
schema:
|
|
460
|
-
'$ref': '#/components/schemas/Planet'
|
|
461
|
-
'400':
|
|
462
|
-
description: Bad Request
|
|
463
|
-
content:
|
|
464
|
-
application/json:
|
|
465
|
-
schema:
|
|
466
|
-
'$ref': '#/components/responses/BadRequest'
|
|
467
|
-
'403':
|
|
468
|
-
description: Forbidden
|
|
469
|
-
content:
|
|
470
|
-
application/json:
|
|
471
|
-
schema:
|
|
472
|
-
'$ref': '#/components/responses/Forbidden'
|
|
473
|
-
'404':
|
|
474
|
-
description: Not Found
|
|
475
|
-
content:
|
|
476
|
-
application/json:
|
|
477
|
-
schema:
|
|
478
|
-
'$ref': '#/components/responses/NotFound'
|
|
479
|
-
delete:
|
|
480
|
-
tags:
|
|
481
|
-
- Planets
|
|
482
|
-
summary: Delete a planet
|
|
483
|
-
operationId: deletePlanet
|
|
484
|
-
description:
|
|
485
|
-
This endpoint was used to delete planets. Unfortunately, that caused
|
|
486
|
-
a lot of trouble for planets with life. So, this endpoint is now deprecated
|
|
487
|
-
and should not be used anymore.
|
|
488
|
-
deprecated: true
|
|
489
|
-
parameters:
|
|
490
|
-
- '$ref': '#/components/parameters/planetId'
|
|
491
|
-
responses:
|
|
492
|
-
'204':
|
|
493
|
-
description: No Content
|
|
494
|
-
'404':
|
|
495
|
-
description: Not Found
|
|
496
|
-
'/planets/{planetId}/image':
|
|
497
|
-
post:
|
|
498
|
-
tags:
|
|
499
|
-
- Planets
|
|
500
|
-
summary: Upload an image to a planet
|
|
501
|
-
description: Got a crazy good photo of a planet? Share it with the world!
|
|
502
|
-
operationId: uploadImage
|
|
503
|
-
parameters:
|
|
504
|
-
- '$ref': '#/components/parameters/planetId'
|
|
505
|
-
requestBody:
|
|
506
|
-
content:
|
|
507
|
-
multipart/form-data:
|
|
508
|
-
schema:
|
|
509
|
-
type: object
|
|
510
|
-
properties:
|
|
511
|
-
image:
|
|
512
|
-
type: string
|
|
513
|
-
format: binary
|
|
514
|
-
responses:
|
|
515
|
-
'200':
|
|
516
|
-
description: Image uploaded
|
|
517
|
-
content:
|
|
518
|
-
application/json:
|
|
519
|
-
schema:
|
|
520
|
-
type: object
|
|
521
|
-
properties:
|
|
522
|
-
message:
|
|
523
|
-
type: string
|
|
524
|
-
examples:
|
|
525
|
-
- Image uploaded successfully
|
|
526
|
-
'400':
|
|
527
|
-
description: Bad Upload Request
|
|
528
|
-
content:
|
|
529
|
-
application/json:
|
|
530
|
-
schema:
|
|
531
|
-
'$ref': '#/components/responses/BadRequest'
|
|
532
|
-
'403':
|
|
533
|
-
description: Upload Forbidden
|
|
534
|
-
content:
|
|
535
|
-
application/json:
|
|
536
|
-
schema:
|
|
537
|
-
'$ref': '#/components/responses/Forbidden'
|
|
538
|
-
'404':
|
|
539
|
-
description: Failed to Upload Image, Planet Not Found
|
|
540
|
-
content:
|
|
541
|
-
application/json:
|
|
542
|
-
schema:
|
|
543
|
-
'$ref': '#/components/responses/NotFound'
|
|
544
|
-
'/user/signup':
|
|
545
|
-
post:
|
|
546
|
-
tags:
|
|
547
|
-
- Authentication
|
|
548
|
-
summary: Create a user
|
|
549
|
-
description: Time to create a user account, eh?
|
|
550
|
-
operationId: createUser
|
|
551
|
-
security:
|
|
552
|
-
- {}
|
|
553
|
-
requestBody:
|
|
554
|
-
content:
|
|
555
|
-
application/json:
|
|
556
|
-
schema:
|
|
557
|
-
'$ref': '#/components/schemas/NewUser'
|
|
558
|
-
examples:
|
|
559
|
-
Marc:
|
|
560
|
-
value:
|
|
561
|
-
name: Marc
|
|
562
|
-
email: marc@scalar.com
|
|
563
|
-
password: i-love-scalar
|
|
564
|
-
Cam:
|
|
565
|
-
value:
|
|
566
|
-
name: Cam
|
|
567
|
-
email: cam@scalar.com
|
|
568
|
-
password: scalar-is-cool
|
|
569
|
-
responses:
|
|
570
|
-
'201':
|
|
571
|
-
description: Created
|
|
572
|
-
content:
|
|
573
|
-
application/json:
|
|
574
|
-
schema:
|
|
575
|
-
'$ref': '#/components/schemas/User'
|
|
576
|
-
'400':
|
|
577
|
-
description: Bad Request
|
|
578
|
-
content:
|
|
579
|
-
application/json:
|
|
580
|
-
schema:
|
|
581
|
-
'$ref': '#/components/responses/BadRequest'
|
|
582
|
-
'/auth/token':
|
|
583
|
-
post:
|
|
584
|
-
tags:
|
|
585
|
-
- Authentication
|
|
586
|
-
summary: Get a token
|
|
587
|
-
description: Yeah, this is the boring security stuff. Just get your super secret token and move on.
|
|
588
|
-
operationId: getToken
|
|
589
|
-
security:
|
|
590
|
-
- {}
|
|
591
|
-
requestBody:
|
|
592
|
-
content:
|
|
593
|
-
application/json:
|
|
594
|
-
schema:
|
|
595
|
-
'$ref': '#/components/schemas/Credentials'
|
|
596
|
-
responses:
|
|
597
|
-
'201':
|
|
598
|
-
description: Token Created
|
|
599
|
-
content:
|
|
600
|
-
application/json:
|
|
601
|
-
schema:
|
|
602
|
-
'$ref': '#/components/schemas/Token'
|
|
603
|
-
'/me':
|
|
604
|
-
get:
|
|
605
|
-
tags:
|
|
606
|
-
- Authentication
|
|
607
|
-
summary: Get authenticated user
|
|
608
|
-
description: Find yourself they say. That\u2019s what you can do here.
|
|
609
|
-
operationId: getMe
|
|
610
|
-
security:
|
|
611
|
-
- basicAuth: []
|
|
612
|
-
- oAuth2:
|
|
613
|
-
- read:account
|
|
614
|
-
- bearerAuth: []
|
|
615
|
-
- apiKeyHeader: []
|
|
616
|
-
- apiKeyQuery: []
|
|
617
|
-
responses:
|
|
618
|
-
'200':
|
|
619
|
-
description: OK
|
|
620
|
-
content:
|
|
621
|
-
application/json:
|
|
622
|
-
schema:
|
|
623
|
-
'$ref': '#/components/schemas/User'
|
|
624
|
-
'401':
|
|
625
|
-
description: Unauthorized
|
|
626
|
-
content:
|
|
627
|
-
application/json:
|
|
628
|
-
schema:
|
|
629
|
-
'$ref': '#/components/responses/Unauthorized'
|
|
630
|
-
'403':
|
|
631
|
-
description: Forbidden
|
|
632
|
-
content:
|
|
633
|
-
application/json:
|
|
634
|
-
schema:
|
|
635
|
-
'$ref': '#/components/responses/Forbidden'
|
|
636
|
-
webhooks:
|
|
637
|
-
newPlanet:
|
|
638
|
-
post:
|
|
639
|
-
tags:
|
|
640
|
-
- Planets
|
|
641
|
-
requestBody:
|
|
642
|
-
description: Information about a new planet
|
|
643
|
-
content:
|
|
644
|
-
application/json:
|
|
645
|
-
schema:
|
|
646
|
-
'$ref': '#/components/schemas/Planet'
|
|
647
|
-
responses:
|
|
648
|
-
'200':
|
|
649
|
-
description:
|
|
650
|
-
Return a 200 status to indicate that the data was received
|
|
651
|
-
successfully
|
|
652
|
-
components:
|
|
653
|
-
securitySchemes:
|
|
654
|
-
bearerAuth:
|
|
655
|
-
type: http
|
|
656
|
-
scheme: bearer
|
|
657
|
-
basicAuth:
|
|
658
|
-
type: http
|
|
659
|
-
scheme: basic
|
|
660
|
-
apiKeyHeader:
|
|
661
|
-
type: apiKey
|
|
662
|
-
in: header
|
|
663
|
-
name: X-API-Key
|
|
664
|
-
apiKeyQuery:
|
|
665
|
-
type: apiKey
|
|
666
|
-
in: query
|
|
667
|
-
name: api_key
|
|
668
|
-
apiKeyCookie:
|
|
669
|
-
type: apiKey
|
|
670
|
-
in: cookie
|
|
671
|
-
name: api_key
|
|
672
|
-
oAuth2:
|
|
673
|
-
type: oauth2
|
|
674
|
-
flows:
|
|
675
|
-
authorizationCode:
|
|
676
|
-
authorizationUrl: https://galaxy.scalar.com/oauth/authorize
|
|
677
|
-
tokenUrl: https://galaxy.scalar.com/oauth/token
|
|
678
|
-
scopes:
|
|
679
|
-
read:account: read your account information
|
|
680
|
-
write:planets: modify planets in your account
|
|
681
|
-
read:planets: read your planets
|
|
682
|
-
clientCredentials:
|
|
683
|
-
tokenUrl: https://galaxy.scalar.com/oauth/token
|
|
684
|
-
scopes:
|
|
685
|
-
read:account: read your account information
|
|
686
|
-
write:planets: modify planets in your account
|
|
687
|
-
read:planets: read your planets
|
|
688
|
-
# Legacy
|
|
689
|
-
implicit:
|
|
690
|
-
authorizationUrl: https://galaxy.scalar.com/oauth/authorize
|
|
691
|
-
scopes:
|
|
692
|
-
read:account: read your account information
|
|
693
|
-
write:planets: modify planets in your account
|
|
694
|
-
read:planets: read your planets
|
|
695
|
-
# Legacy
|
|
696
|
-
password:
|
|
697
|
-
tokenUrl: https://galaxy.scalar.com/oauth/token
|
|
698
|
-
scopes:
|
|
699
|
-
read:account: read your account information
|
|
700
|
-
write:planets: modify planets in your account
|
|
701
|
-
read:planets: read your planets
|
|
702
|
-
parameters:
|
|
703
|
-
planetId:
|
|
704
|
-
name: planetId
|
|
705
|
-
in: path
|
|
706
|
-
required: true
|
|
707
|
-
schema:
|
|
708
|
-
type: integer
|
|
709
|
-
format: int64
|
|
710
|
-
examples:
|
|
711
|
-
- 1
|
|
712
|
-
limit:
|
|
713
|
-
name: limit
|
|
714
|
-
in: query
|
|
715
|
-
description: The number of items to return
|
|
716
|
-
required: false
|
|
717
|
-
schema:
|
|
718
|
-
type: integer
|
|
719
|
-
format: int64
|
|
720
|
-
default: 10
|
|
721
|
-
offset:
|
|
722
|
-
name: offset
|
|
723
|
-
in: query
|
|
724
|
-
description:
|
|
725
|
-
The number of items to skip before starting to collect the result
|
|
726
|
-
set
|
|
727
|
-
required: false
|
|
728
|
-
schema:
|
|
729
|
-
type: integer
|
|
730
|
-
format: int64
|
|
731
|
-
default: 0
|
|
732
|
-
responses:
|
|
733
|
-
BadRequest:
|
|
734
|
-
description: Bad Request
|
|
735
|
-
content:
|
|
736
|
-
application/json:
|
|
737
|
-
schema:
|
|
738
|
-
'$ref': '#/components/schemas/Error'
|
|
739
|
-
Forbidden:
|
|
740
|
-
description: Forbidden
|
|
741
|
-
content:
|
|
742
|
-
application/json:
|
|
743
|
-
schema:
|
|
744
|
-
'$ref': '#/components/schemas/Error'
|
|
745
|
-
NotFound:
|
|
746
|
-
description: NotFound
|
|
747
|
-
content:
|
|
748
|
-
application/json:
|
|
749
|
-
schema:
|
|
750
|
-
'$ref': '#/components/schemas/Error'
|
|
751
|
-
Unauthorized:
|
|
752
|
-
description: Unauthorized
|
|
753
|
-
content:
|
|
754
|
-
application/json:
|
|
755
|
-
schema:
|
|
756
|
-
'$ref': '#/components/schemas/Error'
|
|
757
|
-
schemas:
|
|
758
|
-
NewUser:
|
|
759
|
-
type: object
|
|
760
|
-
required:
|
|
761
|
-
- name
|
|
762
|
-
- email
|
|
763
|
-
- password
|
|
764
|
-
properties:
|
|
765
|
-
name:
|
|
766
|
-
type: string
|
|
767
|
-
examples:
|
|
768
|
-
- Hans
|
|
769
|
-
- Brynn
|
|
770
|
-
email:
|
|
771
|
-
type: string
|
|
772
|
-
format: email
|
|
773
|
-
examples:
|
|
774
|
-
- hans@scalar.com
|
|
775
|
-
- brynn@scalar.com
|
|
776
|
-
password:
|
|
777
|
-
type: string
|
|
778
|
-
minLength: 8
|
|
779
|
-
examples:
|
|
780
|
-
- i-love-scalar
|
|
781
|
-
- scalar-is-cool
|
|
782
|
-
User:
|
|
783
|
-
type: object
|
|
784
|
-
required:
|
|
785
|
-
- id
|
|
786
|
-
- name
|
|
787
|
-
- email
|
|
788
|
-
properties:
|
|
789
|
-
id:
|
|
790
|
-
type: integer
|
|
791
|
-
format: int64
|
|
792
|
-
examples:
|
|
793
|
-
- 1
|
|
794
|
-
name:
|
|
795
|
-
type: string
|
|
796
|
-
examples:
|
|
797
|
-
- Marc
|
|
798
|
-
email:
|
|
799
|
-
type: string
|
|
800
|
-
format: email
|
|
801
|
-
examples:
|
|
802
|
-
- marc@scalar.com
|
|
803
|
-
Credentials:
|
|
804
|
-
type: object
|
|
805
|
-
required:
|
|
806
|
-
- email
|
|
807
|
-
- password
|
|
808
|
-
properties:
|
|
809
|
-
email:
|
|
810
|
-
type: string
|
|
811
|
-
format: email
|
|
812
|
-
examples:
|
|
813
|
-
- marc@scalar.com
|
|
814
|
-
password:
|
|
815
|
-
type: string
|
|
816
|
-
examples:
|
|
817
|
-
- i-love-scalar
|
|
818
|
-
Token:
|
|
819
|
-
type: object
|
|
820
|
-
properties:
|
|
821
|
-
token:
|
|
822
|
-
type: string
|
|
823
|
-
examples:
|
|
824
|
-
- eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
|
|
825
|
-
Planet:
|
|
826
|
-
type: object
|
|
827
|
-
required:
|
|
828
|
-
- id
|
|
829
|
-
- name
|
|
830
|
-
properties:
|
|
831
|
-
id:
|
|
832
|
-
type: integer
|
|
833
|
-
format: int64
|
|
834
|
-
examples:
|
|
835
|
-
- 1
|
|
836
|
-
x-variable: planetId
|
|
837
|
-
name:
|
|
838
|
-
type: string
|
|
839
|
-
examples:
|
|
840
|
-
- Mars
|
|
841
|
-
description:
|
|
842
|
-
type:
|
|
843
|
-
- string
|
|
844
|
-
- 'null'
|
|
845
|
-
examples:
|
|
846
|
-
- The red planet
|
|
847
|
-
image:
|
|
848
|
-
type: string
|
|
849
|
-
nullable: true
|
|
850
|
-
examples:
|
|
851
|
-
- https://cdn.scalar.com/photos/mars.jpg
|
|
852
|
-
creator:
|
|
853
|
-
'$ref': '#/components/schemas/User'
|
|
854
|
-
PaginatedResource:
|
|
855
|
-
type: object
|
|
856
|
-
properties:
|
|
857
|
-
meta:
|
|
858
|
-
type: object
|
|
859
|
-
properties:
|
|
860
|
-
limit:
|
|
861
|
-
type: integer
|
|
862
|
-
format: int64
|
|
863
|
-
examples:
|
|
864
|
-
- 10
|
|
865
|
-
offset:
|
|
866
|
-
type: integer
|
|
867
|
-
format: int64
|
|
868
|
-
examples:
|
|
869
|
-
- 0
|
|
870
|
-
total:
|
|
871
|
-
type: integer
|
|
872
|
-
format: int64
|
|
873
|
-
examples:
|
|
874
|
-
- 100
|
|
875
|
-
next:
|
|
876
|
-
type:
|
|
877
|
-
- string
|
|
878
|
-
- 'null'
|
|
879
|
-
examples:
|
|
880
|
-
- '/planets?limit=10&offset=10'
|
|
881
|
-
Error:
|
|
882
|
-
type: object
|
|
883
|
-
description: RFC 7807 (https://datatracker.ietf.org/doc/html/rfc7807)
|
|
884
|
-
properties:
|
|
885
|
-
type:
|
|
886
|
-
type: string
|
|
887
|
-
examples:
|
|
888
|
-
- https://example.com/errors/generic-error
|
|
889
|
-
title:
|
|
890
|
-
type: string
|
|
891
|
-
examples:
|
|
892
|
-
- Something went wrong here.
|
|
893
|
-
status:
|
|
894
|
-
type: integer
|
|
895
|
-
format: int64
|
|
896
|
-
examples:
|
|
897
|
-
- 403
|
|
898
|
-
detail:
|
|
899
|
-
type: string
|
|
900
|
-
examples:
|
|
901
|
-
- Unfortunately, we can\u2019t provide further information.
|
|
902
|
-
&quot;},&quot;pageTitle&quot;:&quot;Scalar Galaxy&quot;}"><\/script>
|
|
903
|
-
<script src="https://cdn.jsdelivr.net/npm/@scalar/api-reference"><\/script>
|
|
904
|
-
</body>
|
|
905
|
-
</html>`;
|
|
906
|
-
fetch.mockResolvedValue(createFetchResponse(html));
|
|
907
|
-
const result = await resolve("https://example.com/reference");
|
|
908
|
-
expect(result).toMatchObject({
|
|
909
|
-
openapi: "3.1.0",
|
|
910
|
-
info: {
|
|
911
|
-
title: "Scalar Galaxy"
|
|
912
|
-
}
|
|
913
|
-
});
|
|
914
|
-
});
|
|
915
|
-
it("transforms GitHub URLs to raw file URLs", async () => {
|
|
916
|
-
const result = await resolve("https://github.com/outline/openapi/blob/main/spec3.yml");
|
|
917
|
-
expect(result).toBe("https://raw.githubusercontent.com/outline/openapi/refs/heads/main/spec3.yml");
|
|
918
|
-
});
|
|
919
|
-
it("finds embedded OpenAPI document in script tag (JSON)", async () => {
|
|
920
|
-
const html = `<!DOCTYPE html>
|
|
921
|
-
<html>
|
|
922
|
-
<head />
|
|
923
|
-
<body>
|
|
924
|
-
<script
|
|
925
|
-
id="api-reference"
|
|
926
|
-
type="application/json">
|
|
927
|
-
{"openapi":"3.1.0","info":{"title":"Hello World","version":"1.0"}}
|
|
928
|
-
<\/script>
|
|
929
|
-
</body>
|
|
930
|
-
</html>
|
|
931
|
-
`;
|
|
932
|
-
fetch.mockResolvedValue(createFetchResponse(html));
|
|
933
|
-
const result = await resolve("https://example.com/reference");
|
|
934
|
-
expect(result).toStrictEqual({
|
|
935
|
-
openapi: "3.1.0",
|
|
936
|
-
info: {
|
|
937
|
-
title: "Hello World",
|
|
938
|
-
version: "1.0"
|
|
939
|
-
}
|
|
940
|
-
});
|
|
941
|
-
});
|
|
942
|
-
it("finds embedded OpenAPI document in script tag, even if it contains HTML tags (JSON)", async () => {
|
|
943
|
-
const html = `<!DOCTYPE html>
|
|
944
|
-
<html>
|
|
945
|
-
<head />
|
|
946
|
-
<body>
|
|
947
|
-
<script
|
|
948
|
-
id="api-reference"
|
|
949
|
-
type="application/json">{"openapi":"3.0.0","paths":{"/v1/projects/{ref}/sessions/tags":{"type":"string","pattern":"/^\\s*([a-z0-9_-]+(\\s*,+\\s*)?)*\\s*$/i"}}}<\/script>
|
|
950
|
-
</body>
|
|
951
|
-
</html>
|
|
952
|
-
`;
|
|
953
|
-
fetch.mockResolvedValue(createFetchResponse(html));
|
|
954
|
-
const result = await resolve("https://example.com/reference");
|
|
955
|
-
expect(result).toStrictEqual({
|
|
956
|
-
openapi: "3.0.0",
|
|
957
|
-
paths: {
|
|
958
|
-
"/v1/projects/{ref}/sessions/tags": {
|
|
959
|
-
pattern: "/^\\s*([a-z0-9_-]+(\\s*,+\\s*)?)*\\s*$/i",
|
|
960
|
-
type: "string"
|
|
961
|
-
}
|
|
962
|
-
}
|
|
963
|
-
});
|
|
964
|
-
});
|
|
965
|
-
it("finds embedded OpenAPI document in script tag (YAML)", async () => {
|
|
966
|
-
const html = `<!DOCTYPE html>
|
|
967
|
-
<html>
|
|
968
|
-
<head />
|
|
969
|
-
<body>
|
|
970
|
-
<script
|
|
971
|
-
id="api-reference"
|
|
972
|
-
type="application/yaml">
|
|
973
|
-
openapi: 3.1.0
|
|
974
|
-
info:
|
|
975
|
-
title: Hello World
|
|
976
|
-
version: '1.0'
|
|
977
|
-
<\/script>
|
|
978
|
-
</body>
|
|
979
|
-
</html>
|
|
980
|
-
`;
|
|
981
|
-
fetch.mockResolvedValue(createFetchResponse(html));
|
|
982
|
-
const result = await resolve("https://example.com/reference");
|
|
983
|
-
expect(result).toStrictEqual({
|
|
984
|
-
openapi: "3.1.0",
|
|
985
|
-
info: {
|
|
986
|
-
title: "Hello World",
|
|
987
|
-
version: "1.0"
|
|
988
|
-
}
|
|
989
|
-
});
|
|
990
|
-
});
|
|
991
|
-
it("finds OpenAPI URL in HTML link text", async () => {
|
|
992
|
-
const html = `<!DOCTYPE html>
|
|
993
|
-
<html>
|
|
994
|
-
<body>
|
|
995
|
-
<p>Fetching spec from <a href="https://example.com/v1/openapi.yml" rel="nofollow" target="_blank">https://example.com/v1/openapi.yml</a></p>
|
|
996
|
-
</body>
|
|
997
|
-
</html>
|
|
998
|
-
`;
|
|
999
|
-
fetch.mockResolvedValue(createFetchResponse(html));
|
|
1000
|
-
const result = await resolve("https://example.com/reference");
|
|
1001
|
-
expect(result).toBe("https://example.com/v1/openapi.yml");
|
|
1002
|
-
});
|
|
1003
|
-
it("finds URL in script configuration", async () => {
|
|
1004
|
-
const html = `<!DOCTYPE html>
|
|
1005
|
-
<html>
|
|
1006
|
-
<head />
|
|
1007
|
-
<body>
|
|
1008
|
-
<script>
|
|
1009
|
-
var configuration = {
|
|
1010
|
-
isEditable: false,
|
|
1011
|
-
layout: "classic",
|
|
1012
|
-
darkMode: false,
|
|
1013
|
-
searchHotKey: "nope",
|
|
1014
|
-
url: "/docs/files/openapi.json",
|
|
1015
|
-
}
|
|
1016
|
-
var apiReference = document.getElementById('api-reference')
|
|
1017
|
-
apiReference.dataset.configuration = JSON.stringify(configuration)
|
|
1018
|
-
<\/script>
|
|
1019
|
-
<script src="https://cdn.jsdelivr.net/npm/@scalar/api-reference@1.20"><\/script>
|
|
1020
|
-
</body>
|
|
1021
|
-
</html>
|
|
1022
|
-
`;
|
|
1023
|
-
fetch.mockResolvedValue(createFetchResponse(html));
|
|
1024
|
-
const result = await resolve("https://example.com/reference");
|
|
1025
|
-
expect(result).toBe("https://example.com/docs/files/openapi.json");
|
|
1026
|
-
});
|
|
1027
|
-
it("returns URL if it directly returns an OpenAPI document", async () => {
|
|
1028
|
-
const openApiDoc = {
|
|
1029
|
-
openapi: "3.0.0",
|
|
1030
|
-
info: {
|
|
1031
|
-
title: "Test API",
|
|
1032
|
-
version: "1.0.0"
|
|
1033
|
-
},
|
|
1034
|
-
paths: {}
|
|
1035
|
-
};
|
|
1036
|
-
fetch.mockResolvedValue(createFetchResponse(JSON.stringify(openApiDoc)));
|
|
1037
|
-
const result = await resolve("https://example.com/swagger/json");
|
|
1038
|
-
expect(result).toBe("https://example.com/swagger/json");
|
|
1039
|
-
});
|
|
1040
|
-
it("finds the URL in an escaped JS object", async () => {
|
|
1041
|
-
fetch.mockResolvedValue(
|
|
1042
|
-
createFetchResponse(
|
|
1043
|
-
`<html>\\"$L8e\\",null,{\\"configuration\\":{\\"spec\\":{\\"url\\":\\"https://raw.githubusercontent.com/Foo/Bar/main/api/foobar.json\\"}},\\"initialRequest`
|
|
1044
|
-
)
|
|
1045
|
-
);
|
|
1046
|
-
const result = await resolve("https://example.com/foo");
|
|
1047
|
-
expect(result).toBe("https://raw.githubusercontent.com/Foo/Bar/main/api/foobar.json");
|
|
1048
|
-
});
|
|
1049
|
-
});
|
|
1050
|
-
//# sourceMappingURL=resolve.test.js.map
|
package/dist/resolve.test.js.map
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../src/resolve.test.ts"],
|
|
4
|
-
"sourcesContent": ["import { beforeEach, describe, expect, it, vi } from 'vitest'\n\nimport { resolve } from './resolve'\n\nglobal.fetch = vi.fn()\n\nfunction createFetchResponse(data: string, headers: Record<string, string> = {}) {\n return {\n ok: true,\n text: () => new Promise((r) => r(data)),\n headers: new Headers(headers),\n }\n}\n\ndescribe('resolve', () => {\n beforeEach(() => {\n // @ts-expect-error\n global.fetch.mockReset()\n })\n\n it('returns JSON urls', async () => {\n const result = await resolve('https://cdn.jsdelivr.net/npm/@scalar/galaxy/dist/latest.json')\n\n expect(result).toBe('https://cdn.jsdelivr.net/npm/@scalar/galaxy/dist/latest.json')\n })\n\n it('returns YAML urls', async () => {\n const result = await resolve('https://cdn.jsdelivr.net/npm/@scalar/galaxy/dist/latest.yaml')\n\n expect(result).toBe('https://cdn.jsdelivr.net/npm/@scalar/galaxy/dist/latest.yaml')\n\n const otherResult = await resolve('https://cdn.jsdelivr.net/npm/@scalar/galaxy/dist/latest.yml')\n\n expect(otherResult).toBe('https://cdn.jsdelivr.net/npm/@scalar/galaxy/dist/latest.yml')\n })\n\n it('finds URLs from sandbox URL', async () => {\n const result = await resolve('https://sandbox.scalar.com/p/GcxDQ')\n\n expect(result).toBe('https://sandbox.scalar.com/files/GcxDQ/openapi.yaml')\n\n const otherResult = await resolve('https://sandbox.scalar.com/e/GcxDQ')\n\n expect(otherResult).toBe('https://sandbox.scalar.com/files/GcxDQ/openapi.yaml')\n })\n\n it('finds URL in the CDN example', async () => {\n const html = `<!doctype html>\n<html>\n <head>\n <title>Scalar API Reference</title>\n <meta charset=\"utf-8\" />\n <meta\n name=\"viewport\"\n content=\"width=device-width, initial-scale=1\" />\n </head>\n <body>\n <script\n id=\"api-reference\"\n data-url=\"https://cdn.jsdelivr.net/npm/@scalar/galaxy/dist/latest.yaml\"></script>\n <script src=\"https://cdn.jsdelivr.net/npm/@scalar/api-reference\"></script>\n </body>\n</html>`\n\n // @ts-expect-error Mocking types are missing\n fetch.mockResolvedValue(createFetchResponse(html))\n\n const result = await resolve('https://example.com/reference')\n\n expect(result).toBe('https://cdn.jsdelivr.net/npm/@scalar/galaxy/dist/latest.yaml')\n })\n\n it('works with single quote data attributes', async () => {\n const html = `<!doctype html>\n<html>\n <head>\n <title>Scalar API Reference</title>\n <meta charset=\"utf-8\" />\n <meta\n name=\"viewport\"\n content=\"width=device-width, initial-scale=1\" />\n </head>\n <body>\n <script\n id=\"api-reference\"\n data-url='https://cdn.jsdelivr.net/npm/@scalar/galaxy/dist/latest.yaml'></script>\n <script src=\"https://cdn.jsdelivr.net/npm/@scalar/api-reference\"></script>\n </body>\n</html>`\n\n // @ts-expect-error Mocking types are missing\n fetch.mockResolvedValue(createFetchResponse(html))\n\n const result = await resolve('https://example.com/reference')\n\n expect(result).toBe('https://cdn.jsdelivr.net/npm/@scalar/galaxy/dist/latest.yaml')\n })\n\n it('returns absolute URLs', async () => {\n const html = `<!doctype html>\n<html>\n <head>\n <title>Scalar API Reference</title>\n <meta charset=\"utf-8\" />\n <meta\n name=\"viewport\"\n content=\"width=device-width, initial-scale=1\" />\n </head>\n <body>\n <div data-url=\"/not-what-we-are-looking-for\" id=\"foobar\" />\n <script\n id=\"api-reference\"\n data-url=\"/openapi.yaml\"></script>\n <script src=\"https://cdn.jsdelivr.net/npm/@scalar/api-reference\"></script>\n </body>\n</html>`\n\n // @ts-expect-error Mocking types are missing\n fetch.mockResolvedValue(createFetchResponse(html))\n\n const result = await resolve('https://example.com/reference')\n\n expect(result).toBe('https://example.com/openapi.yaml')\n })\n\n it('returns absolute URLs based on the X-Forwarded-Host header', async () => {\n const html = `<!doctype html>\n<html>\n <head>\n <title>Scalar API Reference</title>\n <meta charset=\"utf-8\" />\n <meta\n name=\"viewport\"\n content=\"width=device-width, initial-scale=1\" />\n </head>\n <body>\n <div data-url=\"/not-what-we-are-looking-for\" id=\"foobar\" />\n <script\n id=\"api-reference\"\n data-url=\"../openapi.yaml\"></script>\n <script src=\"https://cdn.jsdelivr.net/npm/@scalar/api-reference\"></script>\n </body>\n</html>`\n\n // @ts-expect-error Mocking types are missing\n fetch.mockResolvedValue(\n createFetchResponse(html, {\n 'X-Forwarded-Host': 'https://example.com/somewhere/else/',\n }),\n )\n\n const result = await resolve('https://example.com/reference')\n\n expect(result).toBe('https://example.com/somewhere/openapi.yaml')\n })\n\n it('finds URLs in some wrangled configuration object', async () => {\n const html = `<!DOCTYPE html>\n<html>\n <head>\n <title>Hono API Reference Demo</title>\n <meta charset=\"utf-8\" />\n <meta\n name=\"viewport\"\n content=\"width=device-width, initial-scale=1\" />\n </head>\n <body>\n\n <script\n id=\"api-reference\"\n type=\"application/json\"\n data-configuration=\"{&quot;spec&quot;:{&quot;url&quot;:&quot;/openapi.yaml&quot;},&quot;pageTitle&quot;:&quot;Hono API Reference Demo&quot;}\">\n\n </script>\n <script src=\"https://cdn.jsdelivr.net/npm/@scalar/api-reference\"></script>\n\n </body>\n</html>`\n\n // @ts-expect-error Mocking types are missing\n fetch.mockResolvedValue(createFetchResponse(html))\n\n const result = await resolve('https://example.com/reference')\n\n expect(result).toBe('https://example.com/openapi.yaml')\n })\n\n it('finds URLs in redoc HTML', async () => {\n const html = `<!DOCTYPE html>\n<html>\n <head>\n <title>Redoc</title>\n <meta charset=\"utf-8\"/>\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n <link href=\"https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700\" rel=\"stylesheet\">\n </head>\n <body>\n <redoc spec-url='https://cdn.jsdelivr.net/npm/@scalar/galaxy/dist/latest.yaml'></redoc>\n <script src=\"https://cdn.redoc.ly/redoc/latest/bundles/redoc.standalone.js\"> </script>\n </body>\n</html>`\n\n // @ts-expect-error Mocking types are missing\n fetch.mockResolvedValue(createFetchResponse(html))\n\n const result = await resolve('https://example.com/reference')\n\n expect(result).toBe('https://cdn.jsdelivr.net/npm/@scalar/galaxy/dist/latest.yaml')\n })\n\n it('finds embedded OpenAPI documents', async () => {\n const html = `<!DOCTYPE html>\n<html>\n <head />\n <body>\n <script\n id=\"api-reference\"\n type=\"application/json\"\n data-configuration=\"{"spec":{"content":{"openapi":"3.0.0","paths":{"/":{"get":{"operationId":"AppController_getHello","parameters":[],"responses":{"200":{"description":""}}}}},"info":{"title":"Cats example","description":"The cats API description","version":"1.0","contact":{}},"tags":[{"name":"cats","description":""}],"servers":[],"components":{"schemas":{}}}}}\">{\"openapi\":\"3.0.0\",\"paths\":{\"/\":{\"get\":{\"operationId\":\"AppController_getHello\",\"parameters\":[],\"responses\":{\"200\":{\"description\":\"\"}}}}},\"info\":{\"title\":\"Cats example\",\"description\":\"The cats API description\",\"version\":\"1.0\",\"contact\":{}},\"tags\":[{\"name\":\"cats\",\"description\":\"\"}],\"servers\":[],\"components\":{\"schemas\":{}}}</script>\n <script src=\"https://cdn.jsdelivr.net/npm/@scalar/api-reference\"></script>\n </body>\n</html>\n `\n\n // @ts-expect-error Mocking types are missing\n fetch.mockResolvedValue(createFetchResponse(html))\n\n const result = await resolve('https://example.com/reference')\n\n expect(result).toStrictEqual({\n openapi: '3.0.0',\n paths: {\n '/': {\n get: {\n operationId: 'AppController_getHello',\n parameters: [],\n responses: { '200': { description: '' } },\n },\n },\n },\n info: {\n title: 'Cats example',\n description: 'The cats API description',\n version: '1.0',\n contact: {},\n },\n tags: [{ name: 'cats', description: '' }],\n servers: [],\n components: { schemas: {} },\n })\n })\n\n it('finds embedded OpenAPI documents, even if they contain HTML tags', async () => {\n const html = `<!DOCTYPE html>\n<html>\n <head />\n <body>\n <script\n id=\"api-reference\"\n type=\"application/json\"\n data-configuration=\"{"spec":{"content":{"openapi":"3.0.0","paths":{"/":{"get":{"operationId":"AppController_getHello","parameters":[],"responses":{"200":{"description":""}}}}},"info":{"title":"Cats example","description":"The cats<br>API description","version":"1.0","contact":{}},"tags":[{"name":"cats","description":""}],"servers":[],"components":{"schemas":{}}}}}\"></script>\n <script src=\"https://cdn.jsdelivr.net/npm/@scalar/api-reference\"></script>\n </body>\n</html>\n `\n\n // @ts-expect-error Mocking types are missing\n fetch.mockResolvedValue(createFetchResponse(html))\n\n const result = await resolve('https://example.com/reference')\n\n expect(result).toStrictEqual({\n openapi: '3.0.0',\n paths: {\n '/': {\n get: {\n operationId: 'AppController_getHello',\n parameters: [],\n responses: { '200': { description: '' } },\n },\n },\n },\n info: {\n title: 'Cats example',\n description: 'The cats<br>API description',\n version: '1.0',\n contact: {},\n },\n tags: [{ name: 'cats', description: '' }],\n servers: [],\n components: { schemas: {} },\n })\n })\n\n it('finds embedded OpenAPI document URLs (JSON)', async () => {\n const html = `<!DOCTYPE html>\n<html>\n <head />\n <body>\n <script\n id=\"api-reference\"\n type=\"application/json\"\n data-configuration=\"{"spec":{"url":"/openapi.json"}}\">\n </script>\n <script src=\"https://cdn.jsdelivr.net/npm/@scalar/api-reference\"></script>\n </body>\n</html>\n `\n\n // @ts-expect-error Mocking types are missing\n fetch.mockResolvedValue(createFetchResponse(html))\n\n const result = await resolve('https://example.com/reference')\n\n expect(result).toBe('https://example.com/openapi.json')\n })\n\n it('finds embedded OpenAPI document URLs (JSON) unescaped', async () => {\n const html = `<!DOCTYPE html>\n<html>\n <head />\n <body>\n <script\n id=\"api-reference\"\n type=\"application/json\"\n data-configuration='{\"url\":\"/openapi.yaml\",\"hideClientButton\":false,\"showSidebar\":true,\"theme\":\"default\",\"_integration\":\"hono\",\"layout\":\"modern\",\"isEditable\":false,\"hideModels\":false,\"hideDownloadButton\":false,\"hideTestRequestButton\":false,\"hideSearch\":false,\"hideDarkModeToggle\":false,\"withDefaultFonts\":true}'></script>\n <script src=\"https://cdn.jsdelivr.net/npm/@scalar/api-reference\"></script>\n </body>\n</html>\n `\n\n // @ts-expect-error Mocking types are missing\n fetch.mockResolvedValue(createFetchResponse(html))\n\n const result = await resolve('https://example.com/reference')\n\n expect(result).toBe('https://example.com/openapi.yaml')\n })\n\n it('finds embedded OpenAPI documents (YAML)', async () => {\n const html = `<!DOCTYPE html>\n <html>\n <head />\n <body>\n\n <script\n id=\"api-reference\"\n type=\"application/json\"\n data-configuration=\"{&quot;_integration&quot;:&quot;hono&quot;,&quot;spec&quot;:{&quot;content&quot;:&quot;openapi: 3.1.0\\ninfo:\\n title: Scalar Galaxy\\n description: |\\n The Scalar Galaxy is an example OpenAPI specification to test OpenAPI tools and libraries. It\u2019s a fictional universe with fictional planets and fictional data. Get all the data for [all planets](#tag/planets/GET/planets).\\n\\n ## Resources\\n\\n * https://github.com/scalar/scalar\\n * https://github.com/OAI/OpenAPI-Specification\\n * https://scalar.com\\n\\n ## Markdown Support\\n\\n All descriptions *can* contain ~~tons of text~~ **Markdown**. [If GitHub supports the syntax](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax), chances are we\u2019re supporting it, too. You can even create [internal links to reference endpoints](#tag/authentication/POST/user/signup).\\n\\n <details>\\n <summary>Examples</summary>\\n\\n **Blockquotes**\\n\\n > I love OpenAPI. <3\\n\\n **Tables**\\n\\n | Feature | Availability |\\n | ---------------- | ------------ |\\n | Markdown Support | \u2713 |\\n\\n **Accordion**\\n\\n \\`\\`\\`html\\n <details>\\n <summary>Using Details Tags</summary>\\n <p>HTML Example</p>\\n </details>\\n \\`\\`\\`\\n\\n **Images**\\n\\n Yes, there\u2019s support for images, too!\\n\\n \\n\\n </details>\\n version: 1.0.0\\n contact:\\n name: Marc from Scalar\\n url: https://scalar.com\\n email: marc@scalar.com\\nservers:\\n - url: https://galaxy.scalar.com\\n - url: '{protocol}://void.scalar.com/{path}'\\n description: Responds with your request data\\n variables:\\n protocol:\\n enum:\\n - https\\n default: https\\n path:\\n default: ''\\nsecurity:\\n - bearerAuth: []\\n - basicAuth: []\\n - apiKeyQuery: []\\n - apiKeyHeader: []\\n - apiKeyCookie: []\\n - oAuth2: []\\ntags:\\n - name: Authentication\\n description:\\n Some endpoints are public, but some require authentication. We provide\\n all the required endpoints to create an account and authorize yourself.\\n - name: Planets\\n description: Everything about planets\\npaths:\\n '/planets':\\n get:\\n tags:\\n - Planets\\n summary: Get all planets\\n description: It\u2019s easy to say you know them all, but do you really? Retrieve all the planets and check whether you missed one.\\n operationId: getAllData\\n security:\\n - {}\\n parameters:\\n - '$ref': '#/components/parameters/limit'\\n - '$ref': '#/components/parameters/offset'\\n responses:\\n '200':\\n description: OK\\n content:\\n application/json:\\n schema:\\n allOf:\\n - type: object\\n properties:\\n data:\\n type: array\\n items:\\n '$ref': '#/components/schemas/Planet'\\n - '$ref': '#/components/schemas/PaginatedResource'\\n post:\\n tags:\\n - Planets\\n summary: Create a planet\\n description: Time to play god and create a new planet. What do you think? Ah, don\u2019t think too much. What could go wrong anyway?\\n operationId: createPlanet\\n requestBody:\\n description: Planet\\n content:\\n application/json:\\n schema:\\n '$ref': '#/components/schemas/Planet'\\n responses:\\n '201':\\n description: Created\\n content:\\n application/json:\\n schema:\\n '$ref': '#/components/schemas/Planet'\\n '400':\\n description: Bad Request\\n content:\\n application/json:\\n schema:\\n '$ref': '#/components/responses/BadRequest'\\n '403':\\n description: Forbidden\\n content:\\n application/json:\\n schema:\\n '$ref': '#/components/responses/Forbidden'\\n '/planets/{planetId}':\\n get:\\n tags:\\n - Planets\\n summary: Get a planet\\n description: You\u2019ll better learn a little bit more about the planets. It might come in handy once space travel is available for everyone.\\n operationId: getPlanet\\n security:\\n - {}\\n parameters:\\n - '$ref': '#/components/parameters/planetId'\\n responses:\\n '200':\\n description: Planet Found\\n content:\\n application/json:\\n schema:\\n '$ref': '#/components/schemas/Planet'\\n '404':\\n description: Planet Not Found\\n content:\\n application/json:\\n schema:\\n '$ref': '#/components/responses/NotFound'\\n put:\\n tags:\\n - Planets\\n summary: Update a planet\\n description: Sometimes you make mistakes, that\u2019s fine. No worries, you can update all planets.\\n operationId: updatePlanet\\n requestBody:\\n description: New information about the planet\\n content:\\n application/json:\\n schema:\\n '$ref': '#/components/schemas/Planet'\\n parameters:\\n - '$ref': '#/components/parameters/planetId'\\n responses:\\n '200':\\n description: OK\\n content:\\n application/json:\\n schema:\\n '$ref': '#/components/schemas/Planet'\\n '400':\\n description: Bad Request\\n content:\\n application/json:\\n schema:\\n '$ref': '#/components/responses/BadRequest'\\n '403':\\n description: Forbidden\\n content:\\n application/json:\\n schema:\\n '$ref': '#/components/responses/Forbidden'\\n '404':\\n description: Not Found\\n content:\\n application/json:\\n schema:\\n '$ref': '#/components/responses/NotFound'\\n delete:\\n tags:\\n - Planets\\n summary: Delete a planet\\n operationId: deletePlanet\\n description:\\n This endpoint was used to delete planets. Unfortunately, that caused\\n a lot of trouble for planets with life. So, this endpoint is now deprecated\\n and should not be used anymore.\\n deprecated: true\\n parameters:\\n - '$ref': '#/components/parameters/planetId'\\n responses:\\n '204':\\n description: No Content\\n '404':\\n description: Not Found\\n '/planets/{planetId}/image':\\n post:\\n tags:\\n - Planets\\n summary: Upload an image to a planet\\n description: Got a crazy good photo of a planet? Share it with the world!\\n operationId: uploadImage\\n parameters:\\n - '$ref': '#/components/parameters/planetId'\\n requestBody:\\n content:\\n multipart/form-data:\\n schema:\\n type: object\\n properties:\\n image:\\n type: string\\n format: binary\\n responses:\\n '200':\\n description: Image uploaded\\n content:\\n application/json:\\n schema:\\n type: object\\n properties:\\n message:\\n type: string\\n examples:\\n - Image uploaded successfully\\n '400':\\n description: Bad Upload Request\\n content:\\n application/json:\\n schema:\\n '$ref': '#/components/responses/BadRequest'\\n '403':\\n description: Upload Forbidden\\n content:\\n application/json:\\n schema:\\n '$ref': '#/components/responses/Forbidden'\\n '404':\\n description: Failed to Upload Image, Planet Not Found\\n content:\\n application/json:\\n schema:\\n '$ref': '#/components/responses/NotFound'\\n '/user/signup':\\n post:\\n tags:\\n - Authentication\\n summary: Create a user\\n description: Time to create a user account, eh?\\n operationId: createUser\\n security:\\n - {}\\n requestBody:\\n content:\\n application/json:\\n schema:\\n '$ref': '#/components/schemas/NewUser'\\n examples:\\n Marc:\\n value:\\n name: Marc\\n email: marc@scalar.com\\n password: i-love-scalar\\n Cam:\\n value:\\n name: Cam\\n email: cam@scalar.com\\n password: scalar-is-cool\\n responses:\\n '201':\\n description: Created\\n content:\\n application/json:\\n schema:\\n '$ref': '#/components/schemas/User'\\n '400':\\n description: Bad Request\\n content:\\n application/json:\\n schema:\\n '$ref': '#/components/responses/BadRequest'\\n '/auth/token':\\n post:\\n tags:\\n - Authentication\\n summary: Get a token\\n description: Yeah, this is the boring security stuff. Just get your super secret token and move on.\\n operationId: getToken\\n security:\\n - {}\\n requestBody:\\n content:\\n application/json:\\n schema:\\n '$ref': '#/components/schemas/Credentials'\\n responses:\\n '201':\\n description: Token Created\\n content:\\n application/json:\\n schema:\\n '$ref': '#/components/schemas/Token'\\n '/me':\\n get:\\n tags:\\n - Authentication\\n summary: Get authenticated user\\n description: Find yourself they say. That\u2019s what you can do here.\\n operationId: getMe\\n security:\\n - basicAuth: []\\n - oAuth2:\\n - read:account\\n - bearerAuth: []\\n - apiKeyHeader: []\\n - apiKeyQuery: []\\n responses:\\n '200':\\n description: OK\\n content:\\n application/json:\\n schema:\\n '$ref': '#/components/schemas/User'\\n '401':\\n description: Unauthorized\\n content:\\n application/json:\\n schema:\\n '$ref': '#/components/responses/Unauthorized'\\n '403':\\n description: Forbidden\\n content:\\n application/json:\\n schema:\\n '$ref': '#/components/responses/Forbidden'\\nwebhooks:\\n newPlanet:\\n post:\\n tags:\\n - Planets\\n requestBody:\\n description: Information about a new planet\\n content:\\n application/json:\\n schema:\\n '$ref': '#/components/schemas/Planet'\\n responses:\\n '200':\\n description:\\n Return a 200 status to indicate that the data was received\\n successfully\\ncomponents:\\n securitySchemes:\\n bearerAuth:\\n type: http\\n scheme: bearer\\n basicAuth:\\n type: http\\n scheme: basic\\n apiKeyHeader:\\n type: apiKey\\n in: header\\n name: X-API-Key\\n apiKeyQuery:\\n type: apiKey\\n in: query\\n name: api_key\\n apiKeyCookie:\\n type: apiKey\\n in: cookie\\n name: api_key\\n oAuth2:\\n type: oauth2\\n flows:\\n authorizationCode:\\n authorizationUrl: https://galaxy.scalar.com/oauth/authorize\\n tokenUrl: https://galaxy.scalar.com/oauth/token\\n scopes:\\n read:account: read your account information\\n write:planets: modify planets in your account\\n read:planets: read your planets\\n clientCredentials:\\n tokenUrl: https://galaxy.scalar.com/oauth/token\\n scopes:\\n read:account: read your account information\\n write:planets: modify planets in your account\\n read:planets: read your planets\\n # Legacy\\n implicit:\\n authorizationUrl: https://galaxy.scalar.com/oauth/authorize\\n scopes:\\n read:account: read your account information\\n write:planets: modify planets in your account\\n read:planets: read your planets\\n # Legacy\\n password:\\n tokenUrl: https://galaxy.scalar.com/oauth/token\\n scopes:\\n read:account: read your account information\\n write:planets: modify planets in your account\\n read:planets: read your planets\\n parameters:\\n planetId:\\n name: planetId\\n in: path\\n required: true\\n schema:\\n type: integer\\n format: int64\\n examples:\\n - 1\\n limit:\\n name: limit\\n in: query\\n description: The number of items to return\\n required: false\\n schema:\\n type: integer\\n format: int64\\n default: 10\\n offset:\\n name: offset\\n in: query\\n description:\\n The number of items to skip before starting to collect the result\\n set\\n required: false\\n schema:\\n type: integer\\n format: int64\\n default: 0\\n responses:\\n BadRequest:\\n description: Bad Request\\n content:\\n application/json:\\n schema:\\n '$ref': '#/components/schemas/Error'\\n Forbidden:\\n description: Forbidden\\n content:\\n application/json:\\n schema:\\n '$ref': '#/components/schemas/Error'\\n NotFound:\\n description: NotFound\\n content:\\n application/json:\\n schema:\\n '$ref': '#/components/schemas/Error'\\n Unauthorized:\\n description: Unauthorized\\n content:\\n application/json:\\n schema:\\n '$ref': '#/components/schemas/Error'\\n schemas:\\n NewUser:\\n type: object\\n required:\\n - name\\n - email\\n - password\\n properties:\\n name:\\n type: string\\n examples:\\n - Hans\\n - Brynn\\n email:\\n type: string\\n format: email\\n examples:\\n - hans@scalar.com\\n - brynn@scalar.com\\n password:\\n type: string\\n minLength: 8\\n examples:\\n - i-love-scalar\\n - scalar-is-cool\\n User:\\n type: object\\n required:\\n - id\\n - name\\n - email\\n properties:\\n id:\\n type: integer\\n format: int64\\n examples:\\n - 1\\n name:\\n type: string\\n examples:\\n - Marc\\n email:\\n type: string\\n format: email\\n examples:\\n - marc@scalar.com\\n Credentials:\\n type: object\\n required:\\n - email\\n - password\\n properties:\\n email:\\n type: string\\n format: email\\n examples:\\n - marc@scalar.com\\n password:\\n type: string\\n examples:\\n - i-love-scalar\\n Token:\\n type: object\\n properties:\\n token:\\n type: string\\n examples:\\n - eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c\\n Planet:\\n type: object\\n required:\\n - id\\n - name\\n properties:\\n id:\\n type: integer\\n format: int64\\n examples:\\n - 1\\n x-variable: planetId\\n name:\\n type: string\\n examples:\\n - Mars\\n description:\\n type:\\n - string\\n - 'null'\\n examples:\\n - The red planet\\n image:\\n type: string\\n nullable: true\\n examples:\\n - https://cdn.scalar.com/photos/mars.jpg\\n creator:\\n '$ref': '#/components/schemas/User'\\n PaginatedResource:\\n type: object\\n properties:\\n meta:\\n type: object\\n properties:\\n limit:\\n type: integer\\n format: int64\\n examples:\\n - 10\\n offset:\\n type: integer\\n format: int64\\n examples:\\n - 0\\n total:\\n type: integer\\n format: int64\\n examples:\\n - 100\\n next:\\n type:\\n - string\\n - 'null'\\n examples:\\n - '/planets?limit=10&offset=10'\\n Error:\\n type: object\\n description: RFC 7807 (https://datatracker.ietf.org/doc/html/rfc7807)\\n properties:\\n type:\\n type: string\\n examples:\\n - https://example.com/errors/generic-error\\n title:\\n type: string\\n examples:\\n - Something went wrong here.\\n status:\\n type: integer\\n format: int64\\n examples:\\n - 403\\n detail:\\n type: string\\n examples:\\n - Unfortunately, we can\u2019t provide further information.\\n&quot;},&quot;pageTitle&quot;:&quot;Scalar Galaxy&quot;}\"></script>\n <script src=\"https://cdn.jsdelivr.net/npm/@scalar/api-reference\"></script>\n </body>\n </html>`\n\n // @ts-expect-error Mocking types are missing\n fetch.mockResolvedValue(createFetchResponse(html))\n\n const result = await resolve('https://example.com/reference')\n\n expect(result).toMatchObject({\n openapi: '3.1.0',\n info: {\n title: 'Scalar Galaxy',\n },\n })\n })\n\n it('transforms GitHub URLs to raw file URLs', async () => {\n const result = await resolve('https://github.com/outline/openapi/blob/main/spec3.yml')\n\n expect(result).toBe('https://raw.githubusercontent.com/outline/openapi/refs/heads/main/spec3.yml')\n })\n\n it('finds embedded OpenAPI document in script tag (JSON)', async () => {\n const html = `<!DOCTYPE html>\n<html>\n <head />\n <body>\n <script\n id=\"api-reference\"\n type=\"application/json\">\n {\"openapi\":\"3.1.0\",\"info\":{\"title\":\"Hello World\",\"version\":\"1.0\"}}\n </script>\n </body>\n</html>\n `\n\n // @ts-expect-error Mocking types are missing\n fetch.mockResolvedValue(createFetchResponse(html))\n\n const result = await resolve('https://example.com/reference')\n\n expect(result).toStrictEqual({\n openapi: '3.1.0',\n info: {\n title: 'Hello World',\n version: '1.0',\n },\n })\n })\n\n it('finds embedded OpenAPI document in script tag, even if it contains HTML tags (JSON)', async () => {\n const html = `<!DOCTYPE html>\n<html>\n <head />\n <body>\n <script\n id=\"api-reference\"\n type=\"application/json\">{\"openapi\":\"3.0.0\",\"paths\":{\"/v1/projects/{ref}/sessions/tags\":{\"type\":\"string\",\"pattern\":\"/^\\\\s*([a-z0-9_-]+(\\\\s*,+\\\\s*)?)*\\\\s*$/i\"}}}</script>\n </body>\n</html>\n `\n\n // @ts-expect-error Mocking types are missing\n fetch.mockResolvedValue(createFetchResponse(html))\n\n const result = await resolve('https://example.com/reference')\n\n expect(result).toStrictEqual({\n openapi: '3.0.0',\n paths: {\n '/v1/projects/{ref}/sessions/tags': {\n pattern: '/^\\\\s*([a-z0-9_-]+(\\\\s*,+\\\\s*)?)*\\\\s*$/i',\n type: 'string',\n },\n },\n })\n })\n\n it('finds embedded OpenAPI document in script tag (YAML)', async () => {\n const html = `<!DOCTYPE html>\n<html>\n <head />\n <body>\n <script\n id=\"api-reference\"\n type=\"application/yaml\">\nopenapi: 3.1.0\ninfo:\n title: Hello World\n version: '1.0'\n </script>\n </body>\n</html>\n `\n\n // @ts-expect-error Mocking types are missing\n fetch.mockResolvedValue(createFetchResponse(html))\n\n const result = await resolve('https://example.com/reference')\n\n expect(result).toStrictEqual({\n openapi: '3.1.0',\n info: {\n title: 'Hello World',\n version: '1.0',\n },\n })\n })\n\n it('finds OpenAPI URL in HTML link text', async () => {\n const html = `<!DOCTYPE html>\n<html>\n <body>\n <p>Fetching spec from <a href=\"https://example.com/v1/openapi.yml\" rel=\"nofollow\" target=\"_blank\">https://example.com/v1/openapi.yml</a></p>\n </body>\n</html>\n `\n\n // @ts-expect-error Mocking types are missing\n fetch.mockResolvedValue(createFetchResponse(html))\n\n const result = await resolve('https://example.com/reference')\n\n expect(result).toBe('https://example.com/v1/openapi.yml')\n })\n\n it('finds URL in script configuration', async () => {\n const html = `<!DOCTYPE html>\n<html>\n <head />\n <body>\n <script>\n var configuration = {\n isEditable: false,\n layout: \"classic\",\n darkMode: false,\n searchHotKey: \"nope\",\n url: \"/docs/files/openapi.json\",\n }\n var apiReference = document.getElementById('api-reference')\n apiReference.dataset.configuration = JSON.stringify(configuration)\n </script>\n <script src=\"https://cdn.jsdelivr.net/npm/@scalar/api-reference@1.20\"></script>\n </body>\n</html>\n `\n\n // @ts-expect-error Mocking types are missing\n fetch.mockResolvedValue(createFetchResponse(html))\n\n const result = await resolve('https://example.com/reference')\n\n expect(result).toBe('https://example.com/docs/files/openapi.json')\n })\n\n it('returns URL if it directly returns an OpenAPI document', async () => {\n const openApiDoc = {\n openapi: '3.0.0',\n info: {\n title: 'Test API',\n version: '1.0.0',\n },\n paths: {},\n }\n\n // @ts-expect-error Mocking types are missing\n fetch.mockResolvedValue(createFetchResponse(JSON.stringify(openApiDoc)))\n\n const result = await resolve('https://example.com/swagger/json')\n\n expect(result).toBe('https://example.com/swagger/json')\n })\n\n it('finds the URL in an escaped JS object', async () => {\n // @ts-expect-error Mocking types are missing\n fetch.mockResolvedValue(\n createFetchResponse(\n `<html>\\\\\"$L8e\\\\\",null,{\\\\\"configuration\\\\\":{\\\\\"spec\\\\\":{\\\\\"url\\\\\":\\\\\"https://raw.githubusercontent.com/Foo/Bar/main/api/foobar.json\\\\\"}},\\\\\"initialRequest`,\n ),\n )\n\n const result = await resolve('https://example.com/foo')\n\n expect(result).toBe('https://raw.githubusercontent.com/Foo/Bar/main/api/foobar.json')\n })\n})\n"],
|
|
5
|
-
"mappings": "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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA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",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|