aboutsummaryrefslogtreecommitdiff
path: root/src/components/rich_content/rich_content.jsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/rich_content/rich_content.jsx')
-rw-r--r--src/components/rich_content/rich_content.jsx53
1 files changed, 33 insertions, 20 deletions
diff --git a/src/components/rich_content/rich_content.jsx b/src/components/rich_content/rich_content.jsx
index 8ab007e3..c0d20c5e 100644
--- a/src/components/rich_content/rich_content.jsx
+++ b/src/components/rich_content/rich_content.jsx
@@ -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'
@@ -61,6 +62,8 @@ export default Vue.component('RichContent', {
// Pre-process HTML
const { newHtml: html } = preProcessPerLine(this.html, this.greentext)
let currentMentions = null // Current chain of mentions, we group all mentions together
+ // This is used to recover spacing removed when parsing mentions
+ let lastSpacing = ''
const lastTags = [] // Tags that appear at the end of post body
const writtenMentions = [] // All mentions that appear in post body
@@ -81,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) => {
@@ -119,14 +119,9 @@ export default Vue.component('RichContent', {
if (emptyText) {
// don't include spaces when processing mentions - we'll include them
// in MentionsLine
+ lastSpacing = item
return currentMentions !== null ? item.trim() : item
}
- // We add space with mentionsLine, otherwise non-text elements will
- // stick to them.
- if (currentMentions !== null) {
- // single whitespace trim
- item = item[0].match(/\s/) ? item.slice(1) : item
- }
currentMentions = null
if (item.includes(':')) {
@@ -151,21 +146,32 @@ export default Vue.component('RichContent', {
const [opener, children, closer] = item
const Tag = getTagName(opener)
const attrs = getAttrs(opener)
+ const previouslyMentions = currentMentions !== null
+ /* During grouping of mentions we trim all the empty text elements
+ * This padding is added to recover last space removed in case
+ * we have a tag right next to mentions
+ */
+ const mentionsLinePadding =
+ // Padding is only needed if we just finished parsing mentions
+ previouslyMentions &&
+ // Don't add padding if content is string and has padding already
+ !(children && typeof children[0] === 'string' && children[0].match(/^\s/))
+ ? lastSpacing
+ : ''
switch (Tag) {
case 'br':
currentMentions = null
break
case 'img': // replace images with StillImage
- return renderImage(opener)
+ return ['', [mentionsLinePadding, renderImage(opener)], '']
case 'a': // replace mentions with MentionLink
if (!this.handleLinks) break
if (attrs['class'] && attrs['class'].includes('mention')) {
// Handling mentions here
return renderMention(attrs, children)
} else {
- // Everything else will be handled in reverse pass
currentMentions = null
- return item // We'll handle it later
+ break
}
case 'span':
if (this.handleLinks && attrs['class'] && attrs['class'].includes('h-card')) {
@@ -174,9 +180,16 @@ export default Vue.component('RichContent', {
}
if (children !== undefined) {
- return [opener, children.map(processItem), closer]
+ return [
+ '',
+ [
+ mentionsLinePadding,
+ [opener, children.map(processItem), closer]
+ ],
+ ''
+ ]
} else {
- return item
+ return ['', [mentionsLinePadding, item], '']
}
}
}
@@ -199,7 +212,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'
@@ -215,7 +231,6 @@ export default Vue.component('RichContent', {
// Render tag as is
if (children !== undefined) {
- html.includes('freenode') && console.log('PASS2', children)
const newChildren = Array.isArray(children)
? [...children].reverse().map(processItemReverse).reverse()
: children
@@ -264,7 +279,7 @@ const getLinkData = (attrs, children, index) => {
return {
index,
url: attrs.href,
- hashtag: attrs['data-tag'],
+ tag: attrs['data-tag'],
content: flattenDeep(children).join(''),
textContent
}
@@ -283,8 +298,6 @@ export const preProcessPerLine = (html, greentext) => {
const lines = convertHtmlToLines(html)
const newHtml = lines.reverse().map((item, index, array) => {
- // Going over each line in reverse to detect last mentions,
- // keeping non-text stuff as-is
if (!item.text) return item
const string = item.text