Merge branch 'better-still-emoji' into proper-attachments

* better-still-emoji:
  fix non-notifying mentions and original mention display
  fix not escaping some stuff
  fix rich images
This commit is contained in:
Henry Jameson 2021-06-22 20:45:44 +03:00
commit dd3fe61cf3
7 changed files with 65 additions and 12 deletions

View file

@ -5,8 +5,9 @@
<!-- eslint-disable vue/no-v-html --> <!-- eslint-disable vue/no-v-html -->
<a <a
v-if="!user" v-if="!user"
href="url" :href="url"
class="original" class="original"
target="_blank"
v-html="content" v-html="content"
/> />
<!-- eslint-enable vue/no-v-html --> <!-- eslint-enable vue/no-v-html -->

View file

@ -36,6 +36,10 @@ export default Vue.component('RichContent', {
required: true, required: true,
type: String type: String
}, },
attentions: {
required: false,
default: () => []
},
// Emoji object, as in status.emojis, note the "s" at the end... // Emoji object, as in status.emojis, note the "s" at the end...
emoji: { emoji: {
required: true, required: true,
@ -91,8 +95,12 @@ export default Vue.component('RichContent', {
</a> </a>
} }
const renderMention = (attrs, children, encounteredText) => { const renderMention = (attrs, children) => {
const linkData = getLinkData(attrs, children, mentionIndex++) const linkData = getLinkData(attrs, children, mentionIndex++)
linkData.notifying = this.attentions.some(a => a.statusnet_profile_url === linkData.url)
if (!linkData.notifying) {
encounteredText = true
}
writtenMentions.push(linkData) writtenMentions.push(linkData)
if (!encounteredText) { if (!encounteredText) {
firstMentions.push(linkData) firstMentions.push(linkData)
@ -121,14 +129,13 @@ export default Vue.component('RichContent', {
if (emptyText) { if (emptyText) {
return encounteredText ? item : item.trim() return encounteredText ? item : item.trim()
} }
let unescapedItem = unescape(item)
if (!encounteredText) { if (!encounteredText) {
unescapedItem = unescapedItem.trimStart() item = item.trimStart()
encounteredText = true encounteredText = true
} }
if (item.includes(':')) { if (item.includes(':')) {
unescapedItem = ['', processTextForEmoji( item = ['', processTextForEmoji(
unescapedItem, item,
this.emoji, this.emoji,
({ shortcode, url }) => { ({ shortcode, url }) => {
return <StillImage return <StillImage
@ -140,7 +147,7 @@ export default Vue.component('RichContent', {
} }
)] )]
} }
return unescapedItem return item
} }
// Handle tag nodes // Handle tag nodes
@ -149,7 +156,7 @@ export default Vue.component('RichContent', {
const Tag = getTagName(opener) const Tag = getTagName(opener)
const attrs = getAttrs(opener) const attrs = getAttrs(opener)
switch (Tag) { switch (Tag) {
case 'span': // replace images with StillImage case 'span': // Replace last mentions class with mentionsline
if (attrs['class'] && attrs['class'].includes('lastMentions')) { if (attrs['class'] && attrs['class'].includes('lastMentions')) {
if (firstMentions.length > 1 && lastMentions.length > 1) { if (firstMentions.length > 1 && lastMentions.length > 1) {
break break
@ -189,7 +196,7 @@ export default Vue.component('RichContent', {
const emptyText = item.trim() === '' const emptyText = item.trim() === ''
if (emptyText) return item if (emptyText) return item
if (!encounteredTextReverse) encounteredTextReverse = true if (!encounteredTextReverse) encounteredTextReverse = true
return item return unescape(item)
} else if (Array.isArray(item)) { } else if (Array.isArray(item)) {
// Handle tag nodes // Handle tag nodes
const [opener, children] = item const [opener, children] = item
@ -203,9 +210,7 @@ export default Vue.component('RichContent', {
return renderHashtag(attrs, children, encounteredTextReverse) return renderHashtag(attrs, children, encounteredTextReverse)
} else { } else {
attrs.target = '_blank' attrs.target = '_blank'
html.includes('freenode') && console.log('PASS1', children)
const newChildren = [...children].reverse().map(processItemReverse).reverse() const newChildren = [...children].reverse().map(processItemReverse).reverse()
html.includes('freenode') && console.log('PASS1b', newChildren)
return <a {...{ attrs }}> return <a {...{ attrs }}>
{ newChildren } { newChildren }

View file

@ -86,6 +86,20 @@ const StatusContent = {
}) })
}, },
methods: { methods: {
onParseReady (event) {
this.$emit('parseReady', event)
const { writtenMentions } = event
writtenMentions
.filter(mention => !mention.notifying)
.forEach(mention => {
const { content, url } = mention
const cleanedString = content.replace(/<[^>]+?>/gi, '') // remove all tags
if (!cleanedString.startsWith('@')) return
const handle = cleanedString.slice(1)
const host = url.replace(/^https?:\/\//, '').replace(/\/.+?$/, '')
this.$store.dispatch('fetchUserIfMissing', `${handle}@${host}`)
})
},
toggleShowMore () { toggleShowMore () {
if (this.mightHideBecauseTall) { if (this.mightHideBecauseTall) {
this.showingTall = !this.showingTall this.showingTall = !this.showingTall

View file

@ -50,7 +50,8 @@
:handle-links="true" :handle-links="true"
:hide-mentions="hideMentions" :hide-mentions="hideMentions"
:greentext="mergedConfig.greentext" :greentext="mergedConfig.greentext"
@parseReady="$emit('parseReady', $event)" :attentions="status.attentions"
@parseReady="onParseReady"
/> />
<button <button

View file

@ -114,6 +114,8 @@ export const convertHtmlToLines = (html) => {
} else { } else {
handleOpen(tagFull) handleOpen(tagFull)
} }
} else {
textBuffer += tagFull
} }
} else { } else {
textBuffer += tagFull textBuffer += tagFull

View file

@ -27,6 +27,29 @@ describe('RichContent', () => {
expect(wrapper.html()).to.eql(compwrap(html)) expect(wrapper.html()).to.eql(compwrap(html))
}) })
it('unescapes everything as needed', () => {
const html = [
p('Testing &#39;em all'),
'Testing &#39;em all'
].join('')
const expected = [
p('Testing \'em all'),
'Testing \'em all'
].join('')
const wrapper = shallowMount(RichContent, {
localVue,
propsData: {
hideMentions: true,
handleLinks: true,
greentext: true,
emoji: [],
html
}
})
expect(wrapper.html()).to.eql(compwrap(expected))
})
it('removes mentions from the beginning of post', () => { it('removes mentions from the beginning of post', () => {
const html = p( const html = p(
makeMention('John'), makeMention('John'),

View file

@ -69,6 +69,13 @@ describe('html_line_converter', () => {
const comparableResult = result.map(mapOnlyText(processorKeep)).join('') const comparableResult = result.map(mapOnlyText(processorKeep)).join('')
expect(comparableResult).to.eql(inputOutput) expect(comparableResult).to.eql(inputOutput)
}) })
it('fed with some recognized but not handled elements', () => {
const inputOutput = 'testing images\n\n<img src="benis.png">'
const result = convertHtmlToLines(inputOutput)
const comparableResult = result.map(mapOnlyText(processorKeep)).join('')
expect(comparableResult).to.eql(inputOutput)
})
}) })
describe('with processor that replaces lines with word "_" should match expected line when', () => { describe('with processor that replaces lines with word "_" should match expected line when', () => {
const processorReplace = (line) => '_' const processorReplace = (line) => '_'