@agent-cms/agentcms 0.0.0-stage → 0.1.1

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 (84) hide show
  1. package/LICENSE +143 -0
  2. package/README.md +1119 -2
  3. package/changelog.json +31 -0
  4. package/dist/admin/admin-files.json +48 -0
  5. package/dist/admin/assets/CodeEditor-Wx1WlF3h.js +24 -0
  6. package/dist/admin/assets/flexweg-logo-CdtuqAFA.png +0 -0
  7. package/dist/admin/assets/index-DFVZw8E0.js +5460 -0
  8. package/dist/admin/assets/index-DMcGogR2.css +1 -0
  9. package/dist/admin/assets/sql-wasm-Bfkbn6Oa.js +2 -0
  10. package/dist/admin/assets/sql-wasm-C1U8OeUW.wasm +0 -0
  11. package/dist/admin/assets/sql-wasm-V5jTDcrT.js +1 -0
  12. package/dist/admin/config.js +11 -0
  13. package/dist/admin/external.default.json +72 -0
  14. package/dist/admin/index.html +116 -0
  15. package/dist/admin/plugins/core-seo/bundle.js +55 -0
  16. package/dist/admin/plugins/core-seo/manifest.json +7 -0
  17. package/dist/admin/plugins/flexweg-archives/bundle.js +1414 -0
  18. package/dist/admin/plugins/flexweg-archives/manifest.json +7 -0
  19. package/dist/admin/plugins/flexweg-multilang/bundle.js +1187 -0
  20. package/dist/admin/plugins/flexweg-multilang/manifest.json +7 -0
  21. package/dist/admin/plugins/flexweg-rss/bundle.js +1354 -0
  22. package/dist/admin/plugins/flexweg-rss/manifest.json +7 -0
  23. package/dist/admin/plugins/flexweg-search/bundle.js +1243 -0
  24. package/dist/admin/plugins/flexweg-search/manifest.json +7 -0
  25. package/dist/admin/plugins/flexweg-sitemaps/bundle.js +1293 -0
  26. package/dist/admin/plugins/flexweg-sitemaps/manifest.json +7 -0
  27. package/dist/admin/runtime/cms-runtime.js +164 -0
  28. package/dist/admin/runtime/react-dom-client.js +13 -0
  29. package/dist/admin/runtime/react-dom.js +16 -0
  30. package/dist/admin/runtime/react-i18next.js +21 -0
  31. package/dist/admin/runtime/react-jsx-runtime.js +17 -0
  32. package/dist/admin/runtime/react.js +55 -0
  33. package/dist/admin/themes/corporate/bundle.js +14465 -0
  34. package/dist/admin/themes/corporate/manifest.json +7 -0
  35. package/dist/admin/themes/corporate/theme.css +2 -0
  36. package/dist/admin/themes/magazine/bundle.js +10229 -0
  37. package/dist/admin/themes/magazine/manifest.json +7 -0
  38. package/dist/admin/themes/magazine/theme.css +2 -0
  39. package/dist/admin/themes/marketplace-core/bundle.js +11213 -0
  40. package/dist/admin/themes/marketplace-core/manifest.json +7 -0
  41. package/dist/admin/themes/marketplace-core/theme.css +1613 -0
  42. package/dist/admin/themes/portfolio/bundle.js +9195 -0
  43. package/dist/admin/themes/portfolio/manifest.json +7 -0
  44. package/dist/admin/themes/portfolio/theme.css +2 -0
  45. package/dist/admin/themes/storefront/bundle.js +13172 -0
  46. package/dist/admin/themes/storefront/manifest.json +7 -0
  47. package/dist/admin/themes/storefront/theme.css +2 -0
  48. package/dist/agent/agentcms.mjs +1711 -0
  49. package/dist/agent/chunks/hosting-BftlDdsL.mjs +117 -0
  50. package/dist/agent/chunks/index-BG05qslv.mjs +3608 -0
  51. package/dist/agent/chunks/install-DnmgOT3F.mjs +577 -0
  52. package/dist/agent/chunks/plan-BrM8ztEp.mjs +245 -0
  53. package/dist/agent/chunks/registry-C9TSnZ77.mjs +53517 -0
  54. package/dist/agent/chunks/siteAdd-BcXhN9fk.mjs +118 -0
  55. package/dist/agent/chunks/sql-wasm-GjJDiefO.mjs +10 -0
  56. package/dist/agent/chunks/sqljs-DjSCStJ0.mjs +20 -0
  57. package/dist/agent/vendor/sql-wasm.cjs +188 -0
  58. package/dist/theme-assets/corporate-menu.js +266 -0
  59. package/dist/theme-assets/corporate-posts.js +571 -0
  60. package/dist/theme-assets/corporate.css +2 -0
  61. package/dist/theme-assets/default-menu.js +266 -0
  62. package/dist/theme-assets/default-posts.js +378 -0
  63. package/dist/theme-assets/default.css +1 -0
  64. package/dist/theme-assets/magazine-menu.js +227 -0
  65. package/dist/theme-assets/magazine-posts.js +361 -0
  66. package/dist/theme-assets/magazine.css +2 -0
  67. package/dist/theme-assets/portfolio-filters.js +104 -0
  68. package/dist/theme-assets/portfolio-menu.js +240 -0
  69. package/dist/theme-assets/portfolio-posts.js +358 -0
  70. package/dist/theme-assets/portfolio.css +2 -0
  71. package/dist/theme-assets/storefront-catalog.js +504 -0
  72. package/dist/theme-assets/storefront-menu.js +239 -0
  73. package/dist/theme-assets/storefront-posts.js +404 -0
  74. package/dist/theme-assets/storefront.css +2 -0
  75. package/dist/version.json +9 -0
  76. package/package.json +101 -4
  77. package/plugin/.claude-plugin/plugin.json +16 -0
  78. package/plugin/skills/agentcms-install/SKILL.md +110 -0
  79. package/plugin/skills/agentcms-install/references/cloudflare.md +15 -0
  80. package/plugin/skills/agentcms-install/references/flexweg.md +11 -0
  81. package/plugin/skills/agentcms-install/references/github.md +67 -0
  82. package/plugin/skills/agentcms-install/references/gitlab.md +15 -0
  83. package/plugin/skills/agentcms-install/references/s3.md +81 -0
  84. package/plugin/skills/agentcms-manage/SKILL.md +92 -0
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Portfolio theme — runtime project filters.
3
+ *
4
+ * Wires the [data-cms-portfolio-filters] chip cloud on the home page
5
+ * (and any other page that ships filterable cards). Source of truth
6
+ * is the rendered DOM:
7
+ * - Every project card carries `data-cms-category="<slug>"`.
8
+ * - The chip cloud already has an "All" chip with
9
+ * `data-cms-filter="*"` baked in by the template.
10
+ *
11
+ * On boot we:
12
+ * 1. Read every unique category slug present on the page.
13
+ * 2. Append one button[data-cms-filter="<slug>"] per slug to the
14
+ * filter host, labelled from the first card carrying that slug
15
+ * via its category meta (the meta is uppercase already).
16
+ * 3. Wire click handlers that toggle `is-active` on the buttons
17
+ * and show/hide cards (display:none) by matching
18
+ * `data-cms-category`.
19
+ *
20
+ * The implementation is purposefully without animation — the design
21
+ * system rejects transitions on layout to keep the architectural
22
+ * feel. The card list reflows instantly.
23
+ */
24
+ (function () {
25
+ "use strict";
26
+
27
+ function init() {
28
+ var host = document.querySelector("[data-cms-portfolio-filters]");
29
+ if (!host) return;
30
+ var cards = Array.prototype.slice.call(
31
+ document.querySelectorAll("[data-cms-category]"),
32
+ );
33
+ if (cards.length === 0) {
34
+ host.setAttribute("hidden", "");
35
+ return;
36
+ }
37
+
38
+ // Gather unique slugs + their human label (taken from the
39
+ // first card's `.project-card__meta` text — the "CATEGORY / 2024"
40
+ // string. We split on " / " and use the leading word.)
41
+ var slugToLabel = {};
42
+ cards.forEach(function (card) {
43
+ var slug = card.getAttribute("data-cms-category");
44
+ if (!slug) return;
45
+ if (slugToLabel[slug]) return;
46
+ var metaEl = card.querySelector(".project-card__meta");
47
+ var rawMeta = metaEl ? metaEl.textContent || "" : "";
48
+ var label = rawMeta.split(" / ")[0].trim();
49
+ slugToLabel[slug] = label || slug.toUpperCase();
50
+ });
51
+
52
+ var slugs = Object.keys(slugToLabel).sort();
53
+ if (slugs.length === 0) {
54
+ host.setAttribute("hidden", "");
55
+ return;
56
+ }
57
+
58
+ // Append a chip button per slug. The "All" chip (data-cms-filter="*")
59
+ // is already in the DOM from the template.
60
+ slugs.forEach(function (slug) {
61
+ var chip = document.createElement("button");
62
+ chip.type = "button";
63
+ chip.className = "portfolio-btn-outline";
64
+ chip.setAttribute("data-cms-filter", slug);
65
+ chip.textContent = slugToLabel[slug];
66
+ host.appendChild(chip);
67
+ });
68
+
69
+ function applyFilter(slug) {
70
+ var showAll = slug === "*" || !slug;
71
+ cards.forEach(function (card) {
72
+ if (showAll) {
73
+ card.style.display = "";
74
+ return;
75
+ }
76
+ var cardSlug = card.getAttribute("data-cms-category");
77
+ card.style.display = cardSlug === slug ? "" : "none";
78
+ });
79
+ // Update active state on the chips.
80
+ host.querySelectorAll("[data-cms-filter]").forEach(function (btn) {
81
+ var thisSlug = btn.getAttribute("data-cms-filter");
82
+ if (thisSlug === slug || (showAll && thisSlug === "*")) {
83
+ btn.classList.add("is-active");
84
+ } else {
85
+ btn.classList.remove("is-active");
86
+ }
87
+ });
88
+ }
89
+
90
+ host.addEventListener("click", function (event) {
91
+ var target = event.target;
92
+ if (!(target instanceof Element)) return;
93
+ var btn = target.closest("[data-cms-filter]");
94
+ if (!btn) return;
95
+ applyFilter(btn.getAttribute("data-cms-filter"));
96
+ });
97
+ }
98
+
99
+ if (document.readyState === "loading") {
100
+ document.addEventListener("DOMContentLoaded", init);
101
+ } else {
102
+ init();
103
+ }
104
+ })();
@@ -0,0 +1,240 @@
1
+ /**
2
+ * Storefront theme — runtime menu loader.
3
+ *
4
+ * Same contract as default / magazine / corporate: fetches /data/menu.json
5
+ * and paints every `[data-cms-menu]` container on the page. The storefront
6
+ * header ships TWO such containers — the inline horizontal nav (visible
7
+ * md+) and the off-canvas burger overlay (always present, opens on
8
+ * burger-toggle click). The storefront bottom-nav links also pick up the
9
+ * `aria-current="page"` state via the same `samePath` helper.
10
+ *
11
+ * Differences vs corporate:
12
+ * - Branding logo gets `h-8 w-auto` to fit the storefront header (h-16).
13
+ * - Burger menu links use the editorial serif + sage active color.
14
+ */
15
+ (function () {
16
+ "use strict";
17
+
18
+ // ─── Base path ────────────────────────────────────────────────────
19
+ // Sites served from a sub-folder (e.g. GitHub Pages project sites)
20
+ // carry <meta name="x-cms-base" content="/repo/"> in <head>; no meta
21
+ // means the site lives at the domain root. URLs built at runtime from
22
+ // JSON data go through withBase() so they land under that folder.
23
+ var BASE = (function () {
24
+ var meta = document.querySelector('meta[name="x-cms-base"]');
25
+ var b = (meta && meta.getAttribute("content")) || "/";
26
+ if (b.charAt(0) !== "/") b = "/" + b;
27
+ if (b.charAt(b.length - 1) !== "/") b += "/";
28
+ return b;
29
+ })();
30
+
31
+ function withBase(url) {
32
+ if (BASE === "/" || !url) return url;
33
+ // Absolute URLs (http:, mailto:, data:, …), protocol-relative and
34
+ // fragment-only links pass through.
35
+ if (/^([a-z][a-z0-9+.-]*:|\/\/|#)/i.test(url)) return url;
36
+ if (url.indexOf(BASE) === 0 || url === BASE.slice(0, -1)) return url;
37
+ return BASE + (url.charAt(0) === "/" ? url.slice(1) : url);
38
+ }
39
+
40
+ function fetchMenu() {
41
+ return fetch(withBase("/data/menu.json"), { credentials: "omit" })
42
+ .then(function (res) {
43
+ if (!res.ok) throw new Error("HTTP " + res.status);
44
+ return res.json();
45
+ })
46
+ .catch(function (err) {
47
+ console.warn("[cms] menu.json load failed:", err);
48
+ return null;
49
+ });
50
+ }
51
+
52
+ function samePath(href) {
53
+ try {
54
+ var url = new URL(href, window.location.origin);
55
+ var here = window.location.pathname.replace(/\/index\.html$/, "/");
56
+ var there = url.pathname.replace(/\/index\.html$/, "/");
57
+ return here === there;
58
+ } catch (e) {
59
+ return false;
60
+ }
61
+ }
62
+
63
+ // Picks the per-language label from item.labels (set by the admin
64
+ // in the menu builder) based on <html lang>, with a region-stripped
65
+ // fallback so "en-US" matches "en". Mono-lingual sites just return
66
+ // item.label.
67
+ function pickLabel(item) {
68
+ var lang = (document.documentElement.getAttribute("lang") || "").trim();
69
+ if (lang && item.labels && typeof item.labels[lang] === "string" && item.labels[lang]) {
70
+ return item.labels[lang];
71
+ }
72
+ if (lang && lang.indexOf("-") > 0) {
73
+ var base = lang.split("-")[0];
74
+ if (item.labels && typeof item.labels[base] === "string" && item.labels[base]) {
75
+ return item.labels[base];
76
+ }
77
+ }
78
+ return item.label || "";
79
+ }
80
+
81
+ function renderBurgerItem(item) {
82
+ var li = document.createElement("li");
83
+ var a = document.createElement("a");
84
+ a.href = withBase(item.href) || "#";
85
+ a.textContent = pickLabel(item);
86
+ if (samePath(a.href)) a.setAttribute("aria-current", "page");
87
+ li.appendChild(a);
88
+ if (item.children && item.children.length) {
89
+ var sub = document.createElement("ul");
90
+ sub.className = "menu-children";
91
+ item.children.forEach(function (child) {
92
+ sub.appendChild(renderBurgerItem(child));
93
+ });
94
+ li.appendChild(sub);
95
+ }
96
+ return li;
97
+ }
98
+
99
+ function renderInlineItem(item) {
100
+ var a = document.createElement("a");
101
+ a.href = withBase(item.href) || "#";
102
+ a.textContent = pickLabel(item);
103
+ // Portfolio nav uses the `nav-link` component class declared in
104
+ // theme.css — the active-state pink dot lives there. No
105
+ // Tailwind-specific styling per link here so the theme can change
106
+ // typography without rebuilding the loader.
107
+ a.className = "nav-link";
108
+ var active = samePath(a.href);
109
+ if (active) {
110
+ a.setAttribute("aria-current", "page");
111
+ a.classList.add("is-active");
112
+ }
113
+ return a;
114
+ }
115
+
116
+ function paint(menu) {
117
+ if (!menu) return;
118
+ document.querySelectorAll("[data-cms-menu]").forEach(function (host) {
119
+ var key = host.getAttribute("data-cms-menu");
120
+ var items = (menu && menu[key]) || [];
121
+ var inline = host.hasAttribute("data-cms-menu-inline");
122
+
123
+ if (inline) {
124
+ host.innerHTML = "";
125
+ items.forEach(function (item) {
126
+ host.appendChild(renderInlineItem(item));
127
+ });
128
+ } else {
129
+ var list = host.querySelector("ul");
130
+ if (!list) return;
131
+ list.innerHTML = "";
132
+ items.forEach(function (item) {
133
+ list.appendChild(renderBurgerItem(item));
134
+ });
135
+ }
136
+
137
+ // Hide empty inline / footer hosts so they don't reserve
138
+ // whitespace. Skip #burger-menu: it's `position: fixed` (no
139
+ // layout impact) AND any `hidden` attribute would `display:
140
+ // none` the panel, which the `.burger-menu.is-open { transform:
141
+ // translate(0) }` rule can never override — the burger toggle
142
+ // would open an invisible panel. Visibility of the burger UI is
143
+ // gated by the burger TOGGLE button below instead.
144
+ var isBurgerMenu = host.id === "burger-menu";
145
+ if (items.length === 0 && !isBurgerMenu) host.setAttribute("hidden", "");
146
+ else host.removeAttribute("hidden");
147
+ });
148
+ // Hide the burger TOGGLE button when the header menu has no
149
+ // items — otherwise users see a button that opens an empty
150
+ // off-canvas panel and conclude "the burger is broken".
151
+ var headerItems = (menu && menu.header) || [];
152
+ document.querySelectorAll(".burger-toggle").forEach(function (toggle) {
153
+ if (headerItems.length === 0) toggle.setAttribute("hidden", "");
154
+ else toggle.removeAttribute("hidden");
155
+ });
156
+ paintBranding(menu);
157
+ }
158
+
159
+ // Swap the wordmark for an <img> when the theme has a logo
160
+ // configured. Falls back to the static text in every other case.
161
+ function paintBranding(menu) {
162
+ var branding = menu && menu.branding;
163
+ var logoUrl = branding && branding.logoUrl;
164
+ if (!logoUrl) return;
165
+ document.querySelectorAll("[data-cms-brand]").forEach(function (host) {
166
+ var alt = host.textContent || "";
167
+ var img = document.createElement("img");
168
+ img.src = withBase(logoUrl);
169
+ img.alt = alt;
170
+ img.className = "h-8 w-auto";
171
+ img.loading = "lazy";
172
+ host.innerHTML = "";
173
+ host.appendChild(img);
174
+ });
175
+ }
176
+
177
+ function ensureCloseButton(menu) {
178
+ if (menu.querySelector(".burger-close")) return menu.querySelector(".burger-close");
179
+ var close = document.createElement("button");
180
+ close.type = "button";
181
+ close.className = "burger-close";
182
+ close.setAttribute("aria-label", "Close menu");
183
+ close.innerHTML =
184
+ '<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>';
185
+ menu.insertBefore(close, menu.firstChild);
186
+ return close;
187
+ }
188
+
189
+ function ensureBackdrop() {
190
+ var existing = document.querySelector(".burger-backdrop");
191
+ if (existing) return existing;
192
+ var backdrop = document.createElement("div");
193
+ backdrop.className = "burger-backdrop";
194
+ backdrop.setAttribute("aria-hidden", "true");
195
+ document.body.appendChild(backdrop);
196
+ return backdrop;
197
+ }
198
+
199
+ function wireBurger() {
200
+ var toggle = document.querySelector(".burger-toggle");
201
+ var menu = document.getElementById("burger-menu");
202
+ if (!toggle || !menu) return;
203
+ var close = ensureCloseButton(menu);
204
+ var backdrop = ensureBackdrop();
205
+ function setOpen(open) {
206
+ toggle.setAttribute("aria-expanded", open ? "true" : "false");
207
+ menu.classList.toggle("is-open", open);
208
+ backdrop.classList.toggle("is-open", open);
209
+ document.body.classList.toggle("burger-open", open);
210
+ }
211
+ toggle.addEventListener("click", function () {
212
+ var isOpen = toggle.getAttribute("aria-expanded") === "true";
213
+ setOpen(!isOpen);
214
+ });
215
+ close.addEventListener("click", function () { setOpen(false); });
216
+ backdrop.addEventListener("click", function () { setOpen(false); });
217
+ document.addEventListener("keydown", function (e) {
218
+ if (e.key === "Escape") setOpen(false);
219
+ });
220
+ menu.addEventListener("click", function (e) {
221
+ if (e.target.tagName === "A") setOpen(false);
222
+ });
223
+ document.addEventListener("pointerdown", function (e) {
224
+ if (toggle.getAttribute("aria-expanded") !== "true") return;
225
+ if (menu.contains(e.target)) return;
226
+ if (toggle.contains(e.target)) return;
227
+ setOpen(false);
228
+ });
229
+ }
230
+
231
+ function ready(fn) {
232
+ if (document.readyState !== "loading") fn();
233
+ else document.addEventListener("DOMContentLoaded", fn);
234
+ }
235
+
236
+ ready(function () {
237
+ wireBurger();
238
+ fetchMenu().then(paint);
239
+ });
240
+ })();