@tiptap/extension-youtube 2.0.0-beta.5 → 2.0.0-beta.6
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/packages/extension-youtube/src/utils.d.ts +3 -1
- package/dist/packages/extension-youtube/src/youtube.d.ts +6 -5
- package/dist/tiptap-extension-youtube.cjs.js +21 -4
- package/dist/tiptap-extension-youtube.cjs.js.map +1 -1
- package/dist/tiptap-extension-youtube.esm.js +22 -5
- package/dist/tiptap-extension-youtube.esm.js.map +1 -1
- package/dist/tiptap-extension-youtube.umd.js +21 -4
- package/dist/tiptap-extension-youtube.umd.js.map +1 -1
- package/package.json +2 -2
- package/src/utils.ts +4 -1
- package/src/youtube.ts +28 -10
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
export declare const YOUTUBE_REGEX: RegExp;
|
|
2
|
+
export declare const YOUTUBE_REGEX_GLOBAL: RegExp;
|
|
1
3
|
export declare const isValidYoutubeUrl: (url: string) => RegExpMatchArray | null;
|
|
2
4
|
export interface GetEmbedUrlOptions {
|
|
3
5
|
url: string;
|
|
@@ -5,5 +7,5 @@ export interface GetEmbedUrlOptions {
|
|
|
5
7
|
nocookie?: boolean;
|
|
6
8
|
startAt?: number;
|
|
7
9
|
}
|
|
8
|
-
export declare const getYoutubeEmbedUrl: (nocookie?: boolean
|
|
10
|
+
export declare const getYoutubeEmbedUrl: (nocookie?: boolean) => "https://www.youtube-nocookie.com/embed/" | "https://www.youtube.com/embed/";
|
|
9
11
|
export declare const getEmbedURLFromYoutubeURL: (options: GetEmbedUrlOptions) => string | null;
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { Node } from '@tiptap/core';
|
|
2
2
|
export interface YoutubeOptions {
|
|
3
|
-
|
|
4
|
-
width: number;
|
|
5
|
-
height: number;
|
|
6
|
-
controls: boolean;
|
|
7
|
-
nocookie: boolean;
|
|
3
|
+
addPasteHandler: boolean;
|
|
8
4
|
allowFullscreen: boolean;
|
|
5
|
+
controls: boolean;
|
|
6
|
+
height: number;
|
|
9
7
|
HTMLAttributes: Record<string, any>;
|
|
8
|
+
inline: boolean;
|
|
9
|
+
nocookie: boolean;
|
|
10
|
+
width: number;
|
|
10
11
|
}
|
|
11
12
|
declare module '@tiptap/core' {
|
|
12
13
|
interface Commands<ReturnType> {
|
|
@@ -4,8 +4,10 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
4
4
|
|
|
5
5
|
var core = require('@tiptap/core');
|
|
6
6
|
|
|
7
|
+
const YOUTUBE_REGEX = /^(https?:\/\/)?(www\.|music\.)?(youtube\.com|youtu\.be)(.+)?$/;
|
|
8
|
+
const YOUTUBE_REGEX_GLOBAL = /^(https?:\/\/)?(www\.|music\.)?(youtube\.com|youtu\.be)(.+)?$/g;
|
|
7
9
|
const isValidYoutubeUrl = (url) => {
|
|
8
|
-
return url.match(
|
|
10
|
+
return url.match(YOUTUBE_REGEX);
|
|
9
11
|
};
|
|
10
12
|
const getYoutubeEmbedUrl = (nocookie) => {
|
|
11
13
|
return nocookie ? 'https://www.youtube-nocookie.com/embed/' : 'https://www.youtube.com/embed/';
|
|
@@ -47,13 +49,14 @@ const Youtube = core.Node.create({
|
|
|
47
49
|
name: 'youtube',
|
|
48
50
|
addOptions() {
|
|
49
51
|
return {
|
|
50
|
-
|
|
52
|
+
addPasteHandler: true,
|
|
53
|
+
allowFullscreen: false,
|
|
51
54
|
controls: true,
|
|
55
|
+
height: 480,
|
|
52
56
|
HTMLAttributes: {},
|
|
57
|
+
inline: false,
|
|
53
58
|
nocookie: false,
|
|
54
|
-
allowFullscreen: false,
|
|
55
59
|
width: 640,
|
|
56
|
-
height: 480,
|
|
57
60
|
};
|
|
58
61
|
},
|
|
59
62
|
inline() {
|
|
@@ -99,6 +102,20 @@ const Youtube = core.Node.create({
|
|
|
99
102
|
},
|
|
100
103
|
};
|
|
101
104
|
},
|
|
105
|
+
addPasteRules() {
|
|
106
|
+
if (!this.options.addPasteHandler) {
|
|
107
|
+
return [];
|
|
108
|
+
}
|
|
109
|
+
return [
|
|
110
|
+
core.nodePasteRule({
|
|
111
|
+
find: YOUTUBE_REGEX_GLOBAL,
|
|
112
|
+
type: this.type,
|
|
113
|
+
getAttributes: match => {
|
|
114
|
+
return { src: match.input };
|
|
115
|
+
},
|
|
116
|
+
}),
|
|
117
|
+
];
|
|
118
|
+
},
|
|
102
119
|
renderHTML({ HTMLAttributes }) {
|
|
103
120
|
const embedUrl = getEmbedURLFromYoutubeURL({
|
|
104
121
|
url: HTMLAttributes.src,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tiptap-extension-youtube.cjs.js","sources":["../src/utils.ts","../src/youtube.ts"],"sourcesContent":["export const
|
|
1
|
+
{"version":3,"file":"tiptap-extension-youtube.cjs.js","sources":["../src/utils.ts","../src/youtube.ts"],"sourcesContent":["export const YOUTUBE_REGEX = /^(https?:\\/\\/)?(www\\.|music\\.)?(youtube\\.com|youtu\\.be)(.+)?$/\nexport const YOUTUBE_REGEX_GLOBAL = /^(https?:\\/\\/)?(www\\.|music\\.)?(youtube\\.com|youtu\\.be)(.+)?$/g\n\nexport const isValidYoutubeUrl = (url: string) => {\n return url.match(YOUTUBE_REGEX)\n}\n\nexport interface GetEmbedUrlOptions {\n url: string;\n controls?: boolean;\n nocookie?: boolean;\n startAt?: number;\n}\n\nexport const getYoutubeEmbedUrl = (nocookie?: boolean) => {\n return nocookie ? 'https://www.youtube-nocookie.com/embed/' : 'https://www.youtube.com/embed/'\n}\n\nexport const getEmbedURLFromYoutubeURL = (options: GetEmbedUrlOptions) => {\n const {\n url,\n controls,\n nocookie,\n startAt,\n } = options\n\n // if is already an embed url, return it\n if (url.includes('/embed/')) {\n return url\n }\n\n // if is a youtu.be url, get the id after the /\n if (url.includes('youtu.be')) {\n const id = url.split('/').pop()\n\n if (!id) {\n return null\n }\n return `${getYoutubeEmbedUrl(nocookie)}${id}`\n }\n\n const videoIdRegex = /v=([-\\w]+)/gm\n const matches = videoIdRegex.exec(url)\n\n if (!matches || !matches[1]) {\n return null\n }\n\n let outputUrl = `${getYoutubeEmbedUrl(nocookie)}${matches[1]}`\n\n const params = []\n\n if (!controls) {\n params.push('controls=0')\n }\n\n if (startAt) {\n params.push(`start=${startAt}`)\n }\n\n if (params.length) {\n outputUrl += `?${params.join('&')}`\n }\n\n return outputUrl\n}\n","import { mergeAttributes, Node, nodePasteRule } from '@tiptap/core'\n\nimport { getEmbedURLFromYoutubeURL, isValidYoutubeUrl, YOUTUBE_REGEX_GLOBAL } from './utils'\n\nexport interface YoutubeOptions {\n addPasteHandler: boolean;\n allowFullscreen: boolean;\n controls: boolean;\n height: number;\n HTMLAttributes: Record<string, any>,\n inline: boolean;\n nocookie: boolean;\n width: number;\n}\n\ndeclare module '@tiptap/core' {\n interface Commands<ReturnType> {\n youtube: {\n /**\n * Insert a youtube video\n */\n setYoutubeVideo: (options: { src: string, width?: number, height?: number, start?: number }) => ReturnType,\n }\n }\n}\n\nexport const Youtube = Node.create<YoutubeOptions>({\n name: 'youtube',\n\n addOptions() {\n return {\n addPasteHandler: true,\n allowFullscreen: false,\n controls: true,\n height: 480,\n HTMLAttributes: {},\n inline: false,\n nocookie: false,\n width: 640,\n }\n },\n\n inline() {\n return this.options.inline\n },\n\n group() {\n return this.options.inline ? 'inline' : 'block'\n },\n\n draggable: true,\n\n addAttributes() {\n return {\n src: {\n default: null,\n },\n start: {\n default: 0,\n },\n width: {\n default: this.options.width,\n },\n height: {\n default: this.options.height,\n },\n }\n },\n\n parseHTML() {\n return [\n {\n tag: 'div[data-youtube-video] iframe',\n },\n ]\n },\n\n addCommands() {\n return {\n setYoutubeVideo: options => ({ commands }) => {\n if (!isValidYoutubeUrl(options.src)) {\n return false\n }\n\n return commands.insertContent({\n type: this.name,\n attrs: options,\n })\n },\n }\n },\n\n addPasteRules() {\n if (!this.options.addPasteHandler) {\n return []\n }\n\n return [\n nodePasteRule({\n find: YOUTUBE_REGEX_GLOBAL,\n type: this.type,\n getAttributes: match => {\n return { src: match.input }\n },\n }),\n ]\n },\n\n renderHTML({ HTMLAttributes }) {\n const embedUrl = getEmbedURLFromYoutubeURL({\n url: HTMLAttributes.src,\n controls: this.options.controls,\n nocookie: this.options.nocookie,\n startAt: HTMLAttributes.start || 0,\n })\n\n HTMLAttributes.src = embedUrl\n\n return [\n 'div',\n { 'data-youtube-video': '' },\n [\n 'iframe',\n mergeAttributes(\n this.options.HTMLAttributes,\n {\n width: this.options.width,\n height: this.options.height,\n allowfullscreen: this.options.allowFullscreen,\n },\n HTMLAttributes,\n ),\n ],\n ]\n },\n})\n"],"names":["Node","nodePasteRule","mergeAttributes"],"mappings":"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"}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import { Node, mergeAttributes } from '@tiptap/core';
|
|
1
|
+
import { Node, nodePasteRule, mergeAttributes } from '@tiptap/core';
|
|
2
2
|
|
|
3
|
+
const YOUTUBE_REGEX = /^(https?:\/\/)?(www\.|music\.)?(youtube\.com|youtu\.be)(.+)?$/;
|
|
4
|
+
const YOUTUBE_REGEX_GLOBAL = /^(https?:\/\/)?(www\.|music\.)?(youtube\.com|youtu\.be)(.+)?$/g;
|
|
3
5
|
const isValidYoutubeUrl = (url) => {
|
|
4
|
-
return url.match(
|
|
6
|
+
return url.match(YOUTUBE_REGEX);
|
|
5
7
|
};
|
|
6
8
|
const getYoutubeEmbedUrl = (nocookie) => {
|
|
7
9
|
return nocookie ? 'https://www.youtube-nocookie.com/embed/' : 'https://www.youtube.com/embed/';
|
|
@@ -43,13 +45,14 @@ const Youtube = Node.create({
|
|
|
43
45
|
name: 'youtube',
|
|
44
46
|
addOptions() {
|
|
45
47
|
return {
|
|
46
|
-
|
|
48
|
+
addPasteHandler: true,
|
|
49
|
+
allowFullscreen: false,
|
|
47
50
|
controls: true,
|
|
51
|
+
height: 480,
|
|
48
52
|
HTMLAttributes: {},
|
|
53
|
+
inline: false,
|
|
49
54
|
nocookie: false,
|
|
50
|
-
allowFullscreen: false,
|
|
51
55
|
width: 640,
|
|
52
|
-
height: 480,
|
|
53
56
|
};
|
|
54
57
|
},
|
|
55
58
|
inline() {
|
|
@@ -95,6 +98,20 @@ const Youtube = Node.create({
|
|
|
95
98
|
},
|
|
96
99
|
};
|
|
97
100
|
},
|
|
101
|
+
addPasteRules() {
|
|
102
|
+
if (!this.options.addPasteHandler) {
|
|
103
|
+
return [];
|
|
104
|
+
}
|
|
105
|
+
return [
|
|
106
|
+
nodePasteRule({
|
|
107
|
+
find: YOUTUBE_REGEX_GLOBAL,
|
|
108
|
+
type: this.type,
|
|
109
|
+
getAttributes: match => {
|
|
110
|
+
return { src: match.input };
|
|
111
|
+
},
|
|
112
|
+
}),
|
|
113
|
+
];
|
|
114
|
+
},
|
|
98
115
|
renderHTML({ HTMLAttributes }) {
|
|
99
116
|
const embedUrl = getEmbedURLFromYoutubeURL({
|
|
100
117
|
url: HTMLAttributes.src,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tiptap-extension-youtube.esm.js","sources":["../src/utils.ts","../src/youtube.ts"],"sourcesContent":["export const
|
|
1
|
+
{"version":3,"file":"tiptap-extension-youtube.esm.js","sources":["../src/utils.ts","../src/youtube.ts"],"sourcesContent":["export const YOUTUBE_REGEX = /^(https?:\\/\\/)?(www\\.|music\\.)?(youtube\\.com|youtu\\.be)(.+)?$/\nexport const YOUTUBE_REGEX_GLOBAL = /^(https?:\\/\\/)?(www\\.|music\\.)?(youtube\\.com|youtu\\.be)(.+)?$/g\n\nexport const isValidYoutubeUrl = (url: string) => {\n return url.match(YOUTUBE_REGEX)\n}\n\nexport interface GetEmbedUrlOptions {\n url: string;\n controls?: boolean;\n nocookie?: boolean;\n startAt?: number;\n}\n\nexport const getYoutubeEmbedUrl = (nocookie?: boolean) => {\n return nocookie ? 'https://www.youtube-nocookie.com/embed/' : 'https://www.youtube.com/embed/'\n}\n\nexport const getEmbedURLFromYoutubeURL = (options: GetEmbedUrlOptions) => {\n const {\n url,\n controls,\n nocookie,\n startAt,\n } = options\n\n // if is already an embed url, return it\n if (url.includes('/embed/')) {\n return url\n }\n\n // if is a youtu.be url, get the id after the /\n if (url.includes('youtu.be')) {\n const id = url.split('/').pop()\n\n if (!id) {\n return null\n }\n return `${getYoutubeEmbedUrl(nocookie)}${id}`\n }\n\n const videoIdRegex = /v=([-\\w]+)/gm\n const matches = videoIdRegex.exec(url)\n\n if (!matches || !matches[1]) {\n return null\n }\n\n let outputUrl = `${getYoutubeEmbedUrl(nocookie)}${matches[1]}`\n\n const params = []\n\n if (!controls) {\n params.push('controls=0')\n }\n\n if (startAt) {\n params.push(`start=${startAt}`)\n }\n\n if (params.length) {\n outputUrl += `?${params.join('&')}`\n }\n\n return outputUrl\n}\n","import { mergeAttributes, Node, nodePasteRule } from '@tiptap/core'\n\nimport { getEmbedURLFromYoutubeURL, isValidYoutubeUrl, YOUTUBE_REGEX_GLOBAL } from './utils'\n\nexport interface YoutubeOptions {\n addPasteHandler: boolean;\n allowFullscreen: boolean;\n controls: boolean;\n height: number;\n HTMLAttributes: Record<string, any>,\n inline: boolean;\n nocookie: boolean;\n width: number;\n}\n\ndeclare module '@tiptap/core' {\n interface Commands<ReturnType> {\n youtube: {\n /**\n * Insert a youtube video\n */\n setYoutubeVideo: (options: { src: string, width?: number, height?: number, start?: number }) => ReturnType,\n }\n }\n}\n\nexport const Youtube = Node.create<YoutubeOptions>({\n name: 'youtube',\n\n addOptions() {\n return {\n addPasteHandler: true,\n allowFullscreen: false,\n controls: true,\n height: 480,\n HTMLAttributes: {},\n inline: false,\n nocookie: false,\n width: 640,\n }\n },\n\n inline() {\n return this.options.inline\n },\n\n group() {\n return this.options.inline ? 'inline' : 'block'\n },\n\n draggable: true,\n\n addAttributes() {\n return {\n src: {\n default: null,\n },\n start: {\n default: 0,\n },\n width: {\n default: this.options.width,\n },\n height: {\n default: this.options.height,\n },\n }\n },\n\n parseHTML() {\n return [\n {\n tag: 'div[data-youtube-video] iframe',\n },\n ]\n },\n\n addCommands() {\n return {\n setYoutubeVideo: options => ({ commands }) => {\n if (!isValidYoutubeUrl(options.src)) {\n return false\n }\n\n return commands.insertContent({\n type: this.name,\n attrs: options,\n })\n },\n }\n },\n\n addPasteRules() {\n if (!this.options.addPasteHandler) {\n return []\n }\n\n return [\n nodePasteRule({\n find: YOUTUBE_REGEX_GLOBAL,\n type: this.type,\n getAttributes: match => {\n return { src: match.input }\n },\n }),\n ]\n },\n\n renderHTML({ HTMLAttributes }) {\n const embedUrl = getEmbedURLFromYoutubeURL({\n url: HTMLAttributes.src,\n controls: this.options.controls,\n nocookie: this.options.nocookie,\n startAt: HTMLAttributes.start || 0,\n })\n\n HTMLAttributes.src = embedUrl\n\n return [\n 'div',\n { 'data-youtube-video': '' },\n [\n 'iframe',\n mergeAttributes(\n this.options.HTMLAttributes,\n {\n width: this.options.width,\n height: this.options.height,\n allowfullscreen: this.options.allowFullscreen,\n },\n HTMLAttributes,\n ),\n ],\n ]\n },\n})\n"],"names":[],"mappings":"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"}
|
|
@@ -4,8 +4,10 @@
|
|
|
4
4
|
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global["@tiptap/extension-youtube"] = {}, global.core));
|
|
5
5
|
})(this, (function (exports, core) { 'use strict';
|
|
6
6
|
|
|
7
|
+
const YOUTUBE_REGEX = /^(https?:\/\/)?(www\.|music\.)?(youtube\.com|youtu\.be)(.+)?$/;
|
|
8
|
+
const YOUTUBE_REGEX_GLOBAL = /^(https?:\/\/)?(www\.|music\.)?(youtube\.com|youtu\.be)(.+)?$/g;
|
|
7
9
|
const isValidYoutubeUrl = (url) => {
|
|
8
|
-
return url.match(
|
|
10
|
+
return url.match(YOUTUBE_REGEX);
|
|
9
11
|
};
|
|
10
12
|
const getYoutubeEmbedUrl = (nocookie) => {
|
|
11
13
|
return nocookie ? 'https://www.youtube-nocookie.com/embed/' : 'https://www.youtube.com/embed/';
|
|
@@ -47,13 +49,14 @@
|
|
|
47
49
|
name: 'youtube',
|
|
48
50
|
addOptions() {
|
|
49
51
|
return {
|
|
50
|
-
|
|
52
|
+
addPasteHandler: true,
|
|
53
|
+
allowFullscreen: false,
|
|
51
54
|
controls: true,
|
|
55
|
+
height: 480,
|
|
52
56
|
HTMLAttributes: {},
|
|
57
|
+
inline: false,
|
|
53
58
|
nocookie: false,
|
|
54
|
-
allowFullscreen: false,
|
|
55
59
|
width: 640,
|
|
56
|
-
height: 480,
|
|
57
60
|
};
|
|
58
61
|
},
|
|
59
62
|
inline() {
|
|
@@ -99,6 +102,20 @@
|
|
|
99
102
|
},
|
|
100
103
|
};
|
|
101
104
|
},
|
|
105
|
+
addPasteRules() {
|
|
106
|
+
if (!this.options.addPasteHandler) {
|
|
107
|
+
return [];
|
|
108
|
+
}
|
|
109
|
+
return [
|
|
110
|
+
core.nodePasteRule({
|
|
111
|
+
find: YOUTUBE_REGEX_GLOBAL,
|
|
112
|
+
type: this.type,
|
|
113
|
+
getAttributes: match => {
|
|
114
|
+
return { src: match.input };
|
|
115
|
+
},
|
|
116
|
+
}),
|
|
117
|
+
];
|
|
118
|
+
},
|
|
102
119
|
renderHTML({ HTMLAttributes }) {
|
|
103
120
|
const embedUrl = getEmbedURLFromYoutubeURL({
|
|
104
121
|
url: HTMLAttributes.src,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tiptap-extension-youtube.umd.js","sources":["../src/utils.ts","../src/youtube.ts"],"sourcesContent":["export const
|
|
1
|
+
{"version":3,"file":"tiptap-extension-youtube.umd.js","sources":["../src/utils.ts","../src/youtube.ts"],"sourcesContent":["export const YOUTUBE_REGEX = /^(https?:\\/\\/)?(www\\.|music\\.)?(youtube\\.com|youtu\\.be)(.+)?$/\nexport const YOUTUBE_REGEX_GLOBAL = /^(https?:\\/\\/)?(www\\.|music\\.)?(youtube\\.com|youtu\\.be)(.+)?$/g\n\nexport const isValidYoutubeUrl = (url: string) => {\n return url.match(YOUTUBE_REGEX)\n}\n\nexport interface GetEmbedUrlOptions {\n url: string;\n controls?: boolean;\n nocookie?: boolean;\n startAt?: number;\n}\n\nexport const getYoutubeEmbedUrl = (nocookie?: boolean) => {\n return nocookie ? 'https://www.youtube-nocookie.com/embed/' : 'https://www.youtube.com/embed/'\n}\n\nexport const getEmbedURLFromYoutubeURL = (options: GetEmbedUrlOptions) => {\n const {\n url,\n controls,\n nocookie,\n startAt,\n } = options\n\n // if is already an embed url, return it\n if (url.includes('/embed/')) {\n return url\n }\n\n // if is a youtu.be url, get the id after the /\n if (url.includes('youtu.be')) {\n const id = url.split('/').pop()\n\n if (!id) {\n return null\n }\n return `${getYoutubeEmbedUrl(nocookie)}${id}`\n }\n\n const videoIdRegex = /v=([-\\w]+)/gm\n const matches = videoIdRegex.exec(url)\n\n if (!matches || !matches[1]) {\n return null\n }\n\n let outputUrl = `${getYoutubeEmbedUrl(nocookie)}${matches[1]}`\n\n const params = []\n\n if (!controls) {\n params.push('controls=0')\n }\n\n if (startAt) {\n params.push(`start=${startAt}`)\n }\n\n if (params.length) {\n outputUrl += `?${params.join('&')}`\n }\n\n return outputUrl\n}\n","import { mergeAttributes, Node, nodePasteRule } from '@tiptap/core'\n\nimport { getEmbedURLFromYoutubeURL, isValidYoutubeUrl, YOUTUBE_REGEX_GLOBAL } from './utils'\n\nexport interface YoutubeOptions {\n addPasteHandler: boolean;\n allowFullscreen: boolean;\n controls: boolean;\n height: number;\n HTMLAttributes: Record<string, any>,\n inline: boolean;\n nocookie: boolean;\n width: number;\n}\n\ndeclare module '@tiptap/core' {\n interface Commands<ReturnType> {\n youtube: {\n /**\n * Insert a youtube video\n */\n setYoutubeVideo: (options: { src: string, width?: number, height?: number, start?: number }) => ReturnType,\n }\n }\n}\n\nexport const Youtube = Node.create<YoutubeOptions>({\n name: 'youtube',\n\n addOptions() {\n return {\n addPasteHandler: true,\n allowFullscreen: false,\n controls: true,\n height: 480,\n HTMLAttributes: {},\n inline: false,\n nocookie: false,\n width: 640,\n }\n },\n\n inline() {\n return this.options.inline\n },\n\n group() {\n return this.options.inline ? 'inline' : 'block'\n },\n\n draggable: true,\n\n addAttributes() {\n return {\n src: {\n default: null,\n },\n start: {\n default: 0,\n },\n width: {\n default: this.options.width,\n },\n height: {\n default: this.options.height,\n },\n }\n },\n\n parseHTML() {\n return [\n {\n tag: 'div[data-youtube-video] iframe',\n },\n ]\n },\n\n addCommands() {\n return {\n setYoutubeVideo: options => ({ commands }) => {\n if (!isValidYoutubeUrl(options.src)) {\n return false\n }\n\n return commands.insertContent({\n type: this.name,\n attrs: options,\n })\n },\n }\n },\n\n addPasteRules() {\n if (!this.options.addPasteHandler) {\n return []\n }\n\n return [\n nodePasteRule({\n find: YOUTUBE_REGEX_GLOBAL,\n type: this.type,\n getAttributes: match => {\n return { src: match.input }\n },\n }),\n ]\n },\n\n renderHTML({ HTMLAttributes }) {\n const embedUrl = getEmbedURLFromYoutubeURL({\n url: HTMLAttributes.src,\n controls: this.options.controls,\n nocookie: this.options.nocookie,\n startAt: HTMLAttributes.start || 0,\n })\n\n HTMLAttributes.src = embedUrl\n\n return [\n 'div',\n { 'data-youtube-video': '' },\n [\n 'iframe',\n mergeAttributes(\n this.options.HTMLAttributes,\n {\n width: this.options.width,\n height: this.options.height,\n allowfullscreen: this.options.allowFullscreen,\n },\n HTMLAttributes,\n ),\n ],\n ]\n },\n})\n"],"names":["Node","nodePasteRule","mergeAttributes"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tiptap/extension-youtube",
|
|
3
3
|
"description": "a youtube embed extension for tiptap",
|
|
4
|
-
"version": "2.0.0-beta.
|
|
4
|
+
"version": "2.0.0-beta.6",
|
|
5
5
|
"homepage": "https://tiptap.dev",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"tiptap",
|
|
@@ -28,5 +28,5 @@
|
|
|
28
28
|
"url": "https://github.com/ueberdosis/tiptap",
|
|
29
29
|
"directory": "packages/extension-youtube"
|
|
30
30
|
},
|
|
31
|
-
"gitHead": "
|
|
31
|
+
"gitHead": "090c5a44566bcd936096574fa62bf301ab4a1285"
|
|
32
32
|
}
|
package/src/utils.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
export const YOUTUBE_REGEX = /^(https?:\/\/)?(www\.|music\.)?(youtube\.com|youtu\.be)(.+)?$/
|
|
2
|
+
export const YOUTUBE_REGEX_GLOBAL = /^(https?:\/\/)?(www\.|music\.)?(youtube\.com|youtu\.be)(.+)?$/g
|
|
3
|
+
|
|
1
4
|
export const isValidYoutubeUrl = (url: string) => {
|
|
2
|
-
return url.match(
|
|
5
|
+
return url.match(YOUTUBE_REGEX)
|
|
3
6
|
}
|
|
4
7
|
|
|
5
8
|
export interface GetEmbedUrlOptions {
|
package/src/youtube.ts
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
import { mergeAttributes, Node } from '@tiptap/core'
|
|
1
|
+
import { mergeAttributes, Node, nodePasteRule } from '@tiptap/core'
|
|
2
2
|
|
|
3
|
-
import { getEmbedURLFromYoutubeURL, isValidYoutubeUrl } from './utils'
|
|
3
|
+
import { getEmbedURLFromYoutubeURL, isValidYoutubeUrl, YOUTUBE_REGEX_GLOBAL } from './utils'
|
|
4
4
|
|
|
5
5
|
export interface YoutubeOptions {
|
|
6
|
-
|
|
7
|
-
width: number;
|
|
8
|
-
height: number;
|
|
9
|
-
controls: boolean;
|
|
10
|
-
nocookie: boolean;
|
|
6
|
+
addPasteHandler: boolean;
|
|
11
7
|
allowFullscreen: boolean;
|
|
8
|
+
controls: boolean;
|
|
9
|
+
height: number;
|
|
12
10
|
HTMLAttributes: Record<string, any>,
|
|
11
|
+
inline: boolean;
|
|
12
|
+
nocookie: boolean;
|
|
13
|
+
width: number;
|
|
13
14
|
}
|
|
14
15
|
|
|
15
16
|
declare module '@tiptap/core' {
|
|
@@ -28,13 +29,14 @@ export const Youtube = Node.create<YoutubeOptions>({
|
|
|
28
29
|
|
|
29
30
|
addOptions() {
|
|
30
31
|
return {
|
|
31
|
-
|
|
32
|
+
addPasteHandler: true,
|
|
33
|
+
allowFullscreen: false,
|
|
32
34
|
controls: true,
|
|
35
|
+
height: 480,
|
|
33
36
|
HTMLAttributes: {},
|
|
37
|
+
inline: false,
|
|
34
38
|
nocookie: false,
|
|
35
|
-
allowFullscreen: false,
|
|
36
39
|
width: 640,
|
|
37
|
-
height: 480,
|
|
38
40
|
}
|
|
39
41
|
},
|
|
40
42
|
|
|
@@ -88,6 +90,22 @@ export const Youtube = Node.create<YoutubeOptions>({
|
|
|
88
90
|
}
|
|
89
91
|
},
|
|
90
92
|
|
|
93
|
+
addPasteRules() {
|
|
94
|
+
if (!this.options.addPasteHandler) {
|
|
95
|
+
return []
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return [
|
|
99
|
+
nodePasteRule({
|
|
100
|
+
find: YOUTUBE_REGEX_GLOBAL,
|
|
101
|
+
type: this.type,
|
|
102
|
+
getAttributes: match => {
|
|
103
|
+
return { src: match.input }
|
|
104
|
+
},
|
|
105
|
+
}),
|
|
106
|
+
]
|
|
107
|
+
},
|
|
108
|
+
|
|
91
109
|
renderHTML({ HTMLAttributes }) {
|
|
92
110
|
const embedUrl = getEmbedURLFromYoutubeURL({
|
|
93
111
|
url: HTMLAttributes.src,
|