@farming-labs/docs 0.0.9 → 0.0.11

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.d.mts CHANGED
@@ -223,13 +223,36 @@ interface OGConfig {
223
223
  endpoint?: string;
224
224
  defaultImage?: string;
225
225
  }
226
+ /** Single image entry for Open Graph (frontmatter or Next metadata). */
227
+ interface OpenGraphImage {
228
+ url: string;
229
+ width?: number;
230
+ height?: number;
231
+ }
232
+ /** Open Graph block in page frontmatter. When present, used as-is for metadata (replaces generated OG). */
233
+ interface PageOpenGraph {
234
+ images?: OpenGraphImage[];
235
+ title?: string;
236
+ description?: string;
237
+ }
238
+ /** Twitter card block in page frontmatter. When present, used as-is for metadata (replaces generated twitter). */
239
+ interface PageTwitter {
240
+ card?: "summary" | "summary_large_image";
241
+ images?: string[];
242
+ title?: string;
243
+ description?: string;
244
+ }
226
245
  interface PageFrontmatter {
227
246
  title: string;
228
247
  description?: string;
229
248
  tags?: string[];
230
249
  icon?: string;
231
- /** Path to custom OG image for this page */
250
+ /** Path to custom OG image for this page (shorthand). Ignored if `openGraph` is set. */
232
251
  ogImage?: string;
252
+ /** Full Open Graph object. When set, replaces any generated OG from config (e.g. dynamic endpoint). */
253
+ openGraph?: PageOpenGraph;
254
+ /** Full Twitter card object. When set, replaces any generated twitter from config. */
255
+ twitter?: PageTwitter;
233
256
  /** Sort order in the sidebar. Lower numbers appear first. Pages without `order` are sorted alphabetically after ordered pages. */
234
257
  order?: number;
235
258
  }
@@ -962,6 +985,20 @@ interface OrderingItem {
962
985
  /** Ordering for child pages within this folder */
963
986
  children?: OrderingItem[];
964
987
  }
