@underverse-ui/underverse 1.0.144 → 1.0.146

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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "package": "@underverse-ui/underverse",
3
- "version": "1.0.144",
3
+ "version": "1.0.146",
4
4
  "sourceEntry": "src/index.ts",
5
5
  "totalExports": 232,
6
6
  "exports": [
package/dist/index.cjs CHANGED
@@ -25913,6 +25913,26 @@ function extractClipboardHtmlFragment(html) {
25913
25913
  }
25914
25914
  return html;
25915
25915
  }
25916
+ var EMPTY_TABLE_CELL_HTML = "<p></p>";
25917
+ var TABLE_MEDIA_SELECTOR = "img,video,audio,iframe,svg,canvas,embed,object";
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());
25921
+ }
25922
+ function normalizeClipboardTableCell(cell) {
25923
+ const hasText = hasMeaningfulTableCellText(cell.textContent);
25924
+ const hasBlockContent = Boolean(cell.querySelector(TABLE_BLOCK_SELECTOR));
25925
+ const hasMediaContent = Boolean(cell.querySelector(TABLE_MEDIA_SELECTOR));
25926
+ if (!hasText && !hasBlockContent && !hasMediaContent) {
25927
+ cell.innerHTML = EMPTY_TABLE_CELL_HTML;
25928
+ }
25929
+ }
25930
+ function normalizeClipboardTable(table) {
25931
+ for (const cell of Array.from(table.querySelectorAll("td,th"))) {
25932
+ if (!(cell instanceof HTMLTableCellElement)) continue;
25933
+ normalizeClipboardTableCell(cell);
25934
+ }
25935
+ }
25916
25936
  function getClipboardTableHtml(dataTransfer) {
25917
25937
  const html = getClipboardData(dataTransfer, "text/html");
25918
25938
  if (!/<table(?:\s|>)/i.test(html)) return "";
@@ -25920,19 +25940,81 @@ function getClipboardTableHtml(dataTransfer) {
25920
25940
  if (typeof DOMParser !== "undefined") {
25921
25941
  const doc = new DOMParser().parseFromString(fragment, "text/html");
25922
25942
  const table = doc.querySelector("table");
25923
- if (table) return table.outerHTML;
25943
+ if (table instanceof HTMLTableElement) {
25944
+ normalizeClipboardTable(table);
25945
+ return table.outerHTML;
25946
+ }
25924
25947
  }
25925
25948
  return fragment;
25926
25949
  }
25927
25950
  function escapeHtml(value) {
25928
25951
  return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
25929
25952
  }
25953
+ function parseClipboardTsvRows(text) {
25954
+ const rows = [];
25955
+ let row = [];
25956
+ let field = "";
25957
+ let inQuotes = false;
25958
+ const pushField = () => {
25959
+ row.push(field);
25960
+ field = "";
25961
+ };
25962
+ const pushRow = () => {
25963
+ pushField();
25964
+ rows.push(row);
25965
+ row = [];
25966
+ };
25967
+ for (let index = 0; index < text.length; index += 1) {
25968
+ const char = text[index];
25969
+ const nextChar = text[index + 1];
25970
+ if (inQuotes) {
25971
+ if (char === '"' && nextChar === '"') {
25972
+ field += '"';
25973
+ index += 1;
25974
+ continue;
25975
+ }
25976
+ if (char === '"') {
25977
+ inQuotes = false;
25978
+ continue;
25979
+ }
25980
+ field += char;
25981
+ continue;
25982
+ }
25983
+ if (char === '"' && field.length === 0) {
25984
+ inQuotes = true;
25985
+ continue;
25986
+ }
25987
+ if (char === " ") {
25988
+ pushField();
25989
+ continue;
25990
+ }
25991
+ if (char === "\n") {
25992
+ pushRow();
25993
+ continue;
25994
+ }
25995
+ field += char;
25996
+ }
25997
+ pushRow();
25998
+ while (rows.length > 0 && rows[rows.length - 1].every((cell) => cell === "")) {
25999
+ rows.pop();
26000
+ }
26001
+ return rows;
26002
+ }
26003
+ function renderClipboardTableCellHtml(value) {
26004
+ const lines = value.split("\n");
26005
+ const paragraphs = lines.length > 0 ? lines : [""];
26006
+ return paragraphs.map((line) => `<p>${escapeHtml(line)}</p>`).join("");
26007
+ }
25930
26008
  function getClipboardTsvTableHtml(dataTransfer) {
25931
- const text = getClipboardData(dataTransfer, "text/plain").replace(/\r\n/g, "\n").replace(/\r/g, "\n").replace(/\n+$/, "");
26009
+ const text = getClipboardData(dataTransfer, "text/plain").replace(/\r\n/g, "\n").replace(/\r/g, "\n");
25932
26010
  if (!text.includes(" ")) return "";
25933
- const rows = text.split("\n").map((row) => row.split(" "));
26011
+ const rows = parseClipboardTsvRows(text);
25934
26012
  if (rows.length === 0 || rows.every((row) => row.length < 2)) return "";
25935
- const body = rows.map((row) => `<tr>${row.map((cell) => `<td>${escapeHtml(cell)}</td>`).join("")}</tr>`).join("");
26013
+ const columnCount = rows.reduce((max, row) => Math.max(max, row.length), 0);
26014
+ const body = rows.map((row) => {
26015
+ const normalizedRow = Array.from({ length: columnCount }, (_, index) => row[index] ?? "");
26016
+ return `<tr>${normalizedRow.map((cell) => `<td>${renderClipboardTableCellHtml(cell)}</td>`).join("")}</tr>`;
26017
+ }).join("");
25936
26018
  return `<table><tbody>${body}</tbody></table>`;
25937
26019
  }
25938
26020
  function fileToDataUrl(file) {
@@ -36721,6 +36803,14 @@ var MenuBar = ({
36721
36803
  }
36722
36804
  openPreviewDialog();
36723
36805
  };
36806
+ import_react67.default.useEffect(() => {
36807
+ if (!showPreviewDialog) return void 0;
36808
+ const previousOverflow = document.body.style.overflow;
36809
+ document.body.style.overflow = "hidden";
36810
+ return () => {
36811
+ document.body.style.overflow = previousOverflow;
36812
+ };
36813
+ }, [showPreviewDialog]);
36724
36814
  const applySourceHtml = () => {
36725
36815
  editor.chain().focus().setContent(sourceHtml).run();
36726
36816
  setShowSourceDialog(false);
@@ -36938,29 +37028,38 @@ var MenuBar = ({
36938
37028
  ] })
36939
37029
  }
36940
37030
  ),
