diff --git a/src/components/tiptap/HbAdminTipTap.vue b/src/components/tiptap/HbAdminTipTap.vue index eb2af3d..85845e3 100644 --- a/src/components/tiptap/HbAdminTipTap.vue +++ b/src/components/tiptap/HbAdminTipTap.vue @@ -4,14 +4,14 @@ import StarterKit from '@tiptap/starter-kit' import MenuBar from "./MenuBar" import Highlight from '@tiptap/extension-highlight' import Image from '@tiptap/extension-image' +import Video from './extension/video' import Table from '@tiptap/extension-table' import TableRow from '@tiptap/extension-table-row' import TableCell from '@tiptap/extension-table-cell' import TableHeader from '@tiptap/extension-table-header' import CodeBlockLowlight from '@tiptap/extension-code-block-lowlight' -import 'github-markdown-css' // load all highlight.js languages -import { lowlight } from 'lowlight' +import {lowlight} from 'lowlight' import CodeBlockComponent from './CodeBlockComponent.vue' @@ -38,6 +38,7 @@ const editor = useEditor({ extensions: [ StarterKit, Image, + Video, Highlight.configure({multicolor: true}), Table.configure({ resizable: true @@ -46,12 +47,12 @@ const editor = useEditor({ TableHeader, CustomTableCell, CodeBlockLowlight - .extend({ - addNodeView() { - return VueNodeViewRenderer(CodeBlockComponent) - }, - }) - .configure({ lowlight }), + .extend({ + addNodeView() { + return VueNodeViewRenderer(CodeBlockComponent) + }, + }) + .configure({lowlight}), ], }) diff --git a/src/components/tiptap/MenuBar.vue b/src/components/tiptap/MenuBar.vue index df91738..3d15e5e 100644 --- a/src/components/tiptap/MenuBar.vue +++ b/src/components/tiptap/MenuBar.vue @@ -163,6 +163,16 @@ export default { } } }, + { + icon: 'video-line', + title: '插入视频', + action: () => { + const url = window.prompt('URL') + if (url) { + props.editor.chain().focus().setVideo({ src: url }).run() + } + } + }, { type: 'divider' }, diff --git a/src/components/tiptap/extension/video.js b/src/components/tiptap/extension/video.js new file mode 100644 index 0000000..87d1400 --- /dev/null +++ b/src/components/tiptap/extension/video.js @@ -0,0 +1,82 @@ +import { + mergeAttributes, + Node, + nodeInputRule, +} from '@tiptap/core' + +// https://oss.injs.jsxww.cn/net-disk-smh/07597e2562d44311aefc82095e3f19df.mp4 +export const inputRegex = /(?:^|\s)(!\[(.+|:?)]\((\S+)(?:(?:\s+)["'](\S+)["'])?\))$/ + +export const Video = Node.create({ + name: 'video', + + addOptions() { + return { + inline: false, + HTMLAttributes: {}, + } + }, + + inline() { + return this.options.inline + }, + + group() { + return this.options.inline ? 'inline' : 'block' + }, + + draggable: false, + + addAttributes() { + return { + src: { + default: null, + }, + alt: { + default: null, + }, + title: { + default: null, + }, + } + }, + + parseHTML() { + return [ + { + tag: 'video[src]' + }, + ] + }, + + renderHTML({ HTMLAttributes }) { + return ['video', mergeAttributes(this.options.HTMLAttributes, HTMLAttributes)] + }, + + addCommands() { + return { + setVideo: options => ({ commands }) => { + return commands.insertContent({ + type: this.name, + attrs: options, + }) + }, + } + }, + + addInputRules() { + return [ + nodeInputRule({ + find: inputRegex, + type: this.type, + getAttributes: match => { + const [,, alt, src, title] = match + + return { src, alt, title } + }, + }), + ] + }, +}) + +export default Video diff --git a/src/utils/imageFactory.js b/src/utils/imageFactory.js index ab0561d..92ef9f7 100644 --- a/src/utils/imageFactory.js +++ b/src/utils/imageFactory.js @@ -1,8 +1,8 @@ /** * 图片添加水印 * callback //回调方法,返回base64的图片 - * image: Image() //底图对象 - * sign: Image() //水印对象 + * image: Video() //底图对象 + * sign: Video() //水印对象 * left: Number //水印左侧位置 * top: Number //水印顶部位置 * imageWidth: Number //底图宽度 @@ -50,7 +50,7 @@ export function watermark ( /** * 图片裁剪 * callback //回调方法,返回base64的图片 - * image: Image() //底图对象 + * image: Video() //底图对象 * left: Number //裁剪左侧距离 * right: Number //裁剪右侧距离 * top: Number //裁剪顶部距离 @@ -119,7 +119,7 @@ export function cropper ( /** * 调整图片宽高 * callback //回调方法,返回base64的图片 - * image: Image() //底图对象 + * image: Video() //底图对象 * width: Number //调整的宽度 * height: Number //调整的高度 * */ @@ -157,7 +157,7 @@ export function resize ( /** * 调整图片质量 * callback //回调方法,返回base64的图片 - * image: Image() //底图对象 + * image: Video() //底图对象 * quality: Number //图片质量 0 - 1 * */ export function quality (callback, image, quality = 1) { diff --git a/src/views/image-factory-demo/index.vue b/src/views/image-factory-demo/index.vue index 41dd2f9..9aa0bf4 100644 --- a/src/views/image-factory-demo/index.vue +++ b/src/views/image-factory-demo/index.vue @@ -11,8 +11,8 @@ hljs.registerLanguage('xml', xml) const code1 = '1.首先引入 \nimport { watermark } from \'@/utils/imageFactory\' \n2.然后调用 \n/**\n' + ' * 图片添加水印\n' + ' * callback //回调方法,返回base64的图片【{success: true, data: "base64数据"}】\n' + - ' * image: Image() //底图对象\n' + - ' * sign: Image() //水印对象\n' + + ' * image: Video() //底图对象\n' + + ' * sign: Video() //水印对象\n' + ' * left: Number //水印左侧位置\n' + ' * top: Number //水印顶部位置\n' + ' * imageWidth: Number //底图宽度\n' + @@ -26,7 +26,7 @@ const code2 = '1.首先引入 \nimport { cropper } from \'@/utils/imageFactory\' '/**\n' + ' * 图片裁剪\n' + ' * callback //回调方法,返回base64的图片\n' + - ' * image: Image() //底图对象\n' + + ' * image: Video() //底图对象\n' + ' * left: Number //裁剪左侧距离\n' + ' * right: Number //裁剪右侧距离\n' + ' * top: Number //裁剪顶部距离\n' + @@ -40,7 +40,7 @@ const code3 = '1.首先引入 \nimport { resize } from \'@/utils/imageFactory\' '/**\n' + ' * 调整图片尺寸\n' + ' * callback //回调方法,返回base64的图片\n' + - ' * image: Image() //底图对象\n' + + ' * image: Video() //底图对象\n' + ' * width: Number //调整的宽度\n' + ' * height: Number //调整的高度\n' + ' * */\n' + @@ -50,7 +50,7 @@ const code4 = '1.首先引入 \nimport { quality } from \'@/utils/imageFactory\' '/**\n' + ' * 调整图片质量\n' + ' * callback //回调方法,返回base64的图片\n' + - ' * image: Image() //底图对象\n' + + ' * image: Video() //底图对象\n' + ' * quality: Number //图片质量 0 - 1\n' + ' * */\n' + 'quality(callback, image, quality)'