frontend-auto-cms 1.0.8 → 1.0.10

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,6 +1,6 @@
1
- const me = "cms-export.patch.json", ye = "frontend-auto-cms::content", te = "frontend-auto-cms::locales";
1
+ const ye = "cms-export.patch.json", he = "frontend-auto-cms::content", te = "frontend-auto-cms::locales";
2
2
  function ae(e) {
3
- localStorage.setItem(ye, JSON.stringify(e));
3
+ localStorage.setItem(he, JSON.stringify(e));
4
4
  }
5
5
  function ne() {
6
6
  try {
@@ -10,10 +10,10 @@ function ne() {
10
10
  return {};
11
11
  }
12
12
  }
13
- function T(e) {
13
+ function I(e) {
14
14
  localStorage.setItem(te, JSON.stringify(e));
15
15
  }
16
- async function he() {
16
+ async function xe() {
17
17
  try {
18
18
  const e = await fetch("/cms-content.json", { cache: "no-store" });
19
19
  if (!e.ok)
@@ -24,7 +24,7 @@ async function he() {
24
24
  return null;
25
25
  }
26
26
  }
27
- async function xe() {
27
+ async function oe() {
28
28
  try {
29
29
  const e = await fetch("/cms-locales.json", { cache: "no-store" });
30
30
  if (!e.ok)
@@ -37,7 +37,7 @@ async function xe() {
37
37
  }
38
38
  function ve(e) {
39
39
  const t = new Blob([JSON.stringify(e, null, 2)], { type: "application/json" }), a = URL.createObjectURL(t), o = document.createElement("a");
40
- o.href = a, o.download = me, o.click(), URL.revokeObjectURL(a);
40
+ o.href = a, o.download = ye, o.click(), URL.revokeObjectURL(a);
41
41
  }
42
42
  function _(e) {
43
43
  return e.replace(/[^\w]+/g, "_").replace(/^_+|_+$/g, "").toLowerCase();
@@ -49,7 +49,7 @@ function v(e) {
49
49
  const a = (e.getAttribute("class") ?? "").split(/\s+/).filter(Boolean)[0];
50
50
  return a ? `${e.tagName.toLowerCase()}.${a}` : e.tagName.toLowerCase();
51
51
  }
52
- function oe(e) {
52
+ function re(e) {
53
53
  return ["SCRIPT", "STYLE", "NOSCRIPT", "IFRAME"].includes(e.tagName);
54
54
  }
55
55
  function N(e) {
@@ -57,7 +57,7 @@ function N(e) {
57
57
  }
58
58
  function ke(e, t, a) {
59
59
  const o = t.parentElement;
60
- if (!o || oe(o))
60
+ if (!o || re(o))
61
61
  return null;
62
62
  if (Array.from(o.childNodes).filter(
63
63
  (s) => s.nodeType === Node.TEXT_NODE && N(s.nodeValue).length > 0
@@ -69,7 +69,7 @@ function ke(e, t, a) {
69
69
  function $(e = document, t) {
70
70
  const a = [];
71
71
  let o = 0, n = 0, r = 0, s = 0;
72
- const l = t ?? e.location?.pathname ?? location.pathname, c = e.body;
72
+ const i = t ?? e.location?.pathname ?? location.pathname, c = e.body;
73
73
  if (!c)
74
74
  return {
75
75
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
@@ -84,74 +84,74 @@ function $(e = document, t) {
84
84
  if (m.length < 2)
85
85
  continue;
86
86
  o += 1;
87
- const K = `${_(l || "index")}.text.${o}`, j = ke(e, b, K);
88
- if (!j)
87
+ const K = `${_(i || "index")}.text.${o}`, O = ke(e, b, K);
88
+ if (!O)
89
89
  continue;
90
90
  a.push({
91
91
  id: `dom_txt_${o}`,
92
92
  key: K,
93
93
  type: "text",
94
- label: v(j),
94
+ label: v(O),
95
95
  value: m,
96
- selector: v(j),
97
- sourceRefs: [{ file: l, original: m }]
96
+ selector: v(O),
97
+ sourceRefs: [{ file: i, original: m }]
98
98
  });
99
99
  continue;
100
100
  }
101
- const i = d;
102
- if (oe(i))
101
+ const l = d;
102
+ if (re(l))
103
103
  continue;
104
- const p = i.tagName.toLowerCase();
104
+ const p = l.tagName.toLowerCase();
105
105
  if (p === "img" || p === "video") {
106
- const b = i.getAttribute("src") ?? "";
106
+ const b = l.getAttribute("src") ?? "";
107
107
  if (b) {
108
108
  n += 1;
109
- const m = `${_(l || "index")}.${p}.${n}`;
110
- i.setAttribute("data-cms-key", m), a.push({
109
+ const m = `${_(i || "index")}.${p}.${n}`;
110
+ l.setAttribute("data-cms-key", m), a.push({
111
111
  id: `dom_media_${n}`,
112
112
  key: m,
113
113
  type: p === "img" ? "image" : "video",
114
- label: v(i),
114
+ label: v(l),
115
115
  value: b,
116
- selector: v(i),
117
- attrs: { src: b, alt: i.getAttribute("alt") ?? "" },
118
- sourceRefs: [{ file: l, original: b }]
116
+ selector: v(l),
117
+ attrs: { src: b, alt: l.getAttribute("alt") ?? "" },
118
+ sourceRefs: [{ file: i, original: b }]
119
119
  });
120
120
  }
121
121
  }
122
- if (["section", "ul", "ol"].includes(p) || i.hasAttribute("data-repeatable")) {
123
- const b = Array.from(i.children).map((m) => N(m.textContent)).filter(Boolean);
122
+ if (["section", "ul", "ol"].includes(p) || l.hasAttribute("data-repeatable")) {
123
+ const b = Array.from(l.children).map((m) => N(m.textContent)).filter(Boolean);
124
124
  if (b.length >= 2) {
125
125
  r += 1;
126
- const m = `${_(l || "index")}.section.${r}`;
127
- i.setAttribute("data-cms-key", m), a.push({
126
+ const m = `${_(i || "index")}.section.${r}`;
127
+ l.setAttribute("data-cms-key", m), a.push({
128
128
  id: `dom_sec_${r}`,
129
129
  key: m,
130
130
  type: "section",
131
- label: v(i),
131
+ label: v(l),
132
132
  value: b.join(" | "),
133
- selector: v(i),
133
+ selector: v(l),
134
134
  sectionItems: b,
135
- sourceRefs: [{ file: l, original: i.innerHTML }]
135
+ sourceRefs: [{ file: i, original: l.innerHTML }]
136
136
  });
137
137
  }
138
138
  }
139
139
  const g = {};
140
140
  if (["alt", "href", "src", "aria-label", "title"].forEach((b) => {
141
- const m = i.getAttribute(b);
141
+ const m = l.getAttribute(b);
142
142
  m != null && m.trim() && (g[b] = m);
143
143
  }), Object.keys(g).length > 0 && !(p === "img" || p === "video")) {
144
144
  s += 1;
145
- const b = `${_(l || "index")}.property.${s}`;
145
+ const b = `${_(i || "index")}.property.${s}`;
146
146
  a.push({
147
147
  id: `dom_prop_${s}`,
148
148
  key: b,
149
149
  type: "property",
150
- label: v(i),
150
+ label: v(l),
151
151
  value: JSON.stringify(g),
152
- selector: v(i),
152
+ selector: v(l),
153
153
  attrs: g,
154
- sourceRefs: [{ file: l, original: JSON.stringify(g) }]
154
+ sourceRefs: [{ file: i, original: JSON.stringify(g) }]
155
155
  });
156
156
  }
157
157
  }
@@ -272,27 +272,27 @@ async function Le(e, t, a) {
272
272
  return typeof s == "string" && s.trim() ? s : e;
273
273
  }
274
274
  async function $e(e, t, a = "en", o) {
275
- const n = F(a), r = F(t), s = /* @__PURE__ */ new Map(), l = {}, c = Object.entries(e), f = c.length;
275
+ const n = F(a), r = F(t), s = /* @__PURE__ */ new Map(), i = {}, c = Object.entries(e), f = c.length;
276
276
  let d = 0;
277
- for (const [i, p] of c) {
277
+ for (const [l, p] of c) {
278
278
  if (s.has(p)) {
279
- l[i] = s.get(p), d += 1, o?.(d, f);
279
+ i[l] = s.get(p), d += 1, o?.(d, f);
280
280
  continue;
281
281
  }
282
282
  try {
283
283
  const g = await Le(p, n, r);
284
- s.set(p, g), l[i] = g;
284
+ s.set(p, g), i[l] = g;
285
285
  } catch {
286
- l[i] = p;
286
+ i[l] = p;
287
287
  }
288
288
  d += 1, o?.(d, f);
289
289
  }
290
- return l;
290
+ return i;
291
291
  }
292
- function re(e) {
292
+ function se(e) {
293
293
  return /^[^/\s]+\/[^/\s]+$/.test(e);
294
294
  }
295
- function se(e) {
295
+ function ie(e) {
296
296
  return /^([^/\s]+\/)+[^/\s]+$/.test(e);
297
297
  }
298
298
  async function Se(e, t, a) {
@@ -313,18 +313,18 @@ async function Ee() {
313
313
  if (!t || !t.provider || t.provider === "none" || t.provider !== "github" && t.provider !== "gitlab" || typeof t.repository != "string" || !t.repository.trim())
314
314
  return null;
315
315
  const a = t.repository.trim();
316
- return t.provider === "github" && !re(a) || t.provider === "gitlab" && !se(a) || typeof t.branch != "string" || !t.branch.trim() ? null : { ...t, repository: a, branch: t.branch.trim() };
316
+ 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() };
317
317
  } catch {
318
318
  return null;
319
319
  }
320
320
  }
321
- async function O(e, t, a, o, n) {
321
+ async function A(e, t, a, o, n) {
322
322
  const r = `https://api.github.com/repos/${e.repository}/contents/${encodeURIComponent(a).replace(/%2F/g, "/")}`;
323
323
  let s;
324
- const l = await fetch(`${r}?ref=${encodeURIComponent(e.branch)}`, {
324
+ const i = await fetch(`${r}?ref=${encodeURIComponent(e.branch)}`, {
325
325
  headers: { Authorization: `Bearer ${t}` }
326
326
  });
327
- l.ok && (s = (await l.json()).sha);
327
+ i.ok && (s = (await i.json()).sha);
328
328
  const c = {
329
329
  message: n,
330
330
  content: btoa(unescape(encodeURIComponent(o))),
@@ -343,24 +343,34 @@ async function O(e, t, a, o, n) {
343
343
  }
344
344
  async function _e(e, t, a) {
345
345
  const o = `chore(cms): publish content updates ${(/* @__PURE__ */ new Date()).toISOString()}`;
346
- if (await O(e, t, "cms-content.json", JSON.stringify(a.content, null, 2), o), a.locales)
346
+ if (await A(e, t, "cms-content.json", JSON.stringify(a.content, null, 2), o), a.locales) {
347
347
  for (const [n, r] of Object.entries(a.locales))
348
- await O(e, t, `locales/${n}.json`, JSON.stringify(r, null, 2), o);
349
- await O(e, t, "cms-export.patch.json", JSON.stringify(a, null, 2), o);
348
+ await A(e, t, `locales/${n}.json`, JSON.stringify(r, null, 2), o);
349
+ await A(
350
+ e,
351
+ t,
352
+ "cms-locales.json",
353
+ JSON.stringify({ version: 1, locales: a.locales }, null, 2),
354
+ o
355
+ );
356
+ }
357
+ await A(e, t, "cms-export.patch.json", JSON.stringify(a, null, 2), o);
350
358
  }
351
359
  async function Ae(e, t, a) {
352
360
  const o = [
353
361
  { filePath: "cms-content.json", content: JSON.stringify(a.content, null, 2) },
354
362
  { filePath: "cms-export.patch.json", content: JSON.stringify(a, null, 2) }
355
363
  ];
356
- if (a.locales)
357
- for (const [s, l] of Object.entries(a.locales))
358
- o.push({ filePath: `locales/${s}.json`, content: JSON.stringify(l, null, 2) });
364
+ if (a.locales) {
365
+ for (const [s, i] of Object.entries(a.locales))
366
+ o.push({ filePath: `locales/${s}.json`, content: JSON.stringify(i, null, 2) });
367
+ o.push({ filePath: "cms-locales.json", content: JSON.stringify({ version: 1, locales: a.locales }, null, 2) });
368
+ }
359
369
  const n = [];
360
370
  for (const s of o) {
361
- const l = await Se(e, t, s.filePath);
371
+ const i = await Se(e, t, s.filePath);
362
372
  n.push({
363
- action: l ? "update" : "create",
373
+ action: i ? "update" : "create",
364
374
  file_path: s.filePath,
365
375
  content: s.content
366
376
  });
@@ -382,15 +392,15 @@ async function Ae(e, t, a) {
382
392
  async function Te(e, t, a) {
383
393
  if (!a || !t.trim())
384
394
  return !1;
385
- if (a.provider === "github" && !re(a.repository))
395
+ if (a.provider === "github" && !se(a.repository))
386
396
  throw new Error('Invalid GitHub repository format. Use "owner/repo".');
387
- if (a.provider === "gitlab" && !se(a.repository))
397
+ if (a.provider === "gitlab" && !ie(a.repository))
388
398
  throw new Error('Invalid GitLab repository format. Use "group/project".');
389
399
  return a.provider === "github" ? (await _e(a, t.trim(), e), !0) : a.provider === "gitlab" ? (await Ae(a, t.trim(), e), !0) : !1;
390
400
  }
391
- const Y = "facms-auth-modal", M = "facms-auth-missing", V = "facms-token-modal", W = "facms-language-modal", Ie = "frontend-auto-cms::theme", ie = "frontend-auto-cms::main-language", le = "frontend-auto-cms::language-labels";
401
+ const Y = "facms-auth-modal", M = "facms-auth-missing", V = "facms-token-modal", W = "facms-language-modal", Ie = "frontend-auto-cms::theme", le = "frontend-auto-cms::main-language", ce = "frontend-auto-cms::language-labels";
392
402
  let D = !1, k = null, X = !1, x = null, u = "dark";
393
- function ce() {
403
+ function de() {
394
404
  if (document.getElementById("facms-dashboard-css"))
395
405
  return;
396
406
  const e = document.createElement("style");
@@ -629,15 +639,15 @@ function ce() {
629
639
  }
630
640
  `, document.head.appendChild(e);
631
641
  }
632
- function de(e) {
642
+ function ue(e) {
633
643
  u = e;
634
644
  const t = e === "dark";
635
645
  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(Ie, e);
636
646
  const o = document.getElementById("facms-theme-toggle");
637
647
  o && (o.textContent = e === "dark" ? "Switch to light" : "Switch to dark");
638
648
  }
639
- function ue() {
640
- u = "dark", de("dark");
649
+ function fe() {
650
+ u = "dark", ue("dark");
641
651
  }
642
652
  function Ce(e) {
643
653
  return Array.from(new Uint8Array(e)).map((t) => t.toString(16).padStart(2, "0")).join("");
@@ -646,7 +656,7 @@ async function je(e) {
646
656
  const t = new TextEncoder().encode(e), a = await crypto.subtle.digest("SHA-256", t);
647
657
  return Ce(a);
648
658
  }
649
- async function fe() {
659
+ async function pe() {
650
660
  if (x)
651
661
  return x;
652
662
  try {
@@ -694,10 +704,10 @@ function ze() {
694
704
  function Ne() {
695
705
  document.getElementById(M)?.remove();
696
706
  }
697
- async function pe() {
707
+ async function ge() {
698
708
  return await G(), k ? (Ne(), !0) : (ze(), !1);
699
709
  }
700
- function ge(e) {
710
+ function be(e) {
701
711
  const t = document.getElementById(Y);
702
712
  if (t) {
703
713
  t.style.display = "grid";
@@ -727,7 +737,7 @@ function ge(e) {
727
737
  }
728
738
  n && (n.style.display = "none"), D = !0, r(), e();
729
739
  };
730
- a.querySelector("#facms-passcode-cancel")?.addEventListener("click", r), a.querySelector("#facms-passcode-submit")?.addEventListener("click", s), o?.addEventListener("keydown", (l) => l.key === "Enter" && void s()), document.body.appendChild(a), o?.focus();
740
+ 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();
731
741
  }
732
742
  function Me(e, t) {
733
743
  const a = document.getElementById(V);
@@ -745,7 +755,7 @@ function Me(e, t) {
745
755
  </div>
746
756
  </div>
747
757
  `;
748
- const n = o.querySelector("#facms-token-input"), r = o.querySelector("#facms-token-error"), s = () => o.style.display = "none", l = () => {
758
+ const n = o.querySelector("#facms-token-input"), r = o.querySelector("#facms-token-error"), s = () => o.style.display = "none", i = () => {
749
759
  const c = (n?.value ?? "").trim();
750
760
  if (!c) {
751
761
  r && (r.style.display = "block");
@@ -753,7 +763,7 @@ function Me(e, t) {
753
763
  }
754
764
  r && (r.style.display = "none"), s(), t(c);
755
765
  };
756
- o.querySelector("#facms-token-cancel")?.addEventListener("click", s), o.querySelector("#facms-token-submit")?.addEventListener("click", l), n?.addEventListener("keydown", (c) => c.key === "Enter" && l()), document.body.appendChild(o), n?.focus();
766
+ 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();
757
767
  }
758
768
  function Pe(e, t, a) {
759
769
  const o = document.getElementById(W);
@@ -780,25 +790,25 @@ function Pe(e, t, a) {
780
790
  `;
781
791
  const r = () => n.style.display = "none";
782
792
  n.querySelector("#facms-language-cancel")?.addEventListener("click", r);
783
- const s = n.querySelector("#facms-language-select"), l = n.querySelector("#facms-language-input"), c = n.querySelector("#facms-language-name");
793
+ const s = n.querySelector("#facms-language-select"), i = n.querySelector("#facms-language-input"), c = n.querySelector("#facms-language-name");
784
794
  s?.addEventListener("change", () => {
785
795
  const d = s.value === "__custom__";
786
- l && (l.style.display = d ? "block" : "none"), c && (c.style.display = d ? "block" : "none");
796
+ i && (i.style.display = d ? "block" : "none"), c && (c.style.display = d ? "block" : "none");
787
797
  });
788
798
  const f = (d) => {
789
- const i = n.querySelector("#facms-language-error");
799
+ const l = n.querySelector("#facms-language-error");
790
800
  let p = "";
791
801
  const g = s?.value ?? "";
792
802
  let h = "";
793
- if (g && g !== "__custom__" ? (p = I(g), h = S(p)) : (p = I(l?.value ?? ""), h = (c?.value ?? "").trim()), !p || !/^[a-z]{2,3}([_-][a-z0-9]{2,8})?$|^[a-z]{3}_[A-Za-z]+$/i.test(p)) {
794
- i && (i.textContent = "Enter a valid language code.", i.style.display = "block");
803
+ if (g && g !== "__custom__" ? (p = C(g), h = S(p)) : (p = C(i?.value ?? ""), h = (c?.value ?? "").trim()), !p || !/^[a-z]{2,3}([_-][a-z0-9]{2,8})?$|^[a-z]{3}_[A-Za-z]+$/i.test(p)) {
804
+ l && (l.textContent = "Enter a valid language code.", l.style.display = "block");
795
805
  return;
796
806
  }
797
807
  if (h || (h = S(p)), e.includes(p)) {
798
- i && (i.textContent = `Language "${p}" already exists.`, i.style.display = "block");
808
+ l && (l.textContent = `Language "${p}" already exists.`, l.style.display = "block");
799
809
  return;
800
810
  }
801
- i && (i.style.display = "none"), r(), a(`${p}::${h}`, d);
811
+ l && (l.style.display = "none"), r(), a(`${p}::${h}`, d);
802
812
  };
803
813
  n.querySelector("#facms-language-manual")?.addEventListener("click", () => f("manual")), t && n.querySelector("#facms-language-autofill")?.addEventListener("click", () => f("auto")), document.body.appendChild(n);
804
814
  }
@@ -809,7 +819,7 @@ function z(e, t) {
809
819
  }
810
820
  console.info(`[frontend-auto-cms:dashboard] ${e}`, t);
811
821
  }
812
- function I(e) {
822
+ function C(e) {
813
823
  return e.trim().toLowerCase();
814
824
  }
815
825
  function Re(e) {
@@ -817,12 +827,12 @@ function Re(e) {
817
827
  return t === "/" ? "/" : (t.startsWith("/") ? t : `/${t}`).toLowerCase();
818
828
  }
819
829
  function S(e) {
820
- const t = I(e), a = B.find((o) => o.code === t);
830
+ const t = C(e), a = B.find((o) => o.code === t);
821
831
  return a ? a.label : t.toUpperCase();
822
832
  }
823
833
  function Be() {
824
834
  try {
825
- const e = localStorage.getItem(le);
835
+ const e = localStorage.getItem(ce);
826
836
  if (!e)
827
837
  return {};
828
838
  const t = JSON.parse(e);
@@ -832,24 +842,24 @@ function Be() {
832
842
  }
833
843
  }
834
844
  function H(e) {
835
- localStorage.setItem(le, JSON.stringify(e));
845
+ localStorage.setItem(ce, JSON.stringify(e));
836
846
  }
837
- function C(e) {
838
- const t = localStorage.getItem(ie);
847
+ function j(e) {
848
+ const t = localStorage.getItem(le);
839
849
  return t && e[t] ? t : e.en ? "en" : Object.keys(e)[0] ?? "en";
840
850
  }
841
851
  function Z(e) {
842
- localStorage.setItem(ie, e);
852
+ localStorage.setItem(le, e);
843
853
  }
844
854
  function y(e) {
845
855
  return e.replace(/[&<>'"]/g, (t) => ({ "&": "&amp;", "<": "&lt;", ">": "&gt;", "'": "&#39;", '"': "&quot;" })[t]);
846
856
  }
847
- function A(e, t = 72) {
857
+ function T(e, t = 72) {
848
858
  const a = e.replace(/\s+/g, " ").trim();
849
859
  return a.length <= t ? a : `${a.slice(0, t)}...`;
850
860
  }
851
861
  function De(e) {
852
- return e.type === "section" ? A((e.sectionItems ?? []).join(" | ")) : e.type === "property" ? A(JSON.stringify(e.attrs ?? {})) : A(e.value);
862
+ return e.type === "section" ? T((e.sectionItems ?? []).join(" | ")) : e.type === "property" ? T(JSON.stringify(e.attrs ?? {})) : T(e.value);
853
863
  }
854
864
  function Ge(e) {
855
865
  const t = [];
@@ -884,11 +894,11 @@ async function Ue(e) {
884
894
  }
885
895
  async function qe(e, t, a) {
886
896
  const o = e.nodes.flatMap(
887
- (s) => s.sourceRefs.map((l) => ({
888
- file: l.file,
889
- find: l.original,
897
+ (s) => s.sourceRefs.map((i) => ({
898
+ file: i.file,
899
+ find: i.original,
890
900
  replace: s.type === "property" ? JSON.stringify(s.attrs ?? {}) : s.type === "section" ? (s.sectionItems ?? []).join(" ") : s.type === "text" ? a[s.key] ?? s.value : s.value,
891
- occurrence: l.occurrence ?? 1
901
+ occurrence: i.occurrence ?? 1
892
902
  }))
893
903
  ), n = {
894
904
  generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
@@ -933,9 +943,9 @@ function Fe(e, t) {
933
943
  return;
934
944
  const o = Object.keys(t.locales);
935
945
  a.innerHTML = o.map((n) => {
936
- const r = n === t.activeLanguage, s = n === t.mainLanguage, l = t.languageLabels[n] ?? S(n);
946
+ const r = n === t.activeLanguage, s = n === t.mainLanguage, i = t.languageLabels[n] ?? S(n);
937
947
  return `<div class="inline-flex items-center rounded-lg overflow-hidden border ${r ? "border-indigo-500" : "border-slate-200 dark:border-slate-700"}">
938
- <button data-lang="${n}" class="px-2.5 py-1.5 text-xs ${r ? "bg-indigo-600 text-white" : "bg-slate-100 dark:bg-slate-800 text-slate-700 dark:text-slate-200"}">${y(l)}</button>
948
+ <button data-lang="${n}" class="px-2.5 py-1.5 text-xs ${r ? "bg-indigo-600 text-white" : "bg-slate-100 dark:bg-slate-800 text-slate-700 dark:text-slate-200"}">${y(i)}</button>
939
949
  ${s ? `<span class="px-2 py-1.5 text-[10px] font-semibold ${r ? "bg-indigo-700 text-indigo-100" : "bg-emerald-600 text-white"}">MAIN</span>` : `<button data-main-lang="${n}" title="Set as main language" class="px-2 py-1.5 text-xs ${r ? "bg-indigo-700 text-indigo-100 hover:bg-indigo-800" : "bg-emerald-600 text-white hover:bg-emerald-500"}">★</button>`}
940
950
  <button data-remove-lang="${n}" title="Remove language" class="px-2 py-1.5 text-xs ${r ? "bg-indigo-700 text-indigo-100 hover:bg-indigo-800" : "bg-slate-200 dark:bg-slate-700 text-slate-700 dark:text-slate-200 hover:bg-slate-300 dark:hover:bg-slate-600"}">×</button>
941
951
  </div>`;
@@ -959,7 +969,7 @@ function Fe(e, t) {
959
969
  alert("You must keep at least one language.");
960
970
  return;
961
971
  }
962
- delete t.locales[s], delete t.languageLabels[s], H(t.languageLabels), T(t.locales), t.mainLanguage === s && (t.mainLanguage = C(t.locales), Z(t.mainLanguage), t.baseTextByKey = { ...t.locales[t.mainLanguage] ?? {} }), t.activeLanguage === s && (t.activeLanguage = U(t.locales, t.mainLanguage)), be(t), L(e, t);
972
+ delete t.locales[s], delete t.languageLabels[s], H(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 = U(t.locales, t.mainLanguage)), me(t), L(e, t);
963
973
  }
964
974
  });
965
975
  });
@@ -974,7 +984,7 @@ function Ye(e, t) {
974
984
  r.value = a.value, r.type === "text" && (t.activeLanguage === t.mainLanguage ? (t.baseTextByKey[r.key] = a.value, t.locales[t.mainLanguage] = { ...t.locales[t.mainLanguage] ?? {}, [r.key]: a.value }) : t.locales[t.activeLanguage] = {
975
985
  ...t.locales[t.activeLanguage] ?? {},
976
986
  [r.key]: a.value
977
- }, T(t.locales));
987
+ }, I(t.locales));
978
988
  else if (n === "alt") r.attrs = { ...r.attrs ?? {}, alt: a.value };
979
989
  else if (n === "sectionItems") r.sectionItems = a.value.split(`
980
990
  `).map((s) => s.trim()).filter(Boolean);
@@ -999,13 +1009,13 @@ function P(e, t) {
999
1009
  }
1000
1010
  function L(e, t) {
1001
1011
  const a = Ge(t.content.nodes), o = a.length ? a.map((n) => {
1002
- const r = n.items[0], s = n.items[n.items.length - 1], l = r.index === s.index ? `#${r.index + 1}` : `#${r.index + 1} - #${s.index + 1}`, c = n.items.map((i) => De(i.node)).filter(Boolean).join(" • "), f = n.items.length > 1 ? `${l} ${y(n.selector || "Grouped fields")} (${n.items.length} fields)` : `${l} ${y(r.node.type.toUpperCase())} • ${y(r.node.label || r.node.selector || "")}`, d = n.items.map((i) => Ke(i.node, i.index)).join("");
1012
+ 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) => De(l.node)).filter(Boolean).join(" • "), f = n.items.length > 1 ? `${i} ${y(n.selector || "Grouped fields")} (${n.items.length} fields)` : `${i} ${y(r.node.type.toUpperCase())} • ${y(r.node.label || r.node.selector || "")}`, d = n.items.map((l) => Ke(l.node, l.index)).join("");
1003
1013
  return `
1004
1014
  <details class="rounded-xl p-2 border border-slate-200 dark:border-transparent bg-white dark:bg-slate-900/60 shadow-sm">
1005
1015
  <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">
1006
1016
  <div class="min-w-0">
1007
1017
  <div class="text-xs text-slate-500 dark:text-slate-400">${f}</div>
1008
- <div class="text-sm text-slate-700 dark:text-slate-300 truncate">${y(A(c || "No preview"))}</div>
1018
+ <div class="text-sm text-slate-700 dark:text-slate-300 truncate">${y(T(c || "No preview"))}</div>
1009
1019
  </div>
1010
1020
  <span class="text-xs text-indigo-600 dark:text-indigo-400">Expand</span>
1011
1021
  </summary>
@@ -1038,13 +1048,13 @@ function L(e, t) {
1038
1048
  return;
1039
1049
  }
1040
1050
  const s = r.provider;
1041
- Me(s, async (l) => {
1051
+ Me(s, async (i) => {
1042
1052
  let c = !1, f = "Publishing failed. Please verify token permissions and repository settings.";
1043
1053
  try {
1044
- c = await Te(n, l, r);
1054
+ c = await Te(n, i, r);
1045
1055
  } catch (d) {
1046
- const i = d instanceof Error ? d.message : String(d);
1047
- i && (f = `Publishing failed: ${i}`), c = !1;
1056
+ const l = d instanceof Error ? d.message : String(d);
1057
+ l && (f = `Publishing failed: ${l}`), c = !1;
1048
1058
  }
1049
1059
  if (!c) {
1050
1060
  alert(f);
@@ -1054,27 +1064,27 @@ function L(e, t) {
1054
1064
  });
1055
1065
  }), e.querySelector("#facms-add-language")?.addEventListener("click", () => {
1056
1066
  Pe(Object.keys(t.locales), x?.autoTranslateEnabled ?? !0, async (n, r) => {
1057
- const [s, l] = n.split("::"), c = I(s ?? ""), f = (l ?? "").trim() || S(c);
1067
+ const [s, i] = n.split("::"), c = C(s ?? ""), f = (i ?? "").trim() || S(c);
1058
1068
  if (!c)
1059
1069
  return;
1060
- const d = performance.now(), i = t.locales[t.mainLanguage] ?? t.baseTextByKey, p = { ...i };
1070
+ const d = performance.now(), l = t.locales[t.mainLanguage] ?? t.baseTextByKey, p = { ...l };
1061
1071
  if (z("Add language requested", {
1062
1072
  lang: c,
1063
1073
  mode: r,
1064
- sourceKeys: Object.keys(i).length,
1074
+ sourceKeys: Object.keys(l).length,
1065
1075
  browserLanguage: navigator.language,
1066
1076
  browserLanguages: navigator.languages
1067
- }), t.locales[c] = p, t.languageLabels[c] = f, H(t.languageLabels), t.activeLanguage = c, T(t.locales), E(t.content, t.locales[c], t.workingDocument, t.baseTextByKey), L(e, t), z("Manual language tab created", { lang: c }), w(e, `Added ${f} tab prefilled with source text for manual translation.`, !1), r !== "auto" || !(x?.autoTranslateEnabled ?? !0)) {
1077
+ }), t.locales[c] = p, t.languageLabels[c] = f, H(t.languageLabels), t.activeLanguage = c, I(t.locales), E(t.content, t.locales[c], t.workingDocument, t.baseTextByKey), L(e, t), z("Manual language tab created", { lang: c }), w(e, `Added ${f} tab prefilled with source text for manual translation.`, !1), r !== "auto" || !(x?.autoTranslateEnabled ?? !0)) {
1068
1078
  r === "auto" && !(x?.autoTranslateEnabled ?? !0) && w(e, `Privacy mode is on. Added ${f} tab for manual translation only.`, !1);
1069
1079
  return;
1070
1080
  }
1071
1081
  try {
1072
- const g = Object.keys(i).length;
1082
+ const g = Object.keys(l).length;
1073
1083
  w(e, `Auto-filling ${f} translation... (0/${g})`, !0);
1074
- const h = await $e(i, c, t.mainLanguage, (q, b) => {
1084
+ const h = await $e(l, c, t.mainLanguage, (q, b) => {
1075
1085
  w(e, `Auto-filling ${f} translation... (${q}/${b})`, !0);
1076
1086
  });
1077
- t.locales[c] = h, T(t.locales), t.activeLanguage = c, E(t.content, h, t.workingDocument, t.baseTextByKey), L(e, t), z("Automatic translation succeeded", {
1087
+ t.locales[c] = h, I(t.locales), t.activeLanguage = c, E(t.content, h, t.workingDocument, t.baseTextByKey), L(e, t), z("Automatic translation succeeded", {
1078
1088
  lang: c,
1079
1089
  translatedKeys: Object.keys(h).length,
1080
1090
  ms: Math.round(performance.now() - d)
@@ -1091,13 +1101,13 @@ function L(e, t) {
1091
1101
  }), Ye(e, t);
1092
1102
  }
1093
1103
  function U(e, t) {
1094
- const a = Object.keys(e), o = t && e[t] ? t : C(e), n = [...navigator.languages ?? [], navigator.language].map((r) => r.toLowerCase().split("-")[0]);
1104
+ const a = Object.keys(e), o = t && e[t] ? t : j(e), n = [...navigator.languages ?? [], navigator.language].map((r) => r.toLowerCase().split("-")[0]);
1095
1105
  for (const r of n)
1096
1106
  if (a.includes(r))
1097
1107
  return r;
1098
1108
  return a.includes(o) ? o : a[0] ?? "en";
1099
1109
  }
1100
- function be(e) {
1110
+ function me(e) {
1101
1111
  const t = e.locales[e.activeLanguage] ?? e.locales.en ?? e.baseTextByKey;
1102
1112
  E(e.content, t, e.workingDocument, e.baseTextByKey);
1103
1113
  }
@@ -1118,26 +1128,26 @@ function We(e, t, a) {
1118
1128
  const o = ne(), n = {
1119
1129
  ...a,
1120
1130
  ...o
1121
- }, r = Be(), s = Object.fromEntries(e.nodes.filter((i) => i.type === "text").map((i) => [i.key, i.value])), l = C(n), c = {
1131
+ }, r = Be(), s = Object.fromEntries(e.nodes.filter((l) => l.type === "text").map((l) => [l.key, l.value])), i = j(n), c = {
1122
1132
  ...n,
1123
- [l]: { ...n[l] ?? {}, ...s }
1133
+ [i]: { ...n[i] ?? {}, ...s }
1124
1134
  };
1125
- !c.en && l === "en" && (c.en = Object.assign({}, c.en ?? {}, s));
1126
- const f = U(c, l), d = { ...r };
1127
- return Object.keys(c).forEach((i) => {
1128
- d[i] || (d[i] = S(i));
1135
+ !c.en && i === "en" && (c.en = Object.assign({}, c.en ?? {}, s));
1136
+ const f = U(c, i), d = { ...r };
1137
+ return Object.keys(c).forEach((l) => {
1138
+ d[l] || (d[l] = S(l));
1129
1139
  }), H(d), {
1130
1140
  content: e,
1131
1141
  locales: c,
1132
1142
  workingDocument: t,
1133
- baseTextByKey: c[l] ?? s,
1143
+ baseTextByKey: c[i] ?? s,
1134
1144
  activeLanguage: f,
1135
- mainLanguage: l,
1145
+ mainLanguage: i,
1136
1146
  languageLabels: d
1137
1147
  };
1138
1148
  }
1139
1149
  async function Xe() {
1140
- const e = await he();
1150
+ const e = await xe();
1141
1151
  if (!e?.nodes?.length)
1142
1152
  return;
1143
1153
  const t = $(document, location.pathname);
@@ -1151,17 +1161,20 @@ async function Xe() {
1151
1161
  }
1152
1162
  async function Ze() {
1153
1163
  await Xe();
1154
- const e = ne();
1155
- if (!Object.keys(e).length)
1164
+ const t = {
1165
+ ...await oe(),
1166
+ ...ne()
1167
+ };
1168
+ if (!Object.keys(t).length)
1156
1169
  return;
1157
- const t = U(e, C(e));
1158
- if (!t || t === "en")
1170
+ const a = j(t), o = U(t, a);
1171
+ if (!o || o === a)
1159
1172
  return;
1160
- const a = $(document, location.pathname), o = e[t];
1161
- if (!o)
1173
+ const n = $(document, location.pathname), r = t[o];
1174
+ if (!r)
1162
1175
  return;
1163
- const n = Object.fromEntries(a.nodes.filter((r) => r.type === "text").map((r) => [r.key, r.value]));
1164
- E(a, o, document, n);
1176
+ const s = Object.fromEntries(n.nodes.filter((i) => i.type === "text").map((i) => [i.key, i.value]));
1177
+ E(n, r, document, s);
1165
1178
  }
1166
1179
  function Qe(e) {
1167
1180
  const t = e.pages.length ? e.pages : ["/"];
@@ -1194,7 +1207,7 @@ function Qe(e) {
1194
1207
  </div>
1195
1208
  `;
1196
1209
  const a = document.getElementById("facms-route-preview"), o = document.getElementById("facms-route-editor"), n = document.getElementById("facms-page-tabs"), r = /* @__PURE__ */ new Map();
1197
- let s = t[0], l = {};
1210
+ let s = t[0], i = {};
1198
1211
  const c = () => {
1199
1212
  n.innerHTML = t.map(
1200
1213
  (f) => `<button data-page="${f}" class="w-full text-left px-3 py-2 rounded-lg text-sm border ${f === s ? "bg-indigo-600 border-indigo-500 text-white" : "bg-slate-100 border-slate-200 dark:bg-slate-800 dark:border-slate-700 text-slate-700 dark:text-slate-200 hover:bg-slate-200 dark:hover:bg-slate-700"}">${y(f)}</button>`
@@ -1204,7 +1217,7 @@ function Qe(e) {
1204
1217
  });
1205
1218
  });
1206
1219
  };
1207
- de(u), a.addEventListener("load", async () => {
1220
+ ue(u), a.addEventListener("load", async () => {
1208
1221
  const f = a.contentDocument;
1209
1222
  if (f) {
1210
1223
  P(!0, `Scanning page content for ${s}...`);
@@ -1212,40 +1225,40 @@ function Qe(e) {
1212
1225
  let d = r.get(s);
1213
1226
  if (d) {
1214
1227
  d.workingDocument = f;
1215
- const i = d.content.nodes.length ? $(f, s) : await Q(f, s);
1216
- i.nodes.length && !d.content.nodes.length && (d.content = i);
1228
+ const l = d.content.nodes.length ? $(f, s) : await Q(f, s);
1229
+ l.nodes.length && !d.content.nodes.length && (d.content = l);
1217
1230
  } else {
1218
- const i = await Q(f, s);
1219
- d = We(i, f, l), r.set(s, d);
1231
+ const l = await Q(f, s);
1232
+ d = We(l, f, i), r.set(s, d);
1220
1233
  }
1221
- be(d), ae(d.content), L(o, d);
1234
+ me(d), ae(d.content), L(o, d);
1222
1235
  } finally {
1223
1236
  P(!1, "Loading");
1224
1237
  }
1225
1238
  }
1226
- }), c(), xe().then((f) => {
1227
- l = f, a.src = s;
1239
+ }), c(), oe().then((f) => {
1240
+ i = f, a.src = s;
1228
1241
  });
1229
1242
  }
1230
1243
  async function ee() {
1231
- if (ce(), ue(), !await pe())
1244
+ if (de(), fe(), !await ge())
1232
1245
  return;
1233
- const e = await fe(), t = () => Qe(e);
1246
+ const e = await pe(), t = () => Qe(e);
1234
1247
  if (!D) {
1235
- ge(t);
1248
+ be(t);
1236
1249
  return;
1237
1250
  }
1238
1251
  t();
1239
1252
  }
1240
1253
  async function et() {
1241
- const e = await fe(), a = new URLSearchParams(location.search).get("__facms") === "1";
1254
+ const e = await pe(), a = new URLSearchParams(location.search).get("__facms") === "1";
1242
1255
  if (location.pathname !== e.dashboardPath && !a) {
1243
1256
  Ze();
1244
1257
  return;
1245
1258
  }
1246
- if (ce(), ue(), !!await pe()) {
1259
+ if (de(), fe(), !!await ge()) {
1247
1260
  if (!D) {
1248
- ge(() => {
1261
+ be(() => {
1249
1262
  ee();
1250
1263
  });
1251
1264
  return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "frontend-auto-cms",
3
- "version": "1.0.8",
3
+ "version": "1.0.10",
4
4
  "description": "Turn any frontend into an editable mini-CMS with one import.",
5
5
  "type": "module",
6
6
  "license": "MIT",