36941
- /* @__PURE__ */ (0, import_jsx_runtime93.jsx)(
36942
- Modal_default,
36943
- {
36944
- isOpen: showPreviewDialog,
36945
- onClose: () => setShowPreviewDialog(false),
36946
- title: t("menubar.preview"),
36947
- size: "lg",
36948
- children: editor.isEmpty ? /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("p", { className: "text-muted-foreground text-sm", children: t("menubar.previewEmpty") }) : /* @__PURE__ */ (0, import_jsx_runtime93.jsx)(
36949
- "div",
37031
+ showPreviewDialog && /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)("div", { className: "fixed inset-0 z-9999 flex flex-col bg-background text-foreground", children: [
37032
+ /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)("div", { className: "flex shrink-0 items-center justify-between border-b border-border bg-card px-4 py-3", children: [
37033
+ /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("h2", { className: "text-base font-semibold", children: t("menubar.preview") }),
37034
+ /* @__PURE__ */ (0, import_jsx_runtime93.jsx)(
37035
+ "button",
36950
37036
  {
36951
- "data-testid": "preview-content",
36952
- className: "max-h-[70vh] overflow-y-auto overscroll-contain pr-2",
36953
- children: /* @__PURE__ */ (0, import_jsx_runtime93.jsx)(
36954
- "div",
36955
- {
36956
- className: UEDITOR_PROSEMIRROR_CLASS_NAME,
36957
- dangerouslySetInnerHTML: { __html: editor.getHTML() }
36958
- }
36959
- )
37037
+ type: "button",
37038
+ onClick: () => setShowPreviewDialog(false),
37039
+ "aria-label": t("menubar.closeDialog"),
37040
+ className: cn(
37041
+ "inline-flex h-8 w-8 items-center justify-center rounded-md text-muted-foreground transition-colors",
37042
+ "hover:bg-accent hover:text-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-1"
37043
+ ),
37044
+ children: /* @__PURE__ */ (0, import_jsx_runtime93.jsx)(import_lucide_react53.X, { className: "h-4 w-4", "aria-hidden": "true" })
36960
37045
  }
36961
37046
  )
36962
- }
36963
- )
37047
+ ] }),
37048
+ /* @__PURE__ */ (0, import_jsx_runtime93.jsx)(
37049
+ "div",
37050
+ {
37051
+ "data-testid": "preview-content",
37052
+ className: "min-h-0 flex-1 overflow-y-auto overscroll-contain px-4 py-4 md:px-8",
37053
+ children: editor.isEmpty ? /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("p", { className: "text-muted-foreground text-sm", children: t("menubar.previewEmpty") }) : /* @__PURE__ */ (0, import_jsx_runtime93.jsx)(
37054
+ "div",
37055
+ {
37056
+ className: UEDITOR_PROSEMIRROR_CLASS_NAME,
37057
+ dangerouslySetInnerHTML: { __html: editor.getHTML() }
37058
+ }
37059
+ )
37060
+ }
37061
+ )
37062
+ ] })
36964
37063
  ] });
36965
37064
  };
36966
37065