@oktis-works/admin 0.23.2 → 0.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/dist/client/_astro/{ActivityWidget.Dzoi-bq3.js → ActivityWidget.ZVWCvrxL.js} +1 -1
  2. package/dist/client/_astro/{AdminBar.eT1ch_B6.js → AdminBar.Cp3-f-Na.js} +1 -1
  3. package/dist/client/_astro/{ApiKeysManager.kbTE1CPk.js → ApiKeysManager.CpgNjjZm.js} +1 -1
  4. package/dist/client/_astro/{AtGlanceWidget.w23IIv06.js → AtGlanceWidget.B4v1yrwI.js} +1 -1
  5. package/dist/client/_astro/BaseLayout.Ceb72bti.css +1 -0
  6. package/dist/client/_astro/{CommentsManager.BN7i1RHa.js → CommentsManager.Da4veAPJ.js} +1 -1
  7. package/dist/client/_astro/ContentEditor.CSin5EHw.js +1 -0
  8. package/dist/client/_astro/ContentTypeWorkspace.CjOEvGzy.js +1 -0
  9. package/dist/client/_astro/{DashboardHome.DXzu_IXZ.js → DashboardHome.C40YVSiB.js} +1 -1
  10. package/dist/client/_astro/{DashboardLayout.astro_astro_type_script_index_0_lang.DmNSzErX.js → DashboardLayout.astro_astro_type_script_index_0_lang.DEsBqJww.js} +1 -1
  11. package/dist/client/_astro/{FieldGroupEditor.DsqphEgt.js → FieldGroupEditor.9WZ-czWM.js} +3 -3
  12. package/dist/client/_astro/{FieldGroupList.pW2Um9om.js → FieldGroupList.BG9Wq5_L.js} +1 -1
  13. package/dist/client/_astro/FieldRenderer.DrX12H8L.js +3 -0
  14. package/dist/client/_astro/{Footer.5Lcn2VXz.js → Footer.D7L9WAh7.js} +1 -1
  15. package/dist/client/_astro/{GeneralSettings.B-H8Rzy7.js → GeneralSettings.udEZdv-v.js} +1 -1
  16. package/dist/client/_astro/{LogsManager.Crd8q2te.js → LogsManager.B5TC9xQ_.js} +1 -1
  17. package/dist/client/_astro/{MediaLibrary.Cv6Ry3u9.js → MediaLibrary.D2v__yUO.js} +1 -1
  18. package/dist/client/_astro/{MenuManager.D25ika09.js → MenuManager.glKVLQiP.js} +1 -1
  19. package/dist/client/_astro/{Modal.572hmVvb.js → Modal.DijYhpj_.js} +1 -1
  20. package/dist/client/_astro/PluginManager.BGdxyG-e.js +112 -0
  21. package/dist/client/_astro/PluginPageHost.CEDOBtUT.js +1 -0
  22. package/dist/client/_astro/{PostTypesManager.C3RbmOZT.js → PostTypesManager.DTbeJSyc.js} +1 -1
  23. package/dist/client/_astro/{QuickDraftWidget.BtSGzhKq.js → QuickDraftWidget.wRkEcf8k.js} +1 -1
  24. package/dist/client/_astro/{ReadingSettings.ZFDaeo5U.js → ReadingSettings.CD8voAVk.js} +1 -1
  25. package/dist/client/_astro/{ResourceHubs.Cx9fbCv1.js → ResourceHubs.Cpu4lcaN.js} +1 -1
  26. package/dist/client/_astro/{TaxonomiesManager.BLsvmjaL.js → TaxonomiesManager.gPoogAar.js} +1 -1
  27. package/dist/client/_astro/TaxonomyTermsManager.B3TphEaE.js +1 -0
  28. package/dist/client/_astro/{ThemeCustomizer.BrDHVXLk.js → ThemeCustomizer.BKKTlRC5.js} +1 -1
  29. package/dist/client/_astro/{ThemeManager.BpS3m7Qc.js → ThemeManager.KDwxbVIq.js} +1 -1
  30. package/dist/client/_astro/{UserCreateForm.BYwgAqKk.js → UserCreateForm.IAFj7Afs.js} +1 -1
  31. package/dist/client/_astro/{UsersManager.DODMr48D.js → UsersManager.BfVYX6D5.js} +1 -1
  32. package/dist/client/_astro/{WebhooksManager.DmWIW272.js → WebhooksManager.Bp3Zp4vO.js} +1 -1
  33. package/dist/client/_astro/{api.53l1ob4Z.js → api.C1uUawnK.js} +1 -1
  34. package/dist/client/_astro/extensions.XVI9Kud6.js +1 -0
  35. package/dist/client/_astro/i18n.TTF80CEw.js +1 -0
  36. package/dist/client/_astro/{login.astro_astro_type_script_index_0_lang.BLf2Iun3.js → login.astro_astro_type_script_index_0_lang.C_Lrwk3I.js} +1 -1
  37. package/dist/client/_astro/{pt-BR.zZcF2v3X.js → pt-BR.C041vzOT.js} +1 -1
  38. package/dist/client/_astro/slots.CSARb9TW.js +1 -0
  39. package/dist/client/_astro/{src.CYKGYEyR.js → src.DoHIZU0i.js} +1 -1
  40. package/dist/client/_astro/store.BUgA6DSh.js +1 -0
  41. package/dist/server/chunks/{404_BAOD9OCa.mjs → 404_CouGE9Mj.mjs} +1 -1
  42. package/dist/server/chunks/{BaseLayout_BE8O-LS4.mjs → BaseLayout_DRJ6-Y9z.mjs} +5 -5
  43. package/dist/server/chunks/ContentEditor_DIjqVt5v.mjs +324 -0
  44. package/dist/server/chunks/{DashboardLayout_D6zphdT0.mjs → DashboardLayout_Bz8ZBDme.mjs} +102 -17
  45. package/dist/server/chunks/{FieldRenderer_D4dcZjgt.mjs → FieldRenderer_RlFoxao4.mjs} +574 -66
  46. package/dist/server/chunks/{MediaLibrary_DGmYSSZH.mjs → MediaLibrary_Dh6dBT17.mjs} +2 -2
  47. package/dist/server/chunks/{Modal_BmuvdwoB.mjs → Modal_CpojFoyP.mjs} +1 -1
  48. package/dist/server/chunks/_.._C1o1V5X_.mjs +76 -0
  49. package/dist/server/chunks/{_id__XEnJ5nS2.mjs → _id__BKZ7vD0U.mjs} +4 -4
  50. package/dist/server/chunks/{access_B5npG273.mjs → access_COyC7DxO.mjs} +3 -3
  51. package/dist/server/chunks/{api-keys_Bs6zIXYm.mjs → api-keys_D2TJYRAW.mjs} +3 -3
  52. package/dist/server/chunks/{comments_zJrnFEjl.mjs → comments_CySyBx_l.mjs} +2 -2
  53. package/dist/server/chunks/{custom-fields_C5EBkR02.mjs → custom-fields_Clivf3ew.mjs} +2 -2
  54. package/dist/server/chunks/{customize_CKqMX14y.mjs → customize_XWQyyFCl.mjs} +3 -3
  55. package/dist/server/chunks/{edit_QKBYgFkJ.mjs → edit_CYlskXjG.mjs} +2 -2
  56. package/dist/server/chunks/{i18n_C-sgJSi1.mjs → i18n_Bp0_xO2v.mjs} +27 -8
  57. package/dist/server/chunks/{index_CDwohy44.mjs → index_BufAjUfw.mjs} +2 -2
  58. package/dist/server/chunks/{index_DenKi4a3.mjs → index_CJOIvqZF.mjs} +2 -2
  59. package/dist/server/chunks/{index_BM_-WBYo.mjs → index_DBmNvPut.mjs} +2 -2
  60. package/dist/server/chunks/{index_BletZ9T6.mjs → index_Z5USLJCo.mjs} +3 -3
  61. package/dist/server/chunks/{index_Btvmuytk.mjs → index_pSSu8X0A.mjs} +2 -2
  62. package/dist/server/chunks/{login_CtIWLqC2.mjs → login_BbReGd7a.mjs} +1 -1
  63. package/dist/server/chunks/{logs_DlTldv5b.mjs → logs_D_xRW_Dm.mjs} +2 -2
  64. package/dist/server/chunks/{menus_z2d_K44p.mjs → menus_t0aZuQCI.mjs} +2 -2
  65. package/dist/server/chunks/{new_CYvLScge.mjs → new_CkSJ-S3h.mjs} +2 -2
  66. package/dist/server/chunks/{new_Cxp8Mdw4.mjs → new_DFA50r2h.mjs} +2 -2
  67. package/dist/server/chunks/{plugins_4g6EEkCb.mjs → plugins_rehiATzz.mjs} +13 -5
  68. package/dist/server/chunks/{post-types_7cW4BLBV.mjs → post-types_Dx4bmkB7.mjs} +2 -2
  69. package/dist/server/chunks/{pt-BR_AVNE88MZ.mjs → pt-BR_B8bZo1Id.mjs} +7 -1
  70. package/dist/server/chunks/{reading_2DqfBhj_.mjs → reading_DVMggOZa.mjs} +2 -2
  71. package/dist/server/chunks/{taxonomies_D7mMKpNX.mjs → taxonomies_BKVuy-kF.mjs} +2 -2
  72. package/dist/server/chunks/{taxonomy_64ggDTF9.mjs → taxonomy_CsnDSlD1.mjs} +31 -18
  73. package/dist/server/chunks/{themes_Dscq-5uk.mjs → themes_c2vDYHy-.mjs} +2 -2
  74. package/dist/server/chunks/{upload_B-DdqpaQ.mjs → upload_DYFOxmHE.mjs} +2 -2
  75. package/dist/server/chunks/{webhooks_D05B4_Rs.mjs → webhooks_CjBMAJt2.mjs} +2 -2
  76. package/dist/server/entry.mjs +43 -43
  77. package/dist/server/virtual_astro_middleware.mjs +1 -1
  78. package/package.json +5 -5
  79. package/dist/client/_astro/BaseLayout.Rpr86VwM.css +0 -1
  80. package/dist/client/_astro/ContentEditor.BlsJ2bwD.js +0 -1
  81. package/dist/client/_astro/ContentTypeWorkspace.BPVuQgzA.js +0 -1
  82. package/dist/client/_astro/FieldRenderer.AYtSBfHZ.js +0 -3
  83. package/dist/client/_astro/PluginManager.DLfgQFPF.js +0 -112
  84. package/dist/client/_astro/TaxonomyTermsManager.C_xEh8Ab.js +0 -1
  85. package/dist/client/_astro/extensions.DzQcQsO9.js +0 -1
  86. package/dist/client/_astro/i18n.A82w5XQu.js +0 -1
  87. package/dist/client/_astro/preload-helper.oCYlU9a4.js +0 -1
  88. package/dist/client/_astro/store.DLCqLxBR.js +0 -1
  89. package/dist/server/chunks/ContentEditor_DPy3I4HM.mjs +0 -690
  90. package/dist/server/chunks/_slug__BkXrukGe.mjs +0 -34
