gazetta 0.0.4 → 0.0.6

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 (50) hide show
  1. package/admin-dist/assets/{index-o6Ikobnh.js → index-CVC2_Byr.js} +68 -65
  2. package/admin-dist/assets/{index-CWxPBgs-.css → index-W1ylqX_Y.css} +1 -1
  3. package/admin-dist/index.html +2 -2
  4. package/dist/admin-api/routes/preview.js +4 -1
  5. package/dist/admin-api/routes/preview.js.map +1 -1
  6. package/dist/admin-api/routes/publish.d.ts.map +1 -1
  7. package/dist/admin-api/routes/publish.js +30 -7
  8. package/dist/admin-api/routes/publish.js.map +1 -1
  9. package/dist/assemble.d.ts +23 -0
  10. package/dist/assemble.d.ts.map +1 -0
  11. package/dist/assemble.js +95 -0
  12. package/dist/assemble.js.map +1 -0
  13. package/dist/cli/index.js +273 -4
  14. package/dist/cli/index.js.map +1 -1
  15. package/dist/content.d.ts +6 -0
  16. package/dist/content.d.ts.map +1 -0
  17. package/dist/content.js +28 -0
  18. package/dist/content.js.map +1 -0
  19. package/dist/editor/mount.d.ts.map +1 -1
  20. package/dist/editor/mount.js +11 -19
  21. package/dist/editor/mount.js.map +1 -1
  22. package/dist/formats.d.ts +60 -0
  23. package/dist/formats.d.ts.map +1 -0
  24. package/dist/formats.js +34 -0
  25. package/dist/formats.js.map +1 -0
  26. package/dist/index.d.ts +4 -2
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/index.js +5 -1
  29. package/dist/index.js.map +1 -1
  30. package/dist/manifest.d.ts.map +1 -1
  31. package/dist/manifest.js +1 -0
  32. package/dist/manifest.js.map +1 -1
  33. package/dist/publish-rendered.d.ts +6 -4
  34. package/dist/publish-rendered.d.ts.map +1 -1
  35. package/dist/publish-rendered.js +64 -12
  36. package/dist/publish-rendered.js.map +1 -1
  37. package/dist/resolver.d.ts.map +1 -1
  38. package/dist/resolver.js +3 -2
  39. package/dist/resolver.js.map +1 -1
  40. package/dist/targets.d.ts +3 -1
  41. package/dist/targets.d.ts.map +1 -1
  42. package/dist/targets.js +14 -10
  43. package/dist/targets.js.map +1 -1
  44. package/dist/types.d.ts +23 -4
  45. package/dist/types.d.ts.map +1 -1
  46. package/dist/workers/cloudflare-r2.d.ts +31 -0
  47. package/dist/workers/cloudflare-r2.d.ts.map +1 -0
  48. package/dist/workers/cloudflare-r2.js +122 -0
  49. package/dist/workers/cloudflare-r2.js.map +1 -0
  50. package/package.json +16 -2
