payload-richtext-tiptap 0.0.129 → 0.0.130

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 +1 @@
1
- {"version":3,"file":"instagram.d.ts","sourceRoot":"","sources":["../../../../../../../src/fields/TiptapEditor/extensions/SocialMedia/Instagram/instagram.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,cAAc,CAAC;IAC5B,UAAU,QAAQ,CAAC,UAAU;QAC3B,SAAS,EAAE;YACT;;eAEG;YAEH,eAAe,EAAE,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,KAAK,UAAU,CAAA;SAClE,CAAA;KACF;CACF;AAED,OAAO,EAAE,IAAI,EAAmB,MAAM,cAAc,CAAA;AAIpD,eAAO,MAAM,SAAS,gBAwGpB,CAAA"}
1
+ {"version":3,"file":"instagram.d.ts","sourceRoot":"","sources":["../../../../../../../src/fields/TiptapEditor/extensions/SocialMedia/Instagram/instagram.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,cAAc,CAAC;IAC5B,UAAU,QAAQ,CAAC,UAAU;QAC3B,SAAS,EAAE;YACT;;eAEG;YAEH,eAAe,EAAE,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,KAAK,UAAU,CAAA;SAClE,CAAA;KACF;CACF;AAED,OAAO,EAAE,IAAI,EAAmB,MAAM,cAAc,CAAA;AAIpD,eAAO,MAAM,SAAS,gBAkGpB,CAAA"}
@@ -63,7 +63,7 @@ export const Instagram = Node.create({
63
63
  [
64
64
  'iframe',
65
65
  mergeAttributes({
66
- src: HTMLAttributes.src,
66
+ src: convertInstaUrlToEmbed(HTMLAttributes.url),
67
67
  class: "instagram-media instagram-media-rendered"
68
68
  }, HTMLAttributes)
69
69
  ]
@@ -88,14 +88,7 @@ export const Instagram = Node.create({
88
88
  insertInstagram: (url, className)=>({ commands, state })=>{
89
89
  let embedUrl = "";
90
90
  if (url) {
91
- // Convert URL to embed format
92
- const urlObj = new URL(url);
93
- const path = urlObj.pathname;
94
- const postId = path.split('/').filter(Boolean)[1] // Get the post ID after /p/
95
- ;
96
- if (postId) {
97
- embedUrl = `https://www.instagram.com/p/${postId}/embed/`;
98
- }
91
+ embedUrl = convertInstaUrlToEmbed(url);
99
92
  }
100
93
  return commands.insertContent({
101
94
  type: 'instagram',
@@ -109,6 +102,19 @@ export const Instagram = Node.create({
109
102
  };
110
103
  }
111
104
  });
105
+ function convertInstaUrlToEmbed(url) {
106
+ if (!url) return undefined;
107
+ try {
108
+ // Convert URL to embed format
109
+ const urlObj = new URL(url);
110
+ const path = urlObj.pathname;
111
+ const postId = path.split('/').filter(Boolean)[1] // Get the post ID after /p/
112
+ ;
113
+ return postId ? `https://www.instagram.com/p/${postId}/embed/` : undefined;
114
+ } catch {
115
+ return undefined;
116
+ }
117
+ }
112
118
  function isValidHttpUrl(string) {
113
119
  let url;
114
120
  try {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../src/fields/TiptapEditor/extensions/SocialMedia/Instagram/instagram.ts"],"sourcesContent":["declare module '@tiptap/core' {\n interface Commands<ReturnType> {\n instagram: {\n /**\n * Add an image\n */\n\n insertInstagram: (url?: string, className?: string) => ReturnType\n }\n }\n}\n\nimport { Node, mergeAttributes } from '@tiptap/core'\nimport { ReactNodeViewRenderer } from '@tiptap/react'\nimport InstagramEmbed from './InstagramEmbed.js'\n\nexport const Instagram = Node.create({\n name: 'instagram',\n\n group: 'block',\n content: 'inline*',\n draggable: true,\n // content: 'inline*',\n\n addAttributes() {\n return {\n url: { default: null },\n class: { default: null },\n src: {\n default: null,\n },\n width: {\n default: '328px',\n },\n height: {\n default: '100%',\n },\n frameborder: {\n default: '0',\n },\n scrolling: {\n default: 'no',\n },\n allowtransparency: {\n default: 'true',\n },\n }\n },\n\n\n parseHTML() {\n return [\n {\n tag: 'div[data-type=\"instagram\"]',\n },\n ]\n },\n renderHTML({ HTMLAttributes }) {\n return [\n \"div\",\n mergeAttributes(HTMLAttributes, {\n \"data-type\": \"instagram\",\n class: `react-renderer node-instagram ${HTMLAttributes.class ?? \"\"}`,\n }), [\n 'div',\n mergeAttributes(\n { class: 'socialMediaContainer' },\n ),\n ['div', mergeAttributes({ class: 'rsme-embed rsme-instagram-embed max-w-[328px]', style: 'overflow: hidden; width: 328px; border-radius: 3px; position: relative;' }),\n\n ['iframe', mergeAttributes({ src: HTMLAttributes.src, class: \"instagram-media instagram-media-rendered\" }, HTMLAttributes)],\n ]\n ]\n ]\n },\n addKeyboardShortcuts() {\n return {\n 'Mod-Enter': () => {\n return this.editor\n .chain()\n .insertContentAt(this.editor.state.selection.head, {\n type: this.type.name,\n })\n .focus()\n .run()\n },\n }\n },\n\n addNodeView() {\n return ReactNodeViewRenderer(InstagramEmbed)\n },\n\n addCommands() {\n return {\n insertInstagram:\n (url, className) =>\n ({ commands, state }) => {\n let embedUrl = \"\"\n if (url) {\n\n // Convert URL to embed format\n const urlObj = new URL(url)\n const path = urlObj.pathname\n const postId = path.split('/').filter(Boolean)[1] // Get the post ID after /p/\n if (postId) {\n embedUrl = `https://www.instagram.com/p/${postId}/embed/`\n }\n }\n return commands.insertContent({\n type: 'instagram',\n attrs: {\n url: url,\n class: className,\n src: embedUrl,\n },\n })\n },\n }\n },\n})\n\nfunction isValidHttpUrl(string: string) {\n let url\n\n try {\n url = new URL(string)\n } catch (_) {\n return false\n }\n\n return url.protocol === 'http:' || url.protocol === 'https:'\n}\n"],"names":["Node","mergeAttributes","ReactNodeViewRenderer","InstagramEmbed","Instagram","create","name","group","content","draggable","addAttributes","url","default","class","src","width","height","frameborder","scrolling","allowtransparency","parseHTML","tag","renderHTML","HTMLAttributes","style","addKeyboardShortcuts","editor","chain","insertContentAt","state","selection","head","type","focus","run","addNodeView","addCommands","insertInstagram","className","commands","embedUrl","urlObj","URL","path","pathname","postId","split","filter","Boolean","insertContent","attrs","isValidHttpUrl","string","_","protocol"],"mappings":"AAYA,SAASA,IAAI,EAAEC,eAAe,QAAQ,eAAc;AACpD,SAASC,qBAAqB,QAAQ,gBAAe;AACrD,OAAOC,oBAAoB,sBAAqB;AAEhD,OAAO,MAAMC,YAAYJ,KAAKK,MAAM,CAAC;IACnCC,MAAM;IAENC,OAAO;IACPC,SAAS;IACTC,WAAW;IACX,sBAAsB;IAEtBC;QACE,OAAO;YACLC,KAAK;gBAAEC,SAAS;YAAK;YACrBC,OAAO;gBAAED,SAAS;YAAK;YACvBE,KAAK;gBACHF,SAAS;YACX;YACAG,OAAO;gBACLH,SAAS;YACX;YACAI,QAAQ;gBACNJ,SAAS;YACX;YACAK,aAAa;gBACXL,SAAS;YACX;YACAM,WAAW;gBACTN,SAAS;YACX;YACAO,mBAAmB;gBACjBP,SAAS;YACX;QACF;IACF;IAGAQ;QACE,OAAO;YACL;gBACEC,KAAK;YACP;SACD;IACH;IACAC,YAAW,EAAEC,cAAc,EAAE;QAC3B,OAAO;YACL;YACAtB,gBAAgBsB,gBAAgB;gBAC9B,aAAa;gBACbV,OAAO,CAAC,8BAA8B,EAAEU,eAAeV,KAAK,IAAI,GAAG,CAAC;YACtE;YAAI;gBACF;gBACAZ,gBACE;oBAAEY,OAAO;gBAAuB;gBAElC;oBAAC;oBAAOZ,gBAAgB;wBAAEY,OAAO;wBAAiDW,OAAO;oBAA0E;oBAEjK;wBAAC;wBAAUvB,gBAAgB;4BAAEa,KAAKS,eAAeT,GAAG;4BAAED,OAAO;wBAA2C,GAAGU;qBAAgB;iBAC5H;aACF;SACF;IACH;IACAE;QACE,OAAO;YACL,aAAa;gBACX,OAAO,IAAI,CAACC,MAAM,CACfC,KAAK,GACLC,eAAe,CAAC,IAAI,CAACF,MAAM,CAACG,KAAK,CAACC,SAAS,CAACC,IAAI,EAAE;oBACjDC,MAAM,IAAI,CAACA,IAAI,CAAC1B,IAAI;gBACtB,GACC2B,KAAK,GACLC,GAAG;YACR;QACF;IACF;IAEAC;QACE,OAAOjC,sBAAsBC;IAC/B;IAEAiC;QACE,OAAO;YACLC,iBACE,CAAC1B,KAAK2B,YACJ,CAAC,EAAEC,QAAQ,EAAEV,KAAK,EAAE;oBAClB,IAAIW,WAAW;oBACf,IAAI7B,KAAK;wBAEP,8BAA8B;wBAC9B,MAAM8B,SAAS,IAAIC,IAAI/B;wBACvB,MAAMgC,OAAOF,OAAOG,QAAQ;wBAC5B,MAAMC,SAASF,KAAKG,KAAK,CAAC,KAAKC,MAAM,CAACC,QAAQ,CAAC,EAAE,CAAC,4BAA4B;;wBAC9E,IAAIH,QAAQ;4BACVL,WAAW,CAAC,4BAA4B,EAAEK,OAAO,OAAO,CAAC;wBAC3D;oBACF;oBACA,OAAON,SAASU,aAAa,CAAC;wBAC5BjB,MAAM;wBACNkB,OAAO;4BACLvC,KAAKA;4BACLE,OAAOyB;4BACPxB,KAAK0B;wBACP;oBACF;gBACF;QACN;IACF;AACF,GAAE;AAEF,SAASW,eAAeC,MAAc;IACpC,IAAIzC;IAEJ,IAAI;QACFA,MAAM,IAAI+B,IAAIU;IAChB,EAAE,OAAOC,GAAG;QACV,OAAO;IACT;IAEA,OAAO1C,IAAI2C,QAAQ,KAAK,WAAW3C,IAAI2C,QAAQ,KAAK;AACtD"}
1
+ {"version":3,"sources":["../../../../../../../src/fields/TiptapEditor/extensions/SocialMedia/Instagram/instagram.ts"],"sourcesContent":["declare module '@tiptap/core' {\n interface Commands<ReturnType> {\n instagram: {\n /**\n * Add an image\n */\n\n insertInstagram: (url?: string, className?: string) => ReturnType\n }\n }\n}\n\nimport { Node, mergeAttributes } from '@tiptap/core'\nimport { ReactNodeViewRenderer } from '@tiptap/react'\nimport InstagramEmbed from './InstagramEmbed.js'\n\nexport const Instagram = Node.create({\n name: 'instagram',\n\n group: 'block',\n content: 'inline*',\n draggable: true,\n // content: 'inline*',\n\n addAttributes() {\n return {\n url: { default: null },\n class: { default: null },\n src: {\n default: null,\n },\n width: {\n default: '328px',\n },\n height: {\n default: '100%',\n },\n frameborder: {\n default: '0',\n },\n scrolling: {\n default: 'no',\n },\n allowtransparency: {\n default: 'true',\n },\n }\n },\n\n\n parseHTML() {\n return [\n {\n tag: 'div[data-type=\"instagram\"]',\n },\n ]\n },\n renderHTML({ HTMLAttributes }) {\n return [\n \"div\",\n mergeAttributes(HTMLAttributes, {\n \"data-type\": \"instagram\",\n class: `react-renderer node-instagram ${HTMLAttributes.class ?? \"\"}`,\n }), [\n 'div',\n mergeAttributes(\n { class: 'socialMediaContainer' },\n ),\n ['div', mergeAttributes({ class: 'rsme-embed rsme-instagram-embed max-w-[328px]', style: 'overflow: hidden; width: 328px; border-radius: 3px; position: relative;' }),\n\n ['iframe', mergeAttributes({ src: convertInstaUrlToEmbed(HTMLAttributes.url), class: \"instagram-media instagram-media-rendered\" }, HTMLAttributes)],\n ]\n ]\n ]\n },\n addKeyboardShortcuts() {\n return {\n 'Mod-Enter': () => {\n return this.editor\n .chain()\n .insertContentAt(this.editor.state.selection.head, {\n type: this.type.name,\n })\n .focus()\n .run()\n },\n }\n },\n\n addNodeView() {\n return ReactNodeViewRenderer(InstagramEmbed)\n },\n\n addCommands() {\n return {\n insertInstagram:\n (url, className) =>\n ({ commands, state }) => {\n let embedUrl = \"\"\n if (url) {\n embedUrl = convertInstaUrlToEmbed(url)\n\n }\n return commands.insertContent({\n type: 'instagram',\n attrs: {\n url: url,\n class: className,\n src: embedUrl,\n },\n })\n },\n }\n },\n})\nfunction convertInstaUrlToEmbed(url: string): string | undefined {\n if (!url) return undefined;\n try {\n // Convert URL to embed format\n const urlObj = new URL(url)\n const path = urlObj.pathname\n const postId = path.split('/').filter(Boolean)[1] // Get the post ID after /p/\n return postId ? `https://www.instagram.com/p/${postId}/embed/` : undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction isValidHttpUrl(string: string) {\n let url\n\n try {\n url = new URL(string)\n } catch (_) {\n return false\n }\n\n return url.protocol === 'http:' || url.protocol === 'https:'\n}\n"],"names":["Node","mergeAttributes","ReactNodeViewRenderer","InstagramEmbed","Instagram","create","name","group","content","draggable","addAttributes","url","default","class","src","width","height","frameborder","scrolling","allowtransparency","parseHTML","tag","renderHTML","HTMLAttributes","style","convertInstaUrlToEmbed","addKeyboardShortcuts","editor","chain","insertContentAt","state","selection","head","type","focus","run","addNodeView","addCommands","insertInstagram","className","commands","embedUrl","insertContent","attrs","undefined","urlObj","URL","path","pathname","postId","split","filter","Boolean","isValidHttpUrl","string","_","protocol"],"mappings":"AAYA,SAASA,IAAI,EAAEC,eAAe,QAAQ,eAAc;AACpD,SAASC,qBAAqB,QAAQ,gBAAe;AACrD,OAAOC,oBAAoB,sBAAqB;AAEhD,OAAO,MAAMC,YAAYJ,KAAKK,MAAM,CAAC;IACnCC,MAAM;IAENC,OAAO;IACPC,SAAS;IACTC,WAAW;IACX,sBAAsB;IAEtBC;QACE,OAAO;YACLC,KAAK;gBAAEC,SAAS;YAAK;YACrBC,OAAO;gBAAED,SAAS;YAAK;YACvBE,KAAK;gBACHF,SAAS;YACX;YACAG,OAAO;gBACLH,SAAS;YACX;YACAI,QAAQ;gBACNJ,SAAS;YACX;YACAK,aAAa;gBACXL,SAAS;YACX;YACAM,WAAW;gBACTN,SAAS;YACX;YACAO,mBAAmB;gBACjBP,SAAS;YACX;QACF;IACF;IAGAQ;QACE,OAAO;YACL;gBACEC,KAAK;YACP;SACD;IACH;IACAC,YAAW,EAAEC,cAAc,EAAE;QAC3B,OAAO;YACL;YACAtB,gBAAgBsB,gBAAgB;gBAC9B,aAAa;gBACbV,OAAO,CAAC,8BAA8B,EAAEU,eAAeV,KAAK,IAAI,GAAG,CAAC;YACtE;YAAI;gBACF;gBACAZ,gBACE;oBAAEY,OAAO;gBAAuB;gBAElC;oBAAC;oBAAOZ,gBAAgB;wBAAEY,OAAO;wBAAiDW,OAAO;oBAA0E;oBAEjK;wBAAC;wBAAUvB,gBAAgB;4BAAEa,KAAKW,uBAAuBF,eAAeZ,GAAG;4BAAGE,OAAO;wBAA2C,GAAGU;qBAAgB;iBACpJ;aACF;SACF;IACH;IACAG;QACE,OAAO;YACL,aAAa;gBACX,OAAO,IAAI,CAACC,MAAM,CACfC,KAAK,GACLC,eAAe,CAAC,IAAI,CAACF,MAAM,CAACG,KAAK,CAACC,SAAS,CAACC,IAAI,EAAE;oBACjDC,MAAM,IAAI,CAACA,IAAI,CAAC3B,IAAI;gBACtB,GACC4B,KAAK,GACLC,GAAG;YACR;QACF;IACF;IAEAC;QACE,OAAOlC,sBAAsBC;IAC/B;IAEAkC;QACE,OAAO;YACLC,iBACE,CAAC3B,KAAK4B,YACJ,CAAC,EAAEC,QAAQ,EAAEV,KAAK,EAAE;oBAClB,IAAIW,WAAW;oBACf,IAAI9B,KAAK;wBACP8B,WAAWhB,uBAAuBd;oBAEpC;oBACA,OAAO6B,SAASE,aAAa,CAAC;wBAC5BT,MAAM;wBACNU,OAAO;4BACLhC,KAAKA;4BACLE,OAAO0B;4BACPzB,KAAK2B;wBACP;oBACF;gBACF;QACN;IACF;AACF,GAAE;AACF,SAAShB,uBAAuBd,GAAW;IACzC,IAAI,CAACA,KAAK,OAAOiC;IACjB,IAAI;QACF,8BAA8B;QAC9B,MAAMC,SAAS,IAAIC,IAAInC;QACvB,MAAMoC,OAAOF,OAAOG,QAAQ;QAC5B,MAAMC,SAASF,KAAKG,KAAK,CAAC,KAAKC,MAAM,CAACC,QAAQ,CAAC,EAAE,CAAC,4BAA4B;;QAC9E,OAAOH,SAAS,CAAC,4BAA4B,EAAEA,OAAO,OAAO,CAAC,GAAGL;IACnE,EAAE,OAAM;QACN,OAAOA;IACT;AACF;AAEA,SAASS,eAAeC,MAAc;IACpC,IAAI3C;IAEJ,IAAI;QACFA,MAAM,IAAImC,IAAIQ;IAChB,EAAE,OAAOC,GAAG;QACV,OAAO;IACT;IAEA,OAAO5C,IAAI6C,QAAQ,KAAK,WAAW7C,IAAI6C,QAAQ,KAAK;AACtD"}
@@ -1 +1 @@
1
- {"version":3,"file":"tiktok.d.ts","sourceRoot":"","sources":["../../../../../../../src/fields/TiptapEditor/extensions/SocialMedia/Tiktok/tiktok.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,cAAc,CAAC;IAC5B,UAAU,QAAQ,CAAC,UAAU;QAC3B,MAAM,EAAE;YACN;;eAEG;YAEH,YAAY,EAAE,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,KAAK,UAAU,CAAA;SAC/D,CAAA;KACF;CACF;AAED,OAAO,EAAE,IAAI,EAAmB,MAAM,cAAc,CAAA;AAIpD,eAAO,MAAM,MAAM,gBA0GjB,CAAA"}
1
+ {"version":3,"file":"tiktok.d.ts","sourceRoot":"","sources":["../../../../../../../src/fields/TiptapEditor/extensions/SocialMedia/Tiktok/tiktok.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,cAAc,CAAC;IAC5B,UAAU,QAAQ,CAAC,UAAU;QAC3B,MAAM,EAAE;YACN;;eAEG;YAEH,YAAY,EAAE,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,KAAK,UAAU,CAAA;SAC/D,CAAA;KACF;CACF;AAED,OAAO,EAAE,IAAI,EAAmB,MAAM,cAAc,CAAA;AAIpD,eAAO,MAAM,MAAM,gBAoGjB,CAAA"}
@@ -68,7 +68,7 @@ export const Tiktok = Node.create({
68
68
  [
69
69
  'iframe',
70
70
  mergeAttributes({
71
- src: HTMLAttributes.src
71
+ src: convertTikTokUrlToEmbed(HTMLAttributes.url)
72
72
  }, HTMLAttributes)
73
73
  ]
74
74
  ]
@@ -92,15 +92,8 @@ export const Tiktok = Node.create({
92
92
  return {
93
93
  insertTiktok: (url, className)=>({ commands, state })=>{
94
94
  let embedUrl;
95
- if (url) {
96
- const urlObj = new URL(url);
97
- const path = urlObj.pathname;
98
- const videoId = path.split('/').filter(Boolean)[2] // Get video ID from path
99
- ;
100
- if (videoId) {
101
- embedUrl = `https://www.tiktok.com/embed/v3/${videoId}`;
102
- }
103
- }
95
+ // Usage in the original location:
96
+ embedUrl = url ? convertTikTokUrlToEmbed(url) : undefined;
104
97
  return commands.insertContent({
105
98
  type: 'tiktok',
106
99
  attrs: {
@@ -113,6 +106,17 @@ export const Tiktok = Node.create({
113
106
  };
114
107
  }
115
108
  });
109
+ function convertTikTokUrlToEmbed(url) {
110
+ if (!url) return undefined;
111
+ try {
112
+ const urlObj = new URL(url);
113
+ const path = urlObj.pathname;
114
+ const videoId = path.split('/').filter(Boolean)[2];
115
+ return videoId ? `https://www.tiktok.com/embed/v3/${videoId}` : undefined;
116
+ } catch {
117
+ return undefined;
118
+ }
119
+ }
116
120
  function isValidHttpUrl(string) {
117
121
  let url;
118
122
  try {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../src/fields/TiptapEditor/extensions/SocialMedia/Tiktok/tiktok.ts"],"sourcesContent":["declare module '@tiptap/core' {\n interface Commands<ReturnType> {\n tiktok: {\n /**\n * Add an image\n */\n\n insertTiktok: (url?: string, className?: string) => ReturnType\n }\n }\n}\n\nimport { Node, mergeAttributes } from '@tiptap/core'\nimport { ReactNodeViewRenderer } from '@tiptap/react'\nimport TiktokEmbed from './TiktokEmbed.js'\n\nexport const Tiktok = Node.create({\n name: 'tiktok',\n\n group: 'block',\n content: 'inline*',\n draggable: true,\n\n // content: 'inline*',\n\n addAttributes() {\n return {\n url: { default: null },\n class: { default: null },\n src: {\n default: null,\n },\n width: {\n default: '328px',\n },\n height: {\n default: '100%',\n },\n frameborder: {\n default: '0',\n },\n scrolling: {\n default: 'no',\n },\n allowtransparency: {\n default: 'true',\n },\n }\n },\n parseHTML() {\n return [\n {\n tag: 'div[data-type=\"tiktok\"]',\n },\n ]\n },\n renderHTML({ HTMLAttributes }) {\n return [\n \"div\",\n mergeAttributes({\n \"data-type\": \"tiktok\",\n class: `react-renderer node-tiktok ${HTMLAttributes.class ?? \"\"}`,\n }), [\n 'div',\n mergeAttributes(\n { class: 'socialMediaContainer' },\n ),\n ['div', mergeAttributes({ class: 'rsme-embed rsme-tiktok-embed', style: 'overflow: hidden; border-radius: 8px;' }),\n ['div', { class: 'tiktok-embed-container' },\n ['iframe', mergeAttributes({ src: HTMLAttributes.src }, HTMLAttributes)],\n ]\n ]\n ]\n ]\n },\n addKeyboardShortcuts() {\n return {\n 'Mod-Enter': () => {\n return this.editor\n .chain()\n .insertContentAt(this.editor.state.selection.head, {\n type: this.type.name,\n })\n .focus()\n .run()\n },\n }\n },\n\n addNodeView() {\n return ReactNodeViewRenderer(TiktokEmbed)\n },\n\n addCommands() {\n return {\n insertTiktok:\n (url, className) =>\n ({ commands, state }) => {\n\n\n let embedUrl\n if (url) { // Convert URL to embed format\n const urlObj = new URL(url)\n const path = urlObj.pathname\n const videoId = path.split('/').filter(Boolean)[2] // Get video ID from path\n\n\n if (videoId) {\n embedUrl = `https://www.tiktok.com/embed/v3/${videoId}`\n }\n }\n return commands.insertContent({\n type: 'tiktok',\n attrs: {\n url,\n class: className,\n src: embedUrl,\n },\n })\n },\n }\n },\n})\n\nfunction isValidHttpUrl(string: string) {\n let url\n\n try {\n url = new URL(string)\n } catch (_) {\n return false\n }\n\n return url.protocol === 'http:' || url.protocol === 'https:'\n}\n"],"names":["Node","mergeAttributes","ReactNodeViewRenderer","TiktokEmbed","Tiktok","create","name","group","content","draggable","addAttributes","url","default","class","src","width","height","frameborder","scrolling","allowtransparency","parseHTML","tag","renderHTML","HTMLAttributes","style","addKeyboardShortcuts","editor","chain","insertContentAt","state","selection","head","type","focus","run","addNodeView","addCommands","insertTiktok","className","commands","embedUrl","urlObj","URL","path","pathname","videoId","split","filter","Boolean","insertContent","attrs","isValidHttpUrl","string","_","protocol"],"mappings":"AAYA,SAASA,IAAI,EAAEC,eAAe,QAAQ,eAAc;AACpD,SAASC,qBAAqB,QAAQ,gBAAe;AACrD,OAAOC,iBAAiB,mBAAkB;AAE1C,OAAO,MAAMC,SAASJ,KAAKK,MAAM,CAAC;IAChCC,MAAM;IAENC,OAAO;IACPC,SAAS;IACTC,WAAW;IAEX,sBAAsB;IAEtBC;QACE,OAAO;YACLC,KAAK;gBAAEC,SAAS;YAAK;YACrBC,OAAO;gBAAED,SAAS;YAAK;YACvBE,KAAK;gBACHF,SAAS;YACX;YACAG,OAAO;gBACLH,SAAS;YACX;YACAI,QAAQ;gBACNJ,SAAS;YACX;YACAK,aAAa;gBACXL,SAAS;YACX;YACAM,WAAW;gBACTN,SAAS;YACX;YACAO,mBAAmB;gBACjBP,SAAS;YACX;QACF;IACF;IACAQ;QACE,OAAO;YACL;gBACEC,KAAK;YACP;SACD;IACH;IACAC,YAAW,EAAEC,cAAc,EAAE;QAC3B,OAAO;YACL;YACAtB,gBAAgB;gBACd,aAAa;gBACbY,OAAO,CAAC,2BAA2B,EAAEU,eAAeV,KAAK,IAAI,GAAG,CAAC;YACnE;YAAI;gBACF;gBACAZ,gBACE;oBAAEY,OAAO;gBAAuB;gBAElC;oBAAC;oBAAOZ,gBAAgB;wBAAEY,OAAO;wBAAgCW,OAAO;oBAAwC;oBAC9G;wBAAC;wBAAO;4BAAEX,OAAO;wBAAyB;wBACxC;4BAAC;4BAAUZ,gBAAgB;gCAAEa,KAAKS,eAAeT,GAAG;4BAAC,GAAGS;yBAAgB;qBACzE;iBACF;aACF;SACF;IACH;IACAE;QACE,OAAO;YACL,aAAa;gBACX,OAAO,IAAI,CAACC,MAAM,CACfC,KAAK,GACLC,eAAe,CAAC,IAAI,CAACF,MAAM,CAACG,KAAK,CAACC,SAAS,CAACC,IAAI,EAAE;oBACjDC,MAAM,IAAI,CAACA,IAAI,CAAC1B,IAAI;gBACtB,GACC2B,KAAK,GACLC,GAAG;YACR;QACF;IACF;IAEAC;QACE,OAAOjC,sBAAsBC;IAC/B;IAEAiC;QACE,OAAO;YACLC,cACE,CAAC1B,KAAK2B,YACJ,CAAC,EAAEC,QAAQ,EAAEV,KAAK,EAAE;oBAGlB,IAAIW;oBACJ,IAAI7B,KAAK;wBACP,MAAM8B,SAAS,IAAIC,IAAI/B;wBACvB,MAAMgC,OAAOF,OAAOG,QAAQ;wBAC5B,MAAMC,UAAUF,KAAKG,KAAK,CAAC,KAAKC,MAAM,CAACC,QAAQ,CAAC,EAAE,CAAC,yBAAyB;;wBAG5E,IAAIH,SAAS;4BACXL,WAAW,CAAC,gCAAgC,EAAEK,QAAQ,CAAC;wBACzD;oBACF;oBACA,OAAON,SAASU,aAAa,CAAC;wBAC5BjB,MAAM;wBACNkB,OAAO;4BACLvC;4BACAE,OAAOyB;4BACPxB,KAAK0B;wBACP;oBACF;gBACF;QACN;IACF;AACF,GAAE;AAEF,SAASW,eAAeC,MAAc;IACpC,IAAIzC;IAEJ,IAAI;QACFA,MAAM,IAAI+B,IAAIU;IAChB,EAAE,OAAOC,GAAG;QACV,OAAO;IACT;IAEA,OAAO1C,IAAI2C,QAAQ,KAAK,WAAW3C,IAAI2C,QAAQ,KAAK;AACtD"}
1
+ {"version":3,"sources":["../../../../../../../src/fields/TiptapEditor/extensions/SocialMedia/Tiktok/tiktok.ts"],"sourcesContent":["declare module '@tiptap/core' {\n interface Commands<ReturnType> {\n tiktok: {\n /**\n * Add an image\n */\n\n insertTiktok: (url?: string, className?: string) => ReturnType\n }\n }\n}\n\nimport { Node, mergeAttributes } from '@tiptap/core'\nimport { ReactNodeViewRenderer } from '@tiptap/react'\nimport TiktokEmbed from './TiktokEmbed.js'\n\nexport const Tiktok = Node.create({\n name: 'tiktok',\n\n group: 'block',\n content: 'inline*',\n draggable: true,\n\n // content: 'inline*',\n\n addAttributes() {\n return {\n url: { default: null },\n class: { default: null },\n src: {\n default: null,\n },\n width: {\n default: '328px',\n },\n height: {\n default: '100%',\n },\n frameborder: {\n default: '0',\n },\n scrolling: {\n default: 'no',\n },\n allowtransparency: {\n default: 'true',\n },\n }\n },\n parseHTML() {\n return [\n {\n tag: 'div[data-type=\"tiktok\"]',\n },\n ]\n },\n renderHTML({ HTMLAttributes }) {\n return [\n \"div\",\n mergeAttributes({\n \"data-type\": \"tiktok\",\n class: `react-renderer node-tiktok ${HTMLAttributes.class ?? \"\"}`,\n }), [\n 'div',\n mergeAttributes(\n { class: 'socialMediaContainer' },\n ),\n ['div', mergeAttributes({ class: 'rsme-embed rsme-tiktok-embed', style: 'overflow: hidden; border-radius: 8px;' }),\n ['div', { class: 'tiktok-embed-container' },\n ['iframe', mergeAttributes({ src: convertTikTokUrlToEmbed(HTMLAttributes.url) }, HTMLAttributes)],\n ]\n ]\n ]\n ]\n },\n addKeyboardShortcuts() {\n return {\n 'Mod-Enter': () => {\n return this.editor\n .chain()\n .insertContentAt(this.editor.state.selection.head, {\n type: this.type.name,\n })\n .focus()\n .run()\n },\n }\n },\n\n addNodeView() {\n return ReactNodeViewRenderer(TiktokEmbed)\n },\n\n addCommands() {\n return {\n insertTiktok:\n (url, className) =>\n ({ commands, state }) => {\n\n\n let embedUrl\n\n\n // Usage in the original location:\n embedUrl = url ? convertTikTokUrlToEmbed(url) : undefined;\n return commands.insertContent({\n type: 'tiktok',\n attrs: {\n url,\n class: className,\n src: embedUrl,\n },\n })\n },\n }\n },\n})\n\nfunction convertTikTokUrlToEmbed(url: string): string | undefined {\n if (!url) return undefined;\n try {\n const urlObj = new URL(url);\n const path = urlObj.pathname;\n const videoId = path.split('/').filter(Boolean)[2];\n return videoId ? `https://www.tiktok.com/embed/v3/${videoId}` : undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction isValidHttpUrl(string: string) {\n let url\n\n try {\n url = new URL(string)\n } catch (_) {\n return false\n }\n\n return url.protocol === 'http:' || url.protocol === 'https:'\n}\n"],"names":["Node","mergeAttributes","ReactNodeViewRenderer","TiktokEmbed","Tiktok","create","name","group","content","draggable","addAttributes","url","default","class","src","width","height","frameborder","scrolling","allowtransparency","parseHTML","tag","renderHTML","HTMLAttributes","style","convertTikTokUrlToEmbed","addKeyboardShortcuts","editor","chain","insertContentAt","state","selection","head","type","focus","run","addNodeView","addCommands","insertTiktok","className","commands","embedUrl","undefined","insertContent","attrs","urlObj","URL","path","pathname","videoId","split","filter","Boolean","isValidHttpUrl","string","_","protocol"],"mappings":"AAYA,SAASA,IAAI,EAAEC,eAAe,QAAQ,eAAc;AACpD,SAASC,qBAAqB,QAAQ,gBAAe;AACrD,OAAOC,iBAAiB,mBAAkB;AAE1C,OAAO,MAAMC,SAASJ,KAAKK,MAAM,CAAC;IAChCC,MAAM;IAENC,OAAO;IACPC,SAAS;IACTC,WAAW;IAEX,sBAAsB;IAEtBC;QACE,OAAO;YACLC,KAAK;gBAAEC,SAAS;YAAK;YACrBC,OAAO;gBAAED,SAAS;YAAK;YACvBE,KAAK;gBACHF,SAAS;YACX;YACAG,OAAO;gBACLH,SAAS;YACX;YACAI,QAAQ;gBACNJ,SAAS;YACX;YACAK,aAAa;gBACXL,SAAS;YACX;YACAM,WAAW;gBACTN,SAAS;YACX;YACAO,mBAAmB;gBACjBP,SAAS;YACX;QACF;IACF;IACAQ;QACE,OAAO;YACL;gBACEC,KAAK;YACP;SACD;IACH;IACAC,YAAW,EAAEC,cAAc,EAAE;QAC3B,OAAO;YACL;YACAtB,gBAAgB;gBACd,aAAa;gBACbY,OAAO,CAAC,2BAA2B,EAAEU,eAAeV,KAAK,IAAI,GAAG,CAAC;YACnE;YAAI;gBACF;gBACAZ,gBACE;oBAAEY,OAAO;gBAAuB;gBAElC;oBAAC;oBAAOZ,gBAAgB;wBAAEY,OAAO;wBAAgCW,OAAO;oBAAwC;oBAC9G;wBAAC;wBAAO;4BAAEX,OAAO;wBAAyB;wBACxC;4BAAC;4BAAUZ,gBAAgB;gCAAEa,KAAKW,wBAAwBF,eAAeZ,GAAG;4BAAE,GAAGY;yBAAgB;qBAClG;iBACF;aACF;SACF;IACH;IACAG;QACE,OAAO;YACL,aAAa;gBACX,OAAO,IAAI,CAACC,MAAM,CACfC,KAAK,GACLC,eAAe,CAAC,IAAI,CAACF,MAAM,CAACG,KAAK,CAACC,SAAS,CAACC,IAAI,EAAE;oBACjDC,MAAM,IAAI,CAACA,IAAI,CAAC3B,IAAI;gBACtB,GACC4B,KAAK,GACLC,GAAG;YACR;QACF;IACF;IAEAC;QACE,OAAOlC,sBAAsBC;IAC/B;IAEAkC;QACE,OAAO;YACLC,cACE,CAAC3B,KAAK4B,YACJ,CAAC,EAAEC,QAAQ,EAAEV,KAAK,EAAE;oBAGlB,IAAIW;oBAGJ,kCAAkC;oBAClCA,WAAW9B,MAAMc,wBAAwBd,OAAO+B;oBAChD,OAAOF,SAASG,aAAa,CAAC;wBAC5BV,MAAM;wBACNW,OAAO;4BACLjC;4BACAE,OAAO0B;4BACPzB,KAAK2B;wBACP;oBACF;gBACF;QACN;IACF;AACF,GAAE;AAEF,SAAShB,wBAAwBd,GAAW;IAC1C,IAAI,CAACA,KAAK,OAAO+B;IACjB,IAAI;QACF,MAAMG,SAAS,IAAIC,IAAInC;QACvB,MAAMoC,OAAOF,OAAOG,QAAQ;QAC5B,MAAMC,UAAUF,KAAKG,KAAK,CAAC,KAAKC,MAAM,CAACC,QAAQ,CAAC,EAAE;QAClD,OAAOH,UAAU,CAAC,gCAAgC,EAAEA,QAAQ,CAAC,GAAGP;IAClE,EAAE,OAAM;QACN,OAAOA;IACT;AACF;AAEA,SAASW,eAAeC,MAAc;IACpC,IAAI3C;IAEJ,IAAI;QACFA,MAAM,IAAImC,IAAIQ;IAChB,EAAE,OAAOC,GAAG;QACV,OAAO;IACT;IAEA,OAAO5C,IAAI6C,QAAQ,KAAK,WAAW7C,IAAI6C,QAAQ,KAAK;AACtD"}
@@ -1 +1 @@
1
- {"version":3,"file":"twitter.d.ts","sourceRoot":"","sources":["../../../../../../../src/fields/TiptapEditor/extensions/SocialMedia/Twitter/twitter.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,cAAc,CAAC;IAC5B,UAAU,QAAQ,CAAC,UAAU;QAC3B,OAAO,EAAE;YACP;;eAEG;YAEH,aAAa,EAAE,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,KAAK,UAAU,CAAA;SAChE,CAAA;KACF;CACF;AAED,OAAO,EAAE,IAAI,EAA6C,MAAM,cAAc,CAAA;AAI9E,eAAO,MAAM,OAAO,gBA0GlB,CAAA"}
1
+ {"version":3,"file":"twitter.d.ts","sourceRoot":"","sources":["../../../../../../../src/fields/TiptapEditor/extensions/SocialMedia/Twitter/twitter.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,cAAc,CAAC;IAC5B,UAAU,QAAQ,CAAC,UAAU;QAC3B,OAAO,EAAE;YACP;;eAEG;YAEH,aAAa,EAAE,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,KAAK,UAAU,CAAA;SAChE,CAAA;KACF;CACF;AAED,OAAO,EAAE,IAAI,EAA6C,MAAM,cAAc,CAAA;AAI9E,eAAO,MAAM,OAAO,gBAsGlB,CAAA"}
@@ -69,7 +69,7 @@ export const Twitter = Node.create({
69
69
  [
70
70
  'a',
71
71
  {
72
- href: HTMLAttributes.src ?? HTMLAttributes.url
72
+ href: convertYoutubeUrlToEmbed(HTMLAttributes.url) ?? HTMLAttributes.src
73
73
  },
74
74
  ''
75
75
  ]
@@ -94,11 +94,7 @@ export const Twitter = Node.create({
94
94
  insertTwitter: (url, className)=>({ commands, state })=>{
95
95
  let formattedUrl = url;
96
96
  if (url) {
97
- const tweetMatch = url.match(/(?:twitter\.com|x\.com)\/([^\/]+)\/status\/(\d+)/);
98
- if (tweetMatch) {
99
- const [_, username, tweetId] = tweetMatch;
100
- formattedUrl = `https://twitter.com/${username}/status/${tweetId}`;
101
- }
97
+ formattedUrl = convertYoutubeUrlToEmbed(url);
102
98
  }
103
99
  return commands.insertContent({
104
100
  type: 'twitter',
@@ -112,6 +108,20 @@ export const Twitter = Node.create({
112
108
  };
113
109
  }
114
110
  });
111
+ function convertYoutubeUrlToEmbed(url) {
112
+ if (!url) return undefined;
113
+ try {
114
+ let formattedUrl;
115
+ const tweetMatch = url.match(/(?:twitter\.com|x\.com)\/([^\/]+)\/status\/(\d+)/);
116
+ if (tweetMatch) {
117
+ const [_, username, tweetId] = tweetMatch;
118
+ formattedUrl = `https://twitter.com/${username}/status/${tweetId}`;
119
+ }
120
+ return formattedUrl ? formattedUrl : undefined;
121
+ } catch {
122
+ return undefined;
123
+ }
124
+ }
115
125
  function isValidHttpUrl(string) {
116
126
  let url;
117
127
  try {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../src/fields/TiptapEditor/extensions/SocialMedia/Twitter/twitter.ts"],"sourcesContent":["declare module '@tiptap/core' {\n interface Commands<ReturnType> {\n twitter: {\n /**\n * Add an image\n */\n\n insertTwitter: (url?: string, className?: string) => ReturnType\n }\n }\n}\n\nimport { Node, PasteRule, markPasteRule, mergeAttributes } from '@tiptap/core'\nimport { ReactNodeViewRenderer } from '@tiptap/react'\nimport TwitterEmbed from './TwitterEmbed.js'\n\nexport const Twitter = Node.create({\n name: 'twitter',\n\n group: 'block',\n content: 'inline*',\n draggable: true,\n\n // content: 'inline*',\n\n parseHTML() {\n return [\n {\n tag: 'div[data-type=\"twitter\"]',\n },\n ]\n },\n\n addAttributes() {\n return {\n url: { default: null },\n src: { default: null },\n class: { default: null },\n }\n },\n\n addKeyboardShortcuts() {\n return {\n 'Mod-Enter': () => {\n return this.editor\n .chain()\n .insertContentAt(this.editor.state.selection.head, {\n type: this.type.name,\n })\n .focus()\n .run()\n },\n }\n },\n\n // renderHTML({ HTMLAttributes }) {\n // return [\n // \"div\",\n // mergeAttributes(HTMLAttributes, { \"data-type\": \"twitter\" }),\n // 0,\n // ];\n // },\n renderHTML({ HTMLAttributes }) {\n return [\n \"div\",\n mergeAttributes(HTMLAttributes, {\n \"data-type\": \"twitter\",\n class: `react-renderer node-twitter ${HTMLAttributes.class ?? \"\"}`,\n }), [\n 'div',\n mergeAttributes(\n { class: 'socialMediaContainer' },\n ),\n ['div', mergeAttributes({ class: 'rsme-embed rsme-twitter-embed', style: 'overflow: hidden; width: 325px; border-radius: 12px;' }),\n\n [\n 'blockquote',\n { class: 'twitter-tweet' },\n ['a', { href: HTMLAttributes.src ?? HTMLAttributes.url }, ''],\n ],\n [\n 'script',\n {\n async: true,\n src: 'https://platform.twitter.com/widgets.js',\n charset: 'utf-8',\n },\n ],\n ]\n ]\n ]\n },\n\n addNodeView() {\n return ReactNodeViewRenderer(TwitterEmbed)\n },\n\n addCommands() {\n return {\n insertTwitter:\n (url, className) =>\n ({ commands, state }) => {\n let formattedUrl = url\n if (url) {\n\n const tweetMatch = url.match(/(?:twitter\\.com|x\\.com)\\/([^\\/]+)\\/status\\/(\\d+)/)\n if (tweetMatch) {\n const [_, username, tweetId] = tweetMatch\n formattedUrl = `https://twitter.com/${username}/status/${tweetId}`\n }\n }\n return commands.insertContent({\n type: 'twitter',\n attrs: {\n url: url,\n class: className,\n src: formattedUrl,\n },\n })\n },\n }\n },\n})\n\nfunction isValidHttpUrl(string: string) {\n let url\n\n try {\n url = new URL(string)\n } catch (_) {\n return false\n }\n\n return url.protocol === 'http:' || url.protocol === 'https:'\n}\n"],"names":["Node","mergeAttributes","ReactNodeViewRenderer","TwitterEmbed","Twitter","create","name","group","content","draggable","parseHTML","tag","addAttributes","url","default","src","class","addKeyboardShortcuts","editor","chain","insertContentAt","state","selection","head","type","focus","run","renderHTML","HTMLAttributes","style","href","async","charset","addNodeView","addCommands","insertTwitter","className","commands","formattedUrl","tweetMatch","match","_","username","tweetId","insertContent","attrs","isValidHttpUrl","string","URL","protocol"],"mappings":"AAYA,SAASA,IAAI,EAA4BC,eAAe,QAAQ,eAAc;AAC9E,SAASC,qBAAqB,QAAQ,gBAAe;AACrD,OAAOC,kBAAkB,oBAAmB;AAE5C,OAAO,MAAMC,UAAUJ,KAAKK,MAAM,CAAC;IACjCC,MAAM;IAENC,OAAO;IACPC,SAAS;IACTC,WAAW;IAEX,sBAAsB;IAEtBC;QACE,OAAO;YACL;gBACEC,KAAK;YACP;SACD;IACH;IAEAC;QACE,OAAO;YACLC,KAAK;gBAAEC,SAAS;YAAK;YACrBC,KAAK;gBAAED,SAAS;YAAK;YACrBE,OAAO;gBAAEF,SAAS;YAAK;QACzB;IACF;IAEAG;QACE,OAAO;YACL,aAAa;gBACX,OAAO,IAAI,CAACC,MAAM,CACfC,KAAK,GACLC,eAAe,CAAC,IAAI,CAACF,MAAM,CAACG,KAAK,CAACC,SAAS,CAACC,IAAI,EAAE;oBACjDC,MAAM,IAAI,CAACA,IAAI,CAAClB,IAAI;gBACtB,GACCmB,KAAK,GACLC,GAAG;YACR;QACF;IACF;IAEA,mCAAmC;IACnC,aAAa;IACb,aAAa;IACb,mEAAmE;IACnE,SAAS;IACT,OAAO;IACP,KAAK;IACLC,YAAW,EAAEC,cAAc,EAAE;QAC3B,OAAO;YACL;YACA3B,gBAAgB2B,gBAAgB;gBAC9B,aAAa;gBACbZ,OAAO,CAAC,4BAA4B,EAAEY,eAAeZ,KAAK,IAAI,GAAG,CAAC;YACpE;YAAI;gBACF;gBACAf,gBACE;oBAAEe,OAAO;gBAAuB;gBAElC;oBAAC;oBAAOf,gBAAgB;wBAAEe,OAAO;wBAAiCa,OAAO;oBAAuD;oBAE9H;wBACE;wBACA;4BAAEb,OAAO;wBAAgB;wBACzB;4BAAC;4BAAK;gCAAEc,MAAMF,eAAeb,GAAG,IAAIa,eAAef,GAAG;4BAAC;4BAAG;yBAAG;qBAC9D;oBACD;wBACE;wBACA;4BACEkB,OAAO;4BACPhB,KAAK;4BACLiB,SAAS;wBACX;qBACD;iBACF;aACF;SACF;IACH;IAEAC;QACE,OAAO/B,sBAAsBC;IAC/B;IAEA+B;QACE,OAAO;YACLC,eACE,CAACtB,KAAKuB,YACJ,CAAC,EAAEC,QAAQ,EAAEhB,KAAK,EAAE;oBAClB,IAAIiB,eAAezB;oBACnB,IAAIA,KAAK;wBAEP,MAAM0B,aAAa1B,IAAI2B,KAAK,CAAC;wBAC7B,IAAID,YAAY;4BACd,MAAM,CAACE,GAAGC,UAAUC,QAAQ,GAAGJ;4BAC/BD,eAAe,CAAC,oBAAoB,EAAEI,SAAS,QAAQ,EAAEC,QAAQ,CAAC;wBACpE;oBACF;oBACA,OAAON,SAASO,aAAa,CAAC;wBAC5BpB,MAAM;wBACNqB,OAAO;4BACLhC,KAAKA;4BACLG,OAAOoB;4BACPrB,KAAKuB;wBACP;oBACF;gBACF;QACN;IACF;AACF,GAAE;AAEF,SAASQ,eAAeC,MAAc;IACpC,IAAIlC;IAEJ,IAAI;QACFA,MAAM,IAAImC,IAAID;IAChB,EAAE,OAAON,GAAG;QACV,OAAO;IACT;IAEA,OAAO5B,IAAIoC,QAAQ,KAAK,WAAWpC,IAAIoC,QAAQ,KAAK;AACtD"}
1
+ {"version":3,"sources":["../../../../../../../src/fields/TiptapEditor/extensions/SocialMedia/Twitter/twitter.ts"],"sourcesContent":["declare module '@tiptap/core' {\n interface Commands<ReturnType> {\n twitter: {\n /**\n * Add an image\n */\n\n insertTwitter: (url?: string, className?: string) => ReturnType\n }\n }\n}\n\nimport { Node, PasteRule, markPasteRule, mergeAttributes } from '@tiptap/core'\nimport { ReactNodeViewRenderer } from '@tiptap/react'\nimport TwitterEmbed from './TwitterEmbed.js'\n\nexport const Twitter = Node.create({\n name: 'twitter',\n\n group: 'block',\n content: 'inline*',\n draggable: true,\n\n // content: 'inline*',\n\n parseHTML() {\n return [\n {\n tag: 'div[data-type=\"twitter\"]',\n },\n ]\n },\n\n addAttributes() {\n return {\n url: { default: null },\n src: { default: null },\n class: { default: null },\n }\n },\n\n addKeyboardShortcuts() {\n return {\n 'Mod-Enter': () => {\n return this.editor\n .chain()\n .insertContentAt(this.editor.state.selection.head, {\n type: this.type.name,\n })\n .focus()\n .run()\n },\n }\n },\n\n // renderHTML({ HTMLAttributes }) {\n // return [\n // \"div\",\n // mergeAttributes(HTMLAttributes, { \"data-type\": \"twitter\" }),\n // 0,\n // ];\n // },\n renderHTML({ HTMLAttributes }) {\n return [\n \"div\",\n mergeAttributes(HTMLAttributes, {\n \"data-type\": \"twitter\",\n class: `react-renderer node-twitter ${HTMLAttributes.class ?? \"\"}`,\n }), [\n 'div',\n mergeAttributes(\n { class: 'socialMediaContainer' },\n ),\n ['div', mergeAttributes({ class: 'rsme-embed rsme-twitter-embed', style: 'overflow: hidden; width: 325px; border-radius: 12px;' }),\n\n [\n 'blockquote',\n { class: 'twitter-tweet' },\n ['a', { href: convertYoutubeUrlToEmbed(HTMLAttributes.url) ?? HTMLAttributes.src }, ''],\n ],\n [\n 'script',\n {\n async: true,\n src: 'https://platform.twitter.com/widgets.js',\n charset: 'utf-8',\n },\n ],\n ]\n ]\n ]\n },\n\n addNodeView() {\n return ReactNodeViewRenderer(TwitterEmbed)\n },\n\n addCommands() {\n return {\n insertTwitter:\n (url, className) =>\n ({ commands, state }) => {\n let formattedUrl = url\n if (url) {\n\n formattedUrl = convertYoutubeUrlToEmbed(url)\n }\n return commands.insertContent({\n type: 'twitter',\n attrs: {\n url: url,\n class: className,\n src: formattedUrl,\n },\n })\n },\n }\n },\n})\n\nfunction convertYoutubeUrlToEmbed(url: string): string | undefined {\n if (!url) return undefined;\n try {\n let formattedUrl\n const tweetMatch = url.match(/(?:twitter\\.com|x\\.com)\\/([^\\/]+)\\/status\\/(\\d+)/)\n if (tweetMatch) {\n const [_, username, tweetId] = tweetMatch\n formattedUrl = `https://twitter.com/${username}/status/${tweetId}`\n }\n return formattedUrl ? formattedUrl : undefined;\n } catch {\n return undefined;\n }\n}\nfunction isValidHttpUrl(string: string) {\n let url\n\n try {\n url = new URL(string)\n } catch (_) {\n return false\n }\n\n return url.protocol === 'http:' || url.protocol === 'https:'\n}\n"],"names":["Node","mergeAttributes","ReactNodeViewRenderer","TwitterEmbed","Twitter","create","name","group","content","draggable","parseHTML","tag","addAttributes","url","default","src","class","addKeyboardShortcuts","editor","chain","insertContentAt","state","selection","head","type","focus","run","renderHTML","HTMLAttributes","style","href","convertYoutubeUrlToEmbed","async","charset","addNodeView","addCommands","insertTwitter","className","commands","formattedUrl","insertContent","attrs","undefined","tweetMatch","match","_","username","tweetId","isValidHttpUrl","string","URL","protocol"],"mappings":"AAYA,SAASA,IAAI,EAA4BC,eAAe,QAAQ,eAAc;AAC9E,SAASC,qBAAqB,QAAQ,gBAAe;AACrD,OAAOC,kBAAkB,oBAAmB;AAE5C,OAAO,MAAMC,UAAUJ,KAAKK,MAAM,CAAC;IACjCC,MAAM;IAENC,OAAO;IACPC,SAAS;IACTC,WAAW;IAEX,sBAAsB;IAEtBC;QACE,OAAO;YACL;gBACEC,KAAK;YACP;SACD;IACH;IAEAC;QACE,OAAO;YACLC,KAAK;gBAAEC,SAAS;YAAK;YACrBC,KAAK;gBAAED,SAAS;YAAK;YACrBE,OAAO;gBAAEF,SAAS;YAAK;QACzB;IACF;IAEAG;QACE,OAAO;YACL,aAAa;gBACX,OAAO,IAAI,CAACC,MAAM,CACfC,KAAK,GACLC,eAAe,CAAC,IAAI,CAACF,MAAM,CAACG,KAAK,CAACC,SAAS,CAACC,IAAI,EAAE;oBACjDC,MAAM,IAAI,CAACA,IAAI,CAAClB,IAAI;gBACtB,GACCmB,KAAK,GACLC,GAAG;YACR;QACF;IACF;IAEA,mCAAmC;IACnC,aAAa;IACb,aAAa;IACb,mEAAmE;IACnE,SAAS;IACT,OAAO;IACP,KAAK;IACLC,YAAW,EAAEC,cAAc,EAAE;QAC3B,OAAO;YACL;YACA3B,gBAAgB2B,gBAAgB;gBAC9B,aAAa;gBACbZ,OAAO,CAAC,4BAA4B,EAAEY,eAAeZ,KAAK,IAAI,GAAG,CAAC;YACpE;YAAI;gBACF;gBACAf,gBACE;oBAAEe,OAAO;gBAAuB;gBAElC;oBAAC;oBAAOf,gBAAgB;wBAAEe,OAAO;wBAAiCa,OAAO;oBAAuD;oBAE9H;wBACE;wBACA;4BAAEb,OAAO;wBAAgB;wBACzB;4BAAC;4BAAK;gCAAEc,MAAMC,yBAAyBH,eAAef,GAAG,KAAKe,eAAeb,GAAG;4BAAC;4BAAG;yBAAG;qBACxF;oBACD;wBACE;wBACA;4BACEiB,OAAO;4BACPjB,KAAK;4BACLkB,SAAS;wBACX;qBACD;iBACF;aACF;SACF;IACH;IAEAC;QACE,OAAOhC,sBAAsBC;IAC/B;IAEAgC;QACE,OAAO;YACLC,eACE,CAACvB,KAAKwB,YACJ,CAAC,EAAEC,QAAQ,EAAEjB,KAAK,EAAE;oBAClB,IAAIkB,eAAe1B;oBACnB,IAAIA,KAAK;wBAEP0B,eAAeR,yBAAyBlB;oBAC1C;oBACA,OAAOyB,SAASE,aAAa,CAAC;wBAC5BhB,MAAM;wBACNiB,OAAO;4BACL5B,KAAKA;4BACLG,OAAOqB;4BACPtB,KAAKwB;wBACP;oBACF;gBACF;QACN;IACF;AACF,GAAE;AAEF,SAASR,yBAAyBlB,GAAW;IAC3C,IAAI,CAACA,KAAK,OAAO6B;IACjB,IAAI;QACF,IAAIH;QACJ,MAAMI,aAAa9B,IAAI+B,KAAK,CAAC;QAC7B,IAAID,YAAY;YACd,MAAM,CAACE,GAAGC,UAAUC,QAAQ,GAAGJ;YAC/BJ,eAAe,CAAC,oBAAoB,EAAEO,SAAS,QAAQ,EAAEC,QAAQ,CAAC;QACpE;QACA,OAAOR,eAAeA,eAAeG;IACvC,EAAE,OAAM;QACN,OAAOA;IACT;AACF;AACA,SAASM,eAAeC,MAAc;IACpC,IAAIpC;IAEJ,IAAI;QACFA,MAAM,IAAIqC,IAAID;IAChB,EAAE,OAAOJ,GAAG;QACV,OAAO;IACT;IAEA,OAAOhC,IAAIsC,QAAQ,KAAK,WAAWtC,IAAIsC,QAAQ,KAAK;AACtD"}
@@ -1 +1 @@
1
- {"version":3,"file":"youtube.d.ts","sourceRoot":"","sources":["../../../../../../../src/fields/TiptapEditor/extensions/SocialMedia/Youtube/youtube.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,cAAc,CAAC;IAC5B,UAAU,QAAQ,CAAC,UAAU;QAC3B,OAAO,EAAE;YACP;;eAEG;YAEH,aAAa,EAAE,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,KAAK,UAAU,CAAA;SAChE,CAAA;KACF;CACF;AAED,OAAO,EAAE,IAAI,EAA6C,MAAM,cAAc,CAAA;AAI9E,eAAO,MAAM,OAAO,gBA0HlB,CAAA"}
1
+ {"version":3,"file":"youtube.d.ts","sourceRoot":"","sources":["../../../../../../../src/fields/TiptapEditor/extensions/SocialMedia/Youtube/youtube.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,cAAc,CAAC;IAC5B,UAAU,QAAQ,CAAC,UAAU;QAC3B,OAAO,EAAE;YACP;;eAEG;YAEH,aAAa,EAAE,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,KAAK,UAAU,CAAA;SAChE,CAAA;KACF;CACF;AAED,OAAO,EAAE,IAAI,EAA6C,MAAM,cAAc,CAAA;AAI9E,eAAO,MAAM,OAAO,gBAgGlB,CAAA"}
@@ -74,7 +74,7 @@ export const Youtube = Node.create({
74
74
  [
75
75
  'iframe',
76
76
  mergeAttributes({
77
- src: HTMLAttributes.src
77
+ src: convertYoutubeUrlToEmbed(HTMLAttributes.url)
78
78
  }, HTMLAttributes)
79
79
  ]
80
80
  ]
@@ -90,28 +90,7 @@ export const Youtube = Node.create({
90
90
  insertYoutube: (url, className)=>({ commands, state })=>{
91
91
  let embedUrl = '';
92
92
  if (url) {
93
- // Extract video ID from various YouTube URL formats
94
- const urlObj = new URL(url);
95
- let videoId = '';
96
- if (urlObj.hostname === 'youtu.be') {
97
- // Handle youtu.be format
98
- videoId = urlObj.pathname.slice(1);
99
- } else {
100
- // Handle youtube.com formats
101
- const searchParams = new URLSearchParams(urlObj.search);
102
- videoId = searchParams.get('v') || '';
103
- if (!videoId) {
104
- // Try extracting from pathname for embed URLs
105
- const matches = urlObj.pathname.match(/\/embed\/([^/?]+)/);
106
- if (matches) {
107
- videoId = matches[1];
108
- }
109
- }
110
- }
111
- if (videoId) {
112
- // Convert to embed URL
113
- embedUrl = `https://www.youtube.com/embed/${videoId}`;
114
- }
93
+ embedUrl = convertYoutubeUrlToEmbed(url);
115
94
  }
116
95
  return commands.insertContent({
117
96
  type: 'youtube',
@@ -125,6 +104,32 @@ export const Youtube = Node.create({
125
104
  };
126
105
  }
127
106
  });
107
+ function convertYoutubeUrlToEmbed(url) {
108
+ if (!url) return undefined;
109
+ try {
110
+ // Extract video ID from various YouTube URL formats
111
+ const urlObj = new URL(url);
112
+ let videoId = '';
113
+ if (urlObj.hostname === 'youtu.be') {
114
+ // Handle youtu.be format
115
+ videoId = urlObj.pathname.slice(1);
116
+ } else {
117
+ // Handle youtube.com formats
118
+ const searchParams = new URLSearchParams(urlObj.search);
119
+ videoId = searchParams.get('v') || '';
120
+ if (!videoId) {
121
+ // Try extracting from pathname for embed URLs
122
+ const matches = urlObj.pathname.match(/\/embed\/([^/?]+)/);
123
+ if (matches) {
124
+ videoId = matches[1];
125
+ }
126
+ }
127
+ }
128
+ return videoId ? `https://www.youtube.com/embed/${videoId}` : undefined;
129
+ } catch {
130
+ return undefined;
131
+ }
132
+ }
128
133
  function isValidHttpUrl(string) {
129
134
  let url;
130
135
  try {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../src/fields/TiptapEditor/extensions/SocialMedia/Youtube/youtube.ts"],"sourcesContent":["declare module '@tiptap/core' {\n interface Commands<ReturnType> {\n youtube: {\n /**\n * Add an image\n */\n\n insertYoutube: (url?: string, className?: string) => ReturnType\n }\n }\n}\n\nimport { Node, PasteRule, markPasteRule, mergeAttributes } from '@tiptap/core'\nimport { ReactNodeViewRenderer } from '@tiptap/react'\nimport YoutubeEmbed from './YoutubeEmbed.js'\n\nexport const Youtube = Node.create({\n name: 'youtube',\n\n group: 'block',\n content: 'inline*',\n draggable: true,\n\n // content: 'inline*',\n parseHTML() {\n return [\n {\n tag: 'div[data-type=\"youtube\"]',\n },\n ]\n },\n addAttributes() {\n return {\n url: { default: null },\n class: { default: null },\n src: {\n default: null,\n },\n width: {\n default: '560',\n },\n height: {\n default: '315',\n },\n frameborder: {\n default: '0',\n },\n allowfullscreen: {\n default: true,\n },\n }\n },\n\n addKeyboardShortcuts() {\n return {\n 'Mod-Enter': () => {\n return this.editor\n .chain()\n .insertContentAt(this.editor.state.selection.head, {\n type: this.type.name,\n })\n .focus()\n .run()\n },\n }\n },\n\n renderHTML({ HTMLAttributes }) {\n return [\n \"div\",\n mergeAttributes(HTMLAttributes, {\n \"data-type\": \"youtube\",\n class: `react-renderer node-youtube ${HTMLAttributes.class ?? \"\"}`,\n }), [\n 'div',\n mergeAttributes(\n { class: 'socialMediaContainer' },\n ),\n ['div', mergeAttributes({ class: 'rsme-embed rsme-youtube-embed', style: 'overflow: hidden; border-radius: 0px;' }),\n ['div', { class: 'youtube-iframe' },\n ['iframe', mergeAttributes({ src: HTMLAttributes.src }, HTMLAttributes)],\n ]\n ]\n ]\n ]\n },\n addNodeView() {\n return ReactNodeViewRenderer(YoutubeEmbed)\n },\n\n addCommands() {\n return {\n insertYoutube:\n (url, className) =>\n ({ commands, state }) => {\n let embedUrl = ''\n\n if (url) {\n\n\n // Extract video ID from various YouTube URL formats\n const urlObj = new URL(url)\n let videoId = ''\n\n if (urlObj.hostname === 'youtu.be') {\n // Handle youtu.be format\n videoId = urlObj.pathname.slice(1)\n } else {\n // Handle youtube.com formats\n const searchParams = new URLSearchParams(urlObj.search)\n videoId = searchParams.get('v') || ''\n\n if (!videoId) {\n // Try extracting from pathname for embed URLs\n const matches = urlObj.pathname.match(/\\/embed\\/([^/?]+)/)\n if (matches) {\n videoId = matches[1]\n }\n }\n }\n\n if (videoId) {\n // Convert to embed URL\n embedUrl = `https://www.youtube.com/embed/${videoId}`\n }\n }\n\n return commands.insertContent({\n type: 'youtube',\n attrs: {\n url,\n class: className,\n src: embedUrl,\n },\n })\n },\n }\n },\n})\n\nfunction isValidHttpUrl(string: string) {\n let url\n\n try {\n url = new URL(string)\n } catch (_) {\n return false\n }\n\n return url.protocol === 'http:' || url.protocol === 'https:'\n}\n"],"names":["Node","mergeAttributes","ReactNodeViewRenderer","YoutubeEmbed","Youtube","create","name","group","content","draggable","parseHTML","tag","addAttributes","url","default","class","src","width","height","frameborder","allowfullscreen","addKeyboardShortcuts","editor","chain","insertContentAt","state","selection","head","type","focus","run","renderHTML","HTMLAttributes","style","addNodeView","addCommands","insertYoutube","className","commands","embedUrl","urlObj","URL","videoId","hostname","pathname","slice","searchParams","URLSearchParams","search","get","matches","match","insertContent","attrs","isValidHttpUrl","string","_","protocol"],"mappings":"AAYA,SAASA,IAAI,EAA4BC,eAAe,QAAQ,eAAc;AAC9E,SAASC,qBAAqB,QAAQ,gBAAe;AACrD,OAAOC,kBAAkB,oBAAmB;AAE5C,OAAO,MAAMC,UAAUJ,KAAKK,MAAM,CAAC;IACjCC,MAAM;IAENC,OAAO;IACPC,SAAS;IACTC,WAAW;IAEX,sBAAsB;IACtBC;QACE,OAAO;YACL;gBACEC,KAAK;YACP;SACD;IACH;IACAC;QACE,OAAO;YACLC,KAAK;gBAAEC,SAAS;YAAK;YACrBC,OAAO;gBAAED,SAAS;YAAK;YACvBE,KAAK;gBACHF,SAAS;YACX;YACAG,OAAO;gBACLH,SAAS;YACX;YACAI,QAAQ;gBACNJ,SAAS;YACX;YACAK,aAAa;gBACXL,SAAS;YACX;YACAM,iBAAiB;gBACfN,SAAS;YACX;QACF;IACF;IAEAO;QACE,OAAO;YACL,aAAa;gBACX,OAAO,IAAI,CAACC,MAAM,CACfC,KAAK,GACLC,eAAe,CAAC,IAAI,CAACF,MAAM,CAACG,KAAK,CAACC,SAAS,CAACC,IAAI,EAAE;oBACjDC,MAAM,IAAI,CAACA,IAAI,CAACtB,IAAI;gBACtB,GACCuB,KAAK,GACLC,GAAG;YACR;QACF;IACF;IAEAC,YAAW,EAAEC,cAAc,EAAE;QAC3B,OAAO;YACL;YACA/B,gBAAgB+B,gBAAgB;gBAC9B,aAAa;gBACbjB,OAAO,CAAC,6BAA6B,EAAEiB,eAAejB,KAAK,IAAI,GAAG,CAAC;YACrE;YAAI;gBACF;gBACAd,gBACE;oBAAEc,OAAO;gBAAuB;gBAElC;oBAAC;oBAAOd,gBAAgB;wBAAEc,OAAO;wBAAiCkB,OAAO;oBAAwC;oBAC/G;wBAAC;wBAAO;4BAAElB,OAAO;wBAAiB;wBAChC;4BAAC;4BAAUd,gBAAgB;gCAAEe,KAAKgB,eAAehB,GAAG;4BAAC,GAAGgB;yBAAgB;qBACzE;iBACF;aACF;SACF;IACH;IACAE;QACE,OAAOhC,sBAAsBC;IAC/B;IAEAgC;QACE,OAAO;YACLC,eACE,CAACvB,KAAKwB,YACJ,CAAC,EAAEC,QAAQ,EAAEb,KAAK,EAAE;oBAClB,IAAIc,WAAW;oBAEf,IAAI1B,KAAK;wBAGP,oDAAoD;wBACpD,MAAM2B,SAAS,IAAIC,IAAI5B;wBACvB,IAAI6B,UAAU;wBAEd,IAAIF,OAAOG,QAAQ,KAAK,YAAY;4BAClC,yBAAyB;4BACzBD,UAAUF,OAAOI,QAAQ,CAACC,KAAK,CAAC;wBAClC,OAAO;4BACL,6BAA6B;4BAC7B,MAAMC,eAAe,IAAIC,gBAAgBP,OAAOQ,MAAM;4BACtDN,UAAUI,aAAaG,GAAG,CAAC,QAAQ;4BAEnC,IAAI,CAACP,SAAS;gCACZ,8CAA8C;gCAC9C,MAAMQ,UAAUV,OAAOI,QAAQ,CAACO,KAAK,CAAC;gCACtC,IAAID,SAAS;oCACXR,UAAUQ,OAAO,CAAC,EAAE;gCACtB;4BACF;wBACF;wBAEA,IAAIR,SAAS;4BACX,uBAAuB;4BACvBH,WAAW,CAAC,8BAA8B,EAAEG,QAAQ,CAAC;wBACvD;oBACF;oBAEA,OAAOJ,SAASc,aAAa,CAAC;wBAC5BxB,MAAM;wBACNyB,OAAO;4BACLxC;4BACAE,OAAOsB;4BACPrB,KAAKuB;wBACP;oBACF;gBACF;QACN;IACF;AACF,GAAE;AAEF,SAASe,eAAeC,MAAc;IACpC,IAAI1C;IAEJ,IAAI;QACFA,MAAM,IAAI4B,IAAIc;IAChB,EAAE,OAAOC,GAAG;QACV,OAAO;IACT;IAEA,OAAO3C,IAAI4C,QAAQ,KAAK,WAAW5C,IAAI4C,QAAQ,KAAK;AACtD"}
1
+ {"version":3,"sources":["../../../../../../../src/fields/TiptapEditor/extensions/SocialMedia/Youtube/youtube.ts"],"sourcesContent":["declare module '@tiptap/core' {\n interface Commands<ReturnType> {\n youtube: {\n /**\n * Add an image\n */\n\n insertYoutube: (url?: string, className?: string) => ReturnType\n }\n }\n}\n\nimport { Node, PasteRule, markPasteRule, mergeAttributes } from '@tiptap/core'\nimport { ReactNodeViewRenderer } from '@tiptap/react'\nimport YoutubeEmbed from './YoutubeEmbed.js'\n\nexport const Youtube = Node.create({\n name: 'youtube',\n\n group: 'block',\n content: 'inline*',\n draggable: true,\n\n // content: 'inline*',\n parseHTML() {\n return [\n {\n tag: 'div[data-type=\"youtube\"]',\n },\n ]\n },\n addAttributes() {\n return {\n url: { default: null },\n class: { default: null },\n src: {\n default: null,\n },\n width: {\n default: '560',\n },\n height: {\n default: '315',\n },\n frameborder: {\n default: '0',\n },\n allowfullscreen: {\n default: true,\n },\n }\n },\n\n addKeyboardShortcuts() {\n return {\n 'Mod-Enter': () => {\n return this.editor\n .chain()\n .insertContentAt(this.editor.state.selection.head, {\n type: this.type.name,\n })\n .focus()\n .run()\n },\n }\n },\n\n renderHTML({ HTMLAttributes }) {\n return [\n \"div\",\n mergeAttributes(HTMLAttributes, {\n \"data-type\": \"youtube\",\n class: `react-renderer node-youtube ${HTMLAttributes.class ?? \"\"}`,\n }), [\n 'div',\n mergeAttributes(\n { class: 'socialMediaContainer' },\n ),\n ['div', mergeAttributes({ class: 'rsme-embed rsme-youtube-embed', style: 'overflow: hidden; border-radius: 0px;' }),\n ['div', { class: 'youtube-iframe' },\n ['iframe', mergeAttributes({ src: convertYoutubeUrlToEmbed(HTMLAttributes.url) }, HTMLAttributes)],\n ]\n ]\n ]\n ]\n },\n addNodeView() {\n return ReactNodeViewRenderer(YoutubeEmbed)\n },\n\n addCommands() {\n return {\n insertYoutube:\n (url, className) =>\n ({ commands, state }) => {\n let embedUrl = ''\n\n if (url) {\n embedUrl = convertYoutubeUrlToEmbed(url)\n }\n\n return commands.insertContent({\n type: 'youtube',\n attrs: {\n url,\n class: className,\n src: embedUrl,\n },\n })\n },\n }\n },\n})\n\n\n\n\n\nfunction convertYoutubeUrlToEmbed(url: string): string | undefined {\n if (!url) return undefined;\n try {\n // Extract video ID from various YouTube URL formats\n const urlObj = new URL(url)\n let videoId = ''\n\n if (urlObj.hostname === 'youtu.be') {\n // Handle youtu.be format\n videoId = urlObj.pathname.slice(1)\n } else {\n // Handle youtube.com formats\n const searchParams = new URLSearchParams(urlObj.search)\n videoId = searchParams.get('v') || ''\n\n if (!videoId) {\n // Try extracting from pathname for embed URLs\n const matches = urlObj.pathname.match(/\\/embed\\/([^/?]+)/)\n if (matches) {\n videoId = matches[1]\n }\n }\n }\n\n return videoId ? `https://www.youtube.com/embed/${videoId}` : undefined;\n } catch {\n return undefined;\n }\n}\nfunction isValidHttpUrl(string: string) {\n let url\n\n try {\n url = new URL(string)\n } catch (_) {\n return false\n }\n\n return url.protocol === 'http:' || url.protocol === 'https:'\n}\n"],"names":["Node","mergeAttributes","ReactNodeViewRenderer","YoutubeEmbed","Youtube","create","name","group","content","draggable","parseHTML","tag","addAttributes","url","default","class","src","width","height","frameborder","allowfullscreen","addKeyboardShortcuts","editor","chain","insertContentAt","state","selection","head","type","focus","run","renderHTML","HTMLAttributes","style","convertYoutubeUrlToEmbed","addNodeView","addCommands","insertYoutube","className","commands","embedUrl","insertContent","attrs","undefined","urlObj","URL","videoId","hostname","pathname","slice","searchParams","URLSearchParams","search","get","matches","match","isValidHttpUrl","string","_","protocol"],"mappings":"AAYA,SAASA,IAAI,EAA4BC,eAAe,QAAQ,eAAc;AAC9E,SAASC,qBAAqB,QAAQ,gBAAe;AACrD,OAAOC,kBAAkB,oBAAmB;AAE5C,OAAO,MAAMC,UAAUJ,KAAKK,MAAM,CAAC;IACjCC,MAAM;IAENC,OAAO;IACPC,SAAS;IACTC,WAAW;IAEX,sBAAsB;IACtBC;QACE,OAAO;YACL;gBACEC,KAAK;YACP;SACD;IACH;IACAC;QACE,OAAO;YACLC,KAAK;gBAAEC,SAAS;YAAK;YACrBC,OAAO;gBAAED,SAAS;YAAK;YACvBE,KAAK;gBACHF,SAAS;YACX;YACAG,OAAO;gBACLH,SAAS;YACX;YACAI,QAAQ;gBACNJ,SAAS;YACX;YACAK,aAAa;gBACXL,SAAS;YACX;YACAM,iBAAiB;gBACfN,SAAS;YACX;QACF;IACF;IAEAO;QACE,OAAO;YACL,aAAa;gBACX,OAAO,IAAI,CAACC,MAAM,CACfC,KAAK,GACLC,eAAe,CAAC,IAAI,CAACF,MAAM,CAACG,KAAK,CAACC,SAAS,CAACC,IAAI,EAAE;oBACjDC,MAAM,IAAI,CAACA,IAAI,CAACtB,IAAI;gBACtB,GACCuB,KAAK,GACLC,GAAG;YACR;QACF;IACF;IAEAC,YAAW,EAAEC,cAAc,EAAE;QAC3B,OAAO;YACL;YACA/B,gBAAgB+B,gBAAgB;gBAC9B,aAAa;gBACbjB,OAAO,CAAC,6BAA6B,EAAEiB,eAAejB,KAAK,IAAI,GAAG,CAAC;YACrE;YAAI;gBACF;gBACAd,gBACE;oBAAEc,OAAO;gBAAuB;gBAElC;oBAAC;oBAAOd,gBAAgB;wBAAEc,OAAO;wBAAiCkB,OAAO;oBAAwC;oBAC/G;wBAAC;wBAAO;4BAAElB,OAAO;wBAAiB;wBAChC;4BAAC;4BAAUd,gBAAgB;gCAAEe,KAAKkB,yBAAyBF,eAAenB,GAAG;4BAAE,GAAGmB;yBAAgB;qBACnG;iBACF;aACF;SACF;IACH;IACAG;QACE,OAAOjC,sBAAsBC;IAC/B;IAEAiC;QACE,OAAO;YACLC,eACE,CAACxB,KAAKyB,YACJ,CAAC,EAAEC,QAAQ,EAAEd,KAAK,EAAE;oBAClB,IAAIe,WAAW;oBAEf,IAAI3B,KAAK;wBACP2B,WAAWN,yBAAyBrB;oBACtC;oBAEA,OAAO0B,SAASE,aAAa,CAAC;wBAC5Bb,MAAM;wBACNc,OAAO;4BACL7B;4BACAE,OAAOuB;4BACPtB,KAAKwB;wBACP;oBACF;gBACF;QACN;IACF;AACF,GAAE;AAMF,SAASN,yBAAyBrB,GAAW;IAC3C,IAAI,CAACA,KAAK,OAAO8B;IACjB,IAAI;QACF,oDAAoD;QACpD,MAAMC,SAAS,IAAIC,IAAIhC;QACvB,IAAIiC,UAAU;QAEd,IAAIF,OAAOG,QAAQ,KAAK,YAAY;YAClC,yBAAyB;YACzBD,UAAUF,OAAOI,QAAQ,CAACC,KAAK,CAAC;QAClC,OAAO;YACL,6BAA6B;YAC7B,MAAMC,eAAe,IAAIC,gBAAgBP,OAAOQ,MAAM;YACtDN,UAAUI,aAAaG,GAAG,CAAC,QAAQ;YAEnC,IAAI,CAACP,SAAS;gBACZ,8CAA8C;gBAC9C,MAAMQ,UAAUV,OAAOI,QAAQ,CAACO,KAAK,CAAC;gBACtC,IAAID,SAAS;oBACXR,UAAUQ,OAAO,CAAC,EAAE;gBACtB;YACF;QACF;QAEA,OAAOR,UAAU,CAAC,8BAA8B,EAAEA,QAAQ,CAAC,GAAGH;IAChE,EAAE,OAAM;QACN,OAAOA;IACT;AACF;AACA,SAASa,eAAeC,MAAc;IACpC,IAAI5C;IAEJ,IAAI;QACFA,MAAM,IAAIgC,IAAIY;IAChB,EAAE,OAAOC,GAAG;QACV,OAAO;IACT;IAEA,OAAO7C,IAAI8C,QAAQ,KAAK,WAAW9C,IAAI8C,QAAQ,KAAK;AACtD"}