mdsvr 2.2.13 → 2.2.16

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.
Files changed (64) hide show
  1. package/README.md +3 -3
  2. package/dist/generators/feed.d.ts.map +1 -1
  3. package/dist/generators/feed.js +4 -2
  4. package/dist/generators/feed.js.map +1 -1
  5. package/dist/generators/search-index.d.ts.map +1 -1
  6. package/dist/generators/search-index.js +10 -1
  7. package/dist/generators/search-index.js.map +1 -1
  8. package/dist/generators/sitemap.d.ts.map +1 -1
  9. package/dist/generators/sitemap.js +3 -1
  10. package/dist/generators/sitemap.js.map +1 -1
  11. package/dist/generators/static-export.d.ts.map +1 -1
  12. package/dist/generators/static-export.js +182 -21
  13. package/dist/generators/static-export.js.map +1 -1
  14. package/dist/og/generator.d.ts +25 -0
  15. package/dist/og/generator.d.ts.map +1 -0
  16. package/dist/og/generator.js +234 -0
  17. package/dist/og/generator.js.map +1 -0
  18. package/dist/og/index.d.ts +4 -0
  19. package/dist/og/index.d.ts.map +1 -0
  20. package/dist/og/index.js +4 -0
  21. package/dist/og/index.js.map +1 -0
  22. package/dist/og/template.d.ts +12 -0
  23. package/dist/og/template.d.ts.map +1 -0
  24. package/dist/og/template.js +183 -0
  25. package/dist/og/template.js.map +1 -0
  26. package/dist/og/types.d.ts +54 -0
  27. package/dist/og/types.d.ts.map +1 -0
  28. package/dist/og/types.js +3 -0
  29. package/dist/og/types.js.map +1 -0
  30. package/dist/renderer/markdown.d.ts +16 -0
  31. package/dist/renderer/markdown.d.ts.map +1 -1
  32. package/dist/renderer/markdown.js +56 -0
  33. package/dist/renderer/markdown.js.map +1 -1
  34. package/dist/router.d.ts.map +1 -1
  35. package/dist/router.js +10 -3
  36. package/dist/router.js.map +1 -1
  37. package/dist/settings/defaults.d.ts +1 -0
  38. package/dist/settings/defaults.d.ts.map +1 -1
  39. package/dist/settings/defaults.js +1 -0
  40. package/dist/settings/defaults.js.map +1 -1
  41. package/dist/settings/index.d.ts +1 -1
  42. package/dist/settings/index.d.ts.map +1 -1
  43. package/dist/settings/index.js +1 -1
  44. package/dist/settings/index.js.map +1 -1
  45. package/dist/settings/schema.d.ts +260 -0
  46. package/dist/settings/schema.d.ts.map +1 -1
  47. package/dist/settings/schema.js +26 -1
  48. package/dist/settings/schema.js.map +1 -1
  49. package/dist/template/index.d.ts +1 -0
  50. package/dist/template/index.d.ts.map +1 -1
  51. package/dist/template/index.js +50 -11
  52. package/dist/template/index.js.map +1 -1
  53. package/dist/template/search.d.ts +1 -1
  54. package/dist/template/search.d.ts.map +1 -1
  55. package/dist/template/search.js +5 -2
  56. package/dist/template/search.js.map +1 -1
  57. package/dist/template/seo.d.ts.map +1 -1
  58. package/dist/template/seo.js +4 -2
  59. package/dist/template/seo.js.map +1 -1
  60. package/dist/template/sidebar.d.ts +2 -1
  61. package/dist/template/sidebar.d.ts.map +1 -1
  62. package/dist/template/sidebar.js +71 -14
  63. package/dist/template/sidebar.js.map +1 -1
  64. package/package.json +15 -8
