sourcey 3.4.10 → 3.5.0
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/README.md +13 -12
- package/dist/cli.js +46 -4
- package/dist/components/changelog/ChangelogPage.d.ts +5 -0
- package/dist/components/changelog/ChangelogPage.d.ts.map +1 -0
- package/dist/components/changelog/ChangelogPage.js +8 -0
- package/dist/components/changelog/EntryList.d.ts +5 -0
- package/dist/components/changelog/EntryList.d.ts.map +1 -0
- package/dist/components/changelog/EntryList.js +6 -0
- package/dist/components/changelog/TypeBadge.d.ts +6 -0
- package/dist/components/changelog/TypeBadge.d.ts.map +1 -0
- package/dist/components/changelog/TypeBadge.js +14 -0
- package/dist/components/changelog/VersionCard.d.ts +6 -0
- package/dist/components/changelog/VersionCard.d.ts.map +1 -0
- package/dist/components/changelog/VersionCard.js +25 -0
- package/dist/components/layout/Head.d.ts.map +1 -1
- package/dist/components/layout/Head.js +15 -3
- package/dist/components/layout/Page.d.ts.map +1 -1
- package/dist/components/layout/Page.js +12 -6
- package/dist/components/openapi/Introduction.d.ts.map +1 -1
- package/dist/components/openapi/Introduction.js +1 -1
- package/dist/components/openapi/MediaTypeDetails.d.ts +11 -0
- package/dist/components/openapi/MediaTypeDetails.d.ts.map +1 -0
- package/dist/components/openapi/MediaTypeDetails.js +54 -0
- package/dist/components/openapi/Parameters.d.ts.map +1 -1
- package/dist/components/openapi/Parameters.js +6 -1
- package/dist/components/openapi/RequestBody.d.ts.map +1 -1
- package/dist/components/openapi/RequestBody.js +5 -1
- package/dist/components/openapi/Responses.d.ts.map +1 -1
- package/dist/components/openapi/Responses.js +1 -1
- package/dist/components/openapi/Security.d.ts.map +1 -1
- package/dist/components/openapi/Security.js +3 -2
- package/dist/components/openapi/Tags.d.ts.map +1 -1
- package/dist/components/openapi/Tags.js +8 -1
- package/dist/config.d.ts +50 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +50 -4
- package/dist/core/changelog-normalizer.d.ts +8 -0
- package/dist/core/changelog-normalizer.d.ts.map +1 -0
- package/dist/core/changelog-normalizer.js +531 -0
- package/dist/core/doxygen-loader.d.ts.map +1 -1
- package/dist/core/doxygen-loader.js +2 -0
- package/dist/core/loader.js +2 -0
- package/dist/core/markdown-loader.d.ts +21 -0
- package/dist/core/markdown-loader.d.ts.map +1 -1
- package/dist/core/markdown-loader.js +53 -28
- package/dist/core/mcp-normalizer.d.ts.map +1 -1
- package/dist/core/navigation.d.ts +2 -2
- package/dist/core/navigation.d.ts.map +1 -1
- package/dist/core/navigation.js +5 -1
- package/dist/core/normalizer.d.ts.map +1 -1
- package/dist/core/normalizer.js +102 -4
- package/dist/core/parser.d.ts +2 -2
- package/dist/core/parser.d.ts.map +1 -1
- package/dist/core/parser.js +23 -16
- package/dist/core/search-indexer.d.ts +3 -2
- package/dist/core/search-indexer.d.ts.map +1 -1
- package/dist/core/search-indexer.js +50 -17
- package/dist/core/tag-utils.d.ts +5 -0
- package/dist/core/tag-utils.d.ts.map +1 -0
- package/dist/core/tag-utils.js +22 -0
- package/dist/core/types.d.ts +82 -4
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js +1 -1
- package/dist/dev-server.d.ts +2 -0
- package/dist/dev-server.d.ts.map +1 -1
- package/dist/dev-server.js +81 -210
- package/dist/index.d.ts +6 -10
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +115 -247
- package/dist/init.d.ts.map +1 -1
- package/dist/init.js +7 -3
- package/dist/og/fonts/Inter-Bold.ttf +0 -0
- package/dist/og/fonts/Inter-Regular.ttf +0 -0
- package/dist/og/generate-og-image.d.ts +10 -0
- package/dist/og/generate-og-image.d.ts.map +1 -0
- package/dist/og/generate-og-image.js +198 -0
- package/dist/renderer/changelog-feed.d.ts +18 -0
- package/dist/renderer/changelog-feed.d.ts.map +1 -0
- package/dist/renderer/changelog-feed.js +91 -0
- package/dist/renderer/context.d.ts +27 -7
- package/dist/renderer/context.d.ts.map +1 -1
- package/dist/renderer/html-builder.d.ts +10 -1
- package/dist/renderer/html-builder.d.ts.map +1 -1
- package/dist/renderer/html-builder.js +58 -5
- package/dist/renderer/llms.d.ts.map +1 -1
- package/dist/renderer/llms.js +133 -24
- package/dist/site-assembly.d.ts +25 -0
- package/dist/site-assembly.d.ts.map +1 -0
- package/dist/site-assembly.js +467 -0
- package/dist/site-url.d.ts +12 -0
- package/dist/site-url.d.ts.map +1 -0
- package/dist/site-url.js +67 -0
- package/dist/themes/default/sourcey.css +237 -1
- package/dist/utils/code-samples.d.ts.map +1 -1
- package/dist/utils/code-samples.js +53 -12
- package/dist/utils/markdown.d.ts +6 -0
- package/dist/utils/markdown.d.ts.map +1 -1
- package/dist/utils/markdown.js +11 -2
- package/dist/vite-plugin.d.ts +2 -0
- package/dist/vite-plugin.d.ts.map +1 -1
- package/dist/vite-plugin.js +6 -2
- package/package.json +6 -3
- package/dist/cli.js.map +0 -1
- package/dist/client/copy.js +0 -21
- package/dist/client/index.js.map +0 -1
- package/dist/components/App.js.map +0 -1
- package/dist/components/layout/Head.js.map +0 -1
- package/dist/components/layout/Header.js.map +0 -1
- package/dist/components/layout/Page.js.map +0 -1
- package/dist/components/layout/Sidebar.js.map +0 -1
- package/dist/components/layout/TableOfContents.js.map +0 -1
- package/dist/components/openapi/CodeSamples.js.map +0 -1
- package/dist/components/openapi/Definition.js.map +0 -1
- package/dist/components/openapi/EndpointBar.js.map +0 -1
- package/dist/components/openapi/Introduction.js.map +0 -1
- package/dist/components/openapi/Operation.js.map +0 -1
- package/dist/components/openapi/Parameters.js.map +0 -1
- package/dist/components/openapi/RequestBody.js.map +0 -1
- package/dist/components/openapi/Responses.js.map +0 -1
- package/dist/components/openapi/Security.js.map +0 -1
- package/dist/components/openapi/Tags.js.map +0 -1
- package/dist/components/schema/ExampleView.js.map +0 -1
- package/dist/components/schema/SchemaDatatype.js.map +0 -1
- package/dist/components/schema/SchemaView.js.map +0 -1
- package/dist/components/ui/Badge.js.map +0 -1
- package/dist/components/ui/CopyButton.js.map +0 -1
- package/dist/components/ui/Logo.js.map +0 -1
- package/dist/components/ui/Markdown.js.map +0 -1
- package/dist/components/ui/SectionLabel.js.map +0 -1
- package/dist/components/ui/SocialIcon.js.map +0 -1
- package/dist/config.js.map +0 -1
- package/dist/core/converter.js.map +0 -1
- package/dist/core/doxygen-loader.js.map +0 -1
- package/dist/core/loader.js.map +0 -1
- package/dist/core/markdown-loader.js.map +0 -1
- package/dist/core/navigation.js.map +0 -1
- package/dist/core/normalizer.js.map +0 -1
- package/dist/core/parser.js.map +0 -1
- package/dist/core/search-indexer.js.map +0 -1
- package/dist/core/types.js.map +0 -1
- package/dist/dev-server.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/init.js.map +0 -1
- package/dist/renderer/context.js.map +0 -1
- package/dist/renderer/html-builder.js.map +0 -1
- package/dist/renderer/static-renderer.js.map +0 -1
- package/dist/utils/code-samples.js.map +0 -1
- package/dist/utils/copy-svg.js.map +0 -1
- package/dist/utils/example-generator.js.map +0 -1
- package/dist/utils/highlighter.js.map +0 -1
- package/dist/utils/html-id.js.map +0 -1
- package/dist/utils/http.js.map +0 -1
- package/dist/utils/icons.js.map +0 -1
- package/dist/utils/lang-icons.js.map +0 -1
- package/dist/utils/markdown.js.map +0 -1
- package/dist/vite-plugin.js.map +0 -1
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import satori from "satori";
|
|
2
|
+
import { Resvg } from "@resvg/resvg-js";
|
|
3
|
+
import { readFile } from "node:fs/promises";
|
|
4
|
+
import { resolve, dirname } from "node:path";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
7
|
+
// ---------------------------------------------------------------------------
|
|
8
|
+
// Font loading (cached across all pages)
|
|
9
|
+
// ---------------------------------------------------------------------------
|
|
10
|
+
let fontsCache = null;
|
|
11
|
+
async function loadFonts() {
|
|
12
|
+
if (fontsCache)
|
|
13
|
+
return fontsCache;
|
|
14
|
+
// Works from both src/ (dev) and dist/ (published)
|
|
15
|
+
const fontsDir = resolve(__dirname, "fonts");
|
|
16
|
+
const [regular, bold] = await Promise.all([
|
|
17
|
+
readFile(resolve(fontsDir, "Inter-Regular.ttf")),
|
|
18
|
+
readFile(resolve(fontsDir, "Inter-Bold.ttf")),
|
|
19
|
+
]);
|
|
20
|
+
fontsCache = {
|
|
21
|
+
regular: regular.buffer.slice(regular.byteOffset, regular.byteOffset + regular.byteLength),
|
|
22
|
+
bold: bold.buffer.slice(bold.byteOffset, bold.byteOffset + bold.byteLength),
|
|
23
|
+
};
|
|
24
|
+
return fontsCache;
|
|
25
|
+
}
|
|
26
|
+
// ---------------------------------------------------------------------------
|
|
27
|
+
// OG card template
|
|
28
|
+
// ---------------------------------------------------------------------------
|
|
29
|
+
function rgbCss(triplet) {
|
|
30
|
+
return `rgb(${triplet.replace(/ /g, ", ")})`;
|
|
31
|
+
}
|
|
32
|
+
function rgbaCss(triplet, alpha) {
|
|
33
|
+
return `rgba(${triplet.replace(/ /g, ", ")}, ${alpha})`;
|
|
34
|
+
}
|
|
35
|
+
function ogCard({ title, description, siteName, theme, logo }) {
|
|
36
|
+
const primary = rgbCss(theme.colors.primary);
|
|
37
|
+
const primaryGlow = rgbaCss(theme.colors.primary, 0.18);
|
|
38
|
+
const displayTitle = title.length > 90 ? title.slice(0, 87) + "..." : title;
|
|
39
|
+
const displayDesc = description
|
|
40
|
+
? description.length > 160 ? description.slice(0, 157) + "..." : description
|
|
41
|
+
: undefined;
|
|
42
|
+
return {
|
|
43
|
+
type: "div",
|
|
44
|
+
props: {
|
|
45
|
+
style: {
|
|
46
|
+
display: "flex",
|
|
47
|
+
flexDirection: "column",
|
|
48
|
+
width: "100%",
|
|
49
|
+
height: "100%",
|
|
50
|
+
backgroundColor: "#0f172a",
|
|
51
|
+
padding: "72px",
|
|
52
|
+
fontFamily: "Inter",
|
|
53
|
+
backgroundImage: `radial-gradient(ellipse 70% 50% at 20% 70%, ${primaryGlow}, transparent 70%)`,
|
|
54
|
+
},
|
|
55
|
+
children: [
|
|
56
|
+
// Brand block: logo (or coloured mark) + site name, top-left
|
|
57
|
+
{
|
|
58
|
+
type: "div",
|
|
59
|
+
props: {
|
|
60
|
+
style: { display: "flex", alignItems: "center", gap: "14px" },
|
|
61
|
+
children: [
|
|
62
|
+
logo
|
|
63
|
+
? {
|
|
64
|
+
type: "img",
|
|
65
|
+
props: {
|
|
66
|
+
src: logo,
|
|
67
|
+
width: 48,
|
|
68
|
+
height: 48,
|
|
69
|
+
style: { borderRadius: "8px" },
|
|
70
|
+
},
|
|
71
|
+
}
|
|
72
|
+
: {
|
|
73
|
+
type: "div",
|
|
74
|
+
props: {
|
|
75
|
+
style: {
|
|
76
|
+
width: "14px",
|
|
77
|
+
height: "14px",
|
|
78
|
+
backgroundColor: primary,
|
|
79
|
+
borderRadius: "4px",
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
...(siteName
|
|
84
|
+
? [
|
|
85
|
+
{
|
|
86
|
+
type: "div",
|
|
87
|
+
props: {
|
|
88
|
+
style: {
|
|
89
|
+
fontSize: 28,
|
|
90
|
+
fontWeight: 700,
|
|
91
|
+
color: "#ffffff",
|
|
92
|
+
letterSpacing: "-0.02em",
|
|
93
|
+
},
|
|
94
|
+
children: siteName,
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
]
|
|
98
|
+
: []),
|
|
99
|
+
],
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
// Middle: vertical accent bar + title + description
|
|
103
|
+
{
|
|
104
|
+
type: "div",
|
|
105
|
+
props: {
|
|
106
|
+
style: {
|
|
107
|
+
display: "flex",
|
|
108
|
+
flex: 1,
|
|
109
|
+
alignItems: "center",
|
|
110
|
+
marginTop: "48px",
|
|
111
|
+
},
|
|
112
|
+
children: [
|
|
113
|
+
{
|
|
114
|
+
type: "div",
|
|
115
|
+
props: {
|
|
116
|
+
style: {
|
|
117
|
+
width: "4px",
|
|
118
|
+
alignSelf: "stretch",
|
|
119
|
+
backgroundColor: primary,
|
|
120
|
+
borderRadius: "2px",
|
|
121
|
+
marginRight: "32px",
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
type: "div",
|
|
127
|
+
props: {
|
|
128
|
+
style: { display: "flex", flexDirection: "column", flex: 1 },
|
|
129
|
+
children: [
|
|
130
|
+
{
|
|
131
|
+
type: "div",
|
|
132
|
+
props: {
|
|
133
|
+
style: {
|
|
134
|
+
fontSize: 64,
|
|
135
|
+
fontWeight: 700,
|
|
136
|
+
color: "#ffffff",
|
|
137
|
+
lineHeight: 1.1,
|
|
138
|
+
letterSpacing: "-0.02em",
|
|
139
|
+
display: "-webkit-box",
|
|
140
|
+
WebkitLineClamp: 2,
|
|
141
|
+
WebkitBoxOrient: "vertical",
|
|
142
|
+
overflow: "hidden",
|
|
143
|
+
},
|
|
144
|
+
children: displayTitle,
|
|
145
|
+
},
|
|
146
|
+
},
|
|
147
|
+
...(displayDesc
|
|
148
|
+
? [
|
|
149
|
+
{
|
|
150
|
+
type: "div",
|
|
151
|
+
props: {
|
|
152
|
+
style: {
|
|
153
|
+
fontSize: 26,
|
|
154
|
+
fontWeight: 400,
|
|
155
|
+
color: "#cbd5e1",
|
|
156
|
+
marginTop: "24px",
|
|
157
|
+
lineHeight: 1.4,
|
|
158
|
+
letterSpacing: "-0.005em",
|
|
159
|
+
display: "-webkit-box",
|
|
160
|
+
WebkitLineClamp: 2,
|
|
161
|
+
WebkitBoxOrient: "vertical",
|
|
162
|
+
overflow: "hidden",
|
|
163
|
+
},
|
|
164
|
+
children: displayDesc,
|
|
165
|
+
},
|
|
166
|
+
},
|
|
167
|
+
]
|
|
168
|
+
: []),
|
|
169
|
+
],
|
|
170
|
+
},
|
|
171
|
+
},
|
|
172
|
+
],
|
|
173
|
+
},
|
|
174
|
+
},
|
|
175
|
+
],
|
|
176
|
+
},
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
// ---------------------------------------------------------------------------
|
|
180
|
+
// Public API
|
|
181
|
+
// ---------------------------------------------------------------------------
|
|
182
|
+
export async function generateOgImage(options) {
|
|
183
|
+
const fonts = await loadFonts();
|
|
184
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
185
|
+
const svg = await satori(ogCard(options), {
|
|
186
|
+
width: 1200,
|
|
187
|
+
height: 630,
|
|
188
|
+
fonts: [
|
|
189
|
+
{ name: "Inter", data: fonts.regular, weight: 400, style: "normal" },
|
|
190
|
+
{ name: "Inter", data: fonts.bold, weight: 700, style: "normal" },
|
|
191
|
+
],
|
|
192
|
+
});
|
|
193
|
+
const resvg = new Resvg(svg, {
|
|
194
|
+
fitTo: { mode: "width", value: 1200 },
|
|
195
|
+
});
|
|
196
|
+
const png = resvg.render();
|
|
197
|
+
return Buffer.from(png.asPng());
|
|
198
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { ChangelogPage } from "../core/markdown-loader.js";
|
|
2
|
+
import type { NormalizedChangelogVersion } from "../core/types.js";
|
|
3
|
+
export interface ChangelogFeedOptions {
|
|
4
|
+
atomPath: string;
|
|
5
|
+
rssPath: string;
|
|
6
|
+
pagePath: string;
|
|
7
|
+
buildDate?: Date;
|
|
8
|
+
siteName: string;
|
|
9
|
+
title?: string;
|
|
10
|
+
description?: string;
|
|
11
|
+
versionHref(version: NormalizedChangelogVersion): string;
|
|
12
|
+
}
|
|
13
|
+
export interface ChangelogFeedFiles {
|
|
14
|
+
atom: string;
|
|
15
|
+
rss: string;
|
|
16
|
+
}
|
|
17
|
+
export declare function generateChangelogFeeds(page: ChangelogPage, options: ChangelogFeedOptions): ChangelogFeedFiles;
|
|
18
|
+
//# sourceMappingURL=changelog-feed.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"changelog-feed.d.ts","sourceRoot":"","sources":["../../src/renderer/changelog-feed.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,kBAAkB,CAAC;AAEnE,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,IAAI,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,OAAO,EAAE,0BAA0B,GAAG,MAAM,CAAC;CAC1D;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;CACb;AAED,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,aAAa,EACnB,OAAO,EAAE,oBAAoB,GAC5B,kBAAkB,CAsEpB"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
export function generateChangelogFeeds(page, options) {
|
|
2
|
+
const buildDate = options.buildDate ?? new Date();
|
|
3
|
+
const updated = page.changelog.versions
|
|
4
|
+
.map((version) => version.date ? new Date(`${version.date}T00:00:00Z`) : null)
|
|
5
|
+
.find(Boolean) ?? buildDate;
|
|
6
|
+
const title = options.title ?? [options.siteName, page.title].filter(Boolean).join(" ").trim();
|
|
7
|
+
const description = options.description ?? page.description ?? `${page.title} feed`;
|
|
8
|
+
const feedId = toFeedId(options.atomPath);
|
|
9
|
+
const atomEntries = page.changelog.versions.map((version) => {
|
|
10
|
+
const href = options.versionHref(version);
|
|
11
|
+
const content = renderVersionHtml(version);
|
|
12
|
+
const updatedAt = version.date ? new Date(`${version.date}T00:00:00Z`) : updated;
|
|
13
|
+
const label = version.version ?? "Unreleased";
|
|
14
|
+
return [
|
|
15
|
+
" <entry>",
|
|
16
|
+
` <title>${escapeXml(label)}</title>`,
|
|
17
|
+
` <id>${escapeXml(toFeedId(href))}</id>`,
|
|
18
|
+
` <link href="${escapeXml(href)}" />`,
|
|
19
|
+
` <updated>${updatedAt.toISOString()}</updated>`,
|
|
20
|
+
` <content type="html">${escapeXml(content)}</content>`,
|
|
21
|
+
" </entry>",
|
|
22
|
+
].join("\n");
|
|
23
|
+
}).join("\n");
|
|
24
|
+
const atom = [
|
|
25
|
+
`<?xml version="1.0" encoding="UTF-8"?>`,
|
|
26
|
+
`<feed xmlns="http://www.w3.org/2005/Atom">`,
|
|
27
|
+
` <title>${escapeXml(title)}</title>`,
|
|
28
|
+
` <id>${escapeXml(feedId)}</id>`,
|
|
29
|
+
` <updated>${updated.toISOString()}</updated>`,
|
|
30
|
+
` <subtitle>${escapeXml(description)}</subtitle>`,
|
|
31
|
+
` <link rel="self" href="${escapeXml(options.atomPath)}" />`,
|
|
32
|
+
` <link href="${escapeXml(options.pagePath)}" />`,
|
|
33
|
+
page.changelog.versions.length ? atomEntries : "",
|
|
34
|
+
`</feed>`,
|
|
35
|
+
].filter(Boolean).join("\n");
|
|
36
|
+
const rssItems = page.changelog.versions.map((version) => {
|
|
37
|
+
const href = options.versionHref(version);
|
|
38
|
+
const label = version.version ?? "Unreleased";
|
|
39
|
+
const pubDate = version.date
|
|
40
|
+
? new Date(`${version.date}T00:00:00Z`)
|
|
41
|
+
: updated;
|
|
42
|
+
return [
|
|
43
|
+
" <item>",
|
|
44
|
+
` <title>${escapeXml(label)}</title>`,
|
|
45
|
+
` <link>${escapeXml(href)}</link>`,
|
|
46
|
+
` <guid>${escapeXml(href)}</guid>`,
|
|
47
|
+
` <pubDate>${pubDate.toUTCString()}</pubDate>`,
|
|
48
|
+
` <description>${escapeXml(renderVersionHtml(version))}</description>`,
|
|
49
|
+
" </item>",
|
|
50
|
+
].join("\n");
|
|
51
|
+
}).join("\n");
|
|
52
|
+
const rss = [
|
|
53
|
+
`<?xml version="1.0" encoding="UTF-8"?>`,
|
|
54
|
+
`<rss version="2.0">`,
|
|
55
|
+
` <channel>`,
|
|
56
|
+
` <title>${escapeXml(title)}</title>`,
|
|
57
|
+
` <link>${escapeXml(options.pagePath)}</link>`,
|
|
58
|
+
` <description>${escapeXml(description)}</description>`,
|
|
59
|
+
page.changelog.versions.length ? rssItems : "",
|
|
60
|
+
` </channel>`,
|
|
61
|
+
`</rss>`,
|
|
62
|
+
].filter(Boolean).join("\n");
|
|
63
|
+
return { atom, rss };
|
|
64
|
+
}
|
|
65
|
+
function renderVersionHtml(version) {
|
|
66
|
+
const summary = version.summary ? `<p>${escapeHtml(version.summary)}</p>` : "";
|
|
67
|
+
const sections = version.sections.map((section) => {
|
|
68
|
+
const items = section.entries.map((entry) => `<li>${entry.html}</li>`).join("");
|
|
69
|
+
return `<section><h3>${escapeHtml(section.label)}</h3><ul>${items}</ul></section>`;
|
|
70
|
+
}).join("");
|
|
71
|
+
return `<article><h2>${escapeHtml(version.version ?? "Unreleased")}</h2>${summary}${sections}</article>`;
|
|
72
|
+
}
|
|
73
|
+
function escapeXml(value) {
|
|
74
|
+
return value
|
|
75
|
+
.replace(/&/g, "&")
|
|
76
|
+
.replace(/</g, "<")
|
|
77
|
+
.replace(/>/g, ">")
|
|
78
|
+
.replace(/"/g, """)
|
|
79
|
+
.replace(/'/g, "'");
|
|
80
|
+
}
|
|
81
|
+
function escapeHtml(value) {
|
|
82
|
+
return value
|
|
83
|
+
.replace(/&/g, "&")
|
|
84
|
+
.replace(/</g, "<")
|
|
85
|
+
.replace(/>/g, ">");
|
|
86
|
+
}
|
|
87
|
+
function toFeedId(value) {
|
|
88
|
+
if (value.startsWith("http://") || value.startsWith("https://"))
|
|
89
|
+
return value;
|
|
90
|
+
return `urn:sourcey:${value.replace(/^\/+/, "").replace(/\//g, ":")}`;
|
|
91
|
+
}
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import type { NormalizedSpec } from "../core/types.js";
|
|
2
2
|
import type { SiteNavigation } from "../core/navigation.js";
|
|
3
|
-
import type { MarkdownPage } from "../core/markdown-loader.js";
|
|
4
|
-
import type { NavbarLink, ResolvedTheme } from "../config.js";
|
|
3
|
+
import type { ChangelogPage, MarkdownPage } from "../core/markdown-loader.js";
|
|
4
|
+
import type { NavbarLink, PrettyUrls, ResolvedChangelogConfig, ResolvedTheme } from "../config.js";
|
|
5
|
+
export interface AlternateLink {
|
|
6
|
+
href: string;
|
|
7
|
+
type: string;
|
|
8
|
+
title?: string;
|
|
9
|
+
}
|
|
5
10
|
/**
|
|
6
11
|
* Options that control rendering behavior.
|
|
7
12
|
*/
|
|
@@ -10,6 +15,12 @@ export interface RenderOptions {
|
|
|
10
15
|
embeddable: boolean;
|
|
11
16
|
/** Base URL for assets (CSS, JS) */
|
|
12
17
|
assetBase: string;
|
|
18
|
+
/** Canonical absolute URL for the current page, when configured. */
|
|
19
|
+
pageUrl?: string;
|
|
20
|
+
/** Public URL for the OG image for this page. */
|
|
21
|
+
ogImageUrl?: string;
|
|
22
|
+
/** Alternate link tags to emit for the current page. */
|
|
23
|
+
alternateLinks?: AlternateLink[];
|
|
13
24
|
}
|
|
14
25
|
/**
|
|
15
26
|
* Full context available to all components during rendering.
|
|
@@ -21,11 +32,16 @@ export interface RenderContext {
|
|
|
21
32
|
/**
|
|
22
33
|
* What the current page is rendering.
|
|
23
34
|
*/
|
|
24
|
-
export
|
|
25
|
-
kind: "spec"
|
|
26
|
-
spec
|
|
27
|
-
|
|
28
|
-
|
|
35
|
+
export type CurrentPage = {
|
|
36
|
+
kind: "spec";
|
|
37
|
+
spec: NormalizedSpec;
|
|
38
|
+
} | {
|
|
39
|
+
kind: "markdown";
|
|
40
|
+
markdown: MarkdownPage;
|
|
41
|
+
} | {
|
|
42
|
+
kind: "changelog";
|
|
43
|
+
changelog: ChangelogPage;
|
|
44
|
+
};
|
|
29
45
|
/**
|
|
30
46
|
* Preact context for passing spec data to deeply nested components.
|
|
31
47
|
*/
|
|
@@ -47,6 +63,9 @@ export declare const PageContext: import("preact").Context<CurrentPage>;
|
|
|
47
63
|
*/
|
|
48
64
|
export interface SiteConfig {
|
|
49
65
|
name: string;
|
|
66
|
+
siteUrl?: string;
|
|
67
|
+
baseUrl: string;
|
|
68
|
+
prettyUrls: PrettyUrls;
|
|
50
69
|
theme: ResolvedTheme;
|
|
51
70
|
logo?: {
|
|
52
71
|
light?: string;
|
|
@@ -70,6 +89,7 @@ export interface SiteConfig {
|
|
|
70
89
|
links: NavbarLink[];
|
|
71
90
|
};
|
|
72
91
|
customCSS?: string;
|
|
92
|
+
changelog: ResolvedChangelogConfig;
|
|
73
93
|
}
|
|
74
94
|
export declare const SiteContext: import("preact").Context<SiteConfig>;
|
|
75
95
|
//# sourceMappingURL=context.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/renderer/context.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/renderer/context.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC9E,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,uBAAuB,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAEnG,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,mEAAmE;IACnE,UAAU,EAAE,OAAO,CAAC;IACpB,oCAAoC;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,oEAAoE;IACpE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iDAAiD;IACjD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,wDAAwD;IACxD,cAAc,CAAC,EAAE,aAAa,EAAE,CAAC;CAClC;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,cAAc,CAAC;IACrB,OAAO,EAAE,aAAa,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,MAAM,WAAW,GACnB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,cAAc,CAAA;CAAE,GACtC;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,EAAE,YAAY,CAAA;CAAE,GAC5C;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,SAAS,EAAE,aAAa,CAAA;CAAE,CAAC;AAEpD;;GAEG;AACH,eAAO,MAAM,WAAW,0CAA+C,CAAC;AAExE;;GAEG;AACH,eAAO,MAAM,cAAc,yCAGzB,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,iBAAiB,0CAA+C,CAAC;AAE9E;;GAEG;AACH,eAAO,MAAM,WAAW,uCAA4C,CAAC;AAErE;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,UAAU,CAAC;IACvB,KAAK,EAAE,aAAa,CAAC;IACrB,IAAI,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACxD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,MAAM,EAAE;QAAE,KAAK,EAAE,UAAU,EAAE,CAAC;QAAC,OAAO,CAAC,EAAE;YAAE,IAAI,EAAE,QAAQ,CAAC;YAAC,KAAK,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAC;IAC3F,MAAM,EAAE;QAAE,KAAK,EAAE,UAAU,EAAE,CAAA;KAAE,CAAC;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,uBAAuB,CAAC;CACpC;AAED,eAAO,MAAM,WAAW,sCAA2C,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { NormalizedSpec } from "../core/types.js";
|
|
2
|
-
import type { CurrentPage, SiteConfig } from "./context.js";
|
|
2
|
+
import type { AlternateLink, RenderOptions, CurrentPage, SiteConfig } from "./context.js";
|
|
3
3
|
import type { SiteNavigation } from "../core/navigation.js";
|
|
4
4
|
export interface BuildOutput {
|
|
5
5
|
htmlPath: string;
|
|
@@ -11,7 +11,14 @@ export interface SitePage {
|
|
|
11
11
|
spec: NormalizedSpec;
|
|
12
12
|
tabSlug: string;
|
|
13
13
|
pageSlug: string;
|
|
14
|
+
/** Relative path to the generated OG image (set during build) */
|
|
15
|
+
ogImagePath?: string;
|
|
16
|
+
alternateLinks?: AlternateLink[];
|
|
14
17
|
}
|
|
18
|
+
export declare function createRenderOptions(page: SitePage, site: SiteConfig, options?: {
|
|
19
|
+
embeddable?: boolean;
|
|
20
|
+
assetBase?: string;
|
|
21
|
+
}): RenderOptions;
|
|
15
22
|
/**
|
|
16
23
|
* Build a documentation site.
|
|
17
24
|
*/
|
|
@@ -20,5 +27,7 @@ export declare function buildSite(pages: SitePage[], navigation: SiteNavigation,
|
|
|
20
27
|
searchIndex?: string;
|
|
21
28
|
llmsTxt?: string;
|
|
22
29
|
llmsFullTxt?: string;
|
|
30
|
+
ogImages?: Map<string, Buffer>;
|
|
31
|
+
extraFiles?: Map<string, string | Buffer>;
|
|
23
32
|
}): Promise<BuildOutput>;
|
|
24
33
|
//# sourceMappingURL=html-builder.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"html-builder.d.ts","sourceRoot":"","sources":["../../src/renderer/html-builder.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"html-builder.d.ts","sourceRoot":"","sources":["../../src/renderer/html-builder.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1F,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AA2B5D,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,QAAQ;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,WAAW,CAAC;IACzB,IAAI,EAAE,cAAc,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,iEAAiE;IACjE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,aAAa,EAAE,CAAC;CAClC;AAED,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,QAAQ,EACd,IAAI,EAAE,UAAU,EAChB,OAAO,CAAC,EAAE;IACR,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GACA,aAAa,CAcf;AAED;;GAEG;AACH,wBAAsB,SAAS,CAC7B,KAAK,EAAE,QAAQ,EAAE,EACjB,UAAU,EAAE,cAAc,EAC1B,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,UAAU,EAChB,OAAO,CAAC,EAAE;IACR,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,UAAU,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;CAC3C,GACA,OAAO,CAAC,WAAW,CAAC,CA8EtB"}
|
|
@@ -6,6 +6,7 @@ import tailwindcss from "@tailwindcss/vite";
|
|
|
6
6
|
import preact from "@preact/preset-vite";
|
|
7
7
|
import { renderPage } from "./static-renderer.js";
|
|
8
8
|
import { withActivePage } from "../core/navigation.js";
|
|
9
|
+
import { isAbsoluteHttpUrl, toAbsoluteUrl, toPublicPath } from "../site-url.js";
|
|
9
10
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
10
11
|
const projectRoot = resolve(__dirname, "../..");
|
|
11
12
|
async function exists(path) {
|
|
@@ -30,6 +31,20 @@ async function resolveAssetPaths() {
|
|
|
30
31
|
const sourceyCssPath = await exists(srcCss) ? srcCss : distCss;
|
|
31
32
|
return { clientEntry, sourceyCssPath };
|
|
32
33
|
}
|
|
34
|
+
export function createRenderOptions(page, site, options) {
|
|
35
|
+
const assetBase = options?.assetBase ?? "";
|
|
36
|
+
const pagePublicPath = toPublicPath(page.outputPath, site.baseUrl, site.prettyUrls);
|
|
37
|
+
return {
|
|
38
|
+
embeddable: options?.embeddable ?? false,
|
|
39
|
+
assetBase,
|
|
40
|
+
pageUrl: site.siteUrl ? toAbsoluteUrl(pagePublicPath, site.siteUrl) : undefined,
|
|
41
|
+
ogImageUrl: page.ogImagePath ? resolveRenderHref(page.ogImagePath, assetBase, site) : undefined,
|
|
42
|
+
alternateLinks: page.alternateLinks?.map((link) => ({
|
|
43
|
+
...link,
|
|
44
|
+
href: resolveRenderHref(link.href, assetBase, site),
|
|
45
|
+
})),
|
|
46
|
+
};
|
|
47
|
+
}
|
|
33
48
|
/**
|
|
34
49
|
* Build a documentation site.
|
|
35
50
|
*/
|
|
@@ -42,10 +57,10 @@ export async function buildSite(pages, navigation, outputDir, site, options) {
|
|
|
42
57
|
await mkdir(pageDir, { recursive: true });
|
|
43
58
|
const depth = page.outputPath.split("/").length - 1;
|
|
44
59
|
const assetBase = depth > 0 ? "../".repeat(depth) : "";
|
|
45
|
-
const renderOptions = {
|
|
46
|
-
embeddable: options?.embeddable
|
|
60
|
+
const renderOptions = createRenderOptions(page, site, {
|
|
61
|
+
embeddable: options?.embeddable,
|
|
47
62
|
assetBase,
|
|
48
|
-
};
|
|
63
|
+
});
|
|
49
64
|
const activeNav = withActivePage(navigation, page.tabSlug, page.pageSlug);
|
|
50
65
|
const html = renderPage(page.spec, renderOptions, activeNav, page.currentPage, site);
|
|
51
66
|
await writeFile(resolve(resolvedDir, page.outputPath), html, "utf-8");
|
|
@@ -53,7 +68,10 @@ export async function buildSite(pages, navigation, outputDir, site, options) {
|
|
|
53
68
|
if (pages.length > 0 && pages[0].outputPath !== "index.html") {
|
|
54
69
|
const first = pages[0];
|
|
55
70
|
const activeNav = withActivePage(navigation, first.tabSlug, first.pageSlug);
|
|
56
|
-
const renderOptions =
|
|
71
|
+
const renderOptions = createRenderOptions(first, site, {
|
|
72
|
+
embeddable: options?.embeddable,
|
|
73
|
+
assetBase: "",
|
|
74
|
+
});
|
|
57
75
|
const html = renderPage(first.spec, renderOptions, activeNav, first.currentPage, site);
|
|
58
76
|
await writeFile(resolve(resolvedDir, "index.html"), html, "utf-8");
|
|
59
77
|
}
|
|
@@ -67,7 +85,11 @@ export async function buildSite(pages, navigation, outputDir, site, options) {
|
|
|
67
85
|
if (options?.llmsFullTxt) {
|
|
68
86
|
await writeFile(resolve(resolvedDir, "llms-full.txt"), options.llmsFullTxt, "utf-8");
|
|
69
87
|
}
|
|
70
|
-
const urls = pages.map(
|
|
88
|
+
const urls = pages.map((page) => {
|
|
89
|
+
const publicPath = toPublicPath(page.outputPath, site.baseUrl, site.prettyUrls);
|
|
90
|
+
const loc = site.siteUrl ? toAbsoluteUrl(publicPath, site.siteUrl) : publicPath;
|
|
91
|
+
return ` <url><loc>${loc}</loc></url>`;
|
|
92
|
+
});
|
|
71
93
|
const sitemap = [
|
|
72
94
|
`<?xml version="1.0" encoding="UTF-8"?>`,
|
|
73
95
|
`<!-- Generated by Sourcey https://sourcey.com -->`,
|
|
@@ -76,8 +98,39 @@ export async function buildSite(pages, navigation, outputDir, site, options) {
|
|
|
76
98
|
`</urlset>`,
|
|
77
99
|
].join("\n");
|
|
78
100
|
await writeFile(resolve(resolvedDir, "sitemap.xml"), sitemap, "utf-8");
|
|
101
|
+
// Write generated OG images
|
|
102
|
+
if (options?.ogImages) {
|
|
103
|
+
for (const [path, data] of options.ogImages) {
|
|
104
|
+
const fullPath = resolve(resolvedDir, path);
|
|
105
|
+
await mkdir(dirname(fullPath), { recursive: true });
|
|
106
|
+
await writeFile(fullPath, data);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
if (options?.extraFiles) {
|
|
110
|
+
for (const [path, data] of options.extraFiles) {
|
|
111
|
+
const fullPath = resolve(resolvedDir, path);
|
|
112
|
+
await mkdir(dirname(fullPath), { recursive: true });
|
|
113
|
+
await writeFile(fullPath, data);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
79
116
|
return { htmlPath: resolve(resolvedDir, "index.html"), outputDir: resolvedDir };
|
|
80
117
|
}
|
|
118
|
+
function resolveRenderHref(pathOrUrl, assetBase, site) {
|
|
119
|
+
if (!pathOrUrl ||
|
|
120
|
+
pathOrUrl.startsWith("#") ||
|
|
121
|
+
pathOrUrl.startsWith("mailto:") ||
|
|
122
|
+
pathOrUrl.startsWith("data:") ||
|
|
123
|
+
isAbsoluteHttpUrl(pathOrUrl)) {
|
|
124
|
+
return pathOrUrl;
|
|
125
|
+
}
|
|
126
|
+
if (site.siteUrl) {
|
|
127
|
+
return toAbsoluteUrl(toPublicPath(pathOrUrl, site.baseUrl), site.siteUrl);
|
|
128
|
+
}
|
|
129
|
+
if (site.baseUrl) {
|
|
130
|
+
return toPublicPath(pathOrUrl, site.baseUrl);
|
|
131
|
+
}
|
|
132
|
+
return `${assetBase}${pathOrUrl}`;
|
|
133
|
+
}
|
|
81
134
|
/**
|
|
82
135
|
* Build client JS + Tailwind CSS via Vite.
|
|
83
136
|
* Same plugins as the dev server — preact() + tailwindcss().
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"llms.d.ts","sourceRoot":"","sources":["../../src/renderer/llms.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"llms.d.ts","sourceRoot":"","sources":["../../src/renderer/llms.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAI5D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAElD,wBAAgB,eAAe,CAC7B,KAAK,EAAE,QAAQ,EAAE,EACjB,UAAU,EAAE,cAAc,EAC1B,IAAI,EAAE,UAAU,GACf,MAAM,CAyDR;AAED,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,QAAQ,EAAE,EACjB,UAAU,EAAE,cAAc,EAC1B,IAAI,EAAE,UAAU,GACf,MAAM,CAgCR"}
|