@farming-labs/theme 0.1.69 → 0.1.71

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-api.mjs CHANGED
@@ -3,7 +3,7 @@ import { getNextAppDir } from "./get-app-dir.mjs";
3
3
  import fs from "node:fs";
4
4
  import path from "node:path";
5
5
  import matter from "gray-matter";
6
- import { emitDocsAnalyticsEvent, normalizeDocsRelated, performDocsSearch, renderDocsRelatedMarkdownLines, resolveChangelogConfig, resolveDocsI18n, resolveDocsLocale, resolveSearchRequestConfig } from "@farming-labs/docs";
6
+ import { emitDocsAnalyticsEvent, normalizeDocsRelated, performDocsSearch, renderDocsRelatedMarkdownLines, resolveChangelogConfig, resolveDocsI18n, resolveDocsLocale, resolvePageSidebarFolderIndexBehavior, resolveSearchRequestConfig } from "@farming-labs/docs";
7
7
  import { createDocsMcpHttpHandler, createFilesystemDocsMcpSource, resolveDocsMcpConfig } from "@farming-labs/docs/server";
8
8
 
9
9
  //#region src/docs-api.ts
@@ -660,6 +660,45 @@ function resolveAgentMdxContent(content, audience) {
660
660
  function stripMdx(content) {
661
661
  return content.replace(/^(import|export)\s.*$/gm, "").replace(/<[^>]+\/>/g, "").replace(/<\/?[A-Z][^>]*>/g, "").replace(/<\/?[a-z][^>]*>/g, "").replace(/\[([^\]]+)\]\([^)]+\)/g, "$1").replace(/!\[([^\]]*)\]\([^)]+\)/g, "$1").replace(/^#{1,6}\s+/gm, "").replace(/(\*{1,3}|_{1,3})(.*?)\1/g, "$2").replace(/```[\s\S]*?```/g, "").replace(/`([^`]+)`/g, "$1").replace(/^>\s+/gm, "").replace(/^[-*_]{3,}\s*$/gm, "").replace(/\n{3,}/g, "\n\n").trim();
662
662
  }
