frontend-auto-cms 1.0.11 → 1.0.13

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.
@@ -1,17 +1,17 @@
1
- const xe = "cms-export.patch.json", ve = "frontend-auto-cms::content", te = "frontend-auto-cms::locales";
2
- function ae(e) {
1
+ const xe = "cms-export.patch.json", ve = "frontend-auto-cms::content", ne = "frontend-auto-cms::locales";
2
+ function oe(e) {
3
3
  localStorage.setItem(ve, JSON.stringify(e));
4
4
  }
5
- function ne() {
5
+ function re() {
6
6
  try {
7
- const e = localStorage.getItem(te);
7
+ const e = localStorage.getItem(ne);
8
8
  return e ? JSON.parse(e) : {};
9
9
  } catch {
10
10
  return {};
11
11
  }
12
12
  }
13
13
  function I(e) {
14
- localStorage.setItem(te, JSON.stringify(e));
14
+ localStorage.setItem(ne, JSON.stringify(e));
15
15
  }
16
16
  async function ke() {
17
17
  try {
@@ -24,7 +24,7 @@ async function ke() {
24
24
  return null;
25
25
  }
26
26
  }
27
- async function oe() {
27
+ async function se() {
28
28
  try {
29
29
  const e = await fetch("/cms-locales.json", { cache: "no-store" });
30
30
  if (!e.ok)
@@ -60,7 +60,7 @@ function v(e) {
60
60
  const a = (e.getAttribute("class") ?? "").split(/\s+/).filter(Boolean)[0];
61
61
  return a ? `${e.tagName.toLowerCase()}.${a}` : e.tagName.toLowerCase();
62
62
  }
63
- function re(e) {
63
+ function ie(e) {
64
64
  return ["SCRIPT", "STYLE", "NOSCRIPT", "IFRAME"].includes(e.tagName);
65
65
  }
66
66
  function N(e) {
@@ -68,7 +68,7 @@ function N(e) {
68
68
  }
69
69
  function $e(e, t, a) {
70
70
  const o = t.parentElement;
71
- if (!o || re(o))
71
+ if (!o || ie(o))
72
72
  return null;
73
73
  if (Array.from(o.childNodes).filter(
74
74
  (s) => s.nodeType === Node.TEXT_NODE && N(s.nodeValue).length > 0
@@ -95,12 +95,12 @@ function S(e = document, t) {
95
95
  if (m.length < 2)
96
96
  continue;
97
97
  o += 1;
98
- const K = `${A(i || "index")}.text.${o}`, O = $e(e, b, K);
98
+ const J = `${A(i || "index")}.text.${o}`, O = $e(e, b, J);
99
99
  if (!O)
100
100
  continue;
101
101
  a.push({
102
102
  id: `dom_txt_${o}`,
103
- key: K,
103
+ key: J,
104
104
  type: "text",
105
105
  label: v(O),
106
106
  value: m,
@@ -110,7 +110,7 @@ function S(e = document, t) {
110
110
  continue;
111
111
  }
112
112
  const l = d;
113
- if (re(l))
113
+ if (ie(l))
114
114
  continue;
115
115
  const p = l.tagName.toLowerCase();
116
116
  if (p === "img" || p === "video") {
@@ -172,7 +172,7 @@ function S(e = document, t) {
172
172
  nodes: a
173
173
  };
174
174
  }
175
- function R(e, t = document) {
175
+ function P(e, t = document) {
176
176
  if (!e.key)
177
177
  return;
178
178
  const a = t.querySelector(`[data-cms-key="${CSS.escape(e.key)}"]`);
@@ -256,15 +256,15 @@ const B = [
256
256
  { code: "uz", label: "Uzbek", nllb: "uzn_Latn" },
257
257
  { code: "vi", label: "Vietnamese", nllb: "vie_Latn" },
258
258
  { code: "zh", label: "Chinese (Simplified)", nllb: "zho_Hans" }
259
- ], J = Object.fromEntries(
259
+ ], W = Object.fromEntries(
260
260
  B.map((e) => [e.nllb.slice(0, 3).toLowerCase(), e.code])
261
261
  ), Se = "https://api.mymemory.translated.net/get";
262
- function F(e) {
262
+ function Y(e) {
263
263
  const t = e.trim().toLowerCase().split(/[-_]/)[0];
264
264
  if (/^[a-z]{2}$/i.test(t))
265
265
  return t;
266
- if (/^[a-z]{3}$/i.test(t) && J[t])
267
- return J[t];
266
+ if (/^[a-z]{3}$/i.test(t) && W[t])
267
+ return W[t];
268
268
  throw new Error(`Unsupported language code "${e}" for MyMemory translation.`);
269
269
  }
270
270
  async function Ee(e, t, a) {
@@ -283,7 +283,7 @@ async function Ee(e, t, a) {
283
283
  return typeof s == "string" && s.trim() ? s : e;
284
284
  }
285
285
  async function _e(e, t, a = "en", o) {
286
- const n = F(a), r = F(t), s = /* @__PURE__ */ new Map(), i = {}, c = Object.entries(e), u = c.length;
286
+ const n = Y(a), r = Y(t), s = /* @__PURE__ */ new Map(), i = {}, c = Object.entries(e), u = c.length;
287
287
  let d = 0;
288
288
  for (const [l, p] of c) {
289
289
  if (s.has(p)) {
@@ -300,10 +300,10 @@ async function _e(e, t, a = "en", o) {
300
300
  }
301
301
  return i;
302
302
  }
303
- function se(e) {
303
+ function le(e) {
304
304
  return /^[^/\s]+\/[^/\s]+$/.test(e);
305
305
  }
306
- function ie(e) {
306
+ function ce(e) {
307
307
  return /^([^/\s]+\/)+[^/\s]+$/.test(e);
308
308
  }
309
309
  async function Ae(e, t, a) {
@@ -324,7 +324,7 @@ async function Te() {
324
324
  if (!t || !t.provider || t.provider === "none" || t.provider !== "github" && t.provider !== "gitlab" || typeof t.repository != "string" || !t.repository.trim())
325
325
  return null;
326
326
  const a = t.repository.trim();
327
- return t.provider === "github" && !se(a) || t.provider === "gitlab" && !ie(a) || typeof t.branch != "string" || !t.branch.trim() ? null : { ...t, repository: a, branch: t.branch.trim() };
327
+ return t.provider === "github" && !le(a) || t.provider === "gitlab" && !ce(a) || typeof t.branch != "string" || !t.branch.trim() ? null : { ...t, repository: a, branch: t.branch.trim() };
328
328
  } catch {
329
329
  return null;
330
330
  }
@@ -385,28 +385,36 @@ async function Oe(e, t, a) {
385
385
  }
386
386
  async function ze(e, t, a, o) {
387
387
  const n = /* @__PURE__ */ new Map();
388
- a.forEach((r) => {
389
- const s = Ce(r.file);
390
- if (!s)
388
+ let r = 0;
389
+ a.forEach((i) => {
390
+ i.find !== i.replace && (r += 1);
391
+ const c = Ce(i.file);
392
+ if (!c)
391
393
  return;
392
- const i = n.get(s) ?? [];
393
- i.push({ ...r, file: s }), n.set(s, i);
394
+ const u = n.get(c) ?? [];
395
+ u.push({ ...i, file: c }), n.set(c, u);
394
396
  });
395
- for (const [r, s] of n.entries()) {
396
- const i = await Oe(e, t, r);
397
- if (!i)
397
+ let s = 0;
398
+ for (const [i, c] of n.entries()) {
399
+ const u = await Oe(e, t, i);
400
+ if (!u)
398
401
  continue;
399
- let c = i.content;
400
- s.forEach((u) => {
401
- c = Ie(c, u.find, u.replace, u.occurrence ?? 1);
402
- }), c !== i.content && await $(e, t, r, c, o);
402
+ let d = u.content;
403
+ c.forEach((l) => {
404
+ d = Ie(d, l.find, l.replace, l.occurrence ?? 1);
405
+ }), d !== u.content && (await $(e, t, i, d, o), s += 1);
403
406
  }
407
+ return { updatedFiles: s, attemptedFiles: n.size, actionableOperations: r };
404
408
  }
405
409
  async function Ne(e, t, a) {
406
- const o = `chore(cms): publish content updates ${(/* @__PURE__ */ new Date()).toISOString()}`;
407
- if (await ze(e, t, a.operations ?? [], o), await $(e, t, "cms-content.json", JSON.stringify(a.content, null, 2), o), a.locales) {
408
- for (const [n, r] of Object.entries(a.locales))
409
- await $(e, t, `locales/${n}.json`, JSON.stringify(r, null, 2), o);
410
+ const o = `chore(cms): publish content updates ${(/* @__PURE__ */ new Date()).toISOString()}`, n = await ze(e, t, a.operations ?? [], o);
411
+ if (n.actionableOperations > 0 && n.updatedFiles === 0)
412
+ throw new Error(
413
+ `No source files were updated (${n.attemptedFiles} candidate files checked). Run setup again to refresh cms-route-map.json and retry.`
414
+ );
415
+ if (await $(e, t, "cms-content.json", JSON.stringify(a.content, null, 2), o), a.locales) {
416
+ for (const [r, s] of Object.entries(a.locales))
417
+ await $(e, t, `locales/${r}.json`, JSON.stringify(s, null, 2), o);
410
418
  await $(
411
419
  e,
412
420
  t,
@@ -450,18 +458,18 @@ async function Me(e, t, a) {
450
458
  })).ok)
451
459
  throw new Error("GitLab publish failed.");
452
460
  }
453
- async function Pe(e, t, a) {
461
+ async function Re(e, t, a) {
454
462
  if (!a || !t.trim())
455
463
  return !1;
456
- if (a.provider === "github" && !se(a.repository))
464
+ if (a.provider === "github" && !le(a.repository))
457
465
  throw new Error('Invalid GitHub repository format. Use "owner/repo".');
458
- if (a.provider === "gitlab" && !ie(a.repository))
466
+ if (a.provider === "gitlab" && !ce(a.repository))
459
467
  throw new Error('Invalid GitLab repository format. Use "group/project".');
460
468
  return a.provider === "github" ? (await Ne(a, t.trim(), e), !0) : a.provider === "gitlab" ? (await Me(a, t.trim(), e), !0) : !1;
461
469
  }
462
- const W = "facms-auth-modal", M = "facms-auth-missing", Y = "facms-token-modal", V = "facms-language-modal", Re = "frontend-auto-cms::theme", le = "frontend-auto-cms::main-language", ce = "frontend-auto-cms::language-labels";
463
- let D = !1, k = null, X = !1, x = null, f = "dark", de = {};
464
- function ue() {
470
+ const V = "facms-auth-modal", M = "facms-auth-missing", X = "facms-token-modal", Z = "facms-language-modal", Pe = "frontend-auto-cms::theme", de = "frontend-auto-cms::main-language", ue = "frontend-auto-cms::language-labels";
471
+ let D = !1, k = null, Q = !1, x = null, f = "dark", U = {};
472
+ function fe() {
465
473
  if (document.getElementById("facms-dashboard-css"))
466
474
  return;
467
475
  const e = document.createElement("style");
@@ -700,15 +708,15 @@ function ue() {
700
708
  }
701
709
  `, document.head.appendChild(e);
702
710
  }
703
- function fe(e) {
711
+ function pe(e) {
704
712
  f = e;
705
713
  const t = e === "dark";
706
- document.documentElement.classList.toggle("dark", t), document.body.classList.toggle("dark", t), document.documentElement.style.background = t ? "#020617" : "#f1f5f9", document.body.style.background = t ? "#020617" : "#f1f5f9", document.documentElement.setAttribute("data-facms-theme", e), document.getElementById("facms-app")?.classList.toggle("dark", t), localStorage.setItem(Re, e);
714
+ document.documentElement.classList.toggle("dark", t), document.body.classList.toggle("dark", t), document.documentElement.style.background = t ? "#020617" : "#f1f5f9", document.body.style.background = t ? "#020617" : "#f1f5f9", document.documentElement.setAttribute("data-facms-theme", e), document.getElementById("facms-app")?.classList.toggle("dark", t), localStorage.setItem(Pe, e);
707
715
  const o = document.getElementById("facms-theme-toggle");
708
716
  o && (o.textContent = e === "dark" ? "Switch to light" : "Switch to dark");
709
717
  }
710
- function pe() {
711
- f = "dark", fe("dark");
718
+ function ge() {
719
+ f = "dark", pe("dark");
712
720
  }
713
721
  function Be(e) {
714
722
  return Array.from(new Uint8Array(e)).map((t) => t.toString(16).padStart(2, "0")).join("");
@@ -717,7 +725,7 @@ async function De(e) {
717
725
  const t = new TextEncoder().encode(e), a = await crypto.subtle.digest("SHA-256", t);
718
726
  return Be(a);
719
727
  }
720
- async function ge() {
728
+ async function be() {
721
729
  if (x)
722
730
  return x;
723
731
  try {
@@ -726,7 +734,7 @@ async function ge() {
726
734
  const t = await e.json();
727
735
  return x = {
728
736
  dashboardPath: t.dashboardPath || "/dashboard",
729
- pages: (t.pages?.length ? t.pages : ["/"]).map((a) => he(a)),
737
+ pages: (t.pages?.length ? t.pages : ["/"]).map((a) => H(a)),
730
738
  showFloatingButton: t.showFloatingButton ?? !1,
731
739
  autoTranslateEnabled: t.autoTranslateEnabled ?? !0
732
740
  }, x;
@@ -735,9 +743,9 @@ async function ge() {
735
743
  }
736
744
  return x = { dashboardPath: "/dashboard", pages: ["/"], showFloatingButton: !1, autoTranslateEnabled: !0 }, x;
737
745
  }
738
- async function U() {
739
- if (!X) {
740
- X = !0;
746
+ async function G() {
747
+ if (!Q) {
748
+ Q = !0;
741
749
  try {
742
750
  const e = await fetch("/cms-runtime-auth.json", { cache: "no-store" });
743
751
  if (!e.ok) return;
@@ -750,7 +758,7 @@ async function U() {
750
758
  }
751
759
  async function Ue(e) {
752
760
  const t = e.trim();
753
- return !t || (await U(), !k) ? !1 : await De(`${k.salt}:${t}`) === k.passcodeHash;
761
+ return !t || (await G(), !k) ? !1 : await De(`${k.salt}:${t}`) === k.passcodeHash;
754
762
  }
755
763
  function Ge() {
756
764
  let e = document.getElementById(M);
@@ -765,17 +773,17 @@ function Ge() {
765
773
  function He() {
766
774
  document.getElementById(M)?.remove();
767
775
  }
768
- async function be() {
769
- return await U(), k ? (He(), !0) : (Ge(), !1);
776
+ async function me() {
777
+ return await G(), k ? (He(), !0) : (Ge(), !1);
770
778
  }
771
- function me(e) {
772
- const t = document.getElementById(W);
779
+ function he(e) {
780
+ const t = document.getElementById(V);
773
781
  if (t) {
774
782
  t.style.display = "grid";
775
783
  return;
776
784
  }
777
785
  const a = document.createElement("div");
778
- a.id = W, a.style.position = "fixed", a.style.inset = "0", a.style.zIndex = "2147483647", a.style.background = "rgba(2, 6, 23, 0.45)", a.style.display = "grid", a.style.placeItems = "center", a.innerHTML = `
786
+ a.id = V, a.style.position = "fixed", a.style.inset = "0", a.style.zIndex = "2147483647", a.style.background = "rgba(2, 6, 23, 0.45)", a.style.display = "grid", a.style.placeItems = "center", a.innerHTML = `
779
787
  <div style="width: min(420px, 92vw); background: ${f === "dark" ? "#0f172a" : "#ffffff"}; color: ${f === "dark" ? "#e2e8f0" : "#0f172a"}; border: 1px solid ${f === "dark" ? "#334155" : "#e2e8f0"}; border-radius: 16px; padding: 16px; box-shadow: 0 20px 55px rgba(2,6,23,0.45); font-family: Inter, system-ui, sans-serif;">
780
788
  <h3 style="margin: 0 0 6px 0; font-size: 20px; line-height: 1.2; font-weight: 700;">Unlock CMS</h3>
781
789
  <p style="margin: 0 0 12px 0; font-size: 12px; color: ${f === "dark" ? "#94a3b8" : "#475569"};">Enter your passcode to edit content.</p>
@@ -788,7 +796,7 @@ function me(e) {
788
796
  </div>
789
797
  `;
790
798
  const o = a.querySelector("#facms-passcode-input"), n = a.querySelector("#facms-passcode-error"), r = () => a.style.display = "none", s = async () => {
791
- if (await U(), !k) {
799
+ if (await G(), !k) {
792
800
  n && (n.textContent = "CMS auth is not configured. Run setup to generate runtime auth files.", n.style.display = "block");
793
801
  return;
794
802
  }
@@ -801,10 +809,10 @@ function me(e) {
801
809
  a.querySelector("#facms-passcode-cancel")?.addEventListener("click", r), a.querySelector("#facms-passcode-submit")?.addEventListener("click", s), o?.addEventListener("keydown", (i) => i.key === "Enter" && void s()), document.body.appendChild(a), o?.focus();
802
810
  }
803
811
  function qe(e, t) {
804
- const a = document.getElementById(Y);
812
+ const a = document.getElementById(X);
805
813
  a && a.remove();
806
814
  const o = document.createElement("div");
807
- o.id = Y, o.style.position = "fixed", o.style.inset = "0", o.style.zIndex = "2147483647", o.style.background = "rgba(2, 6, 23, 0.45)", o.style.display = "grid", o.style.placeItems = "center", o.innerHTML = `
815
+ o.id = X, o.style.position = "fixed", o.style.inset = "0", o.style.zIndex = "2147483647", o.style.background = "rgba(2, 6, 23, 0.45)", o.style.display = "grid", o.style.placeItems = "center", o.innerHTML = `
808
816
  <div style="width: min(520px, 92vw); background: ${f === "dark" ? "#0f172a" : "#ffffff"}; color: ${f === "dark" ? "#e2e8f0" : "#0f172a"}; border: 1px solid ${f === "dark" ? "#334155" : "#e2e8f0"}; border-radius: 16px; padding: 16px; box-shadow: 0 20px 55px rgba(2,6,23,0.45); font-family: Inter, system-ui, sans-serif;">
809
817
  <h3 style="margin: 0 0 6px 0; font-size: 20px; line-height: 1.2; font-weight: 700;">Publish token required</h3>
810
818
  <p style="margin: 0 0 12px 0; font-size: 12px; color: ${f === "dark" ? "#94a3b8" : "#475569"};">Enter your ${e} token for this publish only. It is not stored.</p>
@@ -827,10 +835,10 @@ function qe(e, t) {
827
835
  o.querySelector("#facms-token-cancel")?.addEventListener("click", s), o.querySelector("#facms-token-submit")?.addEventListener("click", i), n?.addEventListener("keydown", (c) => c.key === "Enter" && i()), document.body.appendChild(o), n?.focus();
828
836
  }
829
837
  function Ke(e, t, a) {
830
- const o = document.getElementById(V);
838
+ const o = document.getElementById(Z);
831
839
  o && o.remove();
832
840
  const n = document.createElement("div");
833
- n.id = V, n.style.position = "fixed", n.style.inset = "0", n.style.zIndex = "2147483647", n.style.background = "rgba(2, 6, 23, 0.45)", n.style.display = "grid", n.style.placeItems = "center", n.innerHTML = `
841
+ n.id = Z, n.style.position = "fixed", n.style.inset = "0", n.style.zIndex = "2147483647", n.style.background = "rgba(2, 6, 23, 0.45)", n.style.display = "grid", n.style.placeItems = "center", n.innerHTML = `
834
842
  <div style="width: min(520px, 92vw); background: ${f === "dark" ? "#0f172a" : "#ffffff"}; color: ${f === "dark" ? "#e2e8f0" : "#0f172a"}; border: 1px solid ${f === "dark" ? "#334155" : "#e2e8f0"}; border-radius: 16px; padding: 16px; box-shadow: 0 20px 55px rgba(2,6,23,0.45); font-family: Inter, system-ui, sans-serif;">
835
843
  <h3 style="margin: 0 0 6px 0; font-size: 20px; line-height: 1.2; font-weight: 700;">Add translation</h3>
836
844
  <p style="margin: 0 0 8px 0; font-size: 12px; color: ${f === "dark" ? "#94a3b8" : "#475569"};">Pick a supported language or define a custom one for manual translation.</p>
@@ -883,7 +891,7 @@ function z(e, t) {
883
891
  function C(e) {
884
892
  return e.trim().toLowerCase();
885
893
  }
886
- function he(e) {
894
+ function H(e) {
887
895
  const t = e.trim() || "/";
888
896
  return t === "/" ? "/" : (t.startsWith("/") ? t : `/${t}`).toLowerCase();
889
897
  }
@@ -891,9 +899,9 @@ function E(e) {
891
899
  const t = C(e), a = B.find((o) => o.code === t);
892
900
  return a ? a.label : t.toUpperCase();
893
901
  }
894
- function Je() {
902
+ function Fe() {
895
903
  try {
896
- const e = localStorage.getItem(ce);
904
+ const e = localStorage.getItem(ue);
897
905
  if (!e)
898
906
  return {};
899
907
  const t = JSON.parse(e);
@@ -902,15 +910,15 @@ function Je() {
902
910
  return {};
903
911
  }
904
912
  }
905
- function G(e) {
906
- localStorage.setItem(ce, JSON.stringify(e));
913
+ function q(e) {
914
+ localStorage.setItem(ue, JSON.stringify(e));
907
915
  }
908
916
  function j(e) {
909
- const t = localStorage.getItem(le);
917
+ const t = localStorage.getItem(de);
910
918
  return t && e[t] ? t : e.en ? "en" : Object.keys(e)[0] ?? "en";
911
919
  }
912
- function Z(e) {
913
- localStorage.setItem(le, e);
920
+ function ee(e) {
921
+ localStorage.setItem(de, e);
914
922
  }
915
923
  function h(e) {
916
924
  return e.replace(/[&<>'"]/g, (t) => ({ "&": "&amp;", "<": "&lt;", ">": "&gt;", "'": "&#39;", '"': "&quot;" })[t]);
@@ -919,7 +927,7 @@ function T(e, t = 72) {
919
927
  const a = e.replace(/\s+/g, " ").trim();
920
928
  return a.length <= t ? a : `${a.slice(0, t)}...`;
921
929
  }
922
- function Fe(e) {
930
+ function Je(e) {
923
931
  return e.type === "section" ? T((e.sectionItems ?? []).join(" | ")) : e.type === "property" ? T(JSON.stringify(e.attrs ?? {})) : T(e.value);
924
932
  }
925
933
  function We(e) {
@@ -958,30 +966,43 @@ function Xe(e) {
958
966
  if (!t)
959
967
  return t;
960
968
  if (t.startsWith("/")) {
961
- const a = he(t);
962
- return de[a] ?? t;
969
+ const a = H(t);
970
+ return U[a] ?? t;
963
971
  }
964
972
  return t.replace(/^\.?\//, "");
965
973
  }
966
974
  async function Ze(e, t, a) {
967
- const o = e.nodes.flatMap(
968
- (s) => s.sourceRefs.map((i) => ({
969
- file: Xe(i.file),
970
- find: i.original,
971
- replace: s.type === "property" ? JSON.stringify(s.attrs ?? {}) : s.type === "section" ? (s.sectionItems ?? []).join(" ") : s.type === "text" ? a[s.key] ?? s.value : s.value,
972
- occurrence: i.occurrence ?? 1
975
+ const o = /* @__PURE__ */ new Set(), n = e.nodes.flatMap(
976
+ (i) => i.sourceRefs.map((c) => ({
977
+ file: (() => {
978
+ const u = (c.file ?? "").trim();
979
+ if (u.startsWith("/")) {
980
+ const d = H(u);
981
+ if (!U[d])
982
+ return o.add(d), u;
983
+ }
984
+ return Xe(u);
985
+ })(),
986
+ find: c.original,
987
+ replace: i.type === "property" ? JSON.stringify(i.attrs ?? {}) : i.type === "section" ? (i.sectionItems ?? []).join(" ") : (i.type === "text", i.value),
988
+ occurrence: c.occurrence ?? 1
973
989
  }))
974
- ), n = {
990
+ );
991
+ if (o.size)
992
+ throw new Error(
993
+ `Missing route mappings for: ${Array.from(o).join(", ")}. Run setup again and commit public/cms-route-map.json.`
994
+ );
995
+ const r = {
975
996
  generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
976
997
  content: { ...e, updatedAt: (/* @__PURE__ */ new Date()).toISOString() },
977
- operations: o,
998
+ operations: n,
978
999
  locales: t
979
- }, r = await Ve(Ye(n));
1000
+ }, s = await Ve(Ye(r));
980
1001
  return {
981
- ...n,
1002
+ ...r,
982
1003
  integrity: {
983
1004
  algorithm: "sha256",
984
- value: r
1005
+ value: s
985
1006
  }
986
1007
  };
987
1008
  }
@@ -1000,7 +1021,7 @@ function Qe(e, t) {
1000
1021
  }
1001
1022
  function _(e, t, a, o) {
1002
1023
  e.nodes.forEach((n) => {
1003
- n.type === "text" && (n.value = t[n.key] ?? o[n.key] ?? n.value, R(n, a));
1024
+ n.type === "text" && (n.value = t[n.key] ?? o[n.key] ?? n.value, P(n, a));
1004
1025
  });
1005
1026
  }
1006
1027
  function et(e, t) {
@@ -1029,7 +1050,7 @@ function tt(e, t) {
1029
1050
  n.addEventListener("click", (r) => {
1030
1051
  r.stopPropagation();
1031
1052
  const s = n.dataset.mainLang;
1032
- !s || !t.locales[s] || (t.mainLanguage = s, Z(s), t.baseTextByKey = { ...t.locales[s] }, L(e, t));
1053
+ !s || !t.locales[s] || (t.mainLanguage = s, ee(s), t.baseTextByKey = { ...t.locales[s] }, L(e, t));
1033
1054
  });
1034
1055
  }), a.querySelectorAll("[data-remove-lang]").forEach((n) => {
1035
1056
  n.addEventListener("click", (r) => {
@@ -1040,7 +1061,7 @@ function tt(e, t) {
1040
1061
  alert("You must keep at least one language.");
1041
1062
  return;
1042
1063
  }
1043
- delete t.locales[s], delete t.languageLabels[s], G(t.languageLabels), I(t.locales), t.mainLanguage === s && (t.mainLanguage = j(t.locales), Z(t.mainLanguage), t.baseTextByKey = { ...t.locales[t.mainLanguage] ?? {} }), t.activeLanguage === s && (t.activeLanguage = H(t.locales, t.mainLanguage)), ye(t), L(e, t);
1064
+ delete t.locales[s], delete t.languageLabels[s], q(t.languageLabels), I(t.locales), t.mainLanguage === s && (t.mainLanguage = j(t.locales), ee(t.mainLanguage), t.baseTextByKey = { ...t.locales[t.mainLanguage] ?? {} }), t.activeLanguage === s && (t.activeLanguage = K(t.locales, t.mainLanguage)), ye(t), L(e, t);
1044
1065
  }
1045
1066
  });
1046
1067
  });
@@ -1065,22 +1086,22 @@ function at(e, t) {
1065
1086
  } catch {
1066
1087
  return;
1067
1088
  }
1068
- R(r, t.workingDocument), ae(t.content);
1089
+ P(r, t.workingDocument), oe(t.content);
1069
1090
  }
1070
1091
  });
1071
1092
  });
1072
1093
  }
1073
1094
  function w(e, t, a) {
1074
1095
  const o = e.querySelector("#facms-i18n-status"), n = e.querySelector("#facms-translate-loader"), r = e.querySelector("#facms-add-language");
1075
- P(a, t), o && (o.textContent = t), n && (n.style.display = a ? "inline-flex" : "none"), r && (r.disabled = a);
1096
+ R(a, t), o && (o.textContent = t), n && (n.style.display = a ? "inline-flex" : "none"), r && (r.disabled = a);
1076
1097
  }
1077
- function P(e, t) {
1098
+ function R(e, t) {
1078
1099
  const a = document.getElementById("facms-global-loader"), o = document.getElementById("facms-global-loader-label");
1079
1100
  a && (a.style.display = e ? "flex" : "none"), o && (o.textContent = e ? t : "Loading");
1080
1101
  }
1081
1102
  function L(e, t) {
1082
1103
  const a = We(t.content.nodes), o = a.length ? a.map((n) => {
1083
- const r = n.items[0], s = n.items[n.items.length - 1], i = r.index === s.index ? `#${r.index + 1}` : `#${r.index + 1} - #${s.index + 1}`, c = n.items.map((l) => Fe(l.node)).filter(Boolean).join(" • "), u = n.items.length > 1 ? `${i} ${h(n.selector || "Grouped fields")} (${n.items.length} fields)` : `${i} ${h(r.node.type.toUpperCase())} • ${h(r.node.label || r.node.selector || "")}`, d = n.items.map((l) => Qe(l.node, l.index)).join("");
1104
+ const r = n.items[0], s = n.items[n.items.length - 1], i = r.index === s.index ? `#${r.index + 1}` : `#${r.index + 1} - #${s.index + 1}`, c = n.items.map((l) => Je(l.node)).filter(Boolean).join(" • "), u = n.items.length > 1 ? `${i} ${h(n.selector || "Grouped fields")} (${n.items.length} fields)` : `${i} ${h(r.node.type.toUpperCase())} • ${h(r.node.label || r.node.selector || "")}`, d = n.items.map((l) => Qe(l.node, l.index)).join("");
1084
1105
  return `
1085
1106
  <details class="rounded-xl p-2 border border-slate-200 dark:border-transparent bg-white dark:bg-slate-900/60 shadow-sm">
1086
1107
  <summary class="list-none cursor-pointer flex items-center justify-between gap-2 p-3 rounded-lg bg-slate-50 dark:bg-slate-800/70 border border-slate-200 dark:border-slate-800">
@@ -1113,7 +1134,14 @@ function L(e, t) {
1113
1134
  </div>
1114
1135
  </div>
1115
1136
  `, tt(e, t), e.querySelector("#facms-save")?.addEventListener("click", async () => {
1116
- const n = await Ze(t.content, t.locales, t.baseTextByKey), r = await Te();
1137
+ let n, r;
1138
+ try {
1139
+ n = await Ze(t.content, t.locales, t.baseTextByKey), r = await Te();
1140
+ } catch (i) {
1141
+ const c = i instanceof Error ? i.message : String(i);
1142
+ alert(`Could not prepare publish payload: ${c}`);
1143
+ return;
1144
+ }
1117
1145
  if (!r || r.provider === "none") {
1118
1146
  Le(n), alert("Patch downloaded. Configure hosting in setup for one-click publish.");
1119
1147
  return;
@@ -1122,7 +1150,7 @@ function L(e, t) {
1122
1150
  qe(s, async (i) => {
1123
1151
  let c = !1, u = "Publishing failed. Please verify token permissions and repository settings.";
1124
1152
  try {
1125
- c = await Pe(n, i, r);
1153
+ c = await Re(n, i, r);
1126
1154
  } catch (d) {
1127
1155
  const l = d instanceof Error ? d.message : String(d);
1128
1156
  l && (u = `Publishing failed: ${l}`), c = !1;
@@ -1145,15 +1173,15 @@ function L(e, t) {
1145
1173
  sourceKeys: Object.keys(l).length,
1146
1174
  browserLanguage: navigator.language,
1147
1175
  browserLanguages: navigator.languages
1148
- }), t.locales[c] = p, t.languageLabels[c] = u, G(t.languageLabels), t.activeLanguage = c, I(t.locales), _(t.content, t.locales[c], t.workingDocument, t.baseTextByKey), L(e, t), z("Manual language tab created", { lang: c }), w(e, `Added ${u} tab prefilled with source text for manual translation.`, !1), r !== "auto" || !(x?.autoTranslateEnabled ?? !0)) {
1176
+ }), t.locales[c] = p, t.languageLabels[c] = u, q(t.languageLabels), t.activeLanguage = c, I(t.locales), _(t.content, t.locales[c], t.workingDocument, t.baseTextByKey), L(e, t), z("Manual language tab created", { lang: c }), w(e, `Added ${u} tab prefilled with source text for manual translation.`, !1), r !== "auto" || !(x?.autoTranslateEnabled ?? !0)) {
1149
1177
  r === "auto" && !(x?.autoTranslateEnabled ?? !0) && w(e, `Privacy mode is on. Added ${u} tab for manual translation only.`, !1);
1150
1178
  return;
1151
1179
  }
1152
1180
  try {
1153
1181
  const g = Object.keys(l).length;
1154
1182
  w(e, `Auto-filling ${u} translation... (0/${g})`, !0);
1155
- const y = await _e(l, c, t.mainLanguage, (q, b) => {
1156
- w(e, `Auto-filling ${u} translation... (${q}/${b})`, !0);
1183
+ const y = await _e(l, c, t.mainLanguage, (F, b) => {
1184
+ w(e, `Auto-filling ${u} translation... (${F}/${b})`, !0);
1157
1185
  });
1158
1186
  t.locales[c] = y, I(t.locales), t.activeLanguage = c, _(t.content, y, t.workingDocument, t.baseTextByKey), L(e, t), z("Automatic translation succeeded", {
1159
1187
  lang: c,
@@ -1171,7 +1199,7 @@ function L(e, t) {
1171
1199
  });
1172
1200
  }), at(e, t);
1173
1201
  }
1174
- function H(e, t) {
1202
+ function K(e, t) {
1175
1203
  const a = Object.keys(e), o = t && e[t] ? t : j(e), n = [...navigator.languages ?? [], navigator.language].map((r) => r.toLowerCase().split("-")[0]);
1176
1204
  for (const r of n)
1177
1205
  if (a.includes(r))
@@ -1185,7 +1213,7 @@ function ye(e) {
1185
1213
  function nt(e) {
1186
1214
  return new Promise((t) => window.setTimeout(t, e));
1187
1215
  }
1188
- async function Q(e, t) {
1216
+ async function te(e, t) {
1189
1217
  const a = [0, 120, 280, 600, 1100, 1800, 2600];
1190
1218
  let o = S(e, t);
1191
1219
  if (o.nodes.length > 0)
@@ -1196,18 +1224,18 @@ async function Q(e, t) {
1196
1224
  return o;
1197
1225
  }
1198
1226
  function ot(e, t, a) {
1199
- const o = ne(), n = {
1227
+ const o = re(), n = {
1200
1228
  ...a,
1201
1229
  ...o
1202
- }, r = Je(), s = Object.fromEntries(e.nodes.filter((l) => l.type === "text").map((l) => [l.key, l.value])), i = j(n), c = {
1230
+ }, r = Fe(), s = Object.fromEntries(e.nodes.filter((l) => l.type === "text").map((l) => [l.key, l.value])), i = j(n), c = {
1203
1231
  ...n,
1204
1232
  [i]: { ...n[i] ?? {}, ...s }
1205
1233
  };
1206
1234
  !c.en && i === "en" && (c.en = Object.assign({}, c.en ?? {}, s));
1207
- const u = H(c, i), d = { ...r };
1235
+ const u = K(c, i), d = { ...r };
1208
1236
  return Object.keys(c).forEach((l) => {
1209
1237
  d[l] || (d[l] = E(l));
1210
- }), G(d), {
1238
+ }), q(d), {
1211
1239
  content: e,
1212
1240
  locales: c,
1213
1241
  workingDocument: t,
@@ -1227,18 +1255,18 @@ async function rt() {
1227
1255
  const a = new Map(e.nodes.map((o) => [o.key, o]));
1228
1256
  t.nodes.forEach((o) => {
1229
1257
  const n = a.get(o.key);
1230
- !n || n.type !== o.type || (o.value = n.value, n.attrs && (o.attrs = { ...n.attrs }), n.sectionItems && (o.sectionItems = [...n.sectionItems]), R(o, document));
1258
+ !n || n.type !== o.type || (o.value = n.value, n.attrs && (o.attrs = { ...n.attrs }), n.sectionItems && (o.sectionItems = [...n.sectionItems]), P(o, document));
1231
1259
  });
1232
1260
  }
1233
1261
  async function st() {
1234
1262
  await rt();
1235
1263
  const t = {
1236
- ...await oe(),
1237
- ...ne()
1264
+ ...await se(),
1265
+ ...re()
1238
1266
  };
1239
1267
  if (!Object.keys(t).length)
1240
1268
  return;
1241
- const a = j(t), o = H(t, a);
1269
+ const a = j(t), o = K(t, a);
1242
1270
  if (!o || o === a)
1243
1271
  return;
1244
1272
  const n = S(document, location.pathname), r = t[o];
@@ -1288,56 +1316,56 @@ function it(e) {
1288
1316
  });
1289
1317
  });
1290
1318
  };
1291
- fe(f), a.addEventListener("load", async () => {
1319
+ pe(f), a.addEventListener("load", async () => {
1292
1320
  const u = a.contentDocument;
1293
1321
  if (u) {
1294
- P(!0, `Scanning page content for ${s}...`);
1322
+ R(!0, `Scanning page content for ${s}...`);
1295
1323
  try {
1296
1324
  let d = r.get(s);
1297
1325
  if (d) {
1298
1326
  d.workingDocument = u;
1299
- const l = d.content.nodes.length ? S(u, s) : await Q(u, s);
1327
+ const l = d.content.nodes.length ? S(u, s) : await te(u, s);
1300
1328
  l.nodes.length && !d.content.nodes.length && (d.content = l);
1301
1329
  } else {
1302
- const l = await Q(u, s);
1330
+ const l = await te(u, s);
1303
1331
  d = ot(l, u, i), r.set(s, d);
1304
1332
  }
1305
- ye(d), ae(d.content), L(o, d);
1333
+ ye(d), oe(d.content), L(o, d);
1306
1334
  } finally {
1307
- P(!1, "Loading");
1335
+ R(!1, "Loading");
1308
1336
  }
1309
1337
  }
1310
- }), c(), Promise.all([oe(), we()]).then(([u, d]) => {
1311
- i = u, de = d, a.src = s;
1338
+ }), c(), Promise.all([se(), we()]).then(([u, d]) => {
1339
+ i = u, U = d, a.src = s;
1312
1340
  });
1313
1341
  }
1314
- async function ee() {
1315
- if (ue(), pe(), !await be())
1342
+ async function ae() {
1343
+ if (fe(), ge(), !await me())
1316
1344
  return;
1317
- const e = await ge(), t = () => it(e);
1345
+ const e = await be(), t = () => it(e);
1318
1346
  if (!D) {
1319
- me(t);
1347
+ he(t);
1320
1348
  return;
1321
1349
  }
1322
1350
  t();
1323
1351
  }
1324
1352
  async function lt() {
1325
- const e = await ge(), a = new URLSearchParams(location.search).get("__facms") === "1";
1353
+ const e = await be(), a = new URLSearchParams(location.search).get("__facms") === "1";
1326
1354
  if (location.pathname !== e.dashboardPath && !a) {
1327
1355
  st();
1328
1356
  return;
1329
1357
  }
1330
- if (ue(), pe(), !!await be()) {
1358
+ if (fe(), ge(), !!await me()) {
1331
1359
  if (!D) {
1332
- me(() => {
1333
- ee();
1360
+ he(() => {
1361
+ ae();
1334
1362
  });
1335
1363
  return;
1336
1364
  }
1337
- ee();
1365
+ ae();
1338
1366
  }
1339
1367
  }
1340
1368
  export {
1341
- ee as launchDashboard,
1369
+ ae as launchDashboard,
1342
1370
  lt as registerCmsLauncher
1343
1371
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "frontend-auto-cms",
3
- "version": "1.0.11",
3
+ "version": "1.0.13",
4
4
  "description": "Turn any frontend into an editable mini-CMS with one import.",
5
5
  "type": "module",
6
6
  "license": "MIT",