@@ -0,0 +1,234 @@
1
+ // OG Image generator using Satori and Resvg
2
+ import satori from "satori";
3
+ import { Resvg } from "@resvg/resvg-js";
4
+ import sharp from "sharp";
5
+ import { promises as fs } from "node:fs";
6
+ import path from "node:path";
7
+ import https from "node:https";
8
+ import { generateOgTemplate, OG_WIDTH, OG_HEIGHT } from "./template.js";
9
+ // Font CDN URLs - using jsDelivr for reliable font delivery
10
+ const FONT_URLS = {
11
+ Inter: "https://cdn.jsdelivr.net/npm/@fontsource/inter@5.0.8/files/inter-latin-400-normal.woff",
12
+ "Inter-400": "https://cdn.jsdelivr.net/npm/@fontsource/inter@5.0.8/files/inter-latin-400-normal.woff",
13
+ "Inter-600": "https://cdn.jsdelivr.net/npm/@fontsource/inter@5.0.8/files/inter-latin-600-normal.woff",
14
+ "Inter-700": "https://cdn.jsdelivr.net/npm/@fontsource/inter@5.0.8/files/inter-latin-700-normal.woff",
15
+ "Inter-800": "https://cdn.jsdelivr.net/npm/@fontsource/inter@5.0.8/files/inter-latin-800-normal.woff",
16
+ };
17
+ // Font data cache
18
+ const fontCache = new Map();
19
+ /**
20
+ * Download font from URL
21
+ */
22
+ function downloadFont(url) {
23
+ return new Promise((resolve, reject) => {
24
+ https
25
+ .get(url, { timeout: 30000 }, (res) => {
26
+ if (res.statusCode !== 200) {
27
+ reject(new Error(`Failed to download font: ${res.statusCode}`));
28
+ return;
29
+ }
30
+ const chunks = [];
31
+ res.on("data", (chunk) => chunks.push(chunk));
32
+ res.on("end", () => resolve(Buffer.concat(chunks)));
33
+ res.on("error", reject);
34
+ })
35
+ .on("error", reject);
36
+ });
37
+ }
38
+ /**
39
+ * Load font data (with caching and CDN fallback)
40
+ */
41
+ async function loadFont(fontFamily, weight = 400) {
42
+ const cacheKey = `${fontFamily}-${weight}`;
43
+ // Check cache first
44
+ if (fontCache.has(cacheKey)) {
45
+ return fontCache.get(cacheKey);
46
+ }
47
+ try {
48
+ // Try to load from CDN for Inter
49
+ if (fontFamily.toLowerCase() === "inter") {
50
+ const fontUrl = FONT_URLS[`Inter-${weight}`] || FONT_URLS["Inter"];
51
+ if (fontUrl) {
52
+ try {
53
+ const data = await downloadFont(fontUrl);
54
+ fontCache.set(cacheKey, data);
55
+ return data;
56
+ }
57
+ catch {
58
+ // Fallback to next method
59
+ }
60
+ }
61
+ }
62
+ // Try to load from local paths
63
+ const possiblePaths = [
64
+ path.join(process.cwd(), "assets", "fonts", `${fontFamily}-${weight}.woff2`),
65
+ path.join(process.cwd(), "assets", "fonts", `${fontFamily}-${weight}.woff`),
66
+ path.join(process.cwd(), "assets", "fonts", `${fontFamily}.ttf`),
67
+ path.join(process.cwd(), "src", "assets", "fonts", `${fontFamily}-${weight}.woff2`),
68
+ path.join(process.cwd(), "src", "assets", "fonts", `${fontFamily}.ttf`),
69
+ ];
70
+ for (const fontPath of possiblePaths) {
71
+ try {
72
+ const data = await fs.readFile(fontPath);
73
+ fontCache.set(cacheKey, data);
74
+ return data;
75
+ }
76
+ catch {
77
+ // Continue to next path
78
+ }
79
+ }
80
+ return null;
81
+ }
82
+ catch {
83
+ return null;
84
+ }
85
+ }
86
+ /**
87
+ * Generate OG image using Satori and Resvg
88
+ */
89
+ export async function generateOgImage(data, options) {
90
+ const { outputPath, format = "jpg", quality = 85, width = OG_WIDTH, height = OG_HEIGHT, } = options;
91
+ try {
92
+ // Ensure output directory exists
93
+ await fs.mkdir(path.dirname(outputPath), { recursive: true });
94
+ // Generate template
95
+ const template = generateOgTemplate(data);
96
+ // Load fonts - we need specific weights for the template
97
+ const fontFamily = data.fontFamily || "Inter";
98
+ const fonts = [];
99
+ // Load different font weights needed for the template
100
+ const weights = [400, 600, 700, 800];
101
+ for (const weight of weights) {
102
+ const fontData = await loadFont(fontFamily, weight);
103
+ if (fontData) {
104
+ fonts.push({
105
+ name: fontFamily,
106
+ data: fontData,
107
+ weight,
108
+ });
109
+ }
110
+ }
111
+ // If no fonts were loaded, we can't generate the image
112
+ if (fonts.length === 0) {
113
+ throw new Error(`No fonts are loaded for ${fontFamily}. Unable to generate OG image.`);
114
+ }
115
+ // Generate SVG using Satori
116
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
117
+ const satoriOptions = {
118
+ width,
119
+ height,
120
+ };
121
+ if (fonts.length > 0) {
122
+ satoriOptions.fonts = fonts;
123
+ }
124
+ const svg = await satori(template, satoriOptions);
125
+ // Convert SVG to raster image using Resvg
126
+ const resvg = new Resvg(svg, {
127
+ fitTo: {
128
+ mode: "width",
129
+ value: width,
130
+ },
131
+ });
132
+ const pngData = resvg.render();
133
+ const pngBuffer = pngData.asPng();
134
+ // Convert to JPG if needed using sharp
135
+ let finalBuffer;
136
+ const outputExt = path.extname(outputPath).toLowerCase();
137
+ if (outputExt === ".jpg" || outputExt === ".jpeg") {
138
+ finalBuffer = await sharp(pngBuffer)
139
+ .jpeg({ quality: options.quality || 85, progressive: true })
140
+ .toBuffer();
141
+ }
142
+ else {
143
+ finalBuffer = pngBuffer;
144
+ }
145
+ await fs.writeFile(outputPath, finalBuffer);
146
+ return {
147
+ success: true,
148
+ outputPath,
149
+ };
150
+ }
151
+ catch (error) {
152
+ const errorMessage = error instanceof Error ? error.message : String(error);
153
+ console.error(`[mdsvr] OG image generation failed: ${errorMessage}`);
154
+ return {
155
+ success: false,
156
+ error: errorMessage,
157
+ };
158
+ }
159
+ }
160
+ /**
161
+ * Batch generate OG images for multiple pages
162
+ */
163
+ export async function batchGenerateOgImages(items, format = "jpg", silent = false) {
164
+ let generated = 0;
165
+ let failed = 0;
166
+ for (const item of items) {
167
+ const result = await generateOgImage(item.data, {
168
+ outputPath: item.outputPath,
169
+ format,
170
+ });
171
+ if (result.success) {
172
+ generated++;
173
+ if (!silent) {
174
+ console.log(` ✓ OG image: ${item.urlPath} → ${item.outputPath}`);
175
+ }
176
+ }
177
+ else {
178
+ failed++;
179
+ if (!silent) {
180
+ console.log(` ✗ OG image failed: ${item.urlPath} (${result.error})`);
181
+ }
182
+ }
183
+ }
184
+ return { generated, failed };
185
+ }
186
+ /**
187
+ * Get OG image output path for a URL path
188
+ */
189
+ export function getOgImagePath(urlPath, outputDir, format = "jpg", basePath = "") {
190
+ // Normalize URL path and strip basePath if present
191
+ let normalized = urlPath.replace(/\/$/, "");
192
+ // Remove basePath prefix from urlPath if it exists
193
+ // This ensures the file structure matches the URL structure
194
+ const normalizedBase = basePath.endsWith("/")
195
+ ? basePath.slice(0, -1)
196
+ : basePath;
197
+ if (normalizedBase && normalized.startsWith(normalizedBase)) {
198
+ normalized = normalized.slice(normalizedBase.length);
199
+ }
200
+ const segments = normalized.split("/").filter(Boolean);
201
+ if (segments.length === 0) {
202
+ // Root path
203
+ return path.join(outputDir, `index.${format}`);
204
+ }
205
+ // Create path: /og/docs/guides → /og/docs/guides.jpg
206
+ // For directories ending with index, use index.jpg
207
+ if (urlPath.endsWith("/")) {
208
+ return path.join(outputDir, ...segments, `index.${format}`);
209
+ }
210
+ // For specific files: /guides/setup → /og/guides/setup.jpg
211
+ return path.join(outputDir, ...segments, `index.${format}`);
212
+ }
213
+ /**
214
+ * Get OG image URL for a page
215
+ */
216
+ export function getOgImageUrl(urlPath, basePath, format = "jpg") {
217
+ const normalizedBase = basePath.endsWith("/")
218
+ ? basePath.slice(0, -1)
219
+ : basePath;
220
+ // Normalize URL path and strip basePath if present
221
+ let normalized = urlPath.replace(/\/$/, "");
222
+ // Remove basePath prefix from urlPath if it exists
223
+ // urlPath already includes basePath (e.g., /docs/3.-features/mdx)
224
+ // We need to strip it to avoid double basePath
225
+ if (normalizedBase && normalized.startsWith(normalizedBase)) {
226
+ normalized = normalized.slice(normalizedBase.length);
227
+ }
228
+ const segments = normalized.split("/").filter(Boolean);
229
+ if (segments.length === 0) {
230
+ return `${normalizedBase}/public/og/index.${format}`;
231
+ }
232
+ return `${normalizedBase}/public/og/${segments.join("/")}/index.${format}`;
233
+ }
234
+ //# sourceMappingURL=generator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generator.js","sourceRoot":"","sources":["../../src/og/generator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export { generateOgImage, batchGenerateOgImages, getOgImagePath, getOgImageUrl } from "./generator.js";
2
+ export { generateOgTemplate, generateMinimalOgTemplate, OG_WIDTH, OG_HEIGHT } from "./template.js";
3
+ export type { OgImageData, OgGenerationOptions, OgGenerationResult, OgSettings, } from "./types.js";
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/og/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,qBAAqB,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACvG,OAAO,EAAE,kBAAkB,EAAE,yBAAyB,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AACnG,YAAY,EACV,WAAW,EACX,mBAAmB,EACnB,kBAAkB,EAClB,UAAU,GACX,MAAM,YAAY,CAAC"}
@@ -0,0 +1,4 @@
1
+ // OG Image generation module exports
2
+ export { generateOgImage, batchGenerateOgImages, getOgImagePath, getOgImageUrl } from "./generator.js";
3
+ export { generateOgTemplate, generateMinimalOgTemplate, OG_WIDTH, OG_HEIGHT } from "./template.js";
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/og/index.ts"],"names":[],"mappings":"AAAA,qCAAqC;AAErC,OAAO,EAAE,eAAe,EAAE,qBAAqB,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACvG,OAAO,EAAE,kBAAkB,EAAE,yBAAyB,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { OgImageData } from "./types.js";
2
+ export declare const OG_WIDTH = 1200;
3
+ export declare const OG_HEIGHT = 630;
4
+ /**
5
+ * Generate the OG image JSX structure for Satori
6
+ */
7
+ export declare function generateOgTemplate(data: OgImageData): JSX.Element;
8
+ /**
9
+ * Alternative minimal template
10
+ */
11
+ export declare function generateMinimalOgTemplate(data: OgImageData): JSX.Element;
12
+ //# sourceMappingURL=template.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"template.d.ts","sourceRoot":"","sources":["../../src/og/template.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAG9C,eAAO,MAAM,QAAQ,OAAO,CAAC;AAC7B,eAAO,MAAM,SAAS,MAAM,CAAC;AA+B7B;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,WAAW,GAAG,GAAG,CAAC,OAAO,CAkMjE;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,WAAW,GAAG,GAAG,CAAC,OAAO,CAsExE"}
@@ -0,0 +1,183 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ // OG Image dimensions
3
+ export const OG_WIDTH = 1200;
4
+ export const OG_HEIGHT = 630;
5
+ // Font fallback stack
6
+ const FONT_STACK = [
7
+ "Inter",
8
+ "system-ui",
9
+ "-apple-system",
10
+ "BlinkMacSystemFont",
11
+ "Segoe UI",
12
+ "Roboto",
13
+ "sans-serif",
14
+ ];
15
+ // Monospace font for URL
16
+ const MONO_FONT = [
17
+ "JetBrains Mono",
18
+ "Fira Code",
19
+ "SF Mono",
20
+ "Monaco",
21
+ "Consolas",
22
+ "monospace",
23
+ ];
24
+ /**
25
+ * Truncate text to a maximum length
26
+ */
27
+ function truncate(text, maxLength) {
28
+ if (text.length <= maxLength)
29
+ return text;
30
+ return text.slice(0, maxLength - 3).trim() + "...";
31
+ }
32
+ /**
33
+ * Generate the OG image JSX structure for Satori
34
+ */
35
+ export function generateOgTemplate(data) {
36
+ const { title, description, siteName, urlPath, accentColor = "#0969da", fontFamily = "Inter", backgroundColor = "#0a0a0f", textColor = "#ffffff", } = data;
37
+ const truncatedTitle = truncate(title, 120);
38
+ const truncatedDesc = description ? truncate(description, 200) : "";
39
+ // Create font family string
40
+ const fonts = [fontFamily, ...FONT_STACK.filter((f) => f !== fontFamily)];
41
+ const fontFamilyString = fonts.join(", ");
42
+ const monoFontString = MONO_FONT.join(", ");
43
+ return (_jsxs("div", { style: {
44
+ width: OG_WIDTH,
45
+ height: OG_HEIGHT,
46
+ display: "flex",
47
+ flexDirection: "column",
48
+ background: backgroundColor,
49
+ fontFamily: fontFamilyString,
50
+ color: textColor,
51
+ padding: "60px 80px",
52
+ position: "relative",
53
+ overflow: "hidden",
54
+ }, children: [_jsx("div", { style: {
55
+ position: "absolute",
56
+ top: -100,
57
+ right: -100,
58
+ width: 600,
59
+ height: 600,
60
+ background: `radial-gradient(circle, ${accentColor}20 0%, transparent 70%)`,
61
+ borderRadius: "50%",
62
+ } }), _jsx("div", { style: {
63
+ position: "absolute",
64
+ bottom: -150,
65
+ left: -100,
66
+ width: 500,
67
+ height: 500,
68
+ background: `radial-gradient(circle, ${accentColor}15 0%, transparent 70%)`,
69
+ borderRadius: "50%",
70
+ } }), _jsx("div", { style: {
71
+ position: "absolute",
72
+ top: 0,
73
+ left: 0,
74
+ right: 0,
75
+ height: 6,
76
+ background: `linear-gradient(90deg, ${accentColor} 0%, ${accentColor}80 50%, ${accentColor}40 100%)`,
77
+ } }), _jsxs("div", { style: {
78
+ display: "flex",
79
+ flexDirection: "column",
80
+ flex: 1,
81
+ justifyContent: "center",
82
+ }, children: [_jsx("div", { style: {
83
+ fontSize: 24,
84
+ fontWeight: 600,
85
+ color: accentColor,
86
+ textTransform: "uppercase",
87
+ letterSpacing: "0.1em",
88
+ marginBottom: 20,
89
+ }, children: siteName }), _jsx("div", { style: {
90
+ fontSize: 64,
91
+ fontWeight: 800,
92
+ lineHeight: 1.1,
93
+ marginBottom: description ? 24 : 0,
94
+ color: textColor,
95
+ }, children: truncatedTitle }), truncatedDesc && (_jsx("div", { style: {
96
+ fontSize: 28,
97
+ fontWeight: 400,
98
+ lineHeight: 1.4,
99
+ color: `${textColor}cc`,
100
+ maxWidth: 900,
101
+ }, children: truncatedDesc }))] }), urlPath && (_jsxs("div", { style: {
102
+ display: "flex",
103
+ alignItems: "center",
104
+ gap: 12,
105
+ marginTop: "auto",
106
+ paddingTop: 40,
107
+ }, children: [_jsx("div", { style: {
108
+ width: 8,
109
+ height: 8,
110
+ background: accentColor,
111
+ borderRadius: "50%",
112
+ } }), _jsx("div", { style: {
113
+ fontFamily: monoFontString,
114
+ fontSize: 18,
115
+ color: `${textColor}99`,
116
+ letterSpacing: "0.02em",
117
+ }, children: urlPath })] })), _jsxs("div", { style: {
118
+ position: "absolute",
119
+ bottom: 40,
120
+ right: 80,
121
+ display: "flex",
122
+ alignItems: "center",
123
+ gap: 8,
124
+ }, children: [_jsx("div", { style: {
125
+ width: 40,
126
+ height: 4,
127
+ background: accentColor,
128
+ borderRadius: 2,
129
+ } }), _jsx("div", { style: {
130
+ width: 20,
131
+ height: 4,
132
+ background: `${accentColor}60`,
133
+ borderRadius: 2,
134
+ } }), _jsx("div", { style: {
135
+ width: 10,
136
+ height: 4,
137
+ background: `${accentColor}30`,
138
+ borderRadius: 2,
139
+ } })] })] }));
140
+ }
141
+ /**
142
+ * Alternative minimal template
143
+ */
144
+ export function generateMinimalOgTemplate(data) {
145
+ const { title, siteName, accentColor = "#0969da", backgroundColor = "#ffffff", textColor = "#1a1a1a", } = data;
146
+ const fonts = [data.fontFamily || "Inter", ...FONT_STACK];
147
+ return (_jsxs("div", { style: {
148
+ width: OG_WIDTH,
149
+ height: OG_HEIGHT,
150
+ display: "flex",
151
+ flexDirection: "column",
152
+ background: backgroundColor,
153
+ fontFamily: fonts.join(", "),
154
+ padding: "80px",
155
+ position: "relative",
156
+ }, children: [_jsx("div", { style: {
157
+ position: "absolute",
158
+ left: 0,
159
+ top: 0,
160
+ bottom: 0,
161
+ width: 12,
162
+ background: accentColor,
163
+ } }), _jsxs("div", { style: {
164
+ display: "flex",
165
+ flexDirection: "column",
166
+ justifyContent: "center",
167
+ flex: 1,
168
+ paddingLeft: 40,
169
+ }, children: [_jsx("div", { style: {
170
+ fontSize: 20,
171
+ fontWeight: 500,
172
+ color: accentColor,
173
+ textTransform: "uppercase",
174
+ letterSpacing: "0.15em",
175
+ marginBottom: 24,
176
+ }, children: siteName }), _jsx("div", { style: {
177
+ fontSize: 72,
178
+ fontWeight: 700,
179
+ lineHeight: 1.15,
180
+ color: textColor,
181
+ }, children: truncate(title, 100) })] })] }));
182
+ }
183
+ //# sourceMappingURL=template.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"template.js","sourceRoot":"","sources":["../../src/og/template.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,54 @@
1
+ export interface OgImageData {
2
+ /** Page title (from frontmatter or extracted from H1) */
3
+ title: string;
4
+ /** Page description (from frontmatter or extracted from content) */
5
+ description?: string;
6
+ /** Site name */
7
+ siteName: string;
8
+ /** URL path */
9
+ urlPath?: string;
10
+ /** Accent color from settings */
11
+ accentColor?: string;
12
+ /** Font family */
13
+ fontFamily?: string;
14
+ /** Background color */
15
+ backgroundColor?: string;
16
+ /** Text color */
17
+ textColor?: string;
18
+ }
19
+ export interface OgGenerationOptions {
20
+ /** Output file path */
21
+ outputPath: string;
22
+ /** Image format */
23
+ format: "jpg" | "png";
24
+ /** Image quality (0-100) for JPG */
25
+ quality?: number;
26
+ /** Width of the image */
27
+ width?: number;
28
+ /** Height of the image */
29
+ height?: number;
30
+ }
31
+ export interface OgSettings {
32
+ /** Enable OG image generation */
33
+ enabled: boolean;
34
+ /** Template name (default: "default") */
35
+ template: string;
36
+ /** Image format */
37
+ imageFormat: "jpg" | "png";
38
+ /** Generate on serve mode */
39
+ generateOnServe: boolean;
40
+ /** Font family */
41
+ fontFamily: string;
42
+ /** Color scheme */
43
+ colors: {
44
+ background: string;
45
+ text: string;
46
+ accent: string;
47
+ };
48
+ }
49
+ export interface OgGenerationResult {
50
+ success: boolean;
51
+ outputPath?: string;
52
+ error?: string;
53
+ }
54
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/og/types.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,WAAW;IAC1B,yDAAyD;IACzD,KAAK,EAAE,MAAM,CAAC;IACd,oEAAoE;IACpE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gBAAgB;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iCAAiC;IACjC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kBAAkB;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,uBAAuB;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iBAAiB;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,mBAAmB;IAClC,uBAAuB;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,mBAAmB;IACnB,MAAM,EAAE,KAAK,GAAG,KAAK,CAAC;IACtB,oCAAoC;IACpC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,yBAAyB;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0BAA0B;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,UAAU;IACzB,iCAAiC;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,yCAAyC;IACzC,QAAQ,EAAE,MAAM,CAAC;IACjB,mBAAmB;IACnB,WAAW,EAAE,KAAK,GAAG,KAAK,CAAC;IAC3B,6BAA6B;IAC7B,eAAe,EAAE,OAAO,CAAC;IACzB,kBAAkB;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,mBAAmB;IACnB,MAAM,EAAE;QACN,UAAU,EAAE,MAAM,CAAC;QACnB,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;CACH;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB"}
@@ -0,0 +1,3 @@
1
+ // OG Image data types
2
+ export {};
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/og/types.ts"],"names":[],"mappings":"AAAA,sBAAsB"}
@@ -11,5 +11,21 @@ export interface MarkdownResult {
11
11
  toc: TocItem[];
12
12
  }
