@uniweb/build 0.4.10 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -15,7 +15,7 @@ npm install @uniweb/build --save-dev
15
15
  ## Features
16
16
 
17
17
  **For Foundations:**
18
- - **Component Discovery** - Automatically discovers components from `src/components/*/meta.js`
18
+ - **Component Discovery** - Discovers section types from `src/sections/` (implicit at root) and `src/components/` (requires `meta.js`)
19
19
  - **Entry Generation** - Generates the foundation entry point with all exports
20
20
  - **Schema Building** - Creates `schema.json` with full component metadata for editors
21
21
  - **Image Processing** - Converts preview images to WebP format
@@ -263,7 +263,7 @@ src/
263
263
  ### Component Meta File
264
264
 
265
265
  ```js
266
- // src/components/Hero/meta.js
266
+ // src/sections/Hero/meta.js
267
267
  export default {
268
268
  title: 'Hero Banner',
269
269
  description: 'A prominent header section',
@@ -367,7 +367,7 @@ Identity fields (`name`, `version`, `description`) come from the foundation's `p
367
367
 
368
368
  | Function | Description |
369
369
  |----------|-------------|
370
- | `discoverComponents(srcDir)` | Discover all exposed components |
370
+ | `discoverComponents(srcDir)` | Discover all section types (folders with meta.js) |
371
371
  | `loadComponentMeta(componentDir)` | Load meta file for a component |
372
372
  | `loadPackageJson(srcDir)` | Load identity from package.json |
373
373
  | `loadFoundationConfig(srcDir)` | Load foundation.js configuration |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uniweb/build",
3
- "version": "0.4.10",
3
+ "version": "0.6.0",
4
4
  "description": "Build tooling for the Uniweb Component Web Platform",
5
5
  "type": "module",
6
6
  "exports": {
@@ -50,8 +50,9 @@
50
50
  "sharp": "^0.33.2"
51
51
  },
52
52
  "optionalDependencies": {
53
+ "@uniweb/runtime": "0.5.11",
53
54
  "@uniweb/content-reader": "1.1.2",
54
- "@uniweb/runtime": "0.5.11"
55
+ "@uniweb/schemas": "0.2.1"
55
56
  },
56
57
  "peerDependencies": {
57
58
  "vite": "^5.0.0 || ^6.0.0 || ^7.0.0",
@@ -60,7 +61,7 @@
60
61
  "@tailwindcss/vite": "^4.0.0",
61
62
  "@vitejs/plugin-react": "^4.0.0 || ^5.0.0",
62
63
  "vite-plugin-svgr": "^4.0.0",
63
- "@uniweb/core": "0.3.10"
64
+ "@uniweb/core": "0.4.0"
64
65
  },
