bejamas 0.2.3 → 0.2.5

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.
@@ -1,4 +1,4 @@
1
- import { a as extractComponentTagsFromMDX, b as logger, c as extractPropsFromDeclaredProps, d as parseJsDocMetadata, f as resolveOutDir, g as getConfig, h as toIdentifier, i as discoverExamples, l as normalizeBlockMDX, m as slugify, n as createSourceFileFromFrontmatter, o as extractFrontmatter, p as resolveUiRoot, r as detectHasImportTopLevel, s as extractPropsFromAstroProps, t as RESERVED_COMPONENTS, u as normalizeUsageMDX, y as spinner } from "./utils-BXyPCddm.js";
1
+ import { a as extractComponentTagsFromMDX, b as logger, c as extractPropsFromDeclaredProps, d as parseJsDocMetadata, f as resolveOutDir, g as getConfig, h as toIdentifier, i as discoverExamples, l as normalizeBlockMDX, m as slugify, n as createSourceFileFromFrontmatter, o as extractFrontmatter, p as resolveUiRoot, r as detectHasImportTopLevel, s as extractPropsFromAstroProps, t as RESERVED_COMPONENTS, u as normalizeUsageMDX, y as spinner } from "./utils-YFyZFTwZ.js";
2
2
  import { createRequire } from "node:module";
3
3
  import { dirname, extname, join, relative } from "path";
4
4
  import { existsSync, mkdirSync } from "fs";
@@ -188,7 +188,7 @@ function buildMdx(params) {
188
188
  snippet: lines.slice(snippetStartIdx).join("\n").trim()
189
189
  };
190
190
  };
191
- const primaryExampleSection = primaryExampleMDX && primaryExampleMDX.length ? `<div class="not-content sl-bejamas-component-preview flex justify-center px-10 py-12 border border-border rounded-t-lg min-h-72 items-center [&_input]:max-w-xs">
191
+ const primaryExampleSection = primaryExampleMDX && primaryExampleMDX.length ? `<div class="not-content sl-bejamas-component-preview flex justify-center px-4 md:px-10 py-12 border border-border rounded-t-lg min-h-72 items-center [&_input]:max-w-xs">
192
192
  ${toMdxPreview(primaryExampleMDX)}
193
193
  </div>
194
194
 
@@ -210,7 +210,7 @@ ${descriptionMD}`.trim());
210
210
  }
211
211
  exampleSections.push(`### ${blk.title}
212
212
 
213
- ${descriptionMD ? `${descriptionMD}\n\n` : ""}<div class="not-content sl-bejamas-component-preview flex justify-center px-10 py-12 border border-border rounded-t-lg min-h-72 items-center [&_input]:max-w-xs">
213
+ ${descriptionMD ? `${descriptionMD}\n\n` : ""}<div class="not-content sl-bejamas-component-preview flex justify-center px-4 md:px-10 py-12 border border-border rounded-t-lg min-h-72 items-center [&_input]:max-w-xs">
214
214
  ${previewBody}
215
215
  </div>
216
216
 