@@ -1,690 +0,0 @@
1
- import { n as useTranslation, r as apiClient } from "./i18n_C-sgJSi1.mjs";
2
- import { a as MetaBoxesSlot, n as emptyExtensionsState, o as PluginComponentHost, r as loadExtensions } from "./DashboardLayout_D6zphdT0.mjs";
3
- import { t as FieldRenderer } from "./FieldRenderer_D4dcZjgt.mjs";
4
- import { t as expandCloneFields } from "./clone_FT3Zf-Bf.mjs";
5
- import { createComponent, escape, ssr, ssrAttribute, ssrHydrationKey } from "solid-js/web";
6
- import { For, Show, createMemo, createSignal, onMount } from "solid-js";
7
- //#region src/lib/sanitize.ts
8
- /**
9
- * Sanitizador de HTML em allowlist para pontos de injeção (innerHTML).
10
- *
11
- * O admin injeta HTML apenas no conteúdo das abas de ajuda (HelpTabs), que
12
- * vem do i18n — mas todo innerHTML passa por aqui por defesa em profundidade.
13
- *
14
- * Garantias:
15
- * - Allowlist de tags e atributos (script/style/svg/iframe/form são removidos,
16
- * incluindo o conteúdo de tags de texto bruto como <script> e <style>).
17
- * - Atributos de evento (on*), style e demais fora da allowlist são descartados.
18
- * - href/src têm o protocolo validado DEPOIS de decodificar entidades e remover
19
- * tab/newline — o valor emitido é re-escapado a partir do valor decodificado,
20
- * de modo que o que o navegador decodifica é exatamente o que foi validado
21
- * (bloqueia `javascript:`, `&#106;avascript:`, `javascript&colon;`, etc).
22
- * - Texto é escapado (& < >), preservando entidades já válidas.
23
- * - Tags de fechamento sem âncora são ignoradas: conteúdo malicioso não consegue
24
- * "escapar" do container nem desbalancear a árvore (o quebra-cabeça de abas
25
- * e widgets continua íntegro).
26
- *
27
- * Puro JavaScript, sem APIs de DOM: roda igual no SSR (Node) e no navegador.
28
- */
29
- /** Tags permitidas (conteúdo rico simples: ajuda, títulos, listas, links). */
30
- var ALLOWED_TAGS = /* @__PURE__ */ new Set([
31
- "a",
32
- "abbr",
33
- "b",
34
- "blockquote",
35
- "br",
36
- "code",
37
- "dd",
38
- "div",
39
- "dl",
40
- "dt",
41
- "em",
42
- "figcaption",
43
- "figure",
44
- "h1",
45
- "h2",
46
- "h3",
47
- "h4",
48
- "h5",
49
- "h6",
50
- "hr",
51
- "i",
52
- "img",
53
- "li",
54
- "ol",
55
- "p",
56
- "pre",
57
- "q",
58
- "s",
59
- "span",
60
- "strong",
61
- "sub",
62
- "sup",
63
- "u",
64
- "ul"
65
- ]);
66
- /** Tags vazias (emitidas com fechamento próprio, nunca empilhadas). */
67
- var VOID_TAGS = /* @__PURE__ */ new Set([
68
- "br",
69
- "hr",
70
- "img"
71
- ]);
72
- /**
73
- * Tags cujo conteúdo é texto bruto no HTML. Ao encontrá-las abertas, todo o
74
- * miolo é descartado até o fechamento correspondente (senão, o conteúdo do
75
- * <script> viraria texto visível ou vetor de parse).
76
- */
77
- var RAW_TEXT_TAGS = /* @__PURE__ */ new Set([
78
- "script",
79
- "style",
80
- "iframe",
81
- "object",
82
- "embed",
83
- "svg",
84
- "math",
85
- "textarea",
86
- "title",
87
- "noscript",
88
- "template"
89
- ]);
90
- /** Atributos permitidos (globais; validação extra por atributo abaixo). */
91
- var ALLOWED_ATTRS = /* @__PURE__ */ new Set([
92
- "class",
93
- "title",
94
- "alt",
95
- "width",
96
- "height",
97
- "href",
98
- "src",
99
- "target",
100
- "rel"
101
- ]);
102
- /** Esquemas aceitos em href (links externos, e-mail, telefone). */
103
- var HREF_SCHEMES = /* @__PURE__ */ new Set([
104
- "http",
105
- "https",
106
- "mailto",
107
- "tel"
108
- ]);
109
- /** Esquemas aceitos em src (somente rede). */
110
- var SRC_SCHEMES = /* @__PURE__ */ new Set(["http", "https"]);
111
- /** Entidades nomeadas relevantes (as que poderiam alterar a validação de URL). */
112
- var NAMED_ENTITIES = {
113
- amp: "&",
114
- lt: "<",
115
- gt: ">",
116
- quot: "\"",
117
- apos: "'",
118
- colon: ":",
119
- tab: " ",
120
- newline: "\n",
121
- sol: "/",
122
- lpar: "(",
123
- rpar: ")",
124
- num: "#",
125
- period: ".",
126
- excl: "!",
127
- comma: ","
128
- };
129
- /** Decodifica referências numéricas e nomeadas (uma passada, como o navegador). */
130
- function decodeEntities(value) {
131
- return value.replace(/&#x([0-9a-fA-F]+);?/g, (_m, hex) => fromCodePoint(parseInt(hex, 16))).replace(/&#(\d+);?/g, (_m, dec) => fromCodePoint(parseInt(dec, 10))).replace(/&([a-zA-Z][a-zA-Z0-9]{1,30});?/g, (m, name) => {
132
- return NAMED_ENTITIES[name in NAMED_ENTITIES ? name : name.toLowerCase()] ?? m;
133
- });
134
- }
135
- function fromCodePoint(cp) {
136
- if (!Number.isFinite(cp) || cp < 0 || cp > 1114111) return "";
137
- try {
138
- return String.fromCodePoint(cp);
139
- } catch {
140
- return "";
141
- }
142
- }
143
- /** Escapa valor para uso dentro de atributo entre aspas duplas. */
144
- function escapeAttr(value) {
145
- return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
146
- }
147
- /**
148
- * Escapa texto preservando entidades já válidas (evita exibir `&amp;`
149
- * literalmente quando a tradução usa `&amp;` de propósito).
150
- */
151
- function escapeText(text) {
152
- return text.replace(/&(?![a-zA-Z][a-zA-Z0-9]{1,30};|#[0-9]{1,7};|#[xX][0-9a-fA-F]{1,6};)|[<>]/g, (m) => m === "&" ? "&amp;" : m === "<" ? "&lt;" : "&gt;");
153
- }
154
- /**
155
- * Valida URL decodificando entidades e removendo tab/newline (mesmo tratamento
156
- * do parser de URL do navegador) antes de inspecionar o esquema.
157
- */
158
- function isSafeUrl(raw, allowedSchemes) {
159
- const decoded = decodeEntities(raw).replace(/[\t\n\r]/g, "").trim();
160
- const scheme = /^([a-zA-Z][a-zA-Z0-9+.-]*):/.exec(decoded);
161
- if (!scheme) return true;
162
- return allowedSchemes.has(scheme[1].toLowerCase());
163
- }
164
- /** Normaliza valor de atributo: decodifica (como o navegador faria) e re-escapa. */
165
- function normalizeAttrValue(raw) {
166
- return escapeAttr(decodeEntities(raw));
167
- }
168
- /**
169
- * Extrai pares nome/valor de uma tag, respeitando aspas (um `>` dentro de
170
- * aspas não termina a tag) e valores não-aspados do HTML.
171
- */
172
- function parseAttrs(body) {
173
- const pairs = [];
174
- const n = body.length;
175
- let i = 0;
176
- const isWs = (c) => c === " " || c === " " || c === "\n" || c === "\r" || c === "\f";
177
- while (i < n) {
178
- while (i < n && (isWs(body.charAt(i)) || body.charAt(i) === "/")) i++;
179
- if (i >= n) break;
180
- let name = "";
181
- while (i < n && !isWs(body.charAt(i)) && body.charAt(i) !== "=" && body.charAt(i) !== ">" && body.charAt(i) !== "/" && body.charAt(i) !== "<") {
182
- name += body.charAt(i);
183
- i++;
184
- }
185
- if (!name) {
186
- i++;
187
- continue;
188
- }
189
- let value = "";
190
- let j = i;
191
- while (j < n && isWs(body.charAt(j))) j++;
192
- if (j < n && body.charAt(j) === "=") {
193
- j++;
194
- while (j < n && isWs(body.charAt(j))) j++;
195
- if (j < n && (body.charAt(j) === "\"" || body.charAt(j) === "'")) {
196
- const quote = body.charAt(j);
197
- j++;
198
- const start = j;
199
- while (j < n && body.charAt(j) !== quote) j++;
200
- value = body.slice(start, j);
201
- j++;
202
- } else {
203
- const start = j;
204
- while (j < n && !isWs(body.charAt(j)) && body.charAt(j) !== ">") j++;
205
- value = body.slice(start, j);
206
- }
207
- i = j;
208
- }
209
- pairs.push([name.toLowerCase(), value]);
210
- }
211
- return pairs;
212
- }
213
- /** Filtra atributos: allowlist + validação de protocolo; força rel seguro. */
214
- function filterAttrs(tag, pairs) {
215
- const kept = [];
216
- const seen = /* @__PURE__ */ new Set();
217
- let targetBlank = false;
218
- for (const [name, raw] of pairs) {
219
- if (!ALLOWED_ATTRS.has(name) || seen.has(name)) continue;
220
- if (name === "href" && !isSafeUrl(raw, HREF_SCHEMES)) continue;
221
- if (name === "src" && !isSafeUrl(raw, SRC_SCHEMES)) continue;
222
- if (name === "target") {
223
- if (normalizeAttrValue(raw) !== "_blank") continue;
224
- targetBlank = true;
225
- continue;
226
- }
227
- if (name === "rel") continue;
228
- seen.add(name);
229
- kept.push(`${name}="${normalizeAttrValue(raw)}"`);
230
- }
231
- if (tag === "a" && targetBlank) {
232
- kept.push("target=\"_blank\"");
233
- kept.push("rel=\"noopener noreferrer\"");
234
- }
235
- return kept.length > 0 ? ` ${kept.join(" ")}` : "";
236
- }
237
- /**
238
- * Sanitiza uma string de HTML. Retorna apenas marcação da allowlist.
239
- * Idempotente e sem dependências de DOM (seguro no SSR e no cliente).
240
- */
241
- function sanitizeHtml(input) {
242
- if (typeof input !== "string" || input.length === 0) return "";
243
- const lower = input.toLowerCase();
244
- const n = input.length;
245
- const stack = [];
246
- let out = "";
247
- let i = 0;
248
- while (i < n) {
249
- const lt = input.indexOf("<", i);
250
- if (lt === -1) {
251
- out += escapeText(input.slice(i));
252
- break;
253
- }
254
- if (lt > i) out += escapeText(input.slice(i, lt));
255
- if (input.startsWith("<!--", lt)) {
256
- const end = input.indexOf("-->", lt + 4);
257
- i = end === -1 ? n : end + 3;
258
- continue;
259
- }
260
- if (input.charAt(lt + 1) === "!" || input.charAt(lt + 1) === "?") {
261
- const end = input.indexOf(">", lt + 2);
262
- i = end === -1 ? n : end + 1;
263
- continue;
264
- }
265
- const tagMatch = /^<(\/?)([a-zA-Z][a-zA-Z0-9]*)(?=[\s/>])/.exec(input.slice(lt, Math.min(lt + 64, n)));
266
- if (!tagMatch) {
267
- out += "&lt;";
268
- i = lt + 1;
269
- continue;
270
- }
271
- const isClosing = tagMatch[1] === "/";
272
- const tag = tagMatch[2].toLowerCase();
273
- let j = lt + tagMatch[0].length;
274
- let quote = "";
275
- while (j < n) {
276
- const ch = input[j];
277
- if (quote) {
278
- if (ch === quote) quote = "";
279
- } else if (ch === "\"" || ch === "'") quote = ch;
280
- else if (ch === ">") break;
281
- j++;
282
- }
283
- if (j >= n) break;
284
- const body = input.slice(lt + tagMatch[0].length, j);
285
- i = j + 1;
286
- if (!isClosing && RAW_TEXT_TAGS.has(tag)) {
287
- const closeAt = lower.indexOf(`</${tag}`, i);
288
- if (closeAt === -1) break;
289
- const closeEnd = input.indexOf(">", closeAt);
290
- i = closeEnd === -1 ? n : closeEnd + 1;
291
- continue;
292
- }
293
- if (isClosing) {
294
- const anchor = stack.lastIndexOf(tag);
295
- if (anchor !== -1) {
296
- for (let k = stack.length - 1; k >= anchor; k--) out += `</${stack[k]}>`;
297
- stack.length = anchor;
298
- }
299
- continue;
300
- }
301
- if (!ALLOWED_TAGS.has(tag)) continue;
302
- const attrs = filterAttrs(tag, parseAttrs(body));
303
- if (VOID_TAGS.has(tag)) out += `<${tag}${attrs} />`;
304
- else {
305
- out += `<${tag}${attrs}>`;
306
- stack.push(tag);
307
- }
308
- }
309
- for (let k = stack.length - 1; k >= 0; k--) out += `</${stack[k]}>`;
310
- return out;
311
- }
312
- //#endregion
313
- //#region src/components/content/ContentEditor.tsx
314
- var _tmpl$ = [
315
- "<div",
316
- " class=\"notice notice--success\">",
317
- "</div>"
318
- ];
319
- var _tmpl$2 = [
320
- "<input",
321
- " class=\"classic-editor__title\" required",
322
- ">"
323
- ];
324
- var _tmpl$3 = [
325
- "<div",
326
- " class=\"classic-editor__toolbar\" role=\"toolbar\"",
327
- "><select class=\"input\"",
328
- " value><option value>",
329
- "</option><option value=\"<h1>\">",
330
- "</option><option value=\"<h2>\">",
331
- "</option><option value=\"<h3>\">",
332
- "</option><option value=\"<h4>\">",
333
- "</option><option value=\"<blockquote>\">",
334
- "</option><option value=\"<pre>\">",
335
- "</option></select><span class=\"classic-editor__toolbar-divider\"></span><button type=\"button\"><strong>",
336
- "</strong></button><button type=\"button\"><em>",
337
- "</em></button><button type=\"button\"><u>",
338
- "</u></button><span class=\"classic-editor__toolbar-divider\"></span><button type=\"button\">",
339
- "</button><button type=\"button\">",
340
- "</button><button type=\"button\">",
341
- "</button></div>"
342
- ];
343
- var _tmpl$4 = [
344
- "<div",
345
- " class=\"classic-editor__body\" contenteditable=\"true\" data-classic-editor role=\"textbox\" aria-multiline=\"true\"",
346
- ">",
347
- "</div>"
348
- ];
349
- var _tmpl$5 = [
350
- "<div",
351
- " class=\"plugin-editor plugin-editor--below\"",
352
- ">",
353
- "</div>"
354
- ];
355
- var _tmpl$6 = [
356
- "<label",
357
- " class=\"classic-editor__excerpt\"><span>",
358
- "</span><textarea class=\"input\" rows=\"4\"",
359
- "></textarea></label>"
360
- ];
361
- var _tmpl$7 = [
362
- "<section",
363
- " class=\"card custom-fields\"><h3>",
364
- "</h3><!--$-->",
365
- "<!--/--></section>"
366
- ];
367
- var _tmpl$8 = [
368
- "<section",
369
- " class=\"card classic-editor__panel\"><h3>",
370
- "</h3><input class=\"input\"",
371
- "><p class=\"muted\">",
372
- "</p></section>"
373
- ];
374
- var _tmpl$9 = [
375
- "<section",
376
- " class=\"card classic-editor__panel\"><h3>",
377
- "</h3><label><!--$-->",
378
- "<!--/--><select class=\"input\"",
379
- "><option value>",
380
- "</option><!--$-->",
381
- "<!--/--></select></label></section>"
382
- ];
383
- var _tmpl$0 = [
384
- "<form",
385
- " class=\"content-editor classic-editor\"><!--$-->",
386
- "<!--/--><!--$-->",
387
- "<!--/--><div class=\"classic-editor__topbar\"><div><span class=\"classic-editor__eyebrow\">",
388
- "</span><h2>",
389
- "</h2></div><div class=\"classic-editor__actions\"><a class=\"btn btn-secondary\" href=\"",
390
- "\">",
391
- "</a><button type=\"submit\" class=\"btn btn-primary\"",
392
- ">",
393
- "</button></div></div><div class=\"classic-editor__columns\"><main class=\"classic-editor__main\"><section class=\"card classic-editor__canvas-card\"><!--$-->",
394
- "<!--/--><div class=\"classic-editor__permalink\"><span><!--$-->",
395
- "<!--/-->:</span><input class=\"input\"",
396
- "></div><!--$-->",
397
- "<!--/--><!--$-->",
398
- "<!--/--><!--$-->",
399
- "<!--/--></section><!--$-->",
400
- "<!--/--><!--$-->",
401
- "<!--/--></main><aside class=\"classic-editor__sidebar\"><section class=\"card classic-editor__panel\"><h3>",
402
- "</h3><label><!--$-->",
403
- "<!--/--><select class=\"input\"",
404
- "><option value=\"DRAFT\">",
405
- "</option><option value=\"PUBLISHED\">",
406
- "</option><option value=\"ARCHIVED\">",
407
- "</option></select></label><button type=\"submit\" class=\"btn btn-primary classic-editor__full-button\"",
408
- ">",
409
- "</button></section><!--$-->",
410
- "<!--/--><!--$-->",
411
- "<!--/--><!--$-->",
412
- "<!--/--></aside></div><!--$-->",
413
- "<!--/--></form>"
414
- ];
415
- var _tmpl$1 = [
416
- "<div",
417
- " class=\"notice notice--error\">",
418
- "</div>"
419
- ];
420
- var _tmpl$10 = [
421
- "<div",
422
- " class=\"plugin-editor\"",
423
- ">",
424
- "</div>"
425
- ];
426
- var _tmpl$11 = [
427
- "<option",
428
- ">",
429
- "</option>"
430
- ];
431
- /**
432
- * Normalizes content body: parses string (double-encoded) to object.
433
- * Ensures `content` key exists for classic editor (falls back to `html`).
434
- */
435
- function normalizeBody(value) {
436
- if (value !== null && typeof value === "object" && !Array.isArray(value)) {
437
- const body = value;
438
- if (body["content"] === void 0 && typeof body["html"] === "string") body["content"] = body["html"];
439
- return body;
440
- }
441
- if (typeof value === "string") try {
442
- const parsed = JSON.parse(value);
443
- if (parsed !== null && typeof parsed === "object" && !Array.isArray(parsed)) {
444
- const body = parsed;
445
- if (body["content"] === void 0 && typeof body["html"] === "string") body["content"] = body["html"];
446
- return body;
447
- }
448
- } catch {}
449
- return {};
450
- }
451
- function ContentEditor(props) {
452
- const { t } = useTranslation();
453
- const [types, setTypes] = createSignal([]);
454
- const [groups, setGroups] = createSignal([]);
455
- const [themes, setThemes] = createSignal([]);
456
- const [data, setData] = createSignal({});
457
- const [errors, setErrors] = createSignal([]);
458
- const [saving, setSaving] = createSignal(false);
459
- const [message, setMessage] = createSignal("");
460
- const [extensions, setExtensions] = createSignal(emptyExtensionsState());
461
- const [draft, setDraft] = createSignal({
462
- type: props.initialType || "post",
463
- title: "",
464
- status: "DRAFT"
465
- });
466
- const supports = () => new Set(types().find((type) => type.slug === draft().type)?.supports ?? ["title", "editor"]);
467
- const hasSupport = (support) => supports().has(support);
468
- const activeEditor = createMemo(() => {
469
- const screen = draft().type;
470
- return (extensions().editors ?? []).filter((editor) => editor.screens.includes("*") || editor.screens.includes(screen)).sort((a, b) => (a.priority ?? 0) - (b.priority ?? 0))[0] ?? null;
471
- });
472
- const editorSlotProps = () => ({
473
- editorId: activeEditor().id,
474
- contentType: draft().type,
475
- contentId: draft().id ?? "",
476
- body: editorContent(),
477
- setBody: (html) => setData({
478
- ...data(),
479
- content: html
480
- }),
481
- disabled: saving()
482
- });
483
- const typeListFallback = (available, requested) => requested || available[0]?.slug || "post";
484
- const availableLayouts = () => {
485
- const layouts = /* @__PURE__ */ new Set();
486
- for (const theme of themes()) for (const layout of theme.manifest?.provides?.layouts ?? []) layouts.add(layout);
487
- return [...layouts].sort();
488
- };
489
- const loadGroups = async (context) => {
490
- try {
491
- const query = typeof context === "string" ? { type: context } : context;
492
- const all = await apiClient.getFieldGroups(query.type ? query : void 0);
493
- const resolved = await Promise.all(all.filter((group) => group.active).map(async (group) => {
494
- return (await apiClient.getFieldGroup(group.id)).fields ?? [];
495
- }));
496
- setGroups(expandCloneFields(resolved.flat()));
497
- } catch (err) {
498
- setErrors([err instanceof Error ? err.message : String(err)]);
499
- }
500
- };
501
- onMount(async () => {
502
- loadExtensions().then(setExtensions);
503
- let typeList = [];
504
- try {
505
- const [typeCatalog, themeList] = await Promise.all([apiClient.getContentTypes(), apiClient.getThemes().catch(() => [])]);
506
- typeList = typeCatalog;
507
- setTypes(typeCatalog);
508
- setThemes(themeList);
509
- } catch (err) {
510
- setErrors([err instanceof Error ? err.message : String(err)]);
511
- }
512
- const editId = new URLSearchParams(window.location.search).get("id");
513
- if (editId || props.singleton) try {
514
- const existing = editId ? await apiClient.getContentById(editId) : await apiClient.getSingletonContent(draft().type);
515
- if (!existing) {
516
- await loadGroups({
517
- type: draft().type,
518
- status: draft().status
519
- });
520
- return;
521
- }
522
- const rawRow = existing;
523
- setDraft({
524
- id: existing.id,
525
- type: existing.type,
526
- title: existing.title,
527
- slug: existing.slug,
528
- excerpt: existing.excerpt,
529
- featuredImageId: rawRow["featuredImageId"] ?? rawRow["featured_image_id"],
530
- status: existing.status,
531
- layout: existing.layout
532
- });
533
- setData(normalizeBody(existing.body));
534
- } catch (err) {
535
- setErrors([err instanceof Error ? err.message : String(err)]);
536
- }
537
- else if (!typeList.some((type) => type.slug === draft().type)) setDraft({
538
- ...draft(),
539
- type: typeListFallback(typeList, props.initialType)
540
- });
541
- await loadGroups({
542
- type: draft().type,
543
- slug: draft().slug,
544
- status: draft().status
545
- });
546
- });
547
- const editorContent = () => {
548
- const value = data()["content"];
549
- return typeof value === "string" ? value : "";
550
- };
551
- return ssr(_tmpl$0, ssrHydrationKey(), escape(createComponent(Show, {
552
- get when() {
553
- return errors().length > 0;
554
- },
555
- get children() {
556
- return createComponent(For, {
557
- get each() {
558
- return errors();
559
- },
560
- children: (err) => ssr(_tmpl$1, ssrHydrationKey(), escape(err))
561
- });
562
- }
563
- })), escape(createComponent(Show, {
564
- get when() {
565
- return message();
566
- },
567
- get children() {
568
- return ssr(_tmpl$, ssrHydrationKey(), escape(message()));
569
- }
570
- })), escape(types().find((type) => type.slug === draft().type)?.singularLabel || draft().type), draft().id ? escape(t("content.editor.editing")) : escape(t("content.editor.adding")), `/content/${escape(encodeURIComponent(draft().type), true)}`, escape(t("content.editor.backToList")), ssrAttribute("disabled", saving(), true), saving() ? escape(t("content.editor.saving")) : escape(t("content.editor.save")), escape(createComponent(Show, {
571
- get when() {
572
- return hasSupport("title");
573
- },
574
- get children() {
575
- return ssr(_tmpl$2, ssrHydrationKey(), ssrAttribute("aria-label", escape(t("content.editor.title"), true), false) + ssrAttribute("placeholder", escape(t("content.editor.titlePlaceholder"), true), false) + ssrAttribute("value", escape(draft().title, true), false));
576
- }
577
- })), escape(t("content.editor.slug")), ssrAttribute("value", escape(draft().slug ?? "", true), false) + ssrAttribute("placeholder", escape(t("content.editor.slugPlaceholder"), true), false), escape(createComponent(Show, {
578
- get when() {
579
- return hasSupport("editor");
580
- },
581
- get children() {
582
- return createComponent(Show, {
583
- get when() {
584
- return activeEditor()?.mode !== "replace-body";
585
- },
586
- get fallback() {
587
- return ssr(_tmpl$10, ssrHydrationKey(), ssrAttribute("data-plugin-editor", escape(activeEditor().id, true), false), escape(createComponent(PluginComponentHost, {
588
- get componentId() {
589
- return activeEditor().componentId;
590
- },
591
- get extraProps() {
592
- return editorSlotProps();
593
- }
594
- })));
595
- },
596
- get children() {
597
- return [ssr(_tmpl$3, ssrHydrationKey(), ssrAttribute("aria-label", escape(t("content.editor.toolbar"), true), false), ssrAttribute("aria-label", escape(t("content.editor.format"), true), false), escape(t("content.editor.formatParagraph")), escape(t("content.editor.formatH1")), escape(t("content.editor.formatH2")), escape(t("content.editor.formatH3")), escape(t("content.editor.formatH4")), escape(t("content.editor.formatBlockquote")), escape(t("content.editor.formatCode")), escape(t("content.editor.bold")), escape(t("content.editor.italic")), escape(t("content.editor.underline")), escape(t("content.editor.bulletList")), escape(t("content.editor.numberedList")), escape(t("content.editor.link"))), ssr(_tmpl$4, ssrHydrationKey(), ssrAttribute("data-placeholder", escape(t("content.editor.bodyPlaceholder"), true), false), sanitizeHtml(editorContent()))];
598
- }
599
- });
600
- }
601
- })), escape(createComponent(Show, {
602
- get when() {
603
- return activeEditor()?.mode === "below";
604
- },
605
- get children() {
606
- return ssr(_tmpl$5, ssrHydrationKey(), ssrAttribute("data-plugin-editor", escape(activeEditor().id, true), false), escape(createComponent(PluginComponentHost, {
607
- get componentId() {
608
- return activeEditor().componentId;
609
- },
610
- get extraProps() {
611
- return editorSlotProps();
612
- }
613
- })));
614
- }
615
- })), escape(createComponent(Show, {
616
- get when() {
617
- return hasSupport("excerpt");
618
- },
619
- get children() {
620
- return ssr(_tmpl$6, ssrHydrationKey(), escape(t("content.editor.excerpt")), ssrAttribute("value", escape(draft().excerpt ?? "", true), false));
621
- }
622
- })), escape(createComponent(Show, {
623
- get when() {
624
- return groups().length > 0;
625
- },
626
- get children() {
627
- return ssr(_tmpl$7, ssrHydrationKey(), escape(t("content.editor.customFields")), escape(createComponent(For, {
628
- get each() {
629
- return groups();
630
- },
631
- children: (field) => createComponent(FieldRenderer, {
632
- field,
633
- get values() {
634
- return data();
635
- },
636
- onChange: (name, value) => setData({
637
- ...data(),
638
- [name]: value
639
- }),
640
- t
641
- })
642
- })));
643
- }
644
- })), escape(createComponent(MetaBoxesSlot, {
645
- get extensions() {
646
- return extensions();
647
- },
648
- get screen() {
649
- return draft().type;
650
- },
651
- context: "normal"
652
- })), escape(t("content.editor.publishPanel")), escape(t("content.editor.status")), ssrAttribute("value", escape(draft().status, true), false), escape(t("content.editor.statusOptions.draft")), escape(t("content.editor.statusOptions.published")), escape(t("content.editor.statusOptions.archived")), ssrAttribute("disabled", saving(), true), saving() ? escape(t("content.editor.saving")) : escape(t("content.editor.save")), escape(createComponent(Show, {
653
- get when() {
654
- return hasSupport("thumbnail");
655
- },
656
- get children() {
657
- return ssr(_tmpl$8, ssrHydrationKey(), escape(t("content.editor.featuredImage")), ssrAttribute("value", escape(draft().featuredImageId ?? "", true), false) + ssrAttribute("placeholder", escape(t("content.editor.mediaIdPlaceholder"), true), false), escape(t("content.editor.featuredImageHint")));
658
- }
659
- })), escape(createComponent(Show, {
660
- get when() {
661
- return availableLayouts().length > 0;
662
- },
663
- get children() {
664
- return ssr(_tmpl$9, ssrHydrationKey(), escape(t("content.editor.pageAttributes")), escape(t("content.editor.layout")), ssrAttribute("value", escape(draft().layout ?? "", true), false), escape(t("content.editor.layoutAuto")), escape(createComponent(For, {
665
- get each() {
666
- return availableLayouts();
667
- },
668
- children: (layout) => ssr(_tmpl$11, ssrHydrationKey() + ssrAttribute("value", escape(layout, true), false), escape(layout))
669
- })));
670
- }
671
- })), escape(createComponent(MetaBoxesSlot, {
672
- get extensions() {
673
- return extensions();
674
- },
675
- get screen() {
676
- return draft().type;
677
- },
678
- context: "side"
679
- })), escape(createComponent(MetaBoxesSlot, {
680
- get extensions() {
681
- return extensions();
682
- },
683
- get screen() {
684
- return draft().type;
685
- },
686
- context: "advanced"
687
- })));
688
- }
689
- //#endregion
690
- export { ContentEditor as t };