@noirmd/previewer 1.2.0 → 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 +851 -895
  2. package/dist/NReditor.cjs.map +1 -1
  3. package/dist/NReditor.d.cts +1 -1
  4. package/dist/NReditor.d.ts +1 -1
  5. package/dist/NReditor.js +852 -896
  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 +56 -9
  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 +56 -9
  52. package/package.json +5 -10
  53. package/markdown.css +0 -344
package/dist/vue.cjs CHANGED
@@ -1572,14 +1572,9 @@ var require_core = __commonJS({
1572
1572
  // vue.ts
1573
1573
  var vue_exports = {};
1574
1574
  __export(vue_exports, {
1575
- Admonition: () => Admonition,
1576
- CodeBlock: () => CodeBlock,
1577
1575
  CustomMarkdownRenderer: () => CustomMarkdownRenderer_default,
1578
- Details: () => Details,
1579
- IconRenderer: () => IconRenderer,
1580
- Modal: () => Modal,
1581
1576
  NRpreviewer: () => NRpreviewer_default,
1582
- extractHeaders: () => extractHeaders,
1577
+ RawHtmlRenderer: () => RawHtmlRenderer_default,
1583
1578
  parseMarkdown: () => parseMarkdown,
1584
1579
  preloadTailwindCDN: () => preloadTailwindCDN,
1585
1580
  scanTailwindCDN: () => scanTailwindCDN,
@@ -1588,10 +1583,10 @@ __export(vue_exports, {
1588
1583
  module.exports = __toCommonJS(vue_exports);
1589
1584
 
1590
1585
  // vue/NRpreviewer.ts
1591
- var import_vue15 = require("vue");
1586
+ var import_vue4 = require("vue");
1592
1587
 
1593
1588
  // vue/CustomMarkdownRenderer.ts
1594
- var import_vue14 = require("vue");
1589
+ var import_vue2 = require("vue");
1595
1590
 
1596
1591
  // core/utils.ts
1597
1592
  function parseCssString(cssText) {
@@ -1637,9 +1632,6 @@ function extractAttributes(text) {
1637
1632
  return { text: cleanedText, classes: classList.join(" "), id };
1638
1633
  }
1639
1634
  var _scopeCounter = 0;
1640
- function resetScopeCounter() {
1641
- _scopeCounter = 0;
1642
- }
1643
1635
  function generateScopeId() {
1644
1636
  return `scope-${++_scopeCounter}`;
1645
1637
  }
@@ -1687,6 +1679,7 @@ function parseMarkdown(markdown2) {
1687
1679
  if (!markdown2) return [];
1688
1680
  const lines = markdown2.replace(/\r\n/g, "\n").replace(/\r/g, "").split("\n");
1689
1681
  const result = [];
1682
+ const usedIds = /* @__PURE__ */ new Set();
1690
1683
  let i = 0;
1691
1684
  while (i < lines.length) {
1692
1685
  const line = lines[i];
@@ -1696,7 +1689,14 @@ function parseMarkdown(markdown2) {
1696
1689
  const level = match[1].length;
1697
1690
  const rawText = match[2];
1698
1691
  const { text: text2, classes: classes2, id: customId } = extractAttributes(rawText);
1699
- const id2 = customId || generateId(text2.replace(/->|<-/g, ""));
1692
+ const baseId = customId || generateId(text2.replace(/->|<-/g, ""));
1693
+ let id2 = baseId;
1694
+ let n = 1;
1695
+ while (usedIds.has(id2)) {
1696
+ n++;
1697
+ id2 = `${baseId}-${n}`;
1698
+ }
1699
+ usedIds.add(id2);
1700
1700
  result.push({ type: "header", level, text: text2, id: id2, classes: classes2 || void 0 });
1701
1701
  i++;
1702
1702
  continue;
@@ -2011,156 +2011,6 @@ function splitSlots(rawContent) {
2011
2011
  return slots;
2012
2012
  }
2013
2013
 
2014
- // vue/renderers.ts
2015
- var import_vue = require("vue");
2016
- function renderInline(text) {
2017
- if (!text) return [];
2018
- const parsePart = (part, key) => {
2019
- let match2;
2020
- if (match2 = part.match(/^\|\[([^\]]+)\]\|$/)) {
2021
- return (0, import_vue.h)("span", {
2022
- class: "nr-icon material-symbols-rounded",
2023
- "aria-hidden": "true",
2024
- innerHTML: /^[eE][0-9a-fA-F]{3,4}$/.test(match2[1]) ? `&#x${match2[1]};` : void 0,
2025
- key
2026
- }, /^[eE][0-9a-fA-F]{3,4}$/.test(match2[1]) ? void 0 : match2[1]);
2027
- }
2028
- if (match2 = part.match(/^!~(.+?)~!$/)) {
2029
- const content = match2[1];
2030
- const parts = content.split(";");
2031
- let color = "currentColor";
2032
- let decorationStyle = "solid";
2033
- let type = "underline";
2034
- let textIndex = 0;
2035
- if (parts[textIndex]?.match(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/) || ["red", "blue", "green", "purple", "orange", "yellow", "pink"].includes(parts[textIndex])) {
2036
- color = parts[textIndex++];
2037
- }
2038
- if (["solid", "double", "dotted", "dashed", "wavy"].includes(parts[textIndex])) {
2039
- decorationStyle = parts[textIndex++];
2040
- }
2041
- if (["underline", "line-through", "overline", "both"].includes(parts[textIndex])) {
2042
- type = parts[textIndex] === "both" ? "underline line-through" : parts[textIndex++];
2043
- }
2044
- const innerText = parts.slice(textIndex).join(";");
2045
- return (0, import_vue.h)("span", {
2046
- key,
2047
- style: { textDecoration: `${type} ${decorationStyle} ${color}`, textDecorationThickness: "auto" }
2048
- }, renderInline(innerText));
2049
- }
2050
- if (match2 = part.match(/%([^%\s]+?)%([\s\S]+?)%%/)) {
2051
- return (0, import_vue.h)("span", { key, style: { color: match2[1] } }, renderInline(match2[2]));
2052
- }
2053
- if (match2 = part.match(/^!>([^<]+?)<!$/)) {
2054
- return (0, import_vue.h)("span", {
2055
- key,
2056
- class: "bg-text-primary text-bg-primary px-1 rounded hover:bg-transparent transition-colors cursor-pointer"
2057
- }, renderInline(match2[1]));
2058
- }
2059
- if (match2 = part.match(/^==(.+?)==$/)) {
2060
- return (0, import_vue.h)("mark", {
2061
- key,
2062
- class: "bg-yellow-500/20 text-inherit px-0.5 rounded"
2063
- }, renderInline(match2[1]));
2064
- }
2065
- if (match2 = part.match(/^\*\*\*(.+?)\*\*\*$/)) {
2066
- return (0, import_vue.h)("strong", { key }, (0, import_vue.h)("em", renderInline(match2[1])));
2067
- }
2068
- if (match2 = part.match(/^\*\*(.+?)\*\*$/)) {
2069
- return (0, import_vue.h)("strong", { key }, renderInline(match2[1]));
2070
- }
2071
- if (match2 = part.match(/^_(.+?)_$/)) {
2072
- return (0, import_vue.h)("em", { key }, renderInline(match2[1]));
2073
- }
2074
- if (match2 = part.match(/^~~(.+?)~~$/)) {
2075
- return (0, import_vue.h)("del", { key }, renderInline(match2[1]));
2076
- }
2077
- if (match2 = part.match(/^`([^`]+)`$/)) {
2078
- return (0, import_vue.h)("code", {
2079
- key,
2080
- class: "text-[0.875em] font-mono bg-background-secondary/50 px-1.5 py-0.5 rounded text-text-primary"
2081
- }, match2[1]);
2082
- }
2083
- if (match2 = part.match(/^\[([^\]]+?)\]\(([^)]+?)\)$/)) {
2084
- return (0, import_vue.h)("a", {
2085
- key,
2086
- href: match2[2],
2087
- class: "text-accent-primary underline decoration-accent-primary/40 hover:decoration-accent-primary transition-colors",
2088
- target: "_blank",
2089
- rel: "noopener noreferrer"
2090
- }, renderInline(match2[1]));
2091
- }
2092
- if (part.startsWith("<") && part.endsWith(">")) {
2093
- return (0, import_vue.h)("span", { key, innerHTML: part });
2094
- }
2095
- return (0, import_vue.h)("span", { key }, part);
2096
- };
2097
- const regex = /(\|\[[^\]]+\]\||\*\*\*.+?\*\*\*|\*\*.+?\*\*|_.+?_|~~.+?~~|`[^`]+?`|!~.+?~!|%[^%\s]+?%[\s\S]+?%%|!>.+?<!|==.+?==|\[[^\]]+?\]\([^)]+?\)|<[^>]+>)/g;
2098
- const elements = [];
2099
- let lastIndex = 0;
2100
- let match;
2101
- let keyCounter = 0;
2102
- while ((match = regex.exec(text)) !== null) {
2103
- if (match.index > lastIndex) {
2104
- elements.push((0, import_vue.h)("span", { key: `text-${keyCounter++}` }, text.slice(lastIndex, match.index)));
2105
- }
2106
- elements.push(parsePart(match[0], `inline-${keyCounter++}`));
2107
- lastIndex = regex.lastIndex;
2108
- }
2109
- if (lastIndex < text.length) {
2110
- elements.push((0, import_vue.h)("span", { key: `text-${keyCounter++}` }, text.slice(lastIndex)));
2111
- }
2112
- return elements;
2113
- }
2114
- function renderTable(content) {
2115
- const rows = content.split("\n").filter((r) => r.trim());
2116
- if (rows.length < 2) return (0, import_vue.h)("p", content);
2117
- const parseRow = (row) => row.split("|").map((c) => c.trim()).filter(Boolean);
2118
- const headerCells = parseRow(rows[0]);
2119
- const bodyRows = rows.slice(2).map(parseRow);
2120
- return (0, import_vue.h)("div", { class: "overflow-x-auto" }, [
2121
- (0, import_vue.h)("table", { class: "w-full text-sm sm:text-base border-collapse my-4" }, [
2122
- (0, import_vue.h)("thead", [
2123
- (0, import_vue.h)("tr", headerCells.map(
2124
- (cell, ci) => (0, import_vue.h)("th", {
2125
- key: ci,
2126
- class: "border border-border px-3 py-2 bg-background-secondary-solid/10 text-left font-bold"
2127
- }, renderInline(cell))
2128
- ))
2129
- ]),
2130
- (0, import_vue.h)("tbody", bodyRows.map(
2131
- (cells, ri) => (0, import_vue.h)("tr", { key: ri }, cells.map(
2132
- (cell, ci) => (0, import_vue.h)("td", { key: ci, class: "border border-border px-3 py-2" }, renderInline(cell))
2133
- ))
2134
- ))
2135
- ])
2136
- ]);
2137
- }
2138
- function renderList(content) {
2139
- const lines = content.split("\n");
2140
- const items = [];
2141
- for (const line of lines) {
2142
- if (!line.trim()) continue;
2143
- const match = line.match(/^(\s*)([-*+]|\d+\.)\s+(.+)$/);
2144
- if (match) {
2145
- items.push({ indent: match[1].length, marker: match[2], text: match[3] });
2146
- }
2147
- }
2148
- if (items.length === 0) return (0, import_vue.h)("p", content);
2149
- const isOrdered = /^\d+\.$/.test(items[0].marker);
2150
- const tag = isOrdered ? "ol" : "ul";
2151
- return (0, import_vue.h)(tag, {
2152
- class: `${isOrdered ? "list-decimal" : "list-disc"} pl-6 my-3 space-y-1 text-sm sm:text-base`
2153
- }, items.map(
2154
- (item, index) => (0, import_vue.h)("li", { key: index, class: "leading-relaxed" }, renderInline(item.text))
2155
- ));
2156
- }
2157
- function extractHeaders(elements) {
2158
- return elements.filter((el) => el.type === "header");
2159
- }
2160
-
2161
- // vue/ui-components.ts
2162
- var import_vue2 = require("vue");
2163
-
2164
2014
  // node_modules/highlight.js/es/core.js
2165
2015
  var import_core = __toESM(require_core(), 1);
2166
2016
  var core_default = import_core.default;
@@ -11057,7 +10907,7 @@ function shell(hljs) {
11057
10907
  };
11058
10908
  }
11059
10909
 
11060
- // vue/highlightSetup.ts
10910
+ // vanilla/highlightSetup.ts
11061
10911
  core_default.registerLanguage("javascript", javascript);
11062
10912
  core_default.registerLanguage("js", javascript);
11063
10913
  core_default.registerLanguage("jsx", javascript);
@@ -11095,754 +10945,908 @@ core_default.registerLanguage("diff", diff);
11095
10945
  core_default.registerLanguage("shell", shell);
11096
10946
  var highlightSetup_default = core_default;
11097
10947
 
11098
- // vue/ui-components.ts
11099
- var IconRenderer = (0, import_vue2.defineComponent)({
11100
- name: "IconRenderer",
11101
- props: {
11102
- iconName: { type: String, required: true },
11103
- extraClasses: { type: String, default: "" }
11104
- },
11105
- setup(props) {
11106
- return () => {
11107
- if (!props.iconName) return null;
11108
- const baseClass = `material-symbols-rounded !text-[1em] leading-none align-top ${props.extraClasses}`;
11109
- const isCodepoint = /^[eE][0-9a-fA-F]{3,4}$/.test(props.iconName);
11110
- if (isCodepoint) {
11111
- return (0, import_vue2.h)("span", {
11112
- class: baseClass,
11113
- innerHTML: `&#x${props.iconName};`,
11114
- "aria-hidden": "true"
11115
- });
11116
- }
11117
- return (0, import_vue2.h)("span", { class: baseClass, "aria-hidden": "true" }, props.iconName);
11118
- };
10948
+ // vanilla/components.ts
10949
+ function createIcon(iconName, extraClasses) {
10950
+ const span = document.createElement("span");
10951
+ const cls = `nr-icon material-icons-round${extraClasses ? ` ${extraClasses}` : ""}`;
10952
+ span.className = cls;
10953
+ span.setAttribute("aria-hidden", "true");
10954
+ const isCodepoint = /^[eE][0-9a-fA-F]{3,4}$/.test(iconName);
10955
+ if (isCodepoint) {
10956
+ span.innerHTML = `&#x${iconName};`;
10957
+ } else {
10958
+ span.textContent = iconName;
11119
10959
  }
11120
- });
11121
- var CodeBlock = (0, import_vue2.defineComponent)({
11122
- name: "CodeBlock",
11123
- props: {
11124
- code: { type: String, required: true },
11125
- language: { type: String, default: "" },
11126
- title: { type: String, default: void 0 }
11127
- },
11128
- setup(props) {
11129
- const copied = (0, import_vue2.ref)(false);
11130
- let timer = null;
11131
- const lang = () => props.language?.split(/[\s{]/)[0]?.trim() || "";
11132
- const html = () => {
11133
- try {
11134
- if (lang() && highlightSetup_default.getLanguage(lang())) {
11135
- return highlightSetup_default.highlight(props.code, { language: lang() }).value;
11136
- }
11137
- return highlightSetup_default.highlightAuto(props.code).value;
11138
- } catch {
11139
- return "";
11140
- }
11141
- };
11142
- const handleCopy = () => {
11143
- navigator.clipboard.writeText(props.code);
11144
- copied.value = true;
11145
- if (timer) clearTimeout(timer);
11146
- timer = setTimeout(() => {
11147
- copied.value = false;
11148
- }, 1800);
11149
- };
11150
- return () => (0, import_vue2.h)("div", { class: "not-prose my-4 rounded-2xl border border-border overflow-hidden bg-background-secondary-solid/5 relative" }, [
11151
- props.title && (0, import_vue2.h)("div", { class: "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" }, [
11152
- (0, import_vue2.h)("span", { class: "material-symbols-rounded text-base" }, "description"),
11153
- props.title
11154
- ]),
11155
- (0, import_vue2.h)("div", { class: "overflow-auto [&_pre]:m-0 [&_pre]:p-4 [&_pre]:text-xs sm:[&_pre]:text-sm" }, [
11156
- (0, import_vue2.h)("pre", { class: "m-0" }, [
11157
- (0, import_vue2.h)("code", {
11158
- class: `language-${lang() || "plaintext"}`,
11159
- innerHTML: html()
11160
- })
11161
- ])
11162
- ]),
11163
- (0, import_vue2.h)("button", {
11164
- class: "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",
11165
- onClick: handleCopy,
11166
- title: "Copy code"
11167
- }, [
11168
- (0, import_vue2.h)(
11169
- "span",
11170
- { class: "material-symbols-rounded", style: { fontSize: "1rem" } },
11171
- copied.value ? "check" : "content_copy"
11172
- )
11173
- ])
11174
- ]);
10960
+ return span;
10961
+ }
10962
+ function createCodeBlock(code, language, title) {
10963
+ const wrapper = document.createElement("div");
10964
+ wrapper.className = "nr-codeblock";
10965
+ const lang = language?.split(/[\s{]/)[0]?.trim() || "";
10966
+ if (title) {
10967
+ const header = document.createElement("div");
10968
+ header.className = "nr-codeblock__header";
10969
+ header.appendChild(createIcon("description"));
10970
+ const titleSpan = document.createElement("span");
10971
+ titleSpan.textContent = title;
10972
+ header.appendChild(titleSpan);
10973
+ wrapper.appendChild(header);
11175
10974
  }
11176
- });
11177
- var defaultIcons = {
10975
+ const pre = document.createElement("pre");
10976
+ pre.className = "nr-codeblock__pre";
10977
+ const codeEl = document.createElement("code");
10978
+ codeEl.className = `language-${lang || "plaintext"}`;
10979
+ try {
10980
+ if (lang && highlightSetup_default.getLanguage(lang)) {
10981
+ codeEl.innerHTML = highlightSetup_default.highlight(code, { language: lang }).value;
10982
+ } else {
10983
+ codeEl.innerHTML = highlightSetup_default.highlightAuto(code).value;
10984
+ }
10985
+ } catch {
10986
+ codeEl.textContent = code;
10987
+ }
10988
+ pre.appendChild(codeEl);
10989
+ wrapper.appendChild(pre);
10990
+ const copyBtn = document.createElement("button");
10991
+ copyBtn.className = "nr-codeblock__copy";
10992
+ copyBtn.title = "Copy code";
10993
+ const copyIcon = createIcon("content_copy");
10994
+ copyIcon.style.fontSize = "1rem";
10995
+ copyBtn.appendChild(copyIcon);
10996
+ let timer = null;
10997
+ copyBtn.addEventListener("click", () => {
10998
+ navigator.clipboard.writeText(code);
10999
+ copyIcon.textContent = "check";
11000
+ if (timer) clearTimeout(timer);
11001
+ timer = setTimeout(() => {
11002
+ copyIcon.textContent = "content_copy";
11003
+ }, 1800);
11004
+ });
11005
+ wrapper.appendChild(copyBtn);
11006
+ return wrapper;
11007
+ }
11008
+ var DEFAULT_ADMONITION_ICONS = {
11178
11009
  note: "info",
11179
11010
  info: "lightbulb",
11180
11011
  warning: "warning",
11181
11012
  danger: "report",
11182
- greentext: "subdirectory_play_arrow"
11013
+ greentext: "subdirectory_arrow_right"
11183
11014
  };
11184
- var typeClasses = {
11185
- note: "border-info/20 bg-info/5 text-info",
11186
- info: "border-info/30 bg-info/10 text-info",
11187
- warning: "border-amber-500/30 bg-amber-500/10 text-amber-500",
11188
- danger: "border-danger/30 bg-danger/10 text-danger",
11189
- greentext: "border-success/30 bg-success/10 text-success"
11190
- };
11191
- var Admonition = (0, import_vue2.defineComponent)({
11192
- name: "Admonition",
11193
- props: {
11194
- type: { type: String, default: "note" },
11195
- title: { type: String, default: void 0 },
11196
- icon: { type: String, default: void 0 },
11197
- class: { type: String, default: "" },
11198
- style: { type: Object, default: void 0 }
11199
- },
11200
- setup(props, { slots }) {
11201
- return () => {
11202
- const iconToRender = props.icon || defaultIcons[props.type] || "info";
11203
- const cls = `not-prose rounded-2xl mb-6 border shadow-xs p-4 ${typeClasses[props.type] || typeClasses.note} ${props.class}`;
11204
- return (0, import_vue2.h)("div", { class: cls, style: props.style }, [
11205
- props.title && (0, import_vue2.h)("h5", { class: "font-bold text-base mb-2 m-0 flex items-center gap-2" }, [
11206
- (0, import_vue2.h)(IconRenderer, { iconName: iconToRender, extraClasses: "shrink-0" }),
11207
- (0, import_vue2.h)("span", props.title)
11208
- ]),
11209
- (0, import_vue2.h)("div", { class: "text-sm leading-relaxed opacity-90" }, slots.default?.())
11210
- ]);
11211
- };
11015
+ function createAdmonition(type, title, icon) {
11016
+ const el = document.createElement("div");
11017
+ el.className = `nr-admonition nr-admonition--${type || "note"}`;
11018
+ if (title) {
11019
+ const header = document.createElement("h5");
11020
+ header.className = "nr-admonition__title";
11021
+ const iconToRender = icon || DEFAULT_ADMONITION_ICONS[type] || "info";
11022
+ header.appendChild(createIcon(iconToRender, "nr-admonition__icon"));
11023
+ const titleSpan = document.createElement("span");
11024
+ titleSpan.textContent = title;
11025
+ header.appendChild(titleSpan);
11026
+ el.appendChild(header);
11212
11027
  }
11213
- });
11214
- var Details = (0, import_vue2.defineComponent)({
11215
- name: "Details",
11216
- props: {
11217
- title: { type: String, required: true },
11218
- icon: { type: String, default: void 0 },
11219
- defaultOpen: { type: Boolean, default: false },
11220
- class: { type: String, default: "" },
11221
- style: { type: Object, default: void 0 }
11222
- },
11223
- setup(props, { slots }) {
11224
- const isOpen = (0, import_vue2.ref)(props.defaultOpen);
11225
- const iconToRender = props.icon || "play_arrow";
11226
- return () => (0, import_vue2.h)("details", {
11227
- class: `not-prose rounded-2xl border border-border mb-4 bg-background-primary/5 ${props.class}`,
11228
- open: isOpen.value,
11229
- style: props.style
11230
- }, [
11231
- (0, import_vue2.h)("summary", {
11232
- class: "cursor-pointer p-4 font-bold flex items-center gap-2 list-none [&::-webkit-details-marker]:hidden hover:text-accent-primary transition-colors",
11233
- onClick: (e) => {
11234
- e.preventDefault();
11235
- isOpen.value = !isOpen.value;
11236
- }
11237
- }, [
11238
- (0, import_vue2.h)(IconRenderer, {
11239
- iconName: iconToRender,
11240
- extraClasses: `transition-transform ${isOpen.value ? "rotate-90" : ""}`
11241
- }),
11242
- (0, import_vue2.h)("span", props.title)
11243
- ]),
11244
- isOpen.value && (0, import_vue2.h)("div", {
11245
- class: "px-4 pb-4 border-t border-border pt-3 text-sm leading-relaxed opacity-90 overflow-hidden min-w-0"
11246
- }, slots.default?.())
11247
- ]);
11028
+ const body = document.createElement("div");
11029
+ body.className = "nr-admonition__body";
11030
+ el.appendChild(body);
11031
+ return el;
11032
+ }
11033
+ function createDetails(title, icon, defaultOpen) {
11034
+ const details = document.createElement("details");
11035
+ details.className = "nr-details";
11036
+ if (defaultOpen) details.open = true;
11037
+ const summary = document.createElement("summary");
11038
+ summary.className = "nr-details__summary";
11039
+ const iconToRender = icon || "play_arrow";
11040
+ const iconEl = createIcon(iconToRender, "nr-details__icon");
11041
+ summary.appendChild(iconEl);
11042
+ const titleSpan = document.createElement("span");
11043
+ titleSpan.textContent = title || "Details";
11044
+ summary.appendChild(titleSpan);
11045
+ details.addEventListener("toggle", () => {
11046
+ iconEl.classList.toggle("nr-details__icon--open", details.open);
11047
+ });
11048
+ details.appendChild(summary);
11049
+ const body = document.createElement("div");
11050
+ body.className = "nr-details__body";
11051
+ details.appendChild(body);
11052
+ return details;
11053
+ }
11054
+ function createModal(title) {
11055
+ const dialog = document.createElement("dialog");
11056
+ dialog.className = "nr-modal";
11057
+ dialog.addEventListener("click", (e) => {
11058
+ if (e.target === dialog) {
11059
+ dialog.close();
11060
+ }
11061
+ });
11062
+ const popup = document.createElement("div");
11063
+ popup.className = "nr-modal__popup";
11064
+ const header = document.createElement("div");
11065
+ header.className = "nr-modal__header";
11066
+ const titleEl = document.createElement("h2");
11067
+ titleEl.className = "nr-modal__title";
11068
+ titleEl.textContent = title;
11069
+ header.appendChild(titleEl);
11070
+ const closeBtn = document.createElement("button");
11071
+ closeBtn.className = "nr-modal__close";
11072
+ closeBtn.appendChild(createIcon("close"));
11073
+ closeBtn.addEventListener("click", () => dialog.close());
11074
+ header.appendChild(closeBtn);
11075
+ popup.appendChild(header);
11076
+ const body = document.createElement("div");
11077
+ body.className = "nr-modal__body";
11078
+ popup.appendChild(body);
11079
+ dialog.appendChild(popup);
11080
+ return dialog;
11081
+ }
11082
+ function createTable(content, renderInline2) {
11083
+ const rows = content.split("\n").filter((r) => r.trim());
11084
+ if (rows.length < 2) {
11085
+ const p = document.createElement("p");
11086
+ p.textContent = content;
11087
+ return p;
11248
11088
  }
11249
- });
11250
- var Modal = (0, import_vue2.defineComponent)({
11251
- name: "Modal",
11252
- props: {
11253
- title: { type: String, required: true },
11254
- isOpen: { type: Boolean, required: true },
11255
- onClose: { type: Function, required: true }
11256
- },
11257
- setup(props, { slots }) {
11258
- let dialogEl = null;
11259
- const showDialog = () => {
11260
- if (dialogEl && !dialogEl.open) {
11261
- document.body.appendChild(dialogEl);
11262
- dialogEl.showModal();
11263
- }
11264
- };
11265
- const closeDialog = () => {
11266
- if (dialogEl) {
11267
- dialogEl.close();
11268
- }
11269
- };
11270
- return () => {
11271
- const dialog = (0, import_vue2.h)("dialog", {
11272
- ref: (el) => {
11273
- dialogEl = el?.$el || el;
11274
- },
11275
- class: "nr-modal",
11276
- onClick: (e) => {
11277
- if (e.target === dialogEl) closeDialog();
11278
- },
11279
- onClosed: () => {
11280
- dialogEl?.remove();
11281
- props.onClose();
11282
- }
11283
- }, [
11284
- (0, import_vue2.h)("div", { class: "nr-modal__popup" }, [
11285
- (0, import_vue2.h)("div", { class: "nr-modal__header" }, [
11286
- (0, import_vue2.h)("h2", { class: "nr-modal__title" }, props.title),
11287
- (0, import_vue2.h)("button", {
11288
- class: "nr-modal__close",
11289
- onClick: closeDialog
11290
- }, [
11291
- (0, import_vue2.h)("span", { class: "material-symbols-rounded" }, "close")
11292
- ])
11293
- ]),
11294
- (0, import_vue2.h)("div", { class: "nr-modal__body" }, slots.default?.())
11295
- ])
11296
- ]);
11297
- if (props.isOpen) {
11298
- Promise.resolve().then(showDialog);
11299
- }
11300
- return dialog;
11301
- };
11089
+ const parseRow = (row) => row.split("|").map((c) => c.trim()).filter(Boolean);
11090
+ const headerCells = parseRow(rows[0]);
11091
+ const bodyRows = rows.slice(2).map(parseRow);
11092
+ const wrapper = document.createElement("div");
11093
+ wrapper.className = "nr-table-wrap";
11094
+ const table = document.createElement("table");
11095
+ table.className = "nr-table";
11096
+ const thead = document.createElement("thead");
11097
+ const tr = document.createElement("tr");
11098
+ for (const cell of headerCells) {
11099
+ const th = document.createElement("th");
11100
+ th.className = "nr-table__th";
11101
+ th.appendChild(renderInline2(cell));
11102
+ tr.appendChild(th);
11302
11103
  }
11303
- });
11304
-
11305
- // vue/DirectiveRenderer.ts
11306
- var import_vue11 = require("vue");
11307
-
11308
- // vue/directives/AdmonitionDirective.ts
11309
- var import_vue3 = require("vue");
11310
- var AdmonitionDirective = (0, import_vue3.defineComponent)({
11311
- name: "AdmonitionDirective",
11312
- props: {
11313
- directiveType: String,
11314
- props: Object,
11315
- slots: Object,
11316
- renderSlot: Function,
11317
- context: Object,
11318
- index: [String, Number],
11319
- allElements: Array,
11320
- options: Object
11321
- },
11322
- setup(props) {
11323
- return () => {
11324
- const p = props;
11325
- return (0, import_vue3.h)(Admonition, {
11326
- type: p.directiveType,
11327
- title: p.props.title,
11328
- icon: p.props.icon,
11329
- class: p.props.class,
11330
- style: p.props.style ? parseCssString(p.props.style) : void 0
11331
- }, p.renderSlot("default"));
11332
- };
11104
+ thead.appendChild(tr);
11105
+ table.appendChild(thead);
11106
+ const tbody = document.createElement("tbody");
11107
+ for (const cells of bodyRows) {
11108
+ const tr2 = document.createElement("tr");
11109
+ for (const cell of cells) {
11110
+ const td = document.createElement("td");
11111
+ td.className = "nr-table__td";
11112
+ td.appendChild(renderInline2(cell));
11113
+ tr2.appendChild(td);
11114
+ }
11115
+ tbody.appendChild(tr2);
11333
11116
  }
11334
- });
11335
- var AdmonitionDirective_default = AdmonitionDirective;
11336
-
11337
- // vue/directives/CardDirective.ts
11338
- var import_vue5 = require("vue");
11117
+ table.appendChild(tbody);
11118
+ wrapper.appendChild(table);
11119
+ return wrapper;
11120
+ }
11121
+ function createList(content, renderInline2) {
11122
+ const lines = content.split("\n");
11123
+ const items = [];
11124
+ for (const line of lines) {
11125
+ if (!line.trim()) continue;
11126
+ const match = line.match(/^(\s*)([-*+]|\d+\.)\s+(.+)$/);
11127
+ if (match) {
11128
+ items.push({ indent: match[1].length, marker: match[2], text: match[3] });
11129
+ }
11130
+ }
11131
+ if (items.length === 0) {
11132
+ const p = document.createElement("p");
11133
+ p.textContent = content;
11134
+ return p;
11135
+ }
11136
+ const isOrdered = /^\d+\.$/.test(items[0].marker);
11137
+ const list = document.createElement(isOrdered ? "ol" : "ul");
11138
+ list.className = "nr-list";
11139
+ for (const item of items) {
11140
+ const li = document.createElement("li");
11141
+ li.className = "nr-list__item";
11142
+ li.appendChild(renderInline2(item.text));
11143
+ list.appendChild(li);
11144
+ }
11145
+ return list;
11146
+ }
11147
+ function createTOC(headers, renderInline2) {
11148
+ const nav = document.createElement("nav");
11149
+ nav.className = "nr-toc";
11150
+ const title = document.createElement("div");
11151
+ title.className = "nr-toc__title";
11152
+ title.textContent = "Table of Contents";
11153
+ nav.appendChild(title);
11154
+ const ul = document.createElement("ul");
11155
+ ul.className = "nr-toc__list";
11156
+ for (const h4 of headers) {
11157
+ const li = document.createElement("li");
11158
+ li.className = `nr-toc__item nr-toc__item--h${h4.level}`;
11159
+ const a = document.createElement("a");
11160
+ a.className = "nr-toc__link";
11161
+ a.href = `#${h4.id}`;
11162
+ a.appendChild(renderInline2(h4.text.replace(/->|<-/g, "").trim()));
11163
+ a.addEventListener("click", (e) => {
11164
+ e.preventDefault();
11165
+ const target = document.getElementById(h4.id);
11166
+ if (target) target.scrollIntoView({ behavior: "smooth", block: "start" });
11167
+ });
11168
+ li.appendChild(a);
11169
+ ul.appendChild(li);
11170
+ }
11171
+ nav.appendChild(ul);
11172
+ return nav;
11173
+ }
11174
+ function createBlockquote(content, classes, renderInline2) {
11175
+ const el = document.createElement("blockquote");
11176
+ el.className = `nr-blockquote${classes ? ` ${classes}` : ""}`;
11177
+ el.appendChild(renderInline2(content));
11178
+ return el;
11179
+ }
11339
11180
 
11340
- // vue/context.ts
11341
- var import_vue4 = require("vue");
11342
- var RenderContextKey = /* @__PURE__ */ Symbol("RenderContext");
11343
- function useRenderContext() {
11344
- const ctx = (0, import_vue4.inject)(RenderContextKey);
11345
- if (!ctx) {
11346
- throw new Error("useRenderContext must be used within a RenderContextProvider");
11181
+ // vanilla/inline.ts
11182
+ function renderInline(text) {
11183
+ const fragment = document.createDocumentFragment();
11184
+ if (!text) return fragment;
11185
+ const regex = /(\|\[[^\]]+\]\||\*\*\*.+?\*\*\*|\*\*.+?\*\*|_.+?_|~~.+?~~|`[^`]+?`|!~.+?~!|%[^%\s]+?%[\s\S]+?%%|!>.+?<!|==.+?==|\[[^\]]+?\]\([^)]+?\)|<[^>]+>)/g;
11186
+ let lastIndex = 0;
11187
+ let match;
11188
+ while ((match = regex.exec(text)) !== null) {
11189
+ if (match.index > lastIndex) {
11190
+ fragment.appendChild(document.createTextNode(text.slice(lastIndex, match.index)));
11191
+ }
11192
+ fragment.appendChild(parseInlinePart(match[0]));
11193
+ lastIndex = regex.lastIndex;
11194
+ }
11195
+ if (lastIndex < text.length) {
11196
+ fragment.appendChild(document.createTextNode(text.slice(lastIndex)));
11347
11197
  }
11348
- return ctx;
11198
+ return fragment;
11199
+ }
11200
+ function parseInlinePart(part) {
11201
+ let match;
11202
+ if (match = part.match(/^\|\[([^\]]+)\]\|$/)) {
11203
+ return createIcon(match[1]);
11204
+ }
11205
+ if (match = part.match(/^!~(.+?)~!$/)) {
11206
+ const content = match[1];
11207
+ const parts = content.split(";");
11208
+ let color = "currentColor";
11209
+ let decorationStyle = "solid";
11210
+ let type = "underline";
11211
+ let textIndex = 0;
11212
+ if (parts[textIndex]?.match(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/) || ["red", "blue", "green", "purple", "orange", "yellow", "pink"].includes(parts[textIndex])) {
11213
+ color = parts[textIndex++];
11214
+ }
11215
+ if (["solid", "double", "dotted", "dashed", "wavy"].includes(parts[textIndex])) {
11216
+ decorationStyle = parts[textIndex++];
11217
+ }
11218
+ if (["underline", "line-through", "overline", "both"].includes(parts[textIndex])) {
11219
+ type = parts[textIndex] === "both" ? "underline line-through" : parts[textIndex++];
11220
+ }
11221
+ const innerText = parts.slice(textIndex).join(";");
11222
+ const span = document.createElement("span");
11223
+ span.className = "nr-underline";
11224
+ span.style.textDecoration = `${type} ${decorationStyle} ${color}`;
11225
+ span.style.textDecorationThickness = "auto";
11226
+ span.appendChild(renderInline(innerText));
11227
+ return span;
11228
+ }
11229
+ if (match = part.match(/%([^%\s]+?)%([\s\S]+?)%%/)) {
11230
+ const span = document.createElement("span");
11231
+ span.style.color = match[1];
11232
+ span.appendChild(renderInline(match[2]));
11233
+ return span;
11234
+ }
11235
+ if (match = part.match(/^!>([^<]+?)<!$/)) {
11236
+ const span = document.createElement("span");
11237
+ span.className = "nr-spoiler";
11238
+ span.appendChild(renderInline(match[1]));
11239
+ return span;
11240
+ }
11241
+ if (match = part.match(/^==(.+?)==$/)) {
11242
+ const mark = document.createElement("mark");
11243
+ mark.className = "nr-highlight";
11244
+ mark.appendChild(renderInline(match[1]));
11245
+ return mark;
11246
+ }
11247
+ if (match = part.match(/^\*\*\*(.+?)\*\*\*$/)) {
11248
+ const strong = document.createElement("strong");
11249
+ const em = document.createElement("em");
11250
+ em.appendChild(renderInline(match[1]));
11251
+ strong.appendChild(em);
11252
+ return strong;
11253
+ }
11254
+ if (match = part.match(/^\*\*(.+?)\*\*$/)) {
11255
+ const strong = document.createElement("strong");
11256
+ strong.appendChild(renderInline(match[1]));
11257
+ return strong;
11258
+ }
11259
+ if (match = part.match(/^_(.+?)_$/)) {
11260
+ const em = document.createElement("em");
11261
+ em.appendChild(renderInline(match[1]));
11262
+ return em;
11263
+ }
11264
+ if (match = part.match(/^~~(.+?)~~$/)) {
11265
+ const del = document.createElement("del");
11266
+ del.appendChild(renderInline(match[1]));
11267
+ return del;
11268
+ }
11269
+ if (match = part.match(/^`([^`]+)`$/)) {
11270
+ const code = document.createElement("code");
11271
+ code.className = "nr-inline-code";
11272
+ code.textContent = match[1];
11273
+ return code;
11274
+ }
11275
+ if (match = part.match(/^\[([^\]]+?)\]\(([^)]+?)\)$/)) {
11276
+ const a = document.createElement("a");
11277
+ a.className = "nr-link";
11278
+ a.href = match[2];
11279
+ a.target = "_blank";
11280
+ a.rel = "noopener noreferrer";
11281
+ a.appendChild(renderInline(match[1]));
11282
+ return a;
11283
+ }
11284
+ if (part.startsWith("<") && part.endsWith(">")) {
11285
+ const span = document.createElement("span");
11286
+ span.innerHTML = part;
11287
+ return span;
11288
+ }
11289
+ return document.createTextNode(part);
11349
11290
  }
11350
11291
 
11351
- // vue/directives/CardDirective.ts
11352
- var CardDirective = (0, import_vue5.defineComponent)({
11353
- name: "CardDirective",
11354
- props: {
11355
- directiveType: String,
11356
- props: Object,
11357
- slots: Object,
11358
- renderSlot: Function,
11359
- context: Object,
11360
- index: [String, Number],
11361
- allElements: Array,
11362
- options: { type: Object, default: () => ({}) }
11363
- },
11364
- setup(props) {
11365
- return () => {
11366
- const p = props;
11367
- const ctx = useRenderContext();
11368
- const { title, image, icon, class: customClass, url, target } = p.props;
11369
- const hasDescription = !!p.slots.description;
11370
- const { isSingleCard } = p.options || {};
11371
- const isModal = p.directiveType === "card-m";
11372
- const isLink = p.directiveType === "card-b";
11373
- const modalId = `modal-card-${p.props.id || Math.random().toString(36).slice(2, 9)}`;
11374
- const inlineStyles = p.props.style ? parseCssString(p.props.style) : {};
11375
- const description = hasDescription ? p.renderSlot("description") : null;
11376
- const content = p.renderSlot("content") || p.renderSlot("default");
11377
- const handleClick = isModal ? (e) => {
11378
- e.preventDefault();
11379
- e.stopPropagation();
11380
- ctx.setModals((prev) => ({ ...prev, [modalId]: true }));
11381
- } : isLink && url ? () => window.open(url, "_blank") : void 0;
11382
- const card = (0, import_vue5.h)("div", {
11383
- class: `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"} ${customClass || ""}`.trim(),
11384
- style: inlineStyles,
11385
- onClick: handleClick,
11386
- role: isModal ? "button" : void 0,
11387
- tabIndex: isModal ? 0 : void 0,
11388
- onKeyDown: isModal ? (e) => {
11389
- if (e.key === "Enter" || e.key === " ") {
11390
- ctx.setModals((prev) => ({ ...prev, [modalId]: true }));
11391
- }
11392
- } : void 0
11393
- }, [
11394
- // Image banner
11395
- image && (0, import_vue5.h)("div", {
11396
- class: `w-full ${isSingleCard ? "h-[240px]" : "h-[160px]"} overflow-hidden relative transition-all duration-500`
11397
- }, [
11398
- (0, import_vue5.h)("img", { src: image, alt: title || "", class: "w-full h-full object-cover !m-0" }),
11399
- (0, import_vue5.h)("div", { class: "absolute inset-0 bg-gradient-to-t from-background-primary/40 to-transparent" })
11400
- ]),
11401
- // Content body
11402
- (0, import_vue5.h)("div", {
11403
- class: `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`
11404
- }, [
11405
- // Header: Icon + Title
11406
- (icon || title) && (0, import_vue5.h)("div", { class: "flex items-center gap-3 mb-3" }, [
11407
- icon && (0, import_vue5.h)("div", {
11408
- class: "w-10 h-10 text-[1.6em] rounded-xl bg-accent-primary/20 flex items-center justify-center shrink-0 text-accent-primary"
11409
- }, (0, import_vue5.h)(IconRenderer, { iconName: icon })),
11410
- (0, import_vue5.h)("h3", { class: "text-base font-black tracking-tight leading-tight !m-0" }, title)
11411
- ]),
11412
- // Content Body
11413
- (0, import_vue5.h)("div", { class: "flex-1 flex flex-col gap-2" }, [
11414
- description && (0, import_vue5.h)("div", { class: "text-sm opacity-80 leading-relaxed font-medium" }, description),
11415
- p.directiveType === "card" && content && content.length > 0 ? (0, import_vue5.h)("div", { class: "mt-2" }, content) : null
11416
- ]),
11417
- // Bottom: Action Link
11418
- (isModal || isLink) && (0, import_vue5.h)("div", { class: "mt-6 flex justify-end" }, [
11419
- isLink && url ? (0, import_vue5.h)("a", {
11420
- href: url,
11421
- target: "_blank",
11422
- rel: "noopener noreferrer",
11423
- class: "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",
11424
- onClick: (e) => e.stopPropagation()
11425
- }, [(0, import_vue5.h)(IconRenderer, { iconName: "open_in_new" }), " Link"]) : isModal ? (0, import_vue5.h)("div", {
11426
- class: "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"
11427
- }, [(0, import_vue5.h)(IconRenderer, { iconName: "arrow_forward" }), " Abrir"]) : null
11428
- ])
11429
- ])
11430
- ]);
11431
- if (isModal) {
11432
- const modalContent = p.renderSlot("content") || p.renderSlot("default");
11433
- return (0, import_vue5.h)("div", null, [
11434
- card,
11435
- (0, import_vue5.h)(Modal, {
11436
- title: title || "Detalles",
11437
- isOpen: !!ctx.modals.value[modalId],
11438
- onClose: () => ctx.setModals((prev) => ({ ...prev, [modalId]: false }))
11439
- }, [
11440
- (0, import_vue5.h)("div", { class: "prose prose-sm max-w-none" }, modalContent)
11441
- ])
11442
- ]);
11443
- }
11444
- return card;
11445
- };
11292
+ // vanilla/directives/admonition.ts
11293
+ var admonitionDirective = ({ directiveType, props, renderSlot }) => {
11294
+ const el = createAdmonition(directiveType, props.title, props.icon);
11295
+ if (props.class) el.classList.add(...props.class.split(/\s+/).filter(Boolean));
11296
+ if (props.style) el.setAttribute("style", props.style);
11297
+ const body = el.querySelector(".nr-admonition__body");
11298
+ if (body) {
11299
+ body.appendChild(renderSlot("default"));
11446
11300
  }
11447
- });
11448
- var CardDirective_default = CardDirective;
11301
+ return el;
11302
+ };
11303
+ var admonition_default = admonitionDirective;
11449
11304
 
11450
- // vue/directives/DetailsDirective.ts
11451
- var import_vue6 = require("vue");
11452
- var DetailsDirective = (0, import_vue6.defineComponent)({
11453
- name: "DetailsDirective",
11454
- props: {
11455
- directiveType: String,
11456
- props: Object,
11457
- slots: Object,
11458
- renderSlot: Function,
11459
- context: Object,
11460
- index: [String, Number],
11461
- allElements: Array,
11462
- options: Object
11463
- },
11464
- setup(props) {
11465
- return () => {
11466
- const p = props;
11467
- return (0, import_vue6.h)(Details, {
11468
- title: p.props.title || "Details",
11469
- icon: p.props.icon,
11470
- defaultOpen: p.props.defaultOpen === "true",
11471
- class: p.props.class,
11472
- style: p.props.style ? parseCssString(p.props.style) : void 0
11473
- }, p.renderSlot("default"));
11474
- };
11305
+ // vanilla/directives/details.ts
11306
+ var detailsDirective = ({ props, renderSlot }) => {
11307
+ const el = createDetails(
11308
+ props.title || "Details",
11309
+ props.icon,
11310
+ props.defaultOpen === "true"
11311
+ );
11312
+ if (props.class) el.classList.add(...props.class.split(/\s+/).filter(Boolean));
11313
+ if (props.style) el.setAttribute("style", props.style);
11314
+ const body = el.querySelector(".nr-details__body");
11315
+ if (body) {
11316
+ body.appendChild(renderSlot("default"));
11475
11317
  }
11476
- });
11477
- var DetailsDirective_default = DetailsDirective;
11318
+ return el;
11319
+ };
11320
+ var details_default = detailsDirective;
11478
11321
 
11479
- // vue/directives/ModalDirective.ts
11480
- var import_vue7 = require("vue");
11481
- var ModalDirective = (0, import_vue7.defineComponent)({
11482
- name: "ModalDirective",
11483
- props: {
11484
- directiveType: String,
11485
- props: Object,
11486
- slots: Object,
11487
- renderSlot: Function,
11488
- context: Object,
11489
- index: [String, Number],
11490
- allElements: Array,
11491
- options: Object
11492
- },
11493
- setup(props) {
11494
- return () => {
11495
- const p = props;
11496
- const ctx = useRenderContext();
11497
- const modalId = `modal-${p.props.id || Math.random().toString(36).slice(2, 9)}`;
11498
- const label = p.props.label || p.props.title || "Open";
11499
- const modalTitle = p.props.title || "Modal";
11500
- const customClass = p.props.class || "";
11501
- const hasSizeClass = /\btext-(xs|sm|base|lg|xl|[2-9]xl)\b/.test(customClass);
11502
- const sizeClass = hasSizeClass ? "" : "text-sm";
11503
- const hasDisplayClass = /\b(flex|inline-flex|block|inline-block|grid|inline-grid|hidden)\b/.test(customClass);
11504
- const displayClass = hasDisplayClass ? "" : "inline-flex";
11505
- const isInlineFlex = /\binline-flex\b/.test(customClass);
11506
- const marginClass = isInlineFlex ? "my-1 mx-1" : "my-4";
11507
- 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, " ");
11508
- const btnClass = `${btnBase} ${customClass}`.trim();
11509
- const positionMap = {
11510
- "#left": "text-left",
11511
- "#center": "text-center",
11512
- "#right": "text-right"
11513
- };
11514
- const wrapperClass = customClass.split(/\s+/).map((c) => positionMap[c] || c).join(" ");
11515
- const handleOpen = () => {
11516
- ctx.setModals((prev) => ({ ...prev, [modalId]: true }));
11517
- };
11518
- const handleClose = () => {
11519
- ctx.setModals((prev) => ({ ...prev, [modalId]: false }));
11520
- };
11521
- return (0, import_vue7.h)("div", { class: `not-prose ${wrapperClass}`.trim() }, [
11522
- (0, import_vue7.h)("button", { class: btnClass, onClick: handleOpen }, [
11523
- p.props.icon && (0, import_vue7.h)(IconRenderer, { iconName: p.props.icon }),
11524
- label
11525
- ]),
11526
- (0, import_vue7.h)(Modal, {
11527
- title: modalTitle,
11528
- isOpen: !!ctx.modals.value[modalId],
11529
- onClose: handleClose
11530
- }, p.renderSlot("default"))
11531
- ]);
11532
- };
11322
+ // vanilla/directives/modal.ts
11323
+ var modalDirective = ({ props, renderSlot }) => {
11324
+ const label = props.label || props.title || "Open";
11325
+ const modalTitle = props.title || "Modal";
11326
+ const customClass = props.class || "";
11327
+ const wrapper = document.createElement("div");
11328
+ wrapper.className = "nr-modal-trigger";
11329
+ const btn = document.createElement("button");
11330
+ btn.className = `nr-button nr-button--default`;
11331
+ if (customClass) btn.classList.add(...customClass.split(/\s+/).filter(Boolean));
11332
+ const icon = props.icon || "open_in_new";
11333
+ if (icon) btn.appendChild(createIcon(icon));
11334
+ btn.appendChild(document.createTextNode(label));
11335
+ const dialog = createModal(modalTitle);
11336
+ const body = dialog.querySelector(".nr-modal__body");
11337
+ if (body) {
11338
+ body.appendChild(renderSlot("default"));
11533
11339
  }
11534
- });
11535
- var ModalDirective_default = ModalDirective;
11340
+ btn.addEventListener("click", () => {
11341
+ if (!dialog.open) {
11342
+ document.body.appendChild(dialog);
11343
+ dialog.showModal();
11344
+ dialog.addEventListener("close", () => {
11345
+ dialog.remove();
11346
+ }, { once: true });
11347
+ }
11348
+ });
11349
+ wrapper.appendChild(btn);
11350
+ wrapper.appendChild(dialog);
11351
+ return wrapper;
11352
+ };
11353
+ var modal_default = modalDirective;
11536
11354
 
11537
- // vue/directives/ButtonDirective.ts
11538
- var import_vue8 = require("vue");
11539
- var ButtonDirective = (0, import_vue8.defineComponent)({
11540
- name: "ButtonDirective",
11541
- props: {
11542
- directiveType: String,
11543
- props: Object,
11544
- slots: Object,
11545
- renderSlot: Function,
11546
- context: Object,
11547
- index: [String, Number],
11548
- allElements: Array,
11549
- options: Object
11550
- },
11551
- setup(props) {
11552
- return () => {
11553
- const p = props;
11554
- const url = p.props.url || p.props.href || "#";
11555
- const label = p.props.label;
11556
- const icon = p.props.icon || "near_me";
11557
- const target = p.props.target || "_blank";
11558
- const customClass = p.props.class || "";
11559
- const hasSizeClass = /\btext-(xs|sm|base|lg|xl|[2-9]xl)\b/.test(customClass);
11560
- const sizeClass = hasSizeClass ? "" : "text-sm";
11561
- const hasDisplayClass = /\b(flex|inline-flex|block|inline-block|grid|inline-grid|hidden)\b/.test(customClass);
11562
- const displayClass = hasDisplayClass ? "" : "inline-flex";
11563
- const isInline = !customClass || !/\b(flex|block|grid)\b/.test(customClass) || /\binline-flex\b/.test(customClass);
11564
- const marginClass = isInline ? "my-1 mx-1" : "my-4";
11565
- 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, " ");
11566
- const btnClass = `${btnBase} ${customClass}`.trim();
11567
- const positionMap = {
11568
- "#left": "flex justify-start",
11569
- "#center": "flex justify-center",
11570
- "#right": "flex justify-end"
11571
- };
11572
- const wrapperClass = customClass.split(/\s+/).map((c) => positionMap[c] || c).join(" ");
11573
- if (label) {
11574
- return (0, import_vue8.h)("div", { class: `not-prose ${wrapperClass}`.trim() }, [
11575
- (0, import_vue8.h)("a", {
11576
- href: url,
11577
- target,
11578
- rel: "noopener noreferrer",
11579
- class: btnClass
11580
- }, [
11581
- (0, import_vue8.h)(IconRenderer, { iconName: icon }),
11582
- label
11583
- ])
11584
- ]);
11585
- }
11586
- const slotContent = p.renderSlot("default");
11587
- const findLinks = (vnodes) => {
11588
- const links2 = [];
11589
- for (const vnode of vnodes) {
11590
- if (!vnode) continue;
11591
- if (typeof vnode.type === "string" && vnode.type === "a") {
11592
- links2.push(vnode);
11593
- }
11594
- if (vnode.children && Array.isArray(vnode.children)) {
11595
- links2.push(...findLinks(vnode.children));
11596
- }
11597
- }
11598
- return links2;
11599
- };
11600
- const links = findLinks(Array.isArray(slotContent) ? slotContent : [slotContent]);
11601
- if (links.length > 0) {
11602
- return (0, import_vue8.h)("div", { class: `not-prose ${wrapperClass}`.trim() }, links.map((link, i) => {
11603
- const linkChildren = Array.isArray(link.children) ? link.children : link.children != null ? [link.children] : [];
11604
- return (0, import_vue8.h)("a", {
11605
- key: i,
11606
- ...link.props || {},
11607
- class: `${link.props?.class || ""} ${btnClass}`.trim(),
11608
- target,
11609
- rel: "noopener noreferrer"
11610
- }, [
11611
- (0, import_vue8.h)(IconRenderer, { iconName: icon }),
11612
- ...linkChildren
11613
- ]);
11614
- }));
11615
- }
11616
- return (0, import_vue8.h)("div", { class: `not-prose ${wrapperClass}`.trim() }, [
11617
- (0, import_vue8.h)("a", {
11618
- href: url,
11619
- target,
11620
- rel: "noopener noreferrer",
11621
- class: btnClass
11622
- }, [
11623
- (0, import_vue8.h)(IconRenderer, { iconName: icon }),
11624
- slotContent
11625
- ])
11626
- ]);
11627
- };
11355
+ // vanilla/directives/button.ts
11356
+ var buttonDirective = ({ props, renderSlot }) => {
11357
+ const url = props.url || props.href || "#";
11358
+ const label = props.label;
11359
+ const icon = props.icon || "near_me";
11360
+ const target = props.target || "_blank";
11361
+ const customClass = props.class || "";
11362
+ const wrapper = document.createElement("div");
11363
+ wrapper.className = "nr-button-wrap";
11364
+ if (label) {
11365
+ const a = document.createElement("a");
11366
+ a.href = url;
11367
+ a.target = target;
11368
+ a.rel = "noopener noreferrer";
11369
+ a.className = "nr-button nr-button--default";
11370
+ if (customClass) a.classList.add(...customClass.split(/\s+/).filter(Boolean));
11371
+ a.appendChild(createIcon(icon));
11372
+ a.appendChild(document.createTextNode(label));
11373
+ wrapper.appendChild(a);
11374
+ return wrapper;
11628
11375
  }
11629
- });
11630
- var ButtonDirective_default = ButtonDirective;
11376
+ const slotContent = renderSlot("default");
11377
+ const links = slotContent.querySelectorAll("a");
11378
+ if (links.length > 0) {
11379
+ links.forEach((link) => {
11380
+ link.classList.add("nr-button", "nr-button--default");
11381
+ if (customClass) link.classList.add(...customClass.split(/\s+/).filter(Boolean));
11382
+ });
11383
+ wrapper.appendChild(slotContent);
11384
+ } else {
11385
+ const a = document.createElement("a");
11386
+ a.href = url;
11387
+ a.target = target;
11388
+ a.rel = "noopener noreferrer";
11389
+ a.className = "nr-button nr-button--default";
11390
+ if (customClass) a.classList.add(...customClass.split(/\s+/).filter(Boolean));
11391
+ a.appendChild(createIcon(icon));
11392
+ a.appendChild(slotContent);
11393
+ wrapper.appendChild(a);
11394
+ }
11395
+ return wrapper;
11396
+ };
11397
+ var button_default = buttonDirective;
11631
11398
 
11632
- // vue/directives/WrapperDirective.ts
11633
- var import_vue9 = require("vue");
11634
- var WrapperDirective = (0, import_vue9.defineComponent)({
11635
- name: "WrapperDirective",
11636
- props: {
11637
- directiveType: String,
11638
- props: Object,
11639
- slots: Object,
11640
- renderSlot: Function,
11641
- context: Object,
11642
- index: [String, Number],
11643
- allElements: Array,
11644
- options: Object
11645
- },
11646
- setup(props) {
11647
- return () => {
11648
- const p = props;
11649
- const className = p.props.class || "";
11650
- const id = p.props.id || "";
11651
- const inlineStyle = p.props.style ? parseCssString(p.props.style) : {};
11652
- const wrapperProps = {};
11653
- if (className) wrapperProps.class = className;
11654
- if (id) wrapperProps.id = id;
11655
- if (Object.keys(inlineStyle).length > 0) wrapperProps.style = inlineStyle;
11656
- for (const [key, value] of Object.entries(p.props)) {
11657
- if (key.startsWith("data-")) {
11658
- wrapperProps[key] = value;
11659
- }
11399
+ // vanilla/directives/card.ts
11400
+ var cardDirective = ({
11401
+ directiveType,
11402
+ props,
11403
+ slots,
11404
+ renderSlot,
11405
+ options
11406
+ }) => {
11407
+ const { title, image, icon, url, target } = props;
11408
+ const customClass = props.class || "";
11409
+ const hasDescription = !!slots.description;
11410
+ const { isSingleCard } = options || {};
11411
+ const isModal = directiveType === "card-m";
11412
+ const isLink = directiveType === "card-b";
11413
+ const inlineStyles = props.style ? parseCssString(props.style) : {};
11414
+ const card = document.createElement("div");
11415
+ card.className = `nr-card${isModal || isLink ? " nr-card--interactive" : ""} ${customClass}`.trim();
11416
+ for (const [key, value] of Object.entries(inlineStyles)) {
11417
+ card.style.setProperty(key, String(value));
11418
+ }
11419
+ if (image) {
11420
+ const imgWrap = document.createElement("div");
11421
+ imgWrap.className = `nr-card__image${isSingleCard ? " nr-card__image--tall" : ""}`;
11422
+ const img = document.createElement("img");
11423
+ img.src = image;
11424
+ img.alt = title || "";
11425
+ img.className = "nr-card__img";
11426
+ imgWrap.appendChild(img);
11427
+ const gradient = document.createElement("div");
11428
+ gradient.className = "nr-card__gradient";
11429
+ imgWrap.appendChild(gradient);
11430
+ card.appendChild(imgWrap);
11431
+ }
11432
+ const body = document.createElement("div");
11433
+ body.className = `nr-card__body${image ? " nr-card__body--overlap" : ""}`;
11434
+ if (icon || title) {
11435
+ const header = document.createElement("div");
11436
+ header.className = "nr-card__header";
11437
+ if (icon) {
11438
+ const iconWrap = document.createElement("div");
11439
+ iconWrap.className = "nr-card__icon-wrap";
11440
+ iconWrap.appendChild(createIcon(icon));
11441
+ header.appendChild(iconWrap);
11442
+ }
11443
+ if (title) {
11444
+ const h32 = document.createElement("h3");
11445
+ h32.className = "nr-card__title";
11446
+ h32.textContent = title;
11447
+ header.appendChild(h32);
11448
+ }
11449
+ body.appendChild(header);
11450
+ }
11451
+ if (hasDescription) {
11452
+ const desc = document.createElement("div");
11453
+ desc.className = "nr-card__description";
11454
+ desc.appendChild(renderSlot("description"));
11455
+ body.appendChild(desc);
11456
+ }
11457
+ if (directiveType === "card") {
11458
+ const contentSlot = renderSlot("content") || renderSlot("default");
11459
+ if (contentSlot.childNodes.length > 0) {
11460
+ const contentDiv = document.createElement("div");
11461
+ contentDiv.className = "nr-card__content";
11462
+ contentDiv.appendChild(contentSlot);
11463
+ body.appendChild(contentDiv);
11464
+ }
11465
+ }
11466
+ if (isModal || isLink) {
11467
+ const action = document.createElement("div");
11468
+ action.className = "nr-card__action";
11469
+ if (isLink && url) {
11470
+ const a = document.createElement("a");
11471
+ a.href = url;
11472
+ a.target = target || "_blank";
11473
+ a.rel = "noopener noreferrer";
11474
+ a.className = "nr-card__action-link";
11475
+ a.appendChild(createIcon("open_in_new"));
11476
+ a.appendChild(document.createTextNode(" Link"));
11477
+ action.appendChild(a);
11478
+ } else if (isModal) {
11479
+ const modalBtn = document.createElement("div");
11480
+ modalBtn.className = "nr-card__action-link";
11481
+ modalBtn.appendChild(createIcon("arrow_forward"));
11482
+ modalBtn.appendChild(document.createTextNode(" Abrir"));
11483
+ action.appendChild(modalBtn);
11484
+ }
11485
+ body.appendChild(action);
11486
+ }
11487
+ card.appendChild(body);
11488
+ if (isModal) {
11489
+ const dialog = createModal(title || "Detalles");
11490
+ const modalBody = dialog.querySelector(".nr-modal__body");
11491
+ if (modalBody) {
11492
+ const contentSlot = renderSlot("content") || renderSlot("default");
11493
+ modalBody.appendChild(contentSlot);
11494
+ }
11495
+ card.addEventListener("click", () => {
11496
+ if (!dialog.open) {
11497
+ document.body.appendChild(dialog);
11498
+ dialog.showModal();
11499
+ dialog.addEventListener("close", () => dialog.remove(), { once: true });
11660
11500
  }
11661
- return (0, import_vue9.h)("div", wrapperProps, p.renderSlot("default"));
11662
- };
11501
+ });
11502
+ const frag = document.createDocumentFragment();
11503
+ frag.appendChild(card);
11504
+ frag.appendChild(dialog);
11505
+ return frag;
11663
11506
  }
11664
- });
11665
- var WrapperDirective_default = WrapperDirective;
11507
+ if (isLink && url) {
11508
+ card.addEventListener("click", () => window.open(url, target || "_blank"));
11509
+ }
11510
+ return card;
11511
+ };
11512
+ var card_default = cardDirective;
11513
+
11514
+ // vanilla/directives/wrapper.ts
11515
+ var wrapperDirective = ({ props, renderSlot }) => {
11516
+ const el = document.createElement("div");
11517
+ el.className = "nr-wrapper";
11518
+ if (props.class) el.classList.add(...props.class.split(/\s+/).filter(Boolean));
11519
+ if (props.id) el.id = props.id;
11520
+ if (props.style) {
11521
+ const styles = parseCssString(props.style);
11522
+ for (const [key, value] of Object.entries(styles)) {
11523
+ el.style.setProperty(key, String(value));
11524
+ }
11525
+ }
11526
+ for (const [key, value] of Object.entries(props)) {
11527
+ if (key.startsWith("data-")) {
11528
+ el.setAttribute(key, value);
11529
+ }
11530
+ }
11531
+ el.appendChild(renderSlot("default"));
11532
+ return el;
11533
+ };
11534
+ var wrapper_default = wrapperDirective;
11666
11535
 
11667
- // vue/directives/SlideDirective.ts
11668
- var import_vue10 = require("vue");
11536
+ // vanilla/directives/slide.ts
11669
11537
  var slideCounter = 0;
11670
- var SlideDirective = (0, import_vue10.defineComponent)({
11671
- name: "SlideDirective",
11672
- props: {
11673
- directiveType: String,
11674
- props: Object,
11675
- slots: Object,
11676
- renderSlot: Function,
11677
- context: Object,
11678
- index: [String, Number],
11679
- allElements: Array,
11680
- options: Object
11681
- },
11682
- setup(props) {
11683
- const current = (0, import_vue10.ref)(0);
11684
- const maxH = (0, import_vue10.ref)(0);
11685
- let intervalId = null;
11686
- let slideEls = [];
11687
- const measureAndSetHeight = () => {
11688
- let h14 = 0;
11538
+ var slideDirective = ({
11539
+ props,
11540
+ slots,
11541
+ renderInline: renderInline2,
11542
+ renderMarkdown
11543
+ }) => {
11544
+ const rawContent = slots.default || "";
11545
+ const lines = rawContent.split("\n").map((l) => l.trim()).filter(Boolean);
11546
+ if (lines.length === 0) {
11547
+ return document.createDocumentFragment();
11548
+ }
11549
+ const interval = parseInt(props.interval || "3000", 10);
11550
+ const speed = parseInt(props.speed || "500", 10);
11551
+ const rawClass = props.class || "";
11552
+ const inlineStyle = props.style ? parseCssString(props.style) : {};
11553
+ const scopeClass = `sld-${++slideCounter}`;
11554
+ const container = document.createElement("div");
11555
+ container.className = "nr-slide";
11556
+ Object.assign(container.style, {
11557
+ position: "relative",
11558
+ overflow: "hidden",
11559
+ ...inlineStyle
11560
+ });
11561
+ const track = document.createElement("div");
11562
+ track.className = "nr-slide__track";
11563
+ track.style.transition = `transform ${speed}ms cubic-bezier(0.16, 1, 0.3, 1)`;
11564
+ const slideEls = [];
11565
+ for (const line of lines) {
11566
+ const slideEl = document.createElement("div");
11567
+ slideEl.className = `nr-slide__item ${scopeClass} ${rawClass}`.trim();
11568
+ slideEl.style.display = "flex";
11569
+ slideEl.style.alignItems = "center";
11570
+ if (renderMarkdown) {
11571
+ const tokens = renderMarkdown(line);
11572
+ slideEl.appendChild(tokens);
11573
+ } else if (renderInline2) {
11574
+ slideEl.appendChild(renderInline2(line));
11575
+ }
11576
+ track.appendChild(slideEl);
11577
+ slideEls.push(slideEl);
11578
+ }
11579
+ container.appendChild(track);
11580
+ let current = 0;
11581
+ let maxH = 0;
11582
+ const measureAndSetHeight = () => {
11583
+ maxH = 0;
11584
+ for (const el of slideEls) {
11585
+ maxH = Math.max(maxH, el.offsetHeight);
11586
+ }
11587
+ if (maxH > 0) {
11588
+ container.style.height = `${maxH}px`;
11689
11589
  for (const el of slideEls) {
11690
- h14 = Math.max(h14, el.offsetHeight);
11590
+ el.style.height = `${maxH}px`;
11691
11591
  }
11692
- if (h14 > 0) maxH.value = h14;
11693
- };
11694
- (0, import_vue10.onMounted)(() => {
11695
- (0, import_vue10.nextTick)(() => {
11696
- measureAndSetHeight();
11697
- if (document.fonts?.ready) {
11698
- document.fonts.ready.then(measureAndSetHeight);
11699
- }
11700
- });
11701
- });
11702
- (0, import_vue10.onUnmounted)(() => {
11703
- if (intervalId) clearInterval(intervalId);
11704
- });
11705
- return () => {
11706
- const p = props;
11707
- const ctx = p.context;
11708
- const rawContent = p.slots.default || "";
11709
- const lines = rawContent.split("\n").map((l) => l.trim()).filter(Boolean);
11710
- if (lines.length === 0) return (0, import_vue10.h)("div");
11711
- const elements = lines.map((line) => ctx.parseMarkdown(line));
11712
- const interval = parseInt(p.props.interval || "3000", 10);
11713
- const speed = parseInt(p.props.speed || "500", 10);
11714
- const rawClass = p.props.class || "";
11715
- const inlineStyle = p.props.style ? parseCssString(p.props.style) : {};
11716
- const scopeClass = `sld-${++slideCounter}`;
11717
- if (lines.length > 1 && !intervalId) {
11718
- intervalId = setInterval(() => {
11719
- current.value = (current.value + 1) % elements.length;
11720
- }, interval);
11721
- }
11722
- const textSizeMap = {
11723
- "text-xs": "0.75rem",
11724
- "text-sm": "0.875rem",
11725
- "text-base": "1rem",
11726
- "text-lg": "1.125rem",
11727
- "text-xl": "1.25rem",
11728
- "text-2xl": "1.5rem",
11729
- "text-3xl": "1.875rem",
11730
- "text-4xl": "2.25rem",
11731
- "text-5xl": "3rem",
11732
- "text-6xl": "3.75rem",
11733
- "text-7xl": "4.5rem",
11734
- "text-8xl": "6rem",
11735
- "text-9xl": "8rem"
11736
- };
11737
- const textSizeMatch = rawClass.match(/\btext-(xs|sm|base|lg|xl|[2-9]xl)\b/);
11738
- const forcedFontSize = textSizeMatch ? textSizeMap[textSizeMatch[0]] : null;
11739
- const className = textSizeMatch ? rawClass.replace(textSizeMatch[0], "").replace(/\s+/g, " ").trim() : rawClass;
11740
- return (0, import_vue10.h)("div", {
11741
- class: "not-prose",
11742
- style: { height: maxH.value || "auto", position: "relative", overflow: "hidden", ...inlineStyle }
11743
- }, [
11744
- forcedFontSize && (0, import_vue10.h)("style", `.${scopeClass} * { font-size: ${forcedFontSize} !important; line-height: normal !important; }`),
11745
- (0, import_vue10.h)("div", {
11746
- style: {
11747
- position: "absolute",
11748
- left: 0,
11749
- right: 0,
11750
- top: 0,
11751
- transition: `transform ${speed}ms cubic-bezier(0.16, 1, 0.3, 1)`,
11752
- transform: `translateY(${-current.value * maxH.value}px)`
11753
- }
11754
- }, elements.map(
11755
- (tokens, i) => (0, import_vue10.h)("div", {
11756
- key: i,
11757
- ref: (el) => {
11758
- slideEls[i] = el?.$el || el;
11759
- },
11760
- style: maxH.value ? { height: maxH.value, display: "flex", alignItems: "center", overflow: "hidden" } : { display: "flex", alignItems: "center" }
11761
- }, [
11762
- (0, import_vue10.h)("div", {
11763
- class: `${scopeClass} ${className}`.trim(),
11764
- style: { width: "100%" }
11765
- }, ctx.processAndRenderElements(tokens))
11766
- ])
11767
- ))
11768
- ]);
11769
- };
11592
+ }
11593
+ };
11594
+ requestAnimationFrame(() => {
11595
+ measureAndSetHeight();
11596
+ if (document.fonts?.ready) {
11597
+ document.fonts.ready.then(measureAndSetHeight);
11598
+ }
11599
+ });
11600
+ if (lines.length > 1) {
11601
+ setInterval(() => {
11602
+ current = (current + 1) % lines.length;
11603
+ track.style.transform = `translateY(${-current * maxH}px)`;
11604
+ }, interval);
11770
11605
  }
11771
- });
11772
- var SlideDirective_default = SlideDirective;
11606
+ return container;
11607
+ };
11608
+ var slide_default = slideDirective;
11773
11609
 
11774
- // vue/directives/index.ts
11610
+ // vanilla/directives/index.ts
11775
11611
  var directiveRegistry = {
11776
11612
  // Admonitions
11777
- note: AdmonitionDirective_default,
11778
- info: AdmonitionDirective_default,
11779
- warning: AdmonitionDirective_default,
11780
- danger: AdmonitionDirective_default,
11781
- greentext: AdmonitionDirective_default,
11613
+ note: admonition_default,
11614
+ info: admonition_default,
11615
+ warning: admonition_default,
11616
+ danger: admonition_default,
11617
+ greentext: admonition_default,
11782
11618
  // Cards
11783
- card: CardDirective_default,
11784
- "card-m": CardDirective_default,
11785
- "card-b": CardDirective_default,
11619
+ card: card_default,
11620
+ "card-m": card_default,
11621
+ "card-b": card_default,
11786
11622
  // Interactive
11787
- details: DetailsDirective_default,
11788
- modal: ModalDirective_default,
11789
- button: ButtonDirective_default,
11623
+ details: details_default,
11624
+ modal: modal_default,
11625
+ button: button_default,
11790
11626
  // Layout / generic wrappers
11791
- div: WrapperDirective_default,
11792
- style: WrapperDirective_default,
11793
- custom: WrapperDirective_default,
11794
- raw: WrapperDirective_default,
11627
+ div: wrapper_default,
11628
+ style: wrapper_default,
11629
+ custom: wrapper_default,
11630
+ raw: wrapper_default,
11795
11631
  // Animation
11796
- slide: SlideDirective_default
11632
+ slide: slide_default
11797
11633
  };
11798
11634
  var directives_default = directiveRegistry;
11799
11635
 
11800
- // vue/DirectiveRenderer.ts
11801
- var DirectiveRenderer = (0, import_vue11.defineComponent)({
11802
- name: "DirectiveRenderer",
11803
- props: {
11804
- element: { type: Object, required: true },
11805
- context: { type: Object, required: true },
11806
- index: { type: Number, required: true },
11807
- allElements: { type: Array, required: true }
11808
- },
11809
- setup(props) {
11810
- return () => {
11811
- const { element, context, index, allElements } = props;
11812
- const { directiveType, props: directiveProps, slots, scopeId } = element;
11813
- const Component = directives_default[directiveType];
11814
- const renderSlot = (name) => {
11815
- const slotContent = slots[name];
11816
- if (!slotContent) return [];
11817
- const parsed = context.parseMarkdown(slotContent);
11818
- return context.processAndRenderElements(parsed);
11819
- };
11820
- const componentProps = {
11821
- directiveType,
11822
- props: directiveProps,
11823
- slots,
11824
- renderSlot,
11825
- context,
11826
- index,
11827
- allElements
11828
- };
11829
- if (Component) {
11830
- return (0, import_vue11.h)(Component, componentProps);
11636
+ // vanilla/renderer.ts
11637
+ function renderTokens(tokens) {
11638
+ const article = document.createElement("article");
11639
+ article.className = "nr-prose";
11640
+ const ctx = {
11641
+ parseMarkdown,
11642
+ renderElements: (tks) => renderTokensInner(tks, ctx),
11643
+ renderInline,
11644
+ renderMarkdown: (md) => renderTokensInner(parseMarkdown(md), ctx)
11645
+ };
11646
+ article.appendChild(processElements(tokens, ctx, tokens));
11647
+ return article;
11648
+ }
11649
+ function renderMarkdownString(markdown2) {
11650
+ const tokens = parseMarkdown(markdown2);
11651
+ return renderTokens(tokens);
11652
+ }
11653
+ function renderHtmlString(html) {
11654
+ let processedContent = html;
11655
+ processedContent = processedContent.replace(
11656
+ /<style(?:\s+[^>]*)?>([\s\S]*?)<\/style>/gi,
11657
+ (_match, cssContent) => {
11658
+ const styleEl = document.createElement("style");
11659
+ styleEl.setAttribute("data-nr-global", "");
11660
+ styleEl.textContent = cssContent;
11661
+ document.head.appendChild(styleEl);
11662
+ return "";
11663
+ }
11664
+ );
11665
+ const wrapper = document.createElement("div");
11666
+ wrapper.className = "nr-raw-html";
11667
+ wrapper.innerHTML = processedContent;
11668
+ const scripts = wrapper.querySelectorAll("script");
11669
+ scripts.forEach((oldScript) => {
11670
+ const newScript = document.createElement("script");
11671
+ Array.from(oldScript.attributes).forEach(
11672
+ (attr) => newScript.setAttribute(attr.name, attr.value)
11673
+ );
11674
+ newScript.textContent = oldScript.textContent;
11675
+ oldScript.parentNode?.replaceChild(newScript, oldScript);
11676
+ });
11677
+ return wrapper;
11678
+ }
11679
+ function renderTokensInner(tokens, ctx) {
11680
+ const container = document.createElement("div");
11681
+ container.appendChild(processElements(tokens, ctx, tokens));
11682
+ return container;
11683
+ }
11684
+ function processElements(elements, ctx, allElements) {
11685
+ const fragment = document.createDocumentFragment();
11686
+ let i = 0;
11687
+ while (i < elements.length) {
11688
+ const el = elements[i];
11689
+ if (el.type === "directive" && ["card", "card-m", "card-b"].includes(el.directiveType)) {
11690
+ const cards = [];
11691
+ while (i < elements.length && elements[i].type === "directive" && ["card", "card-m", "card-b"].includes(elements[i].directiveType)) {
11692
+ cards.push(elements[i]);
11693
+ i++;
11831
11694
  }
11832
- return (0, import_vue11.h)("div", {
11833
- key: index,
11834
- class: "my-4 p-4 rounded-2xl border border-border bg-background-primary/5"
11835
- }, renderSlot("default"));
11836
- };
11695
+ if (cards.length === 1 || cards[0].props?.batch === "off") {
11696
+ for (const card of cards) {
11697
+ const rendered = renderElement(card, ctx, allElements);
11698
+ if (rendered) fragment.appendChild(rendered);
11699
+ }
11700
+ } else {
11701
+ const grid = document.createElement("div");
11702
+ grid.className = "nr-card-grid";
11703
+ for (const card of cards) {
11704
+ const rendered = renderElement(card, ctx, allElements);
11705
+ if (rendered) grid.appendChild(rendered);
11706
+ }
11707
+ fragment.appendChild(grid);
11708
+ }
11709
+ } else {
11710
+ const rendered = renderElement(el, ctx, allElements);
11711
+ if (rendered) fragment.appendChild(rendered);
11712
+ i++;
11713
+ }
11837
11714
  }
11838
- });
11839
- var DirectiveRenderer_default = DirectiveRenderer;
11840
-
11841
- // vue/RawHtmlRenderer.ts
11842
- var import_vue13 = require("vue");
11715
+ return fragment;
11716
+ }
11717
+ function renderElement(element, ctx, allElements) {
11718
+ switch (element.type) {
11719
+ case "header": {
11720
+ const tag = `h${element.level}`;
11721
+ let text = element.text;
11722
+ const alignCenter = text.match(/^->\s*(.+?)\s*<-\s*$/);
11723
+ const alignRight = text.match(/^->\s*(.+?)\s*->\s*$/);
11724
+ if (alignCenter) text = alignCenter[1];
11725
+ else if (alignRight) text = alignRight[1];
11726
+ const h4 = document.createElement(tag);
11727
+ h4.id = element.id;
11728
+ let cls = `md-h${element.level}`;
11729
+ if (alignCenter) cls += " text-center";
11730
+ if (alignRight) cls += " text-right";
11731
+ if (element.classes) cls += ` ${element.classes}`;
11732
+ h4.className = cls;
11733
+ h4.appendChild(renderInline(text));
11734
+ return h4;
11735
+ }
11736
+ case "paragraph": {
11737
+ const p = document.createElement("p");
11738
+ let cls = "md-p";
11739
+ if (element.classes) cls += ` ${element.classes}`;
11740
+ if (element.align) cls += ` text-${element.align}`;
11741
+ p.className = cls;
11742
+ if (element.id) p.id = element.id;
11743
+ const lines = element.content.split("\n");
11744
+ for (let li = 0; li < lines.length; li++) {
11745
+ const line = lines[li];
11746
+ const hardBreakMatch = line.match(/^(.*?)(\s{2,})$/);
11747
+ if (hardBreakMatch) {
11748
+ p.appendChild(renderInline(hardBreakMatch[1]));
11749
+ p.appendChild(document.createElement("br"));
11750
+ } else {
11751
+ p.appendChild(renderInline(line));
11752
+ if (li < lines.length - 1) {
11753
+ p.appendChild(document.createTextNode(" "));
11754
+ }
11755
+ }
11756
+ }
11757
+ return p;
11758
+ }
11759
+ case "codeblock":
11760
+ return createCodeBlock(element.content, element.language, element.title);
11761
+ case "directive":
11762
+ return renderDirective(element, ctx, allElements);
11763
+ case "html": {
11764
+ const el = element;
11765
+ return renderHtmlString(el.content);
11766
+ }
11767
+ case "html-block": {
11768
+ const htmlBlock = element;
11769
+ const rawProps = parseHtmlAttrs(htmlBlock.attrs);
11770
+ const el = document.createElement(htmlBlock.tag);
11771
+ for (const [key, value] of Object.entries(rawProps)) {
11772
+ if (key === "style" && typeof value === "object") {
11773
+ for (const [prop, val] of Object.entries(value)) {
11774
+ el.style.setProperty(prop, String(val));
11775
+ }
11776
+ } else if (value === true) {
11777
+ el.setAttribute(key, "");
11778
+ } else {
11779
+ el.setAttribute(key, String(value));
11780
+ }
11781
+ }
11782
+ const childFrag = processElements(htmlBlock.children, ctx, allElements);
11783
+ el.appendChild(childFrag);
11784
+ return el;
11785
+ }
11786
+ case "image": {
11787
+ const img = document.createElement("img");
11788
+ img.src = element.src;
11789
+ img.alt = element.alt;
11790
+ img.className = "nr-image";
11791
+ if (element.style) {
11792
+ for (const [key, value] of Object.entries(element.style)) {
11793
+ img.style.setProperty(key, String(value));
11794
+ }
11795
+ }
11796
+ return img;
11797
+ }
11798
+ case "table":
11799
+ return createTable(element.content, renderInline);
11800
+ case "list":
11801
+ return createList(element.content, renderInline);
11802
+ case "blockquote":
11803
+ return createBlockquote(element.content, element.classes, renderInline);
11804
+ case "hr": {
11805
+ const hr = document.createElement("hr");
11806
+ hr.className = "nr-hr";
11807
+ return hr;
11808
+ }
11809
+ case "toc": {
11810
+ const headers = allElements.filter((e) => e.type === "header");
11811
+ return createTOC(headers.map((h4) => ({ level: h4.level, text: h4.text, id: h4.id })), renderInline);
11812
+ }
11813
+ default:
11814
+ return null;
11815
+ }
11816
+ }
11817
+ function renderDirective(element, ctx, allElements) {
11818
+ const { directiveType, props, slots, scopeId } = element;
11819
+ const renderer = directives_default[directiveType];
11820
+ const renderSlot = (name) => {
11821
+ const frag = document.createDocumentFragment();
11822
+ const slotContent = slots[name];
11823
+ if (!slotContent) return frag;
11824
+ const tokens = ctx.parseMarkdown(slotContent);
11825
+ frag.appendChild(ctx.renderElements(tokens));
11826
+ return frag;
11827
+ };
11828
+ const directiveProps = {
11829
+ directiveType,
11830
+ props,
11831
+ slots,
11832
+ renderSlot,
11833
+ context: ctx,
11834
+ index: 0,
11835
+ allElements,
11836
+ renderInline,
11837
+ renderMarkdown: ctx.renderMarkdown
11838
+ };
11839
+ if (renderer) {
11840
+ return renderer(directiveProps);
11841
+ }
11842
+ const fallback = document.createElement("div");
11843
+ fallback.className = "nr-unknown-directive";
11844
+ fallback.appendChild(renderSlot("default"));
11845
+ return fallback;
11846
+ }
11843
11847
 
11844
11848
  // vue/useTailwindCDN.ts
11845
- var import_vue12 = require("vue");
11849
+ var import_vue = require("vue");
11846
11850
  var CDN_URL = "https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4";
11847
11851
  var SCRIPT_ID = "tailwind-cdn-v4-runtime";
11848
11852
  var CONFIG_ID = "tailwind-cdn-v4-config";
@@ -11882,18 +11886,18 @@ function useLazyTailwindCDN(enabled) {
11882
11886
  }
11883
11887
  };
11884
11888
  if (typeof enabled === "boolean") {
11885
- (0, import_vue12.onMounted)(() => {
11889
+ (0, import_vue.onMounted)(() => {
11886
11890
  if (enabled) injectCDN();
11887
11891
  });
11888
- (0, import_vue12.onUnmounted)(() => {
11892
+ (0, import_vue.onUnmounted)(() => {
11889
11893
  if (enabled) removeCDN();
11890
11894
  });
11891
11895
  } else {
11892
- (0, import_vue12.watch)(enabled, (newVal, oldVal) => {
11896
+ (0, import_vue.watch)(enabled, (newVal, oldVal) => {
11893
11897
  if (newVal && !oldVal) injectCDN();
11894
11898
  if (!newVal && oldVal) removeCDN();
11895
11899
  }, { immediate: true });
11896
- (0, import_vue12.onUnmounted)(() => {
11900
+ (0, import_vue.onUnmounted)(() => {
11897
11901
  if (enabled.value) removeCDN();
11898
11902
  });
11899
11903
  }
@@ -11906,7 +11910,7 @@ function scanTailwindCDN() {
11906
11910
  function preloadTailwindCDN() {
11907
11911
  if (typeof window === "undefined" || typeof document === "undefined") return;
11908
11912
  if (document.getElementById(SCRIPT_ID)) return;
11909
- const inject2 = () => {
11913
+ const inject = () => {
11910
11914
  if (document.getElementById(SCRIPT_ID)) return;
11911
11915
  if (!document.getElementById(CONFIG_ID)) {
11912
11916
  const configScript = document.createElement("script");
@@ -11921,267 +11925,76 @@ function preloadTailwindCDN() {
11921
11925
  window.__twCDNRefs = (window.__twCDNRefs ?? 0) + 1;
11922
11926
  };
11923
11927
  if ("requestIdleCallback" in window) {
11924
- window.requestIdleCallback(inject2, { timeout: 2e3 });
11928
+ window.requestIdleCallback(inject, { timeout: 2e3 });
11925
11929
  } else {
11926
- setTimeout(inject2, 200);
11930
+ setTimeout(inject, 200);
11927
11931
  }
11928
11932
  }
11929
11933
 
11930
- // vue/RawHtmlRenderer.ts
11931
- var RawHtmlRenderer = (0, import_vue13.defineComponent)({
11932
- name: "RawHtmlRenderer",
11933
- props: {
11934
- content: { type: String, required: true },
11935
- globalStyles: { type: String, default: void 0 },
11936
- wrapperClassName: { type: String, required: true }
11937
- },
11938
- setup(props) {
11939
- const containerRef = (0, import_vue13.ref)(null);
11940
- (0, import_vue13.onMounted)(() => {
11941
- if (!containerRef.value) return;
11942
- const scripts = containerRef.value.querySelectorAll("script");
11943
- scripts.forEach((oldScript) => {
11944
- const newScript = document.createElement("script");
11945
- Array.from(oldScript.attributes).forEach(
11946
- (attr) => newScript.setAttribute(attr.name, attr.value)
11947
- );
11948
- newScript.textContent = oldScript.textContent;
11949
- oldScript.parentNode?.replaceChild(newScript, oldScript);
11950
- });
11951
- scanTailwindCDN();
11952
- });
11953
- return () => {
11954
- const children = [
11955
- (0, import_vue13.h)("div", { innerHTML: props.content })
11956
- ];
11957
- return (0, import_vue13.h)("div", { ref: containerRef, class: props.wrapperClassName }, children);
11958
- };
11959
- }
11960
- });
11961
- var RawHtmlRenderer_default = RawHtmlRenderer;
11962
-
11963
11934
  // vue/CustomMarkdownRenderer.ts
11964
- var CustomMarkdownRenderer = (0, import_vue14.defineComponent)({
11935
+ var CustomMarkdownRenderer = (0, import_vue2.defineComponent)({
11965
11936
  name: "CustomMarkdownRenderer",
11966
11937
  props: {
11967
11938
  content: { type: String, required: true }
11968
11939
  },
11969
11940
  setup(props) {
11970
- const modals = (0, import_vue14.ref)({});
11971
- const baseId = Math.random().toString(36).slice(2, 9);
11972
- const articleClass = `scope-${baseId}`;
11973
- resetScopeCounter();
11974
- const allElements = (0, import_vue14.computed)(() => parseMarkdown(props.content));
11975
- const handleHashChange = () => {
11976
- const hash = window.location.hash;
11977
- if (hash) {
11978
- const parts = hash.split("#");
11979
- const id = parts[parts.length - 1];
11980
- scrollToId(id);
11981
- }
11941
+ const container = (0, import_vue2.ref)(null);
11942
+ const render = () => {
11943
+ const el = container.value;
11944
+ if (!el) return;
11945
+ el.replaceChildren();
11946
+ el.appendChild(renderMarkdownString(props.content));
11947
+ scanTailwindCDN();
11982
11948
  };
11983
- (0, import_vue14.onMounted)(() => {
11949
+ let cleanupHash = null;
11950
+ (0, import_vue2.onMounted)(() => {
11951
+ render();
11952
+ const handleHashChange = () => {
11953
+ const hash = window.location.hash;
11954
+ if (hash) {
11955
+ const parts = hash.split("#");
11956
+ scrollToId(parts[parts.length - 1]);
11957
+ }
11958
+ };
11984
11959
  handleHashChange();
11985
11960
  window.addEventListener("hashchange", handleHashChange);
11961
+ cleanupHash = () => window.removeEventListener("hashchange", handleHashChange);
11986
11962
  });
11987
- (0, import_vue14.onUnmounted)(() => {
11988
- window.removeEventListener("hashchange", handleHashChange);
11963
+ (0, import_vue2.watch)(() => props.content, render);
11964
+ (0, import_vue2.onUnmounted)(() => {
11965
+ cleanupHash?.();
11989
11966
  });
11990
- const generateToc = (elements) => {
11991
- const headers = extractHeaders(elements);
11992
- if (headers.length === 0) return null;
11993
- return (0, import_vue14.h)("nav", { class: "not-prose my-6 p-4 rounded-2xl border border-border bg-background-primary/5" }, [
11994
- (0, import_vue14.h)("div", { class: "text-base font-bold mb-3" }, "Table of Contents"),
11995
- (0, import_vue14.h)("ul", { class: "space-y-1 list-none p-0 m-0" }, headers.map((h_token, i) => {
11996
- if (h_token.type !== "header") return null;
11997
- const indentClass = h_token.level <= 2 ? "pl-0" : h_token.level === 3 ? "pl-4" : h_token.level === 4 ? "pl-8" : "pl-12";
11998
- return (0, import_vue14.h)("li", { key: i, class: `${indentClass} text-sm sm:text-base` }, [
11999
- (0, import_vue14.h)("a", {
12000
- href: `#${h_token.id}`,
12001
- class: "text-accent-primary hover:text-accent-primary/80 no-underline hover:underline transition-colors",
12002
- onClick: (e) => {
12003
- e.preventDefault();
12004
- scrollToId(h_token.id);
12005
- }
12006
- }, renderInline(h_token.text.replace(/->|<-/g, "").trim()))
12007
- ]);
12008
- }))
12009
- ]);
12010
- };
12011
- const renderElement = (element, index, _depth = 0) => {
12012
- switch (element.type) {
12013
- case "header": {
12014
- const tag = `h${element.level}`;
12015
- let text = element.text;
12016
- const alignCenter = text.match(/^->\s*(.+?)\s*<-\s*$/);
12017
- const alignRight = text.match(/^->\s*(.+?)\s*->\s*$/);
12018
- if (alignCenter) text = alignCenter[1];
12019
- else if (alignRight) text = alignRight[1];
12020
- const userClasses = element.classes || "";
12021
- let headerClasses = `md-h${element.level}`;
12022
- if (alignCenter) headerClasses += " text-center";
12023
- if (alignRight) headerClasses += " text-right";
12024
- if (userClasses) headerClasses += ` ${userClasses}`;
12025
- return (0, import_vue14.h)(tag, { key: index, id: element.id, class: headerClasses }, renderInline(text));
12026
- }
12027
- case "paragraph": {
12028
- const lines = element.content.split("\n");
12029
- const processedContent = lines.map((line, lineIndex) => {
12030
- const hardBreakMatch = line.match(/^(.*?)(\s{2,})$/);
12031
- if (hardBreakMatch) {
12032
- return (0, import_vue14.h)("span", { key: lineIndex }, [
12033
- renderInline(hardBreakMatch[1]),
12034
- (0, import_vue14.h)("br")
12035
- ]);
12036
- }
12037
- const isLastLine = lineIndex === lines.length - 1;
12038
- return (0, import_vue14.h)("span", { key: lineIndex }, [
12039
- renderInline(line),
12040
- !isLastLine && " "
12041
- ]);
12042
- });
12043
- const pUserClasses = element.classes || "";
12044
- let pClasses = "md-p";
12045
- if (pUserClasses) pClasses += ` ${pUserClasses}`;
12046
- if (element.align) pClasses += ` text-${element.align}`;
12047
- return (0, import_vue14.h)("p", { key: index, id: element.id, class: pClasses }, processedContent);
12048
- }
12049
- case "codeblock":
12050
- return (0, import_vue14.h)(CodeBlock, {
12051
- key: index,
12052
- code: element.content,
12053
- language: element.language,
12054
- title: element.title
12055
- });
12056
- case "directive":
12057
- return (0, import_vue14.h)(DirectiveRenderer_default, {
12058
- key: index,
12059
- element,
12060
- context: contextForDirectives,
12061
- index,
12062
- allElements: allElements.value
12063
- });
12064
- case "html": {
12065
- let processedContent = element.content;
12066
- let globalStyles = "";
12067
- processedContent = processedContent.replace(
12068
- /<style(?:\s+[^>]*)?>([\s\S]*?)<\/style>/gi,
12069
- (_match, cssContent) => {
12070
- globalStyles += cssContent + "\n";
12071
- return "";
12072
- }
12073
- );
12074
- return (0, import_vue14.h)(RawHtmlRenderer_default, {
12075
- key: index,
12076
- content: processedContent,
12077
- globalStyles: globalStyles || void 0,
12078
- wrapperClassName: "w-full my-4"
12079
- });
12080
- }
12081
- case "html-block": {
12082
- const htmlBlock = element;
12083
- const rawProps = parseHtmlAttrs(htmlBlock.attrs);
12084
- const props2 = {};
12085
- for (const [key, value] of Object.entries(rawProps)) {
12086
- if (key === "class") props2["class"] = value;
12087
- else props2[key] = value;
12088
- }
12089
- return (0, import_vue14.h)(
12090
- htmlBlock.tag,
12091
- { key: index, ...props2 },
12092
- processAndRenderElements(htmlBlock.children, _depth + 1)
12093
- );
12094
- }
12095
- case "image":
12096
- return (0, import_vue14.h)("img", {
12097
- key: index,
12098
- alt: element.alt,
12099
- src: element.src,
12100
- style: element.style,
12101
- class: "max-w-full h-auto"
12102
- });
12103
- case "table":
12104
- return (0, import_vue14.h)("div", { key: index }, renderTable(element.content));
12105
- case "list":
12106
- return (0, import_vue14.h)("div", { key: index }, renderList(element.content));
12107
- case "blockquote":
12108
- return (0, import_vue14.h)("blockquote", {
12109
- key: index,
12110
- class: `border-l-4 border-accent-primary/30 pl-4 italic text-text-secondary my-4 text-sm sm:text-base${element.classes ? ` ${element.classes}` : ""}`
12111
- }, renderInline(element.content));
12112
- case "hr":
12113
- return (0, import_vue14.h)("hr", { key: index, class: "my-8 border-border" });
12114
- case "toc": {
12115
- const toc = generateToc(allElements.value);
12116
- return toc ? (0, import_vue14.h)("div", { key: index }, toc) : null;
12117
- }
12118
- default:
12119
- return null;
12120
- }
12121
- };
12122
- const processAndRenderElements = (elements, depth = 0) => {
12123
- const result = [];
12124
- let i = 0;
12125
- while (i < elements.length) {
12126
- const el = elements[i];
12127
- if (el.type === "directive" && ["card", "card-m", "card-b"].includes(el.directiveType)) {
12128
- const cards = [];
12129
- while (i < elements.length && elements[i].type === "directive" && ["card", "card-m", "card-b"].includes(elements[i].directiveType)) {
12130
- cards.push(elements[i]);
12131
- i++;
12132
- }
12133
- if (cards.length === 1 || cards[0].props?.batch === "off") {
12134
- for (let c = 0; c < cards.length; c++) {
12135
- result.push(renderElement(cards[c], result.length, depth));
12136
- }
12137
- } else {
12138
- const firstCardClass = cards[0].props?.["class"] || "";
12139
- const justifyClasses = firstCardClass.match(/\bjustify-\S+/g) || [];
12140
- const wrapperJustify = justifyClasses.length > 0 ? justifyClasses.join(" ") : "";
12141
- result.push((0, import_vue14.h)("div", {
12142
- key: `card-grid-${result.length}`,
12143
- class: `not-prose flex flex-wrap gap-6 my-6 ${wrapperJustify}`
12144
- }, cards.map((card, ci) => {
12145
- const rendered = renderElement(card, ci, depth);
12146
- return rendered ? (0, import_vue14.h)("span", { key: ci }, rendered) : null;
12147
- })));
12148
- }
12149
- } else {
12150
- result.push(renderElement(el, result.length, depth));
12151
- i++;
12152
- }
12153
- }
12154
- return result;
12155
- };
12156
- const setModals = (value) => {
12157
- if (typeof value === "function") {
12158
- modals.value = value(modals.value);
12159
- } else {
12160
- modals.value = value;
12161
- }
12162
- };
12163
- const contextForDirectives = {
12164
- modals,
12165
- setModals,
12166
- articleClass,
12167
- allElements: allElements.value,
12168
- parseMarkdown,
12169
- renderElement,
12170
- renderInline,
12171
- processAndRenderElements
12172
- };
12173
- (0, import_vue14.provide)(RenderContextKey, contextForDirectives);
12174
- return () => (0, import_vue14.h)(
12175
- "div",
12176
- { class: articleClass },
12177
- processAndRenderElements(allElements.value)
12178
- );
11967
+ return () => (0, import_vue2.h)("div", { ref: container });
12179
11968
  }
12180
11969
  });
12181
11970
  var CustomMarkdownRenderer_default = CustomMarkdownRenderer;
12182
11971
 
11972
+ // vue/RawHtmlRenderer.ts
11973
+ var import_vue3 = require("vue");
11974
+ var RawHtmlRenderer = (0, import_vue3.defineComponent)({
11975
+ name: "RawHtmlRenderer",
11976
+ props: {
11977
+ content: { type: String, required: true },
11978
+ wrapperClassName: { type: String, default: "nr-raw-html" }
11979
+ },
11980
+ setup(props) {
11981
+ const container = (0, import_vue3.ref)(null);
11982
+ const render = () => {
11983
+ const el = container.value;
11984
+ if (!el) return;
11985
+ el.replaceChildren();
11986
+ el.appendChild(renderHtmlString(props.content));
11987
+ scanTailwindCDN();
11988
+ };
11989
+ (0, import_vue3.onMounted)(render);
11990
+ (0, import_vue3.watch)(() => props.content, render);
11991
+ return () => (0, import_vue3.h)("div", { ref: container, class: props.wrapperClassName });
11992
+ }
11993
+ });
11994
+ var RawHtmlRenderer_default = RawHtmlRenderer;
11995
+
12183
11996
  // vue/NRpreviewer.ts
12184
- var NRpreviewer = (0, import_vue15.defineComponent)({
11997
+ var NRpreviewer = (0, import_vue4.defineComponent)({
12185
11998
  name: "NRpreviewer",
12186
11999
  props: {
12187
12000
  content: { type: String, default: void 0 },
@@ -12191,23 +12004,20 @@ var NRpreviewer = (0, import_vue15.defineComponent)({
12191
12004
  style: { type: Object, default: void 0 }
12192
12005
  },
12193
12006
  setup(props) {
12194
- const tailwindEnabled = (0, import_vue15.ref)(props.tailwindCDN);
12007
+ const tailwindEnabled = (0, import_vue4.ref)(props.tailwindCDN);
12195
12008
  if (typeof window !== "undefined") {
12196
12009
  useLazyTailwindCDN(tailwindEnabled);
12197
12010
  }
12198
12011
  return () => {
12199
12012
  const wrapperClass = `nr-prose${props.className ? ` ${props.className}` : ""}`;
12200
12013
  if (props.content) {
12201
- return (0, import_vue15.h)("div", { class: wrapperClass, style: props.style }, [
12202
- (0, import_vue15.h)(CustomMarkdownRenderer_default, { content: props.content })
12014
+ return (0, import_vue4.h)("div", { class: wrapperClass, style: props.style }, [
12015
+ (0, import_vue4.h)(CustomMarkdownRenderer_default, { content: props.content })
12203
12016
  ]);
12204
12017
  }
12205
12018
  if (props.html) {
12206
- return (0, import_vue15.h)("div", { class: wrapperClass, style: props.style }, [
12207
- (0, import_vue15.h)(RawHtmlRenderer_default, {
12208
- content: props.html,
12209
- wrapperClassName: "nr-preview-html"
12210
- })
12019
+ return (0, import_vue4.h)("div", { class: wrapperClass, style: props.style }, [
12020
+ (0, import_vue4.h)(RawHtmlRenderer_default, { content: props.html })
12211
12021
  ]);
12212
12022
  }
12213
12023
  return null;