tiptap-extension-resize-image
Version:
A tiptap image resizing extension for React, Vue, Next, and VanillaJS. Additionally, it can align the image position.
234 lines (175 loc) • 7.85 kB
Markdown
# `tiptap-extension-resize-image`
[](https://www.npmjs.com/package/tiptap-extension-resize-image)
[](https://www.npmjs.com/package/tiptap-extension-resize-image)
[](https://github.com/bae-sh/tiptap-extension-resize-image/blob/main/LICENSE)
[](https://github.com/bae-sh/tiptap-extension-resize-image)

[Tiptap](https://tiptap.dev/) is a suite of open source content editing and real-time collaboration tools for developers building apps like Notion or Google Docs.
This package provides the ability to adjust the size of the tip tab image. It has been tested in [React](https://codesandbox.io/p/devbox/react-tiptap-image-extension-3ztv5s?file=%2Fsrc%2Ftiptap.tsx%3A5%2C26-5%2C55), [Vue](https://codesandbox.io/p/devbox/vue-tiptap-image-extension-tvxx62?file=%2Fsrc%2FTiptap.vue%3A9%2C1), and [NextJS](https://codesandbox.io/p/devbox/nextjs-tiptap-image-extension-nk6v7p?file=%2Fapp%2Ftiptap.tsx%3A17%2C1), and stability in VanillaJS may not be guaranteed. Additionally, it can align the image position.
## Compatibility
| tiptap-extension-resize-image | Supported TipTap Versions |
| ----------------------------- | ------------------------- |
| ≤ 1.2.2 | v2 only |
| ≥ 1.2.3 | v2 and v3 |
## Installation
You can install it using npm:
```bash
$ npm install tiptap-extension-resize-image
```
## Usage
```javascript
import StarterKit from '@tiptap/starter-kit';
import ImageResize from 'tiptap-extension-resize-image';
import { EditorContent, useEditor } from '@tiptap/react';
const editor = useEditor({
extensions: [StarterKit, ImageResize],
content: `<img src="https://source.unsplash.com/8xznAGy4HcY/800x400" />`,
});
```
### Use as inline
If you want to render images as inline elements, you can configure the extension like this:
```javascript
const editor = useEditor({
extensions: [
StarterKit,
ImageResize.configure({
inline: true,
}),
],
content: `<img src="..."/>`,
});
```
### Resize limits
You can set minimum and maximum width constraints to limit how small or large images can be resized:
```javascript
const editor = useEditor({
extensions: [
StarterKit,
ImageResize.configure({
minWidth: 100, // Minimum width in pixels
maxWidth: 800, // Maximum width in pixels
}),
],
content: `<img src="..."/>`,
});
```
Both `minWidth` and `maxWidth` are optional. You can set one, both, or neither:
```javascript
// Only set a minimum width
ImageResize.configure({ minWidth: 50 });
// Only set a maximum width
ImageResize.configure({ maxWidth: 1200 });
// Set both constraints
ImageResize.configure({ minWidth: 100, maxWidth: 800 });
```
## Options
| Option | Type | Default | Description |
| ---------- | --------- | ----------- | ----------------------------------------------- |
| `inline` | `boolean` | `false` | Render images as inline elements |
| `minWidth` | `number` | `undefined` | Minimum width in pixels (cannot resize smaller) |
| `maxWidth` | `number` | `undefined` | Maximum width in pixels (cannot resize larger) |
<br/>
## Figure with caption
`Figure` and `Figcaption` extensions allow you to add a caption to an image. The `Figure` node wraps an image with a `figcaption` element, and provides commands to add, remove, or toggle captions.
```javascript
import StarterKit from '@tiptap/starter-kit';
import { ImageResize, Figure, Figcaption } from 'tiptap-extension-resize-image';
const editor = useEditor({
extensions: [StarterKit, ImageResize, Figure, Figcaption],
});
```
### Commands
| Command | Description |
| ----------------- | ---------------------------------------------------------- |
| `addCaption()` | Converts a selected `imageResize` node to a `figure` node |
| `removeCaption()` | Converts a selected `figure` node to an `imageResize` node |
| `toggleCaption()` | Toggles between `imageResize` and `figure` node |
```javascript
// Add a caption to a selected image
editor.commands.addCaption();
// Add a caption with initial text
editor.commands.addCaption('My caption');
// Remove a caption from a selected figure
editor.commands.removeCaption();
// Toggle between imageResize and figure
editor.commands.toggleCaption();
```
### Captions are not available in inline mode
When `ImageResize` is configured with `inline: true`, the image becomes an
inline node that lives inside paragraphs (or other inline containers).
A `figure`, on the other hand, is a block-level node by HTML spec and cannot
be nested inside such inline containers without breaking the document
structure.
For this reason, `addCaption()` (and `toggleCaption()` when the current node
is an inline image) will return `false` and do nothing in this case. You can
use this return value to disable the caption button in your UI:
```javascript
<button
onClick={() => editor.chain().focus().addCaption().run()}
disabled={!editor.can().addCaption()}
>
Add Caption
</button>
```
If you need both inline images and captions in the same editor, configure
`ImageResize` without `inline` (the default) so that all images are block
nodes and can be converted into a `figure` with a caption.
### Additional Setup
Figcaption placeholders are displayed with the help of CSS. Add the following styles to your project. You can customize these styles to match your design:
```css
/* Basic figcaption styles */
figcaption {
text-align: left;
font-size: 0.875rem;
color: #666;
}
/* Placeholder styles - displayed when figcaption is empty */
/* Uses the data-placeholder attribute set by the Figcaption extension */
figcaption.is-empty::before {
color: #adb5bd;
content: attr(data-placeholder);
float: left;
height: 0;
pointer-events: none;
}
```
### Figcaption Options
| Option | Type | Default | Description |
| ------------- | -------- | ---------------------- | ---------------------------------- |
| `placeholder` | `string` | `'Write a caption...'` | Placeholder text for empty caption |
```javascript
Figcaption.configure({
placeholder: 'placeholder text as you want',
});
```
### Tiptap v3 Notice
In Tiptap v3, `shouldRerenderOnTransaction` defaults to `false`, which means components won't automatically re-render on editor state changes. To reactively update button states (e.g., `disabled`), use one of the following approaches:
**Option 1: Enable `shouldRerenderOnTransaction`**
```javascript
const editor = useEditor({
shouldRerenderOnTransaction: true,
extensions: [...],
});
// Now you can use editor.can() directly
<button
onClick={() => editor.commands.addCaption()}
disabled={!editor.can().addCaption()}
>
Add Caption
</button>
```
**Option 2: Use `useEditorState` (recommended)**
```javascript
import { useEditorState } from '@tiptap/react';
const { canAddCaption, canRemoveCaption } = useEditorState({
editor,
selector: (ctx) => ({
canAddCaption: ctx.editor.can().addCaption(),
}),
});
<button onClick={() => editor.commands.addCaption()} disabled={!canAddCaption}>
Add Caption
</button>;
```
## Contributing
Contributions are welcome! Please read our [Contributing Guide](./CONTRIBUTING.md) before submitting a Pull Request.