diff options
Diffstat (limited to 'src/components/rich_content/rich_content.jsx')
| -rw-r--r-- | src/components/rich_content/rich_content.jsx | 69 |
1 files changed, 50 insertions, 19 deletions
diff --git a/src/components/rich_content/rich_content.jsx b/src/components/rich_content/rich_content.jsx index ffb36f50..ce562f13 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 MentionLink from 'src/components/mention_link/mention_link.vue' +import MentionsLine from 'src/components/mentions_line/mentions_line.vue' import './rich_content.scss' @@ -51,6 +52,11 @@ export default Vue.component('RichContent', { required: false, type: Boolean, default: false + }, + hideMentions: { + required: false, + type: Boolean, + default: false } }, // NEVER EVER TOUCH DATA INSIDE RENDER @@ -64,6 +70,7 @@ export default Vue.component('RichContent', { // unique index for vue "tag" property let mentionIndex = 0 let tagsIndex = 0 + let firstMentionReplaced = false const renderImage = (tag) => { return <StillImage @@ -78,7 +85,6 @@ export default Vue.component('RichContent', { attrs.target = '_blank' if (!encounteredTextReverse) { lastTags.push(linkData) - attrs['data-parser-last'] = true } return <a {...{ attrs }}> { children.map(processItem) } @@ -90,7 +96,12 @@ export default Vue.component('RichContent', { writtenMentions.push(linkData) if (!encounteredText) { firstMentions.push(linkData) - return '' + if (!firstMentionReplaced && !this.hideMentions) { + firstMentionReplaced = true + return <MentionsLine mentions={ firstMentions } /> + } else { + return '' + } } else { return <MentionLink url={attrs.href} @@ -116,7 +127,7 @@ export default Vue.component('RichContent', { encounteredText = true } if (item.includes(':')) { - unescapedItem = processTextForEmoji( + unescapedItem = ['', processTextForEmoji( unescapedItem, this.emoji, ({ shortcode, url }) => { @@ -127,14 +138,14 @@ export default Vue.component('RichContent', { alt={`:${shortcode}:`} /> } - ) + )] } return unescapedItem } // Handle tag nodes if (Array.isArray(item)) { - const [opener, children] = item + const [opener, children, closer] = item const Tag = getTagName(opener) const attrs = getAttrs(opener) switch (Tag) { @@ -143,7 +154,7 @@ export default Vue.component('RichContent', { if (firstMentions.length > 1 && lastMentions.length > 1) { break } else { - return '' + return !this.hideMentions ? <MentionsLine mentions={lastMentions} /> : '' } } else { break @@ -153,25 +164,19 @@ export default Vue.component('RichContent', { case 'a': // replace mentions with MentionLink if (!this.handleLinks) break if (attrs['class'] && attrs['class'].includes('mention')) { + // Handling mentions here return renderMention(attrs, children, encounteredText) - } else if (attrs['class'] && attrs['class'].includes('hashtag')) { + } else { + // Everything else will be handled in reverse pass encounteredText = true return item // We'll handle it later - } else { - attrs.target = '_blank' - return <a {...{ attrs }}> - { children.map(processItem) } - </a> } } - // Render tag as is if (children !== undefined) { - return <Tag {...{ attrs: getAttrs(opener) }}> - { children.map(processItem) } - </Tag> + return [opener, children.map(processItem), closer] } else { - return <Tag/> + return item } } } @@ -188,7 +193,7 @@ export default Vue.component('RichContent', { } else if (Array.isArray(item)) { // Handle tag nodes const [opener, children] = item - const Tag = getTagName(opener) + const Tag = opener === '' ? '' : getTagName(opener) switch (Tag) { case 'a': // replace mentions with MentionLink if (!this.handleLinks) break @@ -196,17 +201,43 @@ export default Vue.component('RichContent', { // should only be this if (attrs['class'] && attrs['class'].includes('hashtag')) { return renderHashtag(attrs, children, encounteredTextReverse) + } else { + attrs.target = '_blank' + html.includes('freenode') && console.log('PASS1', children) + const newChildren = [...children].reverse().map(processItemReverse).reverse() + html.includes('freenode') && console.log('PASS1b', newChildren) + + return <a {...{ attrs }}> + { newChildren } + </a> } + case '': + return [...children].reverse().map(processItemReverse).reverse() + } + + // 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 + return <Tag {...{ attrs: getAttrs(opener) }}> + { newChildren } + </Tag> + } else { + return <Tag/> } } return item } + const pass1 = convertHtmlToTree(html).map(processItem) + const pass2 = [...pass1].reverse().map(processItemReverse).reverse() // DO NOT USE SLOTS they cause a re-render feedback loop here. // slots updated -> rerender -> emit -> update up the tree -> rerender -> ... // at least until vue3? const result = <span class="RichContent"> - { convertHtmlToTree(html).map(processItem).reverse().map(processItemReverse).reverse() } + { pass2 } </span> const event = { |
