very minimalist hashtaglink implementation, also you can middle-click
mentions now.
This commit is contained in:
parent
04af3e94e1
commit
88b81dcaf5
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"
|
||||
:class="classnames"
|
||||
>
|
||||
<button
|
||||
<a
|
||||
class="short button-unstyled"
|
||||
:href="url"
|
||||
@click.prevent="onClick"
|
||||
>
|
||||
<!-- eslint-disable vue/no-v-html -->
|
||||
|
@ -35,7 +36,7 @@
|
|||
class="you"
|
||||
>{{ $t('status.you') }}</span>
|
||||
<!-- eslint-enable vue/no-v-html -->
|
||||
</button>
|
||||
</a>
|
||||
<span
|
||||
v-if="userName !== userNameFull"
|
||||
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 StillImage from 'src/components/still-image/still-image.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'
|
||||
|
||||
|
@ -83,13 +84,10 @@ export default Vue.component('RichContent', {
|
|||
const renderHashtag = (attrs, children, encounteredTextReverse) => {
|
||||
const linkData = getLinkData(attrs, children, tagsIndex++)
|
||||
writtenTags.push(linkData)
|
||||
attrs.target = '_blank'
|
||||
if (!encounteredTextReverse) {
|
||||
lastTags.push(linkData)
|
||||
}
|
||||
return <a {...{ attrs }}>
|
||||
{ children.map(processItem) }
|
||||
</a>
|
||||
return <HashtagLink {...{ props: linkData }}/>
|
||||
}
|
||||
|
||||
const renderMention = (attrs, children) => {
|
||||
|
@ -211,7 +209,10 @@ export default Vue.component('RichContent', {
|
|||
if (!this.handleLinks) break
|
||||
const attrs = getAttrs(opener)
|
||||
// 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)
|
||||
} else {
|
||||
attrs.target = '_blank'
|
||||
|
@ -275,7 +276,7 @@ const getLinkData = (attrs, children, index) => {
|
|||
return {
|
||||
index,
|
||||
url: attrs.href,
|
||||
hashtag: attrs['data-tag'],
|
||||
tag: attrs['data-tag'],
|
||||
content: flattenDeep(children).join(''),
|
||||
textContent
|
||||
}
|
||||
|
|
|
@ -300,10 +300,10 @@ describe('RichContent', () => {
|
|||
'<p>',
|
||||
'<a href="http://macrochan.org/images/N/H/NHCMDUXJPPZ6M3Z2CQ6D2EBRSWGE7MZY.jpg" target="_blank">',
|
||||
'NHCMDUXJPPZ6M3Z2CQ6D2EBRSWGE7MZY.jpg</a>',
|
||||
' <a class="hashtag" data-tag="nou" href="https://shitposter.club/tag/nou" target="_blank">',
|
||||
'#nou</a>',
|
||||
' <a class="hashtag" data-tag="screencap" href="https://shitposter.club/tag/screencap" target="_blank">',
|
||||
'#screencap</a>',
|
||||
' <hashtaglink-stub url="https://shitposter.club/tag/nou" content="#nou" tag="nou">',
|
||||
'</hashtaglink-stub>',
|
||||
' <hashtaglink-stub url="https://shitposter.club/tag/screencap" content="#screencap" tag="screencap">',
|
||||
'</hashtaglink-stub>',
|
||||
' </p>'
|
||||
].join('')
|
||||
|
||||
|
|
Loading…
Reference in a new issue