@@ -526,4 +526,4 @@ if (process.env.BEJAMAS_SKIP_AUTO_RUN !== "1" && process.env.BEJAMAS_SKIP_AUTO_R
526
526
 
527
527
  //#endregion
528
528
  export { parseExamplesBlocks, runDocsGenerator };
529
- //# sourceMappingURL=generate-mdx-2KXXUsF1.js.map
529
+ //# sourceMappingURL=generate-mdx-QQQyHF4o.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-mdx-QQQyHF4o.js","names":["path","lines: string[]","mainImportLine: string | null","m: RegExpExecArray | null","external: string[]","internal: string[]","exampleSections: string[]","entries: ComponentEntry[]","exports: string[]","match: RegExpExecArray | null","exampleRelPaths: string[]","examples: Array<{\n importName: string;\n importPath: string;\n title: string;\n source: string;\n }>","blocks: Array<{ title: string; body: string[] }>","current: { title: string; body: string[] }"],"sources":["../src/docs/generate-mdx/mdx-builder.ts","../src/docs/generate-mdx/index.ts"],"sourcesContent":["/**\n * Check if an import path uses the new barrel export pattern (no .astro extension)\n */\nfunction isBarrelImport(path: string): boolean {\n return !path.endsWith(\".astro\");\n}\n\n/**\n * Convert a PascalCase component name to its folder path (kebab-case).\n * Examples:\n * - \"Card\" → \"card\"\n * - \"CardHeader\" → \"card\"\n * - \"InputGroup\" → \"input-group\"\n * - \"InputGroupAddon\" → \"input-group\"\n * - \"StickySurface\" → \"sticky-surface\"\n * - \"RadioGroup\" → \"radio-group\"\n * - \"RadioGroupItem\" → \"radio-group\"\n */\nfunction componentToFolder(name: string): string {\n // Known multi-word component families (in PascalCase order)\n // These map to kebab-case folder names\n const multiWordFamilies = [\n \"InputGroup\",\n \"LinkGroup\",\n \"RadioGroup\",\n \"ButtonGroup\",\n \"StickySurface\",\n ];\n\n // Check for multi-word families first (order matters - longer matches first)\n const sortedFamilies = multiWordFamilies.sort((a, b) => b.length - a.length);\n for (const family of sortedFamilies) {\n if (name === family || name.startsWith(family)) {\n // InputGroup → input-group\n return family.replace(/([a-z])([A-Z])/g, \"$1-$2\").toLowerCase();\n }\n }\n\n // For regular names, extract the base component (first PascalCase word)\n // CardHeader → Card → card\n // AvatarFallback → Avatar → avatar\n const baseMatch = name.match(/^[A-Z][a-z]*/);\n return baseMatch ? baseMatch[0].toLowerCase() : name.toLowerCase();\n}\n\n/**\n * Group component names by their folder path\n */\nfunction groupComponentsByFolder(components: string[]): Map<string, string[]> {\n const groups = new Map<string, string[]>();\n for (const comp of components) {\n const folder = componentToFolder(comp);\n if (!groups.has(folder)) {\n groups.set(folder, []);\n }\n groups.get(folder)!.push(comp);\n }\n return groups;\n}\n\n/**\n * Generate import lines for UI components using the barrel import pattern\n */\nfunction generateBarrelImports(\n components: string[],\n componentsAlias: string,\n): string[] {\n const groups = groupComponentsByFolder(components);\n const lines: string[] = [];\n\n // Sort folders alphabetically for consistent output\n const sortedFolders = Array.from(groups.keys()).sort();\n\n for (const folder of sortedFolders) {\n const names = groups.get(folder)!.sort();\n lines.push(\n `import { ${names.join(\", \")} } from '${componentsAlias}/${folder}';`,\n );\n }\n\n return lines;\n}\n\n/**\n * Generate import lines for UI components using the old default import pattern\n */\nfunction generateDefaultImports(\n components: string[],\n componentsAlias: string,\n): string[] {\n return components\n .slice()\n .sort()\n .map((name) => `import ${name} from '${componentsAlias}/${name}.astro';`);\n}\n\nexport function buildMdx(params: {\n importName: string;\n importPath: string;\n title: string;\n description: string;\n descriptionBodyMDX?: string;\n figmaUrl?: string;\n usageMDX: string;\n hasImport: boolean;\n propsList: string;\n propsTable?: Array<{\n name: string;\n type?: string;\n required?: boolean;\n defaultValue?: string | null;\n description?: string | null;\n }>;\n examples: Array<{\n importName: string;\n importPath: string;\n title: string;\n source: string;\n }>;\n examplesBlocks: Array<{ title: string; body: string }>;\n autoImports: string[];\n lucideIcons: string[];\n primaryExampleMDX: string;\n componentSource: string;\n commandName: string;\n componentsAlias: string;\n /**\n * Optional: additional named exports from the main component's barrel.\n * Used when the main component has subcomponents (e.g., Card, CardHeader, CardTitle).\n * If provided, these will be included in the main import statement.\n */\n namedExports?: string[];\n}): string {\n const {\n importName,\n importPath,\n title,\n description,\n descriptionBodyMDX,\n usageMDX,\n hasImport,\n propsList,\n propsTable,\n examples,\n examplesBlocks,\n autoImports,\n lucideIcons,\n primaryExampleMDX,\n componentSource,\n commandName,\n figmaUrl,\n componentsAlias,\n namedExports,\n } = params;\n\n // Detect if we should use the new barrel import pattern\n const useBarrelPattern = isBarrelImport(importPath);\n\n const sortedLucide = (lucideIcons ?? []).slice().sort();\n const lucideTopLine = sortedLucide.length\n ? `import { ${sortedLucide.join(\", \")} } from '@lucide/astro';`\n : null;\n const externalTopImports = [\n `import { Tabs as DocsTabs, TabItem as DocsTabItem } from '@astrojs/starlight/components';`,\n lucideTopLine,\n ]\n .filter((v) => v != null)\n .slice()\n .sort((a, b) => String(a).localeCompare(String(b)));\n\n const sortedUiAuto = (autoImports ?? []).slice().sort();\n\n // Generate UI component imports based on pattern\n const uiAutoLines = useBarrelPattern\n ? generateBarrelImports(sortedUiAuto, componentsAlias)\n : generateDefaultImports(sortedUiAuto, componentsAlias);\n\n const exampleLines = (examples ?? [])\n .map((ex) => `import ${ex.importName} from '${ex.importPath}';`)\n .sort((a, b) => a.localeCompare(b));\n\n // Build main component import\n let mainImportLine: string | null = null;\n if (!hasImport) {\n if (useBarrelPattern) {\n // New pattern: named exports\n const exports = [importName, ...(namedExports ?? [])].sort();\n mainImportLine = `import { ${exports.join(\", \")} } from '${importPath}';`;\n } else {\n // Old pattern: default export\n mainImportLine = `import ${importName} from '${importPath}';`;\n }\n }\n\n const internalTopImports = [mainImportLine, ...uiAutoLines, ...exampleLines]\n .filter((v) => v != null)\n .slice()\n .sort((a, b) => String(a).localeCompare(String(b)));\n\n const importLines = [\n ...externalTopImports,\n externalTopImports.length && internalTopImports.length ? \"\" : null,\n ...internalTopImports,\n ].filter((v) => v !== null && v !== undefined);\n\n // Helper: build per-snippet imports so code fences are minimal and copy-pasteable\n const extractTags = (snippet: string): Set<string> => {\n const found = new Set<string>();\n const tagRegex = /<([A-Z][A-Za-z0-9_]*)\\b/g;\n let m: RegExpExecArray | null;\n while ((m = tagRegex.exec(snippet)) !== null) {\n found.add(m[1]);\n }\n return found;\n };\n\n const buildSnippetImportLines = (snippet: string): string[] => {\n if (!snippet || !snippet.length) return [];\n const used = extractTags(snippet);\n const usedIcons = sortedLucide.filter((n) => used.has(n));\n\n // Find UI components used in snippet\n const usedUi = (autoImports ?? []).filter((n) => used.has(n));\n\n // Check if main component (and its subcomponents) are used\n const includeMain = !hasImport && used.has(importName);\n\n // For new pattern, also check for subcomponents from the main barrel\n const usedNamedExports =\n useBarrelPattern && namedExports\n ? namedExports.filter((n) => used.has(n))\n : [];\n\n const external: string[] = [];\n if (usedIcons.length) {\n external.push(`import { ${usedIcons.join(\", \")} } from '@lucide/astro';`);\n }\n\n const internal: string[] = [];\n\n if (useBarrelPattern) {\n // New pattern: group by folder and use named imports\n\n // Main component and its subcomponents\n if (includeMain || usedNamedExports.length > 0) {\n const mainExports = [\n ...(includeMain ? [importName] : []),\n ...usedNamedExports,\n ].sort();\n internal.push(\n `import { ${mainExports.join(\", \")} } from '${importPath}';`,\n );\n }\n\n // Other UI components grouped by folder\n if (usedUi.length > 0) {\n internal.push(...generateBarrelImports(usedUi, componentsAlias));\n }\n } else {\n // Old pattern: default imports\n if (includeMain) {\n internal.push(`import ${importName} from '${importPath}';`);\n }\n internal.push(\n ...usedUi\n .slice()\n .sort()\n .map(\n (name) => `import ${name} from '${componentsAlias}/${name}.astro';`,\n ),\n );\n }\n\n const externalSorted = external.slice().sort((a, b) => a.localeCompare(b));\n const internalSorted = internal.slice().sort((a, b) => a.localeCompare(b));\n return [\n ...externalSorted,\n externalSorted.length && internalSorted.length ? \"\" : null,\n ...internalSorted,\n ].filter((v) => v !== null && v !== undefined) as string[];\n };\n\n const wrapTextNodes = (snippet: string): string => {\n if (!snippet) return snippet;\n return snippet.replace(/>([^<]+)</g, (match, inner) => {\n const trimmed = inner.trim();\n if (!trimmed.length) return match;\n // Skip if the entire trimmed content is a JSX expression\n if (/^\\{[\\s\\S]*\\}$/.test(trimmed)) return match;\n // Skip if the content already contains JSX expressions (e.g., \"Use{\\\" \\\"}\" or mixed content)\n // This prevents double-wrapping and breaking inline JSX whitespace expressions\n if (/\\{[^}]*\\}/.test(inner)) return match;\n return `>{${JSON.stringify(inner)}}<`;\n });\n };\n\n /**\n * Normalize whitespace in preview content.\n * This collapses ALL newlines and multiple spaces into single spaces to prevent\n * MDX parsing issues. In particular, a '>' at the start of a line is interpreted\n * as a block quote marker by MDX, which causes \"Unexpected lazy line\" errors.\n */\n const normalizeInlineWhitespace = (snippet: string): string => {\n if (!snippet) return snippet;\n // Collapse ALL newlines and multiple whitespace into single spaces\n // This prevents MDX from interpreting '>' at start of line as block quote\n return snippet.replace(/\\s+/g, \" \").trim();\n };\n\n /**\n * Convert <p> tags that contain component tags to <span> tags.\n * This is necessary because components may render as block elements (like <div>),\n * and HTML doesn't allow block elements inside <p>. The browser would automatically\n * close the <p> before any block element, breaking the layout.\n */\n const convertParagraphsWithComponents = (snippet: string): string => {\n if (!snippet) return snippet;\n // Detect if a <p> tag contains component tags (PascalCase like <KbdGroup>)\n // If so, convert <p> to <span> to allow block-level children\n return snippet.replace(\n /<p(\\s[^>]*)?>([^]*?)<\\/p>/gi,\n (match, attrs, content) => {\n // Check if content contains component tags (PascalCase)\n if (/<[A-Z][A-Za-z0-9]*/.test(content)) {\n // Convert to span with inline-block display to preserve paragraph-like behavior\n const spanAttrs = attrs || \"\";\n return `<span${spanAttrs} style=\"display:block\">${content}</span>`;\n }\n return match;\n },\n );\n };\n\n const toMdxPreview = (snippet: string): string => {\n if (!snippet) return snippet;\n // Convert HTML comments to MDX comment blocks for preview sections\n const withoutComments = snippet.replace(/<!--([\\s\\S]*?)-->/g, \"{/*$1*/}\");\n // Convert <p> tags containing components to <span> to avoid HTML validity issues\n const withConvertedParagraphs =\n convertParagraphsWithComponents(withoutComments);\n // If the snippet contains user-defined <p> elements, preserve structure as-is\n if (/<p[\\s>]/i.test(withConvertedParagraphs)) {\n return normalizeInlineWhitespace(withConvertedParagraphs);\n }\n // Normalize whitespace to prevent MDX from splitting inline text into paragraphs\n const normalized = normalizeInlineWhitespace(withConvertedParagraphs);\n return wrapTextNodes(normalized);\n };\n\n // Split an example body into leading markdown description (paragraphs)\n // and the Astro/HTML snippet that should be rendered in Preview/Source tabs\n const splitDescriptionAndSnippet = (\n body: string,\n ): { descriptionMD: string; snippet: string } => {\n if (!body || !body.trim().length) return { descriptionMD: \"\", snippet: \"\" };\n const lines = body.split(\"\\n\");\n let snippetStartIdx = -1;\n for (let i = 0; i < lines.length; i++) {\n const ln = lines[i];\n // Skip empty lines before first meaningful content\n if (!ln.trim().length) continue;\n // Heuristic: consider this line the start of the snippet if it looks like Astro/HTML/JSX\n // e.g. starts with '<' or '{'\n if (/^\\s*[<{]/.test(ln)) {\n snippetStartIdx = i;\n break;\n }\n // Otherwise it's part of markdown description; keep looking until we hit markup\n }\n if (snippetStartIdx <= 0) {\n // No clear description or snippet starts at the very beginning → treat all as snippet\n return { descriptionMD: \"\", snippet: body.trim() };\n }\n const descriptionMD = lines.slice(0, snippetStartIdx).join(\"\\n\").trim();\n const snippet = lines.slice(snippetStartIdx).join(\"\\n\").trim();\n return { descriptionMD, snippet };\n };\n\n const primaryExampleSection =\n primaryExampleMDX && primaryExampleMDX.length\n ? `<div class=\"not-content sl-bejamas-component-preview flex justify-center px-4 md:px-10 py-12 border border-border rounded-t-lg min-h-72 items-center [&_input]:max-w-xs\">\n${toMdxPreview(primaryExampleMDX)}\n</div>\n\n\\`\\`\\`astro\n${(() => {\n const lines = buildSnippetImportLines(primaryExampleMDX);\n return lines.length ? `---\\n${lines.join(\"\\n\")}\\n---\\n\\n` : \"\";\n})()}${primaryExampleMDX}\n\\`\\`\\``\n : null;\n\n const exampleSections: string[] = [];\n if (examplesBlocks && examplesBlocks.length) {\n for (const blk of examplesBlocks) {\n const { descriptionMD, snippet } = splitDescriptionAndSnippet(blk.body);\n const previewBody = toMdxPreview(snippet);\n\n // If there's no snippet, render only header + description\n if (!snippet || !snippet.length) {\n exampleSections.push(\n `### ${blk.title}\n\n${descriptionMD}`.trim(),\n );\n continue;\n }\n\n exampleSections.push(\n `### ${blk.title}\n\n${descriptionMD ? `${descriptionMD}\\n\\n` : \"\"}<div class=\"not-content sl-bejamas-component-preview flex justify-center px-4 md:px-10 py-12 border border-border rounded-t-lg min-h-72 items-center [&_input]:max-w-xs\">\n${previewBody}\n</div>\n\n\\`\\`\\`astro\n${(() => {\n const lines = buildSnippetImportLines(snippet);\n return lines.length ? `---\\n${lines.join(\"\\n\")}\\n---\\n\\n` : \"\";\n})()}${snippet}\n\\`\\`\\``,\n );\n }\n }\n if (examples && examples.length) {\n for (const ex of examples) {\n exampleSections.push(\n `### ${ex.title}\n\n<div class=\"not-content\">\n <${ex.importName} />\n</div>\n\n\\`\\`\\`astro\n${ex.source}\n\\`\\`\\``,\n );\n }\n }\n\n const formatDefault = (val: unknown): string => {\n if (val == null) return \"\";\n let raw = String(val).trim();\n if (!raw.length) return \"\";\n // Normalize curly quotes to ASCII\n raw = raw\n .replace(/[\\u201C\\u201D\\u201E\\u201F]/g, '\"')\n .replace(/[\\u2018\\u2019]/g, \"'\");\n const isSingleQuoted = /^'[^']*'$/.test(raw);\n const isDoubleQuoted = /^\"[^\"]*\"$/.test(raw);\n const isBacktickSimple = /^`[^`]*`$/.test(raw) && raw.indexOf(\"${\") === -1;\n\n let content = raw;\n if (isSingleQuoted || isDoubleQuoted || isBacktickSimple) {\n const inner = raw.slice(1, -1);\n // Re-quote with standard double quotes\n content = `\"${inner}\"`;\n }\n // Escape table pipes\n content = content.replace(/\\|/g, \"\\\\|\");\n // Choose a backtick fence that doesn't appear in content\n const hasTick = content.includes(\"`\");\n const hasDoubleTick = content.includes(\"``\");\n const fence = !hasTick ? \"`\" : !hasDoubleTick ? \"``\" : \"```\";\n return `${fence}${content}${fence}`;\n };\n\n const installationSection = `## Installation\n\n<DocsTabs syncKey=\"pkg\">\n <DocsTabItem label=\"bun\">\n \\`\\`\\`bash\n bunx bejamas add ${commandName}\n \\`\\`\\`\n </DocsTabItem>\n <DocsTabItem label=\"npm\">\n \\`\\`\\`bash\n npx bejamas add ${commandName}\n \\`\\`\\`\n </DocsTabItem>\n <DocsTabItem label=\"pnpm\">\n \\`\\`\\`bash\n pnpm dlx bejamas add ${commandName}\n \\`\\`\\`\n </DocsTabItem>\n <DocsTabItem label=\"yarn\">\n \\`\\`\\`bash\n yarn dlx bejamas add ${commandName}\n \\`\\`\\`\n </DocsTabItem>\n</DocsTabs>`;\n\n const serializeFrontmatter = (\n label: string,\n value?: string,\n ): string | null => {\n if (!value || !value.length) return null;\n return `${label}: ${JSON.stringify(value)}`;\n };\n\n const lines = [\n \"---\",\n serializeFrontmatter(\"title\", title),\n serializeFrontmatter(\"description\", description),\n serializeFrontmatter(\"figmaUrl\", figmaUrl),\n \"---\",\n \"\",\n ...importLines,\n importLines.length ? \"\" : null,\n descriptionBodyMDX && descriptionBodyMDX.length ? descriptionBodyMDX : null,\n descriptionBodyMDX && descriptionBodyMDX.length ? \"\" : null,\n primaryExampleSection,\n primaryExampleSection ? \"\" : null,\n installationSection,\n \"\",\n usageMDX && usageMDX.length ? `## Usage\\n\\n${usageMDX}` : null,\n \"\",\n propsTable && propsTable.length\n ? `## Props\\n\\n| Prop | Type | Default |\\n|---|---|---|\\n${propsTable\n .map(\n (p) =>\n `| <code>${p.name}</code> | \\`${(p.type || \"\").replace(/\\|/g, \"\\\\|\")}\\` | ${formatDefault(p.defaultValue)} |`,\n )\n .join(\"\\n\")}`\n : propsList\n ? `## Props\\n\\n${propsList}`\n : null,\n (propsTable && propsTable.length) || propsList ? \"\" : null,\n exampleSections.length\n ? `## Examples\\n\\n` + exampleSections.join(\"\\n\\n\")\n : null,\n ].filter((v) => v !== null && v !== undefined);\n\n return lines.join(\"\\n\").trim() + \"\\n\";\n}\n","import { mkdirSync, existsSync } from \"fs\";\nimport { readdir, readFile, writeFile } from \"fs/promises\";\nimport { join, extname, dirname, relative, basename } from \"path\";\nimport {\n RESERVED_COMPONENTS,\n slugify,\n extractFrontmatter,\n toIdentifier,\n parseJsDocMetadata,\n extractPropsFromAstroProps,\n extractPropsFromDeclaredProps,\n resolveUiRoot,\n resolveOutDir,\n normalizeUsageMDX,\n normalizeBlockMDX,\n detectHasImportTopLevel,\n discoverExamples,\n extractComponentTagsFromMDX,\n createSourceFileFromFrontmatter,\n} from \"./utils\";\nimport { buildMdx } from \"./mdx-builder\";\nimport { logger } from \"@/src/utils/logger\";\nimport { spinner } from \"@/src/utils/spinner\";\nimport { getConfig } from \"@/src/utils/get-config\";\n\ninterface ComponentEntry {\n /** The main component name (PascalCase), e.g., \"Card\" */\n name: string;\n /** Path to the main .astro file */\n filePath: string;\n /** The folder name (lowercase/kebab-case), e.g., \"card\" */\n folderName: string;\n /** Whether this is a folder-based component with barrel exports */\n isFolder: boolean;\n /** List of subcomponent names exported from the barrel, e.g., [\"CardHeader\", \"CardTitle\"] */\n namedExports: string[];\n}\n\n/**\n * Discover components in the components directory.\n * Supports both:\n * - Old pattern: flat .astro files in components/\n * - New pattern: folders with index.ts barrel exports\n */\nasync function discoverComponents(\n componentsDir: string,\n): Promise<ComponentEntry[]> {\n const entries: ComponentEntry[] = [];\n const dirEntries = await readdir(componentsDir, { withFileTypes: true });\n\n for (const entry of dirEntries) {\n if (entry.isDirectory()) {\n // New pattern: folder with barrel exports\n const folderPath = join(componentsDir, entry.name);\n const indexPath = join(folderPath, \"index.ts\");\n\n if (existsSync(indexPath)) {\n // Parse the barrel file to find exports\n const indexContent = await readFile(indexPath, \"utf-8\");\n const namedExports = parseBarrelExports(indexContent);\n\n // Find the main component (first export or the one matching folder name)\n const mainComponentName = findMainComponent(namedExports, entry.name);\n\n if (mainComponentName) {\n const mainFilePath = join(folderPath, `${mainComponentName}.astro`);\n\n if (existsSync(mainFilePath)) {\n // Filter out the main component from namedExports (it will be imported separately)\n const subComponents = namedExports.filter(\n (n) => n !== mainComponentName,\n );\n\n entries.push({\n name: mainComponentName,\n filePath: mainFilePath,\n folderName: entry.name,\n isFolder: true,\n namedExports: subComponents,\n });\n }\n }\n }\n } else if (entry.isFile() && extname(entry.name).toLowerCase() === \".astro\") {\n // Old pattern: flat .astro file\n const componentName = entry.name.replace(/\\.astro$/i, \"\");\n entries.push({\n name: componentName,\n filePath: join(componentsDir, entry.name),\n folderName: \"\",\n isFolder: false,\n namedExports: [],\n });\n }\n }\n\n return entries;\n}\n\n/**\n * Parse a barrel (index.ts) file to extract named exports.\n * Handles patterns like:\n * - export { default as Card } from \"./Card.astro\";\n * - export { default as CardHeader } from \"./CardHeader.astro\";\n */\nfunction parseBarrelExports(content: string): string[] {\n const exports: string[] = [];\n\n // Match: export { default as ComponentName } from \"...\"\n const exportRegex = /export\\s*\\{\\s*default\\s+as\\s+(\\w+)\\s*\\}/g;\n let match: RegExpExecArray | null;\n\n while ((match = exportRegex.exec(content)) !== null) {\n exports.push(match[1]);\n }\n\n return exports;\n}\n\n/**\n * Find the main component from a list of exports.\n * The main component is typically the one that matches the folder name (PascalCase).\n */\nfunction findMainComponent(\n exports: string[],\n folderName: string,\n): string | null {\n if (exports.length === 0) return null;\n\n // Convert folder name to PascalCase for comparison\n // e.g., \"card\" -> \"Card\", \"input-group\" -> \"InputGroup\"\n const expectedName = folderName\n .split(\"-\")\n .map((part) => part.charAt(0).toUpperCase() + part.slice(1))\n .join(\"\");\n\n // First, try to find exact match\n const exactMatch = exports.find((e) => e === expectedName);\n if (exactMatch) return exactMatch;\n\n // Otherwise, return the first export (usually the main component)\n return exports[0];\n}\n\nasync function main() {\n const DEBUG =\n process.env.BEJAMAS_DEBUG === \"1\" || process.env.BEJAMAS_DEBUG === \"true\";\n const cwd =\n process.env.BEJAMAS_DOCS_CWD && process.env.BEJAMAS_DOCS_CWD.length\n ? (process.env.BEJAMAS_DOCS_CWD as string)\n : process.cwd();\n const config = await getConfig(cwd);\n const componentsAlias = (\n config?.aliases?.ui ||\n config?.aliases?.components ||\n \"@bejamas/ui/components\"\n ).replace(/\\/$/, \"\");\n const componentsDirFromConfig =\n config?.resolvedPaths?.ui || config?.resolvedPaths?.components;\n let uiRoot = resolveUiRoot(cwd);\n let componentsDir = join(uiRoot, \"src\", \"components\");\n if (componentsDirFromConfig) {\n componentsDir = componentsDirFromConfig;\n uiRoot = dirname(dirname(componentsDirFromConfig));\n }\n if (!existsSync(componentsDir)) {\n // Fallback to ui package components if the configured path is missing.\n componentsDir = join(uiRoot, \"src\", \"components\");\n }\n const outDir = resolveOutDir(cwd);\n mkdirSync(outDir, { recursive: true });\n\n if (DEBUG) {\n logger.info(`[docs-generator] cwd: ${cwd}`);\n logger.info(`[docs-generator] uiRoot: ${uiRoot}`);\n logger.info(`[docs-generator] componentsDir: ${componentsDir}`);\n logger.info(`[docs-generator] outDir: ${outDir}`);\n }\n\n // Discover all components (both flat files and folders)\n const components = await discoverComponents(componentsDir);\n\n if (DEBUG) {\n logger.info(`[docs-generator] components found: ${components.length}`);\n if (components.length) {\n logger.info(\n `[docs-generator] first few: ${components\n .slice(0, 5)\n .map((c) => c.name)\n .join(\", \")}`,\n );\n }\n }\n\n let generatedCount = 0;\n const total = components.length;\n const spin = spinner(`Generating docs (0/${total})`).start();\n\n for (const component of components) {\n const { name: pascal, filePath, folderName, isFolder, namedExports } = component;\n\n const astroFile = await readFile(filePath, \"utf-8\");\n const frontmatterCode = extractFrontmatter(astroFile);\n const sourceFile = createSourceFileFromFrontmatter(frontmatterCode);\n const meta = parseJsDocMetadata(frontmatterCode);\n const declaredProps = extractPropsFromDeclaredProps(sourceFile);\n const destructuredProps = extractPropsFromAstroProps(sourceFile);\n\n // Build props table preferring declared types; merge defaults from destructuring\n const defaultsMap = new Map<string, string | null>();\n for (const p of destructuredProps) {\n if (p.name && p.hasDefault) {\n defaultsMap.set(p.name, p.defaultValue || null);\n }\n }\n\n const propsTable = (declaredProps.length ? declaredProps : []).map((p) => ({\n name: p.name,\n type: p.type,\n required: !p.optional,\n defaultValue: defaultsMap.has(p.name) ? defaultsMap.get(p.name)! : null,\n }));\n\n const slug = slugify(pascal);\n const title = meta.title || meta.name || pascal;\n const description = meta.description || \"\";\n const descriptionBodyMDX = (meta as any).descriptionBodyMDX || \"\";\n const figmaUrl = (meta as any).figmaUrl || \"\";\n // Do not display props if there is no declared Props\n const propsList = \"\";\n\n const importName = pascal;\n // Use folder-based barrel import for new pattern, file-based for old pattern\n const importPath = isFolder\n ? `${componentsAlias}/${folderName}`\n : `${componentsAlias}/${pascal}.astro`;\n\n const { text: usageMDX, hasImport: hasImportUsage } = normalizeUsageMDX(\n meta.usageMDX || \"\",\n pascal,\n );\n const primaryExampleMDX = normalizeBlockMDX(\n meta.primaryExampleMDX || \"\",\n ).trim();\n const examplesMDX = normalizeBlockMDX(meta.examplesMDX || \"\").trim();\n const hasImportExamples = detectHasImportTopLevel(examplesMDX, pascal);\n const hasImportPrimary = detectHasImportTopLevel(primaryExampleMDX, pascal);\n const hasImport = hasImportUsage || hasImportExamples || hasImportPrimary;\n\n let exampleRelPaths: string[] = [];\n let examples: Array<{\n importName: string;\n importPath: string;\n title: string;\n source: string;\n }> = [];\n const examplesBlocksRaw = examplesMDX;\n const examplesBlocks = parseExamplesBlocks(examplesBlocksRaw);\n if (examplesBlocks.length === 0) {\n exampleRelPaths = await discoverExamples(filePath, componentsDir);\n examples = (exampleRelPaths || []).map((rel) => {\n const posixRel = rel\n .split(require(\"path\").sep)\n .join(require(\"path\").posix.sep);\n const importPathEx = `${componentsAlias}/${posixRel}`;\n const abs = join(componentsDir, rel);\n const source = require(\"fs\").readFileSync(abs, \"utf-8\");\n const base = toIdentifier(\n require(\"path\").basename(rel, require(\"path\").extname(rel)),\n );\n const importNameEx = `${pascal}${base}`;\n const titleEx = base;\n return { importName: importNameEx, importPath: importPathEx, title: titleEx, source };\n });\n }\n\n const usedInUsage = extractComponentTagsFromMDX(usageMDX).filter(\n (n) => n !== pascal,\n );\n const usedInExamples = extractComponentTagsFromMDX(examplesMDX).filter(\n (n) => n !== pascal,\n );\n const usedInPrimary = extractComponentTagsFromMDX(primaryExampleMDX).filter(\n (n) => n !== pascal,\n );\n const autoSet = new Set<string>([\n ...usedInUsage,\n ...usedInExamples,\n ...usedInPrimary,\n ]);\n\n // For folder-based components, add subcomponents used in examples to namedExports\n const usedNamedExports = isFolder\n ? namedExports.filter((n) => autoSet.has(n))\n : [];\n\n // Remove subcomponents from autoSet (they'll be included via namedExports)\n if (isFolder) {\n for (const n of namedExports) {\n autoSet.delete(n);\n }\n }\n\n const autoImports = Array.from(autoSet)\n .filter((name) => !RESERVED_COMPONENTS.has(name))\n .filter((name) => true);\n\n const lucideIcons = autoImports.filter((n) => /Icon$/.test(n));\n const uiAutoImports = autoImports.filter((n) => !/Icon$/.test(n));\n\n const mdx = buildMdx({\n importName,\n importPath,\n title,\n description,\n usageMDX,\n hasImport,\n propsList,\n propsTable,\n examples,\n examplesBlocks: parseExamplesBlocks(examplesBlocksRaw),\n autoImports: uiAutoImports,\n lucideIcons,\n primaryExampleMDX,\n componentSource: astroFile.trim(),\n commandName: slug,\n figmaUrl,\n descriptionBodyMDX,\n componentsAlias,\n // Pass subcomponents as named exports for folder-based components\n namedExports: isFolder ? usedNamedExports : undefined,\n });\n const outFile = join(outDir, `${slug}.mdx`);\n mkdirSync(dirname(outFile), { recursive: true });\n await writeFile(outFile, mdx, \"utf-8\");\n generatedCount += 1;\n spin.text = `Generating docs (${generatedCount}/${total}) - ${title}`;\n if (DEBUG) logger.info(`Generated ${outFile}`);\n }\n spin.succeed(\n `Created ${generatedCount} file${generatedCount === 1 ? \"\" : \"s\"}:`,\n );\n // log all files with relative paths, sorted alphabetically\n const relPaths = components\n .map((c) => {\n const slug = slugify(c.name);\n const outFile = join(outDir, `${slug}.mdx`);\n return relative(cwd, outFile);\n })\n .sort((a, b) => a.localeCompare(b));\n relPaths.forEach((p) => {\n logger.log(` - ${p}`);\n });\n logger.break();\n}\n\nexport function parseExamplesBlocks(\n examplesMDX: string,\n): Array<{ title: string; body: string }> {\n if (!examplesMDX) return [];\n const lines = examplesMDX.split(\"\\n\");\n const blocks: Array<{ title: string; body: string[] }> = [];\n let current: { title: string; body: string[] } = { title: \"\", body: [] };\n for (const line of lines) {\n const heading = line.match(/^###\\s+(.+)$/);\n if (heading) {\n if (current.title || current.body.length) blocks.push(current);\n current = { title: heading[1].trim(), body: [] };\n continue;\n }\n current.body.push(line);\n }\n if (current.title || current.body.length) blocks.push(current);\n return blocks.map((b, idx) => ({\n title: b.title || `Example ${idx + 1}`,\n body: b.body.join(\"\\n\").trim(),\n }));\n}\n\nexport async function runDocsGenerator(): Promise<void> {\n await main();\n}\n\nif (\n process.env.BEJAMAS_SKIP_AUTO_RUN !== \"1\" &&\n process.env.BEJAMAS_SKIP_AUTO_RUN !== \"true\"\n) {\n runDocsGenerator().catch((err) => {\n logger.error(String(err));\n process.exit(1);\n });\n}\n"],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { S as BASE_COLORS, _ as getWorkspaceConfig, b as logger, d as parseJsDocMetadata, g as getConfig, o as extractFrontmatter, p as resolveUiRoot, v as getProjectInfo, x as highlighter, y as spinner } from "./utils-BXyPCddm.js";
2
+ import { S as BASE_COLORS, _ as getWorkspaceConfig, b as logger, d as parseJsDocMetadata, g as getConfig, o as extractFrontmatter, p as resolveUiRoot, v as getProjectInfo, x as highlighter, y as spinner } from "./utils-YFyZFTwZ.js";
3
3
  import { Command } from "commander";
4
4
  import { createRequire } from "module";
5
5
  import path from "path";
@@ -523,7 +523,7 @@ async function generateDocs({ cwd, outDir, verbose }) {
523
523
  if (process.env.BEJAMAS_DOCS_CWD) logger.info(`Docs CWD: ${process.env.BEJAMAS_DOCS_CWD}`);
524
524
  if (process.env.BEJAMAS_DOCS_OUT_DIR) logger.info(`Docs out: ${process.env.BEJAMAS_DOCS_OUT_DIR}`);
525
525
  }
526
- const mod = await import("./generate-mdx-2KXXUsF1.js");
526
+ const mod = await import("./generate-mdx-QQQyHF4o.js");
527
527
  if (typeof mod.runDocsGenerator === "function") await mod.runDocsGenerator();
528
528
  else throw new Error("Failed to load docs generator. Export 'runDocsGenerator' not found.");
529
529
  } catch (err) {
@@ -997,6 +997,44 @@ function rewritePaths(paths, mapResult) {
997
997
  return filePath;
998
998
  });