13
13
  export declare function renderMarkdown(content: string, settings: Settings): MarkdownResult;
14
+ /**
15
+ * Extract the first H1 heading from markdown content (for SEO title fallback)
16
+ */
17
+ export declare function extractFirstHeading(content: string): string | null;
18
+ /**
19
+ * Extract the first paragraph text from markdown content (for SEO description fallback)
20
+ * Skips frontmatter, headings, code blocks, and HTML comments
21
+ */
22
+ export declare function extractFirstParagraph(content: string): string | null;
23
+ /**
24
+ * Extract SEO data from markdown content
25
+ */
26
+ export declare function extractSeoData(content: string): {
27
+ title: string | null;
28
+ description: string | null;
29
+ };
14
30
  export declare function renderMarkdownSimple(content: string): string;
15
31
  //# sourceMappingURL=markdown.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/renderer/markdown.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAErD,MAAM,WAAW,OAAO;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,GAAG,EAAE,OAAO,EAAE,CAAC;CAChB;AAwDD,wBAAgB,cAAc,CAC5B,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,QAAQ,GACjB,cAAc,CAahB;AAiBD,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAkD5D"}
1
+ {"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/renderer/markdown.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAErD,MAAM,WAAW,OAAO;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,GAAG,EAAE,OAAO,EAAE,CAAC;CAChB;AAwDD,wBAAgB,cAAc,CAC5B,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,QAAQ,GACjB,cAAc,CAahB;AAgBD;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAOlE;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAwCpE;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG;IAC/C,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B,CAKA;AAGD,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAkD5D"}
@@ -73,6 +73,62 @@ function extractToc(html) {
73
73
  }
