@underverse-ui/underverse 1.0.146 → 1.0.148
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/api-reference.json +1 -1
- package/dist/index.cjs +140 -111
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +140 -111
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
package/api-reference.json
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -25835,67 +25835,7 @@ var SlashCommand = import_core4.Extension.create({
|
|
|
25835
25835
|
var import_core5 = require("@tiptap/core");
|
|
25836
25836
|
var import_state2 = require("@tiptap/pm/state");
|
|
25837
25837
|
|
|
25838
|
-
// src/components/UEditor/
|
|
25839
|
-
var LINK_PROTOCOLS = /* @__PURE__ */ new Set(["http:", "https:", "mailto:", "tel:"]);
|
|
25840
|
-
var IMAGE_PROTOCOLS = /* @__PURE__ */ new Set(["http:", "https:"]);
|
|
25841
|
-
function normalizeUrlInput(raw) {
|
|
25842
|
-
return raw.trim().replace(/[\u0000-\u001F\u007F\s]+/g, "");
|
|
25843
|
-
}
|
|
25844
|
-
function isProtocolRelativeUrl(value) {
|
|
25845
|
-
return value.startsWith("//");
|
|
25846
|
-
}
|
|
25847
|
-
function isRelativeUrl(value) {
|
|
25848
|
-
return value.startsWith("/") || value.startsWith("./") || value.startsWith("../") || value.startsWith("#");
|
|
25849
|
-
}
|
|
25850
|
-
function isDataImageUrl(value) {
|
|
25851
|
-
return /^data:image\/(?:png|jpe?g|gif|webp|svg\+xml|bmp|x-icon|avif);base64,/i.test(value);
|
|
25852
|
-
}
|
|
25853
|
-
function isSafeUEditorUrl(raw, kind) {
|
|
25854
|
-
const value = normalizeUrlInput(raw);
|
|
25855
|
-
if (!value) return false;
|
|
25856
|
-
if (kind === "image" && isDataImageUrl(value)) return true;
|
|
25857
|
-
if (isRelativeUrl(value)) return true;
|
|
25858
|
-
if (isProtocolRelativeUrl(value)) return false;
|
|
25859
|
-
try {
|
|
25860
|
-
const parsed = new URL(value);
|
|
25861
|
-
return kind === "image" ? IMAGE_PROTOCOLS.has(parsed.protocol) : LINK_PROTOCOLS.has(parsed.protocol);
|
|
25862
|
-
} catch {
|
|
25863
|
-
return false;
|
|
25864
|
-
}
|
|
25865
|
-
}
|
|
25866
|
-
function sanitizeUEditorUrl(raw, kind) {
|
|
25867
|
-
const value = raw.trim();
|
|
25868
|
-
if (!value) return "";
|
|
25869
|
-
if (isSafeUEditorUrl(value, kind)) return normalizeUrlInput(value);
|
|
25870
|
-
if (kind === "link" && !isProtocolRelativeUrl(value) && !/^[a-zA-Z][a-zA-Z0-9+.-]*:/.test(value)) {
|
|
25871
|
-
const withProtocol = `https://${value}`;
|
|
25872
|
-
return isSafeUEditorUrl(withProtocol, kind) ? withProtocol : "";
|
|
25873
|
-
}
|
|
25874
|
-
return "";
|
|
25875
|
-
}
|
|
25876
|
-
|
|
25877
|
-
// src/components/UEditor/clipboard-images.ts
|
|
25878
|
-
var DEFAULT_UEDITOR_IMAGE_MAX_FILE_SIZE = 10 * 1024 * 1024;
|
|
25879
|
-
var DEFAULT_UEDITOR_IMAGE_MIME_TYPES = ["image/png", "image/jpeg", "image/webp", "image/gif", "image/svg+xml"];
|
|
25880
|
-
function getImageFiles(dataTransfer) {
|
|
25881
|
-
if (!dataTransfer) return [];
|
|
25882
|
-
const itemFiles = [];
|
|
25883
|
-
const byKey = /* @__PURE__ */ new Map();
|
|
25884
|
-
for (const item of Array.from(dataTransfer.items ?? [])) {
|
|
25885
|
-
if (item.kind !== "file") continue;
|
|
25886
|
-
if (!item.type.startsWith("image/")) continue;
|
|
25887
|
-
const file = item.getAsFile();
|
|
25888
|
-
if (!file) continue;
|
|
25889
|
-
byKey.set(`${file.name}:${file.size}:${file.lastModified}`, file);
|
|
25890
|
-
}
|
|
25891
|
-
itemFiles.push(...Array.from(byKey.values()));
|
|
25892
|
-
if (itemFiles.length > 0) return itemFiles;
|
|
25893
|
-
for (const file of Array.from(dataTransfer.files ?? [])) {
|
|
25894
|
-
if (!file.type.startsWith("image/")) continue;
|
|
25895
|
-
byKey.set(`${file.name}:${file.size}:${file.lastModified}`, file);
|
|
25896
|
-
}
|
|
25897
|
-
return Array.from(byKey.values());
|
|
25898
|
-
}
|
|
25838
|
+
// src/components/UEditor/clipboard-tables.ts
|
|
25899
25839
|
function getClipboardData(dataTransfer, type) {
|
|
25900
25840
|
try {
|
|
25901
25841
|
return dataTransfer.getData(type) ?? "";
|
|
@@ -25913,42 +25853,77 @@ function extractClipboardHtmlFragment(html) {
|
|
|
25913
25853
|
}
|
|
25914
25854
|
return html;
|
|
25915
25855
|
}
|
|
25916
|
-
|
|
25917
|
-
|
|
25918
|
-
var TABLE_BLOCK_SELECTOR = "p,ul,ol,blockquote,pre,h1,h2,h3,h4,h5,h6,hr,table";
|
|
25919
|
-
function hasMeaningfulTableCellText(value) {
|
|
25920
|
-
return Boolean(value?.replace(/\u00a0/g, " ").trim());
|
|
25856
|
+
function normalizeClipboardCellText(value) {
|
|
25857
|
+
return value.replace(/\r\n/g, "\n").replace(/\r/g, "\n").replace(/\u00a0/g, " ").replace(/[ \t]+\n/g, "\n").replace(/\n[ \t]+/g, "\n").replace(/\n+$/g, "").replace(/^\n+/g, "").trim();
|
|
25921
25858
|
}
|
|
25922
|
-
function
|
|
25923
|
-
|
|
25924
|
-
|
|
25925
|
-
const hasMediaContent = Boolean(cell.querySelector(TABLE_MEDIA_SELECTOR));
|
|
25926
|
-
if (!hasText && !hasBlockContent && !hasMediaContent) {
|
|
25927
|
-
cell.innerHTML = EMPTY_TABLE_CELL_HTML;
|
|
25859
|
+
function getClipboardCellText(node) {
|
|
25860
|
+
if (node.nodeType === Node.TEXT_NODE) {
|
|
25861
|
+
return node.textContent ?? "";
|
|
25928
25862
|
}
|
|
25929
|
-
|
|
25930
|
-
|
|
25931
|
-
|
|
25932
|
-
|
|
25933
|
-
|
|
25863
|
+
if (!(node instanceof HTMLElement)) {
|
|
25864
|
+
return "";
|
|
25865
|
+
}
|
|
25866
|
+
if (node.tagName === "BR") {
|
|
25867
|
+
return "\n";
|
|
25868
|
+
}
|
|
25869
|
+
const childText = Array.from(node.childNodes).map(getClipboardCellText).join("");
|
|
25870
|
+
if ((node.tagName === "P" || node.tagName === "DIV" || node.tagName === "LI") && childText && !childText.endsWith("\n")) {
|
|
25871
|
+
return `${childText}
|
|
25872
|
+
`;
|
|
25934
25873
|
}
|
|
25874
|
+
return childText;
|
|
25875
|
+
}
|
|
25876
|
+
function getHtmlTableRows(table) {
|
|
25877
|
+
const rows = Array.from(table.querySelectorAll("tr")).map(
|
|
25878
|
+
(row) => Array.from(row.children).filter((cell) => cell instanceof HTMLTableCellElement).map((cell) => ({
|
|
25879
|
+
text: normalizeClipboardCellText(getClipboardCellText(cell)),
|
|
25880
|
+
isHeader: cell.tagName === "TH"
|
|
25881
|
+
}))
|
|
25882
|
+
);
|
|
25883
|
+
return rows.filter((row) => row.length > 0);
|
|
25884
|
+
}
|
|
25885
|
+
function createParagraphContent(text) {
|
|
25886
|
+
return text ? {
|
|
25887
|
+
type: "paragraph",
|
|
25888
|
+
content: [{ type: "text", text }]
|
|
25889
|
+
} : { type: "paragraph" };
|
|
25935
25890
|
}
|
|
25936
|
-
function
|
|
25891
|
+
function createTableCellContent(cell) {
|
|
25892
|
+
const lines = cell.text.split("\n");
|
|
25893
|
+
const paragraphs = (lines.length > 0 ? lines : [""]).map(createParagraphContent);
|
|
25894
|
+
return {
|
|
25895
|
+
type: cell.isHeader ? "tableHeader" : "tableCell",
|
|
25896
|
+
content: paragraphs.length > 0 ? paragraphs : [{ type: "paragraph" }]
|
|
25897
|
+
};
|
|
25898
|
+
}
|
|
25899
|
+
function createTableContent(rows, minColumnCount = 1) {
|
|
25900
|
+
const tableRows = rows.filter((row) => row.length > 0);
|
|
25901
|
+
if (tableRows.length === 0) return null;
|
|
25902
|
+
const columnCount = tableRows.reduce((max, row) => Math.max(max, row.length), 0);
|
|
25903
|
+
if (columnCount < minColumnCount) return null;
|
|
25904
|
+
return {
|
|
25905
|
+
type: "table",
|
|
25906
|
+
content: tableRows.map((row) => {
|
|
25907
|
+
const normalizedRow = Array.from(
|
|
25908
|
+
{ length: columnCount },
|
|
25909
|
+
(_, index) => row[index] ?? { text: "", isHeader: false }
|
|
25910
|
+
);
|
|
25911
|
+
return {
|
|
25912
|
+
type: "tableRow",
|
|
25913
|
+
content: normalizedRow.map(createTableCellContent)
|
|
25914
|
+
};
|
|
25915
|
+
})
|
|
25916
|
+
};
|
|
25917
|
+
}
|
|
25918
|
+
function getClipboardTableContent(dataTransfer) {
|
|
25937
25919
|
const html = getClipboardData(dataTransfer, "text/html");
|
|
25938
|
-
if (!/<table(?:\s|>)/i.test(html)) return
|
|
25920
|
+
if (!/<table(?:\s|>)/i.test(html)) return null;
|
|
25921
|
+
if (typeof DOMParser === "undefined") return null;
|
|
25939
25922
|
const fragment = extractClipboardHtmlFragment(html);
|
|
25940
|
-
|
|
25941
|
-
|
|
25942
|
-
|
|
25943
|
-
|
|
25944
|
-
normalizeClipboardTable(table);
|
|
25945
|
-
return table.outerHTML;
|
|
25946
|
-
}
|
|
25947
|
-
}
|
|
25948
|
-
return fragment;
|
|
25949
|
-
}
|
|
25950
|
-
function escapeHtml(value) {
|
|
25951
|
-
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
25923
|
+
const doc = new DOMParser().parseFromString(fragment, "text/html");
|
|
25924
|
+
const table = doc.querySelector("table");
|
|
25925
|
+
if (!(table instanceof HTMLTableElement)) return null;
|
|
25926
|
+
return createTableContent(getHtmlTableRows(table));
|
|
25952
25927
|
}
|
|
25953
25928
|
function parseClipboardTsvRows(text) {
|
|
25954
25929
|
const rows = [];
|
|
@@ -26000,22 +25975,76 @@ function parseClipboardTsvRows(text) {
|
|
|
26000
25975
|
}
|
|
26001
25976
|
return rows;
|
|
26002
25977
|
}
|
|
26003
|
-
function
|
|
26004
|
-
const lines = value.split("\n");
|
|
26005
|
-
const paragraphs = lines.length > 0 ? lines : [""];
|
|
26006
|
-
return paragraphs.map((line) => `<p>${escapeHtml(line)}</p>`).join("");
|
|
26007
|
-
}
|
|
26008
|
-
function getClipboardTsvTableHtml(dataTransfer) {
|
|
25978
|
+
function getClipboardTsvTableContent(dataTransfer) {
|
|
26009
25979
|
const text = getClipboardData(dataTransfer, "text/plain").replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
26010
|
-
if (!text.includes(" ")) return
|
|
25980
|
+
if (!text.includes(" ")) return null;
|
|
26011
25981
|
const rows = parseClipboardTsvRows(text);
|
|
26012
|
-
|
|
26013
|
-
|
|
26014
|
-
|
|
26015
|
-
|
|
26016
|
-
|
|
26017
|
-
|
|
26018
|
-
|
|
25982
|
+
return createTableContent(
|
|
25983
|
+
rows.map((row) => row.map((cell) => ({ text: normalizeClipboardCellText(cell), isHeader: false }))),
|
|
25984
|
+
2
|
|
25985
|
+
);
|
|
25986
|
+
}
|
|
25987
|
+
|
|
25988
|
+
// src/components/UEditor/url-safety.ts
|
|
25989
|
+
var LINK_PROTOCOLS = /* @__PURE__ */ new Set(["http:", "https:", "mailto:", "tel:"]);
|
|
25990
|
+
var IMAGE_PROTOCOLS = /* @__PURE__ */ new Set(["http:", "https:"]);
|
|
25991
|
+
function normalizeUrlInput(raw) {
|
|
25992
|
+
return raw.trim().replace(/[\u0000-\u001F\u007F\s]+/g, "");
|
|
25993
|
+
}
|
|
25994
|
+
function isProtocolRelativeUrl(value) {
|
|
25995
|
+
return value.startsWith("//");
|
|
25996
|
+
}
|
|
25997
|
+
function isRelativeUrl(value) {
|
|
25998
|
+
return value.startsWith("/") || value.startsWith("./") || value.startsWith("../") || value.startsWith("#");
|
|
25999
|
+
}
|
|
26000
|
+
function isDataImageUrl(value) {
|
|
26001
|
+
return /^data:image\/(?:png|jpe?g|gif|webp|svg\+xml|bmp|x-icon|avif);base64,/i.test(value);
|
|
26002
|
+
}
|
|
26003
|
+
function isSafeUEditorUrl(raw, kind) {
|
|
26004
|
+
const value = normalizeUrlInput(raw);
|
|
26005
|
+
if (!value) return false;
|
|
26006
|
+
if (kind === "image" && isDataImageUrl(value)) return true;
|
|
26007
|
+
if (isRelativeUrl(value)) return true;
|
|
26008
|
+
if (isProtocolRelativeUrl(value)) return false;
|
|
26009
|
+
try {
|
|
26010
|
+
const parsed = new URL(value);
|
|
26011
|
+
return kind === "image" ? IMAGE_PROTOCOLS.has(parsed.protocol) : LINK_PROTOCOLS.has(parsed.protocol);
|
|
26012
|
+
} catch {
|
|
26013
|
+
return false;
|
|
26014
|
+
}
|
|
26015
|
+
}
|
|
26016
|
+
function sanitizeUEditorUrl(raw, kind) {
|
|
26017
|
+
const value = raw.trim();
|
|
26018
|
+
if (!value) return "";
|
|
26019
|
+
if (isSafeUEditorUrl(value, kind)) return normalizeUrlInput(value);
|
|
26020
|
+
if (kind === "link" && !isProtocolRelativeUrl(value) && !/^[a-zA-Z][a-zA-Z0-9+.-]*:/.test(value)) {
|
|
26021
|
+
const withProtocol = `https://${value}`;
|
|
26022
|
+
return isSafeUEditorUrl(withProtocol, kind) ? withProtocol : "";
|
|
26023
|
+
}
|
|
26024
|
+
return "";
|
|
26025
|
+
}
|
|
26026
|
+
|
|
26027
|
+
// src/components/UEditor/clipboard-images.ts
|
|
26028
|
+
var DEFAULT_UEDITOR_IMAGE_MAX_FILE_SIZE = 10 * 1024 * 1024;
|
|
26029
|
+
var DEFAULT_UEDITOR_IMAGE_MIME_TYPES = ["image/png", "image/jpeg", "image/webp", "image/gif", "image/svg+xml"];
|
|
26030
|
+
function getImageFiles(dataTransfer) {
|
|
26031
|
+
if (!dataTransfer) return [];
|
|
26032
|
+
const itemFiles = [];
|
|
26033
|
+
const byKey = /* @__PURE__ */ new Map();
|
|
26034
|
+
for (const item of Array.from(dataTransfer.items ?? [])) {
|
|
26035
|
+
if (item.kind !== "file") continue;
|
|
26036
|
+
if (!item.type.startsWith("image/")) continue;
|
|
26037
|
+
const file = item.getAsFile();
|
|
26038
|
+
if (!file) continue;
|
|
26039
|
+
byKey.set(`${file.name}:${file.size}:${file.lastModified}`, file);
|
|
26040
|
+
}
|
|
26041
|
+
itemFiles.push(...Array.from(byKey.values()));
|
|
26042
|
+
if (itemFiles.length > 0) return itemFiles;
|
|
26043
|
+
for (const file of Array.from(dataTransfer.files ?? [])) {
|
|
26044
|
+
if (!file.type.startsWith("image/")) continue;
|
|
26045
|
+
byKey.set(`${file.name}:${file.size}:${file.lastModified}`, file);
|
|
26046
|
+
}
|
|
26047
|
+
return Array.from(byKey.values());
|
|
26019
26048
|
}
|
|
26020
26049
|
function fileToDataUrl(file) {
|
|
26021
26050
|
return new Promise((resolve, reject) => {
|
|
@@ -26071,16 +26100,16 @@ var ClipboardImages = import_core5.Extension.create({
|
|
|
26071
26100
|
props: {
|
|
26072
26101
|
handlePaste: (_view, event) => {
|
|
26073
26102
|
if (!event || !event.clipboardData) return false;
|
|
26074
|
-
const
|
|
26075
|
-
if (
|
|
26103
|
+
const tableContent = getClipboardTableContent(event.clipboardData);
|
|
26104
|
+
if (tableContent) {
|
|
26076
26105
|
event.preventDefault();
|
|
26077
|
-
editor.chain().focus().insertContent(
|
|
26106
|
+
editor.chain().focus().insertContent(tableContent).run();
|
|
26078
26107
|
return true;
|
|
26079
26108
|
}
|
|
26080
|
-
const
|
|
26081
|
-
if (
|
|
26109
|
+
const tsvTableContent = getClipboardTsvTableContent(event.clipboardData);
|
|
26110
|
+
if (tsvTableContent) {
|
|
26082
26111
|
event.preventDefault();
|
|
26083
|
-
editor.chain().focus().insertContent(
|
|
26112
|
+
editor.chain().focus().insertContent(tsvTableContent).run();
|
|
26084
26113
|
return true;
|
|
26085
26114
|
}
|
|
26086
26115
|
const files = getImageFiles(event.clipboardData);
|