tiptap-image-resize
tiptap-image-resize copied to clipboard
Doesn't work out of the box with NextJS
Throws this error when importing and using with NextJS:
I'll investigate this further, but I've not touched the module itself so I'm pretty sure this is a bug.
Sorry i didn't notice your issue! But it looks like your setup doesn't support loading typescript? (as far as is know it's included in the base NextJS setup since a few years?)
Will setup a NextJS project and try a few things. Thanks for mentioning it!
I use NextJS with typescript configurarion so I know that it can handle typescript files:) What i did as a temporary fix was to make a similar extension under the project src and that worked fine, so I'm not sure what the issue is. 🤔
I use NextJS with typescript configurarion so I know that it can handle typescript files:) What i did as a temporary fix was to make a similar extension under the project src and that worked fine, so I'm not sure what the issue is. 🤔
hi, im having the same issue here. could you perhaps send your solution? thanks
A temporary solution was to copy the code in the node_module extension and separate it into a custom extension located under your own /src
path. So under my src/components/editor/extensions
folder (it could be something else for you) I have this:
This is the extension that I import in my editor with import ImageExtension from './extensions/resize-image/index';
index.ts:
import { ImageResize } from './image'
export * from './image'
export default ImageResize
image.ts:
import React, {Component, FC, ReactElement} from "react";
import {mergeAttributes, nodeInputRule, Node} from "@tiptap/core";
import {ReactNodeViewRenderer} from "@tiptap/react";
import ImageResizeComponent from "./component/ImageResizeComponent";
export interface ImageOptions {
inline: boolean,
allowBase64: boolean,
HTMLAttributes: Record<string, any>,
}
declare module '@tiptap/core' {
interface Commands<ReturnType> {
image: {
/**
* Add an image
*/
setImage: (options: { src: string, alt?: string, title?: string }) => ReturnType,
}
}
}
export const inputRegex = /(?:^|\s)(!\[(.+|:?)]\((\S+)(?:(?:\s+)["'](\S+)["'])?\))$/
export const ImageResize = Node.create<ImageOptions>({
name: 'resizableImage',
addOptions() {
return {
inline: false,
allowBase64: false,
HTMLAttributes: {},
resizeIcon: React.createElement("p", null, "⇲")
}
},
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,
},
width: {
default: '100%',
renderHTML: (attributes) => {
return {
width: attributes.width
};
}
},
height: {
default: 'auto',
renderHTML: (attributes) => {
return {
height: attributes.height
};
}
}
}
},
parseHTML() {
return [
{
tag: 'image-resizer',
},
]
},
renderHTML({ HTMLAttributes }) {
return ['image-resizer', mergeAttributes(this.options.HTMLAttributes,HTMLAttributes)]
},
addNodeView() {
return ReactNodeViewRenderer(ImageResizeComponent)
},
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 }
},
}),
]
},
})
ImageResizeComponent.tsx:
import React from 'react';
import { NodeViewWrapper } from '@tiptap/react';
import Image from 'next/image';
const ImageResizeComponent = (props: any) => {
const handler = (mouseDownEvent: React.MouseEvent<HTMLImageElement>) => {
const parent = (mouseDownEvent.target as HTMLElement).closest(
'.image-resizer'
);
const image = parent?.querySelector('img.postimage') ?? null;
if (image === null) return;
const startSize = { x: image.clientWidth, y: image.clientHeight };
const startPosition = { x: mouseDownEvent.pageX, y: mouseDownEvent.pageY };
function onMouseMove(mouseMoveEvent: MouseEvent) {
props.updateAttributes({
width: startSize.x - startPosition.x + mouseMoveEvent.pageX,
height: startSize.y - startPosition.y + mouseMoveEvent.pageY,
});
}
function onMouseUp() {
document.body.removeEventListener('mousemove', onMouseMove);
}
document.body.addEventListener('mousemove', onMouseMove);
document.body.addEventListener('mouseup', onMouseUp, { once: true });
};
return (
<NodeViewWrapper className="image-resizer">
<img {...props.node.attrs} className="postimage" />
<p></p>
<div className="resize-trigger" onMouseDown={handler}>
{props.extension.options.resizeIcon}
</div>
</NodeViewWrapper>
);
};
export default ImageResizeComponent;
Hey @mattiastofte Thanks for your issue! Will update the code asap to work out of the box!
@mattiastofte thanks!
Same issue, would appreciate the proper fix @breakerh !
I'll use @mattiastofte 's solution for now, thanks for posting the code :smile:
Throws this error when importing and using with NextJS:
I'll investigate this further, but I've not touched the module itself so I'm pretty sure this is a bug.
Same issue, Roger that
- also , had to —force npm install ( perhaps updated for the latest React and tiptap versions )
Throws this error when importing and using with NextJS:
I'll investigate this further, but I've not touched the module itself so I'm pretty sure this is a bug.
also , had to —force npm install ( perhaps updating the extension for the latest React and tiptap versions + .js / .ts fluent would be cool ) thanks brothers
Sorry for not responding in time!
I will update the the code to react 18.x and will update the code to behave as expected.. Again sorry for the ultra delayed response..
worked on something similar: I added a rollup config for typescript support.
https://github.com/Habib-Shahzad/tiptap-resizable-image