@aeriz/wysiwyg 1.0.2 → 1.0.3
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.
- package/README.md +610 -96
- package/angular/README.md +112 -0
- package/angular/aeriz-editor.directive.ts +243 -0
- package/angular/aeriz-wysiwyg.module.ts +14 -0
- package/angular/index.ts +5 -0
- package/dist/adapters/jquery.cjs +1 -0
- package/dist/adapters/jquery.js +91 -0
- package/dist/adapters/react.cjs +1 -0
- package/dist/adapters/react.js +66 -0
- package/dist/adapters/shared.cjs +1 -0
- package/dist/adapters/shared.js +87 -0
- package/dist/adapters/svelte.cjs +1 -0
- package/dist/adapters/svelte.js +29 -0
- package/dist/adapters/vue.cjs +1 -0
- package/dist/adapters/vue.js +110 -0
- package/dist/adapters/vue2.cjs +1 -0
- package/dist/adapters/vue2.js +117 -0
- package/dist/adapters/wc.cjs +1 -0
- package/dist/adapters/wc.js +207 -0
- package/dist/aeriz-wysiwyg-adapter.js +169 -0
- package/dist/aeriz-wysiwyg-adapter.min.js +1 -0
- package/dist/aeriz-wysiwyg-jquery.js +275 -0
- package/dist/aeriz-wysiwyg-jquery.min.js +1 -0
- package/dist/aeriz-wysiwyg-wc.js +401 -0
- package/dist/aeriz-wysiwyg-wc.min.js +1 -0
- package/dist/aeriz-wysiwyg.cjs +6912 -0
- package/dist/aeriz-wysiwyg.css +37 -129
- package/dist/aeriz-wysiwyg.esm.js +1170 -149
- package/dist/aeriz-wysiwyg.esm.min.js +2057 -1209
- package/dist/aeriz-wysiwyg.js +1169 -148
- package/dist/aeriz-wysiwyg.min.cjs +54 -0
- package/dist/aeriz-wysiwyg.min.css +1 -1
- package/dist/aeriz-wysiwyg.min.js +44 -13
- package/dist/server.cjs +32 -0
- package/dist/server.js +666 -0
- package/dist-types/adapters/jquery.d.ts +34 -0
- package/dist-types/adapters/jquery.d.ts.map +1 -0
- package/dist-types/adapters/react.d.ts +28 -0
- package/dist-types/adapters/react.d.ts.map +1 -0
- package/dist-types/adapters/shared.d.ts +83 -0
- package/dist-types/adapters/shared.d.ts.map +1 -0
- package/dist-types/adapters/svelte.d.ts +38 -0
- package/dist-types/adapters/svelte.d.ts.map +1 -0
- package/dist-types/adapters/vue.d.ts +189 -0
- package/dist-types/adapters/vue.d.ts.map +1 -0
- package/dist-types/adapters/vue2.d.ts +175 -0
- package/dist-types/adapters/vue2.d.ts.map +1 -0
- package/dist-types/adapters/wc.d.ts +96 -0
- package/dist-types/adapters/wc.d.ts.map +1 -0
- package/dist-types/cjs/adapters/jquery.d.cts +34 -0
- package/dist-types/cjs/adapters/react.d.cts +28 -0
- package/dist-types/cjs/adapters/shared.d.cts +83 -0
- package/dist-types/cjs/adapters/svelte.d.cts +38 -0
- package/dist-types/cjs/adapters/vue.d.cts +189 -0
- package/dist-types/cjs/adapters/vue2.d.cts +175 -0
- package/dist-types/cjs/adapters/wc.d.cts +96 -0
- package/dist-types/cjs/core/AerizEditor.d.cts +357 -0
- package/dist-types/cjs/core/AerizViewer.d.cts +61 -0
- package/dist-types/cjs/core/block-meta.d.cts +32 -0
- package/dist-types/cjs/core/blocks.d.cts +368 -0
- package/dist-types/cjs/core/fonts.d.cts +60 -0
- package/dist-types/cjs/core/highlight.d.cts +44 -0
- package/dist-types/cjs/core/html-mini.d.cts +65 -0
- package/dist-types/cjs/core/i18n.d.cts +209 -0
- package/dist-types/cjs/core/import-html.d.cts +39 -0
- package/dist-types/cjs/core/import-markdown.d.cts +37 -0
- package/dist-types/cjs/core/markdown-export.d.cts +30 -0
- package/dist-types/cjs/core/plain-text.d.cts +17 -0
- package/dist-types/cjs/core/render-string.d.cts +68 -0
- package/dist-types/cjs/core/snapshot.d.cts +51 -0
- package/dist-types/cjs/index.d.cts +20 -0
- package/dist-types/cjs/server/index.d.cts +37 -0
- package/dist-types/cjs/types/index.d.cts +61 -0
- package/dist-types/cjs/ui/Toolbar.d.cts +21 -0
- package/dist-types/cjs/ui/dialogs.d.cts +74 -0
- package/dist-types/cjs/ui/icons.d.cts +2 -0
- package/dist-types/cjs/ui/popovers.d.cts +70 -0
- package/dist-types/core/AerizEditor.d.ts +30 -10
- package/dist-types/core/AerizEditor.d.ts.map +1 -1
- package/dist-types/core/AerizViewer.d.ts +16 -4
- package/dist-types/core/AerizViewer.d.ts.map +1 -1
- package/dist-types/core/block-meta.d.ts +32 -0
- package/dist-types/core/block-meta.d.ts.map +1 -0
- package/dist-types/core/blocks.d.ts +62 -7
- package/dist-types/core/blocks.d.ts.map +1 -1
- package/dist-types/core/fonts.d.ts +11 -0
- package/dist-types/core/fonts.d.ts.map +1 -1
- package/dist-types/core/html-mini.d.ts +65 -0
- package/dist-types/core/html-mini.d.ts.map +1 -0
- package/dist-types/core/import-html.d.ts.map +1 -1
- package/dist-types/core/markdown-export.d.ts +30 -0
- package/dist-types/core/markdown-export.d.ts.map +1 -0
- package/dist-types/core/plain-text.d.ts +17 -0
- package/dist-types/core/plain-text.d.ts.map +1 -0
- package/dist-types/core/render-string.d.ts +68 -0
- package/dist-types/core/render-string.d.ts.map +1 -0
- package/dist-types/core/snapshot.d.ts +51 -0
- package/dist-types/core/snapshot.d.ts.map +1 -0
- package/dist-types/index.d.ts +19 -10
- package/dist-types/index.d.ts.map +1 -1
- package/dist-types/server/index.d.ts +37 -0
- package/dist-types/server/index.d.ts.map +1 -0
- package/dist-types/types/index.d.ts +21 -0
- package/dist-types/types/index.d.ts.map +1 -1
- package/dist-types/ui/Toolbar.d.ts +1 -1
- package/dist-types/ui/popovers.d.ts +1 -1
- package/dist-types/ui/popovers.d.ts.map +1 -1
- package/package.json +213 -58
package/dist/aeriz-wysiwyg.js
CHANGED
|
@@ -884,27 +884,80 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
884
884
|
return null;
|
|
885
885
|
}
|
|
886
886
|
let loaded = false;
|
|
887
|
+
const unavailable = /* @__PURE__ */ new Set();
|
|
888
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
889
|
+
const SAMPLE_TEXT = "가A";
|
|
890
|
+
function getAvailableFontFamilies() {
|
|
891
|
+
if (unavailable.size === 0) return FONT_FAMILIES;
|
|
892
|
+
return FONT_FAMILIES.filter((f) => !unavailable.has(f.id));
|
|
893
|
+
}
|
|
894
|
+
function subscribeFontAvailability(listener) {
|
|
895
|
+
listeners.add(listener);
|
|
896
|
+
return () => {
|
|
897
|
+
listeners.delete(listener);
|
|
898
|
+
};
|
|
899
|
+
}
|
|
900
|
+
function isInstalledLocally(stack) {
|
|
901
|
+
const family = firstFamilyToken(stack);
|
|
902
|
+
if (!family) return false;
|
|
903
|
+
const ctx = document.createElement("canvas").getContext("2d");
|
|
904
|
+
if (!ctx) return false;
|
|
905
|
+
const widthOf = (spec) => {
|
|
906
|
+
ctx.font = `16px ${spec}`;
|
|
907
|
+
return ctx.measureText("가나다ABCwi").width;
|
|
908
|
+
};
|
|
909
|
+
return ["monospace", "serif"].some(
|
|
910
|
+
(fallback) => widthOf(`"${family}", ${fallback}`) !== widthOf(fallback)
|
|
911
|
+
);
|
|
912
|
+
}
|
|
913
|
+
function markUnavailable(fonts) {
|
|
914
|
+
let changed = false;
|
|
915
|
+
for (const font of fonts) {
|
|
916
|
+
if (unavailable.has(font.id)) continue;
|
|
917
|
+
if (isInstalledLocally(font.stack)) continue;
|
|
918
|
+
unavailable.add(font.id);
|
|
919
|
+
changed = true;
|
|
920
|
+
}
|
|
921
|
+
if (!changed) return;
|
|
922
|
+
for (const listener of listeners) listener();
|
|
923
|
+
}
|
|
924
|
+
function verifyLoaded(fonts) {
|
|
925
|
+
const set = document.fonts;
|
|
926
|
+
if (!set || typeof set.load !== "function") return;
|
|
927
|
+
for (const font of fonts) {
|
|
928
|
+
const family = firstFamilyToken(font.stack);
|
|
929
|
+
if (!family) continue;
|
|
930
|
+
set.load(`16px "${family}"`, SAMPLE_TEXT).then((faces) => {
|
|
931
|
+
if (faces.length === 0) markUnavailable([font]);
|
|
932
|
+
}).catch(() => markUnavailable([font]));
|
|
933
|
+
}
|
|
934
|
+
}
|
|
887
935
|
function ensureFontFamiliesLoaded() {
|
|
888
936
|
if (loaded) return;
|
|
889
937
|
loaded = true;
|
|
890
938
|
if (typeof document === "undefined") return;
|
|
891
|
-
const
|
|
892
|
-
if (
|
|
893
|
-
const url = "https://fonts.googleapis.com/css2?" +
|
|
894
|
-
appendStylesheet(url);
|
|
939
|
+
const googleFonts = FONT_FAMILIES.filter((f) => f.googleFonts);
|
|
940
|
+
if (googleFonts.length > 0) {
|
|
941
|
+
const url = "https://fonts.googleapis.com/css2?" + googleFonts.map((f) => `family=${f.googleFonts}`).join("&") + "&display=swap";
|
|
942
|
+
appendStylesheet(url, googleFonts);
|
|
895
943
|
}
|
|
896
|
-
for (const
|
|
897
|
-
if (
|
|
944
|
+
for (const font of FONT_FAMILIES) {
|
|
945
|
+
if (font.cssUrl) appendStylesheet(font.cssUrl, [font]);
|
|
898
946
|
}
|
|
899
947
|
}
|
|
900
|
-
function appendStylesheet(href) {
|
|
948
|
+
function appendStylesheet(href, provides) {
|
|
901
949
|
const existing = document.querySelector(
|
|
902
950
|
`link[rel="stylesheet"][href="${href}"]`
|
|
903
951
|
);
|
|
904
|
-
if (existing)
|
|
952
|
+
if (existing) {
|
|
953
|
+
verifyLoaded(provides);
|
|
954
|
+
return;
|
|
955
|
+
}
|
|
905
956
|
const link = document.createElement("link");
|
|
906
957
|
link.rel = "stylesheet";
|
|
907
958
|
link.href = href;
|
|
959
|
+
link.addEventListener("error", () => markUnavailable(provides));
|
|
960
|
+
link.addEventListener("load", () => verifyLoaded(provides));
|
|
908
961
|
document.head.appendChild(link);
|
|
909
962
|
}
|
|
910
963
|
function findFontIdFromCss(css) {
|
|
@@ -1632,9 +1685,9 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
1632
1685
|
return m;
|
|
1633
1686
|
})();
|
|
1634
1687
|
function highlightCode(code, langId) {
|
|
1635
|
-
if (!langId) return escapeHtml$
|
|
1688
|
+
if (!langId) return escapeHtml$2(code);
|
|
1636
1689
|
const lang = LANG_BY_ID.get(langId);
|
|
1637
|
-
if (!lang) return escapeHtml$
|
|
1690
|
+
if (!lang) return escapeHtml$2(code);
|
|
1638
1691
|
if (lang.custom) return lang.custom(code);
|
|
1639
1692
|
return tokenize(code, lang);
|
|
1640
1693
|
}
|
|
@@ -1648,14 +1701,14 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
1648
1701
|
if (lang.lineComment && code.startsWith(lang.lineComment, i)) {
|
|
1649
1702
|
const nl = code.indexOf("\n", i);
|
|
1650
1703
|
const stop = nl === -1 ? n : nl;
|
|
1651
|
-
out += `<span class="hl-comment">${escapeHtml$
|
|
1704
|
+
out += `<span class="hl-comment">${escapeHtml$2(code.slice(i, stop))}</span>`;
|
|
1652
1705
|
i = stop;
|
|
1653
1706
|
continue;
|
|
1654
1707
|
}
|
|
1655
1708
|
if (lang.blockComment && code.startsWith(lang.blockComment.start, i)) {
|
|
1656
1709
|
const closeAt = code.indexOf(lang.blockComment.end, i + lang.blockComment.start.length);
|
|
1657
1710
|
const stop = closeAt === -1 ? n : closeAt + lang.blockComment.end.length;
|
|
1658
|
-
out += `<span class="hl-comment">${escapeHtml$
|
|
1711
|
+
out += `<span class="hl-comment">${escapeHtml$2(code.slice(i, stop))}</span>`;
|
|
1659
1712
|
i = stop;
|
|
1660
1713
|
continue;
|
|
1661
1714
|
}
|
|
@@ -1675,7 +1728,7 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
1675
1728
|
if (c === "\n" && sd !== "`") break;
|
|
1676
1729
|
j++;
|
|
1677
1730
|
}
|
|
1678
|
-
out += `<span class="hl-string">${escapeHtml$
|
|
1731
|
+
out += `<span class="hl-string">${escapeHtml$2(code.slice(i, j))}</span>`;
|
|
1679
1732
|
i = j;
|
|
1680
1733
|
continue;
|
|
1681
1734
|
}
|
|
@@ -1683,7 +1736,7 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
1683
1736
|
if (/[0-9]/.test(ch)) {
|
|
1684
1737
|
const m = NUMBER_RE.exec(code.slice(i));
|
|
1685
1738
|
if (m) {
|
|
1686
|
-
out += `<span class="hl-number">${escapeHtml$
|
|
1739
|
+
out += `<span class="hl-number">${escapeHtml$2(m[0])}</span>`;
|
|
1687
1740
|
i += m[0].length;
|
|
1688
1741
|
continue;
|
|
1689
1742
|
}
|
|
@@ -1694,22 +1747,22 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
1694
1747
|
const word = code.slice(i, j);
|
|
1695
1748
|
const lookup = ci ? word.toLowerCase() : word;
|
|
1696
1749
|
if (lang.keywords.has(lookup)) {
|
|
1697
|
-
out += `<span class="hl-keyword">${escapeHtml$
|
|
1750
|
+
out += `<span class="hl-keyword">${escapeHtml$2(word)}</span>`;
|
|
1698
1751
|
} else if ((_b = lang.builtins) == null ? void 0 : _b.has(lookup)) {
|
|
1699
|
-
out += `<span class="hl-builtin">${escapeHtml$
|
|
1752
|
+
out += `<span class="hl-builtin">${escapeHtml$2(word)}</span>`;
|
|
1700
1753
|
} else {
|
|
1701
1754
|
let k = j;
|
|
1702
1755
|
while (k < n && (code[k] === " " || code[k] === " ")) k++;
|
|
1703
1756
|
if (code[k] === "(") {
|
|
1704
|
-
out += `<span class="hl-fn">${escapeHtml$
|
|
1757
|
+
out += `<span class="hl-fn">${escapeHtml$2(word)}</span>`;
|
|
1705
1758
|
} else {
|
|
1706
|
-
out += escapeHtml$
|
|
1759
|
+
out += escapeHtml$2(word);
|
|
1707
1760
|
}
|
|
1708
1761
|
}
|
|
1709
1762
|
i = j;
|
|
1710
1763
|
continue;
|
|
1711
1764
|
}
|
|
1712
|
-
out += escapeHtml$
|
|
1765
|
+
out += escapeHtml$2(ch);
|
|
1713
1766
|
i++;
|
|
1714
1767
|
}
|
|
1715
1768
|
return out;
|
|
@@ -1723,14 +1776,14 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
1723
1776
|
if (code.startsWith("<!--", i)) {
|
|
1724
1777
|
const end = code.indexOf("-->", i + 4);
|
|
1725
1778
|
const stop = end === -1 ? n : end + 3;
|
|
1726
|
-
out += `<span class="hl-comment">${escapeHtml$
|
|
1779
|
+
out += `<span class="hl-comment">${escapeHtml$2(code.slice(i, stop))}</span>`;
|
|
1727
1780
|
i = stop;
|
|
1728
1781
|
continue;
|
|
1729
1782
|
}
|
|
1730
1783
|
if (code[i] === "<") {
|
|
1731
1784
|
const end = code.indexOf(">", i);
|
|
1732
1785
|
if (end === -1) {
|
|
1733
|
-
out += escapeHtml$
|
|
1786
|
+
out += escapeHtml$2(code.slice(i));
|
|
1734
1787
|
break;
|
|
1735
1788
|
}
|
|
1736
1789
|
const tag = code.slice(i, end + 1);
|
|
@@ -1738,7 +1791,7 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
1738
1791
|
i = end + 1;
|
|
1739
1792
|
continue;
|
|
1740
1793
|
}
|
|
1741
|
-
out += escapeHtml$
|
|
1794
|
+
out += escapeHtml$2(code[i] ?? "");
|
|
1742
1795
|
i++;
|
|
1743
1796
|
}
|
|
1744
1797
|
return out;
|
|
@@ -1748,27 +1801,27 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
1748
1801
|
let result = '<span class="hl-punct"><</span>';
|
|
1749
1802
|
const nameMatch = /^\/?[a-zA-Z][a-zA-Z0-9-]*/.exec(inner);
|
|
1750
1803
|
if (nameMatch) {
|
|
1751
|
-
result += `<span class="hl-tag">${escapeHtml$
|
|
1804
|
+
result += `<span class="hl-tag">${escapeHtml$2(nameMatch[0])}</span>`;
|
|
1752
1805
|
let rest = inner.slice(nameMatch[0].length);
|
|
1753
1806
|
const ATTR_RE = /\s+([a-zA-Z_:][a-zA-Z0-9_:.-]*)(\s*=\s*("([^"]*)"|'([^']*)'|([^\s>]+)))?/g;
|
|
1754
1807
|
let last = 0;
|
|
1755
1808
|
let m;
|
|
1756
1809
|
while (m = ATTR_RE.exec(rest)) {
|
|
1757
|
-
result += escapeHtml$
|
|
1758
|
-
result += escapeHtml$
|
|
1759
|
-
result += `<span class="hl-attr">${escapeHtml$
|
|
1810
|
+
result += escapeHtml$2(rest.slice(last, m.index));
|
|
1811
|
+
result += escapeHtml$2(rest.slice(m.index, m.index + m[0].indexOf(m[1] ?? "")));
|
|
1812
|
+
result += `<span class="hl-attr">${escapeHtml$2(m[1] ?? "")}</span>`;
|
|
1760
1813
|
const valuePart = rest.slice(m.index + (m[0].indexOf(m[1] ?? "") + (m[1] ?? "").length), m.index + m[0].length);
|
|
1761
1814
|
if (valuePart.includes("=")) {
|
|
1762
1815
|
const eqIdx = valuePart.indexOf("=");
|
|
1763
|
-
result += escapeHtml$
|
|
1816
|
+
result += escapeHtml$2(valuePart.slice(0, eqIdx + 1));
|
|
1764
1817
|
const valueStr = valuePart.slice(eqIdx + 1);
|
|
1765
|
-
result += `<span class="hl-string">${escapeHtml$
|
|
1818
|
+
result += `<span class="hl-string">${escapeHtml$2(valueStr)}</span>`;
|
|
1766
1819
|
}
|
|
1767
1820
|
last = m.index + m[0].length;
|
|
1768
1821
|
}
|
|
1769
|
-
result += escapeHtml$
|
|
1822
|
+
result += escapeHtml$2(rest.slice(last));
|
|
1770
1823
|
} else {
|
|
1771
|
-
result += escapeHtml$
|
|
1824
|
+
result += escapeHtml$2(inner);
|
|
1772
1825
|
}
|
|
1773
1826
|
result += '<span class="hl-punct">></span>';
|
|
1774
1827
|
return result;
|
|
@@ -1782,20 +1835,20 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
1782
1835
|
if (code.startsWith("/*", i)) {
|
|
1783
1836
|
const end = code.indexOf("*/", i + 2);
|
|
1784
1837
|
const stop = end === -1 ? n : end + 2;
|
|
1785
|
-
out += `<span class="hl-comment">${escapeHtml$
|
|
1838
|
+
out += `<span class="hl-comment">${escapeHtml$2(code.slice(i, stop))}</span>`;
|
|
1786
1839
|
i = stop;
|
|
1787
1840
|
continue;
|
|
1788
1841
|
}
|
|
1789
1842
|
const ch = code[i] ?? "";
|
|
1790
1843
|
if (ch === "{") {
|
|
1791
1844
|
inBlock = true;
|
|
1792
|
-
out += escapeHtml$
|
|
1845
|
+
out += escapeHtml$2(ch);
|
|
1793
1846
|
i++;
|
|
1794
1847
|
continue;
|
|
1795
1848
|
}
|
|
1796
1849
|
if (ch === "}") {
|
|
1797
1850
|
inBlock = false;
|
|
1798
|
-
out += escapeHtml$
|
|
1851
|
+
out += escapeHtml$2(ch);
|
|
1799
1852
|
i++;
|
|
1800
1853
|
continue;
|
|
1801
1854
|
}
|
|
@@ -1807,7 +1860,7 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
1807
1860
|
else j++;
|
|
1808
1861
|
}
|
|
1809
1862
|
j = Math.min(j + 1, n);
|
|
1810
|
-
out += `<span class="hl-string">${escapeHtml$
|
|
1863
|
+
out += `<span class="hl-string">${escapeHtml$2(code.slice(i, j))}</span>`;
|
|
1811
1864
|
i = j;
|
|
1812
1865
|
continue;
|
|
1813
1866
|
}
|
|
@@ -1816,17 +1869,17 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
1816
1869
|
while (j < n && /[a-zA-Z0-9_-]/.test(code[j] ?? "")) j++;
|
|
1817
1870
|
const word = code.slice(i, j);
|
|
1818
1871
|
if (ch === "@") {
|
|
1819
|
-
out += `<span class="hl-keyword">${escapeHtml$
|
|
1872
|
+
out += `<span class="hl-keyword">${escapeHtml$2(word)}</span>`;
|
|
1820
1873
|
} else if (inBlock && /^[a-zA-Z-]+$/.test(word)) {
|
|
1821
1874
|
let k = j;
|
|
1822
1875
|
while (k < n && (code[k] === " " || code[k] === " ")) k++;
|
|
1823
1876
|
if (code[k] === ":") {
|
|
1824
|
-
out += `<span class="hl-prop">${escapeHtml$
|
|
1877
|
+
out += `<span class="hl-prop">${escapeHtml$2(word)}</span>`;
|
|
1825
1878
|
} else {
|
|
1826
|
-
out += escapeHtml$
|
|
1879
|
+
out += escapeHtml$2(word);
|
|
1827
1880
|
}
|
|
1828
1881
|
} else {
|
|
1829
|
-
out += `<span class="hl-tag">${escapeHtml$
|
|
1882
|
+
out += `<span class="hl-tag">${escapeHtml$2(word)}</span>`;
|
|
1830
1883
|
}
|
|
1831
1884
|
i = j;
|
|
1832
1885
|
continue;
|
|
@@ -1834,12 +1887,12 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
1834
1887
|
if (/[0-9]/.test(ch)) {
|
|
1835
1888
|
const m = /^[0-9.]+(px|em|rem|%|vh|vw|s|ms|deg|fr)?/.exec(code.slice(i));
|
|
1836
1889
|
if (m) {
|
|
1837
|
-
out += `<span class="hl-number">${escapeHtml$
|
|
1890
|
+
out += `<span class="hl-number">${escapeHtml$2(m[0])}</span>`;
|
|
1838
1891
|
i += m[0].length;
|
|
1839
1892
|
continue;
|
|
1840
1893
|
}
|
|
1841
1894
|
}
|
|
1842
|
-
out += escapeHtml$
|
|
1895
|
+
out += escapeHtml$2(ch);
|
|
1843
1896
|
i++;
|
|
1844
1897
|
}
|
|
1845
1898
|
return out;
|
|
@@ -1850,22 +1903,22 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
1850
1903
|
function highlightMdLine(line) {
|
|
1851
1904
|
const h = /^(#{1,6})\s+(.*)$/.exec(line);
|
|
1852
1905
|
if (h) {
|
|
1853
|
-
return `<span class="hl-keyword">${escapeHtml$
|
|
1906
|
+
return `<span class="hl-keyword">${escapeHtml$2(h[1] ?? "")}</span> <span class="hl-tag">${highlightMdInline(h[2] ?? "")}</span>`;
|
|
1854
1907
|
}
|
|
1855
1908
|
if (line.startsWith(">")) {
|
|
1856
|
-
return `<span class="hl-comment">${escapeHtml$
|
|
1909
|
+
return `<span class="hl-comment">${escapeHtml$2(line)}</span>`;
|
|
1857
1910
|
}
|
|
1858
1911
|
if (line.startsWith("```")) {
|
|
1859
|
-
return `<span class="hl-keyword">${escapeHtml$
|
|
1912
|
+
return `<span class="hl-keyword">${escapeHtml$2(line)}</span>`;
|
|
1860
1913
|
}
|
|
1861
1914
|
const li = /^(\s*)([-*+]|\d+\.)\s+(.*)$/.exec(line);
|
|
1862
1915
|
if (li) {
|
|
1863
|
-
return `${li[1] ?? ""}<span class="hl-keyword">${escapeHtml$
|
|
1916
|
+
return `${li[1] ?? ""}<span class="hl-keyword">${escapeHtml$2(li[2] ?? "")}</span> ${highlightMdInline(li[3] ?? "")}`;
|
|
1864
1917
|
}
|
|
1865
1918
|
return highlightMdInline(line);
|
|
1866
1919
|
}
|
|
1867
1920
|
function highlightMdInline(s) {
|
|
1868
|
-
let out = escapeHtml$
|
|
1921
|
+
let out = escapeHtml$2(s);
|
|
1869
1922
|
out = out.replace(/\*\*([^*]+)\*\*/g, '<span class="hl-keyword">**$1**</span>');
|
|
1870
1923
|
out = out.replace(new RegExp("(?<!\\*)\\*([^*]+)\\*(?!\\*)", "g"), '<span class="hl-string">*$1*</span>');
|
|
1871
1924
|
out = out.replace(/`([^`]+)`/g, '<span class="hl-builtin">`$1`</span>');
|
|
@@ -1875,7 +1928,7 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
1875
1928
|
);
|
|
1876
1929
|
return out;
|
|
1877
1930
|
}
|
|
1878
|
-
function escapeHtml$
|
|
1931
|
+
function escapeHtml$2(s) {
|
|
1879
1932
|
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
1880
1933
|
}
|
|
1881
1934
|
function preserveSelection(el) {
|
|
@@ -2146,31 +2199,42 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
2146
2199
|
popover.className = "aw-popover aw-font-family-popover";
|
|
2147
2200
|
popover.dataset.popover = "true";
|
|
2148
2201
|
preserveSelection(popover);
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
btn.
|
|
2202
|
+
const render = () => {
|
|
2203
|
+
popover.replaceChildren();
|
|
2204
|
+
for (const font of getAvailableFontFamilies()) {
|
|
2205
|
+
const btn = document.createElement("button");
|
|
2206
|
+
btn.type = "button";
|
|
2207
|
+
btn.className = "aw-popover-item aw-font-family-item";
|
|
2208
|
+
if (currentId && currentId === font.id) {
|
|
2209
|
+
btn.classList.add("aw-popover-item-active");
|
|
2210
|
+
}
|
|
2211
|
+
btn.title = font.label;
|
|
2212
|
+
const name = document.createElement("span");
|
|
2213
|
+
name.className = "aw-font-family-name";
|
|
2214
|
+
name.textContent = font.label;
|
|
2215
|
+
const preview = document.createElement("span");
|
|
2216
|
+
preview.className = "aw-font-family-preview";
|
|
2217
|
+
preview.textContent = "가A";
|
|
2218
|
+
preview.style.fontFamily = font.stack;
|
|
2219
|
+
btn.appendChild(name);
|
|
2220
|
+
btn.appendChild(preview);
|
|
2221
|
+
preserveSelection(btn);
|
|
2222
|
+
btn.addEventListener("click", (e) => {
|
|
2223
|
+
e.stopPropagation();
|
|
2224
|
+
popover.remove();
|
|
2225
|
+
onPick({ id: font.id, label: font.label, stack: font.stack });
|
|
2226
|
+
});
|
|
2227
|
+
popover.appendChild(btn);
|
|
2155
2228
|
}
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
btn.appendChild(preview);
|
|
2166
|
-
preserveSelection(btn);
|
|
2167
|
-
btn.addEventListener("click", (e) => {
|
|
2168
|
-
e.stopPropagation();
|
|
2169
|
-
popover.remove();
|
|
2170
|
-
onPick({ id: font.id, label: font.label, stack: font.stack });
|
|
2171
|
-
});
|
|
2172
|
-
popover.appendChild(btn);
|
|
2173
|
-
}
|
|
2229
|
+
};
|
|
2230
|
+
render();
|
|
2231
|
+
const unsubscribe = subscribeFontAvailability(() => {
|
|
2232
|
+
if (!popover.isConnected) {
|
|
2233
|
+
unsubscribe();
|
|
2234
|
+
return;
|
|
2235
|
+
}
|
|
2236
|
+
render();
|
|
2237
|
+
});
|
|
2174
2238
|
anchorPopover(popover, anchor);
|
|
2175
2239
|
}
|
|
2176
2240
|
function openCodeLanguageDropdown(anchor, onPick, currentId) {
|
|
@@ -2501,6 +2565,24 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
2501
2565
|
"stroke-width",
|
|
2502
2566
|
"text-anchor"
|
|
2503
2567
|
]);
|
|
2568
|
+
const CURRENT_COLOR_DEFAULTED = /* @__PURE__ */ new Set([
|
|
2569
|
+
"border-block-end-color",
|
|
2570
|
+
"border-block-start-color",
|
|
2571
|
+
"border-bottom-color",
|
|
2572
|
+
"border-inline-end-color",
|
|
2573
|
+
"border-inline-start-color",
|
|
2574
|
+
"border-left-color",
|
|
2575
|
+
"border-right-color",
|
|
2576
|
+
"border-top-color",
|
|
2577
|
+
"caret-color",
|
|
2578
|
+
"column-rule-color",
|
|
2579
|
+
"row-rule-color",
|
|
2580
|
+
"outline-color",
|
|
2581
|
+
"text-decoration-color",
|
|
2582
|
+
"text-emphasis-color",
|
|
2583
|
+
"-webkit-text-fill-color",
|
|
2584
|
+
"-webkit-text-stroke-color"
|
|
2585
|
+
]);
|
|
2504
2586
|
async function importHtmlWithComputedStyles(html, options = {}) {
|
|
2505
2587
|
const settleMs = options.settleMs ?? 1e3;
|
|
2506
2588
|
const timeoutMs = options.timeoutMs ?? 3e4;
|
|
@@ -2657,8 +2739,8 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
2657
2739
|
};
|
|
2658
2740
|
return { get, cleanup };
|
|
2659
2741
|
}
|
|
2660
|
-
function computeMinimalInline(el, parent, baselineTagName, getBaseline, win) {
|
|
2661
|
-
const cs = win.getComputedStyle(el);
|
|
2742
|
+
function computeMinimalInline(el, parent, baselineTagName, getBaseline, win, pseudo) {
|
|
2743
|
+
const cs = win.getComputedStyle(el, pseudo ?? null);
|
|
2662
2744
|
const parentCs = parent ? win.getComputedStyle(parent) : null;
|
|
2663
2745
|
const baseline = getBaseline(baselineTagName);
|
|
2664
2746
|
let cssText = "";
|
|
@@ -2667,6 +2749,8 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
2667
2749
|
if (!prop) continue;
|
|
2668
2750
|
const val = cs.getPropertyValue(prop);
|
|
2669
2751
|
if (!val) continue;
|
|
2752
|
+
if (pseudo && prop === "content") continue;
|
|
2753
|
+
if (CURRENT_COLOR_DEFAULTED.has(prop) && val === cs.getPropertyValue("color")) continue;
|
|
2670
2754
|
if (INHERITED_PROPERTIES.has(prop)) {
|
|
2671
2755
|
if (parentCs && parentCs.getPropertyValue(prop) === val) continue;
|
|
2672
2756
|
} else {
|
|
@@ -2676,6 +2760,56 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
2676
2760
|
}
|
|
2677
2761
|
return cssText;
|
|
2678
2762
|
}
|
|
2763
|
+
function textFromCssContent(value) {
|
|
2764
|
+
let text = "";
|
|
2765
|
+
const segments = /"((?:[^"\\]|\\.)*)"|'((?:[^'\\]|\\.)*)'/g;
|
|
2766
|
+
let match;
|
|
2767
|
+
while ((match = segments.exec(value)) !== null) {
|
|
2768
|
+
const raw = match[1] ?? match[2] ?? "";
|
|
2769
|
+
text += raw.replace(
|
|
2770
|
+
/\\(?:([0-9a-fA-F]{1,6})\s?|(.))/g,
|
|
2771
|
+
(_all, hex, ch) => hex ? String.fromCodePoint(parseInt(hex, 16)) : ch ?? ""
|
|
2772
|
+
);
|
|
2773
|
+
}
|
|
2774
|
+
return text;
|
|
2775
|
+
}
|
|
2776
|
+
const NO_PHRASING_CHILDREN = /* @__PURE__ */ new Set([
|
|
2777
|
+
"TABLE",
|
|
2778
|
+
"THEAD",
|
|
2779
|
+
"TBODY",
|
|
2780
|
+
"TFOOT",
|
|
2781
|
+
"TR",
|
|
2782
|
+
"UL",
|
|
2783
|
+
"OL",
|
|
2784
|
+
"DL",
|
|
2785
|
+
"SELECT",
|
|
2786
|
+
"OPTGROUP"
|
|
2787
|
+
]);
|
|
2788
|
+
function materializePseudo(orig, copy, which, getBaseline, win) {
|
|
2789
|
+
if (NO_PHRASING_CHILDREN.has(copy.tagName)) return;
|
|
2790
|
+
const selector = which === "before" ? "::before" : "::after";
|
|
2791
|
+
const cs = win.getComputedStyle(orig, selector);
|
|
2792
|
+
const content = cs.getPropertyValue("content");
|
|
2793
|
+
if (!content || content === "none" || content === "normal") return;
|
|
2794
|
+
if (cs.getPropertyValue("display") === "none") return;
|
|
2795
|
+
const text = textFromCssContent(content);
|
|
2796
|
+
const url = /url\((["']?)([^"')]+)\1\)/.exec(content);
|
|
2797
|
+
const cssText = computeMinimalInline(orig, orig, "span", getBaseline, win, selector);
|
|
2798
|
+
if (!text && !url && !cssText) return;
|
|
2799
|
+
const doc = copy.ownerDocument;
|
|
2800
|
+
const span = doc.createElement("span");
|
|
2801
|
+
span.setAttribute("data-imported-pseudo", which);
|
|
2802
|
+
if (cssText) span.setAttribute("style", cssText);
|
|
2803
|
+
if (url == null ? void 0 : url[2]) {
|
|
2804
|
+
const img = doc.createElement("img");
|
|
2805
|
+
img.setAttribute("src", url[2]);
|
|
2806
|
+
img.setAttribute("alt", "");
|
|
2807
|
+
span.appendChild(img);
|
|
2808
|
+
}
|
|
2809
|
+
if (text) span.appendChild(doc.createTextNode(text));
|
|
2810
|
+
if (which === "before") copy.insertBefore(span, copy.firstChild);
|
|
2811
|
+
else copy.appendChild(span);
|
|
2812
|
+
}
|
|
2679
2813
|
function applyComputedStylesParallel(orig, copy, origParent, getBaseline, win) {
|
|
2680
2814
|
if (orig.nodeType === 1 && copy.nodeType === 1) {
|
|
2681
2815
|
const cssText = computeMinimalInline(
|
|
@@ -2699,6 +2833,10 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
2699
2833
|
const cc = copyChildren[i];
|
|
2700
2834
|
if (oc && cc) applyComputedStylesParallel(oc, cc, orig, getBaseline, win);
|
|
2701
2835
|
}
|
|
2836
|
+
if (orig.nodeType === 1 && copy.nodeType === 1) {
|
|
2837
|
+
materializePseudo(orig, copy, "before", getBaseline, win);
|
|
2838
|
+
materializePseudo(orig, copy, "after", getBaseline, win);
|
|
2839
|
+
}
|
|
2702
2840
|
}
|
|
2703
2841
|
function markdownToBlocks(md) {
|
|
2704
2842
|
const html = markdownToHtml(md);
|
|
@@ -2731,9 +2869,9 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
2731
2869
|
i++;
|
|
2732
2870
|
}
|
|
2733
2871
|
if (i < lines.length) i++;
|
|
2734
|
-
const langAttr = lang ? ` data-language="${escapeAttr(lang)}"` : "";
|
|
2872
|
+
const langAttr = lang ? ` data-language="${escapeAttr$1(lang)}"` : "";
|
|
2735
2873
|
blocks.push(
|
|
2736
|
-
`<pre><code${langAttr}>${escapeHtml(codeLines.join("\n"))}</code></pre>`
|
|
2874
|
+
`<pre><code${langAttr}>${escapeHtml$1(codeLines.join("\n"))}</code></pre>`
|
|
2737
2875
|
);
|
|
2738
2876
|
continue;
|
|
2739
2877
|
}
|
|
@@ -2867,42 +3005,115 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
2867
3005
|
}
|
|
2868
3006
|
return parts.join("");
|
|
2869
3007
|
}
|
|
3008
|
+
const CODE_SLOT = String.fromCharCode(57600);
|
|
3009
|
+
const CODE_SLOT_RE = new RegExp(CODE_SLOT + "([0-9]+)" + CODE_SLOT, "g");
|
|
2870
3010
|
function parseInline(src) {
|
|
2871
3011
|
const codes = [];
|
|
2872
3012
|
let working = src.replace(/(`+)([\s\S]+?)\1/g, (_m, _b, code) => {
|
|
2873
|
-
const idx = codes.push(`<code>${escapeHtml(code)}</code>`) - 1;
|
|
2874
|
-
return
|
|
3013
|
+
const idx = codes.push(`<code>${escapeHtml$1(code)}</code>`) - 1;
|
|
3014
|
+
return `${CODE_SLOT}${idx}${CODE_SLOT}`;
|
|
2875
3015
|
});
|
|
2876
|
-
working = escapeHtml(working);
|
|
3016
|
+
working = escapeHtml$1(working);
|
|
2877
3017
|
working = working.replace(
|
|
2878
3018
|
/<(https?:\/\/[^\s&]+)>/g,
|
|
2879
|
-
(_m, url) => `<a href="${escapeAttr(url)}" target="_blank" rel="noopener">${escapeHtml(url)}</a>`
|
|
3019
|
+
(_m, url) => `<a href="${escapeAttr$1(url)}" target="_blank" rel="noopener">${escapeHtml$1(url)}</a>`
|
|
2880
3020
|
);
|
|
2881
3021
|
working = working.replace(
|
|
2882
3022
|
/!\[([^\]]*)\]\(([^)\s]+)(?:\s+"[^"]*")?\)/g,
|
|
2883
|
-
(_m, alt, url) => `<img src="${escapeAttr(url)}" alt="${escapeAttr(alt)}">`
|
|
3023
|
+
(_m, alt, url) => `<img src="${escapeAttr$1(url)}" alt="${escapeAttr$1(alt)}">`
|
|
2884
3024
|
);
|
|
2885
3025
|
working = working.replace(
|
|
2886
3026
|
/\[([^\]]+)\]\(([^)\s]+)(?:\s+"[^"]*")?\)/g,
|
|
2887
|
-
(_m, text, url) => `<a href="${escapeAttr(url)}" target="_blank" rel="noopener">${text}</a>`
|
|
3027
|
+
(_m, text, url) => `<a href="${escapeAttr$1(url)}" target="_blank" rel="noopener">${text}</a>`
|
|
2888
3028
|
);
|
|
2889
3029
|
working = working.replace(/\*\*([^*\n]+?)\*\*/g, "<strong>$1</strong>");
|
|
2890
3030
|
working = working.replace(/__([^_\n]+?)__/g, "<strong>$1</strong>");
|
|
2891
3031
|
working = working.replace(/(^|[^*])\*([^*\n]+?)\*(?!\*)/g, "$1<em>$2</em>");
|
|
2892
3032
|
working = working.replace(/(^|[^_])_([^_\n]+?)_(?!_)/g, "$1<em>$2</em>");
|
|
2893
3033
|
working = working.replace(/~~([^~\n]+?)~~/g, "<s>$1</s>");
|
|
2894
|
-
working = working.replace(
|
|
3034
|
+
working = working.replace(CODE_SLOT_RE, (_m, n) => {
|
|
2895
3035
|
const idx = Number(n);
|
|
2896
3036
|
return codes[idx] ?? "";
|
|
2897
3037
|
});
|
|
2898
3038
|
return working;
|
|
2899
3039
|
}
|
|
2900
|
-
function escapeHtml(s) {
|
|
3040
|
+
function escapeHtml$1(s) {
|
|
2901
3041
|
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
2902
3042
|
}
|
|
2903
|
-
function escapeAttr(s) {
|
|
3043
|
+
function escapeAttr$1(s) {
|
|
2904
3044
|
return s.replace(/&/g, "&").replace(/"/g, """);
|
|
2905
3045
|
}
|
|
3046
|
+
function formatBytes(bytes) {
|
|
3047
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
3048
|
+
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
3049
|
+
if (bytes < 1024 * 1024 * 1024) return `${(bytes / 1024 / 1024).toFixed(1)} MB`;
|
|
3050
|
+
return `${(bytes / 1024 / 1024 / 1024).toFixed(1)} GB`;
|
|
3051
|
+
}
|
|
3052
|
+
function fileExtensionLabel(name, mime) {
|
|
3053
|
+
if (name) {
|
|
3054
|
+
const idx = name.lastIndexOf(".");
|
|
3055
|
+
if (idx > 0 && idx < name.length - 1) {
|
|
3056
|
+
return name.slice(idx + 1).toUpperCase();
|
|
3057
|
+
}
|
|
3058
|
+
}
|
|
3059
|
+
if (mime) {
|
|
3060
|
+
const sub = mime.split("/").pop() ?? "";
|
|
3061
|
+
return sub.toUpperCase();
|
|
3062
|
+
}
|
|
3063
|
+
return "";
|
|
3064
|
+
}
|
|
3065
|
+
function hostnameFromUrl(url) {
|
|
3066
|
+
try {
|
|
3067
|
+
return new URL(url).hostname;
|
|
3068
|
+
} catch {
|
|
3069
|
+
return "";
|
|
3070
|
+
}
|
|
3071
|
+
}
|
|
3072
|
+
function defaultFaviconUrl(url) {
|
|
3073
|
+
const host = hostnameFromUrl(url);
|
|
3074
|
+
if (!host) return "";
|
|
3075
|
+
return `https://www.google.com/s2/favicons?domain=${encodeURIComponent(host)}&sz=64`;
|
|
3076
|
+
}
|
|
3077
|
+
const FILE_ICON_SVG = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14 3H6a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"/><path d="M14 3v6h6"/></svg>';
|
|
3078
|
+
const FILE_ACTION_SVG = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>';
|
|
3079
|
+
const YOUTUBE_IFRAME_ALLOW = "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture";
|
|
3080
|
+
const YOUTUBE_EMBED_BASE = "https://www.youtube-nocookie.com/embed/";
|
|
3081
|
+
const FILE_FALLBACK_NAME = "파일";
|
|
3082
|
+
const BLOCK_ID_ATTR = "data-block-id";
|
|
3083
|
+
const SNAPSHOT_VERSION = 1;
|
|
3084
|
+
function snapshotVersionOf(snapshot) {
|
|
3085
|
+
const raw = snapshot.version;
|
|
3086
|
+
return typeof raw === "number" && Number.isFinite(raw) && raw > 0 ? raw : 1;
|
|
3087
|
+
}
|
|
3088
|
+
const KNOWN_KINDS = /* @__PURE__ */ new Set([
|
|
3089
|
+
"paragraph",
|
|
3090
|
+
"heading",
|
|
3091
|
+
"bulletList",
|
|
3092
|
+
"orderedList",
|
|
3093
|
+
"blockquote",
|
|
3094
|
+
"codeBlock",
|
|
3095
|
+
"image",
|
|
3096
|
+
"table",
|
|
3097
|
+
"hr",
|
|
3098
|
+
"linkCard",
|
|
3099
|
+
"youtube",
|
|
3100
|
+
"file",
|
|
3101
|
+
"importedHtml",
|
|
3102
|
+
"unknown"
|
|
3103
|
+
]);
|
|
3104
|
+
function upgradeSnapshots(input) {
|
|
3105
|
+
return input.map((snap) => upgradeSnapshot(snap));
|
|
3106
|
+
}
|
|
3107
|
+
function upgradeSnapshot(snapshot) {
|
|
3108
|
+
const kind = KNOWN_KINDS.has(snapshot.kind) ? snapshot.kind : "unknown";
|
|
3109
|
+
const version = Math.max(snapshotVersionOf(snapshot), 1);
|
|
3110
|
+
return {
|
|
3111
|
+
...snapshot,
|
|
3112
|
+
kind,
|
|
3113
|
+
version,
|
|
3114
|
+
html: typeof snapshot.html === "string" ? snapshot.html : ""
|
|
3115
|
+
};
|
|
3116
|
+
}
|
|
2906
3117
|
const ALL_INLINE_MARKS = [
|
|
2907
3118
|
"bold",
|
|
2908
3119
|
"italic",
|
|
@@ -3146,12 +3357,9 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
3146
3357
|
if (attrs == null ? void 0 : attrs.wrapperStyle) wrap.setAttribute("style", attrs.wrapperStyle);
|
|
3147
3358
|
const iframe = document.createElement("iframe");
|
|
3148
3359
|
if (videoId) {
|
|
3149
|
-
iframe.src =
|
|
3360
|
+
iframe.src = `${YOUTUBE_EMBED_BASE}${videoId}`;
|
|
3150
3361
|
}
|
|
3151
|
-
iframe.setAttribute(
|
|
3152
|
-
"allow",
|
|
3153
|
-
"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
|
3154
|
-
);
|
|
3362
|
+
iframe.setAttribute("allow", YOUTUBE_IFRAME_ALLOW);
|
|
3155
3363
|
iframe.setAttribute("allowfullscreen", "");
|
|
3156
3364
|
iframe.setAttribute("frameborder", "0");
|
|
3157
3365
|
iframe.setAttribute("referrerpolicy", "strict-origin-when-cross-origin");
|
|
@@ -3239,18 +3447,6 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
3239
3447
|
},
|
|
3240
3448
|
isEmpty: (el) => !el.getAttribute("href")
|
|
3241
3449
|
};
|
|
3242
|
-
function hostnameFromUrl(url) {
|
|
3243
|
-
try {
|
|
3244
|
-
return new URL(url).hostname;
|
|
3245
|
-
} catch {
|
|
3246
|
-
return "";
|
|
3247
|
-
}
|
|
3248
|
-
}
|
|
3249
|
-
function defaultFaviconUrl(url) {
|
|
3250
|
-
const host = hostnameFromUrl(url);
|
|
3251
|
-
if (!host) return "";
|
|
3252
|
-
return `https://www.google.com/s2/favicons?domain=${encodeURIComponent(host)}&sz=64`;
|
|
3253
|
-
}
|
|
3254
3450
|
const FILE = {
|
|
3255
3451
|
kind: "file",
|
|
3256
3452
|
label: "파일",
|
|
@@ -3289,12 +3485,12 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
3289
3485
|
const iconSpan = document.createElement("span");
|
|
3290
3486
|
iconSpan.className = "aw-file-icon";
|
|
3291
3487
|
iconSpan.setAttribute("aria-hidden", "true");
|
|
3292
|
-
iconSpan.innerHTML =
|
|
3488
|
+
iconSpan.innerHTML = FILE_ICON_SVG;
|
|
3293
3489
|
const meta = document.createElement("span");
|
|
3294
3490
|
meta.className = "aw-file-meta";
|
|
3295
3491
|
const nameSpan = document.createElement("span");
|
|
3296
3492
|
nameSpan.className = "aw-file-name";
|
|
3297
|
-
nameSpan.textContent = (attrs == null ? void 0 : attrs.fileName) ??
|
|
3493
|
+
nameSpan.textContent = (attrs == null ? void 0 : attrs.fileName) ?? FILE_FALLBACK_NAME;
|
|
3298
3494
|
meta.appendChild(nameSpan);
|
|
3299
3495
|
const infoParts = [];
|
|
3300
3496
|
const ext = fileExtensionLabel(attrs == null ? void 0 : attrs.fileName, attrs == null ? void 0 : attrs.fileType);
|
|
@@ -3309,7 +3505,7 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
3309
3505
|
const action = document.createElement("span");
|
|
3310
3506
|
action.className = "aw-file-action";
|
|
3311
3507
|
action.setAttribute("aria-hidden", "true");
|
|
3312
|
-
action.innerHTML =
|
|
3508
|
+
action.innerHTML = FILE_ACTION_SVG;
|
|
3313
3509
|
a.appendChild(iconSpan);
|
|
3314
3510
|
a.appendChild(meta);
|
|
3315
3511
|
a.appendChild(action);
|
|
@@ -3317,25 +3513,6 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
3317
3513
|
},
|
|
3318
3514
|
isEmpty: (el) => !el.getAttribute("href")
|
|
3319
3515
|
};
|
|
3320
|
-
function formatBytes(bytes) {
|
|
3321
|
-
if (bytes < 1024) return `${bytes} B`;
|
|
3322
|
-
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
3323
|
-
if (bytes < 1024 * 1024 * 1024) return `${(bytes / 1024 / 1024).toFixed(1)} MB`;
|
|
3324
|
-
return `${(bytes / 1024 / 1024 / 1024).toFixed(1)} GB`;
|
|
3325
|
-
}
|
|
3326
|
-
function fileExtensionLabel(name, mime) {
|
|
3327
|
-
if (name) {
|
|
3328
|
-
const idx = name.lastIndexOf(".");
|
|
3329
|
-
if (idx > 0 && idx < name.length - 1) {
|
|
3330
|
-
return name.slice(idx + 1).toUpperCase();
|
|
3331
|
-
}
|
|
3332
|
-
}
|
|
3333
|
-
if (mime) {
|
|
3334
|
-
const sub = mime.split("/").pop() ?? "";
|
|
3335
|
-
return sub.toUpperCase();
|
|
3336
|
-
}
|
|
3337
|
-
return "";
|
|
3338
|
-
}
|
|
3339
3516
|
const IMPORTED_HTML = {
|
|
3340
3517
|
kind: "importedHtml",
|
|
3341
3518
|
label: "HTML",
|
|
@@ -3370,7 +3547,11 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
3370
3547
|
allowsColor: false,
|
|
3371
3548
|
allowsFontSize: false,
|
|
3372
3549
|
matches: () => null,
|
|
3373
|
-
|
|
3550
|
+
// `<div>` 로 만든다. unknown 은 미래 버전의 블록이 강등되어 오는 자리이고,
|
|
3551
|
+
// 그 html 에 블록 레벨 요소가 들어 있을 수 있다. `<p>` 로 감싸면 브라우저가
|
|
3552
|
+
// 단락을 조기에 닫아 내용이 래퍼 밖으로 튀어나간다 (문자열 렌더러
|
|
3553
|
+
// render-string.ts 도 같은 이유로 div 를 쓴다 — 두 경로가 일치해야 한다).
|
|
3554
|
+
create: () => fillEmpty(document.createElement("div")),
|
|
3374
3555
|
isEmpty: (el) => isElementBlank(el)
|
|
3375
3556
|
};
|
|
3376
3557
|
const BLOCK_TYPES = [
|
|
@@ -3400,7 +3581,6 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
3400
3581
|
}
|
|
3401
3582
|
return { type: UNKNOWN, match: { kind: "unknown", attrs: {} } };
|
|
3402
3583
|
}
|
|
3403
|
-
const BLOCK_ID_ATTR = "data-block-id";
|
|
3404
3584
|
class BlockIdRegistry {
|
|
3405
3585
|
constructor() {
|
|
3406
3586
|
__publicField(this, "counter", 0);
|
|
@@ -3457,6 +3637,7 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
3457
3637
|
}
|
|
3458
3638
|
}
|
|
3459
3639
|
function normalizeContent(root) {
|
|
3640
|
+
restoreAlignFromClasses(root);
|
|
3460
3641
|
for (const node of Array.from(root.childNodes)) {
|
|
3461
3642
|
if (node.nodeType !== Node.TEXT_NODE) continue;
|
|
3462
3643
|
const text = node.textContent ?? "";
|
|
@@ -3531,13 +3712,25 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
3531
3712
|
}
|
|
3532
3713
|
}
|
|
3533
3714
|
function serializeBlock(block) {
|
|
3715
|
+
const style = block.element.getAttribute("style");
|
|
3534
3716
|
return {
|
|
3717
|
+
version: SNAPSHOT_VERSION,
|
|
3535
3718
|
id: block.id,
|
|
3536
3719
|
kind: block.kind,
|
|
3537
3720
|
attrs: { ...block.attrs },
|
|
3538
|
-
html: block.element
|
|
3721
|
+
html: innerHtmlWithoutChrome(block.element),
|
|
3722
|
+
// 빈 문자열은 굳이 싣지 않는다 — 스냅샷이 커지기만 한다.
|
|
3723
|
+
...style ? { style } : {}
|
|
3539
3724
|
};
|
|
3540
3725
|
}
|
|
3726
|
+
function innerHtmlWithoutChrome(element) {
|
|
3727
|
+
if (!element.querySelector(".aw-block-align-controls, .aw-resize-handle")) {
|
|
3728
|
+
return element.innerHTML;
|
|
3729
|
+
}
|
|
3730
|
+
const clone = element.cloneNode(true);
|
|
3731
|
+
stripEditorOnlyNodes(clone);
|
|
3732
|
+
return clone.innerHTML;
|
|
3733
|
+
}
|
|
3541
3734
|
function serializeBlocks(blocks) {
|
|
3542
3735
|
return blocks.map(serializeBlock);
|
|
3543
3736
|
}
|
|
@@ -3545,6 +3738,7 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
3545
3738
|
const type = BLOCK_TYPE_BY_KIND[snapshot.kind] ?? BLOCK_TYPE_BY_KIND.unknown;
|
|
3546
3739
|
const el = type.create(snapshot.attrs);
|
|
3547
3740
|
el.setAttribute(BLOCK_ID_ATTR, snapshot.id);
|
|
3741
|
+
if (snapshot.style) el.setAttribute("style", snapshot.style);
|
|
3548
3742
|
if (snapshot.html.length > 0) {
|
|
3549
3743
|
el.innerHTML = snapshot.html;
|
|
3550
3744
|
}
|
|
@@ -3552,7 +3746,7 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
3552
3746
|
}
|
|
3553
3747
|
function renderBlocks(root, snapshots) {
|
|
3554
3748
|
while (root.firstChild) root.removeChild(root.firstChild);
|
|
3555
|
-
for (const snap of snapshots) {
|
|
3749
|
+
for (const snap of upgradeSnapshots(snapshots)) {
|
|
3556
3750
|
root.appendChild(renderBlock(snap));
|
|
3557
3751
|
}
|
|
3558
3752
|
}
|
|
@@ -3888,6 +4082,57 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
3888
4082
|
}
|
|
3889
4083
|
return out;
|
|
3890
4084
|
}
|
|
4085
|
+
const ALIGN_CLASS_BY_VALUE = {
|
|
4086
|
+
left: "aw-align-left",
|
|
4087
|
+
center: "aw-align-center",
|
|
4088
|
+
right: "aw-align-right",
|
|
4089
|
+
justify: "aw-align-justify"
|
|
4090
|
+
};
|
|
4091
|
+
function applyBlockClassNames(root) {
|
|
4092
|
+
for (const child of Array.from(root.children)) {
|
|
4093
|
+
if (!(child instanceof HTMLElement)) continue;
|
|
4094
|
+
const { match } = classifyBlockElement(child);
|
|
4095
|
+
child.classList.add("aw-block", `aw-block-${match.kind}`);
|
|
4096
|
+
}
|
|
4097
|
+
for (const el of Array.from(root.querySelectorAll("[style]"))) {
|
|
4098
|
+
if (el.closest("[data-imported-html]")) continue;
|
|
4099
|
+
hoistTextAlignToClass(el);
|
|
4100
|
+
}
|
|
4101
|
+
}
|
|
4102
|
+
function hoistTextAlignToClass(el) {
|
|
4103
|
+
var _a;
|
|
4104
|
+
const value = el.style.textAlign.trim().toLowerCase();
|
|
4105
|
+
const className = ALIGN_CLASS_BY_VALUE[value];
|
|
4106
|
+
const stale = Object.values(ALIGN_CLASS_BY_VALUE).filter(
|
|
4107
|
+
(name) => name !== className && el.classList.contains(name)
|
|
4108
|
+
);
|
|
4109
|
+
for (const name of stale) el.classList.remove(name);
|
|
4110
|
+
if (!className) return;
|
|
4111
|
+
el.classList.add(className);
|
|
4112
|
+
el.style.removeProperty("text-align");
|
|
4113
|
+
if (((_a = el.getAttribute("style")) == null ? void 0 : _a.trim()) === "") el.removeAttribute("style");
|
|
4114
|
+
}
|
|
4115
|
+
function restoreAlignFromClasses(root) {
|
|
4116
|
+
var _a;
|
|
4117
|
+
for (const [value, className] of Object.entries(ALIGN_CLASS_BY_VALUE)) {
|
|
4118
|
+
for (const el of Array.from(
|
|
4119
|
+
root.querySelectorAll(`.${className}`)
|
|
4120
|
+
)) {
|
|
4121
|
+
if (!el.style.textAlign) el.style.textAlign = value;
|
|
4122
|
+
el.classList.remove(className);
|
|
4123
|
+
if (((_a = el.getAttribute("class")) == null ? void 0 : _a.trim()) === "") el.removeAttribute("class");
|
|
4124
|
+
}
|
|
4125
|
+
}
|
|
4126
|
+
}
|
|
4127
|
+
function stripEditorOnlyNodes(root) {
|
|
4128
|
+
const chrome = root.querySelectorAll(
|
|
4129
|
+
".aw-block-align-controls, .aw-resize-handle"
|
|
4130
|
+
);
|
|
4131
|
+
for (const el of Array.from(chrome)) el.remove();
|
|
4132
|
+
for (const el of Array.from(root.querySelectorAll("[contenteditable]"))) {
|
|
4133
|
+
el.removeAttribute("contenteditable");
|
|
4134
|
+
}
|
|
4135
|
+
}
|
|
3891
4136
|
function stripEditorOnlyAttrs(root) {
|
|
3892
4137
|
for (const el of Array.from(root.querySelectorAll("[data-block-kind]"))) {
|
|
3893
4138
|
el.removeAttribute("data-block-kind");
|
|
@@ -3982,6 +4227,7 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
3982
4227
|
codeBlock: "codeBlock"
|
|
3983
4228
|
};
|
|
3984
4229
|
const DRAG_MIME = "application/x-aeriz-block";
|
|
4230
|
+
const MIN_BLOCK_WIDTH = 80;
|
|
3985
4231
|
class AerizEditor {
|
|
3986
4232
|
constructor(options) {
|
|
3987
4233
|
__publicField(this, "root");
|
|
@@ -4140,20 +4386,37 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
4140
4386
|
this.sync();
|
|
4141
4387
|
}
|
|
4142
4388
|
/**
|
|
4143
|
-
* 본문 HTML 을 반환한다.
|
|
4144
|
-
*
|
|
4145
|
-
*
|
|
4146
|
-
*
|
|
4147
|
-
*
|
|
4389
|
+
* 본문 HTML 을 반환한다.
|
|
4390
|
+
*
|
|
4391
|
+
* 두 가지 스타일 전략을 지원한다 (`options.styles`, 기본값은 생성 시
|
|
4392
|
+
* `EditorOptions.htmlStyles`, 그것도 없으면 `'inline'`).
|
|
4393
|
+
*
|
|
4394
|
+
* - `'inline'` — 호출 시점의 테마 변수(--aw-primary 등) 를 읽어 블록 단위
|
|
4395
|
+
* 인라인 스타일에 베이크한다. 스타일시트 없이 어디에 붙여도(이메일 본문,
|
|
4396
|
+
* 다른 페이지) 에디터에서 보이는 그대로 렌더된다.
|
|
4397
|
+
* - `'class'` — 테마 스타일을 베이크하지 않고 `aw-block-*` / `aw-align-*`
|
|
4398
|
+
* 클래스만 남긴다. `style` 속성을 지우는 서버 sanitizer 아래에서 서식을
|
|
4399
|
+
* 보존해야 할 때 쓴다. 출력은 `aeriz-wysiwyg.min.css` 를 로드한 페이지의
|
|
4400
|
+
* `.aeriz-wysiwyg > .aw-content` 안에 넣는 것을 전제로 한다.
|
|
4401
|
+
*
|
|
4402
|
+
* 어느 쪽이든 에디터 내부 DOM 은 변형되지 않으며(clone 트리에 적용),
|
|
4403
|
+
* data-block-kind / data-block-focused 같은 에디터 전용 속성과 리사이즈
|
|
4404
|
+
* 핸들 · 정렬 컨트롤 같은 편집 보조 마크업은 출력에서 제거된다.
|
|
4148
4405
|
* data-block-id 는 보존.
|
|
4149
4406
|
*/
|
|
4150
|
-
getHTML() {
|
|
4407
|
+
getHTML(options = {}) {
|
|
4151
4408
|
const clone = this.content.cloneNode(true);
|
|
4152
|
-
const
|
|
4153
|
-
|
|
4154
|
-
|
|
4155
|
-
|
|
4409
|
+
const styles = options.styles ?? this.options.htmlStyles ?? "inline";
|
|
4410
|
+
if (styles === "class") {
|
|
4411
|
+
applyBlockClassNames(clone);
|
|
4412
|
+
} else {
|
|
4413
|
+
const theme = readBlockStyleTheme(this.root);
|
|
4414
|
+
const mode = this.currentTheme();
|
|
4415
|
+
if (mode) theme.mode = mode;
|
|
4416
|
+
applyBlockInlineStyles(clone, theme);
|
|
4417
|
+
}
|
|
4156
4418
|
stripEditorOnlyAttrs(clone);
|
|
4419
|
+
stripEditorOnlyNodes(clone);
|
|
4157
4420
|
return clone.innerHTML;
|
|
4158
4421
|
}
|
|
4159
4422
|
/** 가공 없는 원본 innerHTML. 직렬화 검증/디버그 용도. */
|
|
@@ -4817,15 +5080,20 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
4817
5080
|
* 이미지 / 유튜브 wrapper 의 너비를 드래그로 조정. 높이는 자동 (이미지는
|
|
4818
5081
|
* 종횡비 유지, 유튜브는 CSS aspect-ratio 16/9). mouseup 에서 cursor 복귀
|
|
4819
5082
|
* + flush.
|
|
5083
|
+
*
|
|
5084
|
+
* 너비는 본문 안쪽 폭을 상한으로 한다. 상한이 없으면 오른쪽으로 계속 끌 때
|
|
5085
|
+
* wrapper 가 본문보다 넓어지고, 그만큼 에디터 전체가 가로로 늘어난다
|
|
5086
|
+
* (드래그를 멈춰도 늘어난 상태가 남는다).
|
|
4820
5087
|
*/
|
|
4821
5088
|
startBlockResize(block, startX) {
|
|
4822
5089
|
const initialWidth = block.getBoundingClientRect().width;
|
|
5090
|
+
const maxWidth = this.contentInnerWidth();
|
|
4823
5091
|
document.body.style.cursor = "nwse-resize";
|
|
4824
5092
|
block.classList.add("aw-resizing");
|
|
4825
5093
|
const onMove = (ev) => {
|
|
4826
5094
|
const delta = ev.clientX - startX;
|
|
4827
|
-
const
|
|
4828
|
-
block.style.width = `${Math.round(
|
|
5095
|
+
const wanted = Math.max(MIN_BLOCK_WIDTH, initialWidth + delta);
|
|
5096
|
+
block.style.width = `${Math.round(Math.min(wanted, maxWidth))}px`;
|
|
4829
5097
|
};
|
|
4830
5098
|
const onUp = () => {
|
|
4831
5099
|
document.removeEventListener("mousemove", onMove);
|
|
@@ -4837,6 +5105,15 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
4837
5105
|
document.addEventListener("mousemove", onMove);
|
|
4838
5106
|
document.addEventListener("mouseup", onUp);
|
|
4839
5107
|
}
|
|
5108
|
+
/**
|
|
5109
|
+
* 본문의 padding 을 제외한 실제 컨텐츠 폭. 블록 리사이즈의 상한이다.
|
|
5110
|
+
* 에디터가 아주 좁을 때도 최소 폭은 확보되도록 하한을 둔다.
|
|
5111
|
+
*/
|
|
5112
|
+
contentInnerWidth() {
|
|
5113
|
+
const cs = getComputedStyle(this.content);
|
|
5114
|
+
const inner = this.content.clientWidth - (Number.parseFloat(cs.paddingLeft) || 0) - (Number.parseFloat(cs.paddingRight) || 0);
|
|
5115
|
+
return Math.max(MIN_BLOCK_WIDTH, inner);
|
|
5116
|
+
}
|
|
4840
5117
|
currentTheme() {
|
|
4841
5118
|
const t = this.root.dataset.theme;
|
|
4842
5119
|
return t === "dark" || t === "light" ? t : void 0;
|
|
@@ -5332,7 +5609,7 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
5332
5609
|
positionHandle(handle, blockEl) {
|
|
5333
5610
|
const blockRect = blockEl.getBoundingClientRect();
|
|
5334
5611
|
const wrapRect = this.contentWrap.getBoundingClientRect();
|
|
5335
|
-
const HANDLE_HEIGHT =
|
|
5612
|
+
const HANDLE_HEIGHT = 18;
|
|
5336
5613
|
const verticalShift = blockRect.height < HANDLE_HEIGHT ? (blockRect.height - HANDLE_HEIGHT) / 2 : 0;
|
|
5337
5614
|
const top = blockRect.top - wrapRect.top + this.contentWrap.scrollTop + verticalShift;
|
|
5338
5615
|
handle.style.top = `${top}px`;
|
|
@@ -5753,7 +6030,7 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
5753
6030
|
return false;
|
|
5754
6031
|
}
|
|
5755
6032
|
}
|
|
5756
|
-
const BLOCK_LEVEL_TAGS = /* @__PURE__ */ new Set([
|
|
6033
|
+
const BLOCK_LEVEL_TAGS$1 = /* @__PURE__ */ new Set([
|
|
5757
6034
|
"P",
|
|
5758
6035
|
"DIV",
|
|
5759
6036
|
"SECTION",
|
|
@@ -5786,7 +6063,7 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
5786
6063
|
"ADDRESS"
|
|
5787
6064
|
]);
|
|
5788
6065
|
function isBlockLevelTag(tagName) {
|
|
5789
|
-
return BLOCK_LEVEL_TAGS.has(tagName.toUpperCase());
|
|
6066
|
+
return BLOCK_LEVEL_TAGS$1.has(tagName.toUpperCase());
|
|
5790
6067
|
}
|
|
5791
6068
|
class AerizViewer {
|
|
5792
6069
|
constructor(options) {
|
|
@@ -5794,10 +6071,17 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
5794
6071
|
__publicField(this, "content");
|
|
5795
6072
|
__publicField(this, "blockIds", new BlockIdRegistry());
|
|
5796
6073
|
__publicField(this, "idFor", (el) => this.blockIds.ensure(el));
|
|
6074
|
+
/**
|
|
6075
|
+
* 생성 시 받은 options 객체를 그대로 들고 있는다. `htmlStyles` 를 여기서
|
|
6076
|
+
* 매번 다시 읽으므로, 호출자가 이 객체를 갱신하면 재생성 없이 출력 전략이
|
|
6077
|
+
* 바뀐다 (AerizEditor 와 같은 규약).
|
|
6078
|
+
*/
|
|
6079
|
+
__publicField(this, "options");
|
|
5797
6080
|
__publicField(this, "destroyed", false);
|
|
5798
6081
|
if (!(options.element instanceof HTMLElement)) {
|
|
5799
6082
|
throw new TypeError("AerizViewer: options.element must be an HTMLElement");
|
|
5800
6083
|
}
|
|
6084
|
+
this.options = options;
|
|
5801
6085
|
this.root = document.createElement("div");
|
|
5802
6086
|
this.root.className = "aeriz-wysiwyg aeriz-wysiwyg-viewer";
|
|
5803
6087
|
if (options.theme) {
|
|
@@ -5836,16 +6120,25 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
5836
6120
|
return findBlockFrom(node, this.content, this.idFor);
|
|
5837
6121
|
}
|
|
5838
6122
|
/**
|
|
5839
|
-
*
|
|
5840
|
-
*
|
|
6123
|
+
* 본문 HTML 을 반환한다. 전략은 `AerizEditor.getHTML()` 과 동일하다.
|
|
6124
|
+
*
|
|
6125
|
+
* - `'inline'` (기본) — 외부 컨텍스트(이메일, 다른 페이지의 HTML 영역 등)
|
|
6126
|
+
* 에서도 동일한 시각으로 보이도록 portable 인라인 스타일을 베이크한다.
|
|
6127
|
+
* - `'class'` — 클래스만 남긴다. `style` 속성을 지우는 sanitizer 대응.
|
|
5841
6128
|
*/
|
|
5842
|
-
getHTML() {
|
|
6129
|
+
getHTML(options = {}) {
|
|
5843
6130
|
const clone = this.content.cloneNode(true);
|
|
5844
|
-
const
|
|
5845
|
-
|
|
5846
|
-
|
|
5847
|
-
|
|
6131
|
+
const styles = options.styles ?? this.options.htmlStyles ?? "inline";
|
|
6132
|
+
if (styles === "class") {
|
|
6133
|
+
applyBlockClassNames(clone);
|
|
6134
|
+
} else {
|
|
6135
|
+
const theme = readBlockStyleTheme(this.root);
|
|
6136
|
+
const mode = this.root.dataset.theme;
|
|
6137
|
+
if (mode === "light" || mode === "dark") theme.mode = mode;
|
|
6138
|
+
applyBlockInlineStyles(clone, theme);
|
|
6139
|
+
}
|
|
5848
6140
|
stripEditorOnlyAttrs(clone);
|
|
6141
|
+
stripEditorOnlyNodes(clone);
|
|
5849
6142
|
return clone.innerHTML;
|
|
5850
6143
|
}
|
|
5851
6144
|
setTheme(theme) {
|
|
@@ -5860,6 +6153,716 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
5860
6153
|
return listBlocks(this.content, this.idFor);
|
|
5861
6154
|
}
|
|
5862
6155
|
}
|
|
6156
|
+
const VOID_TAGS = /* @__PURE__ */ new Set([
|
|
6157
|
+
"area",
|
|
6158
|
+
"base",
|
|
6159
|
+
"br",
|
|
6160
|
+
"col",
|
|
6161
|
+
"embed",
|
|
6162
|
+
"hr",
|
|
6163
|
+
"img",
|
|
6164
|
+
"input",
|
|
6165
|
+
"link",
|
|
6166
|
+
"meta",
|
|
6167
|
+
"param",
|
|
6168
|
+
"source",
|
|
6169
|
+
"track",
|
|
6170
|
+
"wbr"
|
|
6171
|
+
]);
|
|
6172
|
+
const DROPPED_RAW_TAGS = /* @__PURE__ */ new Set(["script", "style"]);
|
|
6173
|
+
const IMPLIED_END = /* @__PURE__ */ new Map([
|
|
6174
|
+
["li", /* @__PURE__ */ new Set(["li"])],
|
|
6175
|
+
["p", /* @__PURE__ */ new Set(["p", "div", "ul", "ol", "blockquote", "pre", "table", "h1", "h2", "h3", "h4", "h5", "h6"])],
|
|
6176
|
+
["td", /* @__PURE__ */ new Set(["td", "th", "tr"])],
|
|
6177
|
+
["th", /* @__PURE__ */ new Set(["td", "th", "tr"])],
|
|
6178
|
+
["tr", /* @__PURE__ */ new Set(["tr"])],
|
|
6179
|
+
["option", /* @__PURE__ */ new Set(["option"])]
|
|
6180
|
+
]);
|
|
6181
|
+
const NAMED_ENTITIES = {
|
|
6182
|
+
amp: "&",
|
|
6183
|
+
lt: "<",
|
|
6184
|
+
gt: ">",
|
|
6185
|
+
quot: '"',
|
|
6186
|
+
apos: "'",
|
|
6187
|
+
nbsp: " ",
|
|
6188
|
+
ensp: " ",
|
|
6189
|
+
emsp: " ",
|
|
6190
|
+
thinsp: " ",
|
|
6191
|
+
zwnj: "",
|
|
6192
|
+
zwj: "",
|
|
6193
|
+
hellip: "…",
|
|
6194
|
+
mdash: "—",
|
|
6195
|
+
ndash: "–",
|
|
6196
|
+
lsquo: "‘",
|
|
6197
|
+
rsquo: "’",
|
|
6198
|
+
ldquo: "“",
|
|
6199
|
+
rdquo: "”",
|
|
6200
|
+
middot: "·",
|
|
6201
|
+
bull: "•",
|
|
6202
|
+
copy: "©",
|
|
6203
|
+
reg: "®",
|
|
6204
|
+
trade: "™",
|
|
6205
|
+
deg: "°",
|
|
6206
|
+
plusmn: "±",
|
|
6207
|
+
times: "×",
|
|
6208
|
+
divide: "÷",
|
|
6209
|
+
laquo: "«",
|
|
6210
|
+
raquo: "»"
|
|
6211
|
+
};
|
|
6212
|
+
function decodeEntities(input) {
|
|
6213
|
+
if (!input.includes("&")) return input;
|
|
6214
|
+
return input.replace(
|
|
6215
|
+
/&(#[Xx][0-9A-Fa-f]+|#\d+|[A-Za-z][A-Za-z0-9]{1,31});/g,
|
|
6216
|
+
(whole, body) => {
|
|
6217
|
+
if (body.charCodeAt(0) === 35) {
|
|
6218
|
+
const isHex = body[1] === "x" || body[1] === "X";
|
|
6219
|
+
const digits = isHex ? body.slice(2) : body.slice(1);
|
|
6220
|
+
const code = Number.parseInt(digits, isHex ? 16 : 10);
|
|
6221
|
+
if (!Number.isFinite(code) || code < 0 || code > 1114111) return whole;
|
|
6222
|
+
if (code >= 55296 && code <= 57343) return whole;
|
|
6223
|
+
try {
|
|
6224
|
+
return String.fromCodePoint(code);
|
|
6225
|
+
} catch {
|
|
6226
|
+
return whole;
|
|
6227
|
+
}
|
|
6228
|
+
}
|
|
6229
|
+
const named = NAMED_ENTITIES[body.toLowerCase()];
|
|
6230
|
+
return named ?? whole;
|
|
6231
|
+
}
|
|
6232
|
+
);
|
|
6233
|
+
}
|
|
6234
|
+
function escapeHtml(input) {
|
|
6235
|
+
return input.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
6236
|
+
}
|
|
6237
|
+
function escapeAttr(input) {
|
|
6238
|
+
return escapeHtml(input).replace(/"/g, """);
|
|
6239
|
+
}
|
|
6240
|
+
function parseAttrs(source) {
|
|
6241
|
+
const attrs = {};
|
|
6242
|
+
const re = /([^\s/=>"']+)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s"'>]+)))?/g;
|
|
6243
|
+
let m;
|
|
6244
|
+
while ((m = re.exec(source)) !== null) {
|
|
6245
|
+
const name = m[1];
|
|
6246
|
+
if (!name) continue;
|
|
6247
|
+
const raw = m[2] ?? m[3] ?? m[4] ?? "";
|
|
6248
|
+
attrs[name.toLowerCase()] = decodeEntities(raw);
|
|
6249
|
+
}
|
|
6250
|
+
return attrs;
|
|
6251
|
+
}
|
|
6252
|
+
function parseHtmlFragment(html) {
|
|
6253
|
+
const root = [];
|
|
6254
|
+
const stack = [];
|
|
6255
|
+
const childrenOfTop = () => {
|
|
6256
|
+
const top = stack[stack.length - 1];
|
|
6257
|
+
return top ? top.children : root;
|
|
6258
|
+
};
|
|
6259
|
+
const pushText = (value) => {
|
|
6260
|
+
if (value.length === 0) return;
|
|
6261
|
+
const target = childrenOfTop();
|
|
6262
|
+
const last = target[target.length - 1];
|
|
6263
|
+
if (last && last.type === "text") last.value += value;
|
|
6264
|
+
else target.push({ type: "text", value });
|
|
6265
|
+
};
|
|
6266
|
+
const closeTag = (tag) => {
|
|
6267
|
+
var _a;
|
|
6268
|
+
for (let i = stack.length - 1; i >= 0; i--) {
|
|
6269
|
+
if (((_a = stack[i]) == null ? void 0 : _a.tag) === tag) {
|
|
6270
|
+
stack.length = i;
|
|
6271
|
+
return;
|
|
6272
|
+
}
|
|
6273
|
+
}
|
|
6274
|
+
};
|
|
6275
|
+
let cursor = 0;
|
|
6276
|
+
while (cursor < html.length) {
|
|
6277
|
+
const lt = html.indexOf("<", cursor);
|
|
6278
|
+
if (lt < 0) {
|
|
6279
|
+
pushText(decodeEntities(html.slice(cursor)));
|
|
6280
|
+
break;
|
|
6281
|
+
}
|
|
6282
|
+
if (lt > cursor) pushText(decodeEntities(html.slice(cursor, lt)));
|
|
6283
|
+
if (html.startsWith("<!--", lt)) {
|
|
6284
|
+
const end = html.indexOf("-->", lt + 4);
|
|
6285
|
+
cursor = end < 0 ? html.length : end + 3;
|
|
6286
|
+
continue;
|
|
6287
|
+
}
|
|
6288
|
+
if (html.startsWith("<!", lt) || html.startsWith("<?", lt)) {
|
|
6289
|
+
const end = html.indexOf(">", lt + 2);
|
|
6290
|
+
cursor = end < 0 ? html.length : end + 1;
|
|
6291
|
+
continue;
|
|
6292
|
+
}
|
|
6293
|
+
const gt = html.indexOf(">", lt + 1);
|
|
6294
|
+
if (gt < 0) {
|
|
6295
|
+
pushText(decodeEntities(html.slice(lt)));
|
|
6296
|
+
break;
|
|
6297
|
+
}
|
|
6298
|
+
const inner = html.slice(lt + 1, gt);
|
|
6299
|
+
cursor = gt + 1;
|
|
6300
|
+
if (inner.startsWith("/")) {
|
|
6301
|
+
const tag2 = inner.slice(1).trim().toLowerCase();
|
|
6302
|
+
if (tag2) closeTag(tag2);
|
|
6303
|
+
continue;
|
|
6304
|
+
}
|
|
6305
|
+
const nameMatch = /^([A-Za-z][^\s/>]*)/.exec(inner);
|
|
6306
|
+
if (!nameMatch || !nameMatch[1]) {
|
|
6307
|
+
pushText(decodeEntities(html.slice(lt, cursor)));
|
|
6308
|
+
continue;
|
|
6309
|
+
}
|
|
6310
|
+
const tag = nameMatch[1].toLowerCase();
|
|
6311
|
+
const rest = inner.slice(nameMatch[1].length);
|
|
6312
|
+
const selfClosing = /\/\s*$/.test(rest);
|
|
6313
|
+
const attrs = parseAttrs(selfClosing ? rest.replace(/\/\s*$/, "") : rest);
|
|
6314
|
+
if (DROPPED_RAW_TAGS.has(tag)) {
|
|
6315
|
+
const closeRe = new RegExp(`</${tag}\\s*>`, "i");
|
|
6316
|
+
const remainder = html.slice(cursor);
|
|
6317
|
+
const found = closeRe.exec(remainder);
|
|
6318
|
+
cursor = found ? cursor + found.index + found[0].length : html.length;
|
|
6319
|
+
continue;
|
|
6320
|
+
}
|
|
6321
|
+
const top = stack[stack.length - 1];
|
|
6322
|
+
if (top) {
|
|
6323
|
+
const closers = IMPLIED_END.get(top.tag);
|
|
6324
|
+
if (closers == null ? void 0 : closers.has(tag)) stack.pop();
|
|
6325
|
+
}
|
|
6326
|
+
const node = { type: "element", tag, attrs, children: [] };
|
|
6327
|
+
childrenOfTop().push(node);
|
|
6328
|
+
if (!selfClosing && !VOID_TAGS.has(tag)) stack.push(node);
|
|
6329
|
+
}
|
|
6330
|
+
return root;
|
|
6331
|
+
}
|
|
6332
|
+
function serializeNodes(nodes) {
|
|
6333
|
+
let out = "";
|
|
6334
|
+
for (const node of nodes) {
|
|
6335
|
+
if (node.type === "text") {
|
|
6336
|
+
out += escapeHtml(node.value);
|
|
6337
|
+
continue;
|
|
6338
|
+
}
|
|
6339
|
+
const attrs = Object.entries(node.attrs).map(([k, v]) => v === "" ? ` ${k}` : ` ${k}="${escapeAttr(v)}"`).join("");
|
|
6340
|
+
if (VOID_TAGS.has(node.tag)) {
|
|
6341
|
+
out += `<${node.tag}${attrs}>`;
|
|
6342
|
+
continue;
|
|
6343
|
+
}
|
|
6344
|
+
out += `<${node.tag}${attrs}>${serializeNodes(node.children)}</${node.tag}>`;
|
|
6345
|
+
}
|
|
6346
|
+
return out;
|
|
6347
|
+
}
|
|
6348
|
+
function textOf(nodes) {
|
|
6349
|
+
let out = "";
|
|
6350
|
+
for (const node of nodes) {
|
|
6351
|
+
if (node.type === "text") {
|
|
6352
|
+
out += node.value;
|
|
6353
|
+
continue;
|
|
6354
|
+
}
|
|
6355
|
+
if (node.tag === "br") {
|
|
6356
|
+
out += "\n";
|
|
6357
|
+
continue;
|
|
6358
|
+
}
|
|
6359
|
+
out += textOf(node.children);
|
|
6360
|
+
}
|
|
6361
|
+
return out;
|
|
6362
|
+
}
|
|
6363
|
+
const BLOCK_LEVEL_TAGS = /* @__PURE__ */ new Set([
|
|
6364
|
+
"address",
|
|
6365
|
+
"article",
|
|
6366
|
+
"aside",
|
|
6367
|
+
"blockquote",
|
|
6368
|
+
"div",
|
|
6369
|
+
"dd",
|
|
6370
|
+
"dl",
|
|
6371
|
+
"dt",
|
|
6372
|
+
"fieldset",
|
|
6373
|
+
"figcaption",
|
|
6374
|
+
"figure",
|
|
6375
|
+
"footer",
|
|
6376
|
+
"form",
|
|
6377
|
+
"h1",
|
|
6378
|
+
"h2",
|
|
6379
|
+
"h3",
|
|
6380
|
+
"h4",
|
|
6381
|
+
"h5",
|
|
6382
|
+
"h6",
|
|
6383
|
+
"header",
|
|
6384
|
+
"hr",
|
|
6385
|
+
"li",
|
|
6386
|
+
"main",
|
|
6387
|
+
"nav",
|
|
6388
|
+
"ol",
|
|
6389
|
+
"p",
|
|
6390
|
+
"pre",
|
|
6391
|
+
"section",
|
|
6392
|
+
"table",
|
|
6393
|
+
"tbody",
|
|
6394
|
+
"td",
|
|
6395
|
+
"tfoot",
|
|
6396
|
+
"th",
|
|
6397
|
+
"thead",
|
|
6398
|
+
"tr",
|
|
6399
|
+
"ul"
|
|
6400
|
+
]);
|
|
6401
|
+
function textWithBlockBreaks(nodes) {
|
|
6402
|
+
let out = "";
|
|
6403
|
+
for (const node of nodes) {
|
|
6404
|
+
if (node.type === "text") {
|
|
6405
|
+
out += node.value;
|
|
6406
|
+
continue;
|
|
6407
|
+
}
|
|
6408
|
+
if (node.tag === "br") {
|
|
6409
|
+
out += "\n";
|
|
6410
|
+
continue;
|
|
6411
|
+
}
|
|
6412
|
+
const isBlock = BLOCK_LEVEL_TAGS.has(node.tag);
|
|
6413
|
+
if (isBlock && out !== "" && !out.endsWith("\n")) out += "\n";
|
|
6414
|
+
out += textWithBlockBreaks(node.children);
|
|
6415
|
+
if (isBlock && !out.endsWith("\n")) out += "\n";
|
|
6416
|
+
}
|
|
6417
|
+
return out;
|
|
6418
|
+
}
|
|
6419
|
+
function childElements(nodes, tag) {
|
|
6420
|
+
return nodes.filter(
|
|
6421
|
+
(n) => n.type === "element" && n.tag === tag
|
|
6422
|
+
);
|
|
6423
|
+
}
|
|
6424
|
+
function renderBlocksToHTML(snapshots, options = {}) {
|
|
6425
|
+
const withIds = options.blockIds !== false;
|
|
6426
|
+
const body = upgradeSnapshots(snapshots).map((snap) => renderNormalizedBlock(snap, { blockIds: withIds })).join("");
|
|
6427
|
+
if (options.wrapper !== "content") return body;
|
|
6428
|
+
const themeAttr = options.theme ? ` data-theme="${options.theme}"` : "";
|
|
6429
|
+
return `<div class="aeriz-wysiwyg aeriz-wysiwyg-viewer"${themeAttr}><div class="aw-content-wrap"><div class="aw-content">${body}</div></div></div>`;
|
|
6430
|
+
}
|
|
6431
|
+
function renderBlockToHTML(snapshot, options = {}) {
|
|
6432
|
+
return renderNormalizedBlock(upgradeSnapshot(snapshot), options);
|
|
6433
|
+
}
|
|
6434
|
+
function renderNormalizedBlock(snapshot, options = {}) {
|
|
6435
|
+
const idAttr = options.blockIds === false ? "" : ` ${BLOCK_ID_ATTR}="${escapeAttr(snapshot.id)}"`;
|
|
6436
|
+
const inner = snapshot.html;
|
|
6437
|
+
const styleAttr = snapshot.style ? ` style="${escapeAttr(snapshot.style)}"` : "";
|
|
6438
|
+
switch (snapshot.kind) {
|
|
6439
|
+
case "paragraph":
|
|
6440
|
+
return `<p${idAttr}${styleAttr}>${inner || "<br>"}</p>`;
|
|
6441
|
+
case "unknown":
|
|
6442
|
+
return `<div${idAttr}${styleAttr}>${inner || "<br>"}</div>`;
|
|
6443
|
+
case "heading": {
|
|
6444
|
+
const level = clampHeadingLevel(snapshot.attrs.level);
|
|
6445
|
+
return `<h${level}${idAttr}${styleAttr}>${inner || "<br>"}</h${level}>`;
|
|
6446
|
+
}
|
|
6447
|
+
case "bulletList":
|
|
6448
|
+
return `<ul${idAttr}${styleAttr}>${inner || "<li><br></li>"}</ul>`;
|
|
6449
|
+
case "orderedList":
|
|
6450
|
+
return `<ol${idAttr}${styleAttr}>${inner || "<li><br></li>"}</ol>`;
|
|
6451
|
+
case "blockquote":
|
|
6452
|
+
return `<blockquote${idAttr}${styleAttr}>${inner || "<p><br></p>"}</blockquote>`;
|
|
6453
|
+
case "codeBlock": {
|
|
6454
|
+
if (inner) return `<pre${idAttr}${styleAttr}>${inner}</pre>`;
|
|
6455
|
+
const lang = snapshot.attrs.language;
|
|
6456
|
+
const langAttr = lang ? ` data-language="${escapeAttr(lang)}"` : "";
|
|
6457
|
+
return `<pre${idAttr}${styleAttr}><code${langAttr}></code></pre>`;
|
|
6458
|
+
}
|
|
6459
|
+
case "table":
|
|
6460
|
+
return `<table${idAttr}${styleAttr}>${inner || emptyTableBody(snapshot.attrs.rows, snapshot.attrs.cols)}</table>`;
|
|
6461
|
+
case "hr":
|
|
6462
|
+
return `<hr${idAttr}${styleAttr}>`;
|
|
6463
|
+
case "image":
|
|
6464
|
+
return inner ? `<figure${idAttr}${styleAttr}>${stripChrome(inner)}</figure>` : renderImage(snapshot.attrs, idAttr, styleAttr);
|
|
6465
|
+
case "youtube": {
|
|
6466
|
+
if (!inner) return renderYoutube(snapshot.attrs, idAttr, styleAttr);
|
|
6467
|
+
const videoId = snapshot.attrs.videoId;
|
|
6468
|
+
const idDataAttr = videoId ? ` data-youtube-id="${escapeAttr(videoId)}"` : "";
|
|
6469
|
+
return `<div class="aw-youtube-embed"${idDataAttr}${idAttr}${styleAttr}>${stripChrome(inner)}</div>`;
|
|
6470
|
+
}
|
|
6471
|
+
case "linkCard":
|
|
6472
|
+
return renderLinkCard(snapshot.attrs, idAttr, styleAttr, inner);
|
|
6473
|
+
case "file":
|
|
6474
|
+
return renderFile(snapshot.attrs, idAttr, styleAttr, inner);
|
|
6475
|
+
case "importedHtml": {
|
|
6476
|
+
const style = snapshot.attrs.importedStyle;
|
|
6477
|
+
const cls = snapshot.attrs.importedClass;
|
|
6478
|
+
const importedStyle = snapshot.style ? styleAttr : style ? ` style="${escapeAttr(style)}"` : "";
|
|
6479
|
+
const classAttr = cls ? ` class="${escapeAttr(cls)}"` : "";
|
|
6480
|
+
return `<div data-imported-html="true"${classAttr}${importedStyle}${idAttr}>${inner}</div>`;
|
|
6481
|
+
}
|
|
6482
|
+
default: {
|
|
6483
|
+
return "";
|
|
6484
|
+
}
|
|
6485
|
+
}
|
|
6486
|
+
}
|
|
6487
|
+
const CHROME_CLASS = /aw-block-align-controls|aw-resize-handle/;
|
|
6488
|
+
function stripChrome(html) {
|
|
6489
|
+
if (!CHROME_CLASS.test(html)) return html;
|
|
6490
|
+
const kept = parseHtmlFragment(html).filter(
|
|
6491
|
+
(node) => !(node.type === "element" && CHROME_CLASS.test(node.attrs["class"] ?? ""))
|
|
6492
|
+
);
|
|
6493
|
+
return serializeNodes(kept);
|
|
6494
|
+
}
|
|
6495
|
+
function clampHeadingLevel(level) {
|
|
6496
|
+
if (level === void 0) return 1;
|
|
6497
|
+
if (level < 1) return 1;
|
|
6498
|
+
if (level > 6) return 6;
|
|
6499
|
+
return level;
|
|
6500
|
+
}
|
|
6501
|
+
function emptyTableBody(rows, cols) {
|
|
6502
|
+
const r = Math.max(1, Number.isFinite(rows) ? rows : 1);
|
|
6503
|
+
const c = Math.max(1, Number.isFinite(cols) ? cols : 1);
|
|
6504
|
+
const cells = "<td><br></td>".repeat(c);
|
|
6505
|
+
return `<tbody>${`<tr>${cells}</tr>`.repeat(r)}</tbody>`;
|
|
6506
|
+
}
|
|
6507
|
+
function renderImage(attrs, idAttr, blockStyleAttr) {
|
|
6508
|
+
const styleAttr = blockStyleAttr || (attrs.wrapperStyle ? ` style="${escapeAttr(attrs.wrapperStyle)}"` : "");
|
|
6509
|
+
const srcAttr = attrs.src ? ` src="${escapeAttr(attrs.src)}"` : "";
|
|
6510
|
+
const altAttr = ` alt="${escapeAttr(attrs.alt ?? "")}"`;
|
|
6511
|
+
return `<figure${idAttr}${styleAttr}><img${srcAttr}${altAttr}></figure>`;
|
|
6512
|
+
}
|
|
6513
|
+
function renderYoutube(attrs, idAttr, blockStyleAttr) {
|
|
6514
|
+
const videoId = attrs.videoId ?? "";
|
|
6515
|
+
const styleAttr = blockStyleAttr || (attrs.wrapperStyle ? ` style="${escapeAttr(attrs.wrapperStyle)}"` : "");
|
|
6516
|
+
const idDataAttr = videoId ? ` data-youtube-id="${escapeAttr(videoId)}"` : "";
|
|
6517
|
+
const srcAttr = videoId ? ` src="${escapeAttr(`${YOUTUBE_EMBED_BASE}${videoId}`)}"` : "";
|
|
6518
|
+
return `<div class="aw-youtube-embed"${idDataAttr}${idAttr}${styleAttr}><iframe${srcAttr} allow="${escapeAttr(YOUTUBE_IFRAME_ALLOW)}" allowfullscreen frameborder="0" referrerpolicy="strict-origin-when-cross-origin"></iframe></div>`;
|
|
6519
|
+
}
|
|
6520
|
+
function renderLinkCard(attrs, idAttr, styleAttr, inner) {
|
|
6521
|
+
const href = attrs.href ?? "#";
|
|
6522
|
+
const title = attrs.text && attrs.text.length > 0 ? attrs.text : hostnameFromUrl(href) || href;
|
|
6523
|
+
const description = attrs.description ?? "";
|
|
6524
|
+
const image = attrs.image ?? "";
|
|
6525
|
+
const favicon = attrs.favicon ?? defaultFaviconUrl(href);
|
|
6526
|
+
const classes = image ? "aw-link-card aw-link-card-with-image" : "aw-link-card";
|
|
6527
|
+
const open = `<a class="${classes}" href="${escapeAttr(href)}" target="_blank" rel="noopener"${idAttr}${styleAttr}>`;
|
|
6528
|
+
if (inner) return `${open}${stripChrome(inner)}</a>`;
|
|
6529
|
+
let out = open;
|
|
6530
|
+
if (image) {
|
|
6531
|
+
out += `<img class="aw-link-card-image" src="${escapeAttr(image)}" alt="" loading="lazy">`;
|
|
6532
|
+
}
|
|
6533
|
+
out += '<span class="aw-link-card-body">';
|
|
6534
|
+
out += `<span class="aw-link-card-title">${escapeHtml(title)}</span>`;
|
|
6535
|
+
if (description) {
|
|
6536
|
+
out += `<span class="aw-link-card-desc">${escapeHtml(description)}</span>`;
|
|
6537
|
+
}
|
|
6538
|
+
out += '<span class="aw-link-card-url">';
|
|
6539
|
+
if (favicon) {
|
|
6540
|
+
out += `<img class="aw-link-card-favicon" src="${escapeAttr(favicon)}" alt="" loading="lazy">`;
|
|
6541
|
+
}
|
|
6542
|
+
out += `<span class="aw-link-card-url-text">${escapeHtml(href)}</span>`;
|
|
6543
|
+
out += "</span></span></a>";
|
|
6544
|
+
return out;
|
|
6545
|
+
}
|
|
6546
|
+
function renderFile(attrs, idAttr, styleAttr, inner) {
|
|
6547
|
+
const hrefAttr = attrs.fileSrc ? ` href="${escapeAttr(attrs.fileSrc)}"` : "";
|
|
6548
|
+
const nameAttr = attrs.fileName ? ` data-file-name="${escapeAttr(attrs.fileName)}"` : "";
|
|
6549
|
+
const sizeAttr = attrs.fileSize !== void 0 ? ` data-file-size="${escapeAttr(String(attrs.fileSize))}"` : "";
|
|
6550
|
+
const typeAttr = attrs.fileType ? ` data-file-type="${escapeAttr(attrs.fileType)}"` : "";
|
|
6551
|
+
const downloadAttr = ` download="${escapeAttr(attrs.fileName ?? "")}"`;
|
|
6552
|
+
const infoParts = [];
|
|
6553
|
+
const ext = fileExtensionLabel(attrs.fileName, attrs.fileType);
|
|
6554
|
+
if (ext) infoParts.push(ext);
|
|
6555
|
+
if (attrs.fileSize !== void 0) infoParts.push(formatBytes(attrs.fileSize));
|
|
6556
|
+
const open = `<a class="aw-file-attachment" target="_blank" rel="noopener"${hrefAttr}${downloadAttr}${nameAttr}${sizeAttr}${typeAttr}${idAttr}${styleAttr}>`;
|
|
6557
|
+
if (inner) return `${open}${stripChrome(inner)}</a>`;
|
|
6558
|
+
let out = open;
|
|
6559
|
+
out += `<span class="aw-file-icon" aria-hidden="true">${FILE_ICON_SVG}</span>`;
|
|
6560
|
+
out += '<span class="aw-file-meta">';
|
|
6561
|
+
out += `<span class="aw-file-name">${escapeHtml(attrs.fileName ?? FILE_FALLBACK_NAME)}</span>`;
|
|
6562
|
+
if (infoParts.length > 0) {
|
|
6563
|
+
out += `<span class="aw-file-info">${escapeHtml(infoParts.join(" · "))}</span>`;
|
|
6564
|
+
}
|
|
6565
|
+
out += "</span>";
|
|
6566
|
+
out += `<span class="aw-file-action" aria-hidden="true">${FILE_ACTION_SVG}</span>`;
|
|
6567
|
+
out += "</a>";
|
|
6568
|
+
return out;
|
|
6569
|
+
}
|
|
6570
|
+
const INLINE_ESCAPE = /([\\`*_[\]<])/g;
|
|
6571
|
+
const LINE_START_ESCAPE = /^([#>|+-]|\d+\.)/;
|
|
6572
|
+
function blocksToMarkdown(snapshots, options = {}) {
|
|
6573
|
+
const bullet = options.bullet ?? "-";
|
|
6574
|
+
const gfmTables = options.gfmTables !== false;
|
|
6575
|
+
const chunks = [];
|
|
6576
|
+
for (const snap of upgradeSnapshots(snapshots)) {
|
|
6577
|
+
const chunk = blockToMarkdown(snap, bullet, gfmTables);
|
|
6578
|
+
if (chunk !== "") chunks.push(chunk);
|
|
6579
|
+
}
|
|
6580
|
+
return chunks.length > 0 ? `${chunks.join("\n\n")}
|
|
6581
|
+
` : "";
|
|
6582
|
+
}
|
|
6583
|
+
function blockToMarkdown(snapshot, bullet, gfmTables) {
|
|
6584
|
+
var _a, _b, _c;
|
|
6585
|
+
const nodes = parseHtmlFragment(snapshot.html);
|
|
6586
|
+
switch (snapshot.kind) {
|
|
6587
|
+
case "paragraph":
|
|
6588
|
+
case "unknown": {
|
|
6589
|
+
const text = inlineToMarkdown(nodes).trim();
|
|
6590
|
+
return text === "" ? "" : escapeLineStart(text);
|
|
6591
|
+
}
|
|
6592
|
+
case "heading": {
|
|
6593
|
+
const level = Math.min(6, Math.max(1, snapshot.attrs.level ?? 1));
|
|
6594
|
+
const text = inlineToMarkdown(nodes).trim();
|
|
6595
|
+
return text === "" ? "" : `${"#".repeat(level)} ${text}`;
|
|
6596
|
+
}
|
|
6597
|
+
case "bulletList":
|
|
6598
|
+
return listToMarkdown(nodes, { ordered: false, bullet, depth: 0 });
|
|
6599
|
+
case "orderedList":
|
|
6600
|
+
return listToMarkdown(nodes, { ordered: true, bullet, depth: 0 });
|
|
6601
|
+
case "blockquote": {
|
|
6602
|
+
const paragraphs = childElements(nodes, "p");
|
|
6603
|
+
const source = paragraphs.length > 0 ? paragraphs.map((p) => inlineToMarkdown(p.children).trim()) : [inlineToMarkdown(nodes).trim()];
|
|
6604
|
+
const lines = source.filter((line) => line !== "").join("\n\n").split("\n").map((line) => line === "" ? ">" : `> ${line}`);
|
|
6605
|
+
return lines.length > 0 && lines[0] !== void 0 ? lines.join("\n") : "";
|
|
6606
|
+
}
|
|
6607
|
+
case "codeBlock": {
|
|
6608
|
+
const code = childElements(nodes, "code")[0];
|
|
6609
|
+
const body = textOf(code ? code.children : nodes).replace(/\n$/, "");
|
|
6610
|
+
const lang = snapshot.attrs.language ?? (code == null ? void 0 : code.attrs["data-language"]) ?? "";
|
|
6611
|
+
const fence = "`".repeat(Math.max(3, longestBacktickRun(body) + 1));
|
|
6612
|
+
return `${fence}${lang}
|
|
6613
|
+
${body}
|
|
6614
|
+
${fence}`;
|
|
6615
|
+
}
|
|
6616
|
+
case "image": {
|
|
6617
|
+
const src = snapshot.attrs.src ?? "";
|
|
6618
|
+
if (src === "") return "";
|
|
6619
|
+
return `})`;
|
|
6620
|
+
}
|
|
6621
|
+
case "table":
|
|
6622
|
+
return gfmTables ? tableToMarkdown(nodes) : `<table>${snapshot.html}</table>`;
|
|
6623
|
+
case "hr":
|
|
6624
|
+
return "---";
|
|
6625
|
+
case "linkCard": {
|
|
6626
|
+
const href = snapshot.attrs.href ?? "";
|
|
6627
|
+
if (href === "") return "";
|
|
6628
|
+
const label = ((_a = snapshot.attrs.text) == null ? void 0 : _a.trim()) || href;
|
|
6629
|
+
const line = `[${escapeInline(label)}](${encodeUrl(href)})`;
|
|
6630
|
+
const desc = (_b = snapshot.attrs.description) == null ? void 0 : _b.trim();
|
|
6631
|
+
return desc ? `${line}
|
|
6632
|
+
|
|
6633
|
+
${escapeLineStart(escapeInline(desc))}` : line;
|
|
6634
|
+
}
|
|
6635
|
+
case "youtube": {
|
|
6636
|
+
const videoId = snapshot.attrs.videoId;
|
|
6637
|
+
if (!videoId) return "";
|
|
6638
|
+
return `[YouTube](${YOUTUBE_EMBED_BASE}${encodeURIComponent(videoId)})`;
|
|
6639
|
+
}
|
|
6640
|
+
case "file": {
|
|
6641
|
+
const src = snapshot.attrs.fileSrc ?? "";
|
|
6642
|
+
if (src === "") return "";
|
|
6643
|
+
const name = ((_c = snapshot.attrs.fileName) == null ? void 0 : _c.trim()) || src;
|
|
6644
|
+
return `[${escapeInline(name)}](${encodeUrl(src)})`;
|
|
6645
|
+
}
|
|
6646
|
+
case "importedHtml":
|
|
6647
|
+
return snapshot.html.trim();
|
|
6648
|
+
default: {
|
|
6649
|
+
return "";
|
|
6650
|
+
}
|
|
6651
|
+
}
|
|
6652
|
+
}
|
|
6653
|
+
function listToMarkdown(nodes, ctx) {
|
|
6654
|
+
const items = childElements(nodes, "li");
|
|
6655
|
+
if (items.length === 0) return "";
|
|
6656
|
+
const indent = " ".repeat(ctx.depth);
|
|
6657
|
+
const lines = [];
|
|
6658
|
+
items.forEach((li, index) => {
|
|
6659
|
+
const inline = [];
|
|
6660
|
+
const nested = [];
|
|
6661
|
+
for (const child of li.children) {
|
|
6662
|
+
if (child.type === "element" && (child.tag === "ul" || child.tag === "ol")) {
|
|
6663
|
+
nested.push(child);
|
|
6664
|
+
} else {
|
|
6665
|
+
inline.push(child);
|
|
6666
|
+
}
|
|
6667
|
+
}
|
|
6668
|
+
const marker = ctx.ordered ? `${index + 1}.` : ctx.bullet;
|
|
6669
|
+
const text = inlineToMarkdown(inline).trim();
|
|
6670
|
+
const continuation = `${indent}${" ".repeat(marker.length + 1)}`;
|
|
6671
|
+
const body = text.split("\n").join(`
|
|
6672
|
+
${continuation}`);
|
|
6673
|
+
lines.push(`${indent}${marker} ${body}`);
|
|
6674
|
+
for (const sub of nested) {
|
|
6675
|
+
const subMd = listToMarkdown(sub.children, {
|
|
6676
|
+
ordered: sub.tag === "ol",
|
|
6677
|
+
bullet: ctx.bullet,
|
|
6678
|
+
depth: ctx.depth + 1
|
|
6679
|
+
});
|
|
6680
|
+
if (subMd !== "") lines.push(subMd);
|
|
6681
|
+
}
|
|
6682
|
+
});
|
|
6683
|
+
return lines.join("\n");
|
|
6684
|
+
}
|
|
6685
|
+
function tableToMarkdown(nodes) {
|
|
6686
|
+
const rows = [];
|
|
6687
|
+
const collectRows = (list) => {
|
|
6688
|
+
for (const node of list) {
|
|
6689
|
+
if (node.type !== "element") continue;
|
|
6690
|
+
if (node.tag === "tr") {
|
|
6691
|
+
rows.push(node);
|
|
6692
|
+
continue;
|
|
6693
|
+
}
|
|
6694
|
+
if (node.tag === "tbody" || node.tag === "thead" || node.tag === "tfoot") {
|
|
6695
|
+
collectRows(node.children);
|
|
6696
|
+
}
|
|
6697
|
+
}
|
|
6698
|
+
};
|
|
6699
|
+
collectRows(nodes);
|
|
6700
|
+
if (rows.length === 0) return "";
|
|
6701
|
+
const grid = rows.map(
|
|
6702
|
+
(tr) => tr.children.filter(
|
|
6703
|
+
(c) => c.type === "element" && (c.tag === "td" || c.tag === "th")
|
|
6704
|
+
).map((cell) => cellToMarkdown(cell.children))
|
|
6705
|
+
);
|
|
6706
|
+
const width = grid.reduce((max, row) => Math.max(max, row.length), 0);
|
|
6707
|
+
if (width === 0) return "";
|
|
6708
|
+
const pad = (row) => row.length === width ? row : [...row, ...Array(width - row.length).fill("")];
|
|
6709
|
+
const [head, ...body] = grid.map(pad);
|
|
6710
|
+
const headRow = head ?? Array(width).fill("");
|
|
6711
|
+
const lines = [
|
|
6712
|
+
`| ${headRow.join(" | ")} |`,
|
|
6713
|
+
`| ${Array(width).fill("---").join(" | ")} |`,
|
|
6714
|
+
...body.map((row) => `| ${row.join(" | ")} |`)
|
|
6715
|
+
];
|
|
6716
|
+
return lines.join("\n");
|
|
6717
|
+
}
|
|
6718
|
+
function cellToMarkdown(nodes) {
|
|
6719
|
+
return inlineToMarkdown(nodes, { inTableCell: true }).replace(/\n+/g, "<br>").replace(/\|/g, "\\|").trim();
|
|
6720
|
+
}
|
|
6721
|
+
function inlineToMarkdown(nodes, ctx = {}) {
|
|
6722
|
+
let out = "";
|
|
6723
|
+
for (const node of nodes) {
|
|
6724
|
+
if (node.type === "text") {
|
|
6725
|
+
out += escapeInline(node.value);
|
|
6726
|
+
continue;
|
|
6727
|
+
}
|
|
6728
|
+
const children = () => inlineToMarkdown(node.children, ctx);
|
|
6729
|
+
switch (node.tag) {
|
|
6730
|
+
case "br":
|
|
6731
|
+
out += ctx.inTableCell ? "\n" : " \n";
|
|
6732
|
+
break;
|
|
6733
|
+
case "b":
|
|
6734
|
+
case "strong": {
|
|
6735
|
+
const inner = children();
|
|
6736
|
+
out += inner.trim() === "" ? inner : `**${inner}**`;
|
|
6737
|
+
break;
|
|
6738
|
+
}
|
|
6739
|
+
case "i":
|
|
6740
|
+
case "em": {
|
|
6741
|
+
const inner = children();
|
|
6742
|
+
out += inner.trim() === "" ? inner : `*${inner}*`;
|
|
6743
|
+
break;
|
|
6744
|
+
}
|
|
6745
|
+
case "s":
|
|
6746
|
+
case "del":
|
|
6747
|
+
case "strike": {
|
|
6748
|
+
const inner = children();
|
|
6749
|
+
out += inner.trim() === "" ? inner : `~~${inner}~~`;
|
|
6750
|
+
break;
|
|
6751
|
+
}
|
|
6752
|
+
case "code": {
|
|
6753
|
+
const raw = textOf(node.children);
|
|
6754
|
+
const fence = "`".repeat(longestBacktickRun(raw) + 1);
|
|
6755
|
+
const padding = raw.startsWith("`") || raw.endsWith("`") ? " " : "";
|
|
6756
|
+
out += `${fence}${padding}${raw}${padding}${fence}`;
|
|
6757
|
+
break;
|
|
6758
|
+
}
|
|
6759
|
+
case "a": {
|
|
6760
|
+
const href = node.attrs["href"];
|
|
6761
|
+
const inner = children();
|
|
6762
|
+
out += href ? `[${inner}](${encodeUrl(href)})` : inner;
|
|
6763
|
+
break;
|
|
6764
|
+
}
|
|
6765
|
+
case "img": {
|
|
6766
|
+
const src = node.attrs["src"];
|
|
6767
|
+
if (src) out += `![${escapeInline(node.attrs["alt"] ?? "")}](${encodeUrl(src)})`;
|
|
6768
|
+
break;
|
|
6769
|
+
}
|
|
6770
|
+
case "u":
|
|
6771
|
+
case "sub":
|
|
6772
|
+
case "sup":
|
|
6773
|
+
case "mark":
|
|
6774
|
+
out += `<${node.tag}>${children()}</${node.tag}>`;
|
|
6775
|
+
break;
|
|
6776
|
+
default:
|
|
6777
|
+
out += children();
|
|
6778
|
+
break;
|
|
6779
|
+
}
|
|
6780
|
+
}
|
|
6781
|
+
return out;
|
|
6782
|
+
}
|
|
6783
|
+
function escapeInline(text) {
|
|
6784
|
+
return text.replace(INLINE_ESCAPE, "\\$1");
|
|
6785
|
+
}
|
|
6786
|
+
function escapeLineStart(text) {
|
|
6787
|
+
return text.replace(LINE_START_ESCAPE, "\\$1");
|
|
6788
|
+
}
|
|
6789
|
+
function longestBacktickRun(text) {
|
|
6790
|
+
let longest = 0;
|
|
6791
|
+
let current = 0;
|
|
6792
|
+
for (const ch of text) {
|
|
6793
|
+
if (ch === "`") {
|
|
6794
|
+
current += 1;
|
|
6795
|
+
if (current > longest) longest = current;
|
|
6796
|
+
} else {
|
|
6797
|
+
current = 0;
|
|
6798
|
+
}
|
|
6799
|
+
}
|
|
6800
|
+
return longest;
|
|
6801
|
+
}
|
|
6802
|
+
function encodeUrl(url) {
|
|
6803
|
+
const trimmed = url.trim();
|
|
6804
|
+
if (/[\s()]/.test(trimmed)) {
|
|
6805
|
+
return `<${trimmed.replace(/[<>]/g, "")}>`;
|
|
6806
|
+
}
|
|
6807
|
+
return trimmed;
|
|
6808
|
+
}
|
|
6809
|
+
function blocksToPlainText(snapshots, options = {}) {
|
|
6810
|
+
const blockSeparator = options.blockSeparator ?? "\n\n";
|
|
6811
|
+
const cellSeparator = options.cellSeparator ?? " ";
|
|
6812
|
+
const chunks = [];
|
|
6813
|
+
for (const snap of upgradeSnapshots(snapshots)) {
|
|
6814
|
+
const text = blockToPlainText(snap, cellSeparator);
|
|
6815
|
+
if (text !== "") chunks.push(text);
|
|
6816
|
+
}
|
|
6817
|
+
return chunks.join(blockSeparator);
|
|
6818
|
+
}
|
|
6819
|
+
function blockToPlainText(snapshot, cellSeparator) {
|
|
6820
|
+
switch (snapshot.kind) {
|
|
6821
|
+
case "hr":
|
|
6822
|
+
case "youtube":
|
|
6823
|
+
return "";
|
|
6824
|
+
case "image":
|
|
6825
|
+
return normalize(snapshot.attrs.alt ?? "");
|
|
6826
|
+
case "linkCard":
|
|
6827
|
+
return normalize(snapshot.attrs.text ?? snapshot.attrs.href ?? "");
|
|
6828
|
+
case "file":
|
|
6829
|
+
return normalize(snapshot.attrs.fileName ?? "");
|
|
6830
|
+
case "bulletList":
|
|
6831
|
+
case "orderedList": {
|
|
6832
|
+
const items = childElements(parseHtmlFragment(snapshot.html), "li");
|
|
6833
|
+
return items.map((li) => normalize(textWithBlockBreaks(li.children))).filter((line) => line !== "").join("\n");
|
|
6834
|
+
}
|
|
6835
|
+
case "table":
|
|
6836
|
+
return tableToPlainText(parseHtmlFragment(snapshot.html), cellSeparator);
|
|
6837
|
+
default:
|
|
6838
|
+
return normalize(textWithBlockBreaks(parseHtmlFragment(snapshot.html)));
|
|
6839
|
+
}
|
|
6840
|
+
}
|
|
6841
|
+
function tableToPlainText(nodes, cellSeparator) {
|
|
6842
|
+
const rows = [];
|
|
6843
|
+
const collect = (list) => {
|
|
6844
|
+
for (const node of list) {
|
|
6845
|
+
if (node.type !== "element") continue;
|
|
6846
|
+
if (node.tag === "tr") rows.push(node);
|
|
6847
|
+
else if (["tbody", "thead", "tfoot"].includes(node.tag)) {
|
|
6848
|
+
collect(node.children);
|
|
6849
|
+
}
|
|
6850
|
+
}
|
|
6851
|
+
};
|
|
6852
|
+
collect(nodes);
|
|
6853
|
+
return rows.map(
|
|
6854
|
+
(tr) => tr.children.filter(
|
|
6855
|
+
(c) => c.type === "element" && (c.tag === "td" || c.tag === "th")
|
|
6856
|
+
).map((cell) => normalize(textWithBlockBreaks(cell.children)).replace(/\n+/g, " ")).join(cellSeparator)
|
|
6857
|
+
).filter((line) => line.replace(new RegExp(escapeRegExp(cellSeparator), "g"), "").trim() !== "").join("\n");
|
|
6858
|
+
}
|
|
6859
|
+
function normalize(text) {
|
|
6860
|
+
return text.replace(/[-]/g, "").split("\n").map((line) => line.replace(/[^\S\n]+/g, " ").trim()).join("\n").replace(/\n{3,}/g, "\n\n").trim();
|
|
6861
|
+
}
|
|
6862
|
+
function escapeRegExp(input) {
|
|
6863
|
+
return input.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
6864
|
+
}
|
|
6865
|
+
exports.ALIGN_CLASS_BY_VALUE = ALIGN_CLASS_BY_VALUE;
|
|
5863
6866
|
exports.ALL_INLINE_MARKS = ALL_INLINE_MARKS;
|
|
5864
6867
|
exports.AerizEditor = AerizEditor;
|
|
5865
6868
|
exports.AerizViewer = AerizViewer;
|
|
@@ -5868,9 +6871,16 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
5868
6871
|
exports.BLOCK_TYPE_BY_KIND = BLOCK_TYPE_BY_KIND;
|
|
5869
6872
|
exports.BlockIdRegistry = BlockIdRegistry;
|
|
5870
6873
|
exports.DEFAULT_TOOLBAR = DEFAULT_TOOLBAR;
|
|
6874
|
+
exports.SNAPSHOT_VERSION = SNAPSHOT_VERSION;
|
|
6875
|
+
exports.applyBlockClassNames = applyBlockClassNames;
|
|
5871
6876
|
exports.applyBlockInlineStyles = applyBlockInlineStyles;
|
|
5872
6877
|
exports.assignMissingIds = assignMissingIds;
|
|
6878
|
+
exports.blocksToMarkdown = blocksToMarkdown;
|
|
6879
|
+
exports.blocksToPlainText = blocksToPlainText;
|
|
5873
6880
|
exports.classifyBlockElement = classifyBlockElement;
|
|
6881
|
+
exports.decodeEntities = decodeEntities;
|
|
6882
|
+
exports.escapeAttr = escapeAttr;
|
|
6883
|
+
exports.escapeHtml = escapeHtml;
|
|
5874
6884
|
exports.extractInlineContent = extractInlineContent;
|
|
5875
6885
|
exports.fillInlineContent = fillInlineContent;
|
|
5876
6886
|
exports.findBlockFrom = findBlockFrom;
|
|
@@ -5878,13 +6888,24 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
5878
6888
|
exports.isElementBlank = isElementBlank;
|
|
5879
6889
|
exports.listBlocks = listBlocks;
|
|
5880
6890
|
exports.normalizeContent = normalizeContent;
|
|
6891
|
+
exports.parseHtmlFragment = parseHtmlFragment;
|
|
5881
6892
|
exports.placeCaretAtStart = placeCaretAtStart;
|
|
5882
6893
|
exports.readBlockStyleTheme = readBlockStyleTheme;
|
|
5883
6894
|
exports.renderBlock = renderBlock;
|
|
6895
|
+
exports.renderBlockToHTML = renderBlockToHTML;
|
|
5884
6896
|
exports.renderBlocks = renderBlocks;
|
|
6897
|
+
exports.renderBlocksToHTML = renderBlocksToHTML;
|
|
6898
|
+
exports.restoreAlignFromClasses = restoreAlignFromClasses;
|
|
5885
6899
|
exports.serializeBlock = serializeBlock;
|
|
5886
6900
|
exports.serializeBlocks = serializeBlocks;
|
|
6901
|
+
exports.serializeNodes = serializeNodes;
|
|
6902
|
+
exports.snapshotVersionOf = snapshotVersionOf;
|
|
5887
6903
|
exports.stripEditorOnlyAttrs = stripEditorOnlyAttrs;
|
|
6904
|
+
exports.stripEditorOnlyNodes = stripEditorOnlyNodes;
|
|
6905
|
+
exports.textOf = textOf;
|
|
6906
|
+
exports.textWithBlockBreaks = textWithBlockBreaks;
|
|
6907
|
+
exports.upgradeSnapshot = upgradeSnapshot;
|
|
6908
|
+
exports.upgradeSnapshots = upgradeSnapshots;
|
|
5888
6909
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
5889
6910
|
return exports;
|
|
5890
6911
|
}({});
|