@oktis-works/admin 0.4.17 → 0.4.19

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 (106) hide show
  1. package/dist/client/_astro/{ActivityWidget.BoV5JMFM.js → ActivityWidget.DGLCPDgH.js} +2 -2
  2. package/dist/client/_astro/{AdminBar.Bzzeux86.js → AdminBar.Cj9iKizr.js} +2 -2
  3. package/dist/client/_astro/{AtGlanceWidget.BIHmD0Mp.js → AtGlanceWidget.B1bDhxvN.js} +2 -2
  4. package/dist/client/_astro/{BaseLayout.B3A9-IS6.css → BaseLayout.Y8xW22CP.css} +1 -1
  5. package/dist/client/_astro/ContentEditor.SP4PO6Pb.js +3 -0
  6. package/dist/client/_astro/ContentList.o2zVu57t.js +1 -0
  7. package/dist/client/_astro/CustomFieldsManager.CvWD3R1q.js +3 -0
  8. package/dist/client/_astro/DashboardHome.DnCbpnkg.js +1 -0
  9. package/dist/client/_astro/DashboardLayout.BOoRKX4v.css +1 -0
  10. package/dist/client/_astro/DashboardLayout.astro_astro_type_script_index_0_lang.7Kcbf7KO.js +1 -0
  11. package/dist/client/_astro/FieldTypePicker.Cyfzqug-.js +1 -0
  12. package/dist/client/_astro/{Footer.LI6Cpgg_.js → Footer.BqzSGnHm.js} +1 -1
  13. package/dist/client/_astro/GeneralSettings.Ditcyy4b.js +1 -0
  14. package/dist/client/_astro/MediaLibrary.qzwN-LI5.js +1 -0
  15. package/dist/client/_astro/{PluginManager.BYI4SRec.js → PluginManager.DEkeX_0Z.js} +2 -2
  16. package/dist/client/_astro/PostTypesManager.CGYbeXgb.js +1 -0
  17. package/dist/client/_astro/{QuickDraftWidget.Cjm5_7y-.js → QuickDraftWidget.xoJjOM58.js} +2 -2
  18. package/dist/client/_astro/ResourceHubs.BHlRlPvI.js +1 -0
  19. package/dist/client/_astro/TaxonomiesManager.DKQAGS8n.js +1 -0
  20. package/dist/client/_astro/TaxonomyTermsManager.CyB7XH-D.js +1 -0
  21. package/dist/client/_astro/{ThemeManager.Hw1k4IW5.js → ThemeManager.BBKCx5pa.js} +2 -2
  22. package/dist/client/_astro/UserCreateForm.BDsHkQYW.js +1 -0
  23. package/dist/client/_astro/UsersManager.DeQ4uL3a.js +1 -0
  24. package/dist/client/_astro/{ar.DsV0P0EN.js → ar.CwC9hXB9.js} +1 -1
  25. package/dist/client/_astro/client.W0NY0lEa.js +1 -0
  26. package/dist/client/_astro/{es-ES.etPSaiLd.js → es-ES.qNcd-cVX.js} +1 -1
  27. package/dist/client/_astro/extensions.DLE6XtMB.js +1 -0
  28. package/dist/client/_astro/{he.U1Vtp3zT.js → he.DfZ0ZzM-.js} +1 -1
  29. package/dist/client/_astro/i18n.JWFhLjfn.js +1 -0
  30. package/dist/client/_astro/{it.DJuI8oO_.js → it.PFmLQj2s.js} +1 -1
  31. package/dist/client/_astro/{ja.Cw8I_NUV.js → ja.CMi5cD8g.js} +1 -1
  32. package/dist/client/_astro/{pl.Dsz-4G_z.js → pl.CRExzLlj.js} +1 -1
  33. package/dist/client/_astro/pt-BR.CGjPpous.js +1 -0
  34. package/dist/client/_astro/{ru.CwIIcTdy.js → ru.CWV-tkZ3.js} +1 -1
  35. package/dist/client/_astro/solid.DN8T1HsY.js +1 -0
  36. package/dist/client/_astro/src.lFTwiz1W.js +1 -0
  37. package/dist/client/_astro/{sw.DwpL3sb6.js → sw.B5x6GU4s.js} +1 -1
  38. package/dist/client/_astro/{tr.CY2JWJ7Y.js → tr.BzxCGQu8.js} +1 -1
  39. package/dist/client/_astro/{uk.BudEWIU8.js → uk.DJHMwNRU.js} +1 -1
  40. package/dist/client/_astro/{version.B9EoEAbb.js → version.Cwfv80ER.js} +1 -1
  41. package/dist/client/_astro/web.Bze9SKEA.js +1 -0
  42. package/dist/client/_astro/{yo.BmoZs0fO.js → yo.DNw_hOnW.js} +1 -1
  43. package/dist/client/_astro/{zh-CN.khaXV6fv.js → zh-CN.Bs7H6Unx.js} +1 -1
  44. package/dist/server/chunks/{ContentEditor_B_alLPkZ.mjs → ContentEditor_CxZJjeXR.mjs} +423 -87
  45. package/dist/server/chunks/{DashboardLayout_B1lpShsT.mjs → DashboardLayout_DCIiRkcO.mjs} +13 -12
  46. package/dist/server/chunks/{MediaLibrary_B_mkxyGz.mjs → MediaLibrary_azhfNs4N.mjs} +2 -2
  47. package/dist/server/chunks/{ResourceHubs_SnzUKv2d.mjs → ResourceHubs_BJMX1AJR.mjs} +1 -1
  48. package/dist/server/chunks/{_slug__DK1dX6Cc.mjs → _slug__BEfbBGa_.mjs} +1 -1
  49. package/dist/server/chunks/{access_BXua9HeF.mjs → access_DNxcWCO1.mjs} +2 -2
  50. package/dist/server/chunks/{ar_DMC8HaoP.mjs → ar_B0LfQbpu.mjs} +1 -1
  51. package/dist/server/chunks/{custom-fields_DZxzXn_Y.mjs → custom-fields_DI9f2Pqi.mjs} +2 -2
  52. package/dist/server/chunks/{edit_DMCL0nv5.mjs → edit_3GtD2cva.mjs} +4 -2
  53. package/dist/server/chunks/{es-ES_DZvHskAD.mjs → es-ES_dBEm2FNw.mjs} +1 -1
  54. package/dist/server/chunks/{general_DY6nfeME.mjs → general_CbiPNS7I.mjs} +2 -2
  55. package/dist/server/chunks/{he_zy3stNhR.mjs → he_DRWoI1A5.mjs} +1 -1
  56. package/dist/server/chunks/{i18n_BZdCNETS.mjs → i18n_DIBvEjfq.mjs} +54 -16
  57. package/dist/server/chunks/{index_D0YtPHrm.mjs → index_BZJqnzEO.mjs} +34 -31
  58. package/dist/server/chunks/{index_Bn9LjtxA.mjs → index_BcV8TVEC.mjs} +2 -2
  59. package/dist/server/chunks/{index_BAVyaaWE.mjs → index_C3amWOJX.mjs} +1 -1
  60. package/dist/server/chunks/{index_BZU6TG9K.mjs → index_CTJw_OsD.mjs} +2 -2
  61. package/dist/server/chunks/{index_eIvtdujt.mjs → index_kTsjYnf7.mjs} +2 -2
  62. package/dist/server/chunks/{it_BiUDLszZ.mjs → it_BDY3lerP.mjs} +1 -1
  63. package/dist/server/chunks/{ja_DjFAG7hL.mjs → ja_C-EybQiV.mjs} +1 -1
  64. package/dist/server/chunks/{login_xmDNRy6-.mjs → login_D-Z6bo6E.mjs} +1 -1
  65. package/dist/server/chunks/{new_vDml0n9D.mjs → new_Dg9ykZGm.mjs} +4 -2
  66. package/dist/server/chunks/{new_DjeZ5fm2.mjs → new_uLMmBd95.mjs} +2 -2
  67. package/dist/server/chunks/{operations_wkXdEoy9.mjs → operations_vnv5cnws.mjs} +2 -2
  68. package/dist/server/chunks/{pl_0Xe9Qom2.mjs → pl_DH5LKmVG.mjs} +1 -1
  69. package/dist/server/chunks/{plugins_BwmcMrFa.mjs → plugins_pNXwbZGI.mjs} +2 -2
  70. package/dist/server/chunks/{post-types_Di0TnpMF.mjs → post-types_g7oMw8xZ.mjs} +2 -2
  71. package/dist/server/chunks/{pt-BR_DIZpU2Mk.mjs → pt-BR_BM0FS26r.mjs} +32 -1
  72. package/dist/server/chunks/{resources_BZh_dXsF.mjs → resources_DhbyXd_o.mjs} +2 -2
  73. package/dist/server/chunks/{ru_DFvIxd0Y.mjs → ru_CFa1xYFr.mjs} +1 -1
  74. package/dist/server/chunks/{sw_CmaPgGYa.mjs → sw_QZf7NSsI.mjs} +1 -1
  75. package/dist/server/chunks/{taxonomies_CuEyvskw.mjs → taxonomies_CX8h73Lt.mjs} +2 -2
  76. package/dist/server/chunks/taxonomy_D8om_RNg.mjs +152 -0
  77. package/dist/server/chunks/{themes_DZ9w9ECK.mjs → themes_JX5WVf2J.mjs} +2 -2
  78. package/dist/server/chunks/{tr_B_acwl2e.mjs → tr_Fjry5R-K.mjs} +1 -1
  79. package/dist/server/chunks/{uk_DXnk4imL.mjs → uk_Bxc3qY45.mjs} +1 -1
  80. package/dist/server/chunks/{upload_Bp9adHy4.mjs → upload_r2qJskLo.mjs} +2 -2
  81. package/dist/server/chunks/{yo_DDQ8a-0v.mjs → yo_BARL-Qrh.mjs} +1 -1
  82. package/dist/server/chunks/{zh-CN_763uzTMQ.mjs → zh-CN_CkjPJL88.mjs} +1 -1
  83. package/dist/server/entry.mjs +70 -39
  84. package/dist/server/virtual_astro_middleware.mjs +1 -1
  85. package/package.json +1 -1
  86. package/dist/client/_astro/ContentEditor.Bdh3rpdn.js +0 -1
  87. package/dist/client/_astro/ContentList.D1XcWg2t.js +0 -1
  88. package/dist/client/_astro/CustomFieldsManager.6c3e_83f.js +0 -3
  89. package/dist/client/_astro/DashboardHome.C0c91P5X.js +0 -1
  90. package/dist/client/_astro/DashboardLayout.CEvRGr78.css +0 -1
  91. package/dist/client/_astro/DashboardLayout.astro_astro_type_script_index_0_lang.CMtAy9r3.js +0 -1
  92. package/dist/client/_astro/FieldTypePicker.BEuYPzV8.js +0 -1
  93. package/dist/client/_astro/GeneralSettings.BFAXjOA2.js +0 -1
  94. package/dist/client/_astro/MediaLibrary.BvtJOo5A.js +0 -1
  95. package/dist/client/_astro/PostTypesManager.bQc6yww5.js +0 -1
  96. package/dist/client/_astro/ResourceHubs.MrbWi-Z_.js +0 -1
  97. package/dist/client/_astro/TaxonomiesManager.kwogAOFS.js +0 -1
  98. package/dist/client/_astro/UserCreateForm.CHb7uDCX.js +0 -1
  99. package/dist/client/_astro/UsersManager.Btde4I0r.js +0 -1
  100. package/dist/client/_astro/client.BY0Z100j.js +0 -1
  101. package/dist/client/_astro/extensions.Y_1XaoRs.js +0 -1
  102. package/dist/client/_astro/i18n.RrM42yx5.js +0 -1
  103. package/dist/client/_astro/pt-BR.CyQAHnXs.js +0 -1
  104. package/dist/client/_astro/src.B10HDgSa.js +0 -1
  105. package/dist/client/_astro/web.D_vCtCLj.js +0 -1
  106. /package/dist/server/chunks/{BaseLayout_D1PbsjNG.mjs → BaseLayout_m8b8Eemd.mjs} +0 -0
