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.
- package/dist/src/fields/TiptapEditor/extensions/SocialMedia/Instagram/instagram.d.ts.map +1 -1
- package/dist/src/fields/TiptapEditor/extensions/SocialMedia/Instagram/instagram.js +15 -9
- package/dist/src/fields/TiptapEditor/extensions/SocialMedia/Instagram/instagram.js.map +1 -1
- package/dist/src/fields/TiptapEditor/extensions/SocialMedia/Tiktok/tiktok.d.ts.map +1 -1
- package/dist/src/fields/TiptapEditor/extensions/SocialMedia/Tiktok/tiktok.js +14 -10
- package/dist/src/fields/TiptapEditor/extensions/SocialMedia/Tiktok/tiktok.js.map +1 -1
- package/dist/src/fields/TiptapEditor/extensions/SocialMedia/Twitter/twitter.d.ts.map +1 -1
- package/dist/src/fields/TiptapEditor/extensions/SocialMedia/Twitter/twitter.js +16 -6
- package/dist/src/fields/TiptapEditor/extensions/SocialMedia/Twitter/twitter.js.map +1 -1
- package/dist/src/fields/TiptapEditor/extensions/SocialMedia/Youtube/youtube.d.ts.map +1 -1
- package/dist/src/fields/TiptapEditor/extensions/SocialMedia/Youtube/youtube.js +28 -23
- package/dist/src/fields/TiptapEditor/extensions/SocialMedia/Youtube/youtube.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
|
@@ -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,
|
|
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.
|
|
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
|
-
|
|
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.
|
|
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,
|
|
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.
|
|
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
|
-
|
|
96
|
-
|
|
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.
|
|
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,
|
|
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.
|
|
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
|
-
|
|
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.
|
|
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,
|
|
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.
|
|
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
|
-
|
|
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.
|
|
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":"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"}
|