commit: 4aac0125e591c6f2ef51bad475e79802be51f068
parent 7309f8ce1a5df1d34e33a242201b6a7b9eced2b7
Author: Henry Jameson <me@hjkos.com>
Date: Tue, 15 Jun 2021 14:43:44 +0300
fixed bug with hashtags
Diffstat:
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))
+ })
})