999
999
  }
1000
+ /** Fetch available components from the registry */
1001
+ async function fetchAvailableComponents(registryUrl) {
1002
+ const indexUrl = `${registryUrl}/index.json`;
1003
+ const response = await fetch(indexUrl);
1004
+ if (!response.ok) throw new Error(`Failed to fetch registry index: ${response.statusText}`);
1005
+ const data = await response.json();
1006
+ return Array.isArray(data) ? data : [];
1007
+ }
1008
+ /** Prompt user to select components interactively */
1009
+ async function promptForComponents(registryUrl) {
1010
+ const checkingSpinner = spinner("Checking registry.").start();
1011
+ let components;
1012
+ try {
1013
+ components = await fetchAvailableComponents(registryUrl);
1014
+ checkingSpinner.succeed();
1015
+ } catch (error) {
1016
+ checkingSpinner.fail();
1017
+ logger.error("Failed to fetch available components from registry.");
1018
+ return null;
1019
+ }
1020
+ if (components.length === 0) {
1021
+ logger.warn("No components available in registry.");
1022
+ return null;
1023
+ }
1024
+ const { selected } = await prompts({
1025
+ type: "autocompleteMultiselect",
1026
+ name: "selected",
1027
+ message: "Which components would you like to add?",
1028
+ choices: components.filter((c) => !c.type || c.type === "registry:ui").map((c) => ({
1029
+ title: c.name,
1030
+ value: c.name
1031
+ })),
1032
+ hint: "- Space to select. Return to submit.",
1033
+ instructions: false
1034
+ });
1035
+ if (!selected) return null;
1036
+ return selected;
1037
+ }
1000
1038
  /** Parse shadcn output to extract file lists (stdout has paths, stderr has headers) */
