uniweb 0.8.32 → 0.8.34

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",
3
- "version": "0.8.32",
3
+ "version": "0.8.34",
4
4
  "description": "Create structured Vite + React sites with content/code separation",
5
5
  "type": "module",
6
6
  "bin": {
@@ -41,14 +41,14 @@
41
41
  "js-yaml": "^4.1.0",
42
42
  "prompts": "^2.4.2",
43
43
  "tar": "^7.0.0",
44
- "@uniweb/core": "0.5.18",
45
- "@uniweb/kit": "0.7.21",
46
- "@uniweb/runtime": "0.6.27"
44
+ "@uniweb/runtime": "0.6.29",
45
+ "@uniweb/core": "0.5.19",
46
+ "@uniweb/kit": "0.7.22"
47
47
  },
48
48
  "peerDependencies": {
49
- "@uniweb/build": "0.8.31",
50
49
  "@uniweb/content-reader": "1.1.4",
51
- "@uniweb/semantic-parser": "1.1.8"
50
+ "@uniweb/semantic-parser": "1.1.9",
51
+ "@uniweb/build": "0.8.33"
52
52
  },
53
53
  "peerDependenciesMeta": {
54
54
  "@uniweb/build": {
@@ -274,6 +274,23 @@ Programs offered │ content.items[1].paragraphs[0]
274
274
 
275
275
  Without the `---`, `## 15,000+` would become `content.subtitle` instead of an item.
276
276
 
277
+ ### Sequential content
278
+
279
+ `content.sequence` is the flat, ordered list of all elements before any grouping. Each element has a `type` (`heading`, `paragraph`, `image`, `codeBlock`, `dataBlock`, `list`, `link`, `divider`, `inset`, etc.) and type-specific fields. Use it when grouping isn't the right lens — for example, rendering prose in document order with `<Prose>`, or finding specific elements regardless of which group they ended up in:
280
+
281
+ ```js
282
+ // All data blocks, regardless of heading groups
283
+ const allData = {}
284
+ for (const el of content.sequence) {
285
+ if (el.type === 'dataBlock') allData[el.tag] = el.data
286
+ }
287
+
288
+ // All headings in order
289
+ const headings = content.sequence.filter(e => e.type === 'heading')
290
+ ```
291
+
292
+ The grouped fields (`title`, `paragraphs`, `items`, `data`) and the sequential view (`sequence`) are two interpretations of the same content. Grouped is better for structured layouts (cards, features). Sequential is better for prose rendering and for finding content without caring about group boundaries.
293
+
277
294
  ### Choosing how to model content
278
295
 
279
296
  You have three layers. Most of the design skill is choosing between them:
@@ -5,6 +5,8 @@
5
5
  import { existsSync, readFileSync, readdirSync } from 'node:fs'
6
6
  import { join, resolve, basename, dirname, relative } from 'node:path'
7
7
  import yaml from 'js-yaml'
8
+ import { getCliVersion } from '../versions.js'
9
+ import { readAgentsVersion } from '../utils/agents-stamp.js'
8
10
 
9
11
  // ANSI colors
10
12
  const colors = {
@@ -484,6 +486,29 @@ export async function doctor(args = []) {
484
486
  }
485
487
  }
486
488
 
489
+ // Check AGENTS.md freshness
490
+ log('')
491
+ const agentsPath = join(workspaceDir, 'AGENTS.md')
492
+ const agentsVersion = readAgentsVersion(agentsPath)
493
+ const cliVersion = getCliVersion()
494
+
495
+ if (!existsSync(agentsPath)) {
496
+ warn('AGENTS.md not found')
497
+ info(`Run: uniweb update`)
498
+ issues.push({ type: 'warn', message: 'AGENTS.md not found' })
499
+ } else if (!agentsVersion) {
500
+ // No stamp — manually created or pre-stamp version
501
+ warn('AGENTS.md has no version stamp (may be outdated)')
502
+ info(`Run: uniweb update`)
503
+ issues.push({ type: 'warn', message: 'AGENTS.md has no version stamp' })
504
+ } else if (agentsVersion !== cliVersion) {
505
+ warn(`AGENTS.md is outdated (v${agentsVersion} → v${cliVersion})`)
506
+ info(`Run: uniweb update`)
507
+ issues.push({ type: 'warn', message: `AGENTS.md outdated (v${agentsVersion} → v${cliVersion})` })
508
+ } else {
509
+ success(`AGENTS.md is up to date (v${cliVersion})`)
510
+ }
511
+
487
512
  // Summary
488
513
  log('')
489
514
  log('─'.repeat(50))
@@ -0,0 +1,55 @@
1
+ /**
2
+ * uniweb update - Update generated project files
3
+ *
4
+ * Regenerates AGENTS.md from the installed CLI version.
5
+ */
6
+
7
+ import { existsSync, writeFileSync } from 'node:fs'
8
+ import { join, resolve } from 'node:path'
9
+ import { findWorkspaceRoot } from '../utils/workspace.js'
10
+ import { readAgentsVersion, generateAgentsContent } from '../utils/agents-stamp.js'
11
+ import { getCliVersion } from '../versions.js'
12
+
13
+ // ANSI colors
14
+ const colors = {
15
+ reset: '\x1b[0m',
16
+ bright: '\x1b[1m',
17
+ dim: '\x1b[2m',
18
+ red: '\x1b[31m',
19
+ green: '\x1b[32m',
20
+ yellow: '\x1b[33m',
21
+ blue: '\x1b[36m'
22
+ }
23
+
24
+ const success = (msg) => console.log(`${colors.green}✓${colors.reset} ${msg}`)
25
+ const warn = (msg) => console.log(`${colors.yellow}⚠${colors.reset} ${msg}`)
26
+ const error = (msg) => console.log(`${colors.red}✗${colors.reset} ${msg}`)
27
+ const log = console.log
28
+
29
+ export async function update(args = []) {
30
+ const workspaceDir = findWorkspaceRoot(process.cwd())
31
+
32
+ if (!workspaceDir) {
33
+ error('Not in a Uniweb workspace')
34
+ log(`${colors.dim}Run this command from your project root or a package directory.${colors.reset}`)
35
+ process.exit(1)
36
+ }
37
+
38
+ const cliVersion = getCliVersion()
39
+ const agentsPath = join(workspaceDir, 'AGENTS.md')
40
+ const currentVersion = readAgentsVersion(agentsPath)
41
+
42
+ if (currentVersion === cliVersion) {
43
+ success(`AGENTS.md is already up to date (v${cliVersion})`)
44
+ return
45
+ }
46
+
47
+ const content = generateAgentsContent()
48
+ writeFileSync(agentsPath, content)
49
+
50
+ if (currentVersion) {
51
+ success(`Updated AGENTS.md (v${currentVersion} → v${cliVersion})`)
52
+ } else {
53
+ success(`Created AGENTS.md (v${cliVersion})`)
54
+ }
55
+ }
package/src/index.js CHANGED
@@ -35,6 +35,7 @@ import { publish } from './commands/publish.js'
35
35
  import { deploy } from './commands/deploy.js'
36
36
  import { invite } from './commands/invite.js'
37
37
  import { handoff } from './commands/handoff.js'
38
+ import { update } from './commands/update.js'
38
39
  import { template } from './commands/template.js'
39
40
  import {
40
41
  resolveTemplate,
@@ -479,6 +480,12 @@ async function main() {
479
480
  return
480
481
  }
481
482
 
483
+ // Handle update command
484
+ if (command === 'update') {
485
+ await update(args.slice(1))
486
+ return
487
+ }
488
+
482
489
  // Handle inspect command
483
490
  if (command === 'inspect') {
484
491
  await inspect(args.slice(1))
@@ -794,6 +801,7 @@ ${colors.bright}Commands:${colors.reset}
794
801
  inspect <path> Inspect parsed content shape of a markdown file or folder
795
802
  docs Generate component documentation
796
803
  doctor Diagnose project configuration issues
804
+ update Update AGENTS.md to match installed CLI version
797
805
  i18n <cmd> Internationalization (extract, sync, status)
798
806
  template publish Publish a site as a cloud template
799
807
  login Log in to your Uniweb account
@@ -0,0 +1,41 @@
1
+ /**
2
+ * AGENTS.md version stamp utilities
3
+ *
4
+ * The stamp is an HTML comment on the first line: <!-- uniweb-agents v0.8.32 -->
5
+ * Used by `doctor` (freshness check) and `update` (regeneration).
6
+ */
7
+
8
+ import { existsSync, readFileSync } from 'node:fs'
9
+ import { join, dirname } from 'node:path'
10
+ import { fileURLToPath } from 'node:url'
11
+ import { getCliVersion } from '../versions.js'
12
+
13
+ const __dirname = dirname(fileURLToPath(import.meta.url))
14
+
15
+ const STAMP_PATTERN = /^<!-- uniweb-agents v([\d.]+) -->/
16
+
17
+ /**
18
+ * Read the version stamp from an AGENTS.md file
19
+ * @param {string} filePath - Absolute path to AGENTS.md
20
+ * @returns {string|null} Version string or null if no stamp
21
+ */
22
+ export function readAgentsVersion(filePath) {
23
+ if (!existsSync(filePath)) return null
24
+ try {
25
+ const firstLine = readFileSync(filePath, 'utf8').split('\n')[0]
26
+ const match = firstLine.match(STAMP_PATTERN)
27
+ return match ? match[1] : null
28
+ } catch {
29
+ return null
30
+ }
31
+ }
32
+
33
+ /**
34
+ * Generate AGENTS.md content with version stamp
35
+ * @returns {string} Full AGENTS.md content with stamp
36
+ */
37
+ export function generateAgentsContent() {
38
+ const partialsDir = join(__dirname, '..', '..', 'partials')
39
+ const agentsContent = readFileSync(join(partialsDir, 'agents.md'), 'utf8')
40
+ return `<!-- uniweb-agents v${getCliVersion()} -->\n${agentsContent}\n`
41
+ }
@@ -11,7 +11,7 @@ import { join, dirname } from 'node:path'
11
11
  import { fileURLToPath } from 'node:url'
12
12
  import yaml from 'js-yaml'
13
13
  import { copyTemplateDirectory, registerVersions } from '../templates/processor.js'
14
- import { getVersionsForTemplates } from '../versions.js'
14
+ import { getVersionsForTemplates, getCliVersion } from '../versions.js'
15
15
 
16
16
  const __dirname = dirname(fileURLToPath(import.meta.url))
17
17
  const TEMPLATES_DIR = join(__dirname, '..', '..', 'templates')
@@ -36,6 +36,9 @@ export async function scaffoldWorkspace(targetDir, context, options = {}) {
36
36
  // because an empty packages: [] makes pnpm search parent directories.
37
37
  const skip = context.workspaceGlobs?.length ? [] : ['pnpm-workspace.yaml']
38
38
 
39
+ // Inject CLI version for AGENTS.md stamp
40
+ context = { ...context, cliVersion: getCliVersion() }
41
+
39
42
  const templatePath = join(TEMPLATES_DIR, 'workspace')
40
43
  await copyTemplateDirectory(templatePath, targetDir, context, {
41
44
  onProgress: options.onProgress,
package/src/versions.js CHANGED
@@ -22,6 +22,15 @@ function getCliPackageJson() {
22
22
  return JSON.parse(readFileSync(packagePath, 'utf8'))
23
23
  }
24
24
 
25
+ /**
26
+ * Get the CLI's own version
27
+ *
28
+ * @returns {string} CLI version (e.g., "0.8.32")
29
+ */
30
+ export function getCliVersion() {
31
+ return getCliPackageJson().version
32
+ }
33
+
25
34
  /**
26
35
  * Extract version number from version spec (e.g., "^0.1.4" -> "0.1.4")
27
36
  */
@@ -1 +1,2 @@
1
+ <!-- uniweb-agents v{{cliVersion}} -->
1
2
  {{> agents}}