@uniweb/build 0.6.16 → 0.6.17

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.6.16",
3
+ "version": "0.6.17",
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/runtime": "0.5.21",
54
53
  "@uniweb/schemas": "0.2.1",
55
- "@uniweb/content-reader": "1.1.2"
54
+ "@uniweb/content-reader": "1.1.2",
55
+ "@uniweb/runtime": "0.5.21"
56
56
  },
57
57
  "peerDependencies": {
58
58
  "vite": "^5.0.0 || ^6.0.0 || ^7.0.0",
package/src/i18n/index.js CHANGED
@@ -176,7 +176,8 @@ export async function extractManifest(siteRoot, options = {}) {
176
176
  const {
177
177
  localesDir = DEFAULTS.localesDir,
178
178
  siteContentPath = join(siteRoot, 'dist', 'site-content.json'),
179
- verbose = false
179
+ verbose = false,
180
+ dryRun = false
180
181
  } = options
181
182
 
182
183
  // Load site content
@@ -203,8 +204,10 @@ export async function extractManifest(siteRoot, options = {}) {
203
204
  // Generate sync report
204
205
  const report = syncManifests(previousManifest, manifest)
205
206
 
206
- // Write new manifest
207
- await writeFile(manifestPath, JSON.stringify(manifest, null, 2))
207
+ // Write new manifest (skip in dry-run mode)
208
+ if (!dryRun) {
209
+ await writeFile(manifestPath, JSON.stringify(manifest, null, 2))
210
+ }
208
211
 
209
212
  if (verbose) {
210
213
  console.log(formatSyncReport(report))
@@ -222,7 +225,7 @@ export async function extractManifest(siteRoot, options = {}) {
222
225
  * @returns {Promise<Object>} { manifest, report }
223
226
  */
224
227
  export async function extractCollectionManifest(siteRoot, options = {}) {
225
- const { localesDir = DEFAULTS.localesDir } = options
228
+ const { localesDir = DEFAULTS.localesDir, dryRun = false } = options
226
229
 
227
230
  // Extract translatable content from collections
228
231
  const manifest = await extractCollectionContent(siteRoot)
@@ -249,8 +252,10 @@ export async function extractCollectionManifest(siteRoot, options = {}) {
249
252
  // Generate sync report
250
253
  const report = syncManifests(previousManifest, manifest)
251
254
 
252
- // Write new manifest
253
- await writeFile(manifestPath, JSON.stringify(manifest, null, 2))
255
+ // Write new manifest (skip in dry-run mode)
256
+ if (!dryRun) {
257
+ await writeFile(manifestPath, JSON.stringify(manifest, null, 2))
258
+ }
254
259
 
255
260
  return { manifest, report }
256
261
  }
package/src/i18n/sync.js CHANGED
@@ -143,6 +143,15 @@ export function formatSyncReport(report) {
143
143
 
144
144
  if (report.moved.length > 0) {
145
145
  lines.push(` ↻ ${report.moved.length} strings moved (contexts updated)`)
146
+ for (const item of report.moved.slice(0, 5)) {
147
+ const preview = truncate(item.source, 40)
148
+ const oldCtx = formatContext(item.previousContexts?.[0])
149
+ const newCtx = formatContext(item.currentContexts?.[0])
150
+ lines.push(` - "${preview}" ${oldCtx} → ${newCtx}`)
151
+ }
152
+ if (report.moved.length > 5) {
153
+ lines.push(` ... and ${report.moved.length - 5} more`)
154
+ }
146
155
  }
147
156
 
148
157
  if (report.changed.length > 0) {
@@ -150,7 +159,7 @@ export function formatSyncReport(report) {
150
159
  for (const item of report.changed.slice(0, 5)) {
151
160
  const prevPreview = truncate(item.previousSource, 30)
152
161
  const currPreview = truncate(item.source, 30)
153
- lines.push(` - ${item.previousHash}: "${prevPreview}" → "${currPreview}"`)
162
+ lines.push(` - "${prevPreview}" → "${currPreview}"`)
154
163
  }
155
164
  if (report.changed.length > 5) {
156
165
  lines.push(` ... and ${report.changed.length - 5} more`)
@@ -159,15 +168,42 @@ export function formatSyncReport(report) {
159
168
 
160
169
  if (report.added.length > 0) {
161
170
  lines.push(` + ${report.added.length} new strings`)
171
+ for (const item of report.added.slice(0, 5)) {
172
+ const preview = truncate(item.source, 40)
173
+ const ctx = formatContext(item.contexts?.[0])
174
+ lines.push(` - "${preview}" ${ctx}`)
175
+ }
176
+ if (report.added.length > 5) {
177
+ lines.push(` ... and ${report.added.length - 5} more`)
178
+ }
162
179
  }
163
180
 
164
181
  if (report.removed.length > 0) {
165
182
  lines.push(` - ${report.removed.length} strings removed`)
183
+ for (const item of report.removed.slice(0, 5)) {
184
+ const preview = truncate(item.source, 40)
185
+ const ctx = formatContext(item.contexts?.[0])
186
+ lines.push(` - "${preview}" ${ctx}`)
187
+ }
188
+ if (report.removed.length > 5) {
189
+ lines.push(` ... and ${report.removed.length - 5} more`)
190
+ }
166
191
  }
167
192
 
168
193
  return lines.join('\n')
169
194
  }
170
195
 
196
+ /**
197
+ * Format a context object for display
198
+ */
199
+ function formatContext(context) {
200
+ if (!context) return ''
201
+ const location = context.page || context.collection || ''
202
+ const section = context.section || context.item || ''
203
+ if (!location && !section) return ''
204
+ return `(${location}:${section})`
205
+ }
206
+
171
207
  /**
172
208
  * Truncate string for display
173
209
  */
@@ -203,10 +203,12 @@ function isIgnoredFolder(name) {
203
203
  /**
204
204
  * Read folder configuration, determining content mode from config file presence.
205
205
  *
206
- * - folder.yml present → pages mode (md files are child pages)
207
- * - page.yml present → sections mode (md files are sections of this page)
206
+ * - folder.yml present → folder mode (md files are child pages)
207
+ * - page.yml present → page mode (md files are sections of this page)
208
208
  * - Neither → inherit mode from parent
209
209
  *
210
+ * Internal mode values: 'pages' (folder mode), 'sections' (page mode)
211
+ *
210
212
  * @param {string} dirPath - Directory path
211
213
  * @param {string} inheritedMode - Mode inherited from parent ('sections' or 'pages')
212
214
  * @returns {Promise<{config: Object, mode: string, source: string}>}
@@ -220,7 +222,7 @@ async function readFolderConfig(dirPath, inheritedMode) {
220
222
  if (Object.keys(pageYml).length > 0) {
221
223
  return { config: pageYml, mode: 'sections', source: 'page.yml' }
222
224
  }
223
- // Check for empty folder.yml (presence signals pages mode even if empty)
225
+ // Check for empty folder.yml (presence signals folder mode even if empty)
224
226
  if (existsSync(join(dirPath, 'folder.yml'))) {
225
227
  return { config: {}, mode: 'pages', source: 'folder.yml' }
226
228
  }
@@ -289,7 +291,7 @@ function applyNonStrictOrder(items, orderArray) {
289
291
  }
290
292
 
291
293
  /**
292
- * Process a markdown file as a standalone page (pages mode).
294
+ * Process a markdown file as a standalone page (folder mode).
293
295
  * Creates a page with a single section from the markdown content.
294
296
  *
295
297
  * @param {string} filePath - Path to markdown file
@@ -818,7 +820,7 @@ async function collectPagesRecursive(dirPath, parentRoute, siteRoot, orderConfig
818
820
  const folderNames = orderedFolders.map(f => f.name)
819
821
  const detectedVersions = detectVersions(folderNames)
820
822
 
821
- // If versioned section, handle version folders specially (always sections mode)
823
+ // If versioned section, handle version folders specially (always page mode)
822
824
  if (detectedVersions && !versionContext) {
823
825
  const parentConfig = await readYamlFile(join(dirPath, 'page.yml'))
824
826
  const versionMeta = buildVersionMetadata(detectedVersions, parentConfig)
@@ -880,7 +882,7 @@ async function collectPagesRecursive(dirPath, parentRoute, siteRoot, orderConfig
880
882
  // Apply non-strict order to md-file-pages
881
883
  const orderedMdPages = applyNonStrictOrder(mdPageItems, orderConfig?.order)
882
884
 
883
- // In pages mode, only promote an index if explicitly set via index: in folder.yml
885
+ // In folder mode, only promote an index if explicitly set via index: in folder.yml
884
886
  // The container page itself owns the parent route — don't auto-promote children
885
887
  const indexName = orderConfig?.index || null
886
888
 
@@ -906,7 +908,7 @@ async function collectPagesRecursive(dirPath, parentRoute, siteRoot, orderConfig
906
908
  const isIndex = entry === indexName
907
909
 
908
910
  if (dirMode === 'sections') {
909
- // Subdirectory overrides to sections mode — process normally
911
+ // Subdirectory overrides to page mode — process normally
910
912
  const result = await processPage(entryPath, entry, siteRoot, {
911
913
  isIndex, parentRoute, parentFetch, versionContext
912
914
  })
@@ -917,7 +919,7 @@ async function collectPagesRecursive(dirPath, parentRoute, siteRoot, orderConfig
917
919
  iconCollection = mergeIconCollections(iconCollection, pageIcons)
918
920
  pages.push(page)
919
921
 
920
- // Recurse into subdirectories (sections mode)
922
+ // Recurse into subdirectories (page mode)
921
923
  const childParentRoute = isIndex ? parentRoute : page.route
922
924
  const childFetch = page.fetch || parentFetch
923
925
  const subResult = await collectPagesRecursive(entryPath, childParentRoute, siteRoot, childOrderConfig, childFetch, versionContext, 'sections')
@@ -929,7 +931,7 @@ async function collectPagesRecursive(dirPath, parentRoute, siteRoot, orderConfig
929
931
  }
930
932
  }
931
933
  } else {
932
- // Container directory in pages mode — create minimal page, recurse
934
+ // Container directory in folder mode — create minimal page, recurse
933
935
  const containerRoute = isIndex
934
936
  ? parentRoute
935
937
  : parentRoute === '/' ? `/${entry}` : `${parentRoute}/${entry}`
@@ -971,7 +973,7 @@ async function collectPagesRecursive(dirPath, parentRoute, siteRoot, orderConfig
971
973
 
972
974
  pages.push(containerPage)
973
975
 
974
- // Recurse in pages mode
976
+ // Recurse in folder mode
975
977
  const subResult = await collectPagesRecursive(entryPath, containerRoute, siteRoot, childOrderConfig, parentFetch, versionContext, 'pages')
976
978
  pages.push(...subResult.pages)
977
979
  assetCollection = mergeAssetCollections(assetCollection, subResult.assetCollection)
@@ -1000,8 +1002,8 @@ async function collectPagesRecursive(dirPath, parentRoute, siteRoot, orderConfig
1000
1002
  const isIndex = entry === indexPageName
1001
1003
 
1002
1004
  if (dirMode === 'pages') {
1003
- // Child directory switches to pages mode (has folder.yml) —
1004
- // create container page with empty sections, recurse in pages mode
1005
+ // Child directory switches to folder mode (has folder.yml) —
1006
+ // create container page with empty sections, recurse in folder mode
1005
1007
  const containerRoute = isIndex
1006
1008
  ? parentRoute
1007
1009
  : parentRoute === '/' ? `/${entry}` : `${parentRoute}/${entry}`