@@ -1,5 +1,5 @@
1
- import { n as useTranslation, r as apiClient } from "./i18n_BZdCNETS.mjs";
2
- import { a as For2, d as createMemo$1, f as createSignal$1, l as Show2 } from "./DashboardLayout_B1lpShsT.mjs";
1
+ import { n as useTranslation, r as apiClient } from "./i18n_DIBvEjfq.mjs";
2
+ import { a as For2, d as createMemo$1, f as createSignal$1, l as Show2 } from "./DashboardLayout_DCIiRkcO.mjs";
3
3
  import { t as FieldTypePicker } from "./FieldTypePicker_CXwpmcQ3.mjs";
4
4
  import { createComponent, escape, memo, ssr, ssrAttribute, ssrHydrationKey } from "solid-js/web";
5
5
  import { For, Show, createMemo, createSignal, onMount } from "solid-js";
@@ -512,6 +512,312 @@ function expandCloneFields(fields) {
512
512
  return result;
513
513
  }
514
514
  //#endregion
515
+ //#region src/lib/sanitize.ts
516
+ /**
517
+ * Sanitizador de HTML em allowlist para pontos de injeção (innerHTML).
518
+ *
519
+ * O admin injeta HTML apenas no conteúdo das abas de ajuda (HelpTabs), que
520
+ * vem do i18n — mas todo innerHTML passa por aqui por defesa em profundidade.
521
+ *
522
+ * Garantias:
523
+ * - Allowlist de tags e atributos (script/style/svg/iframe/form são removidos,
524
+ * incluindo o conteúdo de tags de texto bruto como <script> e <style>).
525
+ * - Atributos de evento (on*), style e demais fora da allowlist são descartados.
526
+ * - href/src têm o protocolo validado DEPOIS de decodificar entidades e remover
527
+ * tab/newline — o valor emitido é re-escapado a partir do valor decodificado,
528
+ * de modo que o que o navegador decodifica é exatamente o que foi validado
529
+ * (bloqueia `javascript:`, `&#106;avascript:`, `javascript&colon;`, etc).
530
+ * - Texto é escapado (& < >), preservando entidades já válidas.
531
+ * - Tags de fechamento sem âncora são ignoradas: conteúdo malicioso não consegue
532
+ * "escapar" do container nem desbalancear a árvore (o quebra-cabeça de abas
533
+ * e widgets continua íntegro).
534
+ *
535
+ * Puro JavaScript, sem APIs de DOM: roda igual no SSR (Node) e no navegador.
536
+ */
537
+ /** Tags permitidas (conteúdo rico simples: ajuda, títulos, listas, links). */
538
+ var ALLOWED_TAGS = /* @__PURE__ */ new Set([
539
+ "a",
540
+ "abbr",
541
+ "b",
542
+ "blockquote",
543
+ "br",
544
+ "code",
545
+ "dd",
546
+ "div",
547
+ "dl",
548
+ "dt",
549
+ "em",
550
+ "figcaption",
551
+ "figure",
552
+ "h1",
553
+ "h2",
554
+ "h3",
555
+ "h4",
556
+ "h5",
557
+ "h6",
558
+ "hr",
559
+ "i",
560
+ "img",
561
+ "li",
562
+ "ol",
563
+ "p",
564
+ "pre",
565
+ "q",
566
+ "s",
567
+ "span",
568
+ "strong",
569
+ "sub",
570
+ "sup",
571
+ "u",
572
+ "ul"
573
+ ]);
574
+ /** Tags vazias (emitidas com fechamento próprio, nunca empilhadas). */
575
+ var VOID_TAGS = /* @__PURE__ */ new Set([
576
+ "br",
577
+ "hr",
578
+ "img"
579
+ ]);
580
+ /**
581
+ * Tags cujo conteúdo é texto bruto no HTML. Ao encontrá-las abertas, todo o
582
+ * miolo é descartado até o fechamento correspondente (senão, o conteúdo do
583
+ * <script> viraria texto visível ou vetor de parse).
584
+ */
585
+ var RAW_TEXT_TAGS = /* @__PURE__ */ new Set([
586
+ "script",
587
+ "style",
588
+ "iframe",
589
+ "object",
590
+ "embed",
591
+ "svg",
592
+ "math",
593
+ "textarea",
594
+ "title",
595
+ "noscript",
596
+ "template"
597
+ ]);
598
+ /** Atributos permitidos (globais; validação extra por atributo abaixo). */
599
+ var ALLOWED_ATTRS = /* @__PURE__ */ new Set([
600
+ "class",
601
+ "title",
602
+ "alt",
603
+ "width",
604
+ "height",
605
+ "href",
606
+ "src",
607
+ "target",
608
+ "rel"
609
+ ]);
610
+ /** Esquemas aceitos em href (links externos, e-mail, telefone). */
611
+ var HREF_SCHEMES = /* @__PURE__ */ new Set([
612
+ "http",
613
+ "https",
614
+ "mailto",
615
+ "tel"
616
+ ]);
617
+ /** Esquemas aceitos em src (somente rede). */
618
+ var SRC_SCHEMES = /* @__PURE__ */ new Set(["http", "https"]);
619
+ /** Entidades nomeadas relevantes (as que poderiam alterar a validação de URL). */
620
+ var NAMED_ENTITIES = {
621
+ amp: "&",
622
+ lt: "<",
623
+ gt: ">",
624
+ quot: "\"",
625
+ apos: "'",
626
+ colon: ":",
627
+ tab: " ",
628
+ newline: "\n",
629
+ sol: "/",
630
+ lpar: "(",
631
+ rpar: ")",
632
+ num: "#",
633
+ period: ".",
634
+ excl: "!",
635
+ comma: ","
636
+ };
637
+ /** Decodifica referências numéricas e nomeadas (uma passada, como o navegador). */
638
+ function decodeEntities(value) {
639
+ 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) => {
640
+ return NAMED_ENTITIES[name in NAMED_ENTITIES ? name : name.toLowerCase()] ?? m;
641
+ });
642
+ }
643
+ function fromCodePoint(cp) {
644
+ if (!Number.isFinite(cp) || cp < 0 || cp > 1114111) return "";
645
+ try {
646
+ return String.fromCodePoint(cp);
647
+ } catch {
648
+ return "";
649
+ }
650
+ }
651
+ /** Escapa valor para uso dentro de atributo entre aspas duplas. */
652
+ function escapeAttr(value) {
653
+ return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
654
+ }
655
+ /**
656
+ * Escapa texto preservando entidades já válidas (evita exibir `&amp;`
657
+ * literalmente quando a tradução usa `&amp;` de propósito).
658
+ */
659
+ function escapeText(text) {
660
+ 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;");
661
+ }
662
+ /**
663
+ * Valida URL decodificando entidades e removendo tab/newline (mesmo tratamento
664
+ * do parser de URL do navegador) antes de inspecionar o esquema.
665
+ */
666
+ function isSafeUrl(raw, allowedSchemes) {
667
+ const decoded = decodeEntities(raw).replace(/[\t\n\r]/g, "").trim();
668
+ const scheme = /^([a-zA-Z][a-zA-Z0-9+.-]*):/.exec(decoded);
669
+ if (!scheme) return true;
670
+ return allowedSchemes.has(scheme[1].toLowerCase());
671
+ }
672
+ /** Normaliza valor de atributo: decodifica (como o navegador faria) e re-escapa. */
673
+ function normalizeAttrValue(raw) {
674
+ return escapeAttr(decodeEntities(raw));
675
+ }
676
+ /**
677
+ * Extrai pares nome/valor de uma tag, respeitando aspas (um `>` dentro de
678
+ * aspas não termina a tag) e valores não-aspados do HTML.
679
+ */
680
+ function parseAttrs(body) {
681
+ const pairs = [];
682
+ const n = body.length;
683
+ let i = 0;
684
+ const isWs = (c) => c === " " || c === " " || c === "\n" || c === "\r" || c === "\f";
685
+ while (i < n) {
686
+ while (i < n && (isWs(body.charAt(i)) || body.charAt(i) === "/")) i++;
687
+ if (i >= n) break;
688
+ let name = "";
689
+ while (i < n && !isWs(body.charAt(i)) && body.charAt(i) !== "=" && body.charAt(i) !== ">" && body.charAt(i) !== "/" && body.charAt(i) !== "<") {
690
+ name += body.charAt(i);
691
+ i++;
692
+ }
693
+ if (!name) {
694
+ i++;
695
+ continue;
696
+ }
697
+ let value = "";
698
+ let j = i;
699
+ while (j < n && isWs(body.charAt(j))) j++;
700
+ if (j < n && body.charAt(j) === "=") {
701
+ j++;
702
+ while (j < n && isWs(body.charAt(j))) j++;
703
+ if (j < n && (body.charAt(j) === "\"" || body.charAt(j) === "'")) {
704
+ const quote = body.charAt(j);
705
+ j++;
706
+ const start = j;
707
+ while (j < n && body.charAt(j) !== quote) j++;
708
+ value = body.slice(start, j);
709
+ j++;
710
+ } else {
711
+ const start = j;
712
+ while (j < n && !isWs(body.charAt(j)) && body.charAt(j) !== ">") j++;
713
+ value = body.slice(start, j);
714
+ }
715
+ i = j;
716
+ }
717
+ pairs.push([name.toLowerCase(), value]);
718
+ }
719
+ return pairs;
720
+ }
721
+ /** Filtra atributos: allowlist + validação de protocolo; força rel seguro. */
722
+ function filterAttrs(tag, pairs) {
723
+ const kept = [];
724
+ const seen = /* @__PURE__ */ new Set();
725
+ let targetBlank = false;
726
+ for (const [name, raw] of pairs) {
727
+ if (!ALLOWED_ATTRS.has(name) || seen.has(name)) continue;
728
+ if (name === "href" && !isSafeUrl(raw, HREF_SCHEMES)) continue;
729
+ if (name === "src" && !isSafeUrl(raw, SRC_SCHEMES)) continue;
730
+ if (name === "target") {
731
+ if (normalizeAttrValue(raw) !== "_blank") continue;
732
+ targetBlank = true;
733
+ continue;
734
+ }
735
+ if (name === "rel") continue;
736
+ seen.add(name);
737
+ kept.push(`${name}="${normalizeAttrValue(raw)}"`);
738
+ }
739
+ if (tag === "a" && targetBlank) {
740
+ kept.push("target=\"_blank\"");
741
+ kept.push("rel=\"noopener noreferrer\"");
742
+ }
743
+ return kept.length > 0 ? ` ${kept.join(" ")}` : "";
744
+ }
745
+ /**
746
+ * Sanitiza uma string de HTML. Retorna apenas marcação da allowlist.
747
+ * Idempotente e sem dependências de DOM (seguro no SSR e no cliente).
748
+ */
749
+ function sanitizeHtml(input) {
750
+ if (typeof input !== "string" || input.length === 0) return "";
751
+ const lower = input.toLowerCase();
752
+ const n = input.length;
753
+ const stack = [];
754
+ let out = "";
755
+ let i = 0;
756
+ while (i < n) {
757
+ const lt = input.indexOf("<", i);
758
+ if (lt === -1) {
759
+ out += escapeText(input.slice(i));
760
+ break;
761
+ }
762
+ if (lt > i) out += escapeText(input.slice(i, lt));
763
+ if (input.startsWith("<!--", lt)) {
764
+ const end = input.indexOf("-->", lt + 4);
765
+ i = end === -1 ? n : end + 3;
766
+ continue;
767
+ }
768
+ if (input.charAt(lt + 1) === "!" || input.charAt(lt + 1) === "?") {
769
+ const end = input.indexOf(">", lt + 2);
770
+ i = end === -1 ? n : end + 1;
771
+ continue;
772
+ }
773
+ const tagMatch = /^<(\/?)([a-zA-Z][a-zA-Z0-9]*)(?=[\s/>])/.exec(input.slice(lt, Math.min(lt + 64, n)));
774
+ if (!tagMatch) {
775
+ out += "&lt;";
776
+ i = lt + 1;
777
+ continue;
778
+ }
779
+ const isClosing = tagMatch[1] === "/";
780
+ const tag = tagMatch[2].toLowerCase();
781
+ let j = lt + tagMatch[0].length;
782
+ let quote = "";
783
+ while (j < n) {
784
+ const ch = input[j];
785
+ if (quote) {
786
+ if (ch === quote) quote = "";
787
+ } else if (ch === "\"" || ch === "'") quote = ch;
788
+ else if (ch === ">") break;
789
+ j++;
790
+ }
791
+ if (j >= n) break;
792
+ const body = input.slice(lt + tagMatch[0].length, j);
793
+ i = j + 1;
794
+ if (!isClosing && RAW_TEXT_TAGS.has(tag)) {
795
+ const closeAt = lower.indexOf(`</${tag}`, i);
796
+ if (closeAt === -1) break;
797
+ const closeEnd = input.indexOf(">", closeAt);
798
+ i = closeEnd === -1 ? n : closeEnd + 1;
799
+ continue;
800
+ }
801
+ if (isClosing) {
802
+ const anchor = stack.lastIndexOf(tag);
803
+ if (anchor !== -1) {
804
+ for (let k = stack.length - 1; k >= anchor; k--) out += `</${stack[k]}>`;
805
+ stack.length = anchor;
806
+ }
807
+ continue;
808
+ }
809
+ if (!ALLOWED_TAGS.has(tag)) continue;
810
+ const attrs = filterAttrs(tag, parseAttrs(body));
811
+ if (VOID_TAGS.has(tag)) out += `<${tag}${attrs} />`;
812
+ else {
813
+ out += `<${tag}${attrs}>`;
814
+ stack.push(tag);
815
+ }
816
+ }
817
+ for (let k = stack.length - 1; k >= 0; k--) out += `</${stack[k]}>`;
818
+ return out;
819
+ }
820
+ //#endregion
515
821
  //#region src/components/content/RelationshipPicker.tsx
