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.)