@uniweb/build 0.7.0 → 0.7.2

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.
Files changed (2) hide show
  1. package/package.json +4 -4
  2. package/src/schema.js +35 -6
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uniweb/build",
3
- "version": "0.7.0",
3
+ "version": "0.7.2",
4
4
  "description": "Build tooling for the Uniweb Component Web Platform",
5
5
  "type": "module",
6
6
  "exports": {
@@ -50,9 +50,9 @@
50
50
  "sharp": "^0.33.2"
51
51
  },
52
52
  "optionalDependencies": {
53
- "@uniweb/content-reader": "1.1.2",
54
- "@uniweb/runtime": "0.5.23",
55
- "@uniweb/schemas": "0.2.1"
53
+ "@uniweb/runtime": "0.6.0",
54
+ "@uniweb/schemas": "0.2.1",
55
+ "@uniweb/content-reader": "1.1.2"
56
56
  },
57
57
  "peerDependencies": {
58
58
  "vite": "^5.0.0 || ^6.0.0 || ^7.0.0",
package/src/schema.js CHANGED
@@ -136,6 +136,16 @@ function isComponentFileName(name) {
136
136
  return /^[A-Z]/.test(name)
137
137
  }
138
138
 
139
+ /**
140
+ * Check if a name is a valid layout identifier.
141
+ * Layout names are lowercase identifiers (e.g., 'docs', 'marketing')
142
+ * but PascalCase is also accepted for backward compatibility.
143
+ * Skips private names (leading _ or .).
144
+ */
145
+ function isLayoutName(name) {
146
+ return /^[a-zA-Z]/.test(name)
147
+ }
148
+
139
149
  /**
140
150
  * Check if a directory has a valid entry file (Name.ext or index.ext)
141
151
  */
@@ -284,15 +294,17 @@ export async function discoverLayoutsInPath(srcDir, layoutsRelPath = LAYOUTS_PAT
284
294
  const ext = extname(entry.name)
285
295
  if (entry.isFile() && COMPONENT_EXTENSIONS.has(ext)) {
286
296
  const name = basename(entry.name, ext)
287
- if (isComponentFileName(name)) {
297
+ if (isLayoutName(name)) {
288
298
  fileNames.add(name)
289
299
  }
290
300
  } else if (entry.isDirectory()) {
291
- dirNames.add(entry.name)
301
+ if (isLayoutName(entry.name)) {
302
+ dirNames.add(entry.name)
303
+ }
292
304
  }
293
305
  }
294
306
 
295
- // Check for name collisions (e.g., DocsLayout.jsx AND DocsLayout/)
307
+ // Check for name collisions (e.g., docs.jsx AND docs/)
296
308
  for (const name of fileNames) {
297
309
  if (dirNames.has(name)) {
298
310
  throw new Error(
@@ -308,7 +320,7 @@ export async function discoverLayoutsInPath(srcDir, layoutsRelPath = LAYOUTS_PAT
308
320
  const ext = extname(entry.name)
309
321
  if (!COMPONENT_EXTENSIONS.has(ext)) continue
310
322
  const name = basename(entry.name, ext)
311
- if (!isComponentFileName(name)) continue
323
+ if (!isLayoutName(name)) continue
312
324
 
313
325
  const meta = createImplicitMeta(name)
314
326
  layouts[name] = {
@@ -320,7 +332,7 @@ export async function discoverLayoutsInPath(srcDir, layoutsRelPath = LAYOUTS_PAT
320
332
  // Discover directories at root (no recursion for layouts)
321
333
  for (const entry of entries) {
322
334
  if (!entry.isDirectory()) continue
323
- if (!isComponentFileName(entry.name)) continue
335
+ if (!isLayoutName(entry.name)) continue
324
336
 
325
337
  const dirPath = join(fullPath, entry.name)
326
338
  const relativePath = join(layoutsRelPath, entry.name)
@@ -464,14 +476,31 @@ export async function buildSchema(srcDir, componentPaths) {
464
476
  // Discover layouts from src/layouts/
465
477
  const layouts = await discoverLayoutsInPath(srcDir)
466
478
 
479
+ // Determine extension role
480
+ const isExtension = !!foundationConfig.extension
481
+
482
+ // Warn if extension declares things it shouldn't
483
+ if (isExtension) {
484
+ if (foundationConfig.vars && Object.keys(foundationConfig.vars).length > 0) {
485
+ console.warn(`Warning: Extension declares theme variables (vars). Extensions don't define theme variables — the primary foundation owns those.`)
486
+ }
487
+ if (Object.keys(layouts).length > 0) {
488
+ console.warn(`Warning: Extension provides layouts. Extensions don't provide layouts — the primary foundation owns the layout.`)
489
+ }
490
+ }
491
+
492
+ // Build _self, stripping the raw extension boolean in favor of normalized role
493
+ const { extension: _ext, ...configWithoutExtension } = foundationConfig
494
+
467
495
  return {
468
496
  _self: {
469
- ...foundationConfig,
497
+ ...configWithoutExtension,
470
498
  ...identity,
471
499
  // foundation.js overrides package.json for editor-facing identity
472
500
  ...(foundationConfig.name && { name: foundationConfig.name }),
473
501
  ...(foundationConfig.description && { description: foundationConfig.description }),
474
502
  ...(foundationConfig.defaultLayout && { defaultLayout: foundationConfig.defaultLayout }),
503
+ ...(isExtension && { role: 'extension' }),
475
504
  },
476
505
  // Layout metadata (full, for editor)
477
506
  ...(Object.keys(layouts).length > 0 && { _layouts: layouts }),