vue의tiptap에서iframe로 생성된 외부 내용을 삽입합니다
개요
vue에서 WYSIWYG 편집기의 tiptap에 다른 사이트를 표시하는 방법을 소개합니다.
단계
Iframely
세부 정보
API 키를 가져오려면 Iframely에 서명
https://iframely.com/에서 업그레이드하면 사용자가 등록하면 API 키가 발행되므로 이 키를 사용합니다.월 최대 1만 회까지 무료로 이용할 수 있다.
API 키 예제58xx1axxbxxxcca68fxxxdb
새로 고치면 홈 페이지에 자신의 API 키가 표시됩니다.
tiptap의 사용자 정의 노드 정의
다음 js 파일을 만들고 vue 구성 요소와 같은 폴더에 준비합니다.toDom
는 점으로 수조 정의 서브노드를 대량으로 사용하여 다음과 같은 html를 생성한다.
공식 가이드의 Iframely embeds for CKEditor oEmbed plugin 이 페이지CKEditor에 있는 WYSIWYG 편집기의 설치 예가 있기 때문에 참고하십시오.
생성할 HTML
<div class="iframely-embed">
<div class="iframely-responsive">
<iframe src="//cdn.iframe.ly/api/iframe?app=1&api_key=APIキー&url=エンコードされたURL" 'frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>
</div>
</div>
CDN에서 iframely로의 embed.js 가져오기(2021/1/1 추적)
index.html의 경우 <script src="//cdn.iframe.ly/embed.js" async></script>
nuxt.config.js시export default {
// Global page headers (https://go.nuxtjs.dev/config-head)
head: {
title: 'xxxxx',
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ hid: 'description', name: 'description', content: '' }
],
link: [
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
],
script: [
{ src: '//cdn.iframe.ly/embed.js'}
]
},
...
tiptap 생성 사용자 정의 노드 js
tiptap는 웹에 풍부한 텍스트 편집기 ProseMirror 를 구축하기 위해 도구 패키지를 사용합니다. 그 규격은 이 도구 패키지를 따라야 합니다.그 방법이 방대하고 이해하는 데 시간이 걸릴 것 같아서 실험을 거듭하면서 진행했어요.
Embed.jsimport { Node } from 'tiptap'
export default class Embed extends Node {
get name() {
return 'embed'
}
get schema() {
return {
attrs: {
src: {
default: null,
}
},
group: 'block',
selectable: false,
parseDOM: [{
tag: 'iframe',
getAttrs: dom => ({
src: dom.getAttribute('src'),
}),
}],
toDOM: node => ['div', { class: 'iframely-embed' },
['div', { class: 'iframely-responsive', style: 'padding-bottom: 66.6667%; padding-top: 120px;' },
['iframe', {
src: '//cdn.iframe.ly/api/iframe?app=1&api_key=58xx1axxbxxxcca68fxxxdb&url=' + encodeURIComponent(node.attrs.src), // ここは自分のAPI Keyを設定する
frameborder: "0",
allow: "autoplay; encrypted-media",
}]
]
],
}
}
commands({ type }) {
return attrs => (state, dispatch) => {
const { selection } = state;
const position = selection.$cursor
? selection.$cursor.pos
: selection.$to.pos;
const node = type.create(attrs);
const transaction = state.tr.insert(position, node);
dispatch(transaction);
};
}
}
2021/1/1 업데이트
위의 toDOM에 있는 iframe의 지정으로 뒤에 0을 추가했지만 이게 있으면 getHTML이 잘못될 수 있어서 뺐습니다.
수정 전) ['iframe', {
src: '//cdn.iframe.ly/api/iframe?app=1&api_key=58xx1axxbxxxcca68fxxxdb&url=' + encodeURIComponent(node.attrs.src), // ここは自分のAPI Keyを設定する
frameborder: "0",
allow: "autoplay; encrypted-media",
}, 0]
수정 후) ['iframe', {
src: '//cdn.iframe.ly/api/iframe?app=1&api_key=58xx1axxbxxxcca68fxxxdb&url=' + encodeURIComponent(node.attrs.src), // ここは自分のAPI Keyを設定する
frameborder: "0",
allow: "autoplay; encrypted-media",
}]
편집기 구성 요소에서command를 통해 URL을 전달하여 노드를 표시합니다
url의 입력 폼 등 생략,editor.command에서 embed를 호출하면 node를 삽입할 수 있습니다.<template>
<div class="editor">
<editor-content class="editor__content" :editor="editor" />
</div>
</template>
<script>
import { Editor, EditorContent } from 'tiptap'
import {
HardBreak,
Heading,
Bold,
Italic,
History,
TrailingNode,
} from 'tiptap-extensions'
import Embed from './Embed.js'
export default {
components: {
EditorContent,
},
data() {
return {
editor: new Editor({
extensions: [
new HardBreak(),
new Heading({ levels: [1, 2, 3] }),
new Bold(),
new Italic(),
new History(),
new TrailingNode(),
// ここで指定する
new Embed(),
],
content: "",
}),
}
},
beforeDestroy() {
this.editor.destroy()
},
methods: {
embed() {
this.editor.commands.embed({ src: 'https://news.yahoo.co.jp/pickup/6348622' });
},
}
}
</script>
<style lang="scss">
...省略
</style>
내장형 이미지
Reference
이 문제에 관하여(vue의tiptap에서iframe로 생성된 외부 내용을 삽입합니다), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/gosshys/items/1aa9af7a8cb0a3df64d2
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
<div class="iframely-embed">
<div class="iframely-responsive">
<iframe src="//cdn.iframe.ly/api/iframe?app=1&api_key=APIキー&url=エンコードされたURL" 'frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>
</div>
</div>
<script src="//cdn.iframe.ly/embed.js" async></script>
export default {
// Global page headers (https://go.nuxtjs.dev/config-head)
head: {
title: 'xxxxx',
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ hid: 'description', name: 'description', content: '' }
],
link: [
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
],
script: [
{ src: '//cdn.iframe.ly/embed.js'}
]
},
...
import { Node } from 'tiptap'
export default class Embed extends Node {
get name() {
return 'embed'
}
get schema() {
return {
attrs: {
src: {
default: null,
}
},
group: 'block',
selectable: false,
parseDOM: [{
tag: 'iframe',
getAttrs: dom => ({
src: dom.getAttribute('src'),
}),
}],
toDOM: node => ['div', { class: 'iframely-embed' },
['div', { class: 'iframely-responsive', style: 'padding-bottom: 66.6667%; padding-top: 120px;' },
['iframe', {
src: '//cdn.iframe.ly/api/iframe?app=1&api_key=58xx1axxbxxxcca68fxxxdb&url=' + encodeURIComponent(node.attrs.src), // ここは自分のAPI Keyを設定する
frameborder: "0",
allow: "autoplay; encrypted-media",
}]
]
],
}
}
commands({ type }) {
return attrs => (state, dispatch) => {
const { selection } = state;
const position = selection.$cursor
? selection.$cursor.pos
: selection.$to.pos;
const node = type.create(attrs);
const transaction = state.tr.insert(position, node);
dispatch(transaction);
};
}
}
['iframe', {
src: '//cdn.iframe.ly/api/iframe?app=1&api_key=58xx1axxbxxxcca68fxxxdb&url=' + encodeURIComponent(node.attrs.src), // ここは自分のAPI Keyを設定する
frameborder: "0",
allow: "autoplay; encrypted-media",
}, 0]
['iframe', {
src: '//cdn.iframe.ly/api/iframe?app=1&api_key=58xx1axxbxxxcca68fxxxdb&url=' + encodeURIComponent(node.attrs.src), // ここは自分のAPI Keyを設定する
frameborder: "0",
allow: "autoplay; encrypted-media",
}]
<template>
<div class="editor">
<editor-content class="editor__content" :editor="editor" />
</div>
</template>
<script>
import { Editor, EditorContent } from 'tiptap'
import {
HardBreak,
Heading,
Bold,
Italic,
History,
TrailingNode,
} from 'tiptap-extensions'
import Embed from './Embed.js'
export default {
components: {
EditorContent,
},
data() {
return {
editor: new Editor({
extensions: [
new HardBreak(),
new Heading({ levels: [1, 2, 3] }),
new Bold(),
new Italic(),
new History(),
new TrailingNode(),
// ここで指定する
new Embed(),
],
content: "",
}),
}
},
beforeDestroy() {
this.editor.destroy()
},
methods: {
embed() {
this.editor.commands.embed({ src: 'https://news.yahoo.co.jp/pickup/6348622' });
},
}
}
</script>
<style lang="scss">
...省略
</style>
Reference
이 문제에 관하여(vue의tiptap에서iframe로 생성된 외부 내용을 삽입합니다), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/gosshys/items/1aa9af7a8cb0a3df64d2텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)