add imageToFigure command for figure experiment
This commit is contained in:
@@ -3,6 +3,10 @@ import {
|
||||
Node,
|
||||
nodeInputRule,
|
||||
mergeAttributes,
|
||||
findChildrenInRange,
|
||||
isNodeSelection,
|
||||
Predicate,
|
||||
NodeWithPos,
|
||||
} from '@tiptap/core'
|
||||
|
||||
export interface FigureOptions {
|
||||
@@ -21,6 +25,16 @@ declare module '@tiptap/core' {
|
||||
title?: string,
|
||||
caption?: string,
|
||||
}) => Command,
|
||||
|
||||
/**
|
||||
* Converts an image to a figure
|
||||
*/
|
||||
imageToFigure: () => Command,
|
||||
|
||||
/**
|
||||
* Converts a figure to an image
|
||||
*/
|
||||
figureToImage: () => Command,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -52,6 +66,7 @@ export const Figure = Node.create<FigureOptions>({
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
alt: {
|
||||
default: null,
|
||||
parseHTML: element => {
|
||||
@@ -60,6 +75,7 @@ export const Figure = Node.create<FigureOptions>({
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
title: {
|
||||
default: null,
|
||||
parseHTML: element => {
|
||||
@@ -108,6 +124,45 @@ export const Figure = Node.create<FigureOptions>({
|
||||
})
|
||||
.run()
|
||||
},
|
||||
|
||||
imageToFigure: () => ({ tr }) => {
|
||||
const { doc, selection } = tr
|
||||
const nodes: NodeWithPos[] = []
|
||||
const predicate: Predicate = node => node.type.name === 'image'
|
||||
|
||||
if (isNodeSelection(selection)) {
|
||||
const node = doc.nodeAt(selection.from)
|
||||
|
||||
if (!node || !predicate(node)) {
|
||||
return false
|
||||
}
|
||||
|
||||
nodes.push({ node, pos: selection.from })
|
||||
} else {
|
||||
const range = {
|
||||
from: selection.from,
|
||||
to: selection.to,
|
||||
}
|
||||
|
||||
nodes.push(...findChildrenInRange(doc, range, predicate))
|
||||
}
|
||||
|
||||
nodes.forEach(({ node, pos }, index) => {
|
||||
const mappedPos = tr.steps
|
||||
.slice(tr.steps.length - index)
|
||||
.reduce((newPos, step) => step.getMap().map(newPos), pos)
|
||||
|
||||
tr.replaceRangeWith(mappedPos, mappedPos + node.nodeSize, this.type.create({
|
||||
src: node.attrs.src,
|
||||
}))
|
||||
})
|
||||
|
||||
return true
|
||||
},
|
||||
|
||||
figureToImage: () => () => {
|
||||
return true
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -3,6 +3,12 @@
|
||||
<button @click="addFigure">
|
||||
figure
|
||||
</button>
|
||||
<button @click="editor.chain().focus().imageToFigure().run()">
|
||||
image to figure
|
||||
</button>
|
||||
<button @click="editor.chain().focus().figureToImage().run()">
|
||||
figure to image
|
||||
</button>
|
||||
<editor-content :editor="editor" />
|
||||
|
||||
<h2>HTML</h2>
|
||||
@@ -13,6 +19,7 @@
|
||||
<script>
|
||||
import { Editor, EditorContent } from '@tiptap/vue-2'
|
||||
import StarterKit from '@tiptap/starter-kit'
|
||||
import Image from '@tiptap/extension-image'
|
||||
import { Figure } from './figure'
|
||||
|
||||
export default {
|
||||
@@ -46,6 +53,7 @@ export default {
|
||||
extensions: [
|
||||
StarterKit,
|
||||
Figure,
|
||||
Image,
|
||||
],
|
||||
content: `
|
||||
<p>Figure + Figcaption</p>
|
||||
@@ -55,6 +63,9 @@ export default {
|
||||
<p>Amazing caption</p>
|
||||
</figcaption>
|
||||
</figure>
|
||||
<img src="https://source.unsplash.com/K9QHL52rE2k/800x400">
|
||||
<img src="https://source.unsplash.com/8xznAGy4HcY/800x400">
|
||||
<img src="https://source.unsplash.com/K9QHL52rE2k/800x400">
|
||||
<p>That’s it.</p>
|
||||
`,
|
||||
})
|
||||
@@ -90,7 +101,8 @@ export default {
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
display: block;
|
||||
max-width: min(100%, 25rem);
|
||||
height: auto;
|
||||
border-radius: 0.5rem;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user