@uniweb/build 0.14.6 → 0.14.8

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uniweb/build",
3
- "version": "0.14.6",
3
+ "version": "0.14.8",
4
4
  "description": "Build tooling for the Uniweb Component Web Platform",
5
5
  "type": "module",
6
6
  "exports": {
@@ -59,13 +59,13 @@
59
59
  "js-yaml": "^4.1.0",
60
60
  "sharp": "^0.33.2",
61
61
  "yaml": "^2.5.0",
62
- "@uniweb/theming": "0.1.3",
63
- "@uniweb/content-writer": "0.2.5"
62
+ "@uniweb/content-writer": "0.2.5",
63
+ "@uniweb/theming": "0.1.3"
64
64
  },
65
65
  "optionalDependencies": {
66
- "@uniweb/runtime": "0.8.15",
66
+ "@uniweb/content-reader": "1.1.12",
67
67
  "@uniweb/schemas": "0.2.1",
68
- "@uniweb/content-reader": "1.1.12"
68
+ "@uniweb/runtime": "0.8.16"
69
69
  },
70
70
  "peerDependencies": {
71
71
  "vite": "^5.0.0 || ^6.0.0 || ^7.0.0",
package/src/prerender.js CHANGED
@@ -25,21 +25,29 @@ import { detectCiContext } from './hosts/detect-ci-context.js'
25
25
  * 2. Project root with dist subdir (dev layout, e.g., project/effects/dist/entry.js)
26
26
  * 3. Original URL (absolute or remote — let import() handle it)
27
27
  */
28
- function resolveExtensionPath(url, distDir, projectRoot) {
28
+ export function resolveExtensionPath(url, distDir, projectRoot) {
29
29
  // Only resolve URLs that look like root-relative paths
30
30
  if (url.startsWith('/')) {
31
31
  // Try dist directory first (production: files copied to site/dist/)
32
32
  const distPath = join(distDir, url)
33
33
  if (existsSync(distPath)) return distPath
34
34
 
35
- // Try project root with dist subdir (dev layout: effects/dist/entry.js)
36
- // "/effects/entry.js" "effects/dist/entry.js"
35
+ // Workspace layouts: "/effects/entry.js" → "<pkg>/dist/entry.js", checked
36
+ // both at the project root and under an `extensions/` parent — the standard
37
+ // multi-foundation layout puts extensions in `extensions/<name>/`, so the
38
+ // bare-root candidate alone misses the built module and prerender can't load
39
+ // the extension.
37
40
  const parts = url.slice(1).split('/')
38
41
  if (parts.length >= 2) {
39
42
  const pkgName = parts[0]
40
43
  const rest = parts.slice(1).join('/')
41
- const devPath = join(projectRoot, pkgName, 'dist', rest)
42
- if (existsSync(devPath)) return devPath
44
+ const candidates = [
45
+ join(projectRoot, pkgName, 'dist', rest),
46
+ join(projectRoot, 'extensions', pkgName, 'dist', rest),
47
+ ]
48
+ for (const devPath of candidates) {
49
+ if (existsSync(devPath)) return devPath
50
+ }
43
51
  }
44
52
  }
45
53
 
@@ -355,7 +355,8 @@ export function extractAllRuntimeSchemas(componentsMeta, dataSchemaMap = {}) {
355
355
  *
356
356
  * Layout runtime metadata:
357
357
  * - areas: Array of area names this layout supports
358
- * - transitions: View transition name mapping (stored but not acted on yet)
358
+ * - transitions: View transition name overrides (the runtime auto-names areas;
359
+ * this overrides per region, or `false` opts the layout out)
359
360
  * - defaults: Param default values
360
361
  * - scroll: Scroll management mode ('self' or CSS selector)
361
362
  *
@@ -71,6 +71,36 @@ export function isLocalAssetPath(value) {
71
71
  return isImagePath(value) || isVideoPath(value) || isPdfPath(value)
72
72
  }
73
73
 
74
+ /**
75
+ * Check whether a frontmatter media-field value (`background`, `image`,
76
+ * `poster`, …) is an asset *reference* rather than a CSS value.
77
+ *
78
+ * `background` is dual-use: it can be an image/video path OR a CSS color
79
+ * (`gray`, `#fff`, `oklch(…)`), a gradient (`linear-gradient(…)`), or a palette
80
+ * token (`primary-900`). The runtime's `Block.normalizeBackground` already
81
+ * classifies these — a string is image/video only when it's path-like or
82
+ * carries a media extension; everything else is a color/gradient. The build
83
+ * must apply the SAME rule, otherwise a bare color like `gray` gets resolved as
84
+ * a relative path (`<page-dir>/gray`) and the asset-processor logs a spurious
85
+ * "Source not found" for a file that was never meant to exist.
86
+ *
87
+ * Looser than `isLocalAssetPath` (which requires BOTH a `./`/`../`/`/` prefix
88
+ * AND an extension): a bare relative `hero.jpg` is a valid asset reference, so a
89
+ * media extension alone qualifies.
90
+ *
91
+ * @param {*} value - Frontmatter field value
92
+ * @returns {boolean} True if it should be resolved as a local asset
93
+ */
94
+ export function isMediaFieldReference(value) {
95
+ if (typeof value !== 'string' || !value) return false
96
+ // External media is loaded at runtime from its URL, not processed here.
97
+ if (isExternalUrl(value)) return false
98
+ // Path-like values are asset references (even without an extension).
99
+ if (value.startsWith('./') || value.startsWith('../') || value.startsWith('/')) return true
100
+ // Otherwise only a media extension makes it an asset (vs. a color/token).
101
+ return isImagePath(value) || isVideoPath(value) || isPdfPath(value)
102
+ }
103
+
74
104
  /**
75
105
  * Recursively walk a parsed data object and collect asset paths
76
106
  *
@@ -268,7 +298,9 @@ export function collectSectionAssets(section, markdownPath, siteRoot) {
268
298
 
269
299
  for (const field of mediaFields) {
270
300
  const value = section.params?.[field]
271
- if (typeof value === 'string' && value) {
301
+ // Only resolve values that are actually asset references. A dual-use field
302
+ // like `background: gray` (a CSS color) must not be treated as a file path.
303
+ if (isMediaFieldReference(value)) {
272
304
  const result = resolveAssetPath(value, markdownPath, siteRoot)
273
305
  if (!result.external && result.resolved) {
274
306
  assets[value] = {