1001
1039
  function parseShadcnOutput(stdout, stderr) {
1002
1040
  const result = {
@@ -1094,8 +1132,27 @@ const add = new Command().name("add").description("Add components via shadcn@lat
1094
1132
  const forwardedOptions = extractOptionsForShadcn(process.argv.slice(2), cmd);
1095
1133
  const opts = typeof cmd.optsWithGlobals === "function" ? cmd.optsWithGlobals() : cmd.opts?.() ?? {};
1096
1134
  const cwd = opts.cwd || process.cwd();
1097
- const config = await getConfig(cwd);
1135
+ let componentsToAdd = packages || [];
1136
+ const wantsAll = Boolean(opts.all);
1137
+ const isSilent = opts.silent || false;
1098
1138
  const registryUrl = process.env.REGISTRY_URL || DEFAULT_REGISTRY_URL;
1139
+ if (wantsAll && componentsToAdd.length === 0) {
1140
+ const fetchingSpinner = spinner("Fetching available components.", { silent: isSilent }).start();
1141
+ try {
1142
+ componentsToAdd = (await fetchAvailableComponents(registryUrl)).filter((c) => !c.type || c.type === "registry:ui").map((c) => c.name);
1143
+ fetchingSpinner.succeed();
1144
+ } catch (error) {
1145
+ fetchingSpinner.fail();
1146
+ logger.error("Failed to fetch available components from registry.");
1147
+ process.exit(1);
1148
+ }
1149
+ }
1150
+ if (componentsToAdd.length === 0) {
1151
+ const selected = await promptForComponents(registryUrl);
1152
+ if (!selected || selected.length === 0) return;
1153
+ componentsToAdd = selected;
1154
+ }
1155
+ const config = await getConfig(cwd);
1099
1156
  let uiDir = config?.resolvedPaths?.ui || "";
1100
1157
  let uiConfig = config;
1101
1158
  if (config) {
@@ -1110,8 +1167,6 @@ const add = new Command().name("add").description("Add components via shadcn@lat
1110
1167
  logger.info(`[bejamas-ui] uiDir: ${uiDir}`);
1111
1168
  logger.info(`[bejamas-ui] aliases.ui: ${uiConfig?.aliases?.ui || "not set"}`);
1112
1169
  }
1113
- const isSilent = opts.silent || false;
1114
- const componentsToAdd = packages || [];
1115
1170
  const totalComponents = componentsToAdd.length;
1116
1171
  for (let i = 0; i < componentsToAdd.length; i++) {
1117
1172
  const component = componentsToAdd[i];