516
822
  var _tmpl$$2 = [
517
823
  "<ul",
@@ -636,8 +942,8 @@ var _tmpl$8$1 = [
636
942
  ">"
637
943
  ];
638
944
  var _tmpl$9$1 = ["<input", " type=\"email\" class=\"input\">"];
639
- var _tmpl$0 = ["<input", " type=\"url\" class=\"input\" placeholder=\"https://\">"];
640
- var _tmpl$1 = ["<input", " type=\"password\" class=\"input\">"];
945
+ var _tmpl$0$1 = ["<input", " type=\"url\" class=\"input\" placeholder=\"https://\">"];
946
+ var _tmpl$1$1 = ["<input", " type=\"password\" class=\"input\">"];
641
947
  var _tmpl$10 = [
642
948
  "<input",
643
949
  " type=\"checkbox\"",
@@ -833,8 +1139,8 @@ function FieldControl(props) {
833
1139
  case "number":
834
1140
  case "range": return ssr(_tmpl$8$1, ssrHydrationKey(), ssrAttribute("min", escape(config()["minValue"], true), false) + ssrAttribute("max", escape(config()["maxValue"], true), false) + ssrAttribute("step", escape(config()["step"], true), false));
835
1141
  case "email": return ssr(_tmpl$9$1, ssrHydrationKey());
836
- case "url": return ssr(_tmpl$0, ssrHydrationKey());
837
- case "password": return ssr(_tmpl$1, ssrHydrationKey());
1142
+ case "url": return ssr(_tmpl$0$1, ssrHydrationKey());
1143
+ case "password": return ssr(_tmpl$1$1, ssrHydrationKey());
838
1144
  case "true_false": return ssr(_tmpl$10, ssrHydrationKey(), ssrAttribute("checked", Boolean(props.value), true));
839
1145
  case "select": return ssr(_tmpl$11, ssrHydrationKey(), ssrAttribute("multiple", config()["multiple"] === true, true), escape(createComponent(For, {
840
1146
  get each() {
@@ -1045,73 +1351,90 @@ var _tmpl$ = [
1045
1351
  "</div>"
1046
1352
  ];
1047
1353
  var _tmpl$2 = [
1048
- "<label",
1049
- "><!--$-->",
1050
- "<!--/--><input class=\"input\" required",
1051
- "></label>"
1354
+ "<input",
1355
+ " class=\"classic-editor__title\" required",
1356
+ ">"
1052
1357
  ];
1053
1358
  var _tmpl$3 = [
1054
- "<label",
1055
- "><!--$-->",
1056
- "<!--/--><textarea class=\"input\" rows=\"3\"",
1057
- "></textarea></label>"
1359
+ "<div",
1360
+ " class=\"classic-editor__toolbar\" role=\"toolbar\"",
1361
+ "><button type=\"button\"><strong>B</strong></button><button type=\"button\"><em>I</em></button><button type=\"button\"><u>U</u></button><span class=\"classic-editor__toolbar-divider\"></span><button type=\"button\">❝</button><button type=\"button\">• List</button><button type=\"button\">1. List</button><button type=\"button\">Link</button></div>"
1058
1362
  ];
1059
1363
  var _tmpl$4 = [
1060
- "<label",
1061
- "><!--$-->",
1062
- "<!--/--><input class=\"input\"",
1063
- "></label>"
1364
+ "<div",
1365
+ " class=\"classic-editor__body\" contenteditable=\"true\" data-classic-editor role=\"textbox\" aria-multiline=\"true\"",
1366
+ ">",
1367
+ "</div>"
1064
1368
  ];
1065
1369
  var _tmpl$5 = [
1066
1370
  "<label",
1067
- "><!--$-->",
1068
- "<!--/--><select class=\"input\"",
1069
- "><option value>",
1070
- "</option><!--$-->",
1071
- "<!--/--></select></label>"
1371
+ " class=\"classic-editor__excerpt\"><span>",
1372
+ "</span><textarea class=\"input\" rows=\"4\"",
1373
+ "></textarea></label>"
1072
1374
  ];
1073
1375
  var _tmpl$6 = [
1074
- "<div",
1376
+ "<section",
1075
1377
  " class=\"card custom-fields\"><h3>",
1076
1378
  "</h3><!--$-->",
1077
1379
  "<!--/--><details><summary>",
1078
1380
  "</summary><!--$-->",
1079
- "<!--/--></details></div>"
1381
+ "<!--/--></details></section>"
1080
1382
  ];
1081
1383
  var _tmpl$7 = [
1384
+ "<section",
1385
+ " class=\"card classic-editor__panel\"><h3>",
1386
+ "</h3><input class=\"input\"",
1387
+ "><p class=\"muted\">",
1388
+ "</p></section>"
1389
+ ];
1390
+ var _tmpl$8 = [
1391
+ "<section",
1392
+ " class=\"card classic-editor__panel\"><h3>",
1393
+ "</h3><label><!--$-->",
1394
+ "<!--/--><select class=\"input\"",
1395
+ "><option value>",
1396
+ "</option><!--$-->",
1397
+ "<!--/--></select></label></section>"
1398
+ ];
1399
+ var _tmpl$9 = [
1082
1400
  "<form",
1083
- " class=\"content-editor\"><!--$-->",
1401
+ " class=\"content-editor classic-editor\"><!--$-->",
1084
1402
  "<!--/--><!--$-->",
1085
- "<!--/--><div class=\"card\"><label><!--$-->",
1086
- "<!--/--><select class=\"input\"",
1403
+ "<!--/--><div class=\"classic-editor__topbar\"><div><span class=\"classic-editor__eyebrow\">",
1404
+ "</span><h2>",
1405
+ "</h2></div><div class=\"classic-editor__actions\"><a class=\"btn btn-secondary\" href=\"",
1406
+ "\">",
1407
+ "</a><button type=\"submit\" class=\"btn btn-primary\"",
1087
1408
  ">",
1088
- "</select></label><!--$-->",
1089
- "<!--/--><label><!--$-->",
1090
- "<!--/--><input class=\"input\"",
1091
- "></label><!--$-->",
1409
+ "</button></div></div><div class=\"classic-editor__columns\"><main class=\"classic-editor__main\"><section class=\"card classic-editor__canvas-card\"><!--$-->",
1410
+ "<!--/--><div class=\"classic-editor__permalink\"><span><!--$-->",
1411
+ "<!--/-->:</span><input class=\"input\"",
1412
+ "></div><!--$-->",
1092
1413
  "<!--/--><!--$-->",
1093
- "<!--/--><label><!--$-->",
1414
+ "<!--/--></section><!--$-->",
1415
+ "<!--/--></main><aside class=\"classic-editor__sidebar\"><section class=\"card classic-editor__panel\"><h3>",
1416
+ "</h3><label><!--$-->",
1094
1417
  "<!--/--><select class=\"input\"",
1095
1418
  "><option value=\"DRAFT\">",
1096
1419
  "</option><option value=\"PUBLISHED\">",
1097
1420
  "</option><option value=\"ARCHIVED\">",
1098
- "</option></select></label><!--$-->",
1099
- "<!--/--></div><!--$-->",
1100
- "<!--/--><button type=\"submit\" class=\"btn btn-primary\"",
1421
+ "</option></select></label><button type=\"submit\" class=\"btn btn-primary classic-editor__full-button\"",
1101
1422
  ">",
1102
- "</button></form>"
1423
+ "</button></section><!--$-->",
1424
+ "<!--/--><!--$-->",
1425
+ "<!--/--></aside></div></form>"
1103
1426
  ];
1104
- var _tmpl$8 = [
1427
+ var _tmpl$0 = [
1105
1428
  "<div",
1106
1429
  " class=\"notice notice--error\">",
1107
1430
  "</div>"
1108
1431
  ];
1109
- var _tmpl$9 = [
1432
+ var _tmpl$1 = [
1110
1433
  "<option",
1111
1434
  ">",
1112
1435
  "</option>"
1113
1436
  ];
1114
- function ContentEditor() {
1437
+ function ContentEditor(props) {
1115
1438
  const { t } = useTranslation();
1116
1439
  const [types, setTypes] = createSignal([]);
1117
1440
  const [fieldTypes, setFieldTypes] = createSignal([]);
@@ -1123,20 +1446,40 @@ function ContentEditor() {
1123
1446
  const [saving, setSaving] = createSignal(false);
1124
1447
  const [message, setMessage] = createSignal("");
1125
1448
  const [draft, setDraft] = createSignal({
1126
- type: "post",
1449
+ type: props.initialType || "post",
1127
1450
  title: "",
1128
1451
  status: "DRAFT"
1129
1452
  });
1130
- const supports = () => new Set(types().find((t) => t.slug === draft().type)?.supports ?? ["title", "editor"]);
1453
+ const supports = () => new Set(types().find((type) => type.slug === draft().type)?.supports ?? ["title", "editor"]);
1131
1454
  const hasSupport = (support) => supports().has(support);
1455
+ const typeListFallback = (available, requested) => requested || available[0]?.slug || "post";
1456
+ const availableLayouts = () => {
1457
+ const layouts = /* @__PURE__ */ new Set();
1458
+ for (const theme of themes()) for (const layout of theme.manifest?.provides?.layouts ?? []) layouts.add(layout);
1459
+ return [...layouts].sort();
1460
+ };
1461
+ const loadGroups = async (context) => {
1462
+ try {
1463
+ const query = typeof context === "string" ? { type: context } : context;
1464
+ const all = await apiClient.getFieldGroups(query.type ? query : void 0);
1465
+ const resolved = await Promise.all(all.filter((group) => group.active).map(async (group) => {
1466
+ return (await apiClient.getFieldGroup(group.id)).fields ?? [];
1467
+ }));
1468
+ setGroups(expandCloneFields(resolved.flat()));
1469
+ } catch (err) {
1470
+ setErrors([err instanceof Error ? err.message : String(err)]);
1471
+ }
1472
+ };
1132
1473
  onMount(async () => {
1474
+ let typeList = [];
1133
1475
  try {
1134
- const [typeList, fieldTypeCatalog, themeList] = await Promise.all([
1476
+ const [typeCatalog, fieldTypeCatalog, themeList] = await Promise.all([
1135
1477
  apiClient.getContentTypes(),
1136
1478
  apiClient.getFieldTypes(),
1137
1479
  apiClient.getThemes().catch(() => [])
1138
1480
  ]);
1139
- setTypes(typeList);
1481
+ typeList = typeCatalog;
1482
+ setTypes(typeCatalog);
1140
1483
  setFieldTypes(fieldTypeCatalog.types);
1141
1484
  setCategories(fieldTypeCatalog.categories);
1142
1485
  setThemes(themeList);
@@ -1161,30 +1504,21 @@ function ContentEditor() {
1161
1504
  } catch (err) {
1162
1505
  setErrors([err instanceof Error ? err.message : String(err)]);
1163
1506
  }
1507
+ else if (!typeList.some((type) => type.slug === draft().type)) setDraft({
1508
+ ...draft(),
1509
+ type: typeListFallback(typeList, props.initialType)
1510
+ });
1164
1511
  await loadGroups({
1165
1512
  type: draft().type,
1166
1513
  slug: draft().slug,
1167
1514
  status: draft().status
1168
1515
  });
1169
1516
  });
1170
- const availableLayouts = () => {
1171
- const layouts = /* @__PURE__ */ new Set();
1172
- for (const theme of themes()) for (const layout of theme.manifest?.provides?.layouts ?? []) layouts.add(layout);
1173
- return [...layouts].sort();
1517
+ const editorContent = () => {
1518
+ const value = data()["content"];
1519
+ return typeof value === "string" ? value : "";
1174
1520
  };
1175
- const loadGroups = async (context) => {
1176
- try {
1177
- const query = typeof context === "string" ? { type: context } : context;
1178
- const all = await apiClient.getFieldGroups(query.type ? query : void 0);
1179
- const resolved = await Promise.all(all.filter((group) => group.active).map(async (group) => {
1180
- return (await apiClient.getFieldGroup(group.id)).fields ?? [];
1181
- }));
1182
- setGroups(expandCloneFields(resolved.flat()));
1183
- } catch (err) {
1184
- setErrors([err instanceof Error ? err.message : String(err)]);
1185
- }
1186
- };
1187
- return ssr(_tmpl$7, ssrHydrationKey(), escape(createComponent(Show, {
1521
+ return ssr(_tmpl$9, ssrHydrationKey(), escape(createComponent(Show, {
1188
1522
  get when() {
1189
1523
  return errors().length > 0;
1190
1524
  },
@@ -1193,7 +1527,7 @@ function ContentEditor() {
1193
1527
  get each() {
1194
1528
  return errors();
1195
1529
  },
1196
- children: (err) => ssr(_tmpl$8, ssrHydrationKey(), escape(err))
1530
+ children: (err) => ssr(_tmpl$0, ssrHydrationKey(), escape(err))
1197
1531
  });
1198
1532
  }
1199
1533
  })), escape(createComponent(Show, {
@@ -1203,43 +1537,26 @@ function ContentEditor() {
1203
1537
  get children() {
1204
1538
  return ssr(_tmpl$, ssrHydrationKey(), escape(message()));
1205
1539
  }
1206
- })), escape(t("content.editor.type")), ssrAttribute("value", escape(draft().type, true), false), escape(createComponent(For, {
1207
- get each() {
1208
- return types();
1209
- },
1210
- children: (type) => ssr(_tmpl$9, ssrHydrationKey() + ssrAttribute("value", escape(type.slug, true), false), escape(type.pluralLabel))
1211
- })), escape(createComponent(Show, {
1540
+ })), escape(types().find((type) => type.slug === draft().type)?.singularLabel || draft().type), draft().id ? escape(t("content.editor.editing")) : escape(t("content.editor.adding")), `/content?type=${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, {
1212
1541
  get when() {
1213
1542
  return hasSupport("title");
1214
1543
  },
1215
1544
  get children() {
1216
- return ssr(_tmpl$2, ssrHydrationKey(), escape(t("content.editor.title")), ssrAttribute("value", escape(draft().title, true), false));
1545
+ 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));
1217
1546
  }
1218
- })), escape(t("content.editor.slug")), ssrAttribute("value", escape(draft().slug ?? "", true), false), escape(createComponent(Show, {
1547
+ })), escape(t("content.editor.slug")), ssrAttribute("value", escape(draft().slug ?? "", true), false) + ssrAttribute("placeholder", escape(t("content.editor.slugPlaceholder"), true), false), escape(createComponent(Show, {
1219
1548
  get when() {
1220
- return hasSupport("excerpt");
1549
+ return hasSupport("editor");
1221
1550
  },
1222
1551
  get children() {
1223
- return ssr(_tmpl$3, ssrHydrationKey(), escape(t("content.editor.excerpt")), ssrAttribute("value", escape(draft().excerpt ?? "", true), false));
1552
+ return [ssr(_tmpl$3, ssrHydrationKey(), ssrAttribute("aria-label", escape(t("content.editor.toolbar"), true), false)), ssr(_tmpl$4, ssrHydrationKey(), ssrAttribute("data-placeholder", escape(t("content.editor.bodyPlaceholder"), true), false), sanitizeHtml(editorContent()))];
1224
1553
  }
1225
1554
  })), escape(createComponent(Show, {
1226
1555
  get when() {
1227
- return hasSupport("thumbnail");
1228
- },
1229
- get children() {
1230
- return ssr(_tmpl$4, ssrHydrationKey(), escape(t("content.editor.featuredImage")), ssrAttribute("value", escape(draft().featuredImageId ?? "", true), false));
1231
- }
1232
- })), 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")), escape(createComponent(Show, {
1233
- get when() {
1234
- return availableLayouts().length > 0;
1556
+ return hasSupport("excerpt");
1235
1557
  },
1236
1558
  get children() {
1237
- return ssr(_tmpl$5, ssrHydrationKey(), escape(t("content.editor.layout")), ssrAttribute("value", escape(draft().layout ?? "", true), false), escape(t("content.editor.layoutAuto")), escape(createComponent(For, {
1238
- get each() {
1239
- return availableLayouts();
1240
- },
1241
- children: (layout) => ssr(_tmpl$9, ssrHydrationKey() + ssrAttribute("value", escape(layout, true), false), escape(layout))
1242
- })));
1559
+ return ssr(_tmpl$5, ssrHydrationKey(), escape(t("content.editor.excerpt")), ssrAttribute("value", escape(draft().excerpt ?? "", true), false));
1243
1560
  }
1244
1561
  })), escape(createComponent(Show, {
1245
1562
  get when() {
@@ -1271,7 +1588,26 @@ function ContentEditor() {
1271
1588
  onChange: () => void 0
1272
1589
  })));
1273
1590
  }
1274
- })), ssrAttribute("disabled", saving(), true), escape(t("content.editor.save")));
1591
+ })), 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, {
1592
+ get when() {
1593
+ return hasSupport("thumbnail");
1594
+ },
1595
+ get children() {
1596
+ return ssr(_tmpl$7, 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")));
1597
+ }
1598
+ })), escape(createComponent(Show, {
1599
+ get when() {
1600
+ return availableLayouts().length > 0;
1601
+ },
1602
+ get children() {
1603
+ return ssr(_tmpl$8, 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, {
1604
+ get each() {
1605
+ return availableLayouts();
1606
+ },
1607
+ children: (layout) => ssr(_tmpl$1, ssrHydrationKey() + ssrAttribute("value", escape(layout, true), false), escape(layout))
1608
+ })));
1609
+ }
1610
+ })));
1275
1611
  }
1276
1612
  //#endregion
1277
1613
  export { ContentEditor as t };