988
+ /**
989
+ * Data passed to the `onCopyClick` callback when the user clicks the copy button
990
+ * on a code block in the docs.
991
+ */
992
+ interface CodeBlockCopyData {
993
+ /** Title of the code block (e.g. from the fenced code block meta string), if present */
994
+ title?: string;
995
+ /** Raw code content (the text that was copied to the clipboard) */
996
+ content: string;
997
+ /** Current page URL at the time of copy */
998
+ url: string;
999
+ /** Language / syntax hint (e.g. "tsx", "bash"), if present */
1000
+ language?: string;
1001
+ }
965
1002
  interface DocsConfig {
966
1003
  /** Entry folder for docs (e.g. "docs" → /docs) */
967
1004
  entry: string;
@@ -1058,6 +1095,24 @@ interface DocsConfig {
1058
1095
  * ```
1059
1096
  */
1060
1097
  components?: Record<string, unknown>;
1098
+ /**
1099
+ * Callback fired when the user clicks the copy button on a code block.
1100
+ * Called in addition to the default copy-to-clipboard behavior.
1101
+ * Use it for analytics, logging, or custom behavior.
1102
+ *
1103
+ * @example
1104
+ * ```ts
1105
+ * export default defineDocs({
1106
+ * entry: "docs",
1107
+ * theme: fumadocs(),
1108
+ * onCopyClick(data) {
1109
+ * console.log("Code copied", data.title, data.language, data.url);
1110
+ * analytics.track("code_block_copy", { title: data.title, url: data.url });
1111
+ * },
1112
+ * });
1113
+ * ```
1114
+ */
1115
+ onCopyClick?: (data: CodeBlockCopyData) => void;
1061
1116
  /**
1062
1117
  * Icon registry for sidebar items.
1063
1118
  *
@@ -1279,7 +1334,20 @@ declare function extendTheme(baseTheme: DocsTheme, extensions: Partial<DocsTheme
1279
1334
  declare function resolveTitle(pageTitle: string, metadata?: DocsMetadata): string;
1280
1335
  /**
1281
1336
  * Resolve OG image URL for a page.
1337
+ * Prefers page.openGraph.images[0], then page.ogImage, then config endpoint/default.
1282
1338
  */
1283
1339
  declare function resolveOGImage(page: PageFrontmatter, ogConfig?: OGConfig, baseUrl?: string): string | undefined;
1340
+ /**
1341
+ * Build the Open Graph metadata object for a page.
1342
+ * When the page has openGraph in frontmatter, uses it (with title/description filled from page if omitted).
1343
+ * Otherwise uses ogImage or config (dynamic endpoint / defaultImage).
1344
+ */
1345
+ declare function buildPageOpenGraph(page: Pick<PageFrontmatter, "title" | "description" | "ogImage" | "openGraph">, ogConfig?: OGConfig, baseUrl?: string): PageOpenGraph | undefined;
1346
+ /**
1347
+ * Build the Twitter card metadata object for a page.
1348
+ * When the page has twitter in frontmatter, uses it.
1349
+ * Otherwise builds from ogImage or config (dynamic endpoint).
1350
+ */
1351
+ declare function buildPageTwitter(page: Pick<PageFrontmatter, "title" | "description" | "ogImage" | "openGraph" | "twitter">, ogConfig?: OGConfig, baseUrl?: string): PageTwitter | undefined;
1284
1352
  //#endregion
1285
- export { type AIConfig, type BreadcrumbConfig, type CopyMarkdownConfig, type DocsConfig, type DocsMetadata, type DocsNav, type DocsTheme, type FontStyle, type GithubConfig, type LastUpdatedConfig, type LlmsTxtConfig, type OGConfig, type OpenDocsConfig, type OpenDocsProvider, type OrderingItem, type PageActionsConfig, type PageFrontmatter, type SidebarComponentProps, type SidebarConfig, type SidebarFolderNode, type SidebarNode, type SidebarPageNode, type SidebarTree, type ThemeToggleConfig, type TypographyConfig, type UIConfig, createTheme, deepMerge, defineDocs, extendTheme, resolveOGImage, resolveTitle };
1353
+ export { type AIConfig, type BreadcrumbConfig, type CodeBlockCopyData, type CopyMarkdownConfig, type DocsConfig, type DocsMetadata, type DocsNav, type DocsTheme, type FontStyle, type GithubConfig, type LastUpdatedConfig, type LlmsTxtConfig, type OGConfig, type OpenDocsConfig, type OpenDocsProvider, type OpenGraphImage, type OrderingItem, type PageActionsConfig, type PageFrontmatter, type PageOpenGraph, type PageTwitter, type SidebarComponentProps, type SidebarConfig, type SidebarFolderNode, type SidebarNode, type SidebarPageNode, type SidebarTree, type ThemeToggleConfig, type TypographyConfig, type UIConfig, buildPageOpenGraph, buildPageTwitter, createTheme, deepMerge, defineDocs, extendTheme, resolveOGImage, resolveTitle };
package/dist/index.mjs CHANGED
@@ -110,13 +110,74 @@ function resolveTitle(pageTitle, metadata) {
110
110
  }
111
111
  /**
112
112
  * Resolve OG image URL for a page.
113
+ * Prefers page.openGraph.images[0], then page.ogImage, then config endpoint/default.
113
114
  */
114
115
  function resolveOGImage(page, ogConfig, baseUrl) {
116
+ if (page.openGraph?.images?.length) return resolveImageUrl(page.openGraph.images[0].url, baseUrl);
115
117
  if (!ogConfig?.enabled) return void 0;
116
- if (page.ogImage) return page.ogImage.startsWith("/") || page.ogImage.startsWith("http") ? page.ogImage : `${baseUrl ?? ""}${page.ogImage}`;
118
+ if (page.ogImage) return resolveImageUrl(page.ogImage, baseUrl);
117
119
  if (ogConfig.type === "dynamic" && ogConfig.endpoint) return `${baseUrl ?? ""}${ogConfig.endpoint}`;
118
120
  return ogConfig.defaultImage;
119
121
  }
122
+ function resolveImageUrl(url, baseUrl) {
123
+ if (url.startsWith("/") || url.startsWith("http")) return url;
124
+ const base = baseUrl ?? "";
125
+ return `${base}${base.length > 0 && !base.endsWith("/") ? "/" : ""}${url}`;
126
+ }
127
+ /**
128
+ * Build the Open Graph metadata object for a page.
129
+ * When the page has openGraph in frontmatter, uses it (with title/description filled from page if omitted).
130
+ * Otherwise uses ogImage or config (dynamic endpoint / defaultImage).
131
+ */
132
+ function buildPageOpenGraph(page, ogConfig, baseUrl) {
133
+ if (page.openGraph) {
134
+ const images = page.openGraph.images?.length ? page.openGraph.images.map((img) => ({
135
+ url: resolveImageUrl(img.url, baseUrl),
136
+ width: img.width ?? 1200,
137
+ height: img.height ?? 630
138
+ })) : void 0;
139
+ return {
140
+ title: page.openGraph.title ?? page.title,
141
+ description: page.openGraph.description ?? page.description,
142
+ ...images && { images }
143
+ };
144
+ }
145
+ const url = resolveOGImage(page, ogConfig, baseUrl);
146
+ if (!url) return void 0;
147
+ return {
148
+ title: page.title,
149
+ ...page.description && { description: page.description },
150
+ images: [{
151
+ url,
152
+ width: 1200,
153
+ height: 630
154
+ }]
155
+ };
156
+ }
157
+ /**
158
+ * Build the Twitter card metadata object for a page.
159
+ * When the page has twitter in frontmatter, uses it.
160
+ * Otherwise builds from ogImage or config (dynamic endpoint).
161
+ */
162
+ function buildPageTwitter(page, ogConfig, baseUrl) {
163
+ if (page.twitter) {
164
+ const images = page.twitter.images?.length ? page.twitter.images.map((url) => resolveImageUrl(url, baseUrl)) : void 0;
165
+ return {
166
+ ...page.twitter.card && { card: page.twitter.card },
167
+ ...page.twitter.title !== void 0 && { title: page.twitter.title },
168
+ ...page.twitter.description !== void 0 && { description: page.twitter.description },
169
+ ...images && { images }
170
+ };
171
+ }
172
+ const url = resolveOGImage(page, ogConfig, baseUrl);
173
+ if (!url) return void 0;
174
+ return {
175
+ card: "summary_large_image",
176
+ title: page.title,
177
+ ...page.description && { description: page.description },
178
+ images: [url]
179
+ };
180
+ }
120
181
 
121
182
  //#endregion
122
- export { createTheme, deepMerge, defineDocs, extendTheme, resolveOGImage, resolveTitle };
183
+ export { buildPageOpenGraph, buildPageTwitter, createTheme, deepMerge, defineDocs, extendTheme, resolveOGImage, resolveTitle };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@farming-labs/docs",
3
- "version": "0.0.9",
3
+ "version": "0.0.11",
4
4
  "description": "Modern, flexible MDX-based docs framework — core types, config, and CLI",
5
5
  "keywords": [
6
6
  "docs",