radiant-docs 0.1.64 → 0.1.66
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/index.js +53 -10
- package/package.json +4 -3
- package/template/package-lock.json +1991 -4096
- package/template/package.json +7 -19
- package/template/src/components/OpenApiPage.astro +107 -18
- package/template/src/components/Sidebar.astro +1 -0
- package/template/src/components/endpoint/PlaygroundBar.astro +1 -1
- package/template/src/components/endpoint/PlaygroundField.astro +433 -71
- package/template/src/components/endpoint/PlaygroundForm.astro +470 -87
- package/template/src/components/endpoint/RequestSnippets.astro +6 -1
- package/template/src/components/endpoint/ResponseDisplay.astro +109 -2
- package/template/src/components/endpoint/ResponseFieldTree.astro +1 -1
- package/template/src/components/endpoint/ResponseFields.astro +97 -28
- package/template/src/components/endpoint/ResponseSnippets.astro +19 -7
- package/template/src/layouts/Layout.astro +94 -0
- package/template/src/lib/openapi/operation-doc.ts +308 -70
- package/template/src/lib/openapi/response-content.ts +133 -0
- package/template/src/lib/openapi/schema-variant-labels.ts +213 -0
- package/template/.vscode/extensions.json +0 -4
- package/template/.vscode/launch.json +0 -11
- package/template/scripts/generate-og-images.mjs +0 -667
- package/template/scripts/generate-og-metadata.mjs +0 -206
- package/template/scripts/generate-proxy-allowed-origins.mjs +0 -48
- package/template/scripts/generate-robots-txt.mjs +0 -47
- package/template/scripts/publish-shiki-platform-assets.mjs +0 -1177
- package/template/scripts/remove-assistant-for-non-pro.mjs +0 -28
- package/template/scripts/stamp-image-versions.mjs +0 -355
- package/template/scripts/stamp-og-image-versions.mjs +0 -199
- package/template/scripts/stamp-pagefind-runtime-version.mjs +0 -140
|
@@ -1,206 +0,0 @@
|
|
|
1
|
-
import fs from "node:fs";
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
import {
|
|
4
|
-
DEFAULT_TEXT_FONT_PRESET,
|
|
5
|
-
FONT_PRESET_OPTIONS,
|
|
6
|
-
} from "radiant-docs-validator";
|
|
7
|
-
|
|
8
|
-
const CWD = process.cwd();
|
|
9
|
-
const DIST_DIR = path.join(CWD, "dist");
|
|
10
|
-
const DOCS_CONFIG_PATH = path.join(CWD, "src/content/docs/docs.json");
|
|
11
|
-
const OUTPUT_DIR = path.join(DIST_DIR, "_og");
|
|
12
|
-
const OUTPUT_PATH = path.join(OUTPUT_DIR, "meta.json");
|
|
13
|
-
const FONT_PRESET_ID_SET = new Set(FONT_PRESET_OPTIONS);
|
|
14
|
-
|
|
15
|
-
function readDocsConfig() {
|
|
16
|
-
if (!fs.existsSync(DOCS_CONFIG_PATH)) {
|
|
17
|
-
return {};
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
try {
|
|
21
|
-
const raw = fs.readFileSync(DOCS_CONFIG_PATH, "utf8");
|
|
22
|
-
return JSON.parse(raw);
|
|
23
|
-
} catch {
|
|
24
|
-
return {};
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
function findHtmlFiles(dir, files = []) {
|
|
29
|
-
if (!fs.existsSync(dir)) return files;
|
|
30
|
-
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
31
|
-
|
|
32
|
-
for (const entry of entries) {
|
|
33
|
-
const fullPath = path.join(dir, entry.name);
|
|
34
|
-
if (entry.isDirectory()) {
|
|
35
|
-
findHtmlFiles(fullPath, files);
|
|
36
|
-
continue;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
if (entry.isFile() && entry.name.endsWith(".html")) {
|
|
40
|
-
files.push(fullPath);
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
return files;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
function normalizeRoutePath(routePath) {
|
|
48
|
-
if (!routePath || routePath === "/") return "/";
|
|
49
|
-
if (!routePath.startsWith("/")) routePath = `/${routePath}`;
|
|
50
|
-
return routePath.endsWith("/") ? routePath : `${routePath}/`;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
function routePathFromHtmlPath(filePath) {
|
|
54
|
-
const relative = path.relative(DIST_DIR, filePath).replace(/\\/g, "/");
|
|
55
|
-
|
|
56
|
-
if (relative === "index.html") return "/";
|
|
57
|
-
if (relative.endsWith("/index.html")) {
|
|
58
|
-
const base = relative.slice(0, -"/index.html".length);
|
|
59
|
-
return normalizeRoutePath(base);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
if (relative.endsWith(".html")) {
|
|
63
|
-
return normalizeRoutePath(relative.slice(0, -".html".length));
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
return "/";
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
function matchMetaContent(html, attrName, attrValue) {
|
|
70
|
-
const regex = new RegExp(
|
|
71
|
-
`<meta\\s+[^>]*${attrName}\\s*=\\s*["']${attrValue}["'][^>]*content\\s*=\\s*["']([^"']*)["'][^>]*>`,
|
|
72
|
-
"i",
|
|
73
|
-
);
|
|
74
|
-
const reverseRegex = new RegExp(
|
|
75
|
-
`<meta\\s+[^>]*content\\s*=\\s*["']([^"']*)["'][^>]*${attrName}\\s*=\\s*["']${attrValue}["'][^>]*>`,
|
|
76
|
-
"i",
|
|
77
|
-
);
|
|
78
|
-
return html.match(regex)?.[1] ?? html.match(reverseRegex)?.[1] ?? "";
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
function decodeHtmlEntities(value) {
|
|
82
|
-
if (!value || typeof value !== "string") return "";
|
|
83
|
-
|
|
84
|
-
const named = {
|
|
85
|
-
amp: "&",
|
|
86
|
-
lt: "<",
|
|
87
|
-
gt: ">",
|
|
88
|
-
quot: '"',
|
|
89
|
-
apos: "'",
|
|
90
|
-
nbsp: " ",
|
|
91
|
-
};
|
|
92
|
-
|
|
93
|
-
return value
|
|
94
|
-
.replace(/&#(\d+);/g, (_, dec) => {
|
|
95
|
-
const code = Number.parseInt(dec, 10);
|
|
96
|
-
return Number.isFinite(code) ? String.fromCodePoint(code) : _;
|
|
97
|
-
})
|
|
98
|
-
.replace(/&#x([0-9a-fA-F]+);/g, (_, hex) => {
|
|
99
|
-
const code = Number.parseInt(hex, 16);
|
|
100
|
-
return Number.isFinite(code) ? String.fromCodePoint(code) : _;
|
|
101
|
-
})
|
|
102
|
-
.replace(/&([a-zA-Z]+);/g, (entity, name) => {
|
|
103
|
-
const decoded = named[name.toLowerCase()];
|
|
104
|
-
return decoded ?? entity;
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
function getLogoImagePath(variant) {
|
|
109
|
-
if (typeof variant === "string") return variant.trim();
|
|
110
|
-
if (!variant || typeof variant !== "object") return "";
|
|
111
|
-
return typeof variant.image === "string" ? variant.image.trim() : "";
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
function normalizeFontPresetId(value) {
|
|
115
|
-
if (typeof value !== "string") return undefined;
|
|
116
|
-
const normalized = value.trim().toLowerCase();
|
|
117
|
-
return FONT_PRESET_ID_SET.has(normalized) ? normalized : undefined;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
function resolveOgFonts(docsConfig) {
|
|
121
|
-
const theme =
|
|
122
|
-
docsConfig?.theme && typeof docsConfig.theme === "object"
|
|
123
|
-
? docsConfig.theme
|
|
124
|
-
: {};
|
|
125
|
-
const fonts =
|
|
126
|
-
theme.fonts && typeof theme.fonts === "object" && !Array.isArray(theme.fonts)
|
|
127
|
-
? theme.fonts
|
|
128
|
-
: {};
|
|
129
|
-
const text = normalizeFontPresetId(fonts.text) ?? DEFAULT_TEXT_FONT_PRESET;
|
|
130
|
-
|
|
131
|
-
return {
|
|
132
|
-
text,
|
|
133
|
-
heading: normalizeFontPresetId(fonts.heading) ?? text,
|
|
134
|
-
};
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
function extractTitle(html) {
|
|
138
|
-
const ogTitle = decodeHtmlEntities(
|
|
139
|
-
matchMetaContent(html, "property", "og:title"),
|
|
140
|
-
).trim();
|
|
141
|
-
if (ogTitle) return ogTitle;
|
|
142
|
-
return decodeHtmlEntities(
|
|
143
|
-
html.match(/<title>([^<]*)<\/title>/i)?.[1] ?? "",
|
|
144
|
-
).trim();
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
function extractDescription(html) {
|
|
148
|
-
const description = decodeHtmlEntities(
|
|
149
|
-
matchMetaContent(html, "name", "description"),
|
|
150
|
-
).trim();
|
|
151
|
-
if (description) return description;
|
|
152
|
-
return decodeHtmlEntities(
|
|
153
|
-
matchMetaContent(html, "property", "og:description"),
|
|
154
|
-
).trim();
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
function main() {
|
|
158
|
-
if (!fs.existsSync(DIST_DIR)) {
|
|
159
|
-
console.warn("Skipping OG metadata generation: dist directory not found.");
|
|
160
|
-
return;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
const docsConfig = readDocsConfig();
|
|
164
|
-
const logo = typeof docsConfig.logo === "object" && docsConfig.logo
|
|
165
|
-
? docsConfig.logo
|
|
166
|
-
: {};
|
|
167
|
-
|
|
168
|
-
const htmlFiles = findHtmlFiles(DIST_DIR);
|
|
169
|
-
htmlFiles.sort();
|
|
170
|
-
const pages = {};
|
|
171
|
-
|
|
172
|
-
for (const filePath of htmlFiles) {
|
|
173
|
-
const routePath = routePathFromHtmlPath(filePath);
|
|
174
|
-
const html = fs.readFileSync(filePath, "utf8");
|
|
175
|
-
|
|
176
|
-
pages[routePath] = {
|
|
177
|
-
title: extractTitle(html),
|
|
178
|
-
description: extractDescription(html),
|
|
179
|
-
};
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
const metadata = {
|
|
183
|
-
defaults: {
|
|
184
|
-
siteName:
|
|
185
|
-
typeof docsConfig.title === "string" ? docsConfig.title.trim() : "",
|
|
186
|
-
logoLight: getLogoImagePath(logo.light),
|
|
187
|
-
logoDark: getLogoImagePath(logo.dark),
|
|
188
|
-
background:
|
|
189
|
-
typeof docsConfig.ogBackground === "string"
|
|
190
|
-
? docsConfig.ogBackground.trim()
|
|
191
|
-
: "",
|
|
192
|
-
primaryColor:
|
|
193
|
-
typeof docsConfig.primaryColor === "string"
|
|
194
|
-
? docsConfig.primaryColor.trim()
|
|
195
|
-
: "",
|
|
196
|
-
fonts: resolveOgFonts(docsConfig),
|
|
197
|
-
},
|
|
198
|
-
pages,
|
|
199
|
-
};
|
|
200
|
-
|
|
201
|
-
fs.mkdirSync(OUTPUT_DIR, { recursive: true });
|
|
202
|
-
fs.writeFileSync(OUTPUT_PATH, JSON.stringify(metadata, null, 2), "utf8");
|
|
203
|
-
console.log(`✅ Generated OG metadata at ${OUTPUT_PATH}`);
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
main();
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import fs from "node:fs/promises";
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
import { buildAllowedOrigins } from "../src/lib/proxy-allowed-origins.mjs";
|
|
4
|
-
|
|
5
|
-
const CWD = process.cwd();
|
|
6
|
-
const OUTPUT_DIR = path.join(CWD, ".radiant");
|
|
7
|
-
const OUTPUT_FILE = path.join(OUTPUT_DIR, "proxy-allowed-origins.json");
|
|
8
|
-
|
|
9
|
-
async function run() {
|
|
10
|
-
let allowedOrigins = [];
|
|
11
|
-
|
|
12
|
-
try {
|
|
13
|
-
allowedOrigins = await buildAllowedOrigins({
|
|
14
|
-
cwd: CWD,
|
|
15
|
-
onSourceError(source, error) {
|
|
16
|
-
console.warn(
|
|
17
|
-
`⚠️ Failed to extract OpenAPI server origins from "${source}":`,
|
|
18
|
-
error instanceof Error ? error.message : String(error),
|
|
19
|
-
);
|
|
20
|
-
},
|
|
21
|
-
});
|
|
22
|
-
} catch (error) {
|
|
23
|
-
console.warn(
|
|
24
|
-
"⚠️ Failed to generate proxy allowed origins. Falling back to empty allowlist.",
|
|
25
|
-
error instanceof Error ? error.message : String(error),
|
|
26
|
-
);
|
|
27
|
-
allowedOrigins = [];
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
await fs.mkdir(OUTPUT_DIR, { recursive: true });
|
|
31
|
-
await fs.writeFile(
|
|
32
|
-
OUTPUT_FILE,
|
|
33
|
-
`${JSON.stringify(allowedOrigins, null, 2)}\n`,
|
|
34
|
-
"utf8",
|
|
35
|
-
);
|
|
36
|
-
|
|
37
|
-
console.log(
|
|
38
|
-
`✅ Wrote ${allowedOrigins.length} proxy allowed origins to ${path.relative(CWD, OUTPUT_FILE)}`,
|
|
39
|
-
);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
run().catch((error) => {
|
|
43
|
-
console.error(
|
|
44
|
-
"❌ Failed to write proxy allowed origins manifest:",
|
|
45
|
-
error instanceof Error ? error.message : String(error),
|
|
46
|
-
);
|
|
47
|
-
process.exit(1);
|
|
48
|
-
});
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import fs from "node:fs";
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
|
|
4
|
-
const CWD = process.cwd();
|
|
5
|
-
const DIST_DIR = path.join(CWD, "dist");
|
|
6
|
-
const ROBOTS_TXT_PATH = path.join(DIST_DIR, "robots.txt");
|
|
7
|
-
const ASTRO_SITEMAP_INDEX_FILENAME = "sitemap-index.xml";
|
|
8
|
-
const PUBLIC_SITEMAP_FILENAME = "sitemap.xml";
|
|
9
|
-
|
|
10
|
-
function buildSitemapUrl() {
|
|
11
|
-
const configuredSiteUrl = process.env.DOCS_SITE_URL?.trim();
|
|
12
|
-
if (!configuredSiteUrl) {
|
|
13
|
-
return `/${PUBLIC_SITEMAP_FILENAME}`;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
try {
|
|
17
|
-
const baseUrl = configuredSiteUrl.endsWith("/")
|
|
18
|
-
? configuredSiteUrl
|
|
19
|
-
: `${configuredSiteUrl}/`;
|
|
20
|
-
return new URL(PUBLIC_SITEMAP_FILENAME, baseUrl).toString();
|
|
21
|
-
} catch {
|
|
22
|
-
return `/${PUBLIC_SITEMAP_FILENAME}`;
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
function main() {
|
|
27
|
-
if (!fs.existsSync(DIST_DIR)) {
|
|
28
|
-
console.log("Skipping robots.txt generation: dist directory not found.");
|
|
29
|
-
return;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
const astroSitemapIndexPath = path.join(
|
|
33
|
-
DIST_DIR,
|
|
34
|
-
ASTRO_SITEMAP_INDEX_FILENAME,
|
|
35
|
-
);
|
|
36
|
-
const publicSitemapPath = path.join(DIST_DIR, PUBLIC_SITEMAP_FILENAME);
|
|
37
|
-
if (fs.existsSync(astroSitemapIndexPath)) {
|
|
38
|
-
fs.copyFileSync(astroSitemapIndexPath, publicSitemapPath);
|
|
39
|
-
console.log("✅ sitemap.xml alias generated.");
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const robotsTxt = `User-agent: *\nAllow: /\nSitemap: ${buildSitemapUrl()}\n`;
|
|
43
|
-
fs.writeFileSync(ROBOTS_TXT_PATH, robotsTxt, "utf8");
|
|
44
|
-
console.log("✅ robots.txt generated.");
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
main();
|