Try embedding iframes in tiptap
This commit is contained in:
parent
f7151f131d
commit
3a8968bdf1
98
common/util/iframe.ts
Normal file
98
common/util/iframe.ts
Normal file
|
@ -0,0 +1,98 @@
|
|||
// Adopted from https://github.com/ueberdosis/tiptap/blob/main/demos/src/Experiments/Embeds/Vue/iframe.ts
|
||||
|
||||
import { Node } from '@tiptap/core'
|
||||
import clsx from 'clsx'
|
||||
|
||||
export interface IframeOptions {
|
||||
allowFullscreen: boolean
|
||||
HTMLAttributes: {
|
||||
[key: string]: any
|
||||
}
|
||||
}
|
||||
|
||||
declare module '@tiptap/core' {
|
||||
interface Commands<ReturnType> {
|
||||
iframe: {
|
||||
/**
|
||||
* Add an iframe
|
||||
*/
|
||||
setIframe: (options: { src: string }) => ReturnType
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const wrapperClasses = 'relative h-auto w-full overflow-hidden'
|
||||
const iframeClasses = 'absolute top-0 left-0 h-full w-full'
|
||||
|
||||
export default Node.create<IframeOptions>({
|
||||
name: 'iframe',
|
||||
|
||||
group: 'block',
|
||||
|
||||
atom: true,
|
||||
|
||||
addOptions() {
|
||||
return {
|
||||
allowFullscreen: true,
|
||||
HTMLAttributes: {
|
||||
class: clsx('iframe-wrapper', wrapperClasses),
|
||||
// Tailwind JIT doesn't seem to pick up `pb-[20rem]`, so we hack this in:
|
||||
style: 'padding-bottom: 20rem;',
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
addAttributes() {
|
||||
return {
|
||||
src: {
|
||||
default: null,
|
||||
},
|
||||
frameborder: {
|
||||
default: 0,
|
||||
},
|
||||
allowfullscreen: {
|
||||
default: this.options.allowFullscreen,
|
||||
parseHTML: () => this.options.allowFullscreen,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
parseHTML() {
|
||||
return [
|
||||
{
|
||||
tag: 'iframe',
|
||||
},
|
||||
]
|
||||
},
|
||||
|
||||
renderHTML({ HTMLAttributes }) {
|
||||
return [
|
||||
'div',
|
||||
this.options.HTMLAttributes,
|
||||
[
|
||||
'iframe',
|
||||
{
|
||||
...HTMLAttributes,
|
||||
class: clsx(HTMLAttributes.class, iframeClasses),
|
||||
},
|
||||
],
|
||||
]
|
||||
},
|
||||
|
||||
addCommands() {
|
||||
return {
|
||||
setIframe:
|
||||
(options: { src: string }) =>
|
||||
({ tr, dispatch }) => {
|
||||
const { selection } = tr
|
||||
const node = this.type.create(options)
|
||||
|
||||
if (dispatch) {
|
||||
tr.replaceRangeWith(selection.from, selection.to, node)
|
||||
}
|
||||
|
||||
return true
|
||||
},
|
||||
}
|
||||
},
|
||||
})
|
|
@ -20,6 +20,7 @@ import { Text } from '@tiptap/extension-text'
|
|||
// other tiptap extensions
|
||||
import { Image } from '@tiptap/extension-image'
|
||||
import { Link } from '@tiptap/extension-link'
|
||||
import Iframe from './iframe'
|
||||
|
||||
export function parseTags(text: string) {
|
||||
const regex = /(?:^|\s)(?:[#][a-z0-9_]+)/gi
|
||||
|
@ -80,6 +81,7 @@ export const exhibitExts = [
|
|||
|
||||
Image,
|
||||
Link,
|
||||
Iframe,
|
||||
]
|
||||
// export const exhibitExts = [StarterKit as unknown as Extension, Image]
|
||||
|
||||
|
|
|
@ -99,6 +99,9 @@ function RichEditContract(props: { contract: Contract; isAdmin?: boolean }) {
|
|||
.setContent(contract.description)
|
||||
.focus('end')
|
||||
.insertContent(`<p>${editTimestamp()}</p>`)
|
||||
.insertContent(
|
||||
`<iframe src="https://manifold.markets/embed/Austin/how-many-upvotes-will-the-new-versi" frameborder="0"></iframe>`
|
||||
)
|
||||
.run()
|
||||
}}
|
||||
>
|
||||
|
|
|
@ -19,6 +19,7 @@ import { useMutation } from 'react-query'
|
|||
import { exhibitExts } from 'common/util/parse'
|
||||
import { FileUploadButton } from './file-upload-button'
|
||||
import { linkClass } from './site-link'
|
||||
import Iframe from 'common/util/iframe'
|
||||
|
||||
const proseClass = clsx(
|
||||
'prose prose-p:my-0 prose-li:my-0 prose-blockquote:not-italic max-w-none prose-quoteless leading-relaxed',
|
||||
|
@ -56,6 +57,7 @@ export function useTextEditor(props: {
|
|||
class: clsx('no-underline !text-indigo-700', linkClass),
|
||||
},
|
||||
}),
|
||||
Iframe,
|
||||
],
|
||||
content: defaultValue,
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue
Block a user