663
+ function resolveDocsSearchPageSource(dir) {
664
+ return ["page.mdx", "page.md"].map((fileName) => path.join(dir, fileName)).find((candidate) => fs.existsSync(candidate));
665
+ }
666
+ function hasVisibleDescendantDocsSearchPage(dir) {
667
+ let entries;
668
+ try {
669
+ entries = fs.readdirSync(dir);
670
+ } catch {
671
+ return false;
672
+ }
673
+ for (const name of entries.sort()) {
674
+ const full = path.join(dir, name);
675
+ try {
676
+ if (!fs.statSync(full).isDirectory()) continue;
677
+ } catch {
678
+ continue;
679
+ }
680
+ const pageSource = resolveDocsSearchPageSource(full);
681
+ if (pageSource) try {
682
+ const data = matter(fs.readFileSync(pageSource, "utf-8")).data;
683
+ const hiddenFolderIndex = resolvePageSidebarFolderIndexBehavior(data.sidebar) === "hidden";
684
+ if (data.hidden !== true && !hiddenFolderIndex) return true;
685
+ } catch {
686
+ return true;
687
+ }
688
+ if (hasVisibleDescendantDocsSearchPage(full)) return true;
689
+ }
690
+ return false;
691
+ }
692
+ function isHiddenFolderIndexPageDir(dir) {
693
+ const pageSource = resolveDocsSearchPageSource(dir);
694
+ if (!pageSource) return false;
695
+ try {
696
+ const data = matter(fs.readFileSync(pageSource, "utf-8")).data;
697
+ return resolvePageSidebarFolderIndexBehavior(data.sidebar) === "hidden" && hasVisibleDescendantDocsSearchPage(dir);
698
+ } catch {
699
+ return false;
700
+ }
701
+ }
663
702
  function scanDocsDir(docsDir, entry, locale, excludedDirs = []) {
664
703
  const indexes = [];
665
704
  function isExcluded(dir) {
@@ -672,27 +711,29 @@ function scanDocsDir(docsDir, entry, locale, excludedDirs = []) {
672
711
  function scan(dir, slugParts) {
673
712
  if (!fs.existsSync(dir)) return;
674
713
  if (isExcluded(dir)) return;
675
- const pagePath = path.join(dir, "page.mdx");
676
- if (fs.existsSync(pagePath)) try {
677
- const raw = fs.readFileSync(pagePath, "utf-8");
714
+ const pageSource = resolveDocsSearchPageSource(dir);
715
+ if (pageSource) try {
716
+ const raw = fs.readFileSync(pageSource, "utf-8");
678
717
  const { data } = matter(raw);
679
- const title = data.title || slugParts[slugParts.length - 1]?.replace(/-/g, " ") || "Documentation";
680
- const description = data.description;
681
- const { content: fileContent } = matter(raw);
682
- const rawContent = resolveAgentMdxContent(fileContent, "human");
683
- const agentRawContent = resolveAgentMdxContent(fileContent, "agent");
684
- const content = stripMdx(rawContent);
685
- const url = withLangInUrl(slugParts.length === 0 ? `/${entry}` : `/${entry}/${slugParts.join("/")}`, locale);
686
- indexes.push({
687
- title,
688
- description,
689
- relatedInput: data.related,
690
- content,
691
- rawContent,
692
- agentFallbackRawContent: agentRawContent !== rawContent ? agentRawContent : void 0,
693
- url,
694
- locale
695
- });
718
+ if (resolvePageSidebarFolderIndexBehavior(data.sidebar) === "hidden" && hasVisibleDescendantDocsSearchPage(dir)) {} else {
719
+ const title = data.title || slugParts[slugParts.length - 1]?.replace(/-/g, " ") || "Documentation";
720
+ const description = data.description;
721
+ const { content: fileContent } = matter(raw);
722
+ const rawContent = resolveAgentMdxContent(fileContent, "human");
723
+ const agentRawContent = resolveAgentMdxContent(fileContent, "agent");
724
+ const content = stripMdx(rawContent);
725
+ const url = withLangInUrl(slugParts.length === 0 ? `/${entry}` : `/${entry}/${slugParts.join("/")}`, locale);
726
+ indexes.push({
727
+ title,
728
+ description,
729
+ relatedInput: data.related,
730
+ content,
731
+ rawContent,
732
+ agentFallbackRawContent: agentRawContent !== rawContent ? agentRawContent : void 0,
733
+ url,
734
+ locale
735
+ });
736
+ }
696
737
  } catch {}
697
738
  let entries;
698
739
  try {
@@ -1249,11 +1290,14 @@ function createDocsAPI(options) {
1249
1290
  return sources;
1250
1291
  }
1251
1292
  async function getMarkdownDocument(ctx, requestedPath) {
1293
+ const normalizedRequest = normalizeRequestedMarkdownPath(ctx.entryPath, requestedPath);
1294
+ const normalizedEntry = `/${normalizePathSegment(ctx.entryPath)}`;
1295
+ const relativeSlug = normalizedRequest === normalizedEntry ? "" : normalizedRequest.slice(normalizedEntry.length).replace(/^\/+/, "");
1296
+ for (const docsDir of ctx.docsDirs) if (isHiddenFolderIndexPageDir(relativeSlug ? path.join(docsDir, ...relativeSlug.split("/")) : docsDir)) return null;
1252
1297
  for (const source of getMarkdownSources(ctx)) {
1253
1298
  const page = findDocsMcpPage(ctx.entryPath, await source.getPages(), requestedPath);
1254
1299
  if (page) return renderMarkdownDocument(page);
1255
1300
  }
1256
- const normalizedRequest = normalizeRequestedMarkdownPath(ctx.entryPath, requestedPath);
1257
1301
  const fallbackPage = getIndexes(ctx).find((page) => normalizeUrlPath(page.url) === normalizedRequest);
1258
1302
  if (fallbackPage) return renderMarkdownDocument(fallbackPage);
1259
1303
  for (const page of getIndexes(ctx)) if (normalizePathSegment(page.url.replace(/^\/+/, "").replace(`${ctx.entryPath}/`, "")) === normalizePathSegment(requestedPath.replace(/^\/+/, "").replace(/\.md$/i, ""))) return renderMarkdownDocument(page);
@@ -152,7 +152,7 @@ function buildTree(config, ctx, flat = false) {
152
152
  const excludedDirs = getExcludedDocsDirs(config, ctx);
153
153
  if (fs.existsSync(path.join(docsDir, "page.mdx"))) {
154
154
  const data = readFrontmatter(path.join(docsDir, "page.mdx"));
155
- rootChildren.push({
155
+ if (data.hidden !== true) rootChildren.push({
156
156
  type: "page",
157
157
  name: data.title ?? "Documentation",
158
158
  url: `/${ctx.entryPath}`,
@@ -170,7 +170,21 @@ function buildTree(config, ctx, flat = false) {
170
170
  const url = `/${ctx.entryPath}/${slug.join("/")}`;
171
171
  const icon = resolveIcon(data.icon, icons);
172
172
  const displayName = data.title ?? name.replace(/-/g, " ");
173
- if (hasChildPages(full, excludedDirs)) {
173
+ const hasChildren = hasChildPages(full, excludedDirs);
174
+ if (data.hidden === true) {
175
+ if (!hasChildren) return null;
176
+ return {
177
+ type: "folder",
178
+ name: displayName,
179
+ icon,
180
+ children: scanDir(full, slug, slugOrder),
181
+ ...flat ? {
182
+ collapsible: false,
183
+ defaultOpen: true
184
+ } : {}
185
+ };
186
+ }
187
+ if (hasChildren) {
174
188
  const folderChildren = scanDir(full, slug, slugOrder);
175
189
  return {
176
190
  type: "folder",
@@ -14,7 +14,7 @@ interface FolderNode {
14
14
  name: string;
15
15
  icon?: ReactNode;
16
16
  index?: PageNode;
17
- folderIndexBehavior?: "link" | "toggle";
17
+ folderIndexBehavior?: "link" | "toggle" | "hidden";
18
18
  children: (PageNode | FolderNode)[];
19
19
  collapsible?: boolean;
20
20
  defaultOpen?: boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@farming-labs/theme",
3
- "version": "0.1.69",
3
+ "version": "0.1.71",
4
4
  "description": "Theme package for @farming-labs/docs — layout, provider, MDX components, and styles",
5
5
  "keywords": [
6
6
  "docs",
@@ -139,7 +139,7 @@
139
139
  "tsdown": "^0.20.3",
140
140
  "typescript": "^5.9.3",
141
141
  "vitest": "^3.2.4",
142
- "@farming-labs/docs": "0.1.69"
142
+ "@farming-labs/docs": "0.1.71"
143
143
  },
144
144
  "peerDependencies": {
145
145
  "@farming-labs/docs": ">=0.0.1",