@tailor-cms/ce-html-edit 0.1.2 → 0.1.4

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.
@@ -3,8 +3,8 @@ declare module '@tiptap/vue-3' {
3
3
  interface Commands<ReturnType> {
4
4
  tooltip: {
5
5
  setTooltip: (attributes: {
6
- tooltip?: string;
7
- text?: string;
6
+ tooltip: string;
7
+ text: string;
8
8
  }) => ReturnType;
9
9
  unsetTooltip: () => ReturnType;
10
10
  };
package/dist/index.cjs CHANGED
@@ -44,7 +44,7 @@ var manifest$1 = {
44
44
  ui,
45
45
  ai
46
46
  };
47
- var index_default = manifest$1;
47
+ var index_default$1 = manifest$1;
48
48
  function OrderedMap(content) {
49
49
  this.content = content;
50
50
  }
@@ -2491,7 +2491,7 @@ function isTagRule(rule) {
2491
2491
  function isStyleRule(rule) {
2492
2492
  return rule.style != null;
2493
2493
  }
2494
- class DOMParser {
2494
+ let DOMParser$1 = class DOMParser2 {
2495
2495
  /**
2496
2496
  Create a parser that targets the given schema, using the given
2497
2497
  parsing rules.
@@ -2617,9 +2617,9 @@ class DOMParser {
2617
2617
  [priority](https://prosemirror.net/docs/ref/#model.ParseRule.priority).
2618
2618
  */
2619
2619
  static fromSchema(schema) {
2620
- return schema.cached.domParser || (schema.cached.domParser = new DOMParser(schema, DOMParser.schemaRules(schema)));
2620
+ return schema.cached.domParser || (schema.cached.domParser = new DOMParser2(schema, DOMParser2.schemaRules(schema)));
2621
2621
  }
2622
- }
2622
+ };
2623
2623
  const blockTags = {
2624
2624
  address: true,
2625
2625
  article: true,
@@ -8641,7 +8641,7 @@ function parseFromClipboard(view, text, html, plainText, $context) {
8641
8641
  dom = child;
8642
8642
  }
8643
8643
  if (!slice2) {
8644
- let parser = view.someProp("clipboardParser") || view.someProp("domParser") || DOMParser.fromSchema(view.state.schema);
8644
+ let parser = view.someProp("clipboardParser") || view.someProp("domParser") || DOMParser$1.fromSchema(view.state.schema);
8645
8645
  slice2 = parser.parseSlice(dom, {
8646
8646
  preserveWhitespace: !!(asText || sliceData),
8647
8647
  context: $context,
@@ -10451,7 +10451,7 @@ function parseBetween(view, from_, to_) {
10451
10451
  }
10452
10452
  }
10453
10453
  let startDoc = view.state.doc;
10454
- let parser = view.someProp("domParser") || DOMParser.fromSchema(view.state.schema);
10454
+ let parser = view.someProp("domParser") || DOMParser$1.fromSchema(view.state.schema);
10455
10455
  let $from = startDoc.resolve(from2);
10456
10456
  let sel = null, doc2 = parser.parse(parent, {
10457
10457
  topNode: $from.parent,
@@ -13774,15 +13774,15 @@ function createNodeFromContent(content, schema, options) {
13774
13774
  })
13775
13775
  });
13776
13776
  if (options.slice) {
13777
- DOMParser.fromSchema(contentCheckSchema).parseSlice(elementFromString(content), options.parseOptions);
13777
+ DOMParser$1.fromSchema(contentCheckSchema).parseSlice(elementFromString(content), options.parseOptions);
13778
13778
  } else {
13779
- DOMParser.fromSchema(contentCheckSchema).parse(elementFromString(content), options.parseOptions);
13779
+ DOMParser$1.fromSchema(contentCheckSchema).parse(elementFromString(content), options.parseOptions);
13780
13780
  }
13781
13781
  if (options.errorOnInvalidContent && hasInvalidContent) {
13782
13782
  throw new Error("[tiptap error]: Invalid HTML content", { cause: new Error(`Invalid element found: ${invalidContent}`) });
13783
13783
  }
13784
13784
  }
13785
- const parser = DOMParser.fromSchema(schema);
13785
+ const parser = DOMParser$1.fromSchema(schema);
13786
13786
  if (options.slice) {
13787
13787
  return parser.parseSlice(elementFromString(content), options.parseOptions).content;
13788
13788
  }
@@ -19840,6 +19840,226 @@ const Highlight = Mark2.create({
19840
19840
  ];
19841
19841
  }
19842
19842
  });
19843
+ function parseRomanNumber(roman) {
19844
+ roman = roman.toUpperCase();
19845
+ let value = 0;
19846
+ const values = { I: 1, V: 5, X: 10, L: 50, C: 100, D: 500, M: 1e3 };
19847
+ let i = roman.length;
19848
+ let lastVal = 0;
19849
+ while (i--) {
19850
+ if (values[roman.charAt(i)] >= lastVal) {
19851
+ value += values[roman.charAt(i)];
19852
+ } else {
19853
+ value -= values[roman.charAt(i)];
19854
+ }
19855
+ lastVal = values[roman.charAt(i)];
19856
+ }
19857
+ return value;
19858
+ }
19859
+ function parseLetterNumber(str) {
19860
+ const alphaVal = (s) => s.toLowerCase().charCodeAt(0) - 97 + 1;
19861
+ let value = 0;
19862
+ let i = str.length;
19863
+ while (i--) {
19864
+ const factor = Math.pow(26, str.length - i - 1);
19865
+ value += alphaVal(str.charAt(i)) * factor;
19866
+ }
19867
+ return value;
19868
+ }
19869
+ function unwrapNode(node) {
19870
+ const parent = node.parentNode;
19871
+ while (node.firstChild) {
19872
+ parent == null ? void 0 : parent.insertBefore(node.firstChild, node);
19873
+ }
19874
+ parent == null ? void 0 : parent.removeChild(node);
19875
+ }
19876
+ function parseStyleAttribute(el) {
19877
+ var _a;
19878
+ const styleRaw = ((_a = el == null ? void 0 : el.attributes[`style`]) == null ? void 0 : _a.value) || ``;
19879
+ return Object.fromEntries(styleRaw.split(`;`).map((line) => line.split(`:`).map((v) => v.trim())));
19880
+ }
19881
+ function transformMsoStyles(html) {
19882
+ html = html.replace(/<o:p>(.*?)<\/o:p>/g, ``);
19883
+ const parser = new DOMParser();
19884
+ const doc2 = parser.parseFromString(html, `text/html`);
19885
+ doc2.querySelectorAll(`[style*="mso-"]`).forEach((node) => {
19886
+ const styles = parseStyleAttribute(node);
19887
+ const newStyles = [];
19888
+ for (const prop of Object.keys(styles)) {
19889
+ if (prop && !prop.startsWith(`mso-`)) {
19890
+ newStyles.push(`${prop}: ${styles[prop]}`);
19891
+ }
19892
+ }
19893
+ node.setAttribute(`style`, newStyles.join(`;`));
19894
+ });
19895
+ doc2.querySelectorAll(`[style*="color: black"]`).forEach((node) => {
19896
+ node.style.removeProperty(`color`);
19897
+ });
19898
+ return doc2.documentElement.outerHTML;
19899
+ }
19900
+ function transformRemoveBookmarks(html) {
19901
+ const parser = new DOMParser();
19902
+ const doc2 = parser.parseFromString(html, `text/html`);
19903
+ const bookmarks = doc2.querySelectorAll(`[style*="mso-bookmark:"]`);
19904
+ bookmarks.forEach((node) => {
19905
+ const bookmark = parseStyleAttribute(node)[`mso-bookmark`];
19906
+ const bookmarkLink = doc2.querySelector(`a[name="${bookmark}"]`);
19907
+ if (bookmarkLink) {
19908
+ unwrapNode(bookmarkLink);
19909
+ }
19910
+ unwrapNode(node);
19911
+ });
19912
+ return doc2.documentElement.outerHTML;
19913
+ }
19914
+ function transformLists(html) {
19915
+ if (html.indexOf(`mso-list:`) === -1) {
19916
+ return html;
19917
+ }
19918
+ const parser = new DOMParser();
19919
+ const doc2 = parser.parseFromString(html, `text/html`);
19920
+ let listStack = [];
19921
+ let currentListId;
19922
+ const listElements = doc2.querySelectorAll(`p[style*="mso-list:"]`);
19923
+ listElements.forEach((node) => {
19924
+ const el = node;
19925
+ const [msoListId, msoListLevel] = parseMsoListAttribute(parseStyleAttribute(el)[`mso-list`]);
19926
+ if (currentListId !== msoListId && (hasNonListItemSibling(el) || msoListLevel === 1)) {
19927
+ currentListId = msoListId;
19928
+ listStack = [];
19929
+ }
19930
+ while (msoListLevel > listStack.length) {
19931
+ const newList = createListElement(el);
19932
+ if (listStack.length > 0) {
19933
+ listStack[listStack.length - 1].appendChild(newList);
19934
+ } else {
19935
+ el.before(newList);
19936
+ }
19937
+ listStack.push(newList);
19938
+ }
19939
+ while (msoListLevel < listStack.length) {
19940
+ listStack.pop();
19941
+ }
19942
+ listStack[listStack.length - 1].appendChild(getListItemFromParagraph(el));
19943
+ el.remove();
19944
+ });
19945
+ return doc2.documentElement.outerHTML;
19946
+ }
19947
+ function hasNonListItemSibling(el) {
19948
+ return !el.previousElementSibling || !(el.previousElementSibling.nodeName === `OL` || el.previousElementSibling.nodeName === `UL`);
19949
+ }
19950
+ function getListItemFromParagraph(el) {
19951
+ const li = document.createElement(`li`);
19952
+ li.innerHTML = el.innerHTML.replace(listTypeRegex, ``);
19953
+ return li;
19954
+ }
19955
+ function parseMsoListAttribute(attr) {
19956
+ var _a;
19957
+ const msoListValue = attr;
19958
+ const msoListInfos = msoListValue.split(` `);
19959
+ const msoListId = msoListInfos.find((e) => /l[0-9]+/.test(e)) || ``;
19960
+ const msoListLevel = +(((_a = msoListInfos.find((e) => e.startsWith(`level`))) == null ? void 0 : _a.substring(5)) || 1);
19961
+ return [msoListId, msoListLevel];
19962
+ }
19963
+ var listTypeRegex = /<!--\[if \!supportLists\]-->((.|\n)*)<!--\[endif\]-->/m;
19964
+ function getListPrefix(el) {
19965
+ var _a;
19966
+ const matches2 = el.innerHTML.match(listTypeRegex);
19967
+ if (matches2 == null ? void 0 : matches2.length) {
19968
+ const parser = new DOMParser();
19969
+ const doc2 = parser.parseFromString(matches2[0], `text/html`);
19970
+ return ((_a = doc2.body.querySelector(`span`)) == null ? void 0 : _a.textContent) || ``;
19971
+ }
19972
+ return ``;
19973
+ }
19974
+ function createListElement(el) {
19975
+ const listInfo = getListInfo(getListPrefix(el));
19976
+ const list = document.createElement(listInfo.type);
19977
+ if (listInfo.countType) {
19978
+ list.setAttribute(`type`, listInfo.countType);
19979
+ }
19980
+ if (listInfo.start > 1) {
19981
+ list.setAttribute(`start`, listInfo.start.toString());
19982
+ }
19983
+ return list;
19984
+ }
19985
+ var listOrderRegex = {
19986
+ number: /[0-9]+\./,
19987
+ romanLower: /(?=[mdclxvi])m*(c[md]|d?c*)(x[cl]|l?x*)(i[xv]|v?i*)\./,
19988
+ romanUpper: /(?=[MDCLXVI])M*(C[MD]|D?C*)(X[CL]|L?X*)(I[XV]|V?I*)\./,
19989
+ letterLower: /[a-z]+\./,
19990
+ letterUpper: /[A-Z]+\./
19991
+ };
19992
+ function getListInfo(prefix) {
19993
+ let type2 = `ul`;
19994
+ let countType = null;
19995
+ let start2 = 1;
19996
+ let matches2;
19997
+ if (matches2 = prefix.match(listOrderRegex.number)) {
19998
+ type2 = `ol`;
19999
+ start2 = +matches2[0].replace(`.`, ``);
20000
+ } else if (matches2 = prefix.match(listOrderRegex.romanLower)) {
20001
+ type2 = `ol`;
20002
+ countType = `i`;
20003
+ start2 = +parseRomanNumber(matches2[0].replace(`.`, ``));
20004
+ } else if (matches2 = prefix.match(listOrderRegex.romanUpper)) {
20005
+ type2 = `ol`;
20006
+ countType = `I`;
20007
+ start2 = +parseRomanNumber(matches2[0].replace(`.`, ``));
20008
+ } else if (matches2 = prefix.match(listOrderRegex.letterLower)) {
20009
+ type2 = `ol`;
20010
+ countType = `a`;
20011
+ start2 = +parseLetterNumber(matches2[0].replace(`.`, ``));
20012
+ } else if (matches2 = prefix.match(listOrderRegex.letterUpper)) {
20013
+ type2 = `ol`;
20014
+ countType = `A`;
20015
+ start2 = +parseLetterNumber(matches2[0].replace(`.`, ``));
20016
+ }
20017
+ return {
20018
+ type: type2,
20019
+ start: start2,
20020
+ countType
20021
+ };
20022
+ }
20023
+ function transformRemoveLineNumberWrapper(html) {
20024
+ const parser = new DOMParser();
20025
+ const doc2 = parser.parseFromString(html, `text/html`);
20026
+ const lineNumbers = doc2.querySelectorAll(`[class*="MsoLineNumber"]`);
20027
+ lineNumbers.forEach((node) => {
20028
+ unwrapNode(node);
20029
+ });
20030
+ return doc2.documentElement.outerHTML;
20031
+ }
20032
+ function transformMsoHtmlClasses(html) {
20033
+ const parser = new DOMParser();
20034
+ const doc2 = parser.parseFromString(html, `text/html`);
20035
+ doc2.querySelectorAll(`p[class*="MsoNormal"]`).forEach((node) => {
20036
+ node.classList.remove(`MsoNormal`);
20037
+ });
20038
+ return doc2.documentElement.outerHTML;
20039
+ }
20040
+ var OfficePaste = Extension.create({
20041
+ priority: 99999,
20042
+ name: `office-paste`,
20043
+ addProseMirrorPlugins() {
20044
+ return [OfficePastePlugin];
20045
+ }
20046
+ });
20047
+ var OfficePastePlugin = new Plugin({
20048
+ key: new PluginKey("office-paste"),
20049
+ props: {
20050
+ transformPastedHTML(html) {
20051
+ if (html.indexOf(`microsoft-com`) !== -1 && html.indexOf(`office`) !== -1) {
20052
+ html = transformLists(html);
20053
+ html = transformRemoveBookmarks(html);
20054
+ html = transformMsoStyles(html);
20055
+ html = transformMsoHtmlClasses(html);
20056
+ html = transformRemoveLineNumberWrapper(html);
20057
+ }
20058
+ return html;
20059
+ }
20060
+ }
20061
+ });
20062
+ var index_default = OfficePaste;
19843
20063
  const Placeholder = Extension.create({
19844
20064
  name: "placeholder",
19845
20065
  addOptions() {
@@ -26168,11 +26388,10 @@ const Link = Link$1.extend({
26168
26388
  addCommands() {
26169
26389
  return {
26170
26390
  ...this.parent?.(),
26171
- setLinkText: ({ attributes, text } = {}) => ({ chain }) => {
26172
- return chain().setMark(this.name, { href: attributes?.href }).command(({ tr: tr2 }) => {
26173
- tr2.insertText(text);
26174
- return true;
26175
- }).setMeta("preventAutolink", true).run();
26391
+ setLinkText: ({ href, text } = { href: "", text: "" }) => ({ chain, state }) => {
26392
+ const { from: from2 } = state.selection;
26393
+ const to = from2 + text.length;
26394
+ return chain().insertContent(text).setTextSelection({ from: from2, to }).setMark(this.name, { href }).setMeta("preventAutolink", true).run();
26176
26395
  }
26177
26396
  };
26178
26397
  }
@@ -26200,6 +26419,8 @@ const Paragraph = Paragraph$1.extend({
26200
26419
  });
26201
26420
  const Tooltip = Mark2.create({
26202
26421
  name: "tooltip",
26422
+ keepOnSplit: false,
26423
+ exitable: true,
26203
26424
  addAttributes() {
26204
26425
  return {
26205
26426
  "data-tooltip": {
@@ -26223,11 +26444,10 @@ const Tooltip = Mark2.create({
26223
26444
  },
26224
26445
  addCommands() {
26225
26446
  return {
26226
- setTooltip: ({ tooltip, text } = {}) => ({ chain }) => {
26227
- return chain().setMark(this.name, { "data-tooltip": tooltip }).command(({ tr: tr2 }) => {
26228
- tr2.insertText(text);
26229
- return true;
26230
- }).run();
26447
+ setTooltip: ({ tooltip, text } = { tooltip: "", text: "" }) => ({ chain, state }) => {
26448
+ const { from: from2 } = state.selection;
26449
+ const to = from2 + text.length;
26450
+ return chain().insertContent(text).setTextSelection({ from: from2, to }).setMark(this.name, { "data-tooltip": tooltip }).run();
26231
26451
  },
26232
26452
  unsetTooltip: () => ({ chain }) => {
26233
26453
  return chain().unsetMark(this.name).run();
@@ -26236,6 +26456,7 @@ const Tooltip = Mark2.create({
26236
26456
  }
26237
26457
  });
26238
26458
  const extensions = [
26459
+ index_default,
26239
26460
  Color,
26240
26461
  FontFamily$1,
26241
26462
  FontSize$1,
@@ -27095,8 +27316,7 @@ const _sfc_main$b = /* @__PURE__ */ vue.defineComponent({
27095
27316
  if (!valid) return;
27096
27317
  const href = url.value.startsWith("http") ? url.value : `https://${url.value}`;
27097
27318
  if (href) {
27098
- const attributes = { href };
27099
- props.editor.chain().focus().setLinkText({ attributes, text: text.value }).run();
27319
+ props.editor.chain().focus().setLinkText({ href, text: text.value }).run();
27100
27320
  } else props.editor.chain().focus().unsetLink().run();
27101
27321
  show.value = false;
27102
27322
  form.value.resetValidation();
@@ -27219,7 +27439,7 @@ const _sfc_main$b = /* @__PURE__ */ vue.defineComponent({
27219
27439
  };
27220
27440
  }
27221
27441
  });
27222
- const AddLink = /* @__PURE__ */ _export_sfc(_sfc_main$b, [["__scopeId", "data-v-8c3b7b32"]]);
27442
+ const AddLink = /* @__PURE__ */ _export_sfc(_sfc_main$b, [["__scopeId", "data-v-426754d7"]]);
27223
27443
  const _hoisted_1$1 = { class: "text-body-2" };
27224
27444
  const INIT_SIZE = 5;
27225
27445
  const MAX_SIZE = 10;
@@ -28328,7 +28548,7 @@ const _sfc_main = /* @__PURE__ */ vue.defineComponent({
28328
28548
  }
28329
28549
  });
28330
28550
  const manifest = {
28331
- ...index_default,
28551
+ ...index_default$1,
28332
28552
  Edit,
28333
28553
  TopToolbar: _sfc_main
28334
28554
  };
package/dist/index.css CHANGED
@@ -179,7 +179,7 @@
179
179
  display: flex;
180
180
  flex-direction: column;
181
181
  gap: 0.75rem;
182
- }.v-sheet[data-v-8c3b7b32] {
182
+ }.v-sheet[data-v-426754d7] {
183
183
  display: flex;
184
184
  flex-direction: column;
185
185
  gap: 0.75rem;
package/dist/index.js CHANGED
@@ -42,7 +42,7 @@ var manifest$1 = {
42
42
  ui,
43
43
  ai
44
44
  };
45
- var index_default = manifest$1;
45
+ var index_default$1 = manifest$1;
46
46
  function OrderedMap(content) {
47
47
  this.content = content;
48
48
  }
@@ -2489,7 +2489,7 @@ function isTagRule(rule) {
2489
2489
  function isStyleRule(rule) {
2490
2490
  return rule.style != null;
2491
2491
  }
2492
- class DOMParser {
2492
+ let DOMParser$1 = class DOMParser2 {
2493
2493
  /**
2494
2494
  Create a parser that targets the given schema, using the given
2495
2495
  parsing rules.
@@ -2615,9 +2615,9 @@ class DOMParser {
2615
2615
  [priority](https://prosemirror.net/docs/ref/#model.ParseRule.priority).
2616
2616
  */
2617
2617
  static fromSchema(schema) {
2618
- return schema.cached.domParser || (schema.cached.domParser = new DOMParser(schema, DOMParser.schemaRules(schema)));
2618
+ return schema.cached.domParser || (schema.cached.domParser = new DOMParser2(schema, DOMParser2.schemaRules(schema)));
2619
2619
  }
2620
- }
2620
+ };
2621
2621
  const blockTags = {
2622
2622
  address: true,
2623
2623
  article: true,
@@ -8639,7 +8639,7 @@ function parseFromClipboard(view, text, html, plainText, $context) {
8639
8639
  dom = child;
8640
8640
  }
8641
8641
  if (!slice2) {
8642
- let parser = view.someProp("clipboardParser") || view.someProp("domParser") || DOMParser.fromSchema(view.state.schema);
8642
+ let parser = view.someProp("clipboardParser") || view.someProp("domParser") || DOMParser$1.fromSchema(view.state.schema);
8643
8643
  slice2 = parser.parseSlice(dom, {
8644
8644
  preserveWhitespace: !!(asText || sliceData),
8645
8645
  context: $context,
@@ -10449,7 +10449,7 @@ function parseBetween(view, from_, to_) {
10449
10449
  }
10450
10450
  }
10451
10451
  let startDoc = view.state.doc;
10452
- let parser = view.someProp("domParser") || DOMParser.fromSchema(view.state.schema);
10452
+ let parser = view.someProp("domParser") || DOMParser$1.fromSchema(view.state.schema);
10453
10453
  let $from = startDoc.resolve(from2);
10454
10454
  let sel = null, doc2 = parser.parse(parent, {
10455
10455
  topNode: $from.parent,
@@ -13772,15 +13772,15 @@ function createNodeFromContent(content, schema, options) {
13772
13772
  })
13773
13773
  });
13774
13774
  if (options.slice) {
13775
- DOMParser.fromSchema(contentCheckSchema).parseSlice(elementFromString(content), options.parseOptions);
13775
+ DOMParser$1.fromSchema(contentCheckSchema).parseSlice(elementFromString(content), options.parseOptions);
13776
13776
  } else {
13777
- DOMParser.fromSchema(contentCheckSchema).parse(elementFromString(content), options.parseOptions);
13777
+ DOMParser$1.fromSchema(contentCheckSchema).parse(elementFromString(content), options.parseOptions);
13778
13778
  }
13779
13779
  if (options.errorOnInvalidContent && hasInvalidContent) {
13780
13780
  throw new Error("[tiptap error]: Invalid HTML content", { cause: new Error(`Invalid element found: ${invalidContent}`) });
13781
13781
  }
13782
13782
  }
13783
- const parser = DOMParser.fromSchema(schema);
13783
+ const parser = DOMParser$1.fromSchema(schema);
13784
13784
  if (options.slice) {
13785
13785
  return parser.parseSlice(elementFromString(content), options.parseOptions).content;
13786
13786
  }
@@ -19838,6 +19838,226 @@ const Highlight = Mark2.create({
19838
19838
  ];
19839
19839
  }
19840
19840
  });
19841
+ function parseRomanNumber(roman) {
19842
+ roman = roman.toUpperCase();
19843
+ let value = 0;
19844
+ const values = { I: 1, V: 5, X: 10, L: 50, C: 100, D: 500, M: 1e3 };
19845
+ let i = roman.length;
19846
+ let lastVal = 0;
19847
+ while (i--) {
19848
+ if (values[roman.charAt(i)] >= lastVal) {
19849
+ value += values[roman.charAt(i)];
19850
+ } else {
19851
+ value -= values[roman.charAt(i)];
19852
+ }
19853
+ lastVal = values[roman.charAt(i)];
19854
+ }
19855
+ return value;
19856
+ }
19857
+ function parseLetterNumber(str) {
19858
+ const alphaVal = (s) => s.toLowerCase().charCodeAt(0) - 97 + 1;
19859
+ let value = 0;
19860
+ let i = str.length;
19861
+ while (i--) {
19862
+ const factor = Math.pow(26, str.length - i - 1);
19863
+ value += alphaVal(str.charAt(i)) * factor;
19864
+ }
19865
+ return value;
19866
+ }
19867
+ function unwrapNode(node) {
19868
+ const parent = node.parentNode;
19869
+ while (node.firstChild) {
19870
+ parent == null ? void 0 : parent.insertBefore(node.firstChild, node);
19871
+ }
19872
+ parent == null ? void 0 : parent.removeChild(node);
19873
+ }
19874
+ function parseStyleAttribute(el) {
19875
+ var _a;
19876
+ const styleRaw = ((_a = el == null ? void 0 : el.attributes[`style`]) == null ? void 0 : _a.value) || ``;
19877
+ return Object.fromEntries(styleRaw.split(`;`).map((line) => line.split(`:`).map((v) => v.trim())));
19878
+ }
19879
+ function transformMsoStyles(html) {
19880
+ html = html.replace(/<o:p>(.*?)<\/o:p>/g, ``);
19881
+ const parser = new DOMParser();
19882
+ const doc2 = parser.parseFromString(html, `text/html`);
19883
+ doc2.querySelectorAll(`[style*="mso-"]`).forEach((node) => {
19884
+ const styles = parseStyleAttribute(node);
19885
+ const newStyles = [];
19886
+ for (const prop of Object.keys(styles)) {
19887
+ if (prop && !prop.startsWith(`mso-`)) {
19888
+ newStyles.push(`${prop}: ${styles[prop]}`);
19889
+ }
19890
+ }
19891
+ node.setAttribute(`style`, newStyles.join(`;`));
19892
+ });
19893
+ doc2.querySelectorAll(`[style*="color: black"]`).forEach((node) => {
19894
+ node.style.removeProperty(`color`);
19895
+ });
19896
+ return doc2.documentElement.outerHTML;
19897
+ }
19898
+ function transformRemoveBookmarks(html) {
19899
+ const parser = new DOMParser();
19900
+ const doc2 = parser.parseFromString(html, `text/html`);
19901
+ const bookmarks = doc2.querySelectorAll(`[style*="mso-bookmark:"]`);
19902
+ bookmarks.forEach((node) => {
19903
+ const bookmark = parseStyleAttribute(node)[`mso-bookmark`];
19904
+ const bookmarkLink = doc2.querySelector(`a[name="${bookmark}"]`);
19905
+ if (bookmarkLink) {
19906
+ unwrapNode(bookmarkLink);
19907
+ }
19908
+ unwrapNode(node);
19909
+ });
19910
+ return doc2.documentElement.outerHTML;
19911
+ }
19912
+ function transformLists(html) {
19913
+ if (html.indexOf(`mso-list:`) === -1) {
19914
+ return html;
19915
+ }
19916
+ const parser = new DOMParser();
19917
+ const doc2 = parser.parseFromString(html, `text/html`);
19918
+ let listStack = [];
19919
+ let currentListId;
19920
+ const listElements = doc2.querySelectorAll(`p[style*="mso-list:"]`);
19921
+ listElements.forEach((node) => {
19922
+ const el = node;
19923
+ const [msoListId, msoListLevel] = parseMsoListAttribute(parseStyleAttribute(el)[`mso-list`]);
19924
+ if (currentListId !== msoListId && (hasNonListItemSibling(el) || msoListLevel === 1)) {
19925
+ currentListId = msoListId;
19926
+ listStack = [];
19927
+ }
19928
+ while (msoListLevel > listStack.length) {
19929
+ const newList = createListElement(el);
19930
+ if (listStack.length > 0) {
19931
+ listStack[listStack.length - 1].appendChild(newList);
19932
+ } else {
19933
+ el.before(newList);
19934
+ }
19935
+ listStack.push(newList);
19936
+ }
19937
+ while (msoListLevel < listStack.length) {
19938
+ listStack.pop();
19939
+ }
19940
+ listStack[listStack.length - 1].appendChild(getListItemFromParagraph(el));
19941
+ el.remove();
19942
+ });
19943
+ return doc2.documentElement.outerHTML;
19944
+ }
19945
+ function hasNonListItemSibling(el) {
19946
+ return !el.previousElementSibling || !(el.previousElementSibling.nodeName === `OL` || el.previousElementSibling.nodeName === `UL`);
19947
+ }
19948
+ function getListItemFromParagraph(el) {
19949
+ const li = document.createElement(`li`);
19950
+ li.innerHTML = el.innerHTML.replace(listTypeRegex, ``);
19951
+ return li;
19952
+ }
19953
+ function parseMsoListAttribute(attr) {
19954
+ var _a;
19955
+ const msoListValue = attr;
19956
+ const msoListInfos = msoListValue.split(` `);
19957
+ const msoListId = msoListInfos.find((e) => /l[0-9]+/.test(e)) || ``;
19958
+ const msoListLevel = +(((_a = msoListInfos.find((e) => e.startsWith(`level`))) == null ? void 0 : _a.substring(5)) || 1);
19959
+ return [msoListId, msoListLevel];
19960
+ }
19961
+ var listTypeRegex = /<!--\[if \!supportLists\]-->((.|\n)*)<!--\[endif\]-->/m;
19962
+ function getListPrefix(el) {
19963
+ var _a;
19964
+ const matches2 = el.innerHTML.match(listTypeRegex);
19965
+ if (matches2 == null ? void 0 : matches2.length) {
19966
+ const parser = new DOMParser();
19967
+ const doc2 = parser.parseFromString(matches2[0], `text/html`);
19968
+ return ((_a = doc2.body.querySelector(`span`)) == null ? void 0 : _a.textContent) || ``;
19969
+ }
19970
+ return ``;
19971
+ }
19972
+ function createListElement(el) {
19973
+ const listInfo = getListInfo(getListPrefix(el));
19974
+ const list = document.createElement(listInfo.type);
19975
+ if (listInfo.countType) {
19976
+ list.setAttribute(`type`, listInfo.countType);
19977
+ }
19978
+ if (listInfo.start > 1) {
19979
+ list.setAttribute(`start`, listInfo.start.toString());
19980
+ }
19981
+ return list;
19982
+ }
19983
+ var listOrderRegex = {
19984
+ number: /[0-9]+\./,
19985
+ romanLower: /(?=[mdclxvi])m*(c[md]|d?c*)(x[cl]|l?x*)(i[xv]|v?i*)\./,
19986
+ romanUpper: /(?=[MDCLXVI])M*(C[MD]|D?C*)(X[CL]|L?X*)(I[XV]|V?I*)\./,
19987
+ letterLower: /[a-z]+\./,
19988
+ letterUpper: /[A-Z]+\./
19989
+ };
19990
+ function getListInfo(prefix) {
19991
+ let type2 = `ul`;
19992
+ let countType = null;
19993
+ let start2 = 1;
19994
+ let matches2;
19995
+ if (matches2 = prefix.match(listOrderRegex.number)) {
19996
+ type2 = `ol`;
19997
+ start2 = +matches2[0].replace(`.`, ``);
19998
+ } else if (matches2 = prefix.match(listOrderRegex.romanLower)) {
19999
+ type2 = `ol`;
20000
+ countType = `i`;
20001
+ start2 = +parseRomanNumber(matches2[0].replace(`.`, ``));
20002
+ } else if (matches2 = prefix.match(listOrderRegex.romanUpper)) {
20003
+ type2 = `ol`;
20004
+ countType = `I`;
20005
+ start2 = +parseRomanNumber(matches2[0].replace(`.`, ``));
20006
+ } else if (matches2 = prefix.match(listOrderRegex.letterLower)) {
20007
+ type2 = `ol`;
20008
+ countType = `a`;
20009
+ start2 = +parseLetterNumber(matches2[0].replace(`.`, ``));
20010
+ } else if (matches2 = prefix.match(listOrderRegex.letterUpper)) {
20011
+ type2 = `ol`;
20012
+ countType = `A`;
20013
+ start2 = +parseLetterNumber(matches2[0].replace(`.`, ``));
20014
+ }
20015
+ return {
20016
+ type: type2,
20017
+ start: start2,
20018
+ countType
20019
+ };
20020
+ }
20021
+ function transformRemoveLineNumberWrapper(html) {
20022
+ const parser = new DOMParser();
20023
+ const doc2 = parser.parseFromString(html, `text/html`);
20024
+ const lineNumbers = doc2.querySelectorAll(`[class*="MsoLineNumber"]`);
20025
+ lineNumbers.forEach((node) => {
20026
+ unwrapNode(node);
20027
+ });
20028
+ return doc2.documentElement.outerHTML;
20029
+ }
20030
+ function transformMsoHtmlClasses(html) {
20031
+ const parser = new DOMParser();
20032
+ const doc2 = parser.parseFromString(html, `text/html`);
20033
+ doc2.querySelectorAll(`p[class*="MsoNormal"]`).forEach((node) => {
20034
+ node.classList.remove(`MsoNormal`);
20035
+ });
20036
+ return doc2.documentElement.outerHTML;
20037
+ }
20038
+ var OfficePaste = Extension.create({
20039
+ priority: 99999,
20040
+ name: `office-paste`,
20041
+ addProseMirrorPlugins() {
20042
+ return [OfficePastePlugin];
20043
+ }
20044
+ });
20045
+ var OfficePastePlugin = new Plugin({
20046
+ key: new PluginKey("office-paste"),
20047
+ props: {
20048
+ transformPastedHTML(html) {
20049
+ if (html.indexOf(`microsoft-com`) !== -1 && html.indexOf(`office`) !== -1) {
20050
+ html = transformLists(html);
20051
+ html = transformRemoveBookmarks(html);
20052
+ html = transformMsoStyles(html);
20053
+ html = transformMsoHtmlClasses(html);
20054
+ html = transformRemoveLineNumberWrapper(html);
20055
+ }
20056
+ return html;
20057
+ }
20058
+ }
20059
+ });
20060
+ var index_default = OfficePaste;
19841
20061
  const Placeholder = Extension.create({
19842
20062
  name: "placeholder",
19843
20063
  addOptions() {
@@ -26166,11 +26386,10 @@ const Link = Link$1.extend({
26166
26386
  addCommands() {
26167
26387
  return {
26168
26388
  ...this.parent?.(),
26169
- setLinkText: ({ attributes, text } = {}) => ({ chain }) => {
26170
- return chain().setMark(this.name, { href: attributes?.href }).command(({ tr: tr2 }) => {
26171
- tr2.insertText(text);
26172
- return true;
26173
- }).setMeta("preventAutolink", true).run();
26389
+ setLinkText: ({ href, text } = { href: "", text: "" }) => ({ chain, state }) => {
26390
+ const { from: from2 } = state.selection;
26391
+ const to = from2 + text.length;
26392
+ return chain().insertContent(text).setTextSelection({ from: from2, to }).setMark(this.name, { href }).setMeta("preventAutolink", true).run();
26174
26393
  }
26175
26394
  };
26176
26395
  }
@@ -26198,6 +26417,8 @@ const Paragraph = Paragraph$1.extend({
26198
26417
  });
26199
26418
  const Tooltip = Mark2.create({
26200
26419
  name: "tooltip",
26420
+ keepOnSplit: false,
26421
+ exitable: true,
26201
26422
  addAttributes() {
26202
26423
  return {
26203
26424
  "data-tooltip": {
@@ -26221,11 +26442,10 @@ const Tooltip = Mark2.create({
26221
26442
  },
26222
26443
  addCommands() {
26223
26444
  return {
26224
- setTooltip: ({ tooltip, text } = {}) => ({ chain }) => {
26225
- return chain().setMark(this.name, { "data-tooltip": tooltip }).command(({ tr: tr2 }) => {
26226
- tr2.insertText(text);
26227
- return true;
26228
- }).run();
26445
+ setTooltip: ({ tooltip, text } = { tooltip: "", text: "" }) => ({ chain, state }) => {
26446
+ const { from: from2 } = state.selection;
26447
+ const to = from2 + text.length;
26448
+ return chain().insertContent(text).setTextSelection({ from: from2, to }).setMark(this.name, { "data-tooltip": tooltip }).run();
26229
26449
  },
26230
26450
  unsetTooltip: () => ({ chain }) => {
26231
26451
  return chain().unsetMark(this.name).run();
@@ -26234,6 +26454,7 @@ const Tooltip = Mark2.create({
26234
26454
  }
26235
26455
  });
26236
26456
  const extensions = [
26457
+ index_default,
26237
26458
  Color,
26238
26459
  FontFamily$1,
26239
26460
  FontSize$1,
@@ -27093,8 +27314,7 @@ const _sfc_main$b = /* @__PURE__ */ defineComponent({
27093
27314
  if (!valid) return;
27094
27315
  const href = url.value.startsWith("http") ? url.value : `https://${url.value}`;
27095
27316
  if (href) {
27096
- const attributes = { href };
27097
- props.editor.chain().focus().setLinkText({ attributes, text: text.value }).run();
27317
+ props.editor.chain().focus().setLinkText({ href, text: text.value }).run();
27098
27318
  } else props.editor.chain().focus().unsetLink().run();
27099
27319
  show.value = false;
27100
27320
  form.value.resetValidation();
@@ -27217,7 +27437,7 @@ const _sfc_main$b = /* @__PURE__ */ defineComponent({
27217
27437
  };
27218
27438
  }
27219
27439
  });
27220
- const AddLink = /* @__PURE__ */ _export_sfc(_sfc_main$b, [["__scopeId", "data-v-8c3b7b32"]]);
27440
+ const AddLink = /* @__PURE__ */ _export_sfc(_sfc_main$b, [["__scopeId", "data-v-426754d7"]]);
27221
27441
  const _hoisted_1$1 = { class: "text-body-2" };
27222
27442
  const INIT_SIZE = 5;
27223
27443
  const MAX_SIZE = 10;
@@ -28326,7 +28546,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
28326
28546
  }
28327
28547
  });
28328
28548
  const manifest = {
28329
- ...index_default,
28549
+ ...index_default$1,
28330
28550
  Edit,
28331
28551
  TopToolbar: _sfc_main
28332
28552
  };
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "description": "Tailor CMS HTML editor authoring component",
4
4
  "author": "Studion <info@gostudion.com> (https://github.com/tailor-cms)",
5
5
  "type": "module",
6
- "version": "0.1.2",
6
+ "version": "0.1.4",
7
7
  "exports": {
8
8
  ".": {
9
9
  "import": "./dist/index.js",
@@ -26,9 +26,10 @@
26
26
  "typescript": "^5.8.3",
27
27
  "vite": "^7.0.3",
28
28
  "vue-tsc": "^3.0.1",
29
- "@tailor-cms/ce-html-manifest": "0.1.2"
29
+ "@tailor-cms/ce-html-manifest": "0.1.4"
30
30
  },
31
31
  "dependencies": {
32
+ "@intevation/tiptap-extension-office-paste": "^0.1.2",
32
33
  "@tiptap/extension-color": "^2.25.0",
33
34
  "@tiptap/extension-font-family": "^2.25.0",
34
35
  "@tiptap/extension-highlight": "^2.25.0",