bejamas 0.1.1 → 0.2.1

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,282 +1,87 @@
1
- import { getConfig, logger, spinner } from "./get-config-CJUwQ2Xb.js";
1
+ import { RESERVED_COMPONENTS, createSourceFileFromFrontmatter, detectHasImportTopLevel, discoverExamples, extractComponentTagsFromMDX, extractFrontmatter, extractPropsFromAstroProps, extractPropsFromDeclaredProps, getConfig, logger, normalizeBlockMDX, normalizeUsageMDX, parseJsDocMetadata, resolveOutDir, resolveUiRoot, slugify, spinner, toIdentifier } from "./utils-DfvCox_O.js";
2
2
  import { createRequire } from "node:module";
3
- import { createRequire as createRequire$1 } from "module";
4
- import path, { dirname, extname, join, posix, relative } from "path";
3
+ import { dirname, extname, join, relative } from "path";
5
4
  import { existsSync, mkdirSync } from "fs";
6
- import { readdir, writeFile } from "fs/promises";
7
- import { Project, SyntaxKind } from "ts-morph";
5
+ import { readFile, readdir, writeFile } from "fs/promises";
8
6
 
9
7
  //#region rolldown:runtime
10
8
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
11
9
 
12
10
  //#endregion
13
- //#region src/docs/generate-mdx/utils.ts
14
- const RESERVED_COMPONENTS = new Set([
15
- "Fragment",
16
- "CodePackageManagers",
17
- "DocsTabs",
18
- "DocsTabItem",
19
- "DocsCodePackageManagers",
20
- "Tabs",
21
- "TabItem"
22
- ]);
23
- function slugify(input) {
24
- return input.replace(/\.(astro|md|mdx|tsx|ts|jsx|js)$/i, "").replace(/([a-z0-9])([A-Z])/g, "$1-$2").replace(/\s+/g, "-").replace(/_+/g, "-").toLowerCase();
25
- }
26
- function extractFrontmatter(source) {
27
- const match = source.match(/^---\n([\s\S]*?)\n---/);
28
- return match && match[1] || "";
29
- }
30
- function toIdentifier(name) {
31
- const base = name.replace(/\.[^.]+$/, "").replace(/[^a-zA-Z0-9]+/g, " ").trim().replace(/\b\w/g, (c) => c.toUpperCase()).replace(/\s+/g, "");
32
- return /^[A-Za-z_]/.test(base) ? base : `Ex${base}`;
33
- }
34
- function parseJsDocMetadata(frontmatterCode) {
35
- const jsDocMatch = frontmatterCode.match(/\/\*\*([\s\S]*?)\*\//);
36
- if (!jsDocMatch) return {};
37
- const lines = jsDocMatch[1].split("\n").map((l) => l.replace(/^\s*\*\s?/, ""));
38
- const meta = {};
39
- let inUsage = false;
40
- let inExamples = false;
41
- let inPrimaryExample = false;
42
- let captureDescriptionBody = false;
43
- const usageLines = [];
44
- const examplesLines = [];
45
- const primaryExampleLines = [];
46
- const descriptionBodyLines = [];
47
- for (const rawLine of lines) {
48
- const line = rawLine;
49
- if (inUsage) if (line.trim().startsWith("@")) inUsage = false;
50
- else {
51
- usageLines.push(line);
52
- continue;
53
- }
54
- if (inPrimaryExample) if (line.trim().startsWith("@")) inPrimaryExample = false;
55
- else {
56
- primaryExampleLines.push(line);
57
- continue;
58
- }
59
- if (inExamples) if (line.trim().startsWith("@")) inExamples = false;
60
- else {
61
- examplesLines.push(line);
62
- continue;
63
- }
64
- if (captureDescriptionBody) if (line.trim().startsWith("@")) captureDescriptionBody = false;
65
- else {
66
- descriptionBodyLines.push(line);
67
- continue;
68
- }
69
- if (line.trim().startsWith("@component")) meta.name = line.replace("@component", "").trim();
70
- else if (line.trim().startsWith("@title")) meta.title = line.replace("@title", "").trim();
71
- else if (line.trim().startsWith("@description")) {
72
- meta.description = line.replace("@description", "").trim();
73
- captureDescriptionBody = true;
74
- continue;
75
- } else if (line.trim().startsWith("@figmaUrl")) meta.figmaUrl = line.replace("@figmaUrl", "").trim();
76
- else if (line.trim().startsWith("@figma")) meta.figmaUrl = line.replace("@figma", "").trim();
77
- else if (line.trim().startsWith("@usage")) {
78
- inUsage = true;
79
- continue;
80
- } else if (line.trim().startsWith("@examples")) {
81
- inExamples = true;
82
- continue;
83
- } else if (line.trim().startsWith("@preview")) {
84
- inPrimaryExample = true;
85
- continue;
86
- } else if (line.trim().startsWith("@example")) {
87
- inPrimaryExample = true;
88
- continue;
89
- }
90
- }
91
- if (usageLines.length) meta.usageMDX = usageLines.join("\n").trim();
92
- if (examplesLines.length) meta.examplesMDX = examplesLines.join("\n").trim();
93
- if (primaryExampleLines.length) meta.primaryExampleMDX = primaryExampleLines.join("\n").trim();
94
- if (descriptionBodyLines.length) meta.descriptionBodyMDX = descriptionBodyLines.join("\n").trim();
95
- return meta;
96
- }
97
- function extractPropsFromAstroProps(sourceFile) {
98
- function unwrapAstroProps(node) {
99
- let current = node;
100
- for (let i = 0; i < 10; i += 1) {
101
- const kind = current.getKind();
102
- if (kind === SyntaxKind.PropertyAccessExpression) {
103
- const expr = current.getExpression();
104
- if (expr && expr.getText() === "Astro" && current.getName() === "props") return current;
105
- return null;
106
- }
107
- if (kind === SyntaxKind.AsExpression || kind === SyntaxKind.TypeAssertion || kind === SyntaxKind.SatisfiesExpression || kind === SyntaxKind.NonNullExpression || kind === SyntaxKind.ParenthesizedExpression) {
108
- const next = current.getExpression && current.getExpression();
109
- if (!next) return null;
110
- current = next;
111
- continue;
112
- }
113
- return null;
114
- }
115
- return null;
116
- }
117
- const target = sourceFile.getDescendantsOfKind(SyntaxKind.VariableDeclaration).find((decl) => {
118
- const init = decl.getInitializer();
119
- if (!init) return false;
120
- return !!unwrapAstroProps(init);
121
- });
122
- if (!target) return [];
123
- const nameNode = target.getNameNode();
124
- if (!nameNode || nameNode.getKind() !== SyntaxKind.ObjectBindingPattern) return [];
125
- return nameNode.asKindOrThrow(SyntaxKind.ObjectBindingPattern).getElements().map((el) => {
126
- if (!!el.getDotDotDotToken()) return {
127
- isRest: true,
128
- hasDefault: false,
129
- alias: el.getName()
130
- };
131
- const propertyNameNode = el.getPropertyNameNode();
132
- const name = el.getName();
133
- const propName = propertyNameNode ? propertyNameNode.getText() : name;
134
- const initializer = el.getInitializer();
135
- let defaultValue;
136
- if (initializer) defaultValue = initializer.getText();
137
- return {
138
- name: propName,
139
- hasDefault: initializer != null,
140
- defaultValue
141
- };
142
- });
143
- }
144
- function extractPropsFromDeclaredProps(sourceFile) {
145
- function normalizeTypeText(text) {
146
- if (!text) return "";
147
- return text.replace(/\s+/g, " ").replace(/;\s*$/, "").trim();
148
- }
149
- const iface = sourceFile.getInterface("Props");
150
- if (iface) return iface.getProperties().map((prop) => {
151
- const name = prop.getName();
152
- const typeNode = prop.getTypeNode();
153
- const rawType = typeNode ? typeNode.getText() : prop.getType().getText();
154
- const typeText = normalizeTypeText(rawType);
155
- const optional = prop.hasQuestionToken();
156
- return {
157
- name,
158
- type: typeText,
159
- optional
160
- };
161
- });
162
- const typeAlias = sourceFile.getTypeAlias("Props");
163
- if (typeAlias) {
164
- const typeNode = typeAlias.getTypeNode();
165
- if (typeNode && typeNode.getKind() === SyntaxKind.TypeLiteral) return typeNode.asKindOrThrow(SyntaxKind.TypeLiteral).getProperties().map((prop) => {
166
- const name = prop.getName();
167
- const tn = prop.getTypeNode();
168
- const rawType = tn ? tn.getText() : prop.getType().getText();
169
- const typeText = normalizeTypeText(rawType);
170
- const optional = prop.hasQuestionToken();
171
- return {
172
- name,
173
- type: typeText,
174
- optional
175
- };
176
- });
177
- }
178
- return [];
179
- }
180
- function resolveUiRoot(cwd) {
181
- const require$1 = createRequire$1(import.meta.url);
182
- const envRoot = process.env.BEJAMAS_UI_ROOT;
183
- if (envRoot && existsSync(path.join(envRoot, "package.json"))) return envRoot;
184
- try {
185
- const pkgPath = require$1.resolve("@bejamas/ui/package.json", { paths: [cwd] });
186
- return path.dirname(pkgPath);
187
- } catch {}
188
- let current = cwd;
189
- for (let i = 0; i < 6; i += 1) {
190
- const candidate = path.join(current, "packages", "ui", "package.json");
191
- if (existsSync(candidate)) return path.dirname(candidate);
192
- const parent = path.dirname(current);
193
- if (parent === current) break;
194
- current = parent;
195
- }
196
- try {
197
- const anyEntry = require$1.resolve("@bejamas/ui/*", { paths: [cwd] });
198
- return path.resolve(anyEntry, "..", "..");
199
- } catch {}
200
- throw new Error("Unable to locate @bejamas/ui in the workspace");
11
+ //#region src/docs/generate-mdx/mdx-builder.ts
12
+ /**
13
+ * Check if an import path uses the new barrel export pattern (no .astro extension)
14
+ */
15
+ function isBarrelImport(path$1) {
16
+ return !path$1.endsWith(".astro");
201
17
  }
202
- function resolveOutDir(cwd) {
203
- const envOut = process.env.BEJAMAS_DOCS_OUT_DIR;
204
- if (envOut && envOut.length) return path.isAbsolute(envOut) ? envOut : path.resolve(cwd, envOut);
205
- return path.resolve(cwd, "../../apps/web/src/content/docs/components");
18
+ /**
19
+ * Convert a PascalCase component name to its folder path (kebab-case).
20
+ * Examples:
21
+ * - "Card" "card"
22
+ * - "CardHeader" → "card"
23
+ * - "InputGroup" → "input-group"
24
+ * - "InputGroupAddon" → "input-group"
25
+ * - "StickySurface" → "sticky-surface"
26
+ * - "RadioGroup" → "radio-group"
27
+ * - "RadioGroupItem" → "radio-group"
28
+ */
29
+ function componentToFolder(name) {
30
+ const sortedFamilies = [
31
+ "InputGroup",
32
+ "LinkGroup",
33
+ "RadioGroup",
34
+ "ButtonGroup",
35
+ "StickySurface"
36
+ ].sort((a, b) => b.length - a.length);
37
+ for (const family of sortedFamilies) if (name === family || name.startsWith(family)) return family.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
38
+ const baseMatch = name.match(/^[A-Z][a-z]*/);
39
+ return baseMatch ? baseMatch[0].toLowerCase() : name.toLowerCase();
206
40
  }
207
- function detectHasImportTopLevel(block, pascalName) {
208
- if (!block) return false;
209
- let inFence = false;
210
- const importLineRegex = /* @__PURE__ */ new RegExp(`^\\s*import\\s+.*\\bfrom\\s+['"][^'"]+\\b${pascalName}\\.astro['"]`);
211
- for (const line of block.split("\n")) {
212
- if (line.trim().startsWith("```")) {
213
- inFence = !inFence;
214
- continue;
215
- }
216
- if (!inFence && importLineRegex.test(line)) return true;
41
+ /**
42
+ * Group component names by their folder path
43
+ */
44
+ function groupComponentsByFolder(components) {
45
+ const groups = /* @__PURE__ */ new Map();
46
+ for (const comp of components) {
47
+ const folder = componentToFolder(comp);
48
+ if (!groups.has(folder)) groups.set(folder, []);
49
+ groups.get(folder).push(comp);
217
50
  }
218
- return false;
51
+ return groups;
219
52
  }
220
- function normalizeBlockMDX(block) {
221
- if (!block) return "";
222
- return block.replace(/from\s+['"]@\/ui\/components\//g, "from '@bejamas/ui/components/");
223
- }
224
- function normalizeUsageMDX(usageMDX, pascalName) {
225
- const normalized = normalizeBlockMDX(usageMDX);
226
- const hasImport = detectHasImportTopLevel(normalized, pascalName);
227
- return {
228
- text: normalized.trim(),
229
- hasImport
230
- };
231
- }
232
- function extractComponentTagsFromMDX(block) {
233
- if (!block) return [];
234
- let inFence = false;
235
- const found = /* @__PURE__ */ new Set();
236
- const tagRegex = /<([A-Z][A-Za-z0-9_]*)\b/g;
237
- for (const line of block.split("\n")) {
238
- if (line.trim().startsWith("```")) {
239
- inFence = !inFence;
240
- continue;
241
- }
242
- if (inFence) continue;
243
- let match;
244
- while ((match = tagRegex.exec(line)) !== null) {
245
- const name = match[1];
246
- found.add(name);
247
- }
53
+ /**
54
+ * Generate import lines for UI components using the barrel import pattern
55
+ */
56
+ function generateBarrelImports(components, componentsAlias) {
57
+ const groups = groupComponentsByFolder(components);
58
+ const lines = [];
59
+ const sortedFolders = Array.from(groups.keys()).sort();
60
+ for (const folder of sortedFolders) {
61
+ const names = groups.get(folder).sort();
62
+ lines.push(`import { ${names.join(", ")} } from '${componentsAlias}/${folder}';`);
248
63
  }
249
- return Array.from(found);
250
- }
251
- async function discoverExamples(componentFilePath, componentsDir) {
252
- const fileBase = path.basename(componentFilePath, path.extname(componentFilePath));
253
- const kebabBase = slugify(fileBase);
254
- const candidates = [join(dirname(componentFilePath), `${fileBase}.examples`), join(dirname(componentFilePath), `${kebabBase}.examples`)];
255
- const found = [];
256
- for (const dir of candidates) try {
257
- const items = await readdir(dir, { withFileTypes: true });
258
- for (const it of items) if (it.isFile() && extname(it.name).toLowerCase() === ".astro") {
259
- const abs = join(dir, it.name);
260
- const relFromComponents = path.relative(componentsDir, abs).split(path.sep).join(posix.sep);
261
- found.push(relFromComponents);
262
- }
263
- } catch {}
264
- return found;
64
+ return lines;
265
65
  }
266
- function createSourceFileFromFrontmatter(frontmatterCode) {
267
- return new Project({ useInMemoryFileSystem: true }).createSourceFile("Component.ts", frontmatterCode, { overwrite: true });
66
+ /**
67
+ * Generate import lines for UI components using the old default import pattern
68
+ */
69
+ function generateDefaultImports(components, componentsAlias) {
70
+ return components.slice().sort().map((name) => `import ${name} from '${componentsAlias}/${name}.astro';`);
268
71
  }
269
-
270
- //#endregion
271
- //#region src/docs/generate-mdx/mdx-builder.ts
272
72
  function buildMdx(params) {
273
- const { importName, importPath, title, description, descriptionBodyMDX, usageMDX, hasImport, propsList, propsTable, examples, examplesBlocks, autoImports, lucideIcons, primaryExampleMDX, componentSource, commandName, figmaUrl, componentsAlias } = params;
73
+ const { importName, importPath, title, description, descriptionBodyMDX, usageMDX, hasImport, propsList, propsTable, examples, examplesBlocks, autoImports, lucideIcons, primaryExampleMDX, componentSource, commandName, figmaUrl, componentsAlias, namedExports } = params;
74
+ const useBarrelPattern = isBarrelImport(importPath);
274
75
  const sortedLucide = (lucideIcons ?? []).slice().sort();
275
76
  const externalTopImports = [`import { Tabs as DocsTabs, TabItem as DocsTabItem } from '@astrojs/starlight/components';`, sortedLucide.length ? `import { ${sortedLucide.join(", ")} } from '@lucide/astro';` : null].filter((v) => v != null).slice().sort((a, b) => String(a).localeCompare(String(b)));
276
- const uiAutoLines = (autoImports ?? []).slice().sort().map((name) => `import ${name} from '${componentsAlias}/${name}.astro';`);
77
+ const sortedUiAuto = (autoImports ?? []).slice().sort();
78
+ const uiAutoLines = useBarrelPattern ? generateBarrelImports(sortedUiAuto, componentsAlias) : generateDefaultImports(sortedUiAuto, componentsAlias);
277
79
  const exampleLines = (examples ?? []).map((ex) => `import ${ex.importName} from '${ex.importPath}';`).sort((a, b) => a.localeCompare(b));
80
+ let mainImportLine = null;
81
+ if (!hasImport) if (useBarrelPattern) mainImportLine = `import { ${[importName, ...namedExports ?? []].sort().join(", ")} } from '${importPath}';`;
82
+ else mainImportLine = `import ${importName} from '${importPath}';`;
278
83
  const internalTopImports = [
279
- !hasImport ? `import ${importName} from '${importPath}';` : null,
84
+ mainImportLine,
280
85
  ...uiAutoLines,
281
86
  ...exampleLines
282
87
  ].filter((v) => v != null).slice().sort((a, b) => String(a).localeCompare(String(b)));
@@ -296,13 +101,22 @@ function buildMdx(params) {
296
101
  if (!snippet || !snippet.length) return [];
297
102
  const used = extractTags(snippet);
298
103
  const usedIcons = sortedLucide.filter((n) => used.has(n));
299
- const usedUi = (autoImports ?? []).filter((n) => used.has(n)).slice().sort();
104
+ const usedUi = (autoImports ?? []).filter((n) => used.has(n));
300
105
  const includeMain = !hasImport && used.has(importName);
106
+ const usedNamedExports = useBarrelPattern && namedExports ? namedExports.filter((n) => used.has(n)) : [];
301
107
  const external = [];
302
108
  if (usedIcons.length) external.push(`import { ${usedIcons.join(", ")} } from '@lucide/astro';`);
303
109
  const internal = [];
304
- if (includeMain) internal.push(`import ${importName} from '${importPath}';`);
305
- internal.push(...usedUi.map((name) => `import ${name} from '${componentsAlias}/${name}.astro';`));
110
+ if (useBarrelPattern) {
111
+ if (includeMain || usedNamedExports.length > 0) {
112
+ const mainExports = [...includeMain ? [importName] : [], ...usedNamedExports].sort();
113
+ internal.push(`import { ${mainExports.join(", ")} } from '${importPath}';`);
114
+ }
115
+ if (usedUi.length > 0) internal.push(...generateBarrelImports(usedUi, componentsAlias));
116
+ } else {
117
+ if (includeMain) internal.push(`import ${importName} from '${importPath}';`);
118
+ internal.push(...usedUi.slice().sort().map((name) => `import ${name} from '${componentsAlias}/${name}.astro';`));
119
+ }
306
120
  const externalSorted = external.slice().sort((a, b) => a.localeCompare(b));
307
121
  const internalSorted = internal.slice().sort((a, b) => a.localeCompare(b));
308
122
  return [
@@ -498,6 +312,72 @@ ${componentSource}
498
312
 
499
313
  //#endregion
500
314
  //#region src/docs/generate-mdx/index.ts
315
+ /**
316
+ * Discover components in the components directory.
317
+ * Supports both:
318
+ * - Old pattern: flat .astro files in components/
319
+ * - New pattern: folders with index.ts barrel exports
320
+ */
321
+ async function discoverComponents(componentsDir) {
322
+ const entries = [];
323
+ const dirEntries = await readdir(componentsDir, { withFileTypes: true });
324
+ for (const entry of dirEntries) if (entry.isDirectory()) {
325
+ const folderPath = join(componentsDir, entry.name);
326
+ const indexPath = join(folderPath, "index.ts");
327
+ if (existsSync(indexPath)) {
328
+ const indexContent = await readFile(indexPath, "utf-8");
329
+ const namedExports = parseBarrelExports(indexContent);
330
+ const mainComponentName = findMainComponent(namedExports, entry.name);
331
+ if (mainComponentName) {
332
+ const mainFilePath = join(folderPath, `${mainComponentName}.astro`);
333
+ if (existsSync(mainFilePath)) {
334
+ const subComponents = namedExports.filter((n) => n !== mainComponentName);
335
+ entries.push({
336
+ name: mainComponentName,
337
+ filePath: mainFilePath,
338
+ folderName: entry.name,
339
+ isFolder: true,
340
+ namedExports: subComponents
341
+ });
342
+ }
343
+ }
344
+ }
345
+ } else if (entry.isFile() && extname(entry.name).toLowerCase() === ".astro") {
346
+ const componentName = entry.name.replace(/\.astro$/i, "");
347
+ entries.push({
348
+ name: componentName,
349
+ filePath: join(componentsDir, entry.name),
350
+ folderName: "",
351
+ isFolder: false,
352
+ namedExports: []
353
+ });
354
+ }
355
+ return entries;
356
+ }
357
+ /**
358
+ * Parse a barrel (index.ts) file to extract named exports.
359
+ * Handles patterns like:
360
+ * - export { default as Card } from "./Card.astro";
361
+ * - export { default as CardHeader } from "./CardHeader.astro";
362
+ */
363
+ function parseBarrelExports(content) {
364
+ const exports = [];
365
+ const exportRegex = /export\s*\{\s*default\s+as\s+(\w+)\s*\}/g;
366
+ let match;
367
+ while ((match = exportRegex.exec(content)) !== null) exports.push(match[1]);
368
+ return exports;
369
+ }
370
+ /**
371
+ * Find the main component from a list of exports.
372
+ * The main component is typically the one that matches the folder name (PascalCase).
373
+ */
374
+ function findMainComponent(exports, folderName) {
375
+ if (exports.length === 0) return null;
376
+ const expectedName = folderName.split("-").map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("");
377
+ const exactMatch = exports.find((e) => e === expectedName);
378
+ if (exactMatch) return exactMatch;
379
+ return exports[0];
380
+ }
501
381
  async function main() {
502
382
  const DEBUG = process.env.BEJAMAS_DEBUG === "1" || process.env.BEJAMAS_DEBUG === "true";
503
383
  const cwd = process.env.BEJAMAS_DOCS_CWD && process.env.BEJAMAS_DOCS_CWD.length ? process.env.BEJAMAS_DOCS_CWD : process.cwd();
@@ -519,17 +399,17 @@ async function main() {
519
399
  logger.info(`[docs-generator] componentsDir: ${componentsDir}`);
520
400
  logger.info(`[docs-generator] outDir: ${outDir}`);
521
401
  }
522
- const files = (await readdir(componentsDir, { withFileTypes: true })).filter((e) => e.isFile() && extname(e.name).toLowerCase() === ".astro");
402
+ const components = await discoverComponents(componentsDir);
523
403
  if (DEBUG) {
524
- logger.info(`[docs-generator] components found: ${files.length}`);
525
- if (files.length) logger.info(`[docs-generator] first few: ${files.slice(0, 5).map((f) => f.name).join(", ")}`);
404
+ logger.info(`[docs-generator] components found: ${components.length}`);
405
+ if (components.length) logger.info(`[docs-generator] first few: ${components.slice(0, 5).map((c) => c.name).join(", ")}`);
526
406
  }
527
407
  let generatedCount = 0;
528
- const total = files.length;
408
+ const total = components.length;
529
409
  const spin = spinner(`Generating docs (0/${total})`).start();
530
- for (const f of files) {
531
- const filePath = join(componentsDir, f.name);
532
- const astroFile = await (await import("fs/promises")).readFile(filePath, "utf-8");
410
+ for (const component of components) {
411
+ const { name: pascal, filePath, folderName, isFolder, namedExports } = component;
412
+ const astroFile = await readFile(filePath, "utf-8");
533
413
  const frontmatterCode = extractFrontmatter(astroFile);
534
414
  const sourceFile = createSourceFileFromFrontmatter(frontmatterCode);
535
415
  const meta = parseJsDocMetadata(frontmatterCode);
@@ -543,15 +423,14 @@ async function main() {
543
423
  required: !p.optional,
544
424
  defaultValue: defaultsMap.has(p.name) ? defaultsMap.get(p.name) : null
545
425
  }));
546
- const slug = `${slugify(f.name)}`;
547
- const pascal = f.name.replace(/\.(astro)$/i, "");
426
+ const slug = slugify(pascal);
548
427
  const title = meta.title || meta.name || pascal;
549
428
  const description = meta.description || "";
550
429
  const descriptionBodyMDX = meta.descriptionBodyMDX || "";
551
430
  const figmaUrl = meta.figmaUrl || "";
552
431
  const propsList = "";
553
432
  const importName = pascal;
554
- const importPath = `${componentsAlias}/${pascal}.astro`;
433
+ const importPath = isFolder ? `${componentsAlias}/${folderName}` : `${componentsAlias}/${pascal}.astro`;
555
434
  const { text: usageMDX, hasImport: hasImportUsage } = normalizeUsageMDX(meta.usageMDX || "", pascal);
556
435
  const primaryExampleMDX = normalizeBlockMDX(meta.primaryExampleMDX || "").trim();
557
436
  const examplesMDX = normalizeBlockMDX(meta.examplesMDX || "").trim();
@@ -565,13 +444,13 @@ async function main() {
565
444
  exampleRelPaths = await discoverExamples(filePath, componentsDir);
566
445
  examples = (exampleRelPaths || []).map((rel) => {
567
446
  const posixRel = rel.split(__require("path").sep).join(__require("path").posix.sep);
568
- const importPath$1 = `${componentsAlias}/${posixRel}`;
447
+ const importPathEx = `${componentsAlias}/${posixRel}`;
569
448
  const abs = join(componentsDir, rel);
570
449
  const source = __require("fs").readFileSync(abs, "utf-8");
571
450
  const base = toIdentifier(__require("path").basename(rel, __require("path").extname(rel)));
572
451
  return {
573
452
  importName: `${pascal}${base}`,
574
- importPath: importPath$1,
453
+ importPath: importPathEx,
575
454
  title: base,
576
455
  source
577
456
  };
@@ -585,6 +464,8 @@ async function main() {
585
464
  ...usedInExamples,
586
465
  ...usedInPrimary
587
466
  ]);
467
+ const usedNamedExports = isFolder ? namedExports.filter((n) => autoSet.has(n)) : [];
468
+ if (isFolder) for (const n of namedExports) autoSet.delete(n);
588
469
  const autoImports = Array.from(autoSet).filter((name) => !RESERVED_COMPONENTS.has(name)).filter((name) => true);
589
470
  const lucideIcons = autoImports.filter((n) => /Icon$/.test(n));
590
471
  const uiAutoImports = autoImports.filter((n) => !/Icon$/.test(n));
@@ -606,7 +487,8 @@ async function main() {
606
487
  commandName: slug,
607
488
  figmaUrl,
608
489
  descriptionBodyMDX,
609
- componentsAlias
490
+ componentsAlias,
491
+ namedExports: isFolder ? usedNamedExports : void 0
610
492
  });
611
493
  const outFile = join(outDir, `${slug}.mdx`);
612
494
  mkdirSync(dirname(outFile), { recursive: true });
@@ -616,8 +498,8 @@ async function main() {
616
498
  if (DEBUG) logger.info(`Generated ${outFile}`);
617
499
  }
618
500
  spin.succeed(`Created ${generatedCount} file${generatedCount === 1 ? "" : "s"}:`);
619
- files.map((f) => {
620
- const slug = `${slugify(f.name)}`;
501
+ components.map((c) => {
502
+ const slug = slugify(c.name);
621
503
  const outFile = join(outDir, `${slug}.mdx`);
622
504
  return relative(cwd, outFile);
623
505
  }).sort((a, b) => a.localeCompare(b)).forEach((p) => {
@@ -661,4 +543,4 @@ if (process.env.BEJAMAS_SKIP_AUTO_RUN !== "1" && process.env.BEJAMAS_SKIP_AUTO_R
661
543
 
662
544
  //#endregion
663
545
  export { runDocsGenerator };
664
- //# sourceMappingURL=generate-mdx-CR4bXlml.js.map
546
+ //# sourceMappingURL=generate-mdx-Csh3BuQB.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-mdx-Csh3BuQB.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 if (/^\\{[\\s\\S]*\\}$/.test(trimmed)) return match;\n return `>{${JSON.stringify(inner)}}<`;\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 return wrapTextNodes(withoutComments);\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 ? `<DocsTabs>\n <DocsTabItem label=\"Preview\">\n <div class=\"not-content sl-bejamas-component-preview flex justify-center px-10 py-12 border border-border rounded-md min-h-[450px] items-center [&_input]:max-w-xs\">\n${toMdxPreview(primaryExampleMDX)}\n </div>\n </DocsTabItem>\n <DocsTabItem label=\"Source\">\n\n\\`\\`\\`astro\n${(() => {\n const lines = buildSnippetImportLines(primaryExampleMDX);\n return lines.length ? `---\\n${lines.join(\"\\n\")}\\n---\\n\\n` : \"\";\n})()}${primaryExampleMDX}\n\\`\\`\\`\n </DocsTabItem>\n</DocsTabs>`\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` : \"\"}<DocsTabs>\n <DocsTabItem label=\"Preview\">\n <div class=\"not-content sl-bejamas-component-preview flex justify-center px-10 py-12 border border-border rounded-md min-h-[450px] items-center [&_input]:max-w-xs\">\n${previewBody}\n </div>\n </DocsTabItem>\n <DocsTabItem label=\"Source\">\n\n\\`\\`\\`astro\n${(() => {\n const lines = buildSnippetImportLines(snippet);\n return lines.length ? `---\\n${lines.join(\"\\n\")}\\n---\\n\\n` : \"\";\n})()}${snippet}\n\\`\\`\\`\n </DocsTabItem>\n</DocsTabs>`,\n );\n }\n }\n if (examples && examples.length) {\n for (const ex of examples) {\n exampleSections.push(\n `### ${ex.title}\n\n<DocsTabs>\n <DocsTabItem label=\"Preview\">\n <div class=\"not-content\">\n <${ex.importName} />\n </div>\n </DocsTabItem>\n <DocsTabItem label=\"Source\">\n\n\\`\\`\\`astro\n${ex.source}\n\\`\\`\\`\n </DocsTabItem>\n</DocsTabs>`,\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<DocsTabs syncKey=\"installation\">\n <DocsTabItem label=\"CLI\">\n\n<DocsTabs syncKey=\"pkg\">\n <DocsTabItem label=\"bun\">\n\n\\`\\`\\`bash\n bunx bejamas add ${commandName}\n\\`\\`\\`\n\n </DocsTabItem>\n <DocsTabItem label=\"npm\">\n\n\\`\\`\\`bash\n npx bejamas add ${commandName}\n\\`\\`\\`\n\n </DocsTabItem>\n <DocsTabItem label=\"pnpm\">\n\n\\`\\`\\`bash\n pnpm dlx bejamas add ${commandName}\n\\`\\`\\`\n\n </DocsTabItem>\n <DocsTabItem label=\"yarn\">\n\n\\`\\`\\`bash\n yarn dlx bejamas add ${commandName}\n\\`\\`\\`\n\n </DocsTabItem>\n</DocsTabs>\n</DocsTabItem>\n<DocsTabItem label=\"Manual\">\n\n\\`\\`\\`astro\n${componentSource}\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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"}