@pixerate/editor 0.5.1 → 0.6.1
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/dist/extensions/index.cjs +202 -15
- package/dist/extensions/index.cjs.map +1 -1
- package/dist/extensions/index.d.cts +50 -1
- package/dist/extensions/index.d.ts +50 -1
- package/dist/extensions/index.js +195 -14
- package/dist/extensions/index.js.map +1 -1
- package/dist/index.cjs +200 -13
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +194 -13
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
|
@@ -33,6 +33,7 @@ __export(extensions_exports, {
|
|
|
33
33
|
ColorHighlighter: () => ColorHighlighter,
|
|
34
34
|
FontSize: () => FontSize,
|
|
35
35
|
GradientText: () => GradientText,
|
|
36
|
+
Image: () => Image2,
|
|
36
37
|
LoadingNode: () => LoadingNode,
|
|
37
38
|
Markdown: () => Markdown2,
|
|
38
39
|
Mention: () => Mention,
|
|
@@ -41,7 +42,12 @@ __export(extensions_exports, {
|
|
|
41
42
|
TemplateSuggestions: () => TemplateSuggestions,
|
|
42
43
|
createMentionExtension: () => createMentionExtension,
|
|
43
44
|
createRichTextPreset: () => createRichTextPreset,
|
|
44
|
-
findHexColors: () => findHexColors
|
|
45
|
+
findHexColors: () => findHexColors,
|
|
46
|
+
handleImageInsertion: () => handleImageInsertion,
|
|
47
|
+
imagePastePluginKey: () => imagePastePluginKey,
|
|
48
|
+
insertImageNode: () => insertImageNode,
|
|
49
|
+
removeImageNode: () => removeImageNode,
|
|
50
|
+
updateImageSrc: () => updateImageSrc
|
|
45
51
|
});
|
|
46
52
|
module.exports = __toCommonJS(extensions_exports);
|
|
47
53
|
|
|
@@ -1594,20 +1600,183 @@ var Markdown = import_core8.Extension.create({
|
|
|
1594
1600
|
var resolveExt = (mod, name) => mod?.[name] || mod?.default?.[name] || mod?.default?.default || mod?.default || mod;
|
|
1595
1601
|
var Markdown2 = resolveExt(Markdown, "Markdown");
|
|
1596
1602
|
|
|
1597
|
-
// src/extensions/
|
|
1603
|
+
// src/extensions/image.ts
|
|
1604
|
+
var _Image = __toESM(require("@tiptap/extension-image"), 1);
|
|
1605
|
+
var import_state5 = require("@tiptap/pm/state");
|
|
1598
1606
|
var resolveExt2 = (mod, name) => mod?.[name] || mod?.default?.[name] || mod?.default?.default || mod?.default || mod;
|
|
1599
|
-
var
|
|
1600
|
-
var
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1607
|
+
var BaseImage = resolveExt2(_Image, "Image");
|
|
1608
|
+
var imagePastePluginKey = new import_state5.PluginKey("imagePasteHandler");
|
|
1609
|
+
function insertImageNode(view, src, alt) {
|
|
1610
|
+
const { schema } = view.state;
|
|
1611
|
+
const imageType = schema.nodes.image;
|
|
1612
|
+
if (!imageType) return;
|
|
1613
|
+
const node = imageType.create({ src, alt: alt || "" });
|
|
1614
|
+
const tr = view.state.tr.replaceSelectionWith(node);
|
|
1615
|
+
view.dispatch(tr);
|
|
1616
|
+
}
|
|
1617
|
+
function updateImageSrc(view, oldSrc, newSrc) {
|
|
1618
|
+
const { doc } = view.state;
|
|
1619
|
+
let foundPos = null;
|
|
1620
|
+
let foundAttrs = null;
|
|
1621
|
+
doc.descendants((node, pos) => {
|
|
1622
|
+
if (node.type.name === "image" && node.attrs.src === oldSrc) {
|
|
1623
|
+
foundPos = pos;
|
|
1624
|
+
foundAttrs = node.attrs;
|
|
1625
|
+
return false;
|
|
1626
|
+
}
|
|
1627
|
+
});
|
|
1628
|
+
if (foundPos !== null && foundAttrs) {
|
|
1629
|
+
const tr = view.state.tr.setNodeMarkup(foundPos, void 0, {
|
|
1630
|
+
...foundAttrs,
|
|
1631
|
+
src: newSrc
|
|
1632
|
+
});
|
|
1633
|
+
view.dispatch(tr);
|
|
1634
|
+
}
|
|
1635
|
+
}
|
|
1636
|
+
function removeImageNode(view, src) {
|
|
1637
|
+
const { doc } = view.state;
|
|
1638
|
+
let foundPos = null;
|
|
1639
|
+
let nodeSize = 0;
|
|
1640
|
+
doc.descendants((node, pos) => {
|
|
1641
|
+
if (node.type.name === "image" && node.attrs.src === src) {
|
|
1642
|
+
foundPos = pos;
|
|
1643
|
+
nodeSize = node.nodeSize;
|
|
1644
|
+
return false;
|
|
1645
|
+
}
|
|
1646
|
+
});
|
|
1647
|
+
if (foundPos !== null) {
|
|
1648
|
+
const tr = view.state.tr.delete(foundPos, foundPos + nodeSize);
|
|
1649
|
+
view.dispatch(tr);
|
|
1650
|
+
}
|
|
1651
|
+
}
|
|
1652
|
+
function handleImageInsertion(view, file, options) {
|
|
1653
|
+
if (typeof options.upload === "function") {
|
|
1654
|
+
const hasObjectUrl = typeof URL !== "undefined" && typeof URL.createObjectURL === "function";
|
|
1655
|
+
const tempUrl = hasObjectUrl ? URL.createObjectURL(file) : null;
|
|
1656
|
+
if (tempUrl) {
|
|
1657
|
+
insertImageNode(view, tempUrl, file.name);
|
|
1658
|
+
}
|
|
1659
|
+
Promise.resolve(options.upload(file)).then((uploadedUrl) => {
|
|
1660
|
+
if (!uploadedUrl) {
|
|
1661
|
+
throw new Error("Upload handler returned empty URL");
|
|
1662
|
+
}
|
|
1663
|
+
if (tempUrl) {
|
|
1664
|
+
updateImageSrc(view, tempUrl, uploadedUrl);
|
|
1665
|
+
if (typeof URL.revokeObjectURL === "function") {
|
|
1666
|
+
URL.revokeObjectURL(tempUrl);
|
|
1667
|
+
}
|
|
1668
|
+
} else {
|
|
1669
|
+
insertImageNode(view, uploadedUrl, file.name);
|
|
1670
|
+
}
|
|
1671
|
+
}).catch((err) => {
|
|
1672
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
1673
|
+
console.error("Failed to upload pasted image:", error);
|
|
1674
|
+
if (tempUrl) {
|
|
1675
|
+
removeImageNode(view, tempUrl);
|
|
1676
|
+
if (typeof URL.revokeObjectURL === "function") {
|
|
1677
|
+
URL.revokeObjectURL(tempUrl);
|
|
1678
|
+
}
|
|
1679
|
+
}
|
|
1680
|
+
if (typeof options.onUploadError === "function") {
|
|
1681
|
+
options.onUploadError(error, file);
|
|
1682
|
+
}
|
|
1683
|
+
});
|
|
1684
|
+
} else if (options.allowBase64 !== false) {
|
|
1685
|
+
const maxBase64Size = options.maxBase64Size ?? 65536;
|
|
1686
|
+
if (file.size > maxBase64Size) {
|
|
1687
|
+
const err = new Error(
|
|
1688
|
+
`Image size (${Math.round(file.size / 1024)}KB) exceeds maxBase64Size (${Math.round(
|
|
1689
|
+
maxBase64Size / 1024
|
|
1690
|
+
)}KB). Provide an upload handler to support large images.`
|
|
1691
|
+
);
|
|
1692
|
+
console.warn(`[Editor] ${err.message}`);
|
|
1693
|
+
if (typeof options.onUploadError === "function") {
|
|
1694
|
+
options.onUploadError(err, file);
|
|
1695
|
+
}
|
|
1696
|
+
return;
|
|
1697
|
+
}
|
|
1698
|
+
if (typeof FileReader !== "undefined") {
|
|
1699
|
+
const reader = new FileReader();
|
|
1700
|
+
reader.onload = () => {
|
|
1701
|
+
const src = reader.result;
|
|
1702
|
+
if (src) {
|
|
1703
|
+
insertImageNode(view, src, file.name);
|
|
1704
|
+
}
|
|
1705
|
+
};
|
|
1706
|
+
reader.readAsDataURL(file);
|
|
1707
|
+
}
|
|
1708
|
+
}
|
|
1709
|
+
}
|
|
1710
|
+
var Image2 = BaseImage.extend({
|
|
1711
|
+
addOptions() {
|
|
1712
|
+
return {
|
|
1713
|
+
...this.parent?.(),
|
|
1714
|
+
allowBase64: true,
|
|
1715
|
+
maxBase64Size: 65536,
|
|
1716
|
+
enablePaste: true,
|
|
1717
|
+
enableDrop: true,
|
|
1718
|
+
upload: void 0,
|
|
1719
|
+
onUploadError: void 0,
|
|
1720
|
+
HTMLAttributes: {
|
|
1721
|
+
class: "rounded-md max-w-full h-auto my-2"
|
|
1722
|
+
}
|
|
1723
|
+
};
|
|
1724
|
+
},
|
|
1725
|
+
addProseMirrorPlugins() {
|
|
1726
|
+
const parentPlugins = this.parent?.() || [];
|
|
1727
|
+
const options = this.options;
|
|
1728
|
+
if (!options.enablePaste && !options.enableDrop) {
|
|
1729
|
+
return parentPlugins;
|
|
1730
|
+
}
|
|
1731
|
+
const pastePlugin = new import_state5.Plugin({
|
|
1732
|
+
key: imagePastePluginKey,
|
|
1733
|
+
props: {
|
|
1734
|
+
handlePaste(view, event) {
|
|
1735
|
+
if (!options.enablePaste) return false;
|
|
1736
|
+
const items = Array.from(event.clipboardData?.items || []);
|
|
1737
|
+
const imageItems = items.filter(
|
|
1738
|
+
(item) => item.kind === "file" && item.type.startsWith("image/")
|
|
1739
|
+
);
|
|
1740
|
+
if (imageItems.length === 0) return false;
|
|
1741
|
+
event.preventDefault();
|
|
1742
|
+
for (const item of imageItems) {
|
|
1743
|
+
const file = item.getAsFile();
|
|
1744
|
+
if (!file) continue;
|
|
1745
|
+
handleImageInsertion(view, file, options);
|
|
1746
|
+
}
|
|
1747
|
+
return true;
|
|
1748
|
+
},
|
|
1749
|
+
handleDrop(view, event) {
|
|
1750
|
+
if (!options.enableDrop) return false;
|
|
1751
|
+
const files = Array.from(event.dataTransfer?.files || []);
|
|
1752
|
+
const imageFiles = files.filter((f) => f.type.startsWith("image/"));
|
|
1753
|
+
if (imageFiles.length === 0) return false;
|
|
1754
|
+
event.preventDefault();
|
|
1755
|
+
for (const file of imageFiles) {
|
|
1756
|
+
handleImageInsertion(view, file, options);
|
|
1757
|
+
}
|
|
1758
|
+
return true;
|
|
1759
|
+
}
|
|
1760
|
+
}
|
|
1761
|
+
});
|
|
1762
|
+
return [...parentPlugins, pastePlugin];
|
|
1763
|
+
}
|
|
1764
|
+
});
|
|
1765
|
+
|
|
1766
|
+
// src/extensions/rich-text-preset.ts
|
|
1767
|
+
var resolveExt3 = (mod, name) => mod?.[name] || mod?.default?.[name] || mod?.default?.default || mod?.default || mod;
|
|
1768
|
+
var StarterKit = resolveExt3(_StarterKit, "StarterKit");
|
|
1769
|
+
var Color = resolveExt3(_Color, "Color");
|
|
1770
|
+
var Highlight = resolveExt3(_Highlight, "Highlight");
|
|
1771
|
+
var Link2 = resolveExt3(_Link, "Link");
|
|
1772
|
+
var TaskList2 = resolveExt3(_TaskList, "TaskList");
|
|
1773
|
+
var TaskItem2 = resolveExt3(_TaskItem, "TaskItem");
|
|
1774
|
+
var TextAlign = resolveExt3(_TextAlign, "TextAlign");
|
|
1775
|
+
var TextStyle = resolveExt3(_TextStyle, "TextStyle");
|
|
1776
|
+
var Typography = resolveExt3(_Typography, "Typography");
|
|
1777
|
+
var Underline = resolveExt3(_Underline, "Underline");
|
|
1778
|
+
var Placeholder = resolveExt3(_Placeholder, "Placeholder");
|
|
1779
|
+
var CharacterCount = resolveExt3(_CharacterCount, "CharacterCount");
|
|
1611
1780
|
function createRichTextPreset(options = {}) {
|
|
1612
1781
|
const {
|
|
1613
1782
|
placeholder = "Start typing...",
|
|
@@ -1729,6 +1898,18 @@ function createRichTextPreset(options = {}) {
|
|
|
1729
1898
|
})
|
|
1730
1899
|
);
|
|
1731
1900
|
}
|
|
1901
|
+
if (options.image !== false) {
|
|
1902
|
+
const imageConfig = typeof options.image === "object" ? options.image : {};
|
|
1903
|
+
extensions2.push(
|
|
1904
|
+
Image2.configure({
|
|
1905
|
+
HTMLAttributes: {
|
|
1906
|
+
class: "rounded-md max-w-full h-auto my-2",
|
|
1907
|
+
...imageConfig.HTMLAttributes || {}
|
|
1908
|
+
},
|
|
1909
|
+
...imageConfig
|
|
1910
|
+
})
|
|
1911
|
+
);
|
|
1912
|
+
}
|
|
1732
1913
|
return extensions2;
|
|
1733
1914
|
}
|
|
1734
1915
|
// Annotate the CommonJS export names for ESM import in node:
|
|
@@ -1736,6 +1917,7 @@ function createRichTextPreset(options = {}) {
|
|
|
1736
1917
|
ColorHighlighter,
|
|
1737
1918
|
FontSize,
|
|
1738
1919
|
GradientText,
|
|
1920
|
+
Image,
|
|
1739
1921
|
LoadingNode,
|
|
1740
1922
|
Markdown,
|
|
1741
1923
|
Mention,
|
|
@@ -1744,6 +1926,11 @@ function createRichTextPreset(options = {}) {
|
|
|
1744
1926
|
TemplateSuggestions,
|
|
1745
1927
|
createMentionExtension,
|
|
1746
1928
|
createRichTextPreset,
|
|
1747
|
-
findHexColors
|
|
1929
|
+
findHexColors,
|
|
1930
|
+
handleImageInsertion,
|
|
1931
|
+
imagePastePluginKey,
|
|
1932
|
+
insertImageNode,
|
|
1933
|
+
removeImageNode,
|
|
1934
|
+
updateImageSrc
|
|
1748
1935
|
});
|
|
1749
1936
|
//# sourceMappingURL=index.cjs.map
|