diff --git a/src/components/mentions_line/mentions_line.scss b/src/components/mentions_line/mentions_line.scss index 976a3fc7d9..222940c803 100644 --- a/src/components/mentions_line/mentions_line.scss +++ b/src/components/mentions_line/mentions_line.scss @@ -2,10 +2,9 @@ .showMoreLess { white-space: normal; color: var(--link); - margin-right: 0.25em; } - .mention-link { + .mention-link:not(:last-child) { margin-right: 0.25em; } } diff --git a/src/components/rich_content/rich_content.jsx b/src/components/rich_content/rich_content.jsx index 8ab007e391..d98947df18 100644 --- a/src/components/rich_content/rich_content.jsx +++ b/src/components/rich_content/rich_content.jsx @@ -61,6 +61,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 @@ -119,14 +121,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 +148,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 +182,13 @@ export default Vue.component('RichContent', { } if (children !== undefined) { - return [opener, children.map(processItem), closer] + return [ + opener, + [mentionsLinePadding].concat(children.map(processItem)), + closer + ] } else { - return item + return ['', [mentionsLinePadding, item], ''] } } } @@ -215,7 +227,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 @@ -283,8 +294,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