@uniweb/build 0.20.1 → 0.21.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.
Files changed (2) hide show
  1. package/package.json +5 -5
  2. package/src/site/plugin.js +49 -3
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uniweb/build",
3
- "version": "0.20.1",
3
+ "version": "0.21.0",
4
4
  "description": "Build tooling for the Uniweb Component Web Platform",
5
5
  "type": "module",
6
6
  "exports": {
@@ -60,15 +60,15 @@
60
60
  "sharp": "^0.35.3",
61
61
  "yaml": "^2.5.0",
62
62
  "@uniweb/schemas": "^0.2.10",
63
+ "@uniweb/projections": "^0.3.0",
63
64
  "@uniweb/theming": "^0.1.15",
64
- "@uniweb/content-writer": "^0.3.3",
65
- "@uniweb/projections": "^0.2.8"
65
+ "@uniweb/content-writer": "^0.3.3"
66
66
  },
67
67
  "optionalDependencies": {
68
- "@uniweb/runtime": "^0.11.7",
69
68
  "@uniweb/schemas": "^0.2.10",
69
+ "@uniweb/content-reader": "^1.2.2",
70
70
  "@uniweb/semantic-parser": "^1.2.2",
71
- "@uniweb/content-reader": "^1.2.2"
71
+ "@uniweb/runtime": "^0.11.7"
72
72
  },
73
73
  "peerDependencies": {
74
74
  "vite": "^5.0.0 || ^6.0.0 || ^7.0.0",
@@ -43,6 +43,7 @@ import {
43
43
  pageMarkdownFilename,
44
44
  branchIndexFilename,
45
45
  applyRouteTranslation,
46
+ partitionKnowledgePages,
46
47
  INDEX_FILENAME
47
48
  } from '@uniweb/projections'
48
49
  import { collectSiteContent, mountEntriesOf } from './content-collector.js'
@@ -505,6 +506,51 @@ export function siteContentPlugin(options = {}) {
505
506
  robots: seo.robots || {}
506
507
  }
507
508
 
509
+ // Warn once per build, not once per collection — the dev server re-collects
510
+ // on every content change and would otherwise repeat this on every keystroke.
511
+ let warnedAboutKnowledge = false
512
+
513
+ /**
514
+ * Collect the site, then drop `knowledge:` pages.
515
+ *
516
+ * ⛔ **This is the bundle lane, and the bundle lane has no agent endpoint.**
517
+ * `uniweb export` and `uniweb deploy --host <adapter>` both run this pipeline
518
+ * (`cli/src/commands/export.js`, `deploy.js`), and their destinations are
519
+ * static hosts — no worker, no backend, nothing that can gate a request. A
520
+ * `knowledge:` page is content the author marked for an agent and not for a
521
+ * visitor; here there is no agent to serve it to and no gate to withhold it
522
+ * with, so shipping it is disclosure with **no consumer on the other side**.
523
+ *
524
+ * Measured 2026-08-13, before this existed: a knowledge page became
525
+ * `dist/kb/index.html` — a public route — and its body rode in the
526
+ * `__SITE_CONTENT__` of *every* prerendered page including `404.html`,
527
+ * because that script carries the whole site.
528
+ *
529
+ * ⚠️ **Deliberately NOT inside `collectSiteContent`.** The link lane
530
+ * (`build-site-data.js`) calls that same collector and **must keep** these
531
+ * pages: it hands `site-content.json` to a backend that derives an agent
532
+ * corpus from it and gates access to that corpus. Same flag, two correct
533
+ * answers, decided by what is behind the destination — so the subtraction
534
+ * belongs to the pipeline, not to the collector.
535
+ */
536
+ async function collectForBundle(path, options) {
537
+ const collected = await collectSiteContent(path, options)
538
+ const { knowledgePages, renderedPages } = partitionKnowledgePages(collected.pages || [])
539
+ if (!knowledgePages.length) return collected
540
+
541
+ if (!warnedAboutKnowledge) {
542
+ warnedAboutKnowledge = true
543
+ const routes = knowledgePages.map(page => page.route).join(', ')
544
+ console.warn(
545
+ `[site-content] Dropped ${knowledgePages.length} knowledge page(s) from this build: ${routes}\n` +
546
+ ` This build targets a host that serves files only, so there is no agent endpoint to read them ` +
547
+ `and no gate to keep them from visitors. Use \`uniweb deploy\` to make them agent-readable.`
548
+ )
549
+ }
550
+
551
+ return { ...collected, pages: renderedPages }
552
+ }
553
+
508
554
  let siteContent = null
509
555
  let resolvedSitePath = null
510
556
  let resolvedPublicDir = null
@@ -738,7 +784,7 @@ export function siteContentPlugin(options = {}) {
738
784
  if (!isProduction) {
739
785
  try {
740
786
  // Do an early content collection to get the collections config
741
- const earlyContent = await collectSiteContent(resolvedSitePath, { foundationPath })
787
+ const earlyContent = await collectForBundle(resolvedSitePath, { foundationPath })
742
788
  collectionsConfig = earlyContent.config?.collections
743
789
 
744
790
  // Resolve content directory paths from site.yml paths: group
@@ -788,7 +834,7 @@ export function siteContentPlugin(options = {}) {
788
834
  // pages stay in the graph so in-progress drafts remain previewable.
789
835
  // strict on a production build: a mount that contributes no pages is a
790
836
  // warning while you author and a broken deploy once you ship.
791
- siteContent = await collectSiteContent(resolvedSitePath, { foundationPath, dropUnpublished: isProduction, base: basePath, strict: isProduction })
837
+ siteContent = await collectForBundle(resolvedSitePath, { foundationPath, dropUnpublished: isProduction, base: basePath, strict: isProduction })
792
838
  headHtml = await loadHeadHtml()
793
839
  console.log(`[site-content] Collected ${siteContent.pages?.length || 0} pages`)
794
840
 
@@ -841,7 +887,7 @@ export function siteContentPlugin(options = {}) {
841
887
  rebuildTimeout = setTimeout(async () => {
842
888
  console.log('[site-content] Content changed, rebuilding...')
843
889
  try {
844
- siteContent = await collectSiteContent(resolvedSitePath, { foundationPath, base: basePath })
890
+ siteContent = await collectForBundle(resolvedSitePath, { foundationPath, base: basePath })
845
891
  headHtml = await loadHeadHtml()
846
892
  // Execute fetches for the updated content
847
893
  await executeDevFetches(siteContent, resolvedSitePath)