@noirmd/previewer 1.1.1 → 2.0.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 (53) hide show
  1. package/dist/NReditor.cjs +950 -913
  2. package/dist/NReditor.cjs.map +1 -1
  3. package/dist/NReditor.d.cts +6 -1
  4. package/dist/NReditor.d.ts +6 -1
  5. package/dist/NReditor.js +951 -914
  6. package/dist/NReditor.js.map +1 -1
  7. package/dist/admonition.css +55 -0
  8. package/dist/{markdown.css → base.css} +96 -126
  9. package/dist/blockquote.css +16 -0
  10. package/dist/button.css +32 -0
  11. package/dist/card.css +143 -0
  12. package/dist/codeblock.css +59 -0
  13. package/dist/core.cjs +9 -1
  14. package/dist/core.cjs.map +1 -1
  15. package/dist/core.js +9 -1
  16. package/dist/core.js.map +1 -1
  17. package/dist/details.css +45 -0
  18. package/dist/editor.css +226 -0
  19. package/dist/fonts/material-icons-round.woff2 +0 -0
  20. package/dist/index.cjs +852 -883
  21. package/dist/index.cjs.map +1 -1
  22. package/dist/index.d.cts +41 -70
  23. package/dist/index.d.ts +41 -70
  24. package/dist/index.js +851 -877
  25. package/dist/index.js.map +1 -1
  26. package/dist/list.css +18 -0
  27. package/dist/modal.css +82 -0
  28. package/dist/react.cjs +852 -886
  29. package/dist/react.cjs.map +1 -1
  30. package/dist/react.d.cts +44 -73
  31. package/dist/react.d.ts +44 -73
  32. package/dist/react.js +851 -880
  33. package/dist/react.js.map +1 -1
  34. package/dist/slide.css +21 -0
  35. package/dist/table.css +36 -0
  36. package/dist/toc.css +45 -0
  37. package/dist/vanilla.cjs +42 -28
  38. package/dist/vanilla.cjs.map +1 -1
  39. package/dist/vanilla.css +32 -677
  40. package/dist/vanilla.d.cts +8 -2
  41. package/dist/vanilla.d.ts +8 -2
  42. package/dist/vanilla.js +41 -28
  43. package/dist/vanilla.js.map +1 -1
  44. package/dist/variables.css +53 -0
  45. package/dist/vue.cjs +931 -1121
  46. package/dist/vue.cjs.map +1 -1
  47. package/dist/vue.d.cts +63 -214
  48. package/dist/vue.d.ts +63 -214
  49. package/dist/vue.js +930 -1120
  50. package/dist/vue.js.map +1 -1
  51. package/editor.css +226 -0
  52. package/package.json +6 -9
  53. package/markdown.css +0 -344
package/dist/NReditor.js CHANGED
@@ -1,7 +1,7 @@
1
1
  // react/NReditor.tsx
2
- import React9, { useRef as useRef6, useState as useState5 } from "react";
2
+ import React2, { useRef as useRef3, useState as useState2 } from "react";
3
3
  import CodeMirror from "@uiw/react-codemirror";
4
- import { EditorView, Decoration, ViewPlugin, lineNumbers, scrollPastEnd, keymap } from "@codemirror/view";
4
+ import { EditorView, Decoration, ViewPlugin, lineNumbers, keymap } from "@codemirror/view";
5
5
 
6
6
  // react/custom-syntax.ts
7
7
  import { StreamLanguage } from "@codemirror/language";
@@ -313,8 +313,64 @@ function useDebounce(value, delay) {
313
313
  return debouncedValue;
314
314
  }
315
315
 
316
+ // react/useTailwindCDN.ts
317
+ import { useEffect as useEffect2, useRef } from "react";
318
+ var CDN_URL = "https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4";
319
+ var SCRIPT_ID = "tailwind-cdn-v4-runtime";
320
+ var CONFIG_ID = "tailwind-cdn-v4-config";
321
+ var TAILWIND_CDN_CONFIG = `
322
+ window.tailwind = window.tailwind || {};
323
+ window.tailwind.config = {
324
+ corePlugins: {
325
+ preflight: false,
326
+ },
327
+ };
328
+ `;
329
+ function useLazyTailwindCDN(enabled) {
330
+ const loadedRef = useRef(false);
331
+ useEffect2(() => {
332
+ if (!enabled) {
333
+ window.__twCDNRefs = (window.__twCDNRefs ?? 1) - 1;
334
+ if ((window.__twCDNRefs ?? 0) <= 0) {
335
+ document.getElementById(SCRIPT_ID)?.remove();
336
+ document.getElementById(CONFIG_ID)?.remove();
337
+ window.__twCDNRefs = 0;
338
+ loadedRef.current = false;
339
+ }
340
+ return;
341
+ }
342
+ window.__twCDNRefs = (window.__twCDNRefs ?? 0) + 1;
343
+ if (!document.getElementById(CONFIG_ID)) {
344
+ const configScript = document.createElement("script");
345
+ configScript.id = CONFIG_ID;
346
+ configScript.textContent = TAILWIND_CDN_CONFIG;
347
+ document.head.appendChild(configScript);
348
+ }
349
+ if (!document.getElementById(SCRIPT_ID)) {
350
+ const script = document.createElement("script");
351
+ script.id = SCRIPT_ID;
352
+ script.src = CDN_URL;
353
+ document.head.appendChild(script);
354
+ loadedRef.current = true;
355
+ }
356
+ return () => {
357
+ window.__twCDNRefs = (window.__twCDNRefs ?? 1) - 1;
358
+ if ((window.__twCDNRefs ?? 0) <= 0) {
359
+ document.getElementById(SCRIPT_ID)?.remove();
360
+ document.getElementById(CONFIG_ID)?.remove();
361
+ window.__twCDNRefs = 0;
362
+ loadedRef.current = false;
363
+ }
364
+ };
365
+ }, [enabled]);
366
+ }
367
+ function scanTailwindCDN() {
368
+ const tw = window.tailwind;
369
+ if (tw?.scan) tw.scan();
370
+ }
371
+
316
372
  // react/CustomMarkdownRenderer.tsx
317
- import React8, { useState as useState4, useEffect as useEffect5, useCallback as useCallback2, useMemo, useId as useId3, useRef as useRef5 } from "react";
373
+ import { useEffect as useEffect3, useRef as useRef2 } from "react";
318
374
 
319
375
  // core/utils.ts
