@farming-labs/theme 0.2.96 → 0.2.98
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/docs-layout.mjs +51 -2
- package/dist/docs-page-client.d.mts +3 -0
- package/dist/docs-page-client.mjs +16 -4
- package/package.json +2 -2
package/dist/docs-layout.mjs
CHANGED
|
@@ -35,6 +35,30 @@ function readFrontmatter(filePath) {
|
|
|
35
35
|
return {};
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
|
+
function hasAuthoredPageTitle(source) {
|
|
39
|
+
const { content } = matter(source);
|
|
40
|
+
const lines = content.split(/\r?\n/);
|
|
41
|
+
let fence;
|
|
42
|
+
let previousTextLine = "";
|
|
43
|
+
for (const line of lines) {
|
|
44
|
+
const fenceMatch = line.match(/^\s*(`{3,}|~{3,})/);
|
|
45
|
+
if (fenceMatch) {
|
|
46
|
+
const marker = fenceMatch[1]?.[0];
|
|
47
|
+
fence = fence === marker ? void 0 : fence ?? marker;
|
|
48
|
+
previousTextLine = "";
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
if (fence) continue;
|
|
52
|
+
if (/^ {0,3}#(?:\s+|$)/.test(line) || /^\s*<h1(?:\s|>)/i.test(line)) return true;
|
|
53
|
+
if (previousTextLine && /^ {0,3}=+\s*$/.test(line)) return true;
|
|
54
|
+
previousTextLine = line.trim() && !line.trimStart().startsWith("<") ? line : "";
|
|
55
|
+
}
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
function resolveSidebarFolderName(themeName, slug, pageTitle) {
|
|
59
|
+
if (themeName !== "shadcn" || pageTitle.trim().toLowerCase() !== "introduction") return pageTitle;
|
|
60
|
+
return slug.split(/[-_]/).filter(Boolean).map((part) => part[0]?.toUpperCase() + part.slice(1)).join(" ");
|
|
61
|
+
}
|
|
38
62
|
/** Check if a directory has any subdirectories that contain page.mdx. */
|
|
39
63
|
function isWithinDir(candidate, target) {
|
|
40
64
|
const relative = path.relative(target, candidate);
|
|
@@ -194,12 +218,13 @@ function buildTree(config, ctx, flat = false) {
|
|
|
194
218
|
const url = publicDocsRoute(ctx, slug);
|
|
195
219
|
const icon = resolveIcon(data.icon, icons);
|
|
196
220
|
const displayName = data.title ?? name.replace(/-/g, " ");
|
|
221
|
+
const folderName = resolveSidebarFolderName(config.theme?.name, name, displayName);
|
|
197
222
|
const hasChildren = hasChildPages(full, excludedDirs);
|
|
198
223
|
if (data.hidden === true) {
|
|
199
224
|
if (!hasChildren) return null;
|
|
200
225
|
return {
|
|
201
226
|
type: "folder",
|
|
202
|
-
name:
|
|
227
|
+
name: folderName,
|
|
203
228
|
icon,
|
|
204
229
|
children: scanDir(full, slug, slugOrder),
|
|
205
230
|
...flat ? {
|
|
@@ -212,7 +237,7 @@ function buildTree(config, ctx, flat = false) {
|
|
|
212
237
|
const folderChildren = scanDir(full, slug, slugOrder);
|
|
213
238
|
return {
|
|
214
239
|
type: "folder",
|
|
215
|
-
name:
|
|
240
|
+
name: folderName,
|
|
216
241
|
icon,
|
|
217
242
|
index: {
|
|
218
243
|
type: "page",
|
|
@@ -380,6 +405,28 @@ function buildDescriptionMap(config, ctx) {
|
|
|
380
405
|
scan(docsDir, []);
|
|
381
406
|
return map;
|
|
382
407
|
}
|
|
408
|
+
/** Build titles only for pages whose MDX body does not already author an h1. */
|
|
409
|
+
function buildGeneratedTitleMap(config, ctx) {
|
|
410
|
+
const docsDir = ctx.docsDir;
|
|
411
|
+
const map = {};
|
|
412
|
+
const excludedDirs = getExcludedDocsDirs(config, ctx);
|
|
413
|
+
function scan(dir, slugParts) {
|
|
414
|
+
if (!fs.existsSync(dir)) return;
|
|
415
|
+
if (isExcludedDir(dir, excludedDirs)) return;
|
|
416
|
+
const pagePath = findDocsPageFile(dir);
|
|
417
|
+
if (pagePath) {
|
|
418
|
+
const source = fs.readFileSync(pagePath, "utf-8");
|
|
419
|
+
const { data } = matter(source);
|
|
420
|
+
if (typeof data.title === "string" && !hasAuthoredPageTitle(source)) map[publicDocsRoute(ctx, slugParts)] = data.title;
|
|
421
|
+
}
|
|
422
|
+
for (const name of fs.readdirSync(dir)) {
|
|
423
|
+
const full = path.join(dir, name);
|
|
424
|
+
if (fs.statSync(full).isDirectory()) scan(full, [...slugParts, name]);
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
scan(docsDir, []);
|
|
428
|
+
return map;
|
|
429
|
+
}
|
|
383
430
|
function buildReadingTimeMap(config, ctx, options) {
|
|
384
431
|
const docsDir = ctx.docsDir;
|
|
385
432
|
const map = {};
|
|
@@ -702,6 +749,7 @@ function createDocsLayout(config, options) {
|
|
|
702
749
|
}
|
|
703
750
|
const lastModifiedMap = buildLastModifiedMap(config, localeContext);
|
|
704
751
|
const descriptionMap = buildDescriptionMap(config, localeContext);
|
|
752
|
+
const generatedTitleMap = config.theme?.name === "shadcn" ? buildGeneratedTitleMap(config, localeContext) : {};
|
|
705
753
|
const readingTimeMap = buildReadingTimeMap(config, localeContext, {
|
|
706
754
|
enabledByDefault: readingTimeEnabledByDefault,
|
|
707
755
|
wordsPerMinute: readingTimeWordsPerMinute,
|
|
@@ -820,6 +868,7 @@ function createDocsLayout(config, options) {
|
|
|
820
868
|
readingTimeMap,
|
|
821
869
|
structuredDataMap,
|
|
822
870
|
llmsTxtEnabled,
|
|
871
|
+
generatedTitleMap,
|
|
823
872
|
descriptionMap,
|
|
824
873
|
feedbackEnabled: feedbackConfig.enabled,
|
|
825
874
|
feedbackQuestion: feedbackConfig.question,
|
|
@@ -78,6 +78,8 @@ interface DocsPageClientProps {
|
|
|
78
78
|
lastUpdatedPosition?: "footer" | "below-title";
|
|
79
79
|
/** Whether llms.txt is enabled — shows links in footer */
|
|
80
80
|
llmsTxtEnabled?: boolean;
|
|
81
|
+
/** Frontmatter titles for pages whose MDX body does not author an h1 */
|
|
82
|
+
generatedTitleMap?: Record<string, string>;
|
|
81
83
|
/** Map of pathname → frontmatter description */
|
|
82
84
|
descriptionMap?: Record<string, string>;
|
|
83
85
|
/** Frontmatter description to display below the page title (overrides descriptionMap) */
|
|
@@ -134,6 +136,7 @@ declare function DocsPageClient({
|
|
|
134
136
|
lastUpdatedLabel,
|
|
135
137
|
lastUpdatedPosition,
|
|
136
138
|
llmsTxtEnabled,
|
|
139
|
+
generatedTitleMap,
|
|
137
140
|
descriptionMap,
|
|
138
141
|
description,
|
|
139
142
|
feedbackEnabled,
|
|
@@ -255,7 +255,7 @@ function findThreadlineTocActionsContainer() {
|
|
|
255
255
|
}
|
|
256
256
|
return toc.parentElement ?? toc;
|
|
257
257
|
}
|
|
258
|
-
function DocsPageClient({ tocEnabled, tocStyle = "default", breadcrumbEnabled = true, changelogBasePath, entry = "docs", publicPath, locale, copyMarkdown = false, copyMarkdownFormat, copyMarkdownIncludeTitle, copyMarkdownLabel, copyMarkdownCopiedLabel, openDocs = false, openDocsProviders, openDocsTarget, openDocsPrompt, pageActionsPosition = "below-title", pageActionsAlignment = "left", githubUrl, contentDir, githubBranch = "main", githubDirectory, editOnGithubUrl, lastModifiedMap, lastModified: lastModifiedProp, readingTimeMap, readingTime: readingTimeProp, readingTimeFormat = "long", previousPage, nextPage, structuredDataMap, structuredData: structuredDataProp, readingTimeEnabled = false, lastUpdatedEnabled = true, lastUpdatedLabel = "Last updated", lastUpdatedPosition = "footer", llmsTxtEnabled = false, descriptionMap, description, feedbackEnabled = false, feedbackQuestion, feedbackPlaceholder, feedbackRequireComment, feedbackPositiveLabel, feedbackNegativeLabel, feedbackSubmitLabel, feedbackSuccessMessage, feedbackErrorMessage, feedbackOnFeedback, analytics = false, children }) {
|
|
258
|
+
function DocsPageClient({ tocEnabled, tocStyle = "default", breadcrumbEnabled = true, changelogBasePath, entry = "docs", publicPath, locale, copyMarkdown = false, copyMarkdownFormat, copyMarkdownIncludeTitle, copyMarkdownLabel, copyMarkdownCopiedLabel, openDocs = false, openDocsProviders, openDocsTarget, openDocsPrompt, pageActionsPosition = "below-title", pageActionsAlignment = "left", githubUrl, contentDir, githubBranch = "main", githubDirectory, editOnGithubUrl, lastModifiedMap, lastModified: lastModifiedProp, readingTimeMap, readingTime: readingTimeProp, readingTimeFormat = "long", previousPage, nextPage, structuredDataMap, structuredData: structuredDataProp, readingTimeEnabled = false, lastUpdatedEnabled = true, lastUpdatedLabel = "Last updated", lastUpdatedPosition = "footer", llmsTxtEnabled = false, generatedTitleMap, descriptionMap, description, feedbackEnabled = false, feedbackQuestion, feedbackPlaceholder, feedbackRequireComment, feedbackPositiveLabel, feedbackNegativeLabel, feedbackSubmitLabel, feedbackSuccessMessage, feedbackErrorMessage, feedbackOnFeedback, analytics = false, children }) {
|
|
259
259
|
const fdTocStyle = tocStyle === "directional" ? "clerk" : void 0;
|
|
260
260
|
const [toc, setToc] = useState([]);
|
|
261
261
|
const [titlePortalHost, setTitlePortalHost] = useState(null);
|
|
@@ -268,8 +268,9 @@ function DocsPageClient({ tocEnabled, tocStyle = "default", breadcrumbEnabled =
|
|
|
268
268
|
const activeLocale = resolveClientLocale(searchParams, locale);
|
|
269
269
|
const resolvedPublicPath = normalizePublicDocsPath(publicPath, entry);
|
|
270
270
|
const llmsLangQuery = activeLocale ? `?lang=${encodeURIComponent(activeLocale)}` : "";
|
|
271
|
-
const pageDescription = description ?? descriptionMap?.[pathname.replace(/\/$/, "") || "/"];
|
|
272
271
|
const normalizedPath = (browserPathname || pathname).replace(/\/$/, "") || "/";
|
|
272
|
+
const pageTitle = generatedTitleMap?.[normalizedPath];
|
|
273
|
+
const pageDescription = description ?? descriptionMap?.[normalizedPath];
|
|
273
274
|
const isChangelogRoute = !!(changelogBasePath && (normalizedPath === changelogBasePath || normalizedPath.startsWith(`${changelogBasePath}/`)));
|
|
274
275
|
const matchedReadingTime = readingTimeMap?.[normalizedPath];
|
|
275
276
|
const structuredDataJson = !isChangelogRoute ? structuredDataProp ?? structuredDataMap?.[normalizedPath] : void 0;
|
|
@@ -495,7 +496,7 @@ function DocsPageClient({ tocEnabled, tocStyle = "default", breadcrumbEnabled =
|
|
|
495
496
|
]
|
|
496
497
|
}, "below-title") : void 0;
|
|
497
498
|
const decoratedChildren = children;
|
|
498
|
-
const needsTitleDecorationsPortal = !!titleDescription || !!belowTitleBlock;
|
|
499
|
+
const needsTitleDecorationsPortal = !pageTitle && (!!titleDescription || !!belowTitleBlock);
|
|
499
500
|
useEffect(() => {
|
|
500
501
|
if (!needsTitleDecorationsPortal) {
|
|
501
502
|
setTitlePortalHost(null);
|
|
@@ -521,6 +522,16 @@ function DocsPageClient({ tocEnabled, tocStyle = "default", breadcrumbEnabled =
|
|
|
521
522
|
}) : null;
|
|
522
523
|
const titleDecorationsPortal = titleDecorations && titlePortalHost ? createPortal(titleDecorations, titlePortalHost, "title-decorations") : null;
|
|
523
524
|
const titleDecorationsFallback = titleDecorations && !titlePortalHost ? titleDecorations : null;
|
|
525
|
+
const generatedPageHeader = pageTitle ? /* @__PURE__ */ jsxs("div", {
|
|
526
|
+
className: "fd-generated-page-header not-prose",
|
|
527
|
+
children: [/* @__PURE__ */ jsx("h1", {
|
|
528
|
+
className: "fd-page-title",
|
|
529
|
+
children: pageTitle
|
|
530
|
+
}), /* @__PURE__ */ jsx(TitleDecorations, {
|
|
531
|
+
description: titleDescription,
|
|
532
|
+
belowTitle: belowTitleBlock
|
|
533
|
+
})]
|
|
534
|
+
}) : null;
|
|
524
535
|
const titleControlsPortal = showActionsInToc && titleControlsPortalHost ? createPortal(/* @__PURE__ */ jsx(ThreadlinePageControls, {}), titleControlsPortalHost, "title-controls") : null;
|
|
525
536
|
const tocActionsPortal = showActionsInToc && tocActionsPortalHost ? createPortal(/* @__PURE__ */ jsx("div", {
|
|
526
537
|
className: "fd-actions-toc-portal not-prose",
|
|
@@ -604,11 +615,12 @@ function DocsPageClient({ tocEnabled, tocStyle = "default", breadcrumbEnabled =
|
|
|
604
615
|
flexDirection: "column"
|
|
605
616
|
},
|
|
606
617
|
children: [
|
|
618
|
+
generatedPageHeader,
|
|
607
619
|
/* @__PURE__ */ jsx("div", {
|
|
608
620
|
style: { flex: 1 },
|
|
609
621
|
children: renderedChildren
|
|
610
622
|
}, "content"),
|
|
611
|
-
titleDecorationsFallback,
|
|
623
|
+
!generatedPageHeader && titleDecorationsFallback,
|
|
612
624
|
titleDecorationsPortal,
|
|
613
625
|
!isChangelogRoute && feedbackEnabled && /* @__PURE__ */ jsx(DocsFeedback, {
|
|
614
626
|
pathname: normalizedPath,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@farming-labs/theme",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.98",
|
|
4
4
|
"description": "Theme package for @farming-labs/docs — layout, provider, MDX components, and styles",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"docs",
|
|
@@ -154,7 +154,7 @@
|
|
|
154
154
|
"tsdown": "^0.20.3",
|
|
155
155
|
"typescript": "^5.9.3",
|
|
156
156
|
"vitest": "^4.1.8",
|
|
157
|
-
"@farming-labs/docs": "0.2.
|
|
157
|
+
"@farming-labs/docs": "0.2.98"
|
|
158
158
|
},
|
|
159
159
|
"peerDependencies": {
|
|
160
160
|
"@farming-labs/docs": ">=0.0.1",
|