forked from AkkomaGang/akkoma-fe
very minimalist hashtaglink implementation, also you can middle-click
mentions now.
This commit is contained in:
parent
c3576211cb
commit
39494439d3
6 changed files with 75 additions and 12 deletions
36
src/components/hashtag_link/hashtag_link.js
Normal file
36
src/components/hashtag_link/hashtag_link.js
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
import { extractTagFromUrl } from 'src/services/matcher/matcher.service.js'
|
||||||
|
|
||||||
|
const HashtagLink = {
|
||||||
|
name: 'HashtagLink',
|
||||||
|
props: {
|
||||||
|
url: {
|
||||||
|
required: true,
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
content: {
|
||||||
|
required: true,
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
tag: {
|
||||||
|
required: false,
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onClick () {
|
||||||
|
const tag = this.tag || extractTagFromUrl(this.url)
|
||||||
|
if (tag) {
|
||||||
|
const link = this.generateTagLink(tag)
|
||||||
|
this.$router.push(link)
|
||||||
|
} else {
|
||||||
|
window.open(this.url, '_blank')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
generateTagLink (tag) {
|
||||||
|
return `/tag/${tag}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default HashtagLink
|
6
src/components/hashtag_link/hashtag_link.scss
Normal file
6
src/components/hashtag_link/hashtag_link.scss
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
.HashtagLink {
|
||||||
|
position: relative;
|
||||||
|
white-space: normal;
|
||||||
|
display: inline-block;
|
||||||
|
color: var(--link);
|
||||||
|
}
|
19
src/components/hashtag_link/hashtag_link.vue
Normal file
19
src/components/hashtag_link/hashtag_link.vue
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
<template>
|
||||||
|
<span
|
||||||
|
class="HashtagLink"
|
||||||
|
>
|
||||||
|
<!-- eslint-disable vue/no-v-html -->
|
||||||
|
<a
|
||||||
|
:href="url"
|
||||||
|
class="original"
|
||||||
|
target="_blank"
|
||||||
|
@click.prevent="onClick"
|
||||||
|
v-html="content"
|
||||||
|
/>
|
||||||
|
<!-- eslint-enable vue/no-v-html -->
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script src="./hashtag_link.js"/>
|
||||||
|
|
||||||
|
<style lang="scss" src="./hashtag_link.scss"/>
|
|
@ -17,8 +17,9 @@
|
||||||
:style="style"
|
:style="style"
|
||||||
:class="classnames"
|
:class="classnames"
|
||||||
>
|
>
|
||||||
<button
|
<a
|
||||||
class="short button-unstyled"
|
class="short button-unstyled"
|
||||||
|
:href="url"
|
||||||
@click.prevent="onClick"
|
@click.prevent="onClick"
|
||||||
>
|
>
|
||||||
<!-- eslint-disable vue/no-v-html -->
|
<!-- eslint-disable vue/no-v-html -->
|
||||||
|
@ -35,7 +36,7 @@
|
||||||
class="you"
|
class="you"
|
||||||
>{{ $t('status.you') }}</span>
|
>{{ $t('status.you') }}</span>
|
||||||
<!-- eslint-enable vue/no-v-html -->
|
<!-- eslint-enable vue/no-v-html -->
|
||||||
</button>
|
</a>
|
||||||
<span
|
<span
|
||||||
v-if="userName !== userNameFull"
|
v-if="userName !== userNameFull"
|
||||||
class="full popover-default"
|
class="full popover-default"
|
||||||
|
|
|
@ -5,6 +5,7 @@ import { convertHtmlToTree } from 'src/services/html_converter/html_tree_convert
|
||||||
import { convertHtmlToLines } from 'src/services/html_converter/html_line_converter.service.js'
|
import { convertHtmlToLines } from 'src/services/html_converter/html_line_converter.service.js'
|
||||||
import StillImage from 'src/components/still-image/still-image.vue'
|
import StillImage from 'src/components/still-image/still-image.vue'
|
||||||
import MentionsLine, { MENTIONS_LIMIT } from 'src/components/mentions_line/mentions_line.vue'
|
import MentionsLine, { MENTIONS_LIMIT } from 'src/components/mentions_line/mentions_line.vue'
|
||||||
|
import HashtagLink from 'src/components/hashtag_link/hashtag_link.vue'
|
||||||
|
|
||||||
import './rich_content.scss'
|
import './rich_content.scss'
|
||||||
|
|
||||||
|
@ -83,13 +84,10 @@ export default Vue.component('RichContent', {
|
||||||
const renderHashtag = (attrs, children, encounteredTextReverse) => {
|
const renderHashtag = (attrs, children, encounteredTextReverse) => {
|
||||||
const linkData = getLinkData(attrs, children, tagsIndex++)
|
const linkData = getLinkData(attrs, children, tagsIndex++)
|
||||||
writtenTags.push(linkData)
|
writtenTags.push(linkData)
|
||||||
attrs.target = '_blank'
|
|
||||||
if (!encounteredTextReverse) {
|
if (!encounteredTextReverse) {
|
||||||
lastTags.push(linkData)
|
lastTags.push(linkData)
|
||||||
}
|
}
|
||||||
return <a {...{ attrs }}>
|
return <HashtagLink {...{ props: linkData }}/>
|
||||||
{ children.map(processItem) }
|
|
||||||
</a>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const renderMention = (attrs, children) => {
|
const renderMention = (attrs, children) => {
|
||||||
|
@ -211,7 +209,10 @@ export default Vue.component('RichContent', {
|
||||||
if (!this.handleLinks) break
|
if (!this.handleLinks) break
|
||||||
const attrs = getAttrs(opener)
|
const attrs = getAttrs(opener)
|
||||||
// should only be this
|
// should only be this
|
||||||
if (attrs['class'] && attrs['class'].includes('hashtag')) {
|
if (
|
||||||
|
(attrs['class'] && attrs['class'].includes('hashtag')) || // Pleroma style
|
||||||
|
(attrs['rel'] === 'tag') // Mastodon style
|
||||||
|
) {
|
||||||
return renderHashtag(attrs, children, encounteredTextReverse)
|
return renderHashtag(attrs, children, encounteredTextReverse)
|
||||||
} else {
|
} else {
|
||||||
attrs.target = '_blank'
|
attrs.target = '_blank'
|
||||||
|
@ -275,7 +276,7 @@ const getLinkData = (attrs, children, index) => {
|
||||||
return {
|
return {
|
||||||
index,
|
index,
|
||||||
url: attrs.href,
|
url: attrs.href,
|
||||||
hashtag: attrs['data-tag'],
|
tag: attrs['data-tag'],
|
||||||
content: flattenDeep(children).join(''),
|
content: flattenDeep(children).join(''),
|
||||||
textContent
|
textContent
|
||||||
}
|
}
|
||||||
|
|
|
@ -300,10 +300,10 @@ describe('RichContent', () => {
|
||||||
'<p>',
|
'<p>',
|
||||||
'<a href="http://macrochan.org/images/N/H/NHCMDUXJPPZ6M3Z2CQ6D2EBRSWGE7MZY.jpg" target="_blank">',
|
'<a href="http://macrochan.org/images/N/H/NHCMDUXJPPZ6M3Z2CQ6D2EBRSWGE7MZY.jpg" target="_blank">',
|
||||||
'NHCMDUXJPPZ6M3Z2CQ6D2EBRSWGE7MZY.jpg</a>',
|
'NHCMDUXJPPZ6M3Z2CQ6D2EBRSWGE7MZY.jpg</a>',
|
||||||
' <a class="hashtag" data-tag="nou" href="https://shitposter.club/tag/nou" target="_blank">',
|
' <hashtaglink-stub url="https://shitposter.club/tag/nou" content="#nou" tag="nou">',
|
||||||
'#nou</a>',
|
'</hashtaglink-stub>',
|
||||||
' <a class="hashtag" data-tag="screencap" href="https://shitposter.club/tag/screencap" target="_blank">',
|
' <hashtaglink-stub url="https://shitposter.club/tag/screencap" content="#screencap" tag="screencap">',
|
||||||
'#screencap</a>',
|
'</hashtaglink-stub>',
|
||||||
' </p>'
|
' </p>'
|
||||||
].join('')
|
].join('')
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue