payload-richtext-tiptap 0.0.159 → 0.0.161

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.
Files changed (89) hide show
  1. package/dist/src/fields/TiptapEditor/extensions/Iframe/IframeEmbed.d.ts +2 -7
  2. package/dist/src/fields/TiptapEditor/extensions/Iframe/IframeEmbed.d.ts.map +1 -1
  3. package/dist/src/fields/TiptapEditor/extensions/Iframe/IframeEmbed.js +20 -7
  4. package/dist/src/fields/TiptapEditor/extensions/Iframe/IframeEmbed.js.map +1 -1
  5. package/dist/src/fields/TiptapEditor/extensions/Iframe/iframe.d.ts +2 -2
  6. package/dist/src/fields/TiptapEditor/extensions/Iframe/iframe.d.ts.map +1 -1
  7. package/dist/src/fields/TiptapEditor/extensions/Iframe/iframe.js +42 -30
  8. package/dist/src/fields/TiptapEditor/extensions/Iframe/iframe.js.map +1 -1
  9. package/dist/src/fields/TiptapEditor/extensions/Paragraph/Paragraph.d.ts.map +1 -1
  10. package/dist/src/fields/TiptapEditor/extensions/Paragraph/Paragraph.js +27 -4
  11. package/dist/src/fields/TiptapEditor/extensions/Paragraph/Paragraph.js.map +1 -1
  12. package/dist/src/fields/TiptapEditor/extensions/PasteHandler/PasteHandler.d.ts +4 -0
  13. package/dist/src/fields/TiptapEditor/extensions/PasteHandler/PasteHandler.d.ts.map +1 -0
  14. package/dist/src/fields/TiptapEditor/extensions/PasteHandler/PasteHandler.js +242 -0
  15. package/dist/src/fields/TiptapEditor/extensions/PasteHandler/PasteHandler.js.map +1 -0
  16. package/dist/src/fields/TiptapEditor/extensions/PasteHandler/index.d.ts +2 -0
  17. package/dist/src/fields/TiptapEditor/extensions/PasteHandler/index.d.ts.map +1 -0
  18. package/dist/src/fields/TiptapEditor/extensions/PasteHandler/index.js +3 -0
  19. package/dist/src/fields/TiptapEditor/extensions/PasteHandler/index.js.map +1 -0
  20. package/dist/src/fields/TiptapEditor/extensions/SlashCommand/groups.d.ts +1 -1
  21. package/dist/src/fields/TiptapEditor/extensions/SlashCommand/groups.d.ts.map +1 -1
  22. package/dist/src/fields/TiptapEditor/extensions/SlashCommand/groups.js +108 -84
  23. package/dist/src/fields/TiptapEditor/extensions/SlashCommand/groups.js.map +1 -1
  24. package/dist/src/fields/TiptapEditor/extensions/Table/Table.d.ts.map +1 -1
  25. package/dist/src/fields/TiptapEditor/extensions/Table/Table.js +2 -1
  26. package/dist/src/fields/TiptapEditor/extensions/Table/Table.js.map +1 -1
  27. package/dist/src/fields/TiptapEditor/extensions/extension-kit.d.ts +3 -3
  28. package/dist/src/fields/TiptapEditor/extensions/extension-kit.d.ts.map +1 -1
  29. package/dist/src/fields/TiptapEditor/extensions/extension-kit.js +29 -22
  30. package/dist/src/fields/TiptapEditor/extensions/extension-kit.js.map +1 -1
  31. package/dist/src/fields/TiptapEditor/extensions/index.d.ts +50 -49
  32. package/dist/src/fields/TiptapEditor/extensions/index.d.ts.map +1 -1
  33. package/dist/src/fields/TiptapEditor/extensions/index.js +50 -49
  34. package/dist/src/fields/TiptapEditor/extensions/index.js.map +1 -1
  35. package/dist/src/fields/TiptapEditor/extensions/serverside/IFrameServerside.d.ts +2 -2
  36. package/dist/src/fields/TiptapEditor/extensions/serverside/IFrameServerside.d.ts.map +1 -1
  37. package/dist/src/fields/TiptapEditor/extensions/serverside/IFrameServerside.js +26 -8
  38. package/dist/src/fields/TiptapEditor/extensions/serverside/IFrameServerside.js.map +1 -1
  39. package/dist/src/fields/TiptapEditor/extensions/serverside/TableServerside.d.ts +10 -0
  40. package/dist/src/fields/TiptapEditor/extensions/serverside/TableServerside.d.ts.map +1 -0
  41. package/dist/src/fields/TiptapEditor/extensions/serverside/TableServerside.js +90 -0
  42. package/dist/src/fields/TiptapEditor/extensions/serverside/TableServerside.js.map +1 -0
  43. package/dist/src/fields/TiptapEditor/extensions/serverside/index.d.ts +15 -13
  44. package/dist/src/fields/TiptapEditor/extensions/serverside/index.d.ts.map +1 -1
  45. package/dist/src/fields/TiptapEditor/extensions/serverside/index.js +15 -13
  46. package/dist/src/fields/TiptapEditor/extensions/serverside/index.js.map +1 -1
  47. package/dist/src/fields/TiptapEditor/features/BlockEditor/BlockEditor.d.ts.map +1 -1
  48. package/dist/src/fields/TiptapEditor/features/BlockEditor/BlockEditor.js +9 -0
  49. package/dist/src/fields/TiptapEditor/features/BlockEditor/BlockEditor.js.map +1 -1
  50. package/dist/src/fields/TiptapEditor/features/panels/IframeLinkEditorPanel/IframeLinkEditorPanel.d.ts +2 -2
  51. package/dist/src/fields/TiptapEditor/features/panels/IframeLinkEditorPanel/IframeLinkEditorPanel.d.ts.map +1 -1
  52. package/dist/src/fields/TiptapEditor/features/panels/IframeLinkEditorPanel/IframeLinkEditorPanel.js +20 -18
  53. package/dist/src/fields/TiptapEditor/features/panels/IframeLinkEditorPanel/IframeLinkEditorPanel.js.map +1 -1
  54. package/dist/src/fields/TiptapEditor/features/ui/SlashCommand/SlashCommandTriggerButton.d.ts +4 -0
  55. package/dist/src/fields/TiptapEditor/features/ui/SlashCommand/SlashCommandTriggerButton.d.ts.map +1 -0
  56. package/dist/src/fields/TiptapEditor/features/ui/SlashCommand/SlashCommandTriggerButton.js +32 -0
  57. package/dist/src/fields/TiptapEditor/features/ui/SlashCommand/SlashCommandTriggerButton.js.map +1 -0
  58. package/dist/src/fields/TiptapEditor/features/ui/SlashCommand/SlashDropdownMenu.d.ts +4 -0
  59. package/dist/src/fields/TiptapEditor/features/ui/SlashCommand/SlashDropdownMenu.d.ts.map +1 -0
  60. package/dist/src/fields/TiptapEditor/features/ui/SlashCommand/SlashDropdownMenu.js +70 -0
  61. package/dist/src/fields/TiptapEditor/features/ui/SlashCommand/SlashDropdownMenu.js.map +1 -0
  62. package/dist/src/fields/TiptapEditor/features/ui/SlashCommand/SlashMenuList.d.ts +10 -0
  63. package/dist/src/fields/TiptapEditor/features/ui/SlashCommand/SlashMenuList.d.ts.map +1 -0
  64. package/dist/src/fields/TiptapEditor/features/ui/SlashCommand/SlashMenuList.js +249 -0
  65. package/dist/src/fields/TiptapEditor/features/ui/SlashCommand/SlashMenuList.js.map +1 -0
  66. package/dist/src/fields/TiptapEditor/features/ui/SlashCommand/SuggestionMenu.d.ts +15 -0
  67. package/dist/src/fields/TiptapEditor/features/ui/SlashCommand/SuggestionMenu.d.ts.map +1 -0
  68. package/dist/src/fields/TiptapEditor/features/ui/SlashCommand/SuggestionMenu.js +291 -0
  69. package/dist/src/fields/TiptapEditor/features/ui/SlashCommand/SuggestionMenu.js.map +1 -0
  70. package/dist/src/fields/TiptapEditor/features/ui/SlashCommand/index.d.ts +7 -0
  71. package/dist/src/fields/TiptapEditor/features/ui/SlashCommand/index.d.ts.map +1 -0
  72. package/dist/src/fields/TiptapEditor/features/ui/SlashCommand/index.js +7 -0
  73. package/dist/src/fields/TiptapEditor/features/ui/SlashCommand/index.js.map +1 -0
  74. package/dist/src/fields/TiptapEditor/features/ui/SlashCommand/types.d.ts +28 -0
  75. package/dist/src/fields/TiptapEditor/features/ui/SlashCommand/types.d.ts.map +1 -0
  76. package/dist/src/fields/TiptapEditor/features/ui/SlashCommand/types.js +3 -0
  77. package/dist/src/fields/TiptapEditor/features/ui/SlashCommand/types.js.map +1 -0
  78. package/dist/src/fields/TiptapEditor/features/ui/SlashCommand/utils.d.ts +6 -0
  79. package/dist/src/fields/TiptapEditor/features/ui/SlashCommand/utils.d.ts.map +1 -0
  80. package/dist/src/fields/TiptapEditor/features/ui/SlashCommand/utils.js +222 -0
  81. package/dist/src/fields/TiptapEditor/features/ui/SlashCommand/utils.js.map +1 -0
  82. package/dist/src/fields/TiptapEditor/lib/utils/updateImageUrl.d.ts +2 -0
  83. package/dist/src/fields/TiptapEditor/lib/utils/updateImageUrl.d.ts.map +1 -0
  84. package/dist/src/fields/TiptapEditor/lib/utils/updateImageUrl.js +17 -0
  85. package/dist/src/fields/TiptapEditor/lib/utils/updateImageUrl.js.map +1 -0
  86. package/dist/src/mobile.css +1 -1
  87. package/dist/src/styles.css +1 -1
  88. package/dist/tsconfig.tsbuildinfo +1 -1
  89. package/package.json +1 -1
@@ -1,9 +1,4 @@
1
- declare const _default: (props: {
2
- node: {
3
- attrs: {
4
- src?: string;
5
- };
6
- };
7
- }) => import("react").JSX.Element;
1
+ import { NodeViewProps } from '@tiptap/react';
2
+ declare const _default: (props: NodeViewProps) => import("react").JSX.Element;
8
3
  export default _default;
9
4
  //# sourceMappingURL=IframeEmbed.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"IframeEmbed.d.ts","sourceRoot":"","sources":["../../../../../../src/fields/TiptapEditor/extensions/Iframe/IframeEmbed.tsx"],"names":[],"mappings":"gCAGuB;IAAE,IAAI,EAAE;QAAE,KAAK,EAAE;YAAE,GAAG,CAAC,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAA;CAAE;AAA5D,wBAQE"}
1
+ {"version":3,"file":"IframeEmbed.d.ts","sourceRoot":"","sources":["../../../../../../src/fields/TiptapEditor/extensions/Iframe/IframeEmbed.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;gCAEtB,aAAa;AAApC,wBA4BC"}
@@ -1,16 +1,29 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import { Link } from "lucide-react";
3
- import SocialMediaEmbed from "../SocialMedia/SocialMediaEmbed.js";
2
+ import { Code } from 'lucide-react';
3
+ import SocialMediaEmbed from '../SocialMedia/SocialMediaEmbed.js';
4
+ import i18next from 'i18next';
4
5
  export default ((props)=>{
6
+ const { src, width = '100%', height = '400', title } = props?.node?.attrs ?? {};
5
7
  return /*#__PURE__*/ _jsx(SocialMediaEmbed, {
6
8
  props: props,
7
- Icon: Link,
8
- text: "Embed an Iframe",
9
+ Icon: Code,
10
+ text: i18next.t('embedIframe') || 'Embed an Iframe (Flourish, Datawrapper, etc.)',
9
11
  children: /*#__PURE__*/ _jsx("div", {
10
- className: "iframe-wrapper",
12
+ className: "iframe-wrapper w-full",
11
13
  children: /*#__PURE__*/ _jsx("iframe", {
12
- src: props?.node?.attrs?.src ?? "",
13
- allowFullScreen: true
14
+ src: src ?? '',
15
+ width: width,
16
+ height: height,
17
+ title: title ?? 'Embedded content',
18
+ allowFullScreen: true,
19
+ loading: "lazy",
20
+ sandbox: "allow-scripts allow-same-origin allow-forms allow-popups allow-presentation",
21
+ referrerPolicy: "no-referrer-when-downgrade",
22
+ style: {
23
+ border: 'none',
24
+ width: '100%',
25
+ minHeight: '300px'
26
+ }
14
27
  })
15
28
  })
16
29
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../src/fields/TiptapEditor/extensions/Iframe/IframeEmbed.tsx"],"sourcesContent":["import { Link } from \"lucide-react\";\r\nimport SocialMediaEmbed from \"../SocialMedia/SocialMediaEmbed.js\";\r\n\r\nexport default (props: { node: { attrs: { src?: string } } }) => {\r\n return (\r\n <SocialMediaEmbed props={props} Icon={Link} text={\"Embed an Iframe\"}>\r\n <div className=\"iframe-wrapper\">\r\n <iframe src={props?.node?.attrs?.src ?? \"\"} allowFullScreen={true} />\r\n </div>\r\n </SocialMediaEmbed>\r\n );\r\n};\r\n"],"names":["Link","SocialMediaEmbed","props","Icon","text","div","className","iframe","src","node","attrs","allowFullScreen"],"mappings":";AAAA,SAASA,IAAI,QAAQ,eAAe;AACpC,OAAOC,sBAAsB,qCAAqC;AAElE,eAAe,CAAA,CAACC;IACd,qBACE,KAACD;QAAiBC,OAAOA;QAAOC,MAAMH;QAAMI,MAAM;kBAChD,cAAA,KAACC;YAAIC,WAAU;sBACb,cAAA,KAACC;gBAAOC,KAAKN,OAAOO,MAAMC,OAAOF,OAAO;gBAAIG,iBAAiB;;;;AAIrE,CAAA,EAAE"}
1
+ {"version":3,"sources":["../../../../../../src/fields/TiptapEditor/extensions/Iframe/IframeEmbed.tsx"],"sourcesContent":["import { Code } from 'lucide-react'\r\nimport SocialMediaEmbed from '../SocialMedia/SocialMediaEmbed.js'\r\nimport i18next from 'i18next'\r\nimport { NodeViewProps } from '@tiptap/react'\r\n\r\nexport default (props: NodeViewProps) => {\r\n const { src, width = '100%', height = '400', title } = props?.node?.attrs ?? {}\r\n\r\n return (\r\n <SocialMediaEmbed\r\n props={props}\r\n Icon={Code}\r\n text={i18next.t('embedIframe') || 'Embed an Iframe (Flourish, Datawrapper, etc.)'}\r\n >\r\n <div className=\"iframe-wrapper w-full\">\r\n <iframe\r\n src={src ?? ''}\r\n width={width}\r\n height={height}\r\n title={title ?? 'Embedded content'}\r\n allowFullScreen\r\n loading=\"lazy\"\r\n sandbox=\"allow-scripts allow-same-origin allow-forms allow-popups allow-presentation\"\r\n referrerPolicy=\"no-referrer-when-downgrade\"\r\n style={{\r\n border: 'none',\r\n width: '100%',\r\n minHeight: '300px',\r\n }}\r\n />\r\n </div>\r\n </SocialMediaEmbed>\r\n )\r\n}\r\n"],"names":["Code","SocialMediaEmbed","i18next","props","src","width","height","title","node","attrs","Icon","text","t","div","className","iframe","allowFullScreen","loading","sandbox","referrerPolicy","style","border","minHeight"],"mappings":";AAAA,SAASA,IAAI,QAAQ,eAAc;AACnC,OAAOC,sBAAsB,qCAAoC;AACjE,OAAOC,aAAa,UAAS;AAG7B,eAAe,CAAA,CAACC;IACd,MAAM,EAAEC,GAAG,EAAEC,QAAQ,MAAM,EAAEC,SAAS,KAAK,EAAEC,KAAK,EAAE,GAAGJ,OAAOK,MAAMC,SAAS,CAAC;IAE9E,qBACE,KAACR;QACCE,OAAOA;QACPO,MAAMV;QACNW,MAAMT,QAAQU,CAAC,CAAC,kBAAkB;kBAElC,cAAA,KAACC;YAAIC,WAAU;sBACb,cAAA,KAACC;gBACCX,KAAKA,OAAO;gBACZC,OAAOA;gBACPC,QAAQA;gBACRC,OAAOA,SAAS;gBAChBS,eAAe;gBACfC,SAAQ;gBACRC,SAAQ;gBACRC,gBAAe;gBACfC,OAAO;oBACLC,QAAQ;oBACRhB,OAAO;oBACPiB,WAAW;gBACb;;;;AAKV,CAAA,EAAC"}
@@ -1,11 +1,11 @@
1
- import { Node } from "@tiptap/core";
1
+ import { Node } from '@tiptap/core';
2
2
  export interface IframeOptions {
3
3
  allowFullscreen: boolean;
4
4
  HTMLAttributes: {
5
5
  [key: string]: any;
6
6
  };
7
7
  }
8
- declare module "@tiptap/core" {
8
+ declare module '@tiptap/core' {
9
9
  interface Commands<ReturnType> {
10
10
  iframe: {
11
11
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"iframe.d.ts","sourceRoot":"","sources":["../../../../../../src/fields/TiptapEditor/extensions/Iframe/iframe.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,IAAI,EAAE,MAAM,cAAc,CAAC;AAIrD,MAAM,WAAW,aAAa;IAC5B,eAAe,EAAE,OAAO,CAAC;IACzB,cAAc,EAAE;QACd,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;KACpB,CAAC;CACH;AAED,OAAO,QAAQ,cAAc,CAAC;IAC5B,UAAU,QAAQ,CAAC,UAAU;QAC3B,MAAM,EAAE;YACN;;eAEG;YACH,SAAS,EAAE,CAAC,OAAO,CAAC,EAAE;gBAAE,GAAG,EAAE,MAAM,CAAA;aAAE,KAAK,UAAU,CAAC;YACrD,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,UAAU,CAAC;YACvC,YAAY,EAAE,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,KAAK,UAAU,CAAC;SAChE,CAAC;KACH;CACF;AAED,eAAO,MAAM,MAAM,0BAqKjB,CAAC"}
1
+ {"version":3,"file":"iframe.d.ts","sourceRoot":"","sources":["../../../../../../src/fields/TiptapEditor/extensions/Iframe/iframe.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,IAAI,EAAE,MAAM,cAAc,CAAA;AAIpD,MAAM,WAAW,aAAa;IAC5B,eAAe,EAAE,OAAO,CAAA;IACxB,cAAc,EAAE;QACd,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;KACnB,CAAA;CACF;AAED,OAAO,QAAQ,cAAc,CAAC;IAC5B,UAAU,QAAQ,CAAC,UAAU;QAC3B,MAAM,EAAE;YACN;;eAEG;YACH,SAAS,EAAE,CAAC,OAAO,CAAC,EAAE;gBAAE,GAAG,EAAE,MAAM,CAAA;aAAE,KAAK,UAAU,CAAA;YACpD,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,UAAU,CAAA;YACtC,YAAY,EAAE,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,KAAK,UAAU,CAAA;SAC/D,CAAA;KACF;CACF;AAED,eAAO,MAAM,MAAM,0BAqKjB,CAAA"}
@@ -1,18 +1,18 @@
1
- import { mergeAttributes, Node } from "@tiptap/core";
2
- import { ReactNodeViewRenderer } from "@tiptap/react";
3
- import IframeEmbed from "./IframeEmbed.js";
1
+ import { mergeAttributes, Node } from '@tiptap/core';
2
+ import { ReactNodeViewRenderer } from '@tiptap/react';
3
+ import IframeEmbed from './IframeEmbed.js';
4
4
  export const Iframe = Node.create({
5
- name: "iframe",
5
+ name: 'iframe',
6
6
  inline: false,
7
- group: "block",
8
- content: "inline*",
7
+ group: 'block',
8
+ content: 'inline*',
9
9
  draggable: true,
10
10
  atom: true,
11
- addOption () {
11
+ addOptions () {
12
12
  return {
13
13
  allowFullscreen: true,
14
14
  HTMLAttributes: {
15
- class: "iframe-wrapper"
15
+ class: 'iframe-wrapper'
16
16
  }
17
17
  };
18
18
  },
@@ -29,23 +29,35 @@ export const Iframe = Node.create({
29
29
  parseHTML: ()=>this.options.allowFullscreen
30
30
  },
31
31
  sandbox: {
32
- default: "allow-forms allow-modals"
32
+ default: 'allow-scripts allow-same-origin allow-forms allow-popups allow-presentation'
33
33
  },
34
34
  referrerpolicy: {
35
- default: "no-referrer"
35
+ default: 'no-referrer-when-downgrade'
36
+ },
37
+ width: {
38
+ default: '100%'
39
+ },
40
+ height: {
41
+ default: 'auto'
42
+ },
43
+ title: {
44
+ default: null
45
+ },
46
+ loading: {
47
+ default: 'lazy'
36
48
  }
37
49
  };
38
50
  },
39
51
  renderHTML ({ HTMLAttributes }) {
40
52
  return [
41
- "iframe",
53
+ 'iframe',
42
54
  mergeAttributes(this.options.HTMLAttributes, HTMLAttributes)
43
55
  ];
44
56
  },
45
57
  parseHTML () {
46
58
  return [
47
59
  {
48
- tag: "iframe"
60
+ tag: 'iframe'
49
61
  }
50
62
  ];
51
63
  },
@@ -59,15 +71,15 @@ export const Iframe = Node.create({
59
71
  let attributes = {
60
72
  ...options
61
73
  };
62
- if (options?.src?.includes("iframe")) {
74
+ if (options?.src?.includes('iframe')) {
63
75
  const parser = new DOMParser();
64
- const html = parser.parseFromString(options?.src, "text/html");
65
- const attrNames = html.getElementsByTagName("iframe")?.[0]?.getAttributeNames();
76
+ const html = parser.parseFromString(options?.src, 'text/html');
77
+ const attrNames = html.getElementsByTagName('iframe')?.[0]?.getAttributeNames();
66
78
  attrNames?.forEach((attr)=>{
67
- attributes[attr] = html.getElementsByTagName("iframe")?.[0]?.getAttribute(attr);
79
+ attributes[attr] = html.getElementsByTagName('iframe')?.[0]?.getAttribute(attr);
68
80
  });
69
81
  } else if (!isValidHttpUrl(options?.src)) {
70
- const htmlData = "data:text/html;charset=utf-8," + encodeURI(options?.src);
82
+ const htmlData = 'data:text/html;charset=utf-8,' + encodeURI(options?.src);
71
83
  attributes = {
72
84
  ...attributes,
73
85
  src: htmlData
@@ -88,34 +100,34 @@ export const Iframe = Node.create({
88
100
  let attributes = {
89
101
  editorValue: value
90
102
  };
91
- if (value?.includes("youtube.com")) {
92
- const ytValue = value?.split("v=")?.[1]?.split("&")?.[0];
103
+ if (value?.includes('youtube.com')) {
104
+ const ytValue = value?.split('v=')?.[1]?.split('&')?.[0];
93
105
  attributes = {
94
106
  ...attributes,
95
107
  src: `https://www.youtube.com/embed/${ytValue}?controls=0`,
96
- title: "YouTube video player"
108
+ title: 'YouTube video player'
97
109
  };
98
- } else if (value?.includes("instagram.com")) {
99
- const instagramValue = value?.split("p/")?.[1]?.split("/")?.[0];
110
+ } else if (value?.includes('instagram.com')) {
111
+ const instagramValue = value?.split('p/')?.[1]?.split('/')?.[0];
100
112
  attributes = {
101
113
  ...attributes,
102
114
  src: `https://www.instagram.com/p/${instagramValue}/embed`,
103
- title: "Instagram"
115
+ title: 'Instagram'
104
116
  };
105
117
  } else if (isValidHttpUrl(value)) {
106
118
  attributes = {
107
119
  ...attributes,
108
120
  src: value
109
121
  };
110
- } else if (value?.includes("iframe")) {
122
+ } else if (value?.includes('iframe')) {
111
123
  const parser = new DOMParser();
112
- const html = parser.parseFromString(value, "text/html");
113
- const attrNames = html.getElementsByTagName("iframe")?.[0]?.getAttributeNames();
124
+ const html = parser.parseFromString(value, 'text/html');
125
+ const attrNames = html.getElementsByTagName('iframe')?.[0]?.getAttributeNames();
114
126
  attrNames?.forEach((attr)=>{
115
- attributes[attr] = html.getElementsByTagName("iframe")?.[0]?.getAttribute(attr);
127
+ attributes[attr] = html.getElementsByTagName('iframe')?.[0]?.getAttribute(attr);
116
128
  });
117
129
  } else {
118
- const htmlData = "data:text/html;charset=utf-8," + encodeURI(value);
130
+ const htmlData = 'data:text/html;charset=utf-8,' + encodeURI(value);
119
131
  attributes = {
120
132
  ...attributes,
121
133
  src: htmlData
@@ -125,7 +137,7 @@ export const Iframe = Node.create({
125
137
  },
126
138
  insertIframe: (src, className)=>({ commands, state })=>{
127
139
  return commands.insertContent({
128
- type: "iframe",
140
+ type: 'iframe',
129
141
  attrs: {
130
142
  src,
131
143
  class: className
@@ -142,7 +154,7 @@ function isValidHttpUrl(string) {
142
154
  } catch (_) {
143
155
  return false;
144
156
  }
145
- return url.protocol === "http:" || url.protocol === "https:";
157
+ return url.protocol === 'http:' || url.protocol === 'https:';
146
158
  }
147
159
 
148
160
  //# sourceMappingURL=iframe.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../src/fields/TiptapEditor/extensions/Iframe/iframe.ts"],"sourcesContent":["import { mergeAttributes, Node } from \"@tiptap/core\";\r\nimport { ReactNodeViewRenderer } from \"@tiptap/react\";\r\nimport IframeEmbed from \"./IframeEmbed.js\";\r\n\r\nexport interface IframeOptions {\r\n allowFullscreen: boolean;\r\n HTMLAttributes: {\r\n [key: string]: any;\r\n };\r\n}\r\n\r\ndeclare module \"@tiptap/core\" {\r\n interface Commands<ReturnType> {\r\n iframe: {\r\n /**\r\n * Add an iframe\r\n */\r\n setIframe: (options?: { src: string }) => ReturnType;\r\n setHtml: (value: string) => ReturnType;\r\n insertIframe: (src?: string, className?: string) => ReturnType;\r\n };\r\n }\r\n}\r\n\r\nexport const Iframe = Node.create<IframeOptions>({\r\n name: \"iframe\",\r\n inline: false,\r\n group: \"block\",\r\n content: \"inline*\",\r\n draggable: true,\r\n\r\n atom: true,\r\n\r\n addOption() {\r\n return {\r\n allowFullscreen: true,\r\n HTMLAttributes: {\r\n class: \"iframe-wrapper\",\r\n },\r\n };\r\n },\r\n\r\n addAttributes() {\r\n return {\r\n src: {\r\n default: null,\r\n },\r\n frameborder: {\r\n default: 0,\r\n },\r\n allowfullscreen: {\r\n default: this.options.allowFullscreen,\r\n parseHTML: () => this.options.allowFullscreen,\r\n },\r\n sandbox: {\r\n default: \"allow-forms allow-modals\",\r\n },\r\n referrerpolicy: {\r\n default: \"no-referrer\"\r\n }\r\n };\r\n },\r\n renderHTML({ HTMLAttributes }) {\r\n return [\r\n \"iframe\",\r\n mergeAttributes(this.options.HTMLAttributes, HTMLAttributes),\r\n ];\r\n },\r\n parseHTML() {\r\n return [\r\n {\r\n tag: \"iframe\",\r\n },\r\n ];\r\n },\r\n\r\n addNodeView() {\r\n return ReactNodeViewRenderer(IframeEmbed);\r\n },\r\n\r\n addCommands() {\r\n return {\r\n setIframe:\r\n (options: { src: string }) =>\r\n ({ tr, dispatch }) => {\r\n const { selection } = tr;\r\n let attributes: Record<string, any> = {\r\n ...options,\r\n };\r\n\r\n if (options?.src?.includes(\"iframe\")) {\r\n const parser = new DOMParser();\r\n const html = parser.parseFromString(options?.src, \"text/html\");\r\n const attrNames = html\r\n .getElementsByTagName(\"iframe\")?.[0]\r\n ?.getAttributeNames();\r\n\r\n attrNames?.forEach((attr) => {\r\n attributes[attr] = html\r\n .getElementsByTagName(\"iframe\")?.[0]\r\n ?.getAttribute(attr);\r\n });\r\n } else if (!isValidHttpUrl(options?.src)) {\r\n const htmlData =\r\n \"data:text/html;charset=utf-8,\" + encodeURI(options?.src);\r\n attributes = {\r\n ...attributes,\r\n src: htmlData,\r\n };\r\n }\r\n const node = this.type.create(attributes);\r\n\r\n if (dispatch) {\r\n tr.replaceRangeWith(selection.from, selection.to, node);\r\n }\r\n\r\n // return commands.insertContent({\r\n // type: 'iframe',\r\n // attrs: attributes,\r\n // })\r\n\r\n return true;\r\n },\r\n\r\n setHtml:\r\n (value) =>\r\n ({ commands, state }) => {\r\n console.log(value);\r\n let attributes: Record<string, any> = {\r\n editorValue: value,\r\n };\r\n\r\n if (value?.includes(\"youtube.com\")) {\r\n const ytValue = value?.split(\"v=\")?.[1]?.split(\"&\")?.[0];\r\n attributes = {\r\n ...attributes,\r\n\r\n src: `https://www.youtube.com/embed/${ytValue}?controls=0`,\r\n title: \"YouTube video player\",\r\n };\r\n } else if (value?.includes(\"instagram.com\")) {\r\n const instagramValue = value?.split(\"p/\")?.[1]?.split(\"/\")?.[0];\r\n attributes = {\r\n ...attributes,\r\n\r\n src: `https://www.instagram.com/p/${instagramValue}/embed`,\r\n title: \"Instagram\",\r\n };\r\n } else if (isValidHttpUrl(value)) {\r\n attributes = {\r\n ...attributes,\r\n\r\n src: value,\r\n };\r\n } else if (value?.includes(\"iframe\")) {\r\n const parser = new DOMParser();\r\n const html = parser.parseFromString(value, \"text/html\");\r\n const attrNames = html\r\n .getElementsByTagName(\"iframe\")?.[0]\r\n ?.getAttributeNames();\r\n\r\n attrNames?.forEach((attr) => {\r\n attributes[attr] = html\r\n .getElementsByTagName(\"iframe\")?.[0]\r\n ?.getAttribute(attr);\r\n });\r\n } else {\r\n const htmlData = \"data:text/html;charset=utf-8,\" + encodeURI(value);\r\n attributes = {\r\n ...attributes,\r\n src: htmlData,\r\n };\r\n }\r\n\r\n return true;\r\n },\r\n insertIframe:\r\n (src, className) =>\r\n ({ commands, state }) => {\r\n return commands.insertContent({\r\n type: \"iframe\",\r\n attrs: {\r\n src,\r\n class: className,\r\n },\r\n });\r\n },\r\n };\r\n },\r\n});\r\n\r\nfunction isValidHttpUrl(string: string) {\r\n let url;\r\n\r\n try {\r\n url = new URL(string);\r\n } catch (_) {\r\n return false;\r\n }\r\n\r\n return url.protocol === \"http:\" || url.protocol === \"https:\";\r\n}\r\n"],"names":["mergeAttributes","Node","ReactNodeViewRenderer","IframeEmbed","Iframe","create","name","inline","group","content","draggable","atom","addOption","allowFullscreen","HTMLAttributes","class","addAttributes","src","default","frameborder","allowfullscreen","options","parseHTML","sandbox","referrerpolicy","renderHTML","tag","addNodeView","addCommands","setIframe","tr","dispatch","selection","attributes","includes","parser","DOMParser","html","parseFromString","attrNames","getElementsByTagName","getAttributeNames","forEach","attr","getAttribute","isValidHttpUrl","htmlData","encodeURI","node","type","replaceRangeWith","from","to","setHtml","value","commands","state","console","log","editorValue","ytValue","split","title","instagramValue","insertIframe","className","insertContent","attrs","string","url","URL","_","protocol"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../src/fields/TiptapEditor/extensions/Iframe/iframe.ts"],"sourcesContent":["import { mergeAttributes, Node } from '@tiptap/core'\r\nimport { ReactNodeViewRenderer } from '@tiptap/react'\r\nimport IframeEmbed from './IframeEmbed.js'\r\n\r\nexport interface IframeOptions {\r\n allowFullscreen: boolean\r\n HTMLAttributes: {\r\n [key: string]: any\r\n }\r\n}\r\n\r\ndeclare module '@tiptap/core' {\r\n interface Commands<ReturnType> {\r\n iframe: {\r\n /**\r\n * Add an iframe\r\n */\r\n setIframe: (options?: { src: string }) => ReturnType\r\n setHtml: (value: string) => ReturnType\r\n insertIframe: (src?: string, className?: string) => ReturnType\r\n }\r\n }\r\n}\r\n\r\nexport const Iframe = Node.create<IframeOptions>({\r\n name: 'iframe',\r\n inline: false,\r\n group: 'block',\r\n content: 'inline*',\r\n draggable: true,\r\n\r\n atom: true,\r\n\r\n addOptions() {\r\n return {\r\n allowFullscreen: true,\r\n HTMLAttributes: {\r\n class: 'iframe-wrapper',\r\n },\r\n }\r\n },\r\n\r\n addAttributes() {\r\n return {\r\n src: {\r\n default: null,\r\n },\r\n frameborder: {\r\n default: 0,\r\n },\r\n allowfullscreen: {\r\n default: this.options.allowFullscreen,\r\n parseHTML: () => this.options.allowFullscreen,\r\n },\r\n sandbox: {\r\n default: 'allow-scripts allow-same-origin allow-forms allow-popups allow-presentation',\r\n },\r\n referrerpolicy: {\r\n default: 'no-referrer-when-downgrade',\r\n },\r\n width: {\r\n default: '100%',\r\n },\r\n height: {\r\n default: 'auto',\r\n },\r\n title: {\r\n default: null,\r\n },\r\n loading: {\r\n default: 'lazy',\r\n },\r\n }\r\n },\r\n renderHTML({ HTMLAttributes }) {\r\n return ['iframe', mergeAttributes(this.options.HTMLAttributes, HTMLAttributes)]\r\n },\r\n parseHTML() {\r\n return [\r\n {\r\n tag: 'iframe',\r\n },\r\n ]\r\n },\r\n\r\n addNodeView() {\r\n return ReactNodeViewRenderer(IframeEmbed)\r\n },\r\n\r\n addCommands() {\r\n return {\r\n setIframe:\r\n (options: { src: string }) =>\r\n ({ tr, dispatch }) => {\r\n const { selection } = tr\r\n let attributes: Record<string, any> = {\r\n ...options,\r\n }\r\n\r\n if (options?.src?.includes('iframe')) {\r\n const parser = new DOMParser()\r\n const html = parser.parseFromString(options?.src, 'text/html')\r\n const attrNames = html.getElementsByTagName('iframe')?.[0]?.getAttributeNames()\r\n\r\n attrNames?.forEach((attr) => {\r\n attributes[attr] = html.getElementsByTagName('iframe')?.[0]?.getAttribute(attr)\r\n })\r\n } else if (!isValidHttpUrl(options?.src)) {\r\n const htmlData = 'data:text/html;charset=utf-8,' + encodeURI(options?.src)\r\n attributes = {\r\n ...attributes,\r\n src: htmlData,\r\n }\r\n }\r\n const node = this.type.create(attributes)\r\n\r\n if (dispatch) {\r\n tr.replaceRangeWith(selection.from, selection.to, node)\r\n }\r\n\r\n // return commands.insertContent({\r\n // type: 'iframe',\r\n // attrs: attributes,\r\n // })\r\n\r\n return true\r\n },\r\n\r\n setHtml:\r\n (value) =>\r\n ({ commands, state }) => {\r\n console.log(value)\r\n let attributes: Record<string, any> = {\r\n editorValue: value,\r\n }\r\n\r\n if (value?.includes('youtube.com')) {\r\n const ytValue = value?.split('v=')?.[1]?.split('&')?.[0]\r\n attributes = {\r\n ...attributes,\r\n\r\n src: `https://www.youtube.com/embed/${ytValue}?controls=0`,\r\n title: 'YouTube video player',\r\n }\r\n } else if (value?.includes('instagram.com')) {\r\n const instagramValue = value?.split('p/')?.[1]?.split('/')?.[0]\r\n attributes = {\r\n ...attributes,\r\n\r\n src: `https://www.instagram.com/p/${instagramValue}/embed`,\r\n title: 'Instagram',\r\n }\r\n } else if (isValidHttpUrl(value)) {\r\n attributes = {\r\n ...attributes,\r\n\r\n src: value,\r\n }\r\n } else if (value?.includes('iframe')) {\r\n const parser = new DOMParser()\r\n const html = parser.parseFromString(value, 'text/html')\r\n const attrNames = html.getElementsByTagName('iframe')?.[0]?.getAttributeNames()\r\n\r\n attrNames?.forEach((attr) => {\r\n attributes[attr] = html.getElementsByTagName('iframe')?.[0]?.getAttribute(attr)\r\n })\r\n } else {\r\n const htmlData = 'data:text/html;charset=utf-8,' + encodeURI(value)\r\n attributes = {\r\n ...attributes,\r\n src: htmlData,\r\n }\r\n }\r\n\r\n return true\r\n },\r\n insertIframe:\r\n (src, className) =>\r\n ({ commands, state }) => {\r\n return commands.insertContent({\r\n type: 'iframe',\r\n attrs: {\r\n src,\r\n class: className,\r\n },\r\n })\r\n },\r\n }\r\n },\r\n})\r\n\r\nfunction isValidHttpUrl(string: string) {\r\n let url\r\n\r\n try {\r\n url = new URL(string)\r\n } catch (_) {\r\n return false\r\n }\r\n\r\n return url.protocol === 'http:' || url.protocol === 'https:'\r\n}\r\n"],"names":["mergeAttributes","Node","ReactNodeViewRenderer","IframeEmbed","Iframe","create","name","inline","group","content","draggable","atom","addOptions","allowFullscreen","HTMLAttributes","class","addAttributes","src","default","frameborder","allowfullscreen","options","parseHTML","sandbox","referrerpolicy","width","height","title","loading","renderHTML","tag","addNodeView","addCommands","setIframe","tr","dispatch","selection","attributes","includes","parser","DOMParser","html","parseFromString","attrNames","getElementsByTagName","getAttributeNames","forEach","attr","getAttribute","isValidHttpUrl","htmlData","encodeURI","node","type","replaceRangeWith","from","to","setHtml","value","commands","state","console","log","editorValue","ytValue","split","instagramValue","insertIframe","className","insertContent","attrs","string","url","URL","_","protocol"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"Paragraph.d.ts","sourceRoot":"","sources":["../../../../../../src/fields/TiptapEditor/extensions/Paragraph/Paragraph.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,SAAS,0FAcpB,CAAC;AAEH,eAAe,SAAS,CAAC"}
1
+ {"version":3,"file":"Paragraph.d.ts","sourceRoot":"","sources":["../../../../../../src/fields/TiptapEditor/extensions/Paragraph/Paragraph.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,SAAS,0FAsCpB,CAAA;AAEF,eAAe,SAAS,CAAA"}
@@ -1,13 +1,13 @@
1
- import { mergeAttributes } from "@tiptap/core";
2
- import TiptapParagraph from "@tiptap/extension-paragraph";
1
+ import { mergeAttributes } from '@tiptap/core';
2
+ import TiptapParagraph from '@tiptap/extension-paragraph';
3
3
  export const Paragraph = TiptapParagraph.extend({
4
4
  addAttributes () {
5
5
  return {
6
6
  textAlign: {
7
- default: ""
7
+ default: ''
8
8
  },
9
9
  class: {
10
- default: ""
10
+ default: ''
11
11
  }
12
12
  };
13
13
  },
@@ -17,6 +17,29 @@ export const Paragraph = TiptapParagraph.extend({
17
17
  mergeAttributes(this.options.HTMLAttributes, HTMLAttributes),
18
18
  0
19
19
  ];
20
+ },
21
+ addKeyboardShortcuts () {
22
+ return {
23
+ Backspace: ({ editor })=>{
24
+ const { state } = editor;
25
+ const { selection } = state;
26
+ const { $from, empty } = selection;
27
+ if (!empty) {
28
+ return false;
29
+ }
30
+ if ($from.parent.type.name !== 'paragraph') {
31
+ return false;
32
+ }
33
+ const isEmpty = $from.parent.content.size === 0;
34
+ const isAtStart = $from.parentOffset === 0;
35
+ // If the paragraph is empty and we're at the start, delete it
36
+ if (isEmpty && isAtStart) {
37
+ const pos = $from.before();
38
+ return editor.chain().setNodeSelection(pos).deleteSelection().run();
39
+ }
40
+ return false;
41
+ }
42
+ };
20
43
  }
21
44
  });
22
45
  export default Paragraph;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../src/fields/TiptapEditor/extensions/Paragraph/Paragraph.ts"],"sourcesContent":["import { mergeAttributes } from \"@tiptap/core\";\r\nimport TiptapParagraph from \"@tiptap/extension-paragraph\";\r\n\r\nexport const Paragraph = TiptapParagraph.extend({\r\n addAttributes() {\r\n return {\r\n textAlign: { default: \"\" },\r\n class: { default: \"\" },\r\n };\r\n },\r\n renderHTML({ node, HTMLAttributes }) {\r\n return [\r\n 'p',\r\n mergeAttributes(this.options.HTMLAttributes, HTMLAttributes),\r\n 0,\r\n ];\r\n },\r\n});\r\n\r\nexport default Paragraph;\r\n"],"names":["mergeAttributes","TiptapParagraph","Paragraph","extend","addAttributes","textAlign","default","class","renderHTML","node","HTMLAttributes","options"],"mappings":"AAAA,SAASA,eAAe,QAAQ,eAAe;AAC/C,OAAOC,qBAAqB,8BAA8B;AAE1D,OAAO,MAAMC,YAAYD,gBAAgBE,MAAM,CAAC;IAC9CC;QACE,OAAO;YACLC,WAAW;gBAAEC,SAAS;YAAG;YACzBC,OAAO;gBAAED,SAAS;YAAG;QACvB;IACF;IACAE,YAAW,EAAEC,IAAI,EAAEC,cAAc,EAAE;QACjC,OAAO;YACL;YACAV,gBAAgB,IAAI,CAACW,OAAO,CAACD,cAAc,EAAEA;YAC7C;SACD;IACH;AACF,GAAG;AAEH,eAAeR,UAAU"}
1
+ {"version":3,"sources":["../../../../../../src/fields/TiptapEditor/extensions/Paragraph/Paragraph.ts"],"sourcesContent":["import { mergeAttributes } from '@tiptap/core'\r\nimport TiptapParagraph from '@tiptap/extension-paragraph'\r\n\r\nexport const Paragraph = TiptapParagraph.extend({\r\n addAttributes() {\r\n return {\r\n textAlign: { default: '' },\r\n class: { default: '' },\r\n }\r\n },\r\n renderHTML({ node, HTMLAttributes }) {\r\n return ['p', mergeAttributes(this.options.HTMLAttributes, HTMLAttributes), 0]\r\n },\r\n addKeyboardShortcuts() {\r\n return {\r\n Backspace: ({ editor }) => {\r\n const { state } = editor\r\n const { selection } = state\r\n const { $from, empty } = selection\r\n\r\n if (!empty) {\r\n return false\r\n }\r\n\r\n if ($from.parent.type.name !== 'paragraph') {\r\n return false\r\n }\r\n\r\n const isEmpty = $from.parent.content.size === 0\r\n const isAtStart = $from.parentOffset === 0\r\n\r\n // If the paragraph is empty and we're at the start, delete it\r\n if (isEmpty && isAtStart) {\r\n const pos = $from.before()\r\n return editor.chain().setNodeSelection(pos).deleteSelection().run()\r\n }\r\n\r\n return false\r\n },\r\n }\r\n },\r\n})\r\n\r\nexport default Paragraph\r\n"],"names":["mergeAttributes","TiptapParagraph","Paragraph","extend","addAttributes","textAlign","default","class","renderHTML","node","HTMLAttributes","options","addKeyboardShortcuts","Backspace","editor","state","selection","$from","empty","parent","type","name","isEmpty","content","size","isAtStart","parentOffset","pos","before","chain","setNodeSelection","deleteSelection","run"],"mappings":"AAAA,SAASA,eAAe,QAAQ,eAAc;AAC9C,OAAOC,qBAAqB,8BAA6B;AAEzD,OAAO,MAAMC,YAAYD,gBAAgBE,MAAM,CAAC;IAC9CC;QACE,OAAO;YACLC,WAAW;gBAAEC,SAAS;YAAG;YACzBC,OAAO;gBAAED,SAAS;YAAG;QACvB;IACF;IACAE,YAAW,EAAEC,IAAI,EAAEC,cAAc,EAAE;QACjC,OAAO;YAAC;YAAKV,gBAAgB,IAAI,CAACW,OAAO,CAACD,cAAc,EAAEA;YAAiB;SAAE;IAC/E;IACAE;QACE,OAAO;YACLC,WAAW,CAAC,EAAEC,MAAM,EAAE;gBACpB,MAAM,EAAEC,KAAK,EAAE,GAAGD;gBAClB,MAAM,EAAEE,SAAS,EAAE,GAAGD;gBACtB,MAAM,EAAEE,KAAK,EAAEC,KAAK,EAAE,GAAGF;gBAEzB,IAAI,CAACE,OAAO;oBACV,OAAO;gBACT;gBAEA,IAAID,MAAME,MAAM,CAACC,IAAI,CAACC,IAAI,KAAK,aAAa;oBAC1C,OAAO;gBACT;gBAEA,MAAMC,UAAUL,MAAME,MAAM,CAACI,OAAO,CAACC,IAAI,KAAK;gBAC9C,MAAMC,YAAYR,MAAMS,YAAY,KAAK;gBAEzC,8DAA8D;gBAC9D,IAAIJ,WAAWG,WAAW;oBACxB,MAAME,MAAMV,MAAMW,MAAM;oBACxB,OAAOd,OAAOe,KAAK,GAAGC,gBAAgB,CAACH,KAAKI,eAAe,GAAGC,GAAG;gBACnE;gBAEA,OAAO;YACT;QACF;IACF;AACF,GAAE;AAEF,eAAe9B,UAAS"}
@@ -0,0 +1,4 @@
1
+ import { Extension } from '@tiptap/core';
2
+ export declare const PasteHandler: Extension<any, any>;
3
+ export default PasteHandler;
4
+ //# sourceMappingURL=PasteHandler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PasteHandler.d.ts","sourceRoot":"","sources":["../../../../../../src/fields/TiptapEditor/extensions/PasteHandler/PasteHandler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAmHxC,eAAO,MAAM,YAAY,qBAoGvB,CAAA;AA2DF,eAAe,YAAY,CAAA"}
@@ -0,0 +1,242 @@
1
+ import { Extension } from '@tiptap/core';
2
+ import { Plugin, PluginKey } from '@tiptap/pm/state';
3
+ /**
4
+ * Checks if the HTML contains a table element
5
+ */ function containsTable(html) {
6
+ return /<table[\s>]/i.test(html);
7
+ }
8
+ /**
9
+ * Checks if the HTML contains an iframe element
10
+ */ function containsIframe(html) {
11
+ return /<iframe[\s>]/i.test(html);
12
+ }
13
+ /**
14
+ * Extracts iframe attributes from HTML string
15
+ */ function extractIframeAttributes(html) {
16
+ const parser = new DOMParser();
17
+ const doc = parser.parseFromString(html, 'text/html');
18
+ const iframe = doc.querySelector('iframe');
19
+ if (!iframe) return null;
20
+ const attributes = {};
21
+ for (const attr of iframe.getAttributeNames()){
22
+ const value = iframe.getAttribute(attr);
23
+ if (value !== null) {
24
+ attributes[attr] = value;
25
+ }
26
+ }
27
+ return attributes;
28
+ }
29
+ /**
30
+ * Checks if text is a Flourish, Datawrapper, or similar embed URL
31
+ */ function isEmbedUrl(text) {
32
+ const embedPatterns = [
33
+ /flourish\.studio/i,
34
+ /datawrapper\.dwcdn\.net/i,
35
+ /infogram\.com/i,
36
+ /public\.tableau\.com/i,
37
+ /plotly\.com/i,
38
+ /app\.powerbi\.com/i
39
+ ];
40
+ return embedPatterns.some((pattern)=>pattern.test(text));
41
+ }
42
+ /**
43
+ * Parses HTML table string and converts it to TipTap table JSON format
44
+ */ function parseHtmlTableToJson(html) {
45
+ const parser = new DOMParser();
46
+ const doc = parser.parseFromString(html, 'text/html');
47
+ const table = doc.querySelector('table');
48
+ if (!table) return null;
49
+ const rows = [];
50
+ const tableRows = table.querySelectorAll('tr');
51
+ tableRows.forEach((tr, rowIndex)=>{
52
+ const cells = [];
53
+ const tableCells = tr.querySelectorAll('td, th');
54
+ tableCells.forEach((cell)=>{
55
+ const isHeader = cell.tagName.toLowerCase() === 'th';
56
+ const cellText = cell.textContent?.trim() || '';
57
+ // Get colspan and rowspan attributes
58
+ const colspan = parseInt(cell.getAttribute('colspan') || '1', 10);
59
+ const rowspan = parseInt(cell.getAttribute('rowspan') || '1', 10);
60
+ const cellNode = {
61
+ type: isHeader ? 'tableHeader' : 'tableCell',
62
+ content: [
63
+ {
64
+ type: 'paragraph',
65
+ content: cellText ? [
66
+ {
67
+ type: 'text',
68
+ text: cellText
69
+ }
70
+ ] : []
71
+ }
72
+ ]
73
+ };
74
+ // Add attrs if colspan or rowspan is not 1
75
+ if (colspan !== 1 || rowspan !== 1) {
76
+ cellNode.attrs = {
77
+ colspan,
78
+ rowspan
79
+ };
80
+ }
81
+ cells.push(cellNode);
82
+ });
83
+ if (cells.length > 0) {
84
+ rows.push({
85
+ type: 'tableRow',
86
+ content: cells
87
+ });
88
+ }
89
+ });
90
+ if (rows.length === 0) return null;
91
+ return {
92
+ type: 'table',
93
+ content: rows
94
+ };
95
+ }
96
+ export const PasteHandler = Extension.create({
97
+ name: 'pasteHandler',
98
+ addProseMirrorPlugins () {
99
+ const { editor } = this;
100
+ return [
101
+ new Plugin({
102
+ key: new PluginKey('pasteHandler'),
103
+ props: {
104
+ handlePaste: (view, event, slice)=>{
105
+ const clipboardData = event.clipboardData;
106
+ if (!clipboardData) return false;
107
+ const html = clipboardData.getData('text/html');
108
+ const text = clipboardData.getData('text/plain');
109
+ // Handle iframe paste (from HTML)
110
+ if (html && containsIframe(html)) {
111
+ const attrs = extractIframeAttributes(html);
112
+ if (attrs && attrs.src) {
113
+ event.preventDefault();
114
+ editor.chain().focus().setIframe({
115
+ src: attrs.src
116
+ }).run();
117
+ return true;
118
+ }
119
+ }
120
+ // Handle iframe embed code paste (as plain text containing <iframe>)
121
+ if (text && containsIframe(text)) {
122
+ const attrs = extractIframeAttributes(text);
123
+ if (attrs && attrs.src) {
124
+ event.preventDefault();
125
+ editor.chain().focus().setIframe({
126
+ src: attrs.src
127
+ }).run();
128
+ return true;
129
+ }
130
+ }
131
+ // Handle embed URL paste (Flourish, Datawrapper, etc.)
132
+ if (text && isEmbedUrl(text) && !html) {
133
+ event.preventDefault();
134
+ editor.chain().focus().setIframe({
135
+ src: text.trim()
136
+ }).run();
137
+ return true;
138
+ }
139
+ // Handle plain text that contains HTML table markup (copy-pasted HTML code as text)
140
+ // Check this FIRST before checking html, because pasting HTML code as text
141
+ // will have the raw tags in text but might also have html content
142
+ if (text && containsTable(text)) {
143
+ // Check if the text itself contains raw HTML tags (not rendered)
144
+ // This happens when someone copies HTML source code
145
+ const hasRawHtmlTags = /<\/?(?:table|tr|td|th|thead|tbody)[\s>]/i.test(text);
146
+ if (hasRawHtmlTags) {
147
+ event.preventDefault();
148
+ try {
149
+ const tableJson = parseHtmlTableToJson(text);
150
+ if (tableJson) {
151
+ editor.chain().focus().insertContent(tableJson).run();
152
+ return true;
153
+ }
154
+ } catch (error) {
155
+ console.error('Error parsing table from text:', error);
156
+ }
157
+ return false;
158
+ }
159
+ }
160
+ // Handle HTML table paste (from clipboard HTML - e.g., copying from a webpage)
161
+ if (html && containsTable(html)) {
162
+ event.preventDefault();
163
+ try {
164
+ const tableJson = parseHtmlTableToJson(html);
165
+ if (tableJson) {
166
+ editor.chain().focus().insertContent(tableJson).run();
167
+ return true;
168
+ }
169
+ } catch (error) {
170
+ console.error('Error parsing table from HTML:', error);
171
+ }
172
+ return false;
173
+ }
174
+ // Handle plain text table paste (tab-separated or similar)
175
+ if (text && !html && isTabularData(text)) {
176
+ event.preventDefault();
177
+ const tableJson = convertTextToTable(text);
178
+ if (tableJson) {
179
+ editor.chain().focus().insertContent(tableJson).run();
180
+ return true;
181
+ }
182
+ }
183
+ return false;
184
+ }
185
+ }
186
+ })
187
+ ];
188
+ }
189
+ });
190
+ /**
191
+ * Checks if text appears to be tabular data (tab or comma separated)
192
+ */ function isTabularData(text) {
193
+ const lines = text.trim().split('\n');
194
+ if (lines.length < 2) return false;
195
+ // Check if lines have consistent tab or comma separators
196
+ const firstLineTabs = (lines[0].match(/\t/g) || []).length;
197
+ const firstLineCommas = (lines[0].match(/,/g) || []).length;
198
+ if (firstLineTabs === 0 && firstLineCommas === 0) return false;
199
+ // Check consistency across lines
200
+ const separator = firstLineTabs > 0 ? '\t' : ',';
201
+ const expectedColumns = lines[0].split(separator).length;
202
+ return lines.every((line)=>{
203
+ const columns = line.split(separator).length;
204
+ return columns === expectedColumns || columns === expectedColumns - 1;
205
+ });
206
+ }
207
+ /**
208
+ * Converts tab/comma separated text to table JSON
209
+ */ function convertTextToTable(text) {
210
+ const lines = text.trim().split('\n');
211
+ if (lines.length < 1) return null;
212
+ const firstLineTabs = (lines[0].match(/\t/g) || []).length;
213
+ const separator = firstLineTabs > 0 ? '\t' : ',';
214
+ const rows = lines.map((line, rowIndex)=>{
215
+ const cells = line.split(separator);
216
+ const cellType = rowIndex === 0 ? 'tableHeader' : 'tableCell';
217
+ return {
218
+ type: 'tableRow',
219
+ content: cells.map((cellText)=>({
220
+ type: cellType,
221
+ content: [
222
+ {
223
+ type: 'paragraph',
224
+ content: cellText.trim() ? [
225
+ {
226
+ type: 'text',
227
+ text: cellText.trim()
228
+ }
229
+ ] : []
230
+ }
231
+ ]
232
+ }))
233
+ };
234
+ });
235
+ return {
236
+ type: 'table',
237
+ content: rows
238
+ };
239
+ }
240
+ export default PasteHandler;
241
+
242
+ //# sourceMappingURL=PasteHandler.js.map