mirror of
https://github.com/Ocelot-Social-Community/Ocelot-Social.git
synced 2025-12-13 07:46:06 +00:00
* Add target="_blank" (on embeds only!)
* When pasting a link, the cursor position is moved after the paste
* Can't reproduce a link slipping into the embed in front of it
@Tirokk it is an unpleasant side efffect that mentions + hastags appear
differently on Edit+View. That's because they don't get parsed from
HTML, it's a one way, they are write only. So, when viewing content,
hashtags and mentions appear as plain links. I don't think I can do
anything about it.
Regarding some links not being embedded: Only those links that have an
oembed provider in this file:
f44d0f1f96/backend/src/schema/resolvers/embeds/providers.json
...will be embedded. Your example `http://backreaction.blogspot.com` and `https://de.wikipedia.org/wiki/Yin_und_Yang`
have no embed provider and won't be embedded.
We would have to add oembed providers to this list if we wanted to embed those
links, too.
97 lines
2.1 KiB
JavaScript
97 lines
2.1 KiB
JavaScript
import { Node } from 'tiptap'
|
|
import pasteRule from '../commands/pasteRule'
|
|
import { compileToFunctions } from 'vue-template-compiler'
|
|
|
|
const template = `
|
|
<a class="embed" :href="dataEmbedUrl" rel="noopener noreferrer nofollow" target="_blank">
|
|
<div v-if="embedHtml" v-html="embedHtml" />
|
|
<em> {{ dataEmbedUrl }} </em>
|
|
</a>
|
|
`
|
|
const compiledTemplate = compileToFunctions(template)
|
|
|
|
export default class Embed extends Node {
|
|
get name() {
|
|
return 'embed'
|
|
}
|
|
|
|
get defaultOptions() {
|
|
return {
|
|
onEmbed: () => ({}),
|
|
}
|
|
}
|
|
|
|
pasteRules({ type, schema }) {
|
|
return [
|
|
pasteRule(
|
|
/https?:\/\/(www\.)?[-a-zA-Z0-9@:%._+~#=]{2,256}\.[a-zA-Z]{2,}\b([-a-zA-Z0-9@:%_+.~#?&//=]*)/g,
|
|
type,
|
|
url => ({ dataEmbedUrl: url }),
|
|
),
|
|
]
|
|
}
|
|
|
|
get schema() {
|
|
return {
|
|
attrs: {
|
|
dataEmbedUrl: {
|
|
default: null,
|
|
},
|
|
},
|
|
group: 'inline',
|
|
inline: true,
|
|
parseDOM: [
|
|
{
|
|
tag: 'a[href].embed',
|
|
getAttrs: dom => ({
|
|
dataEmbedUrl: dom.getAttribute('href'),
|
|
}),
|
|
},
|
|
],
|
|
toDOM: node => [
|
|
'a',
|
|
{
|
|
href: node.attrs.dataEmbedUrl,
|
|
class: 'embed',
|
|
target: '_blank',
|
|
},
|
|
],
|
|
}
|
|
}
|
|
|
|
get view() {
|
|
return {
|
|
props: ['node', 'updateAttrs', 'options'],
|
|
data: () => ({
|
|
embedData: {},
|
|
}),
|
|
async created() {
|
|
if (!this.options) return {}
|
|
this.embedData = await this.options.onEmbed({ url: this.dataEmbedUrl })
|
|
},
|
|
computed: {
|
|
embedClass() {
|
|
return this.embedHtml ? 'embed' : ''
|
|
},
|
|
embedHtml() {
|
|
const { html = '' } = this.embedData
|
|
return html
|
|
},
|
|
dataEmbedUrl: {
|
|
get() {
|
|
return this.node.attrs.dataEmbedUrl
|
|
},
|
|
set(dataEmbedUrl) {
|
|
this.updateAttrs({
|
|
dataEmbedUrl,
|
|
})
|
|
},
|
|
},
|
|
},
|
|
render(createElement) {
|
|
return compiledTemplate.render.call(this, createElement)
|
|
},
|
|
}
|
|
}
|
|
}
|