6 changed files with 165 additions and 7 deletions
@ -0,0 +1,6 @@ |
|||
import { Editor } from "@tiptap/core"; |
|||
|
|||
export abstract class BasePlugin { |
|||
abstract register<T = object>(editor: Editor, option?: T): void |
|||
} |
|||
export default BasePlugin |
@ -0,0 +1,130 @@ |
|||
import { |
|||
mergeAttributes, |
|||
Node, |
|||
nodeInputRule, |
|||
} from '@tiptap/core' |
|||
|
|||
export interface ImageOptions { |
|||
/** |
|||
* Controls if the image node should be inline or not. |
|||
* @default false |
|||
* @example true |
|||
*/ |
|||
inline: boolean, |
|||
|
|||
/** |
|||
* Controls if base64 images are allowed. Enable this if you want to allow |
|||
* base64 image urls in the `src` attribute. |
|||
* @default false |
|||
* @example true |
|||
*/ |
|||
allowBase64: boolean, |
|||
|
|||
/** |
|||
* HTML attributes to add to the image element. |
|||
* @default {} |
|||
* @example { class: 'foo' } |
|||
*/ |
|||
HTMLAttributes: Record<string, any>, |
|||
} |
|||
|
|||
declare module '@tiptap/core' { |
|||
interface Commands<ReturnType> { |
|||
image: { |
|||
/** |
|||
* Add an image |
|||
* @param options The image attributes |
|||
* @example |
|||
* editor |
|||
* .commands |
|||
* .setImage({ src: 'https://tiptap.dev/logo.png', alt: 'tiptap', title: 'tiptap logo' }) |
|||
*/ |
|||
setImage: (options: { src: string, alt?: string, title?: string }) => ReturnType, |
|||
} |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* Matches an image to a  on input. |
|||
*/ |
|||
export const inputRegex = /(?:^|\s)(!\[(.+|:?)]\((\S+)(?:(?:\s+)["'](\S+)["'])?\))$/ |
|||
|
|||
/** |
|||
* This extension allows you to insert images. |
|||
* @see https://www.tiptap.dev/api/nodes/image
|
|||
*/ |
|||
export const Image = Node.create<ImageOptions>({ |
|||
name: 'image', |
|||
|
|||
addOptions() { |
|||
return { |
|||
inline: false, |
|||
allowBase64: false, |
|||
HTMLAttributes: {}, |
|||
} |
|||
}, |
|||
|
|||
inline() { |
|||
return this.options.inline |
|||
}, |
|||
|
|||
group() { |
|||
return this.options.inline ? 'inline' : 'block' |
|||
}, |
|||
|
|||
draggable: true, |
|||
|
|||
addAttributes() { |
|||
return { |
|||
src: { |
|||
default: null, |
|||
}, |
|||
alt: { |
|||
default: null, |
|||
}, |
|||
title: { |
|||
default: null, |
|||
}, |
|||
} |
|||
}, |
|||
|
|||
parseHTML() { |
|||
return [ |
|||
{ |
|||
tag: this.options.allowBase64 |
|||
? 'img[src]' |
|||
: 'img[src]:not([src^="data:"])', |
|||
}, |
|||
] |
|||
}, |
|||
|
|||
renderHTML({ HTMLAttributes }) { |
|||
// return ['img', mergeAttributes(this.options.HTMLAttributes, HTMLAttributes,{dataAa: 123})]
|
|||
return ['div', { "style": "display:inline-block" }, ["img", mergeAttributes(this.options.HTMLAttributes, HTMLAttributes, { dataAa: 123 })]] |
|||
}, |
|||
|
|||
addCommands() { |
|||
return { |
|||
setImage: 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 } |
|||
}, |
|||
}), |
|||
] |
|||
}, |
|||
}) |
@ -0,0 +1,16 @@ |
|||
import { Editor } from "@tiptap/core"; |
|||
import { Image } from "./Image"; |
|||
import BasePlugin from "../../base/BasePlugin.js"; |
|||
|
|||
class ImagePlugin extends BasePlugin { |
|||
register(editor: Editor) { |
|||
editor.extensionManager.extensions.push(Image.configure({ |
|||
inline: true, |
|||
})) |
|||
} |
|||
} |
|||
|
|||
export { |
|||
ImagePlugin |
|||
} |
|||
export default ImagePlugin |
Loading…
Reference in new issue