logo

pleroma-fe

My custom branche(s) on git.pleroma.social/pleroma/pleroma-fe git clone https://hacktivis.me/git/pleroma-fe.git
commit: 4aac0125e591c6f2ef51bad475e79802be51f068
parent 7309f8ce1a5df1d34e33a242201b6a7b9eced2b7
Author: Henry Jameson <me@hjkos.com>
Date:   Tue, 15 Jun 2021 14:43:44 +0300

fixed bug with hashtags

Diffstat:

Msrc/components/rich_content/rich_content.jsx33+++++++++++++++++++++------------
Mtest/unit/specs/components/rich_content.spec.js36++++++++++++++++++++++++++++++++++++
2 files changed, 57 insertions(+), 12 deletions(-)

diff --git a/src/components/rich_content/rich_content.jsx b/src/components/rich_content/rich_content.jsx @@ -85,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) } @@ -128,7 +127,7 @@ export default Vue.component('RichContent', { encounteredText = true } if (item.includes(':')) { - unescapedItem = processTextForEmoji( + unescapedItem = ['', processTextForEmoji( unescapedItem, this.emoji, ({ shortcode, url }) => { @@ -139,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) { @@ -176,14 +175,10 @@ export default Vue.component('RichContent', { </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 } } } @@ -200,7 +195,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 @@ -209,16 +204,30 @@ export default Vue.component('RichContent', { if (attrs['class'] && attrs['class'].includes('hashtag')) { return renderHashtag(attrs, children, encounteredTextReverse) } + break + case '': + return [...children].reverse().map(processItemReverse).reverse() + } + + // Render tag as is + if (children !== undefined) { + return <Tag {...{ attrs: getAttrs(opener) }}> + { Array.isArray(children) ? [...children].reverse().map(processItemReverse).reverse() : children } + </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 = { diff --git a/test/unit/specs/components/rich_content.spec.js b/test/unit/specs/components/rich_content.spec.js @@ -603,4 +603,40 @@ describe('RichContent', () => { expect(wrapper.html()).to.eql(compwrap(expected)) }) + + it('buggy example/hashtags', () => { + const html = [ + '<p>', + '<a href="http://macrochan.org/images/N/H/NHCMDUXJPPZ6M3Z2CQ6D2EBRSWGE7MZY.jpg">', + 'NHCMDUXJPPZ6M3Z2CQ6D2EBRSWGE7MZY.jpg</a>', + ' <a class="hashtag" data-tag="nou" href="https://shitposter.club/tag/nou">', + '#nou</a>', + ' <a class="hashtag" data-tag="screencap" href="https://shitposter.club/tag/screencap">', + '#screencap</a>', + ' </p>' + ].join('') + const expected = [ + '<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>', + ' </p>' + ].join('') + + const wrapper = shallowMount(RichContent, { + localVue, + propsData: { + hideMentions: true, + handleLinks: true, + greentext: true, + emoji: [], + html + } + }) + + expect(wrapper.html()).to.eql(compwrap(expected)) + }) })