65
66
  "peerDependenciesMeta": {
66
67
  "vite": {
package/src/docs.js CHANGED
@@ -30,12 +30,12 @@ function generateComponentDocs(name, meta) {
30
30
  lines.push('')
31
31
  }
32
32
 
33
- // Parameters/Properties (shown first - most important for content authors)
34
- if (meta.properties && Object.keys(meta.properties).length > 0) {
33
+ // Parameters (shown first - most important for content authors)
34
+ if (meta.params && Object.keys(meta.params).length > 0) {
35
35
  lines.push('### Parameters')
36
36
  lines.push('')
37
37
 
38
- for (const [key, prop] of Object.entries(meta.properties)) {
38
+ for (const [key, prop] of Object.entries(meta.params)) {
39
39
  const defaultVal = prop.default !== undefined ? prop.default : ''
40
40
 
41
41
  // Parameter name with default
@@ -48,9 +48,9 @@ const DEFAULT_EXTERNALS = [
48
48
  * @param {Object} [options={}] - Configuration options
49
49
  * @param {string} [options.entry] - Entry point path (default: 'src/_entry.generated.js')
50
50
  * @param {string} [options.fileName] - Output file name (default: 'foundation')
51
- * @param {string[]} [options.components] - Paths to search for components (relative to src/).
52
- * Default: ['components']
53
- * Example: ['components', 'components/sections']
51
+ * @param {string[]} [options.components] - Paths to scan for content interfaces (relative to src/).
52
+ * Default: ['sections', 'components']
53
+ * Example: ['sections', 'sections/marketing']
54
54
  * @param {string[]} [options.externals] - Additional packages to externalize
55
55
  * @param {boolean} [options.includeDefaultExternals] - Include default externals (default: true)
56
56
  * @param {Array} [options.plugins] - Additional Vite plugins
@@ -112,10 +112,10 @@ function generateEntrySource(components, options = {}) {
112
112
  lines.push(`import capabilities from '${foundationExports.path}'`)
113
113
  }
114
114
 
115
- // Component imports (use component's path and detected extension)
115
+ // Component imports
116
116
  for (const name of componentNames) {
117
- const { path, ext = 'js' } = components[name]
118
- lines.push(`import ${name} from './${path}/index.${ext}'`)
117
+ const { path, entryFile = `index.js` } = components[name]
118
+ lines.push(`import ${name} from './${path}/${entryFile}'`)
119
119
  }
120
120
 
121
121
  lines.push('')
@@ -153,19 +153,33 @@ function generateEntrySource(components, options = {}) {
153
153
  }
154
154
 
155
155
  /**
156
- * Detect the index file extension for a component
156
+ * Detect the entry file for a component
157
+ *
158
+ * Supports two conventions:
159
+ * - index.jsx (default)
160
+ * - ComponentName.jsx (named file matching the directory name)
161
+ *
162
+ * Named files are checked first so that Hero/Hero.jsx takes precedence
163
+ * over Hero/index.jsx when both exist (the named file is more intentional).
157
164
  *
158
165
  * @param {string} srcDir - Source directory
159
166
  * @param {string} componentPath - Relative path to component (e.g., 'components/Hero')
167
+ * @param {string} componentName - Component name (e.g., 'Hero')
168
+ * @returns {{ file: string, ext: string }} Entry file name and extension
160
169
  */
161
- function detectComponentExtension(srcDir, componentPath) {
170
+ function detectComponentEntry(srcDir, componentPath, componentName) {
162
171
  const basePath = join(srcDir, componentPath)
163
172
  for (const ext of ['jsx', 'tsx', 'js', 'ts']) {
173
+ // Check named file first: Hero/Hero.jsx
174
+ if (existsSync(join(basePath, `${componentName}.${ext}`))) {
175
+ return { file: `${componentName}.${ext}`, ext }
176
+ }
177
+ // Then index file: Hero/index.jsx
164
178
  if (existsSync(join(basePath, `index.${ext}`))) {
165
- return ext
179
+ return { file: `index.${ext}`, ext }
166
180
  }
167
181
  }
168
- return 'js' // default
182
+ return { file: 'index.js', ext: 'js' } // default
169
183
  }
170
184
 
171
185
  /**
@@ -184,13 +198,18 @@ export async function generateEntryPoint(srcDir, outputPath = null, options = {}
184
198
  const componentNames = Object.keys(components).sort()
185
199
 
186
200
  if (componentNames.length === 0) {
187
- console.warn('Warning: No exposed components found')
201
+ console.warn('Warning: No section types found')
188
202
  }
189
203
 
190
- // Detect extensions for each component and add to component info
204
+ // Detect entry files for each component
205
+ // Bare files discovered in sections/ already have entryFile set — skip detection for those
191
206
  for (const name of componentNames) {
192
207
  const component = components[name]
193
- component.ext = detectComponentExtension(srcDir, component.path)
208
+ if (!component.entryFile) {
209
+ const entry = detectComponentEntry(srcDir, component.path, component.name)
210
+ component.ext = entry.ext
211
+ component.entryFile = entry.file
212
+ }
194
213
  }
195
214
 
196
215
  // Check for CSS file