320
376
  function parseCssString(cssText) {
@@ -360,9 +416,6 @@ function extractAttributes(text) {
360
416
  return { text: cleanedText, classes: classList.join(" "), id };
361
417
  }
362
418
  var _scopeCounter = 0;
363
- function resetScopeCounter() {
364
- _scopeCounter = 0;
365
- }
366
419
  function generateScopeId() {
367
420
  return `scope-${++_scopeCounter}`;
368
421
  }
@@ -410,6 +463,7 @@ function parseMarkdown(markdown2) {
410
463
  if (!markdown2) return [];
411
464
  const lines = markdown2.replace(/\r\n/g, "\n").replace(/\r/g, "").split("\n");
412
465
  const result = [];
466
+ const usedIds = /* @__PURE__ */ new Set();
413
467
  let i = 0;
414
468
  while (i < lines.length) {
415
469
  const line = lines[i];
@@ -419,7 +473,14 @@ function parseMarkdown(markdown2) {
419
473
  const level = match[1].length;
420
474
  const rawText = match[2];
421
475
  const { text: text2, classes: classes2, id: customId } = extractAttributes(rawText);
422
- const id2 = customId || generateId(text2.replace(/->|<-/g, ""));
476
+ const baseId = customId || generateId(text2.replace(/->|<-/g, ""));
477
+ let id2 = baseId;
478
+ let n = 1;
479
+ while (usedIds.has(id2)) {
480
+ n++;
481
+ id2 = `${baseId}-${n}`;
482
+ }
483
+ usedIds.add(id2);
423
484
  result.push({ type: "header", level, text: text2, id: id2, classes: classes2 || void 0 });
424
485
  i++;
425
486
  continue;
@@ -734,10 +795,7 @@ function splitSlots(rawContent) {
734
795
  return slots;
735
796
  }
736
797
 
737
- // react/ui-components.tsx
738
- import { useState as useState2, useRef } from "react";
739
-
740
- // react/highlightSetup.ts
798
+ // vanilla/highlightSetup.ts
741
799
  import hljs from "highlight.js/lib/core";
742
800
  import javascript from "highlight.js/lib/languages/javascript";
743
801
  import typescript from "highlight.js/lib/languages/typescript";
@@ -786,1000 +844,947 @@ hljs.registerLanguage("java", java);
786
844
  hljs.registerLanguage("csharp", csharp);
787
845
  hljs.registerLanguage("cs", csharp);
788
846
  hljs.registerLanguage("cpp", cpp);
789
- hljs.registerLanguage("c", cpp);
790
847
  hljs.registerLanguage("go", go);
791
848
  hljs.registerLanguage("rust", rust);
792
- hljs.registerLanguage("rs", rust);
793
849
  hljs.registerLanguage("php", php);
794
850
  hljs.registerLanguage("ruby", ruby);
795
- hljs.registerLanguage("rb", ruby);
796
851
  hljs.registerLanguage("swift", swift);
797
852
  hljs.registerLanguage("kotlin", kotlin);
798
- hljs.registerLanguage("kt", kotlin);
799
853
  hljs.registerLanguage("dart", dart);
800
854
  hljs.registerLanguage("yaml", yaml);
801
- hljs.registerLanguage("yml", yaml);
802
855
  hljs.registerLanguage("toml", toml);
803
- hljs.registerLanguage("ini", toml);
804
856
  hljs.registerLanguage("dockerfile", dockerfile);
805
- hljs.registerLanguage("docker", dockerfile);
806
857
  hljs.registerLanguage("diff", diff);
807
858
  hljs.registerLanguage("shell", shell);
808
859
  var highlightSetup_default = hljs;
809
860
 
810
- // react/ui-components.tsx
811
- import { Dialog } from "@base-ui/react/dialog";
812
- import { jsx, jsxs } from "react/jsx-runtime";
813
- var IconRenderer = ({ iconName, extraClasses = "" }) => {
814
- if (!iconName) return null;
815
- const baseClass = `material-symbols-rounded !text-[1em] leading-none align-top ${extraClasses}`;
861
+ // vanilla/components.ts
862
+ function createIcon(iconName, extraClasses) {
863
+ const span = document.createElement("span");
864
+ const cls = `nr-icon material-icons-round${extraClasses ? ` ${extraClasses}` : ""}`;
865
+ span.className = cls;
866
+ span.setAttribute("aria-hidden", "true");
816
867
  const isCodepoint = /^[eE][0-9a-fA-F]{3,4}$/.test(iconName);
817
868
  if (isCodepoint) {
818
- return /* @__PURE__ */ jsx(
819
- "span",
820
- {
821
- className: baseClass,
822
- dangerouslySetInnerHTML: { __html: `&#x${iconName};` },
823
- "aria-hidden": "true"
824
- }
825
- );
869
+ span.innerHTML = `&#x${iconName};`;
870
+ } else {
871
+ span.textContent = iconName;
826
872
  }
827
- return /* @__PURE__ */ jsx("span", { className: baseClass, "aria-hidden": "true", children: iconName });
828
- };
829
- var CodeBlock = ({ code, language, title }) => {
830
- const [copied, setCopied] = useState2(false);
831
- const timerRef = useRef(null);
873
+ return span;
874
+ }
875
+ function createCodeBlock(code, language, title) {
876
+ const wrapper = document.createElement("div");
877
+ wrapper.className = "nr-codeblock";
832
878
  const lang = language?.split(/[\s{]/)[0]?.trim() || "";
833
- let html;
879
+ if (title) {
880
+ const header = document.createElement("div");
881
+ header.className = "nr-codeblock__header";
882
+ header.appendChild(createIcon("description"));
883
+ const titleSpan = document.createElement("span");
884
+ titleSpan.textContent = title;
885
+ header.appendChild(titleSpan);
886
+ wrapper.appendChild(header);
887
+ }
888
+ const pre = document.createElement("pre");
889
+ pre.className = "nr-codeblock__pre";
890
+ const codeEl = document.createElement("code");
891
+ codeEl.className = `language-${lang || "plaintext"}`;
834
892
  try {
835
893
  if (lang && highlightSetup_default.getLanguage(lang)) {
836
- html = highlightSetup_default.highlight(code, { language: lang }).value;
894
+ codeEl.innerHTML = highlightSetup_default.highlight(code, { language: lang }).value;
837
895
  } else {
838
- html = highlightSetup_default.highlightAuto(code).value;
896
+ codeEl.innerHTML = highlightSetup_default.highlightAuto(code).value;
839
897
  }
840
898
  } catch {
841
- html = "";
899
+ codeEl.textContent = code;
842
900
  }
843
- const handleCopy = () => {
901
+ pre.appendChild(codeEl);
902
+ wrapper.appendChild(pre);
903
+ const copyBtn = document.createElement("button");
904
+ copyBtn.className = "nr-codeblock__copy";
905
+ copyBtn.title = "Copy code";
906
+ const copyIcon = createIcon("content_copy");
907
+ copyIcon.style.fontSize = "1rem";
908
+ copyBtn.appendChild(copyIcon);
909
+ let timer = null;
910
+ copyBtn.addEventListener("click", () => {
844
911
  navigator.clipboard.writeText(code);
845
- setCopied(true);
846
- if (timerRef.current) clearTimeout(timerRef.current);
847
- timerRef.current = setTimeout(() => setCopied(false), 1800);
848
- };
849
- return /* @__PURE__ */ jsxs("div", { className: "not-prose my-4 rounded-2xl border border-border overflow-hidden bg-background-secondary-solid/5", children: [
850
- title && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 px-4 py-2 border-b border-border bg-background-secondary-solid/10 text-xs sm:text-sm font-mono text-text-secondary", children: [
851
- /* @__PURE__ */ jsx("span", { className: "material-symbols-rounded text-base", children: "description" }),
852
- title
853
- ] }),
854
- /* @__PURE__ */ jsx("div", { className: "overflow-auto [&_pre]:m-0 [&_pre]:p-4 [&_pre]:text-xs sm:[&_pre]:text-sm", children: /* @__PURE__ */ jsx("pre", { className: "m-0", children: /* @__PURE__ */ jsx("code", { className: `language-${lang || "plaintext"}`, dangerouslySetInnerHTML: { __html: html } }) }) }),
855
- /* @__PURE__ */ jsx("button", { className: "absolute top-2 right-2 p-1.5 rounded-lg bg-background-secondary-solid/20 hover:bg-background-secondary-solid/40 transition-colors cursor-pointer border-none text-text-secondary hover:text-text-primary", onClick: handleCopy, title: "Copy code", children: /* @__PURE__ */ jsx("span", { className: "material-symbols-rounded", style: { fontSize: "1rem" }, children: copied ? "check" : "content_copy" }) })
856
- ] });
857
- };
858
- var defaultIcons = {
912
+ copyIcon.textContent = "check";
913
+ if (timer) clearTimeout(timer);
914
+ timer = setTimeout(() => {
915
+ copyIcon.textContent = "content_copy";
916
+ }, 1800);
917
+ });
918
+ wrapper.appendChild(copyBtn);
919
+ return wrapper;
920
+ }
921
+ var DEFAULT_ADMONITION_ICONS = {
859
922
  note: "info",
860
923
  info: "lightbulb",
861
924
  warning: "warning",
862
925
  danger: "report",
863
- greentext: "subdirectory_play_arrow"
926
+ greentext: "subdirectory_arrow_right"
864
927
  };
865
- var typeClasses = {
866
- note: "border-info/20 bg-info/5 text-info",
867
- info: "border-info/30 bg-info/10 text-info",
868
- warning: "border-amber-500/30 bg-amber-500/10 text-amber-500",
869
- danger: "border-danger/30 bg-danger/10 text-danger",
870
- greentext: "border-success/30 bg-success/10 text-success"
871
- };
872
- var Admonition = ({ type, title, icon, className = "", style, children }) => {
873
- const iconToRender = icon || defaultIcons[type] || "info";
874
- return /* @__PURE__ */ jsxs(
875
- "div",
876
- {
877
- className: `not-prose rounded-2xl mb-6 border shadow-xs p-4 ${typeClasses[type] || typeClasses.note} ${className}`,
878
- style,
879
- children: [
880
- title && /* @__PURE__ */ jsxs("h5", { className: "font-bold text-base mb-2 m-0 flex items-center gap-2", children: [
881
- /* @__PURE__ */ jsx(IconRenderer, { iconName: iconToRender, extraClasses: "shrink-0" }),
882
- /* @__PURE__ */ jsx("span", { children: title })
883
- ] }),
884
- /* @__PURE__ */ jsx("div", { className: "text-sm leading-relaxed opacity-90", children })
885
- ]
886
- }
887
- );
888
- };
889
- var Details = ({
890
- title,
891
- icon,
892
- defaultOpen = false,
893
- className = "",
894
- style,
895
- children
896
- }) => {
897
- const [isOpen, setIsOpen] = useState2(defaultOpen);
898
- const iconToRender = icon || "play_arrow";
899
- return /* @__PURE__ */ jsxs(
900
- "details",
901
- {
902
- className: `not-prose rounded-2xl border border-border mb-4 bg-background-primary/5 ${className}`,
903
- open: isOpen,
904
- style,
905
- children: [
906
- /* @__PURE__ */ jsxs(
907
- "summary",
908
- {
909
- className: "cursor-pointer p-4 font-bold flex items-center gap-2 list-none [&::-webkit-details-marker]:hidden hover:text-accent-primary transition-colors",
910
- onClick: (e) => {
911
- e.preventDefault();
912
- setIsOpen((prev) => !prev);
913
- },
914
- children: [
915
- /* @__PURE__ */ jsx(
916
- IconRenderer,
917
- {
918
- iconName: iconToRender,
919
- extraClasses: `transition-transform ${isOpen ? "rotate-90" : ""}`
920
- }
921
- ),
922
- /* @__PURE__ */ jsx("span", { children: title })
923
- ]
924
- }
925
- ),
926
- isOpen && /* @__PURE__ */ jsx("div", { className: "px-4 pb-4 border-t border-border pt-3 text-sm leading-relaxed opacity-90 overflow-hidden min-w-0", children })
927
- ]
928
- }
929
- );
930
- };
931
- var Modal = ({ title, isOpen, onClose, children }) => {
932
- return /* @__PURE__ */ jsx(Dialog.Root, { open: isOpen, onOpenChange: (open) => {
933
- if (!open) onClose();
934
- }, children: /* @__PURE__ */ jsxs(Dialog.Portal, { children: [
935
- /* @__PURE__ */ jsx(Dialog.Backdrop, { className: "fixed inset-0 z-[9999] bg-black/60" }),
936
- /* @__PURE__ */ jsx(Dialog.Viewport, { className: "fixed inset-0 z-[9999] flex items-center justify-center p-4", children: /* @__PURE__ */ jsxs(Dialog.Popup, { className: "bg-background-primary border border-border shadow-2xl rounded-3xl w-full max-w-3xl max-h-[85vh] flex flex-col overflow-hidden", children: [
937
- /* @__PURE__ */ jsxs("div", { className: "flex justify-between items-center p-4 border-b border-border bg-background-secondary-solid/20", children: [
938
- /* @__PURE__ */ jsx(Dialog.Title, { className: "text-lg font-bold !m-0", children: title }),
939
- /* @__PURE__ */ jsx(Dialog.Close, { className: "w-8 h-8 rounded-full hover:bg-white/10 flex items-center justify-center transition-colors cursor-pointer border-none bg-transparent", children: /* @__PURE__ */ jsx("span", { className: "material-symbols-rounded text-base", children: "close" }) })
940
- ] }),
941
- /* @__PURE__ */ jsx("div", { className: "p-6 overflow-auto min-h-0 text-text-primary [&_h1:first-child]:mt-0 [&_h2:first-child]:mt-0 [&_h3:first-child]:mt-0 [&_h4:first-child]:mt-0 [&_h5:first-child]:mt-0 [&_h6:first-child]:mt-0", children })
942
- ] }) })
943
- ] }) });
944
- };
945
-
946
- // react/renderers.tsx
947
- import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
948
- function renderInline(text) {
949
- if (!text) return text;
950
- const parsePart = (part, key) => {
951
- let match2;
952
- if (match2 = part.match(/^\|\[([^\]]+)\]\|$/)) {
953
- return /* @__PURE__ */ jsx2(IconRenderer, { iconName: match2[1] }, key);
954
- }
955
- if (match2 = part.match(/^!~(.+?)~!$/)) {
956
- const content = match2[1];
957
- const parts = content.split(";");
958
- let color = "currentColor";
959
- let decorationStyle = "solid";
960
- let type = "underline";
961
- let textIndex = 0;
962
- if (parts[textIndex]?.match(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/) || ["red", "blue", "green", "purple", "orange", "yellow", "pink"].includes(parts[textIndex])) {
963
- color = parts[textIndex++];
964
- }
965
- if (["solid", "double", "dotted", "dashed", "wavy"].includes(parts[textIndex])) {
966
- decorationStyle = parts[textIndex++];
967
- }
968
- if (["underline", "line-through", "overline", "both"].includes(parts[textIndex])) {
969
- type = parts[textIndex] === "both" ? "underline line-through" : parts[textIndex++];
970
- }
971
- const innerText = parts.slice(textIndex).join(";");
972
- return /* @__PURE__ */ jsx2(
973
- "span",
974
- {
975
- style: {
976
- textDecoration: `${type} ${decorationStyle} ${color}`,
977
- textDecorationThickness: "auto"
978
- },
979
- children: renderInline(innerText)
980
- },
981
- key
982
- );
983
- }
984
- if (match2 = part.match(/%([^%\s]+?)%([\s\S]+?)%%/)) {
985
- return /* @__PURE__ */ jsx2("span", { style: { color: match2[1] }, children: renderInline(match2[2]) }, key);
986
- }
987
- if (match2 = part.match(/^!>([^<]+?)<!$/)) {
988
- return /* @__PURE__ */ jsx2("span", { className: "bg-text-primary text-bg-primary px-1 rounded hover:bg-transparent transition-colors cursor-pointer", children: renderInline(match2[1]) }, key);
989
- }
990
- if (match2 = part.match(/^==(.+?)==$/)) {
991
- return /* @__PURE__ */ jsx2("mark", { className: "bg-yellow-500/20 text-inherit px-0.5 rounded", children: renderInline(match2[1]) }, key);
992
- }
993
- if (match2 = part.match(/^\*\*\*(.+?)\*\*\*$/)) {
994
- return /* @__PURE__ */ jsx2("strong", { children: /* @__PURE__ */ jsx2("em", { children: renderInline(match2[1]) }) }, key);
995
- }
996
- if (match2 = part.match(/^\*\*(.+?)\*\*$/)) {
997
- return /* @__PURE__ */ jsx2("strong", { children: renderInline(match2[1]) }, key);
998
- }
999
- if (match2 = part.match(/^_(.+?)_$/)) {
1000
- return /* @__PURE__ */ jsx2("em", { children: renderInline(match2[1]) }, key);
1001
- }
1002
- if (match2 = part.match(/^~~(.+?)~~$/)) {
1003
- return /* @__PURE__ */ jsx2("del", { children: renderInline(match2[1]) }, key);
1004
- }
1005
- if (match2 = part.match(/^`([^`]+)`$/)) {
1006
- return /* @__PURE__ */ jsx2("code", { className: "text-[0.875em] font-mono bg-background-secondary/50 px-1.5 py-0.5 rounded text-text-primary", children: match2[1] }, key);
1007
- }
1008
- if (match2 = part.match(/^\[([^\]]+?)\]\(([^)]+?)\)$/)) {
1009
- return /* @__PURE__ */ jsx2(
1010
- "a",
1011
- {
1012
- href: match2[2],
1013
- className: "text-accent-primary underline decoration-accent-primary/40 hover:decoration-accent-primary transition-colors",
1014
- target: "_blank",
1015
- rel: "noopener noreferrer",
1016
- children: renderInline(match2[1])
1017
- },
1018
- key
1019
- );
1020
- }
1021
- if (part.startsWith("<") && part.endsWith(">")) {
1022
- return /* @__PURE__ */ jsx2("span", { dangerouslySetInnerHTML: { __html: part } }, key);
1023
- }
1024
- return part;
1025
- };
1026
- const regex = /(\|\[[^\]]+\]\||\*\*\*.+?\*\*\*|\*\*.+?\*\*|_.+?_|~~.+?~~|`[^`]+?`|!~.+?~!|%[^%\s]+?%[\s\S]+?%%|!>.+?<!|==.+?==|\[[^\]]+?\]\([^)]+?\)|<[^>]+>)/g;
1027
- const elements = [];
1028
- let lastIndex = 0;
1029
- let match;
1030
- let keyCounter = 0;
1031
- while ((match = regex.exec(text)) !== null) {
1032
- if (match.index > lastIndex) {
1033
- elements.push(text.slice(lastIndex, match.index));
1034
- }
1035
- elements.push(parsePart(match[0], `inline-${keyCounter++}`));
1036
- lastIndex = regex.lastIndex;
1037
- }
1038
- if (lastIndex < text.length) {
1039
- elements.push(text.slice(lastIndex));
928
+ function createAdmonition(type, title, icon) {
929
+ const el = document.createElement("div");
930
+ el.className = `nr-admonition nr-admonition--${type || "note"}`;
931
+ if (title) {
932
+ const header = document.createElement("h5");
933
+ header.className = "nr-admonition__title";
934
+ const iconToRender = icon || DEFAULT_ADMONITION_ICONS[type] || "info";
935
+ header.appendChild(createIcon(iconToRender, "nr-admonition__icon"));
936
+ const titleSpan = document.createElement("span");
937
+ titleSpan.textContent = title;
938
+ header.appendChild(titleSpan);
939
+ el.appendChild(header);
1040
940
  }
1041
- return elements;
941
+ const body = document.createElement("div");
942
+ body.className = "nr-admonition__body";
943
+ el.appendChild(body);
944
+ return el;
945
+ }
946
+ function createDetails(title, icon, defaultOpen) {
947
+ const details = document.createElement("details");
948
+ details.className = "nr-details";
949
+ if (defaultOpen) details.open = true;
950
+ const summary = document.createElement("summary");
951
+ summary.className = "nr-details__summary";
952
+ const iconToRender = icon || "play_arrow";
953
+ const iconEl = createIcon(iconToRender, "nr-details__icon");
954
+ summary.appendChild(iconEl);
955
+ const titleSpan = document.createElement("span");
956
+ titleSpan.textContent = title || "Details";
957
+ summary.appendChild(titleSpan);
958
+ details.addEventListener("toggle", () => {
959
+ iconEl.classList.toggle("nr-details__icon--open", details.open);
960
+ });
961
+ details.appendChild(summary);
962
+ const body = document.createElement("div");
963
+ body.className = "nr-details__body";
964
+ details.appendChild(body);
965
+ return details;
1042
966
  }
1043
- function renderTable(content) {
967
+ function createModal(title) {
968
+ const dialog = document.createElement("dialog");
969
+ dialog.className = "nr-modal";
970
+ dialog.addEventListener("click", (e) => {
971
+ if (e.target === dialog) {
972
+ dialog.close();
973
+ }
974
+ });
975
+ const popup = document.createElement("div");
976
+ popup.className = "nr-modal__popup";
977
+ const header = document.createElement("div");
978
+ header.className = "nr-modal__header";
979
+ const titleEl = document.createElement("h2");
980
+ titleEl.className = "nr-modal__title";
981
+ titleEl.textContent = title;
982
+ header.appendChild(titleEl);
983
+ const closeBtn = document.createElement("button");
984
+ closeBtn.className = "nr-modal__close";
985
+ closeBtn.appendChild(createIcon("close"));
986
+ closeBtn.addEventListener("click", () => dialog.close());
987
+ header.appendChild(closeBtn);
988
+ popup.appendChild(header);
989
+ const body = document.createElement("div");
990
+ body.className = "nr-modal__body";
991
+ popup.appendChild(body);
992
+ dialog.appendChild(popup);
993
+ return dialog;
994
+ }
995
+ function createTable(content, renderInline2) {
1044
996
  const rows = content.split("\n").filter((r) => r.trim());
1045
- if (rows.length < 2) return /* @__PURE__ */ jsx2("p", { children: content });
997
+ if (rows.length < 2) {
998
+ const p = document.createElement("p");
999
+ p.textContent = content;
1000
+ return p;
1001
+ }
1046
1002
  const parseRow = (row) => row.split("|").map((c) => c.trim()).filter(Boolean);
1047
1003
  const headerCells = parseRow(rows[0]);
1048
1004
  const bodyRows = rows.slice(2).map(parseRow);
1049
- return /* @__PURE__ */ jsx2("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxs2("table", { className: "w-full text-sm sm:text-base border-collapse my-4", children: [
1050
- /* @__PURE__ */ jsx2("thead", { children: /* @__PURE__ */ jsx2("tr", { children: headerCells.map((cell, ci) => /* @__PURE__ */ jsx2("th", { className: "border border-border px-3 py-2 bg-background-secondary-solid/10 text-left font-bold", children: renderInline(cell) }, ci)) }) }),
1051
- /* @__PURE__ */ jsx2("tbody", { children: bodyRows.map((cells, ri) => /* @__PURE__ */ jsx2("tr", { children: cells.map((cell, ci) => /* @__PURE__ */ jsx2("td", { className: "border border-border px-3 py-2", children: renderInline(cell) }, ci)) }, ri)) })
1052
- ] }) });
1005
+ const wrapper = document.createElement("div");
1006
+ wrapper.className = "nr-table-wrap";
1007
+ const table = document.createElement("table");
1008
+ table.className = "nr-table";
1009
+ const thead = document.createElement("thead");
1010
+ const tr = document.createElement("tr");
1011
+ for (const cell of headerCells) {
1012
+ const th = document.createElement("th");
1013
+ th.className = "nr-table__th";
1014
+ th.appendChild(renderInline2(cell));
1015
+ tr.appendChild(th);
1016
+ }
1017
+ thead.appendChild(tr);
1018
+ table.appendChild(thead);
1019
+ const tbody = document.createElement("tbody");
1020
+ for (const cells of bodyRows) {
1021
+ const tr2 = document.createElement("tr");
1022
+ for (const cell of cells) {
1023
+ const td = document.createElement("td");
1024
+ td.className = "nr-table__td";
1025
+ td.appendChild(renderInline2(cell));
1026
+ tr2.appendChild(td);
1027
+ }
1028
+ tbody.appendChild(tr2);
1029
+ }
1030
+ table.appendChild(tbody);
1031
+ wrapper.appendChild(table);
1032
+ return wrapper;
1053
1033
  }
1054
- function renderList(content) {
1034
+ function createList(content, renderInline2) {
1055
1035
  const lines = content.split("\n");
1056
1036
  const items = [];
1057
1037
  for (const line of lines) {
1058
1038
  if (!line.trim()) continue;
1059
1039
  const match = line.match(/^(\s*)([-*+]|\d+\.)\s+(.+)$/);
1060
1040
  if (match) {
1061
- items.push({
1062
- indent: match[1].length,
1063
- marker: match[2],
1064
- text: match[3]
1065
- });
1041
+ items.push({ indent: match[1].length, marker: match[2], text: match[3] });
1066
1042
  }
1067
1043
  }
1068
- if (items.length === 0) return /* @__PURE__ */ jsx2("p", { children: content });
1044
+ if (items.length === 0) {
1045
+ const p = document.createElement("p");
1046
+ p.textContent = content;
1047
+ return p;
1048
+ }
1069
1049
  const isOrdered = /^\d+\.$/.test(items[0].marker);
1070
- const Tag = isOrdered ? "ol" : "ul";
1071
- return /* @__PURE__ */ jsx2(Tag, { className: `${isOrdered ? "list-decimal" : "list-disc"} pl-6 my-3 space-y-1 text-sm sm:text-base`, children: items.map((item, index) => /* @__PURE__ */ jsx2("li", { className: "leading-relaxed", children: renderInline(item.text) }, index)) });
1050
+ const list = document.createElement(isOrdered ? "ol" : "ul");
1051
+ list.className = "nr-list";
1052
+ for (const item of items) {
1053
+ const li = document.createElement("li");
1054
+ li.className = "nr-list__item";
1055
+ li.appendChild(renderInline2(item.text));
1056
+ list.appendChild(li);
1057
+ }
1058
+ return list;
1059
+ }
1060
+ function createTOC(headers, renderInline2) {
1061
+ const nav = document.createElement("nav");
1062
+ nav.className = "nr-toc";
1063
+ const title = document.createElement("div");
1064
+ title.className = "nr-toc__title";
1065
+ title.textContent = "Table of Contents";
1066
+ nav.appendChild(title);
1067
+ const ul = document.createElement("ul");
1068
+ ul.className = "nr-toc__list";
1069
+ for (const h of headers) {
1070
+ const li = document.createElement("li");
1071
+ li.className = `nr-toc__item nr-toc__item--h${h.level}`;
1072
+ const a = document.createElement("a");
1073
+ a.className = "nr-toc__link";
1074
+ a.href = `#${h.id}`;
1075
+ a.appendChild(renderInline2(h.text.replace(/->|<-/g, "").trim()));
1076
+ a.addEventListener("click", (e) => {
1077
+ e.preventDefault();
1078
+ const target = document.getElementById(h.id);
1079
+ if (target) target.scrollIntoView({ behavior: "smooth", block: "start" });
1080
+ });
1081
+ li.appendChild(a);
1082
+ ul.appendChild(li);
1083
+ }
1084
+ nav.appendChild(ul);
1085
+ return nav;
1072
1086
  }
1073
- function extractHeaders(elements) {
1074
- return elements.filter((el) => el.type === "header");
1087
+ function createBlockquote(content, classes, renderInline2) {
1088
+ const el = document.createElement("blockquote");
1089
+ el.className = `nr-blockquote${classes ? ` ${classes}` : ""}`;
1090
+ el.appendChild(renderInline2(content));
1091
+ return el;
1075
1092
  }
1076
1093
 
1077
- // react/directives/AdmonitionDirective.tsx
1078
- import { jsx as jsx3 } from "react/jsx-runtime";
1079
- var AdmonitionDirective = ({
1080
- directiveType,
1081
- props,
1082
- renderSlot
1083
- }) => {
1084
- return /* @__PURE__ */ jsx3(
1085
- Admonition,
1086
- {
1087
- type: directiveType,
1088
- title: props.title,
1089
- icon: props.icon,
1090
- className: props.class,
1091
- style: props.style ? parseCssString(props.style) : void 0,
1092
- children: renderSlot("default")
1094
+ // vanilla/inline.ts
1095
+ function renderInline(text) {
1096
+ const fragment = document.createDocumentFragment();
1097
+ if (!text) return fragment;
1098
+ const regex = /(\|\[[^\]]+\]\||\*\*\*.+?\*\*\*|\*\*.+?\*\*|_.+?_|~~.+?~~|`[^`]+?`|!~.+?~!|%[^%\s]+?%[\s\S]+?%%|!>.+?<!|==.+?==|\[[^\]]+?\]\([^)]+?\)|<[^>]+>)/g;
1099
+ let lastIndex = 0;
1100
+ let match;
1101
+ while ((match = regex.exec(text)) !== null) {
1102
+ if (match.index > lastIndex) {
1103
+ fragment.appendChild(document.createTextNode(text.slice(lastIndex, match.index)));
1093
1104
  }
1094
- );
1095
- };
1096
- var AdmonitionDirective_default = AdmonitionDirective;
1105
+ fragment.appendChild(parseInlinePart(match[0]));
1106
+ lastIndex = regex.lastIndex;
1107
+ }
1108
+ if (lastIndex < text.length) {
1109
+ fragment.appendChild(document.createTextNode(text.slice(lastIndex)));
1110
+ }
1111
+ return fragment;
1112
+ }
1113
+ function parseInlinePart(part) {
1114
+ let match;
1115
+ if (match = part.match(/^\|\[([^\]]+)\]\|$/)) {
1116
+ return createIcon(match[1]);
1117
+ }
1118
+ if (match = part.match(/^!~(.+?)~!$/)) {
1119
+ const content = match[1];
1120
+ const parts = content.split(";");
1121
+ let color = "currentColor";
1122
+ let decorationStyle = "solid";
1123
+ let type = "underline";
1124
+ let textIndex = 0;
1125
+ if (parts[textIndex]?.match(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/) || ["red", "blue", "green", "purple", "orange", "yellow", "pink"].includes(parts[textIndex])) {
1126
+ color = parts[textIndex++];
1127
+ }
1128
+ if (["solid", "double", "dotted", "dashed", "wavy"].includes(parts[textIndex])) {
1129
+ decorationStyle = parts[textIndex++];
1130
+ }
1131
+ if (["underline", "line-through", "overline", "both"].includes(parts[textIndex])) {
1132
+ type = parts[textIndex] === "both" ? "underline line-through" : parts[textIndex++];
1133
+ }
1134
+ const innerText = parts.slice(textIndex).join(";");
1135
+ const span = document.createElement("span");
1136
+ span.className = "nr-underline";
1137
+ span.style.textDecoration = `${type} ${decorationStyle} ${color}`;
1138
+ span.style.textDecorationThickness = "auto";
1139
+ span.appendChild(renderInline(innerText));
1140
+ return span;
1141
+ }
1142
+ if (match = part.match(/%([^%\s]+?)%([\s\S]+?)%%/)) {
1143
+ const span = document.createElement("span");
1144
+ span.style.color = match[1];
1145
+ span.appendChild(renderInline(match[2]));
1146
+ return span;
1147
+ }
1148
+ if (match = part.match(/^!>([^<]+?)<!$/)) {
1149
+ const span = document.createElement("span");
1150
+ span.className = "nr-spoiler";
1151
+ span.appendChild(renderInline(match[1]));
1152
+ return span;
1153
+ }
1154
+ if (match = part.match(/^==(.+?)==$/)) {
1155
+ const mark = document.createElement("mark");
1156
+ mark.className = "nr-highlight";
1157
+ mark.appendChild(renderInline(match[1]));
1158
+ return mark;
1159
+ }
1160
+ if (match = part.match(/^\*\*\*(.+?)\*\*\*$/)) {
1161
+ const strong = document.createElement("strong");
1162
+ const em = document.createElement("em");
1163
+ em.appendChild(renderInline(match[1]));
1164
+ strong.appendChild(em);
1165
+ return strong;
1166
+ }
1167
+ if (match = part.match(/^\*\*(.+?)\*\*$/)) {
1168
+ const strong = document.createElement("strong");
1169
+ strong.appendChild(renderInline(match[1]));
1170
+ return strong;
1171
+ }
1172
+ if (match = part.match(/^_(.+?)_$/)) {
1173
+ const em = document.createElement("em");
1174
+ em.appendChild(renderInline(match[1]));
1175
+ return em;
1176
+ }
1177
+ if (match = part.match(/^~~(.+?)~~$/)) {
1178
+ const del = document.createElement("del");
1179
+ del.appendChild(renderInline(match[1]));
1180
+ return del;
1181
+ }
1182
+ if (match = part.match(/^`([^`]+)`$/)) {
1183
+ const code = document.createElement("code");
1184
+ code.className = "nr-inline-code";
1185
+ code.textContent = match[1];
1186
+ return code;
1187
+ }
1188
+ if (match = part.match(/^\[([^\]]+?)\]\(([^)]+?)\)$/)) {
1189
+ const a = document.createElement("a");
1190
+ a.className = "nr-link";
1191
+ a.href = match[2];
1192
+ a.target = "_blank";
1193
+ a.rel = "noopener noreferrer";
1194
+ a.appendChild(renderInline(match[1]));
1195
+ return a;
1196
+ }
1197
+ if (part.startsWith("<") && part.endsWith(">")) {
1198
+ const span = document.createElement("span");
1199
+ span.innerHTML = part;
1200
+ return span;
1201
+ }
1202
+ return document.createTextNode(part);
1203
+ }
1097
1204
 
1098
- // react/directives/CardDirective.tsx
1099
- import React2, { useId } from "react";
1100
- import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
1101
- var CardDirective = ({
1102
- directiveType,
1103
- props,
1104
- slots,
1105
- renderSlot,
1106
- context,
1107
- options = {}
1108
- }) => {
1109
- const stableId = useId();
1110
- const { title, image, icon, class: customClass, url, target } = props;
1111
- const hasDescription = !!slots.description;
1112
- const { isSingleCard } = options;
1113
- const isModal = directiveType === "card-m";
1114
- const isLink = directiveType === "card-b";
1115
- const modalId = `modal-card-${props.id || stableId}`;
1116
- const wrapperClass = customClass || "";
1117
- const inlineStyles = props.style ? parseCssString(props.style) : {};
1118
- const description = hasDescription ? renderSlot("description") : null;
1119
- const content = renderSlot("content") || renderSlot("default");
1120
- return /* @__PURE__ */ jsxs3(React2.Fragment, { children: [
1121
- /* @__PURE__ */ jsxs3(
1122
- "div",
1123
- {
1124
- className: `flex flex-col h-full rounded-3xl transition-all relative overflow-hidden group border min-w-[18rem] w-[18rem] max-w-[20rem] ${isModal || isLink ? "cursor-pointer !border-accent-primary/10 hover:border-accent-primary/50" : "border-border"} ${wrapperClass}`,
1125
- style: inlineStyles,
1126
- onClick: isModal ? (e) => {
1127
- e.preventDefault();
1128
- e.stopPropagation();
1129
- context.setModals((prev) => ({ ...prev, [modalId]: true }));
1130
- } : isLink && url ? () => window.open(url, "_blank") : void 0,
1131
- role: isModal ? "button" : void 0,
1132
- tabIndex: isModal ? 0 : void 0,
1133
- onKeyDown: isModal ? (e) => {
1134
- if (e.key === "Enter" || e.key === " ") context.setModals((prev) => ({ ...prev, [modalId]: true }));
1135
- } : void 0,
1136
- children: [
1137
- image && /* @__PURE__ */ jsxs3("div", { className: `w-full ${isSingleCard ? "h-[240px]" : "h-[160px]"} overflow-hidden relative transition-all duration-500`, children: [
1138
- /* @__PURE__ */ jsx4("img", { src: image, alt: title || "", className: "w-full h-full object-cover !m-0" }),
1139
- /* @__PURE__ */ jsx4("div", { className: "absolute inset-0 bg-gradient-to-t from-background-primary/40 to-transparent" })
1140
- ] }),
1141
- /* @__PURE__ */ jsxs3("div", { className: `flex flex-col flex-1 bg-background-primary/80 rounded-t-xl p-6 relative ${image ? "-mt-10" : ""} border-t border-white/5 shadow-2xl`, children: [
1142
- /* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-3 mb-3", children: [
1143
- icon && /* @__PURE__ */ jsx4("div", { className: "w-10 h-10 text-[1.6em] rounded-xl bg-accent-primary/20 flex items-center justify-center shrink-0 text-accent-primary", children: /* @__PURE__ */ jsx4(IconRenderer, { iconName: icon }) }),
1144
- /* @__PURE__ */ jsx4("h3", { className: "text-base font-black tracking-tight leading-tight !m-0", children: title })
1145
- ] }),
1146
- /* @__PURE__ */ jsxs3("div", { className: "flex-1 flex flex-col gap-2", children: [
1147
- description && /* @__PURE__ */ jsx4("div", { className: "text-sm opacity-80 leading-relaxed font-medium", children: description }),
1148
- directiveType === "card" && content && /* @__PURE__ */ jsx4("div", { className: "mt-2", children: content })
1149
- ] }),
1150
- (isModal || isLink) && /* @__PURE__ */ jsx4("div", { className: "mt-6 flex justify-end", children: isLink && url ? /* @__PURE__ */ jsxs3(
1151
- "a",
1152
- {
1153
- href: url,
1154
- target: "_blank",
1155
- rel: "noopener noreferrer",
1156
- className: "bg-accent-primary/20 hover:bg-accent-primary/30 px-4 py-2 rounded-xl flex items-center gap-1.5 text-[10px] font-black uppercase tracking-widest opacity-50 group-hover:opacity-100 group-hover:text-accent-primary transition-all no-underline",
1157
- onClick: (e) => e.stopPropagation(),
1158
- children: [
1159
- /* @__PURE__ */ jsx4(IconRenderer, { iconName: "open_in_new" }),
1160
- " Link"
1161
- ]
1162
- }
1163
- ) : isModal ? /* @__PURE__ */ jsxs3("div", { className: "bg-accent-primary/20 hover:bg-accent-primary/30 px-4 py-2 cursor-pointer rounded-xl flex items-center gap-1.5 text-[10px] font-black uppercase tracking-widest opacity-50 group-hover:opacity-100 group-hover:text-accent-primary transition-all", children: [
1164
- /* @__PURE__ */ jsx4(IconRenderer, { iconName: "arrow_forward" }),
1165
- " Abrir"
1166
- ] }) : null })
1167
- ] })
1168
- ]
1169
- }
1170
- ),
1171
- isModal && /* @__PURE__ */ jsx4(
1172
- Modal,
1173
- {
1174
- title: title || "Detalles",
1175
- isOpen: !!context.modals[modalId],
1176
- onClose: () => context.setModals((prev) => ({ ...prev, [modalId]: false })),
1177
- children: /* @__PURE__ */ jsx4("div", { className: "prose prose-sm max-w-none", children: content })
1178
- }
1179
- )
1180
- ] });
1205
+ // vanilla/directives/admonition.ts
1206
+ var admonitionDirective = ({ directiveType, props, renderSlot }) => {
1207
+ const el = createAdmonition(directiveType, props.title, props.icon);
1208
+ if (props.class) el.classList.add(...props.class.split(/\s+/).filter(Boolean));
1209
+ if (props.style) el.setAttribute("style", props.style);
1210
+ const body = el.querySelector(".nr-admonition__body");
1211
+ if (body) {
1212
+ body.appendChild(renderSlot("default"));
1213
+ }
1214
+ return el;
1181
1215
  };