@@ -1 +1 @@
1
- .publish-content[data-v-878d0536]{display:flex;flex-direction:column;gap:1rem}.publish-item[data-v-878d0536]{display:flex;align-items:center;gap:.5rem;font-weight:600;font-size:1rem}.publish-empty[data-v-878d0536]{color:#888;font-size:.875rem}.publish-label[data-v-878d0536]{font-size:.75rem;text-transform:uppercase;color:#888;letter-spacing:.03em}.publish-targets[data-v-878d0536]{display:flex;flex-direction:column;gap:.5rem}.publish-target[data-v-878d0536]{display:flex;align-items:center;gap:.5rem}.publish-target label[data-v-878d0536]{cursor:pointer}.publish-results[data-v-878d0536]{display:flex;flex-direction:column;gap:.5rem}.publish-result[data-v-878d0536]{display:flex;align-items:center;gap:.5rem;padding:.5rem;border-radius:6px}.publish-result.success[data-v-878d0536]{background:#052e16;color:#4ade80}.publish-result.error[data-v-878d0536]{background:#450a0a;color:#f87171}.result-target[data-v-878d0536]{font-weight:600}.result-detail[data-v-878d0536]{margin-left:auto;font-size:.875rem;opacity:.8}.fetch-content[data-v-359a5f85]{display:flex;flex-direction:column;gap:1rem}.fetch-empty[data-v-359a5f85]{color:#888;font-size:.875rem}.fetch-label[data-v-359a5f85]{font-size:.875rem;color:#aaa;margin-bottom:.5rem}.fetch-list[data-v-359a5f85]{width:100%}.fetch-result[data-v-359a5f85]{display:flex;align-items:flex-start;gap:.75rem;padding:.75rem;border-radius:6px}.fetch-result.success[data-v-359a5f85]{background:#052e16;color:#4ade80}.fetch-result.error[data-v-359a5f85]{background:#450a0a;color:#f87171}.fetch-items[data-v-359a5f85]{font-size:.75rem;opacity:.7;margin-top:.25rem}.cms-toolbar[data-v-acd86f5c]{border-radius:0;border-left:0;border-right:0;border-top:0}.cms-logo[data-v-acd86f5c]{font-weight:700;font-size:1.125rem;display:flex;align-items:center;gap:.5rem}.cms-site-name[data-v-acd86f5c]{margin-left:1rem;color:#888;font-size:.875rem}.cms-btn[data-v-acd86f5c]{margin-left:.5rem}.cms-toast[data-v-acd86f5c]{font-size:.8125rem;display:flex;align-items:center;gap:.375rem}.cms-toast-success[data-v-acd86f5c]{color:#16a34a}.cms-toast-error[data-v-acd86f5c]{color:#dc2626}.cms-toast-dirty[data-v-acd86f5c]{color:#d97706}.fade-enter-active[data-v-acd86f5c],.fade-leave-active[data-v-acd86f5c]{transition:opacity .2s}.fade-enter-from[data-v-acd86f5c],.fade-leave-to[data-v-acd86f5c]{opacity:0}*{box-sizing:border-box;margin:0;padding:0}html,body,#app,.cms-app{height:100%}body{font-family:system-ui,-apple-system,sans-serif;color:#1a1a1a;background:#fff}.dark body{color:#e4e4e7;background:#09090b}.cms-error{padding:2rem;color:#c00}.cms-loading{padding:2rem;color:#666}.create-content[data-v-b021d738]{display:flex;flex-direction:column;gap:1rem}.create-field[data-v-b021d738]{display:flex;flex-direction:column;gap:.375rem}.create-field label[data-v-b021d738]{font-size:.75rem;text-transform:uppercase;color:#888;letter-spacing:.03em}.create-input[data-v-b021d738],.create-list[data-v-b021d738]{width:100%}.create-hint[data-v-b021d738]{font-size:.75rem;color:#666}.create-error[data-v-b021d738]{color:#f87171;font-size:.875rem}.create-content[data-v-0b98775c]{display:flex;flex-direction:column;gap:1rem}.create-field[data-v-0b98775c]{display:flex;flex-direction:column;gap:.375rem}.create-field label[data-v-0b98775c]{font-size:.75rem;text-transform:uppercase;color:#888;letter-spacing:.03em}.create-input[data-v-0b98775c],.create-list[data-v-0b98775c]{width:100%}.create-error[data-v-0b98775c]{color:#f87171;font-size:.875rem}.site-tree h3[data-v-890f8b02]{font-size:.75rem;text-transform:uppercase;color:#888;margin-bottom:.5rem;letter-spacing:.05em}.tree[data-v-890f8b02]{font-size:.875rem}.new-btns[data-v-890f8b02]{display:flex;gap:.5rem;margin-top:.5rem}.node-row[data-v-890f8b02]{display:flex;align-items:center;gap:.25rem;width:100%}.node-label[data-v-890f8b02]{flex:1}.node-delete[data-v-890f8b02]{opacity:0;transition:opacity .15s}.node-row:hover .node-delete[data-v-890f8b02]{opacity:1}.add-content[data-v-db28dbd0]{display:flex;flex-direction:column;gap:1rem}.add-field[data-v-db28dbd0]{display:flex;flex-direction:column;gap:.375rem}.add-field label[data-v-db28dbd0]{font-size:.75rem;text-transform:uppercase;color:#888;letter-spacing:.03em}.add-input[data-v-db28dbd0],.add-list[data-v-db28dbd0]{width:100%}.add-error[data-v-db28dbd0]{color:#f87171;font-size:.875rem}.component-tree[data-v-51814cff]{margin-top:1.5rem}.component-tree h3[data-v-51814cff]{font-size:.75rem;text-transform:uppercase;color:#888;margin-bottom:.5rem;letter-spacing:.05em}.component-template[data-v-51814cff]{font-size:.75rem;color:#aaa;margin-bottom:.5rem}.tree[data-v-51814cff]{font-size:.875rem}.empty[data-v-51814cff]{font-size:.875rem;color:#aaa}.node-row[data-v-51814cff]{display:flex;align-items:center;gap:.5rem;width:100%}.node-label[data-v-51814cff]{flex:1}.node-template[data-v-51814cff]{font-size:.6875rem;color:#666}.node-actions[data-v-51814cff]{display:flex;gap:0;opacity:0;transition:opacity .15s}.node-row:hover .node-actions[data-v-51814cff]{opacity:1}.add-btn[data-v-51814cff]{margin-top:.5rem}.editor-panel h3[data-v-0ed9b006]{font-size:.75rem;text-transform:uppercase;color:#888;margin-bottom:1rem;letter-spacing:.05em}.editor-empty[data-v-0ed9b006]{color:#aaa;font-size:.875rem;display:flex;flex-direction:column;align-items:center;padding-top:3rem}.editor-container[data-v-0ed9b006]{font-size:.875rem}.preview-panel[data-v-28c53c49]{height:100%;display:flex;flex-direction:column}.preview-empty[data-v-28c53c49]{padding:3rem 1rem 1rem;color:#aaa;font-size:.875rem;display:flex;flex-direction:column;align-items:center}.preview-iframe[data-v-28c53c49]{flex:1;width:100%;border:0;background:#fff}.cms-editor[data-v-e4099a0e]{border:0;border-radius:0}.cms-panel[data-v-e4099a0e]{overflow:auto}.cms-panel-content[data-v-e4099a0e]{padding:1rem}
1
+ .publish-content[data-v-878d0536]{display:flex;flex-direction:column;gap:1rem}.publish-item[data-v-878d0536]{display:flex;align-items:center;gap:.5rem;font-weight:600;font-size:1rem}.publish-empty[data-v-878d0536]{color:#888;font-size:.875rem}.publish-label[data-v-878d0536]{font-size:.75rem;text-transform:uppercase;color:#888;letter-spacing:.03em}.publish-targets[data-v-878d0536]{display:flex;flex-direction:column;gap:.5rem}.publish-target[data-v-878d0536]{display:flex;align-items:center;gap:.5rem}.publish-target label[data-v-878d0536]{cursor:pointer}.publish-results[data-v-878d0536]{display:flex;flex-direction:column;gap:.5rem}.publish-result[data-v-878d0536]{display:flex;align-items:center;gap:.5rem;padding:.5rem;border-radius:6px}.publish-result.success[data-v-878d0536]{background:#052e16;color:#4ade80}.publish-result.error[data-v-878d0536]{background:#450a0a;color:#f87171}.result-target[data-v-878d0536]{font-weight:600}.result-detail[data-v-878d0536]{margin-left:auto;font-size:.875rem;opacity:.8}.fetch-content[data-v-359a5f85]{display:flex;flex-direction:column;gap:1rem}.fetch-empty[data-v-359a5f85]{color:#888;font-size:.875rem}.fetch-label[data-v-359a5f85]{font-size:.875rem;color:#aaa;margin-bottom:.5rem}.fetch-list[data-v-359a5f85]{width:100%}.fetch-result[data-v-359a5f85]{display:flex;align-items:flex-start;gap:.75rem;padding:.75rem;border-radius:6px}.fetch-result.success[data-v-359a5f85]{background:#052e16;color:#4ade80}.fetch-result.error[data-v-359a5f85]{background:#450a0a;color:#f87171}.fetch-items[data-v-359a5f85]{font-size:.75rem;opacity:.7;margin-top:.25rem}.cms-toolbar[data-v-ad5a7042]{border-radius:0;border-left:0;border-right:0;border-top:0}.cms-logo[data-v-ad5a7042]{font-weight:700;font-size:1.125rem;display:flex;align-items:center;gap:.5rem}.cms-site-name[data-v-ad5a7042]{margin-left:1rem;color:#888;font-size:.875rem}.cms-btn[data-v-ad5a7042]{margin-left:.5rem}.cms-toast[data-v-ad5a7042]{font-size:.8125rem;display:flex;align-items:center;gap:.375rem}.cms-toast-success[data-v-ad5a7042]{color:#16a34a}.cms-toast-error[data-v-ad5a7042]{color:#dc2626}.cms-toast-dirty[data-v-ad5a7042]{color:#d97706}.fade-enter-active[data-v-ad5a7042],.fade-leave-active[data-v-ad5a7042]{transition:opacity .2s}.fade-enter-from[data-v-ad5a7042],.fade-leave-to[data-v-ad5a7042]{opacity:0}*{box-sizing:border-box;margin:0;padding:0}html,body,#app,.cms-app{height:100%}body{font-family:system-ui,-apple-system,sans-serif;color:#1a1a1a;background:#fff}.dark body{color:#e4e4e7;background:#09090b}.cms-error{padding:2rem;color:#c00}.cms-loading{padding:2rem;color:#666}.create-content[data-v-b021d738]{display:flex;flex-direction:column;gap:1rem}.create-field[data-v-b021d738]{display:flex;flex-direction:column;gap:.375rem}.create-field label[data-v-b021d738]{font-size:.75rem;text-transform:uppercase;color:#888;letter-spacing:.03em}.create-input[data-v-b021d738],.create-list[data-v-b021d738]{width:100%}.create-hint[data-v-b021d738]{font-size:.75rem;color:#666}.create-error[data-v-b021d738]{color:#f87171;font-size:.875rem}.create-content[data-v-0b98775c]{display:flex;flex-direction:column;gap:1rem}.create-field[data-v-0b98775c]{display:flex;flex-direction:column;gap:.375rem}.create-field label[data-v-0b98775c]{font-size:.75rem;text-transform:uppercase;color:#888;letter-spacing:.03em}.create-input[data-v-0b98775c],.create-list[data-v-0b98775c]{width:100%}.create-error[data-v-0b98775c]{color:#f87171;font-size:.875rem}.site-tree h3[data-v-ccc411a6]{font-size:.75rem;text-transform:uppercase;color:#888;margin-bottom:.5rem;letter-spacing:.05em}.tree[data-v-ccc411a6]{font-size:.875rem}.new-btns[data-v-ccc411a6]{display:flex;gap:.5rem;margin-top:.5rem}.node-row[data-v-ccc411a6]{display:flex;align-items:center;gap:.25rem;width:100%}.node-label[data-v-ccc411a6]{flex:1}.node-delete[data-v-ccc411a6]{opacity:0;transition:opacity .15s}.node-row:hover .node-delete[data-v-ccc411a6]{opacity:1}.add-content[data-v-db28dbd0]{display:flex;flex-direction:column;gap:1rem}.add-field[data-v-db28dbd0]{display:flex;flex-direction:column;gap:.375rem}.add-field label[data-v-db28dbd0]{font-size:.75rem;text-transform:uppercase;color:#888;letter-spacing:.03em}.add-input[data-v-db28dbd0],.add-list[data-v-db28dbd0]{width:100%}.add-error[data-v-db28dbd0]{color:#f87171;font-size:.875rem}.component-tree[data-v-51814cff]{margin-top:1.5rem}.component-tree h3[data-v-51814cff]{font-size:.75rem;text-transform:uppercase;color:#888;margin-bottom:.5rem;letter-spacing:.05em}.component-template[data-v-51814cff]{font-size:.75rem;color:#aaa;margin-bottom:.5rem}.tree[data-v-51814cff]{font-size:.875rem}.empty[data-v-51814cff]{font-size:.875rem;color:#aaa}.node-row[data-v-51814cff]{display:flex;align-items:center;gap:.5rem;width:100%}.node-label[data-v-51814cff]{flex:1}.node-template[data-v-51814cff]{font-size:.6875rem;color:#666}.node-actions[data-v-51814cff]{display:flex;gap:0;opacity:0;transition:opacity .15s}.node-row:hover .node-actions[data-v-51814cff]{opacity:1}.add-btn[data-v-51814cff]{margin-top:.5rem}.editor-panel h3[data-v-0ed9b006]{font-size:.75rem;text-transform:uppercase;color:#888;margin-bottom:1rem;letter-spacing:.05em}.editor-empty[data-v-0ed9b006]{color:#aaa;font-size:.875rem;display:flex;flex-direction:column;align-items:center;padding-top:3rem}.editor-container[data-v-0ed9b006]{font-size:.875rem}.preview-panel[data-v-28c53c49]{height:100%;display:flex;flex-direction:column}.preview-empty[data-v-28c53c49]{padding:3rem 1rem 1rem;color:#aaa;font-size:.875rem;display:flex;flex-direction:column;align-items:center}.preview-iframe[data-v-28c53c49]{flex:1;width:100%;border:0;background:#fff}.cms-editor[data-v-e4099a0e]{border:0;border-radius:0}.cms-panel[data-v-e4099a0e]{overflow:auto}.cms-panel-content[data-v-e4099a0e]{padding:1rem}
@@ -5,8 +5,8 @@
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
6
  <title>Gazetta CMS</title>
7
7
  <link rel="stylesheet" href="https://unpkg.com/primeicons/primeicons.css">
8
- <script type="module" crossorigin src="/admin/assets/index-o6Ikobnh.js"></script>
9
- <link rel="stylesheet" crossorigin href="/admin/assets/index-CWxPBgs-.css">
8
+ <script type="module" crossorigin src="/admin/assets/index-CVC2_Byr.js"></script>
9
+ <link rel="stylesheet" crossorigin href="/admin/assets/index-W1ylqX_Y.css">
10
10
  </head>
11
11
  <body>
12
12
  <div id="app"></div>
@@ -26,7 +26,10 @@ async function renderPreview(c, siteDir, storage, overrides) {
26
26
  return c.html(await renderPage(resolved, page.metadata, params));
27
27
  }
28
28
  catch (err) {
29
- return c.html(`<pre style="color:red;padding:2rem">${err.message}</pre>`, 500);
29
+ const e = err;
30
+ const msg = e.message.replace(/</g, '&lt;').replace(/>/g, '&gt;');
31
+ const stack = (e.stack ?? '').replace(/</g, '&lt;').replace(/>/g, '&gt;');
32
+ return c.html(`<div style="font-family:system-ui;padding:2rem;color:#fca5a5;background:#1a1a2e;min-height:100vh"><h2 style="color:#f87171;margin-bottom:1rem">Template Error</h2><pre style="white-space:pre-wrap;font-size:0.875rem;line-height:1.7">${msg}</pre><details style="margin-top:1rem"><summary style="color:#52525b;cursor:pointer">Stack trace</summary><pre style="color:#52525b;font-size:0.75rem;margin-top:0.5rem">${stack}</pre></details></div>`, 500);
30
33
  }
31
34
  }
32
35
  }