74
74
  return toc;
75
75
  }
76
+ /**
77
+ * Extract the first H1 heading from markdown content (for SEO title fallback)
78
+ */
79
+ export function extractFirstHeading(content) {
80
+ // Match markdown H1 heading (# Heading text)
81
+ const h1Match = content.match(/^#\s+(.+)$/m);
82
+ if (h1Match) {
83
+ return h1Match[1].trim();
84
+ }
85
+ return null;
86
+ }
87
+ /**
88
+ * Extract the first paragraph text from markdown content (for SEO description fallback)
89
+ * Skips frontmatter, headings, code blocks, and HTML comments
90
+ */
91
+ export function extractFirstParagraph(content) {
92
+ // Remove frontmatter
93
+ const withoutFrontmatter = content.replace(/^---[\s\S]*?---/, "");
94
+ // Remove code blocks
95
+ const withoutCodeBlocks = withoutFrontmatter.replace(/```[\s\S]*?```/g, "");
96
+ // Remove HTML comments
97
+ const withoutComments = withoutCodeBlocks.replace(/<!--[\s\S]*?-->/g, "");
98
+ // Remove headings
99
+ const withoutHeadings = withoutComments.replace(/^#{1,6}\s+.+$/gm, "");
100
+ // Remove horizontal rules
101
+ const withoutRules = withoutHeadings.replace(/^[\s]*[-_*]{3,}[\s]*$/gm, "");
102
+ // Find first non-empty paragraph (text followed by blank line or end of string)
103
+ // Match text that isn't a list item, blockquote, or other special markdown
104
+ const paragraphRegex = /^([^\s#\-\*\>\|\!\`].+)$/m;
105
+ const match = withoutRules.match(paragraphRegex);
106
+ if (match) {
107
+ // Clean up the text: remove markdown formatting and trim
108
+ let text = match[1]
109
+ .replace(/\[([^\]]+)\]\([^)]+\)/g, "$1") // Remove links, keep text
110
+ .replace(/\*\*([^*]+)\*\*/g, "$1") // Remove bold
111
+ .replace(/\*([^*]+)\*/g, "$1") // Remove italic
112
+ .replace(/`([^`]+)`/g, "$1") // Remove inline code
113
+ .replace(/\s+/g, " ") // Normalize whitespace
114
+ .trim();
115
+ // Limit to reasonable length for description
116
+ if (text.length > 300) {
117
+ text = text.slice(0, 297).trim() + "...";
118
+ }
119
+ return text || null;
120
+ }
121
+ return null;
122
+ }
123
+ /**
124
+ * Extract SEO data from markdown content
125
+ */
126
+ export function extractSeoData(content) {
127
+ return {
128
+ title: extractFirstHeading(content),
129
+ description: extractFirstParagraph(content),
130
+ };
131
+ }
76
132
  // For V1 compatibility - simple render without frontmatter extraction
77
133
  export function renderMarkdownSimple(content) {
78
134
  const md = new MarkdownIt({