1182
- var CardDirective_default = CardDirective;
1216
+ var admonition_default = admonitionDirective;
1183
1217
 
1184
- // react/directives/DetailsDirective.tsx
1185
- import { jsx as jsx5 } from "react/jsx-runtime";
1186
- var DetailsDirective = ({
1187
- props,
1188
- renderSlot
1189
- }) => {
1190
- return /* @__PURE__ */ jsx5(
1191
- Details,
1192
- {
1193
- title: props.title || "Details",
1194
- icon: props.icon,
1195
- defaultOpen: props.defaultOpen === "true",
1196
- className: props.class,
1197
- style: props.style ? parseCssString(props.style) : void 0,
1198
- children: renderSlot("default")
1199
- }
1218
+ // vanilla/directives/details.ts
1219
+ var detailsDirective = ({ props, renderSlot }) => {
1220
+ const el = createDetails(
1221
+ props.title || "Details",
1222
+ props.icon,
1223
+ props.defaultOpen === "true"
1200
1224
  );
1225
+ if (props.class) el.classList.add(...props.class.split(/\s+/).filter(Boolean));
1226
+ if (props.style) el.setAttribute("style", props.style);
1227
+ const body = el.querySelector(".nr-details__body");
1228
+ if (body) {
1229
+ body.appendChild(renderSlot("default"));
1230
+ }
1231
+ return el;
1201
1232
  };
1202
- var DetailsDirective_default = DetailsDirective;
1233
+ var details_default = detailsDirective;
1203
1234
 
1204
- // react/directives/ModalDirective.tsx
1205
- import { useId as useId2 } from "react";
1206
- import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
1207
- var ModalDirective = ({
1208
- props,
1209
- renderSlot,
1210
- context
1211
- }) => {
1212
- const stableId = useId2();
1213
- const modalId = `modal-${props.id || stableId}`;
1235
+ // vanilla/directives/modal.ts
1236
+ var modalDirective = ({ props, renderSlot }) => {
1214
1237
  const label = props.label || props.title || "Open";
1215
1238
  const modalTitle = props.title || "Modal";
1216
1239
  const customClass = props.class || "";
1217
- const hasSizeClass = /\btext-(xs|sm|base|lg|xl|[2-9]xl)\b/.test(customClass);
1218
- const sizeClass = hasSizeClass ? "" : "text-sm";
1219
- const hasDisplayClass = /\b(flex|inline-flex|block|inline-block|grid|inline-grid|hidden)\b/.test(customClass);
1220
- const displayClass = hasDisplayClass ? "" : "inline-flex";
1221
- const isInlineFlex = /\binline-flex\b/.test(customClass);
1222
- const marginClass = isInlineFlex ? "my-1 mx-1" : "my-4";
1223
- const btnBase = `${displayClass} items-center w-fit ${marginClass} ${sizeClass} px-4 py-2 rounded-xl font-bold no-underline gap-2 transition-all hover:scale-105 active:scale-95 border border-border bg-background-primary/5 hover:bg-background-primary/10 text-text-primary hover:text-text-primary`.replace(/\s+/g, " ");
1224
- const btnClass = `${btnBase} ${customClass}`.trim();
1225
- const positionMap = {
1226
- "#left": "text-left",
1227
- "#center": "text-center",
1228
- "#right": "text-right"
1229
- };
1230
- const wrapperClass = customClass.split(/\s+/).map((c) => positionMap[c] || c).join(" ");
1231
- const handleOpen = () => {
1232
- context.setModals((prev) => ({ ...prev, [modalId]: true }));
1233
- };
1234
- const handleClose = () => {
1235
- context.setModals((prev) => ({ ...prev, [modalId]: false }));
1236
- };
1237
- return /* @__PURE__ */ jsxs4("div", { className: `not-prose ${wrapperClass}`.trim(), children: [
1238
- /* @__PURE__ */ jsxs4("button", { className: btnClass, onClick: handleOpen, children: [
1239
- props.icon && /* @__PURE__ */ jsx6(IconRenderer, { iconName: props.icon }),
1240
- label
1241
- ] }),
1242
- /* @__PURE__ */ jsx6(
1243
- Modal,
1244
- {
1245
- title: modalTitle,
1246
- isOpen: !!context.modals[modalId],
1247
- onClose: handleClose,
1248
- children: renderSlot("default")
1249
- }
1250
- )
1251
- ] });
1240
+ const wrapper = document.createElement("div");
1241
+ wrapper.className = "nr-modal-trigger";
1242
+ const btn = document.createElement("button");
1243
+ btn.className = `nr-button nr-button--default`;
1244
+ if (customClass) btn.classList.add(...customClass.split(/\s+/).filter(Boolean));
1245
+ const icon = props.icon || "open_in_new";
1246
+ if (icon) btn.appendChild(createIcon(icon));
1247
+ btn.appendChild(document.createTextNode(label));
1248
+ const dialog = createModal(modalTitle);
1249
+ const body = dialog.querySelector(".nr-modal__body");
1250
+ if (body) {
1251
+ body.appendChild(renderSlot("default"));
1252
+ }
1253
+ btn.addEventListener("click", () => {
1254
+ if (!dialog.open) {
1255
+ document.body.appendChild(dialog);
1256
+ dialog.showModal();
1257
+ dialog.addEventListener("close", () => {
1258
+ dialog.remove();
1259
+ }, { once: true });
1260
+ }
1261
+ });
1262
+ wrapper.appendChild(btn);
1263
+ wrapper.appendChild(dialog);
1264
+ return wrapper;
1252
1265
  };
1253
- var ModalDirective_default = ModalDirective;
1266
+ var modal_default = modalDirective;
1254
1267
 
1255
- // react/directives/ButtonDirective.tsx
1256
- import React4 from "react";
1257
- import { Fragment, jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
1258
- var ButtonDirective = ({
1259
- props,
1260
- renderSlot
1261
- }) => {
1268
+ // vanilla/directives/button.ts
1269
+ var buttonDirective = ({ props, renderSlot }) => {
1262
1270
  const url = props.url || props.href || "#";
1263
1271
  const label = props.label;
1264
1272
  const icon = props.icon || "near_me";
1265
1273
  const target = props.target || "_blank";
1266
1274
  const customClass = props.class || "";
1267
- const hasSizeClass = /\btext-(xs|sm|base|lg|xl|[2-9]xl)\b/.test(customClass);
1268
- const sizeClass = hasSizeClass ? "" : "text-sm";
1269
- const hasDisplayClass = /\b(flex|inline-flex|block|inline-block|grid|inline-grid|hidden)\b/.test(customClass);
1270
- const displayClass = hasDisplayClass ? "" : "inline-flex";
1271
- const isInline = !customClass || !/\b(flex|block|grid)\b/.test(customClass) || /\binline-flex\b/.test(customClass);
1272
- const marginClass = isInline ? "my-1 mx-1" : "my-4";
1273
- const btnBase = `${displayClass} items-center w-fit ${marginClass} ${sizeClass} px-4 py-2 rounded-xl font-bold no-underline gap-2 transition-all hover:scale-105 active:scale-95 border border-border bg-background-primary/5 hover:bg-background-primary/10 text-text-primary hover:text-text-primary`.replace(/\s+/g, " ");
1274
- const btnClass = `${btnBase} ${customClass}`.trim();
1275
- const positionMap = {
1276
- "#left": "flex justify-start",
1277
- "#center": "flex justify-center",
1278
- "#right": "flex justify-end"
1279
- };
1280
- const wrapperClass = customClass.split(/\s+/).map((c) => positionMap[c] || c).join(" ");
1275
+ const wrapper = document.createElement("div");
1276
+ wrapper.className = "nr-button-wrap";
1281
1277
  if (label) {
1282
- return /* @__PURE__ */ jsx7("div", { className: `not-prose ${wrapperClass}`.trim(), children: /* @__PURE__ */ jsxs5(
1283
- "a",
1284
- {
1285
- href: url,
1286
- target,
1287
- rel: "noopener noreferrer",
1288
- className: btnClass,
1289
- children: [
1290
- /* @__PURE__ */ jsx7(IconRenderer, { iconName: icon }),
1291
- label
1292
- ]
1293
- }
1294
- ) });
1278
+ const a = document.createElement("a");
1279
+ a.href = url;
1280
+ a.target = target;
1281
+ a.rel = "noopener noreferrer";
1282
+ a.className = "nr-button nr-button--default";
1283
+ if (customClass) a.classList.add(...customClass.split(/\s+/).filter(Boolean));
1284
+ a.appendChild(createIcon(icon));
1285
+ a.appendChild(document.createTextNode(label));
1286
+ wrapper.appendChild(a);
1287
+ return wrapper;
1295
1288
  }
1296
1289
  const slotContent = renderSlot("default");
1297
- const findLinks = (element) => {
1298
- if (!element) return [];
1299
- if (React4.isValidElement(element) && element.type === "a") {
1300
- return [element];
1301
- }
1302
- if (Array.isArray(element)) {
1303
- return element.flatMap(findLinks);
1304
- }
1305
- if (React4.isValidElement(element) && element.props.children) {
1306
- return findLinks(element.props.children);
1307
- }
1308
- return [];
1309
- };
1310
- const links = findLinks(slotContent);
1290
+ const links = slotContent.querySelectorAll("a");
1311
1291
  if (links.length > 0) {
1312
- return /* @__PURE__ */ jsx7("div", { className: `not-prose ${wrapperClass}`.trim(), children: links.map(
1313
- (link, index) => React4.cloneElement(
1314
- link,
1315
- {
1316
- key: index,
1317
- className: `${link.props.className || ""} ${btnClass}`.trim(),
1318
- target,
1319
- rel: "noopener noreferrer"
1320
- },
1321
- /* @__PURE__ */ jsxs5(Fragment, { children: [
1322
- /* @__PURE__ */ jsx7(IconRenderer, { iconName: icon }),
1323
- link.props.children
1324
- ] })
1325
- )
1326
- ) });
1292
+ links.forEach((link) => {
1293
+ link.classList.add("nr-button", "nr-button--default");
1294
+ if (customClass) link.classList.add(...customClass.split(/\s+/).filter(Boolean));
1295
+ });
1296
+ wrapper.appendChild(slotContent);
1297
+ } else {
1298
+ const a = document.createElement("a");
1299
+ a.href = url;
1300
+ a.target = target;
1301
+ a.rel = "noopener noreferrer";
1302
+ a.className = "nr-button nr-button--default";
1303
+ if (customClass) a.classList.add(...customClass.split(/\s+/).filter(Boolean));
1304
+ a.appendChild(createIcon(icon));
1305
+ a.appendChild(slotContent);
1306
+ wrapper.appendChild(a);
1327
1307
  }
1328
- return /* @__PURE__ */ jsx7("div", { className: `not-prose ${wrapperClass}`.trim(), children: /* @__PURE__ */ jsxs5("a", { href: url, target, rel: "noopener noreferrer", className: btnClass, children: [
1329
- /* @__PURE__ */ jsx7(IconRenderer, { iconName: icon }),
1330
- slotContent
1331
- ] }) });
1308
+ return wrapper;
1332
1309
  };
1333
- var ButtonDirective_default = ButtonDirective;
1310
+ var button_default = buttonDirective;
1334
1311
 
1335
- // react/directives/WrapperDirective.tsx
1336
- import { jsx as jsx8 } from "react/jsx-runtime";
1337
- var WrapperDirective = ({
1312
+ // vanilla/directives/card.ts
1313
+ var cardDirective = ({
1314
+ directiveType,
1338
1315
  props,
1339
- renderSlot
1316
+ slots,
1317
+ renderSlot,
1318
+ options
1340
1319
  }) => {
1341
- const className = props.class || "";
1342
- const id = props.id || "";
1343
- const inlineStyle = props.style ? parseCssString(props.style) : {};
1344
- const wrapperProps = {};
1345
- if (className) wrapperProps.className = className;
1346
- if (id) wrapperProps.id = id;
1347
- if (Object.keys(inlineStyle).length > 0) wrapperProps.style = inlineStyle;
1320
+ const { title, image, icon, url, target } = props;
1321
+ const customClass = props.class || "";
1322
+ const hasDescription = !!slots.description;
1323
+ const { isSingleCard } = options || {};
1324
+ const isModal = directiveType === "card-m";
1325
+ const isLink = directiveType === "card-b";
1326
+ const inlineStyles = props.style ? parseCssString(props.style) : {};
1327
+ const card = document.createElement("div");
1328
+ card.className = `nr-card${isModal || isLink ? " nr-card--interactive" : ""} ${customClass}`.trim();
1329
+ for (const [key, value] of Object.entries(inlineStyles)) {
1330
+ card.style.setProperty(key, String(value));
1331
+ }
1332
+ if (image) {
1333
+ const imgWrap = document.createElement("div");
1334
+ imgWrap.className = `nr-card__image${isSingleCard ? " nr-card__image--tall" : ""}`;
1335
+ const img = document.createElement("img");
1336
+ img.src = image;
1337
+ img.alt = title || "";
1338
+ img.className = "nr-card__img";
1339
+ imgWrap.appendChild(img);
1340
+ const gradient = document.createElement("div");
1341
+ gradient.className = "nr-card__gradient";
1342
+ imgWrap.appendChild(gradient);
1343
+ card.appendChild(imgWrap);
1344
+ }
1345
+ const body = document.createElement("div");
1346
+ body.className = `nr-card__body${image ? " nr-card__body--overlap" : ""}`;
1347
+ if (icon || title) {
1348
+ const header = document.createElement("div");
1349
+ header.className = "nr-card__header";
1350
+ if (icon) {
1351
+ const iconWrap = document.createElement("div");
1352
+ iconWrap.className = "nr-card__icon-wrap";
1353
+ iconWrap.appendChild(createIcon(icon));
1354
+ header.appendChild(iconWrap);
1355
+ }
1356
+ if (title) {
1357
+ const h3 = document.createElement("h3");
1358
+ h3.className = "nr-card__title";
1359
+ h3.textContent = title;
1360
+ header.appendChild(h3);
1361
+ }
1362
+ body.appendChild(header);
1363
+ }
1364
+ if (hasDescription) {
1365
+ const desc = document.createElement("div");
1366
+ desc.className = "nr-card__description";
1367
+ desc.appendChild(renderSlot("description"));
1368
+ body.appendChild(desc);
1369
+ }
1370
+ if (directiveType === "card") {
1371
+ const contentSlot = renderSlot("content") || renderSlot("default");
1372
+ if (contentSlot.childNodes.length > 0) {
1373
+ const contentDiv = document.createElement("div");
1374
+ contentDiv.className = "nr-card__content";
1375
+ contentDiv.appendChild(contentSlot);
1376
+ body.appendChild(contentDiv);
1377
+ }
1378
+ }
1379
+ if (isModal || isLink) {
1380
+ const action = document.createElement("div");
1381
+ action.className = "nr-card__action";
1382
+ if (isLink && url) {
1383
+ const a = document.createElement("a");
1384
+ a.href = url;
1385
+ a.target = target || "_blank";
1386
+ a.rel = "noopener noreferrer";
1387
+ a.className = "nr-card__action-link";
1388
+ a.appendChild(createIcon("open_in_new"));
1389
+ a.appendChild(document.createTextNode(" Link"));
1390
+ action.appendChild(a);
1391
+ } else if (isModal) {
1392
+ const modalBtn = document.createElement("div");
1393
+ modalBtn.className = "nr-card__action-link";
1394
+ modalBtn.appendChild(createIcon("arrow_forward"));
1395
+ modalBtn.appendChild(document.createTextNode(" Abrir"));
1396
+ action.appendChild(modalBtn);
1397
+ }
1398
+ body.appendChild(action);
1399
+ }
1400
+ card.appendChild(body);
1401
+ if (isModal) {
1402
+ const dialog = createModal(title || "Detalles");
1403
+ const modalBody = dialog.querySelector(".nr-modal__body");
1404
+ if (modalBody) {
1405
+ const contentSlot = renderSlot("content") || renderSlot("default");
1406
+ modalBody.appendChild(contentSlot);
1407
+ }
1408
+ card.addEventListener("click", () => {
1409
+ if (!dialog.open) {
1410
+ document.body.appendChild(dialog);
1411
+ dialog.showModal();
1412
+ dialog.addEventListener("close", () => dialog.remove(), { once: true });
1413
+ }
1414
+ });
1415
+ const frag = document.createDocumentFragment();
1416
+ frag.appendChild(card);
1417
+ frag.appendChild(dialog);
1418
+ return frag;
1419
+ }
1420
+ if (isLink && url) {
1421
+ card.addEventListener("click", () => window.open(url, target || "_blank"));
1422
+ }
1423
+ return card;
1424
+ };
1425
+ var card_default = cardDirective;
1426
+
1427
+ // vanilla/directives/wrapper.ts
1428
+ var wrapperDirective = ({ props, renderSlot }) => {
1429
+ const el = document.createElement("div");
1430
+ el.className = "nr-wrapper";
1431
+ if (props.class) el.classList.add(...props.class.split(/\s+/).filter(Boolean));
1432
+ if (props.id) el.id = props.id;
1433
+ if (props.style) {
1434
+ const styles = parseCssString(props.style);
1435
+ for (const [key, value] of Object.entries(styles)) {
1436
+ el.style.setProperty(key, String(value));
1437
+ }
1438
+ }
1348
1439
  for (const [key, value] of Object.entries(props)) {
1349
1440
  if (key.startsWith("data-")) {
1350
- wrapperProps[key] = value;
1441
+ el.setAttribute(key, value);
1351
1442
  }
1352
1443
  }
1353
- return /* @__PURE__ */ jsx8("div", { ...wrapperProps, children: renderSlot("default") });
1444
+ el.appendChild(renderSlot("default"));
1445
+ return el;
1354
1446
  };
1355
- var WrapperDirective_default = WrapperDirective;
1447
+ var wrapper_default = wrapperDirective;
1356
1448
 
1357
- // react/directives/SlideDirective.tsx
1358
- import { useState as useState3, useEffect as useEffect2, useCallback, useRef as useRef2, useLayoutEffect } from "react";
1359
- import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
1449
+ // vanilla/directives/slide.ts
1360
1450
  var slideCounter = 0;
1361
- var SlideDirective = ({
1451
+ var slideDirective = ({
1362
1452
  props,
1363
- context,
1364
- slots
1453
+ slots,
1454
+ renderInline: renderInline2,
1455
+ renderMarkdown
1365
1456
  }) => {
1366
1457
  const rawContent = slots.default || "";
1367
1458
  const lines = rawContent.split("\n").map((l) => l.trim()).filter(Boolean);
1368
- const elements = lines.map((line) => context.parseMarkdown(line));
1369
- const [current, setCurrent] = useState3(0);
1459
+ if (lines.length === 0) {
1460
+ return document.createDocumentFragment();
1461
+ }
1370
1462
  const interval = parseInt(props.interval || "3000", 10);
1371
1463
  const speed = parseInt(props.speed || "500", 10);
1372
- const elRefs = useRef2([]);
1373
- const [maxH, setMaxH] = useState3(0);
1374
- useLayoutEffect(() => {
1375
- let h = 0;
1376
- elRefs.current.forEach((el) => {
1377
- if (el) h = Math.max(h, el.offsetHeight);
1378
- });
1379
- if (h > 0) setMaxH(h);
1380
- }, [elements]);
1381
- const cycle = useCallback(() => {
1382
- if (elements.length <= 1) return;
1383
- setCurrent((prev) => (prev + 1) % elements.length);
1384
- }, [elements.length]);
1385
- useEffect2(() => {
1386
- if (elements.length <= 1) return;
1387
- const id = setInterval(cycle, interval);
1388
- return () => clearInterval(id);
1389
- }, [cycle, interval, elements.length]);
1390
- if (elements.length === 0) return null;
1391
1464
  const rawClass = props.class || "";
1392
1465
  const inlineStyle = props.style ? parseCssString(props.style) : {};
1393
- const textSizeMap = {
1394
- "text-xs": "0.75rem",
1395
- "text-sm": "0.875rem",
1396
- "text-base": "1rem",
1397
- "text-lg": "1.125rem",
1398
- "text-xl": "1.25rem",
1399
- "text-2xl": "1.5rem",
1400
- "text-3xl": "1.875rem",
1401
- "text-4xl": "2.25rem",
1402
- "text-5xl": "3rem",
1403
- "text-6xl": "3.75rem",
1404
- "text-7xl": "4.5rem",
1405
- "text-8xl": "6rem",
1406
- "text-9xl": "8rem"
1407
- };
1408
- const textSizeMatch = rawClass.match(/\btext-(xs|sm|base|lg|xl|[2-9]xl)\b/);
1409
- const forcedFontSize = textSizeMatch ? textSizeMap[textSizeMatch[0]] : null;
1410
1466
  const scopeClass = `sld-${++slideCounter}`;
1411
- const className = textSizeMatch ? rawClass.replace(textSizeMatch[0], "").replace(/\s+/g, " ").trim() : rawClass;
1412
- return /* @__PURE__ */ jsxs6(
1413
- "div",
1414
- {
1415
- className: "not-prose",
1416
- style: { height: maxH || "auto", position: "relative", overflow: "hidden", ...inlineStyle },
1417
- children: [
1418
- forcedFontSize && /* @__PURE__ */ jsx9("style", { children: `.${scopeClass} * { font-size: ${forcedFontSize} !important; line-height: normal !important; }` }),
1419
- /* @__PURE__ */ jsx9(
1420
- "div",
1421
- {
1422
- style: {
1423
- position: "absolute",
1424
- left: 0,
1425
- right: 0,
1426
- top: 0,
1427
- transition: `transform ${speed}ms cubic-bezier(0.16, 1, 0.3, 1)`,
1428
- transform: `translateY(${-current * maxH}px)`
1429
- },
1430
- children: elements.map((tokens, i) => /* @__PURE__ */ jsx9(
1431
- "div",
1432
- {
1433
- ref: (el) => {
1434
- elRefs.current[i] = el;
1435
- },
1436
- style: maxH ? { height: maxH, display: "flex", alignItems: "center", overflow: "hidden" } : { display: "flex", alignItems: "center" },
1437
- children: /* @__PURE__ */ jsx9("div", { className: `${scopeClass} ${className}`, style: { width: "100%" }, children: context.processAndRenderElements(tokens) })
1438
- },
1439
- i
1440
- ))
1441
- }
1442
- )
1443
- ]
1467
+ const container = document.createElement("div");
1468
+ container.className = "nr-slide";
1469
+ Object.assign(container.style, {
1470
+ position: "relative",
1471
+ overflow: "hidden",
1472
+ ...inlineStyle
1473
+ });
1474
+ const track = document.createElement("div");
1475
+ track.className = "nr-slide__track";
1476
+ track.style.transition = `transform ${speed}ms cubic-bezier(0.16, 1, 0.3, 1)`;
1477
+ const slideEls = [];
1478
+ for (const line of lines) {
1479
+ const slideEl = document.createElement("div");
1480
+ slideEl.className = `nr-slide__item ${scopeClass} ${rawClass}`.trim();
1481
+ slideEl.style.display = "flex";
1482
+ slideEl.style.alignItems = "center";
1483
+ if (renderMarkdown) {
1484
+ const tokens = renderMarkdown(line);
1485
+ slideEl.appendChild(tokens);
1486
+ } else if (renderInline2) {
1487
+ slideEl.appendChild(renderInline2(line));
1488
+ }
1489
+ track.appendChild(slideEl);
1490
+ slideEls.push(slideEl);
1491
+ }
1492
+ container.appendChild(track);
1493
+ let current = 0;
1494
+ let maxH = 0;
1495
+ const measureAndSetHeight = () => {
1496
+ maxH = 0;
1497
+ for (const el of slideEls) {
1498
+ maxH = Math.max(maxH, el.offsetHeight);
1499
+ }
1500
+ if (maxH > 0) {
1501
+ container.style.height = `${maxH}px`;
1502
+ for (const el of slideEls) {
1503
+ el.style.height = `${maxH}px`;
1504
+ }
1444
1505
  }
1445
- );
1506
+ };
1507
+ requestAnimationFrame(() => {
1508
+ measureAndSetHeight();
1509
+ if (document.fonts?.ready) {
1510
+ document.fonts.ready.then(measureAndSetHeight);
1511
+ }
1512
+ });
1513
+ if (lines.length > 1) {
1514
+ setInterval(() => {
1515
+ current = (current + 1) % lines.length;
1516
+ track.style.transform = `translateY(${-current * maxH}px)`;
1517
+ }, interval);
1518
+ }
1519
+ return container;
1446
1520
  };
1447
- var SlideDirective_default = SlideDirective;
1521
+ var slide_default = slideDirective;
1448
1522
 
1449
- // react/directives/index.ts
1523
+ // vanilla/directives/index.ts
1450
1524
  var directiveRegistry = {
1451
1525
  // Admonitions
1452
- note: AdmonitionDirective_default,
1453
- info: AdmonitionDirective_default,
1454
- warning: AdmonitionDirective_default,
1455
- danger: AdmonitionDirective_default,
1456
- greentext: AdmonitionDirective_default,
1526
+ note: admonition_default,
1527
+ info: admonition_default,
1528
+ warning: admonition_default,
1529
+ danger: admonition_default,
1530
+ greentext: admonition_default,
1457
1531
  // Cards
1458
- card: CardDirective_default,
1459
- "card-m": CardDirective_default,
1460
- "card-b": CardDirective_default,
1532
+ card: card_default,
1533
+ "card-m": card_default,
1534
+ "card-b": card_default,
1461
1535
  // Interactive
1462
- details: DetailsDirective_default,
1463
- modal: ModalDirective_default,
1464
- button: ButtonDirective_default,
1536
+ details: details_default,
1537
+ modal: modal_default,
1538
+ button: button_default,
1465
1539
  // Layout / generic wrappers
1466
- div: WrapperDirective_default,
1467
- style: WrapperDirective_default,
1468
- custom: WrapperDirective_default,
1469
- raw: WrapperDirective_default,
1540
+ div: wrapper_default,
1541
+ style: wrapper_default,
1542
+ custom: wrapper_default,
1543
+ raw: wrapper_default,
1470
1544
  // Animation
1471
- slide: SlideDirective_default
1545
+ slide: slide_default
1472
1546
  };
1473
1547
  var directives_default = directiveRegistry;
1474
1548
 
1475
- // react/DirectiveRenderer.tsx
1476
- import { jsx as jsx10 } from "react/jsx-runtime";
1477
- var DirectiveRenderer = ({
1478
- element,
1479
- context,
1480
- index,
1481
- allElements
1482
- }) => {
1549
+ // vanilla/renderer.ts
1550
+ function renderTokens(tokens) {
1551
+ const article = document.createElement("article");
1552
+ article.className = "nr-prose";
1553
+ const ctx = {
1554
+ parseMarkdown,
1555
+ renderElements: (tks) => renderTokensInner(tks, ctx),
1556
+ renderInline,
1557
+ renderMarkdown: (md) => renderTokensInner(parseMarkdown(md), ctx)
1558
+ };
1559
+ article.appendChild(processElements(tokens, ctx, tokens));
1560
+ return article;
1561
+ }
1562
+ function renderMarkdownString(markdown2) {
1563
+ const tokens = parseMarkdown(markdown2);
1564
+ return renderTokens(tokens);
1565
+ }
1566
+ function renderHtmlString(html) {
1567
+ let processedContent = html;
1568
+ processedContent = processedContent.replace(
1569
+ /<style(?:\s+[^>]*)?>([\s\S]*?)<\/style>/gi,
1570
+ (_match, cssContent) => {
1571
+ const styleEl = document.createElement("style");
1572
+ styleEl.setAttribute("data-nr-global", "");
1573
+ styleEl.textContent = cssContent;
1574
+ document.head.appendChild(styleEl);
1575
+ return "";
1576
+ }
1577
+ );
1578
+ const wrapper = document.createElement("div");
1579
+ wrapper.className = "nr-raw-html";
1580
+ wrapper.innerHTML = processedContent;
1581
+ const scripts = wrapper.querySelectorAll("script");
1582
+ scripts.forEach((oldScript) => {
1583
+ const newScript = document.createElement("script");
1584
+ Array.from(oldScript.attributes).forEach(
1585
+ (attr) => newScript.setAttribute(attr.name, attr.value)
1586
+ );
1587
+ newScript.textContent = oldScript.textContent;
1588
+ oldScript.parentNode?.replaceChild(newScript, oldScript);
1589
+ });
1590
+ return wrapper;
1591
+ }
1592
+ function renderTokensInner(tokens, ctx) {
1593
+ const container = document.createElement("div");
1594
+ container.appendChild(processElements(tokens, ctx, tokens));
1595
+ return container;
1596
+ }
1597
+ function processElements(elements, ctx, allElements) {
1598
+ const fragment = document.createDocumentFragment();
1599
+ let i = 0;
1600
+ while (i < elements.length) {
1601
+ const el = elements[i];
1602
+ if (el.type === "directive" && ["card", "card-m", "card-b"].includes(el.directiveType)) {
1603
+ const cards = [];
1604
+ while (i < elements.length && elements[i].type === "directive" && ["card", "card-m", "card-b"].includes(elements[i].directiveType)) {
1605
+ cards.push(elements[i]);
1606
+ i++;
1607
+ }
1608
+ if (cards.length === 1 || cards[0].props?.batch === "off") {
1609
+ for (const card of cards) {
1610
+ const rendered = renderElement(card, ctx, allElements);
1611
+ if (rendered) fragment.appendChild(rendered);
1612
+ }
1613
+ } else {
1614
+ const grid = document.createElement("div");
1615
+ grid.className = "nr-card-grid";
1616
+ for (const card of cards) {
1617
+ const rendered = renderElement(card, ctx, allElements);
1618
+ if (rendered) grid.appendChild(rendered);
1619
+ }
1620
+ fragment.appendChild(grid);
1621
+ }
1622
+ } else {
1623
+ const rendered = renderElement(el, ctx, allElements);
1624
+ if (rendered) fragment.appendChild(rendered);
1625
+ i++;
1626
+ }
1627
+ }
1628
+ return fragment;
1629
+ }
1630
+ function renderElement(element, ctx, allElements) {
1631
+ switch (element.type) {
1632
+ case "header": {
1633
+ const tag = `h${element.level}`;
1634
+ let text = element.text;
1635
+ const alignCenter = text.match(/^->\s*(.+?)\s*<-\s*$/);
1636
+ const alignRight = text.match(/^->\s*(.+?)\s*->\s*$/);
1637
+ if (alignCenter) text = alignCenter[1];
1638
+ else if (alignRight) text = alignRight[1];
1639
+ const h = document.createElement(tag);
1640
+ h.id = element.id;
1641
+ let cls = `md-h${element.level}`;
1642
+ if (alignCenter) cls += " text-center";
1643
+ if (alignRight) cls += " text-right";
1644
+ if (element.classes) cls += ` ${element.classes}`;
1645
+ h.className = cls;
1646
+ h.appendChild(renderInline(text));
1647
+ return h;
1648
+ }
1649
+ case "paragraph": {
1650
+ const p = document.createElement("p");
1651
+ let cls = "md-p";
1652
+ if (element.classes) cls += ` ${element.classes}`;
1653
+ if (element.align) cls += ` text-${element.align}`;
1654
+ p.className = cls;
1655
+ if (element.id) p.id = element.id;
1656
+ const lines = element.content.split("\n");
1657
+ for (let li = 0; li < lines.length; li++) {
1658
+ const line = lines[li];
1659
+ const hardBreakMatch = line.match(/^(.*?)(\s{2,})$/);
1660
+ if (hardBreakMatch) {
1661
+ p.appendChild(renderInline(hardBreakMatch[1]));
1662
+ p.appendChild(document.createElement("br"));
1663
+ } else {
1664
+ p.appendChild(renderInline(line));
1665
+ if (li < lines.length - 1) {
1666
+ p.appendChild(document.createTextNode(" "));
1667
+ }
1668
+ }
1669
+ }
1670
+ return p;
1671
+ }
1672
+ case "codeblock":
1673
+ return createCodeBlock(element.content, element.language, element.title);
1674
+ case "directive":
1675
+ return renderDirective(element, ctx, allElements);
1676
+ case "html": {
1677
+ const el = element;
1678
+ return renderHtmlString(el.content);
1679
+ }
1680
+ case "html-block": {
1681
+ const htmlBlock = element;
1682
+ const rawProps = parseHtmlAttrs(htmlBlock.attrs);
1683
+ const el = document.createElement(htmlBlock.tag);
1684
+ for (const [key, value] of Object.entries(rawProps)) {
1685
+ if (key === "style" && typeof value === "object") {
1686
+ for (const [prop, val] of Object.entries(value)) {
1687
+ el.style.setProperty(prop, String(val));
1688
+ }
1689
+ } else if (value === true) {
1690
+ el.setAttribute(key, "");
1691
+ } else {
1692
+ el.setAttribute(key, String(value));
1693
+ }
1694
+ }
1695
+ const childFrag = processElements(htmlBlock.children, ctx, allElements);
1696
+ el.appendChild(childFrag);
1697
+ return el;
1698
+ }
1699
+ case "image": {
1700
+ const img = document.createElement("img");
1701
+ img.src = element.src;
1702
+ img.alt = element.alt;
1703
+ img.className = "nr-image";
1704
+ if (element.style) {
1705
+ for (const [key, value] of Object.entries(element.style)) {
1706
+ img.style.setProperty(key, String(value));
1707
+ }
1708
+ }
1709
+ return img;
1710
+ }
1711
+ case "table":
1712
+ return createTable(element.content, renderInline);
1713
+ case "list":
1714
+ return createList(element.content, renderInline);
1715
+ case "blockquote":
1716
+ return createBlockquote(element.content, element.classes, renderInline);
1717
+ case "hr": {
1718
+ const hr = document.createElement("hr");
1719
+ hr.className = "nr-hr";
1720
+ return hr;
1721
+ }
1722
+ case "toc": {
1723
+ const headers = allElements.filter((e) => e.type === "header");
1724
+ return createTOC(headers.map((h) => ({ level: h.level, text: h.text, id: h.id })), renderInline);
1725
+ }
1726
+ default:
1727
+ return null;
1728
+ }
1729
+ }
1730
+ function renderDirective(element, ctx, allElements) {
1483
1731
  const { directiveType, props, slots, scopeId } = element;
1484
- const Component = directives_default[directiveType];
1732
+ const renderer = directives_default[directiveType];
1485
1733
  const renderSlot = (name) => {
1734
+ const frag = document.createDocumentFragment();
1486
1735
  const slotContent = slots[name];
1487
- if (!slotContent) return null;
1488
- const parsed = context.parseMarkdown(slotContent);
1489
- return context.processAndRenderElements(parsed);
1736
+ if (!slotContent) return frag;
1737
+ const tokens = ctx.parseMarkdown(slotContent);
1738
+ frag.appendChild(ctx.renderElements(tokens));
1739
+ return frag;
1490
1740
  };
1491
1741
  const directiveProps = {
1492
1742
  directiveType,
1493
1743
  props,
1494
1744
  slots,
1495
1745
  renderSlot,
1496
- context,
1497
- index,
1498
- allElements
1746
+ context: ctx,
1747
+ index: 0,
1748
+ allElements,
1749
+ renderInline,
1750
+ renderMarkdown: ctx.renderMarkdown
1499
1751
  };
1500
- if (Component) {
1501
- return /* @__PURE__ */ jsx10(Component, { ...directiveProps }, index);
1752
+ if (renderer) {
1753
+ return renderer(directiveProps);
1502
1754
  }
1503
- return /* @__PURE__ */ jsx10("div", { className: `my-4 p-4 rounded-2xl border border-border bg-background-primary/5`, children: renderSlot("default") }, index);
1504
- };
1505
- var DirectiveRenderer_default = DirectiveRenderer;
1506
-
1507
- // react/RawHtmlRenderer.tsx
1508
- import { useRef as useRef4, useEffect as useEffect4 } from "react";
1509
-
1510
- // react/useTailwindCDN.ts
1511
- import { useEffect as useEffect3, useRef as useRef3 } from "react";
1512
- function scanTailwindCDN() {
1513
- const tw = window.tailwind;
1514
- if (tw?.scan) tw.scan();
1755
+ const fallback = document.createElement("div");
1756
+ fallback.className = "nr-unknown-directive";
1757
+ fallback.appendChild(renderSlot("default"));
1758
+ return fallback;
1515
1759
  }
1516
1760
 
1517
- // react/RawHtmlRenderer.tsx
1518
- import { jsx as jsx11 } from "react/jsx-runtime";
1519
- var RawHtmlRenderer = ({
1520
- content,
1521
- globalStyles,
1522
- wrapperClassName
1523
- }) => {
1524
- const containerRef = useRef4(null);
1525
- useEffect4(() => {
1526
- if (!containerRef.current) return;
1527
- const scripts = containerRef.current.querySelectorAll("script");
1528
- scripts.forEach((oldScript) => {
1529
- const newScript = document.createElement("script");
1530
- Array.from(oldScript.attributes).forEach(
1531
- (attr) => newScript.setAttribute(attr.name, attr.value)
1532
- );
1533
- newScript.textContent = oldScript.textContent;
1534
- oldScript.parentNode?.replaceChild(newScript, oldScript);
1535
- });
1536
- scanTailwindCDN();
1537
- }, [content]);
1538
- useEffect4(() => {
1539
- if (!globalStyles) return;
1540
- const styleEl = document.createElement("style");
1541
- styleEl.setAttribute("data-global", "");
1542
- styleEl.textContent = globalStyles;
1543
- document.head.appendChild(styleEl);
1544
- return () => {
1545
- if (styleEl.parentNode) document.head.removeChild(styleEl);
1546
- };
1547
- }, [globalStyles]);
1548
- return /* @__PURE__ */ jsx11("div", { className: wrapperClassName, ref: containerRef, children: /* @__PURE__ */ jsx11("div", { dangerouslySetInnerHTML: { __html: content } }) });
1549
- };
1550
- var RawHtmlRenderer_default = RawHtmlRenderer;
1551
-
1552
- // react/context.tsx
1553
- import { createContext, useContext } from "react";
1554
- var RenderCtx = createContext(null);
1555
- var RenderContextProvider = RenderCtx.Provider;
1556
-
1557
1761
  // react/CustomMarkdownRenderer.tsx
1558
- import { jsx as jsx12, jsxs as jsxs7 } from "react/jsx-runtime";
1559
- var CustomMarkdownRenderer = ({ content: initialContent }) => {
1560
- const [modals, setModals] = useState4({});
1561
- const baseId = useId3().replace(/:/g, "");
1562
- const articleClass = `scope-${baseId}`;
1563
- const contextRef = useRef5(null);
1564
- resetScopeCounter();
1565
- const allElements = useMemo(() => parseMarkdown(initialContent), [initialContent]);
1566
- useEffect5(() => {
1762
+ import { jsx } from "react/jsx-runtime";
1763
+ var CustomMarkdownRenderer = ({ content }) => {
1764
+ const containerRef = useRef2(null);
1765
+ useEffect3(() => {
1766
+ const container = containerRef.current;
1767
+ if (!container) return;
1768
+ container.replaceChildren();
1769
+ container.appendChild(renderMarkdownString(content));
1770
+ scanTailwindCDN();
1567
1771
  const handleHashChange = () => {
1568
1772
  const hash = window.location.hash;
1569
1773
  if (hash) {
1570
1774
  const parts = hash.split("#");
1571
- const id = parts[parts.length - 1];
1572
- scrollToId(id);
1775
+ scrollToId(parts[parts.length - 1]);
1573
1776
  }
1574
1777
  };
1575
1778
  handleHashChange();
1576
1779
  window.addEventListener("hashchange", handleHashChange);
1577
1780
  return () => window.removeEventListener("hashchange", handleHashChange);
1578
- }, [initialContent]);
1579
- const renderElement = useCallback2(
1580
- (element, index, _depth = 0) => {
1581
- switch (element.type) {
1582
- case "header": {
1583
- const HeaderTag = `h${element.level}`;
1584
- let text = element.text;
1585
- const alignCenter = text.match(/^->\s*(.+?)\s*<-\s*$/);
1586
- const alignRight = text.match(/^->\s*(.+?)\s*->\s*$/);
1587
- if (alignCenter) {
1588
- text = alignCenter[1];
1589
- } else if (alignRight) {
1590
- text = alignRight[1];
1591
- }
1592
- const userClasses = element.classes || "";
1593
- let headerClasses = `md-h${element.level}`;
1594
- if (alignCenter) headerClasses += " text-center";
1595
- if (alignRight) headerClasses += " text-right";
1596
- if (userClasses) headerClasses += ` ${userClasses}`;
1597
- return React8.createElement(
1598
- HeaderTag,
1599
- { key: index, id: element.id, className: headerClasses },
1600
- renderInline(text)
1601
- );
1602
- }
1603
- case "paragraph": {
1604
- const lines = element.content.split("\n");
1605
- const processedContent = lines.map((line, lineIndex) => {
1606
- const hardBreakMatch = line.match(/^(.*?)(\s{2,})$/);
1607
- if (hardBreakMatch) {
1608
- return /* @__PURE__ */ jsxs7(React8.Fragment, { children: [
1609
- renderInline(hardBreakMatch[1]),
1610
- /* @__PURE__ */ jsx12("br", {})
1611
- ] }, lineIndex);
1612
- }
1613
- const isLastLine = lineIndex === lines.length - 1;
1614
- return /* @__PURE__ */ jsxs7(React8.Fragment, { children: [
1615
- renderInline(line),
1616
- !isLastLine && " "
1617
- ] }, lineIndex);
1618
- });
1619
- const pUserClasses = element.classes || "";
1620
- let pClasses = "md-p";
1621
- if (pUserClasses) pClasses += ` ${pUserClasses}`;
1622
- if (element.align) pClasses += ` text-${element.align}`;
1623
- return /* @__PURE__ */ jsx12("p", { id: element.id, className: pClasses, children: processedContent }, index);
1624
- }
1625
- case "codeblock":
1626
- return /* @__PURE__ */ jsx12(
1627
- CodeBlock,
1628
- {
1629
- code: element.content,
1630
- language: element.language,
1631
- title: element.title
1632
- },
1633
- index
1634
- );
1635
- case "directive":
1636
- return /* @__PURE__ */ jsx12(
1637
- DirectiveRenderer_default,
1638
- {
1639
- element,
1640
- context: contextRef.current,
1641
- index,
1642
- allElements
1643
- },
1644
- index
1645
- );
1646
- case "html": {
1647
- let processedContent = element.content;
1648
- let globalStyles = "";
1649
- processedContent = processedContent.replace(
1650
- /<style(?:\s+[^>]*)?>([\s\S]*?)<\/style>/gi,
1651
- (_match, cssContent) => {
1652
- globalStyles += cssContent + "\n";
1653
- return "";
1654
- }
1655
- );
1656
- const wrapperClassName = "w-full my-4";
1657
- return /* @__PURE__ */ jsx12(
1658
- RawHtmlRenderer_default,
1659
- {
1660
- content: processedContent,
1661
- globalStyles: globalStyles || void 0,
1662
- wrapperClassName
1663
- },
1664
- index
1665
- );
1666
- }
1667
- case "html-block": {
1668
- const htmlBlock = element;
1669
- const rawProps = parseHtmlAttrs(htmlBlock.attrs);
1670
- const props = {};
1671
- for (const [key, value] of Object.entries(rawProps)) {
1672
- if (key === "class") props["className"] = value;
1673
- else if (key === "for") props["htmlFor"] = value;
1674
- else if (key === "tabindex") props["tabIndex"] = value;
1675
- else props[key] = value;
1676
- }
1677
- return React8.createElement(
1678
- htmlBlock.tag,
1679
- { key: index, ...props },
1680
- ...processAndRenderElements(htmlBlock.children, _depth + 1)
1681
- );
1682
- }
1683
- case "image":
1684
- return /* @__PURE__ */ jsx12(
1685
- "img",
1686
- {
1687
- alt: element.alt,
1688
- src: element.src,
1689
- style: element.style,
1690
- className: "max-w-full h-auto"
1691
- },
1692
- index
1693
- );
1694
- case "table":
1695
- return /* @__PURE__ */ jsx12("div", { children: renderTable(element.content) }, index);
1696
- case "list":
1697
- return /* @__PURE__ */ jsx12("div", { children: renderList(element.content) }, index);
1698
- case "blockquote":
1699
- return /* @__PURE__ */ jsx12("blockquote", { className: `border-l-4 border-accent-primary/30 pl-4 italic text-text-secondary my-4 text-sm sm:text-base${element.classes ? ` ${element.classes}` : ""}`, children: renderInline(element.content) }, index);
1700
- case "hr":
1701
- return /* @__PURE__ */ jsx12("hr", { className: "my-8 border-border" }, index);
1702
- case "toc":
1703
- return /* @__PURE__ */ jsx12("div", { children: generateToc(allElements) }, index);
1704
- default:
1705
- return null;
1706
- }
1707
- },
1708
- [allElements]
1709
- );
1710
- const processAndRenderElements = useCallback2(
1711
- (elements, depth = 0) => {
1712
- const result = [];
1713
- let i = 0;
1714
- while (i < elements.length) {
1715
- const el = elements[i];
1716
- if (el.type === "directive" && ["card", "card-m", "card-b"].includes(el.directiveType)) {
1717
- const cards = [];
1718
- while (i < elements.length && elements[i].type === "directive" && ["card", "card-m", "card-b"].includes(elements[i].directiveType)) {
1719
- cards.push(elements[i]);
1720
- i++;
1721
- }
1722
- if (cards.length === 1 || cards[0].props?.batch === "off") {
1723
- for (let c = 0; c < cards.length; c++) {
1724
- result.push(renderElement(cards[c], result.length, depth));
1725
- }
1726
- } else {
1727
- const firstCardClass = cards[0].props?.["class"] || "";
1728
- const justifyClasses = firstCardClass.match(/\bjustify-\S+/g) || [];
1729
- const wrapperJustify = justifyClasses.length > 0 ? justifyClasses.join(" ") : "";
1730
- result.push(
1731
- /* @__PURE__ */ jsx12("div", { className: `not-prose flex flex-wrap gap-6 my-6 ${wrapperJustify}`, children: cards.map((card, ci) => /* @__PURE__ */ jsx12(React8.Fragment, { children: renderElement(card, ci, depth) }, ci)) }, `card-grid-${result.length}`)
1732
- );
1733
- }
1734
- } else {
1735
- result.push(renderElement(el, result.length, depth));
1736
- i++;
1737
- }
1738
- }
1739
- return result;
1740
- },
1741
- [renderElement]
1742
- );
1743
- const generateToc = (elements) => {
1744
- const headers = extractHeaders(elements);
1745
- if (headers.length === 0) return null;
1746
- return /* @__PURE__ */ jsxs7("nav", { className: "not-prose my-6 p-4 rounded-2xl border border-border bg-background-primary/5", children: [
1747
- /* @__PURE__ */ jsx12("div", { className: "text-base font-bold mb-3", children: "Table of Contents" }),
1748
- /* @__PURE__ */ jsx12("ul", { className: "space-y-1 list-none p-0 m-0", children: headers.map((h, i) => {
1749
- if (h.type !== "header") return null;
1750
- const indentClass = h.level <= 2 ? "pl-0" : h.level === 3 ? "pl-4" : h.level === 4 ? "pl-8" : "pl-12";
1751
- return /* @__PURE__ */ jsx12("li", { className: `${indentClass} text-sm sm:text-base`, children: /* @__PURE__ */ jsx12(
1752
- "a",
1753
- {
1754
- href: `#${h.id}`,
1755
- className: "text-accent-primary hover:text-accent-primary/80 no-underline hover:underline transition-colors",
1756
- onClick: (e) => {
1757
- e.preventDefault();
1758
- scrollToId(h.id);
1759
- },
1760
- children: renderInline(h.text.replace(/->|<-/g, "").trim())
1761
- }
1762
- ) }, i);
1763
- }) })
1764
- ] });
1765
- };
1766
- const contextForDirectives = {
1767
- modals,
1768
- setModals,
1769
- articleClass,
1770
- allElements,
1771
- parseMarkdown,
1772
- renderElement,
1773
- renderInline,
1774
- processAndRenderElements
1775
- };
1776
- contextRef.current = contextForDirectives;
1777
- return /* @__PURE__ */ jsx12(RenderContextProvider, { value: contextForDirectives, children: processAndRenderElements(allElements) });
1781
+ }, [content]);
1782
+ return /* @__PURE__ */ jsx("div", { ref: containerRef });
1778
1783
  };
1779
1784
  var CustomMarkdownRenderer_default = CustomMarkdownRenderer;
1780
1785
 
1781
1786
  // react/NReditor.tsx
1782
- import { jsx as jsx13, jsxs as jsxs8 } from "react/jsx-runtime";
1787
+ import { jsx as jsx2, jsxs } from "react/jsx-runtime";
1783
1788
  var customSyntaxHighlighting = HighlightStyle.define([
1784
1789
  { tag: t2.heading, fontWeight: "bold", color: "var(--tc-heading, #e2e8f0)" },
1785
1790
  { tag: t2.quote, color: "var(--tc-quote, #94a3b8)", fontStyle: "italic" },
@@ -2228,12 +2233,15 @@ var NReditor = ({
2228
2233
  onChange,
2229
2234
  className,
2230
2235
  debounceMs = 300,
2231
- tailwindCDN = false
2236
+ tailwindCDN = false,
2237
+ onGuide,
2238
+ onConfig
2232
2239
  }) => {
2233
- const editorRef = useRef6(null);
2234
- const [isAllFolded, setIsAllFolded] = useState5(false);
2235
- const [editorMode, setEditorMode] = useState5("editor");
2240
+ const editorRef = useRef3(null);
2241
+ const [isAllFolded, setIsAllFolded] = useState2(false);
2242
+ const [editorMode, setEditorMode] = useState2("split");
2236
2243
  const debouncedContent = useDebounce(value, debounceMs);
2244
+ useLazyTailwindCDN(tailwindCDN);
2237
2245
  const handleToggleFold = () => {
2238
2246
  if (!editorRef.current) return;
2239
2247
  if (isAllFolded) {
@@ -2244,7 +2252,7 @@ var NReditor = ({
2244
2252
  setIsAllFolded(true);
2245
2253
  }
2246
2254
  };
2247
- const extensions = React9.useMemo(
2255
+ const extensions = React2.useMemo(
2248
2256
  () => [
2249
2257
  customStreamParserV2,
2250
2258
  lineNumbers(),
@@ -2264,7 +2272,6 @@ var NReditor = ({
2264
2272
  customEditorTheme,
2265
2273
  syntaxHighlighting(customSyntaxHighlighting),
2266
2274
  EditorView.lineWrapping,
2267
- scrollPastEnd(),
2268
2275
  keymap.of([
2269
2276
  { key: "Ctrl-Shift-[", run: foldAll },
2270
2277
  { key: "Ctrl-Shift-]", run: unfoldAll }
@@ -2281,43 +2288,73 @@ var NReditor = ({
2281
2288
  { key: "split", icon: "vertical_split", label: "Split" },
2282
2289
  { key: "preview", icon: "visibility", label: "Preview" }
2283
2290
  ];
2284
- return /* @__PURE__ */ jsxs8("div", { className: `relative flex-1 flex flex-col min-h-0 ${className || ""}`, children: [
2285
- /* @__PURE__ */ jsxs8("div", { className: "flex items-center justify-between px-2 py-1.5 border-b border-border/30 bg-background-secondary-solid/50 rounded-t-2xl shrink-0", children: [
2286
- /* @__PURE__ */ jsx13(
2287
- "button",
2288
- {
2289
- onClick: handleToggleFold,
2290
- className: "p-1 px-2 text-xs font-bold bg-background-secondary-solid border border-border rounded hover:bg-border text-accent-primary transition-colors",
2291
- title: isAllFolded ? "Expand all" : "Collapse all",
2292
- children: isAllFolded ? "\u2569" : "\u2566"
2293
- }
2294
- ),
2295
- /* @__PURE__ */ jsx13("div", { className: "flex items-center gap-0.5 bg-black/10 dark:bg-white/5 rounded-lg p-0.5", children: modeButtons.map((btn) => /* @__PURE__ */ jsxs8(
2296
- "button",
2297
- {
2298
- onClick: () => setEditorMode(btn.key),
2299
- className: `flex items-center gap-1 px-2.5 py-1 text-xs rounded-md transition-colors ${editorMode === btn.key ? "bg-accent-primary/20 text-accent-primary font-semibold" : "text-text-secondary hover:text-text-primary hover:bg-white/5"}`,
2300
- title: btn.label,
2301
- children: [
2302
- /* @__PURE__ */ jsx13("span", { className: "material-symbols-rounded text-sm", children: btn.icon }),
2303
- /* @__PURE__ */ jsx13("span", { className: "hidden sm:inline", children: btn.label })
2304
- ]
2305
- },
2306
- btn.key
2307
- )) })
2291
+ return /* @__PURE__ */ jsxs("div", { className: `nr-editor ${className || ""}`, children: [
2292
+ /* @__PURE__ */ jsxs("div", { className: "nr-editor-toolbar", children: [
2293
+ /* @__PURE__ */ jsxs("div", { className: "nr-editor-toolbar-left", children: [
2294
+ /* @__PURE__ */ jsx2(
2295
+ "button",
2296
+ {
2297
+ onClick: handleToggleFold,
2298
+ className: "nr-toolbar-btn nr-toolbar-btn-fold",
2299
+ title: isAllFolded ? "Expandir todo" : "Colapsar todo",
2300
+ "aria-label": isAllFolded ? "Expandir todo" : "Colapsar todo",
2301
+ children: /* @__PURE__ */ jsx2("span", { className: "material-icons-round", children: isAllFolded ? "unfold_more" : "unfold_less" })
2302
+ }
2303
+ ),
2304
+ /* @__PURE__ */ jsx2("div", { className: "nr-toolbar-divider" }),
2305
+ /* @__PURE__ */ jsx2("div", { className: "nr-toolbar-mode-group", children: modeButtons.map((btn) => /* @__PURE__ */ jsxs(
2306
+ "button",
2307
+ {
2308
+ onClick: () => setEditorMode(btn.key),
2309
+ className: `nr-toolbar-btn nr-toolbar-btn-mode ${editorMode === btn.key ? "nr-toolbar-btn-mode--active" : ""} ${btn.key === "split" ? "nr-toolbar-btn-split" : ""}`,
2310
+ title: btn.label,
2311
+ children: [
2312
+ /* @__PURE__ */ jsx2("span", { className: "material-icons-round", children: btn.icon }),
2313
+ /* @__PURE__ */ jsx2("span", { className: "nr-toolbar-label", children: btn.label })
2314
+ ]
2315
+ },
2316
+ btn.key
2317
+ )) })
2318
+ ] }),
2319
+ /* @__PURE__ */ jsxs("div", { className: "nr-editor-toolbar-right", children: [
2320
+ onGuide && /* @__PURE__ */ jsxs(
2321
+ "button",
2322
+ {
2323
+ onClick: onGuide,
2324
+ className: "nr-toolbar-btn nr-toolbar-btn-sm nr-toolbar-btn-guide",
2325
+ title: "Gu\xEDa de sintaxis",
2326
+ children: [
2327
+ /* @__PURE__ */ jsx2("span", { className: "material-icons-round", children: "menu_book" }),
2328
+ /* @__PURE__ */ jsx2("span", { className: "nr-toolbar-label", children: "Gu\xEDa" })
2329
+ ]
2330
+ }
2331
+ ),
2332
+ onGuide && onConfig && /* @__PURE__ */ jsx2("div", { className: "nr-toolbar-divider" }),
2333
+ onConfig && /* @__PURE__ */ jsxs(
2334
+ "button",
2335
+ {
2336
+ onClick: onConfig,
2337
+ className: "nr-toolbar-btn nr-toolbar-btn-sm nr-toolbar-btn-config",
2338
+ title: "Configurar tema y metadata",
2339
+ children: [
2340
+ /* @__PURE__ */ jsx2("span", { className: "material-icons-round", children: "tune" }),
2341
+ /* @__PURE__ */ jsx2("span", { className: "nr-toolbar-label", children: "Configurar" })
2342
+ ]
2343
+ }
2344
+ )
2345
+ ] })
2308
2346
  ] }),
2309
- /* @__PURE__ */ jsxs8("div", { className: "flex-1 min-h-0 flex", children: [
2310
- (editorMode === "editor" || editorMode === "split") && /* @__PURE__ */ jsx13(
2347
+ /* @__PURE__ */ jsxs("div", { className: "nr-editor-body", children: [
2348
+ (editorMode === "editor" || editorMode === "split") && /* @__PURE__ */ jsx2(
2311
2349
  "div",
2312
2350
  {
2313
- className: `${editorMode === "split" ? "w-1/2 border-r border-border/30" : "w-full"} flex-1 flex flex-col min-h-0 min-w-0`,
2314
- children: /* @__PURE__ */ jsx13(
2351
+ className: `nr-editor-pane ${editorMode === "split" ? "nr-editor-pane--half" : ""}`,
2352
+ children: /* @__PURE__ */ jsx2(
2315
2353
  CodeMirror,
2316
2354
  {
2317
2355
  value,
2318
2356
  onChange,
2319
- className: "flex-1 min-h-0 min-w-0",
2320
- height: "100%",
2357
+ height: "auto",
2321
2358
  onCreateEditor: (view) => {
2322
2359
  editorRef.current = view;
2323
2360
  },
@@ -2330,11 +2367,11 @@ var NReditor = ({
2330
2367
  )
2331
2368
  }
2332
2369
  ),
2333
- (editorMode === "preview" || editorMode === "split") && /* @__PURE__ */ jsx13(
2370
+ (editorMode === "preview" || editorMode === "split") && /* @__PURE__ */ jsx2(
2334
2371
  "div",
2335
2372
  {
2336
- className: `${editorMode === "split" ? "w-1/2" : "w-full"} flex-1 min-h-0 overflow-auto min-w-0`,
2337
- children: /* @__PURE__ */ jsx13("div", { className: "nr-prose h-full shadow-xs overflow-auto p-4", children: /* @__PURE__ */ jsx13(CustomMarkdownRenderer_default, { content: debouncedContent }) })
2373
+ className: `nr-editor-preview ${editorMode === "split" ? "nr-editor-preview--half" : ""}`,
2374
+ children: /* @__PURE__ */ jsx2("div", { className: "nr-editor-prose", children: /* @__PURE__ */ jsx2("div", { className: "nr-prose", children: /* @__PURE__ */ jsx2(CustomMarkdownRenderer_default, { content: debouncedContent }) }) })
2338
2375
  }
2339
2376
  )
2340
2377
  ] })