@@ -1 +1 @@
1
- {"version":3,"file":"preview.js","sourceRoot":"","sources":["../../../src/admin-api/routes/preview.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"preview.js","sourceRoot":"","sources":["../../../src/admin-api/routes/preview.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAgB,MAAM,MAAM,CAAA;AAEzC,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAE9C,MAAM,UAAU,aAAa,CAAC,OAAe,EAAE,OAAwB;IACrE,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAA;IAEtB,GAAG,CAAC,GAAG,CAAC,YAAY,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QAChC,OAAO,aAAa,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,CAAA;IAC3C,CAAC,CAAC,CAAA;IAEF,GAAG,CAAC,IAAI,CAAC,YAAY,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QACjC,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,GAAG,CAAC,IAAI,EAA6D,CAAA;QAC1F,OAAO,aAAa,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,CAAA;IAC3D,CAAC,CAAC,CAAA;IAEF,OAAO,GAAG,CAAA;AACZ,CAAC;AAED,KAAK,UAAU,aAAa,CAC1B,CAAU,EACV,OAAe,EACf,OAAwB,EACxB,SAAmD;IAEnD,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;IAC7C,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,IAAI,GAAG,CAAA;IAEhF,KAAK,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QAC1C,MAAM,MAAM,GAAG,UAAU,CAAC,IAAI,CAAC,KAAK,EAAE,WAAW,CAAC,CAAA;QAClD,IAAI,MAAM,EAAE,CAAC;YACX,IAAI,CAAC;gBACH,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAA;gBAClD,IAAI,SAAS;oBAAE,cAAc,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAA;gBAClD,OAAO,CAAC,CAAC,IAAI,CAAC,MAAM,UAAU,CAAC,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAA;YAClE,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM,CAAC,GAAG,GAAY,CAAA;gBACtB,MAAM,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;gBACjE,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;gBACzE,OAAO,CAAC,CAAC,IAAI,CAAC,0OAA0O,GAAG,4KAA4K,KAAK,wBAAwB,EAAE,GAAG,CAAC,CAAA;YAC5c,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,CAAC,CAAC,IAAI,CAAC,uBAAuB,EAAE,GAAG,CAAC,CAAA;AAC7C,CAAC;AAED,SAAS,cAAc,CAAC,IAAuB,EAAE,SAAkD;IACjG,IAAI,IAAI,CAAC,IAAI,IAAI,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACtC,IAAI,CAAC,OAAO,GAAG,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACrC,CAAC;IACD,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QAClC,cAAc,CAAC,KAAK,EAAE,SAAS,CAAC,CAAA;IAClC,CAAC;AACH,CAAC;AAED,SAAS,UAAU,CAAC,KAAa,EAAE,IAAY;IAC7C,MAAM,UAAU,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IACnC,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IACjC,IAAI,UAAU,CAAC,MAAM,KAAK,SAAS,CAAC,MAAM;QAAE,OAAO,IAAI,CAAA;IAEvD,MAAM,MAAM,GAA2B,EAAE,CAAA;IACzC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3C,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YAClC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAAA;QAC/C,CAAC;aAAM,IAAI,UAAU,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;YAC1C,OAAO,IAAI,CAAA;QACb,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"publish.d.ts","sourceRoot":"","sources":["../../../src/admin-api/routes/publish.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAC3B,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAKnE,wBAAgB,aAAa,CAC3B,OAAO,EAAE,MAAM,EACf,aAAa,EAAE,eAAe,EAC9B,cAAc,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,EAC7C,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,8EA2J7C"}
1
+ {"version":3,"file":"publish.d.ts","sourceRoot":"","sources":["../../../src/admin-api/routes/publish.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAC3B,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAMnE,wBAAgB,aAAa,CAC3B,OAAO,EAAE,MAAM,EACf,aAAa,EAAE,eAAe,EAC9B,cAAc,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,EAC7C,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,8EAgL7C"}
@@ -1,6 +1,7 @@
1
1
  import { Hono } from 'hono';
2
2
  import { publishItems, resolveDependencies } from '../../publish.js';
3
- import { publishPageRendered, publishFragmentRendered, publishSiteManifest, publishFragmentIndex, createWorkerPurge } from '../../publish-rendered.js';
3
+ import { publishPageRendered, publishFragmentRendered, publishSiteManifest, publishFragmentIndex, createCloudflarePurge } from '../../publish-rendered.js';
4
+ import { loadSite } from '../../site-loader.js';
4
5
  export function publishRoutes(siteDir, sourceStorage, preInitTargets, targetConfigs) {
5
6
  const app = new Hono();
6
7
  // Background target initialization
@@ -57,7 +58,8 @@ export function publishRoutes(siteDir, sourceStorage, preInitTargets, targetConf
57
58
  for (const item of allItems) {
58
59
  if (item.startsWith('pages/')) {
59
60
  const pageName = item.replace('pages/', '');
60
- const { files } = await publishPageRendered(pageName, sourceStorage, siteDir, targetStorage);
61
+ const config = getTargetConfig(targetName);
62
+ const { files } = await publishPageRendered(pageName, sourceStorage, siteDir, targetStorage, config?.cache);
61
63
  totalFiles += files;
62
64
  }
63
65
  else if (item.startsWith('fragments/')) {
@@ -70,12 +72,33 @@ export function publishRoutes(siteDir, sourceStorage, preInitTargets, targetConf
70
72
  await publishSiteManifest(sourceStorage, siteDir, targetStorage);
71
73
  await publishFragmentIndex(sourceStorage, siteDir, targetStorage);
72
74
  totalFiles += 2;
73
- // 4. Purge edge cache if worker URL configured
75
+ // 4. Purge edge cache via Cloudflare API
74
76
  const config = getTargetConfig(targetName);
75
- if (config?.workerUrl) {
76
- const purge = createWorkerPurge(config.workerUrl);
77
- await purge.purgeAll();
78
- console.log(` ${targetName}: cache purged`);
77
+ const zoneId = process.env.CF_ZONE_ID;
78
+ const apiToken = process.env.CF_API_TOKEN;
79
+ if (config?.siteUrl && zoneId && apiToken) {
80
+ const purge = createCloudflarePurge(zoneId, apiToken);
81
+ const hasFragments = allItems.some(i => i.startsWith('fragments/'));
82
+ if (hasFragments) {
83
+ // Fragment changed — purge everything (all pages use fragments)
84
+ await purge.purgeAll();
85
+ console.log(` ${targetName}: cache purged (all)`);
86
+ }
87
+ else {
88
+ // Only pages changed — purge specific URLs
89
+ const site = await loadSite(siteDir, sourceStorage);
90
+ const urls = allItems
91
+ .filter(i => i.startsWith('pages/'))
92
+ .map(i => {
93
+ const page = site.pages.get(i.replace('pages/', ''));
94
+ return page ? `${config.siteUrl}${page.route}` : null;
95
+ })
96
+ .filter(Boolean);
97
+ if (urls.length > 0) {
98
+ await purge.purgeUrls(urls);
99
+ console.log(` ${targetName}: cache purged (${urls.join(', ')})`);
100
+ }
101
+ }
79
102
  }
80
103
  results.push({ target: targetName, success: true, copiedFiles: totalFiles });
81
104
  console.log(` ${targetName}: ${totalFiles} files`);
@@ -1 +1 @@
1
- {"version":3,"file":"publish.js","sourceRoot":"","sources":["../../../src/admin-api/routes/publish.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"publish.js","sourceRoot":"","sources":["../../../src/admin-api/routes/publish.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * ESI assembly — pure string functions, no I/O, no platform deps.
3
+ * Used by edge workers and Node servers to compose pages from fragments.
4
+ */
5
+ /** Parse and strip cache comment from page HTML */
6
+ export declare function parseCacheComment(html: string): {
7
+ html: string;
8
+ browser: number;
9
+ edge: number;
10
+ };
11
+ /** Split fragment HTML into head and body sections */
12
+ export declare function splitFragment(html: string): {
13
+ head: string;
14
+ body: string;
15
+ };
16
+ /** Find all ESI paths referenced in the page HTML */
17
+ export declare function findEsiPaths(html: string): string[];
18
+ /** Assemble page HTML with fragment head and body content */
19
+ export declare function assembleEsi(pageHtml: string, fragments: Map<string, {
20
+ head: string;
21
+ body: string;
22
+ }>): string;
23
+ //# sourceMappingURL=assemble.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assemble.d.ts","sourceRoot":"","sources":["../src/assemble.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,mDAAmD;AACnD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAQ/F;AAED,sDAAsD;AACtD,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAY1E;AAED,qDAAqD;AACrD,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAMnD;AAED,6DAA6D;AAC7D,wBAAgB,WAAW,CACzB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,GACrD,MAAM,CA0DR"}
@@ -0,0 +1,95 @@
1
+ /**
2
+ * ESI assembly — pure string functions, no I/O, no platform deps.
3
+ * Used by edge workers and Node servers to compose pages from fragments.
4
+ */
5
+ /** Parse and strip cache comment from page HTML */
6
+ export function parseCacheComment(html) {
7
+ const match = html.match(/^<!--cache:browser=(\d+),edge=(\d+)-->\n/);
8
+ if (!match)
9
+ return { html, browser: 0, edge: 86400 };
10
+ return {
11
+ html: html.slice(match[0].length),
12
+ browser: parseInt(match[1], 10),
13
+ edge: parseInt(match[2], 10),
14
+ };
15
+ }
16
+ /** Split fragment HTML into head and body sections */
17
+ export function splitFragment(html) {
18
+ const headStart = html.indexOf('<head>');
19
+ const headEnd = html.indexOf('</head>');
20
+ if (headStart === -1 || headEnd === -1) {
21
+ return { head: '', body: html };
22
+ }
23
+ return {
24
+ head: html.slice(headStart + 6, headEnd).trim(),
25
+ body: (html.slice(0, headStart) + html.slice(headEnd + 7)).trim(),
26
+ };
27
+ }
28
+ /** Find all ESI paths referenced in the page HTML */
29
+ export function findEsiPaths(html) {
30
+ const paths = new Set();
31
+ const regex = /<!--esi(?:-head)?:(\/[^>]+)-->/g;
32
+ let match;
33
+ while ((match = regex.exec(html)) !== null)
34
+ paths.add(match[1]);
35
+ return [...paths];
36
+ }
37
+ /** Assemble page HTML with fragment head and body content */
38
+ export function assembleEsi(pageHtml, fragments) {
39
+ const esiHeadRegex = /<!--esi-head:(\/[^>]+)-->/g;
40
+ const esiBodyRegex = /<!--esi:(\/[^>]+)-->/g;
41
+ // Collect ESI head order from page
42
+ const esiHeadOrder = [];
43
+ const esiHeadRegex2 = /<!--esi-head:(\/[^>]+)-->/g;
44
+ let m;
45
+ while ((m = esiHeadRegex2.exec(pageHtml)) !== null) {
46
+ if (!esiHeadOrder.includes(m[1]))
47
+ esiHeadOrder.push(m[1]);
48
+ }
49
+ // Collect CSS and JS separately, preserving fragment order, deduplicating
50
+ const cssLines = [];
51
+ const jsLines = [];
52
+ const otherLines = [];
53
+ const seen = new Set();
54
+ for (const path of esiHeadOrder) {
55
+ const frag = fragments.get(path);
56
+ if (!frag?.head)
57
+ continue;
58
+ for (const line of frag.head.split('\n').map(l => l.trim()).filter(Boolean)) {
59
+ if (seen.has(line))
60
+ continue;
61
+ seen.add(line);
62
+ if (line.includes('rel="stylesheet"') || line.includes("rel='stylesheet'")) {
63
+ cssLines.push(line);
64
+ }
65
+ else if (line.startsWith('<script')) {
66
+ jsLines.push(line);
67
+ }
68
+ else {
69
+ otherLines.push(line);
70
+ }
71
+ }
72
+ }
73
+ // Replace first esi-head with other + CSS, remove the rest
74
+ let html = pageHtml;
75
+ const collectedCss = [...otherLines, ...cssLines].join('\n ');
76
+ let cssInserted = false;
77
+ html = html.replace(esiHeadRegex, () => {
78
+ if (!cssInserted && collectedCss) {
79
+ cssInserted = true;
80
+ return collectedCss;
81
+ }
82
+ return '';
83
+ });
84
+ // Insert JS before </head> (after all CSS, preserving fragment order)
85
+ if (jsLines.length > 0) {
86
+ html = html.replace('</head>', ` ${jsLines.join('\n ')}\n</head>`);
87
+ }
88
+ // Replace esi body tags with fragment body content
89
+ html = html.replace(esiBodyRegex, (_match, path) => {
90
+ const frag = fragments.get(path);
91
+ return frag?.body ?? `<!-- fragment not found: ${path} -->`;
92
+ });
93
+ return html;
94
+ }
95
+ //# sourceMappingURL=assemble.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assemble.js","sourceRoot":"","sources":["../src/assemble.ts"],"names":[],"mappings":"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"}
package/dist/cli/index.js CHANGED
@@ -22,30 +22,40 @@ function printHelp() {
22
22
  Usage:
23
23
  gazetta init [dir] Create a new site
24
24
  gazetta dev [site-dir] Start dev server + CMS at /admin
25
+ gazetta publish [site-dir] Pre-render and publish to targets
26
+ gazetta deploy -t <name> Deploy worker to hosting (one-time setup)
27
+ gazetta validate [site-dir] Check site for broken references
25
28
  gazetta help Show this help message
26
29
 
27
30
  Options:
28
31
  --port, -p <port> Server port (default: 3000)
32
+ --target, -t <name> Target to publish/deploy to (default: all)
29
33
 
30
34
  Examples:
31
35
  gazetta init my-site # scaffold a new site
32
36
  gazetta dev # dev server + CMS
33
- gazetta dev ./my-site # specific site directory
34
- gazetta dev --port 8080 # custom port
37
+ gazetta publish # publish to all targets
38
+ gazetta publish -t production # publish to specific target
39
+ gazetta deploy -t production # deploy worker (one-time)
40
+ gazetta validate # check site for broken references
35
41
  `);
36
42
  }
37
43
  function parseArgs(input) {
38
44
  let siteDir = '.';
39
45
  let port;
46
+ let target;
40
47
  for (let i = 0; i < input.length; i++) {
41
48
  if (input[i] === '--port' || input[i] === '-p') {
42
49
  port = parseInt(input[++i], 10);
43
50
  }
51
+ else if (input[i] === '--target' || input[i] === '-t') {
52
+ target = input[++i];
53
+ }
44
54
  else if (!input[i].startsWith('-')) {
45
55
  siteDir = input[i];
46
56
  }
47
57
  }
48
- return { siteDir: resolve(siteDir), port };
58
+ return { siteDir: resolve(siteDir), port, target };
49
59
  }
50
60
  async function runInit(dir) {
51
61
  const { writeFile, mkdir } = await import('node:fs/promises');
@@ -67,6 +77,8 @@ const template: TemplateFunction = ({ children = [] }) => ({
67
77
  css: \`main { max-width: 800px; margin: 0 auto; padding: 2rem; font-family: system-ui, sans-serif; }
68
78
  \${children.map(c => c.css).join('\\n')}\`,
69
79
  js: children.map(c => c.js).filter(Boolean).join('\\n'),
80
+ head: \`<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>⚡</text></svg>">
81
+ \${children.map(c => c.head).filter(Boolean).join('\\n')}\`,
70
82
  })
71
83
 
72
84
  export default template
@@ -183,6 +195,254 @@ content:
183
195
  console.log(` npx gazetta dev`);
184
196
  console.log();
185
197
  }
198
+ async function runPublish(siteDir, targetName) {
199
+ const storage = createFilesystemProvider();
200
+ console.log(`\n Loading site from ${siteDir}...`);
201
+ const site = await loadSite(siteDir, storage);
202
+ // Load target configs from site.yaml
203
+ const siteYamlPath = join(siteDir, 'site.yaml');
204
+ if (!existsSync(siteYamlPath)) {
205
+ console.error(`\n Error: No site.yaml found at ${siteDir}\n`);
206
+ process.exit(1);
207
+ }
208
+ const siteYaml = yaml.load(readFileSync(siteYamlPath, 'utf-8'));
209
+ if (!siteYaml.targets || Object.keys(siteYaml.targets).length === 0) {
210
+ console.error(`\n Error: No targets configured in site.yaml\n`);
211
+ process.exit(1);
212
+ }
213
+ // Determine which targets to publish to
214
+ const targetNames = targetName ? [targetName] : Object.keys(siteYaml.targets);
215
+ for (const name of targetNames) {
216
+ if (!siteYaml.targets[name]) {
217
+ console.error(`\n Error: Unknown target "${name}". Available: ${Object.keys(siteYaml.targets).join(', ')}\n`);
218
+ process.exit(1);
219
+ }
220
+ }
221
+ // Initialize targets
222
+ const { createTargetRegistry } = await import('../targets.js');
223
+ const targets = await createTargetRegistry(Object.fromEntries(targetNames.map(n => [n, siteYaml.targets[n]])), siteDir);
224
+ const { publishPageRendered, publishFragmentRendered, publishSiteManifest, publishFragmentIndex } = await import('../publish-rendered.js');
225
+ console.log(`\n Site: ${site.manifest.name}`);
226
+ console.log(` Pages: ${[...site.pages.keys()].join(', ')}`);
227
+ console.log(` Fragments: ${[...site.fragments.keys()].join(', ')}`);
228
+ console.log(` Targets: ${targetNames.join(', ')}\n`);
229
+ for (const name of targetNames) {
230
+ const targetStorage = targets.get(name);
231
+ if (!targetStorage) {
232
+ console.error(` ${name}: SKIPPED (failed to initialize)`);
233
+ continue;
234
+ }
235
+ console.log(` Publishing to ${name}...`);
236
+ let totalFiles = 0;
237
+ // Publish all fragments
238
+ for (const fragName of site.fragments.keys()) {
239
+ const { files } = await publishFragmentRendered(fragName, storage, siteDir, targetStorage);
240
+ totalFiles += files;
241
+ console.log(` fragment: ${fragName} (${files} files)`);
242
+ }
243
+ // Publish all pages
244
+ for (const pageName of site.pages.keys()) {
245
+ const { files } = await publishPageRendered(pageName, storage, siteDir, targetStorage, siteYaml.targets[name]?.cache);
246
+ totalFiles += files;
247
+ console.log(` page: ${pageName} (${files} files)`);
248
+ }
249
+ // Site manifest + fragment index
250
+ await publishSiteManifest(storage, siteDir, targetStorage);
251
+ await publishFragmentIndex(storage, siteDir, targetStorage);
252
+ totalFiles += 2;
253
+ console.log(` ${name}: ${totalFiles} files published\n`);
254
+ }
255
+ // Purge cache once at the end (all targets)
256
+ const zoneId = process.env.CF_ZONE_ID;
257
+ const apiToken = process.env.CF_API_TOKEN;
258
+ if (zoneId && apiToken) {
259
+ const { createCloudflarePurge } = await import('../publish-rendered.js');
260
+ const purge = createCloudflarePurge(zoneId, apiToken);
261
+ await purge.purgeAll();
262
+ console.log(` Cache purged\n`);
263
+ }
264
+ console.log(` Done!\n`);
265
+ }
266
+ async function runDeploy(siteDir, targetName) {
267
+ const { execSync } = await import('node:child_process');
268
+ const { writeFile, mkdir, rm } = await import('node:fs/promises');
269
+ const siteYamlPath = join(siteDir, 'site.yaml');
270
+ if (!existsSync(siteYamlPath)) {
271
+ console.error(`\n Error: No site.yaml found at ${siteDir}\n`);
272
+ process.exit(1);
273
+ }
274
+ const siteYaml = yaml.load(readFileSync(siteYamlPath, 'utf-8'));
275
+ if (!siteYaml.targets) {
276
+ console.error(`\n Error: No targets configured in site.yaml\n`);
277
+ process.exit(1);
278
+ }
279
+ if (!targetName) {
280
+ console.error(`\n Error: --target is required for deploy\n Usage: gazetta deploy -t <target-name>\n`);
281
+ process.exit(1);
282
+ }
283
+ const target = siteYaml.targets[targetName];
284
+ if (!target) {
285
+ console.error(`\n Error: Unknown target "${targetName}". Available: ${Object.keys(siteYaml.targets).join(', ')}\n`);
286
+ process.exit(1);
287
+ }
288
+ if (!target.worker) {
289
+ console.error(`\n Error: Target "${targetName}" has no worker config. Add to site.yaml:\n\n worker:\n type: cloudflare\n name: my-site\n`);
290
+ process.exit(1);
291
+ }
292
+ if (target.worker.type !== 'cloudflare') {
293
+ console.error(`\n Error: Unsupported worker type "${target.worker.type}". Currently only "cloudflare" is supported.\n`);
294
+ process.exit(1);
295
+ }
296
+ // Generate worker in temp dir
297
+ const workerName = target.worker.name ?? targetName;
298
+ const bucketName = target.storage.bucket ?? workerName;
299
+ const tmpDir = join(siteDir, '.gazetta-deploy');
300
+ await rm(tmpDir, { recursive: true, force: true });
301
+ await mkdir(tmpDir, { recursive: true });
302
+ // Generate wrangler.toml
303
+ let wranglerToml = `name = "${workerName}"\nmain = "index.ts"\ncompatibility_date = "2024-12-01"\nworkers_dev = true\n\n[[r2_buckets]]\nbinding = "SITE_BUCKET"\nbucket_name = "${bucketName}"\n`;
304
+ // Add custom domain route if siteUrl is configured
305
+ if (target.siteUrl) {
306
+ const url = new URL(target.siteUrl);
307
+ const hostname = url.hostname;
308
+ wranglerToml += `\n[[routes]]\npattern = "${hostname}/*"\nzone_name = "${hostname}"\n`;
309
+ }
310
+ await writeFile(join(tmpDir, 'wrangler.toml'), wranglerToml);
311
+ // Generate worker entry point
312
+ const workerCode = `import { createWorker } from 'gazetta/workers/cloudflare-r2'\nexport default createWorker()\n`;
313
+ await writeFile(join(tmpDir, 'index.ts'), workerCode);
314
+ // Generate package.json for wrangler
315
+ const pkgJson = JSON.stringify({
316
+ type: 'module',
317
+ dependencies: { gazetta: '*', hono: '*' },
318
+ });
319
+ await writeFile(join(tmpDir, 'package.json'), pkgJson);
320
+ // Install deps and deploy
321
+ console.log(` Deploying worker "${workerName}" to Cloudflare...`);
322
+ try {
323
+ execSync('npm install --install-links ' + resolve(import.meta.dirname, '../..'), { cwd: tmpDir, stdio: 'pipe' });
324
+ const output = execSync('npx wrangler deploy', { cwd: tmpDir, stdio: 'pipe' }).toString();
325
+ const urlMatch = output.match(/https:\/\/[^\s]+/);
326
+ console.log(` Worker deployed: ${urlMatch?.[0] ?? workerName}`);
327
+ if (target.siteUrl)
328
+ console.log(` Site: ${target.siteUrl}`);
329
+ }
330
+ catch (err) {
331
+ const stderr = err.stderr?.toString() ?? err.message;
332
+ console.error(`\n Deploy failed: ${stderr}\n`);
333
+ process.exit(1);
334
+ }
335
+ finally {
336
+ await rm(tmpDir, { recursive: true, force: true });
337
+ }
338
+ console.log(`\n Worker deployed. Now publish content:\n gazetta publish -t ${targetName}\n`);
339
+ }
340
+ async function runValidate(siteDir) {
341
+ const storage = createFilesystemProvider();
342
+ console.log(`\n Validating ${siteDir}...\n`);
343
+ // 1. Check site.yaml
344
+ let site;
345
+ try {
346
+ site = await loadSite(siteDir, storage);
347
+ console.log(` ✓ site.yaml — ${site.manifest.name}`);
348
+ }
349
+ catch (err) {
350
+ console.error(` ✗ site.yaml — ${err.message}`);
351
+ process.exit(1);
352
+ }
353
+ let errors = 0;
354
+ // 2. Validate all fragments
355
+ for (const [fragName, frag] of site.fragments) {
356
+ try {
357
+ const { resolveComponent } = await import('../resolver.js');
358
+ const templatesDir = join(siteDir, 'templates');
359
+ const ctx = { site, templatesDir, visited: new Set(), path: [`@${fragName}`] };
360
+ await resolveComponent(`@${fragName}`, '', ctx);
361
+ const childCount = frag.components?.length ?? 0;
362
+ console.log(` ✓ fragment: ${fragName} (${childCount} components)`);
363
+ }
364
+ catch (err) {
365
+ console.error(` ✗ fragment: ${fragName} — ${err.message}`);
366
+ errors++;
367
+ }
368
+ }
369
+ // 3. Validate all pages
370
+ for (const [pageName, page] of site.pages) {
371
+ try {
372
+ await resolvePage(pageName, site);
373
+ const componentCount = page.components?.length ?? 0;
374
+ const fragmentCount = page.components?.filter(c => c.startsWith('@')).length ?? 0;
375
+ console.log(` ✓ page: ${pageName} (${componentCount} components, ${fragmentCount} fragments)`);
376
+ }
377
+ catch (err) {
378
+ console.error(` ✗ page: ${pageName} — ${err.message}`);
379
+ errors++;
380
+ }
381
+ }
382
+ // 4. List templates
383
+ const templatesDir = join(siteDir, 'templates');
384
+ try {
385
+ const entries = await storage.readDir(templatesDir);
386
+ const templateCount = entries.filter(e => e.isDirectory).length;
387
+ console.log(` ✓ ${templateCount} templates found`);
388
+ }
389
+ catch {
390
+ console.log(` ⚠ templates/ directory not found`);
391
+ }
392
+ console.log();
393
+ if (errors > 0) {
394
+ console.error(` ${errors} error${errors > 1 ? 's' : ''} found.\n`);
395
+ process.exit(1);
396
+ }
397
+ else {
398
+ console.log(` All good.\n`);
399
+ }
400
+ }
401
+ function renderErrorOverlay(err) {
402
+ const message = err.message.replace(/</g, '&lt;').replace(/>/g, '&gt;');
403
+ const stack = (err.stack ?? '').replace(/</g, '&lt;').replace(/>/g, '&gt;');
404
+ // Extract file path from error message or stack
405
+ const fileMatch = stack.match(/\(?(\/[^\s:)]+):(\d+)/);
406
+ const filePath = fileMatch ? fileMatch[1] : '';
407
+ const lineNum = fileMatch ? fileMatch[2] : '';
408
+ const location = filePath ? `${filePath}${lineNum ? `:${lineNum}` : ''}` : '';
409
+ return `<!DOCTYPE html>
410
+ <html>
411
+ <head>
412
+ <meta charset="UTF-8">
413
+ <title>Error — Gazetta</title>
414
+ <style>
415
+ * { margin: 0; padding: 0; box-sizing: border-box; }
416
+ body { font-family: system-ui, -apple-system, sans-serif; background: #1a1a2e; color: #e4e4e7; min-height: 100vh; display: flex; align-items: center; justify-content: center; }
417
+ .overlay { max-width: 48rem; width: 100%; margin: 2rem; }
418
+ .header { display: flex; align-items: center; gap: 0.75rem; margin-bottom: 1.5rem; }
419
+ .header svg { flex-shrink: 0; }
420
+ .header h1 { font-size: 1.25rem; font-weight: 600; color: #f87171; }
421
+ .message { background: #0f0f1a; border: 1px solid #27272a; border-radius: 8px; padding: 1.5rem; margin-bottom: 1rem; font-family: 'JetBrains Mono', 'Fira Code', monospace; font-size: 0.875rem; line-height: 1.7; white-space: pre-wrap; word-break: break-word; color: #fca5a5; }
422
+ .location { font-size: 0.8125rem; color: #71717a; margin-bottom: 1rem; }
423
+ .location span { color: #a78bfa; }
424
+ .stack { background: #0f0f1a; border: 1px solid #27272a; border-radius: 8px; padding: 1.5rem; font-family: 'JetBrains Mono', 'Fira Code', monospace; font-size: 0.75rem; line-height: 1.7; white-space: pre-wrap; word-break: break-word; color: #52525b; max-height: 20rem; overflow: auto; }
425
+ .hint { margin-top: 1.5rem; font-size: 0.8125rem; color: #52525b; }
426
+ </style>
427
+ </head>
428
+ <body>
429
+ <div class="overlay">
430
+ <div class="header">
431
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#f87171" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/></svg>
432
+ <h1>Template Error</h1>
433
+ </div>
434
+ ${location ? `<div class="location">File: <span>${location}</span></div>` : ''}
435
+ <div class="message">${message}</div>
436
+ <details>
437
+ <summary style="color:#52525b;font-size:0.8125rem;cursor:pointer;margin-bottom:0.5rem">Stack trace</summary>
438
+ <div class="stack">${stack}</div>
439
+ </details>
440
+ <div class="hint">Fix the error and save — the page will reload automatically.</div>
441
+ </div>
442
+ <script>new EventSource('/__reload').onmessage = () => location.reload()</script>
443
+ </body>
444
+ </html>`;
445
+ }
186
446
  async function runDev(siteDir, port) {
187
447
  const storage = createFilesystemProvider();
188
448
  console.log(`\n Loading site from ${siteDir}...`);
@@ -221,7 +481,7 @@ async function runDev(siteDir, port) {
221
481
  return c.html(html.replace('</body>', `${RELOAD_SCRIPT}\n</body>`));
222
482
  }
223
483
  catch (err) {
224
- return c.html(`<pre style="color:red;padding:2rem">${err.message}</pre>`, 500);
484
+ return c.html(renderErrorOverlay(err), 500);
225
485
  }
226
486
  });
227
487
  }
@@ -424,6 +684,15 @@ async function main() {
424
684
  case 'init':
425
685
  await runInit(args[1] ?? '.');
426
686
  break;
687
+ case 'publish':
688
+ await runPublish(parsed.siteDir, parsed.target);
689
+ break;
690
+ case 'deploy':
691
+ await runDeploy(parsed.siteDir, parsed.target);
692
+ break;
693
+ case 'validate':
694
+ await runValidate(parsed.siteDir);
695
+ break;
427
696
  case 'dev':
428
697
  await runDev(parsed.siteDir, parsed.port ?? 3000);
429
698
  break;