From 2f383c2c0197b94b30fdc4c5e0c742c7e104be20 Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Tue, 8 Jun 2021 14:34:47 +0300
Subject: moved mentions into a separate component - MentionLine, added
 collapsing of mentions when there's too many of 'em

---
 src/components/mentions_line/mentions_line.vue | 42 ++++++++++++++++++++++++++
 1 file changed, 42 insertions(+)
 create mode 100644 src/components/mentions_line/mentions_line.vue

(limited to 'src/components/mentions_line/mentions_line.vue')

diff --git a/src/components/mentions_line/mentions_line.vue b/src/components/mentions_line/mentions_line.vue
new file mode 100644
index 00000000..6d114f2d
--- /dev/null
+++ b/src/components/mentions_line/mentions_line.vue
@@ -0,0 +1,42 @@
+<template>
+<span class="MentionsLine">
+  <MentionLink
+    v-for="mention in mentions"
+    class="mention-link"
+    :key="mention.statusnet_profile_url"
+    :content="mention.statusnet_profile_url"
+    :url="mention.statusnet_profile_url"
+    :first-mention="false"
+  /><span v-if="manyMentions" class="extraMentions">
+    <span
+      v-if="expanded"
+      class="fullExtraMentions"
+    >
+      <MentionLink
+        v-for="mention in extraMentions"
+        class="mention-link"
+        :key="mention.statusnet_profile_url"
+        :content="mention.statusnet_profile_url"
+        :url="mention.statusnet_profile_url"
+        :first-mention="false"
+      />
+    </span><button
+      v-if="!expanded"
+      class="showMoreLess"
+      :class="buttonClasses"
+      @click="toggleShowMore"
+    >
+      {{ $t('status.plus_more', { number: extraMentions.length })}}
+    </button><button
+      v-if="expanded"
+      class="showMoreLess"
+      :class="buttonClasses"
+      @click="toggleShowMore"
+    >
+      {{ $t('general.show_less')}}
+    </button>
+  </span>
+</span>
+</template>
+<script src="./mentions_line.js" ></script>
+<style lang="scss" src="./mentions_line.scss" />
-- 
cgit v1.2.3-70-g09d2


From 7ae85c8318add44af1c8f91c9738a2d715da2f3e Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Tue, 8 Jun 2021 14:51:42 +0300
Subject: change defaults

---
 src/components/mention_link/mention_link.js        |  4 +-
 src/components/mention_link/mention_link.vue       | 23 +++++--
 src/components/mentions_line/mentions_line.js      |  4 +-
 src/components/mentions_line/mentions_line.vue     | 75 +++++++++++-----------
 src/components/settings_modal/tabs/general_tab.vue |  8 +--
 src/components/status/status.js                    |  4 +-
 src/components/status/status.vue                   |  5 +-
 src/components/status_body/status_body.js          |  4 +-
 src/components/status_body/status_body.vue         |  2 +-
 src/modules/config.js                              |  4 +-
 10 files changed, 74 insertions(+), 59 deletions(-)

(limited to 'src/components/mentions_line/mentions_line.vue')

diff --git a/src/components/mention_link/mention_link.js b/src/components/mention_link/mention_link.js
index 8a93e8a3..8ad84a51 100644
--- a/src/components/mention_link/mention_link.js
+++ b/src/components/mention_link/mention_link.js
@@ -52,10 +52,10 @@ const MentionLink = {
       if (this.highlight) return highlightClass(this.user)
     },
     oldPlace () {
-      return this.mergedConfig.mentionsOldPlace
+      return !this.mergedConfig.mentionsOwnLine
     },
     oldStyle () {
-      return this.mergedConfig.mentionsOldStyle
+      return !this.mergedConfig.mentionsNewStyle
     },
     style () {
       if (this.highlight) {
diff --git a/src/components/mention_link/mention_link.vue b/src/components/mention_link/mention_link.vue
index d2f4129d..55f49507 100644
--- a/src/components/mention_link/mention_link.vue
+++ b/src/components/mention_link/mention_link.vue
@@ -1,8 +1,8 @@
 <template>
-<span
-  class="MentionLink"
-  :class="{ '-oldPlace': oldPlace }"
->
+  <span
+    class="MentionLink"
+    :class="{ '-oldPlace': oldPlace }"
+  >
     <!-- eslint-disable vue/no-v-html -->
     <a
       v-if="!user"
@@ -23,8 +23,14 @@
         @click.prevent="onClick"
       >
         <!-- eslint-disable vue/no-v-html -->
-        <span class="shortName"><span class="userName" v-html="userName" /></span>
-        <span class="you" v-if="isYou">{{ $t('status.you') }}</span>
+        <span class="shortName"><span
+          class="userName"
+          v-html="userName"
+        /></span>
+        <span
+          v-if="isYou"
+          class="you"
+        >{{ $t('status.you') }}</span>
         <!-- eslint-enable vue/no-v-html -->
       </button>
       <span
@@ -33,7 +39,10 @@
         :class="[highlightType]"
       >
         <!-- eslint-disable vue/no-v-html -->
-        <span class="userNameFull" v-html="userNameFull" />
+        <span
+          class="userNameFull"
+          v-html="userNameFull"
+        />
         <!-- eslint-enable vue/no-v-html -->
       </span>
     </span>
diff --git a/src/components/mentions_line/mentions_line.js b/src/components/mentions_line/mentions_line.js
index 2e84d4c5..6f347058 100644
--- a/src/components/mentions_line/mentions_line.js
+++ b/src/components/mentions_line/mentions_line.js
@@ -15,7 +15,7 @@ const MentionsLine = {
   },
   computed: {
     oldStyle () {
-      return this.mergedConfig.mentionsOldStyle
+      return !this.mergedConfig.mentionsNewStyle
     },
     limit () {
       return 6
@@ -39,7 +39,7 @@ const MentionsLine = {
           : '-newStyle'
       ]
     },
-    ...mapGetters(['mergedConfig']),
+    ...mapGetters(['mergedConfig'])
   },
   methods: {
     toggleShowMore () {
diff --git a/src/components/mentions_line/mentions_line.vue b/src/components/mentions_line/mentions_line.vue
index 6d114f2d..58f3de6f 100644
--- a/src/components/mentions_line/mentions_line.vue
+++ b/src/components/mentions_line/mentions_line.vue
@@ -1,42 +1,45 @@
 <template>
-<span class="MentionsLine">
-  <MentionLink
-    v-for="mention in mentions"
-    class="mention-link"
-    :key="mention.statusnet_profile_url"
-    :content="mention.statusnet_profile_url"
-    :url="mention.statusnet_profile_url"
-    :first-mention="false"
-  /><span v-if="manyMentions" class="extraMentions">
-    <span
-      v-if="expanded"
-      class="fullExtraMentions"
+  <span class="MentionsLine">
+    <MentionLink
+      v-for="mention in mentions"
+      :key="mention.statusnet_profile_url"
+      class="mention-link"
+      :content="mention.statusnet_profile_url"
+      :url="mention.statusnet_profile_url"
+      :first-mention="false"
+    /><span
+      v-if="manyMentions"
+      class="extraMentions"
     >
-      <MentionLink
-        v-for="mention in extraMentions"
-        class="mention-link"
-        :key="mention.statusnet_profile_url"
-        :content="mention.statusnet_profile_url"
-        :url="mention.statusnet_profile_url"
-        :first-mention="false"
-      />
-    </span><button
-      v-if="!expanded"
-      class="showMoreLess"
-      :class="buttonClasses"
-      @click="toggleShowMore"
-    >
-      {{ $t('status.plus_more', { number: extraMentions.length })}}
-    </button><button
-      v-if="expanded"
-      class="showMoreLess"
-      :class="buttonClasses"
-      @click="toggleShowMore"
-    >
-      {{ $t('general.show_less')}}
-    </button>
+      <span
+        v-if="expanded"
+        class="fullExtraMentions"
+      >
+        <MentionLink
+          v-for="mention in extraMentions"
+          :key="mention.statusnet_profile_url"
+          class="mention-link"
+          :content="mention.statusnet_profile_url"
+          :url="mention.statusnet_profile_url"
+          :first-mention="false"
+        />
+      </span><button
+        v-if="!expanded"
+        class="showMoreLess"
+        :class="buttonClasses"
+        @click="toggleShowMore"
+      >
+        {{ $t('status.plus_more', { number: extraMentions.length }) }}
+      </button><button
+        v-if="expanded"
+        class="showMoreLess"
+        :class="buttonClasses"
+        @click="toggleShowMore"
+      >
+        {{ $t('general.show_less') }}
+      </button>
+    </span>
   </span>
-</span>
 </template>
 <script src="./mentions_line.js" ></script>
 <style lang="scss" src="./mentions_line.scss" />
diff --git a/src/components/settings_modal/tabs/general_tab.vue b/src/components/settings_modal/tabs/general_tab.vue
index c8bab869..e62df290 100644
--- a/src/components/settings_modal/tabs/general_tab.vue
+++ b/src/components/settings_modal/tabs/general_tab.vue
@@ -37,13 +37,13 @@
           </BooleanSetting>
         </li>
         <li>
-          <BooleanSetting path="mentionsOldPlace">
-            {{ $t('settings.mentions_old_place') }}
+          <BooleanSetting path="mentionsOwnLine">
+            {{ $t('settings.mentions_new_place') }}
           </BooleanSetting>
         </li>
         <li>
-          <BooleanSetting path="mentionsOldStyle">
-            {{ $t('settings.mentions_old_style') }}
+          <BooleanSetting path="mentionsNewStyle">
+            {{ $t('settings.mentions_new_style') }}
           </BooleanSetting>
         </li>
         <li>
diff --git a/src/components/status/status.js b/src/components/status/status.js
index d921f625..3954df00 100644
--- a/src/components/status/status.js
+++ b/src/components/status/status.js
@@ -163,8 +163,8 @@ const Status = {
     muteWordHits () {
       return muteWordHits(this.status, this.muteWords)
     },
-    mentionsOldPlace () {
-      return this.mergedConfig.mentionsOldPlace
+    mentionsOwnLine () {
+      return this.mergedConfig.mentionsOwnLine
     },
     mentions () {
       return this.statusoid.attentions.filter(attn => {
diff --git a/src/components/status/status.vue b/src/components/status/status.vue
index faf67328..969e2bc8 100644
--- a/src/components/status/status.vue
+++ b/src/components/status/status.vue
@@ -291,7 +291,10 @@
               </div>
             </div>
 
-            <div v-if="hasMentions && !mentionsOldPlace" class="heading-mentions-row">
+            <div
+              v-if="hasMentions && mentionsOwnLine"
+              class="heading-mentions-row"
+            >
               <div
                 class="mentions"
               >
diff --git a/src/components/status_body/status_body.js b/src/components/status_body/status_body.js
index 0c1aa88e..3c092ac7 100644
--- a/src/components/status_body/status_body.js
+++ b/src/components/status_body/status_body.js
@@ -105,8 +105,8 @@ const StatusContent = {
     attachmentTypes () {
       return this.status.attachments.map(file => fileType.fileType(file.mimetype))
     },
-    mentionsOldPlace () {
-      return this.mergedConfig.mentionsOldPlace
+    mentionsOwnLine () {
+      return this.mergedConfig.mentionsOwnLine
     },
     mentions () {
       return this.status.attentions
diff --git a/src/components/status_body/status_body.vue b/src/components/status_body/status_body.vue
index 92e47118..fadbeaf3 100644
--- a/src/components/status_body/status_body.vue
+++ b/src/components/status_body/status_body.vue
@@ -43,7 +43,7 @@
           v-if="!hideSubjectStatus && !(singleLine && status.summary_html)"
         >
           <MentionsLine
-            v-if="mentionsOldPlace"
+            v-if="!mentionsOwnLine"
             :attentions="status.attentions"
             class="mentions-line"
             />
diff --git a/src/modules/config.js b/src/modules/config.js
index 6e21e38b..ad9c8be5 100644
--- a/src/modules/config.js
+++ b/src/modules/config.js
@@ -54,8 +54,8 @@ export const defaultState = {
   interfaceLanguage: browserLocale,
   hideScopeNotice: false,
   useStreamingApi: false,
-  mentionsOldPlace: false,
-  mentionsOldStyle: false,
+  mentionsOwnLine: false,
+  mentionsNewStyle: false,
   sidebarRight: undefined, // instance default
   scopeCopy: undefined, // instance default
   subjectLineBehavior: undefined, // instance default
-- 
cgit v1.2.3-70-g09d2


From aec867b30036fd039113e4197ca98566447efec6 Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Thu, 10 Jun 2021 12:08:31 +0300
Subject: Moved greentext to RichContent, improved how first mentions are
 restored, now shows mentions not uh, mention in post body

---
 src/components/mention_link/mention_link.js    |   1 +
 src/components/mentions_line/mentions_line.js  |   8 +-
 src/components/mentions_line/mentions_line.vue |  14 ++--
 src/components/rich_content/rich_content.jsx   | 112 ++++++++++++++++++++++++-
 src/components/status/status.js                |  25 +++++-
 src/components/status/status.vue               |   4 +-
 src/components/status_body/status_body.js      |  60 +++----------
 src/components/status_body/status_body.vue     |  20 +++--
 8 files changed, 166 insertions(+), 78 deletions(-)

(limited to 'src/components/mentions_line/mentions_line.vue')

diff --git a/src/components/mention_link/mention_link.js b/src/components/mention_link/mention_link.js
index acd0f584..559250c5 100644
--- a/src/components/mention_link/mention_link.js
+++ b/src/components/mention_link/mention_link.js
@@ -6,6 +6,7 @@ const MentionLink = {
   name: 'MentionLink',
   props: {
     url: {
+      required: true,
       type: String
     },
     content: {
diff --git a/src/components/mentions_line/mentions_line.js b/src/components/mentions_line/mentions_line.js
index 4b20d861..e52045ec 100644
--- a/src/components/mentions_line/mentions_line.js
+++ b/src/components/mentions_line/mentions_line.js
@@ -4,7 +4,7 @@ import { mapGetters } from 'vuex'
 const MentionsLine = {
   name: 'MentionsLine',
   props: {
-    attentions: {
+    mentions: {
       required: true,
       type: Array
     }
@@ -20,11 +20,11 @@ const MentionsLine = {
     limit () {
       return 6
     },
-    mentions () {
-      return this.attentions.slice(0, this.limit)
+    mentionsComputed () {
+      return this.mentions.slice(0, this.limit)
     },
     extraMentions () {
-      return this.attentions.slice(this.limit)
+      return this.mentions.slice(this.limit)
     },
     manyMentions () {
       return this.extraMentions.length > 0
diff --git a/src/components/mentions_line/mentions_line.vue b/src/components/mentions_line/mentions_line.vue
index 58f3de6f..f4b3abb9 100644
--- a/src/components/mentions_line/mentions_line.vue
+++ b/src/components/mentions_line/mentions_line.vue
@@ -1,11 +1,11 @@
 <template>
   <span class="MentionsLine">
     <MentionLink
-      v-for="mention in mentions"
-      :key="mention.statusnet_profile_url"
+      v-for="mention in mentionsComputed"
+      :key="mention.index"
       class="mention-link"
-      :content="mention.statusnet_profile_url"
-      :url="mention.statusnet_profile_url"
+      :content="mention.content"
+      :url="mention.url"
       :first-mention="false"
     /><span
       v-if="manyMentions"
@@ -17,10 +17,10 @@
       >
         <MentionLink
           v-for="mention in extraMentions"
-          :key="mention.statusnet_profile_url"
+          :key="mention.index"
           class="mention-link"
-          :content="mention.statusnet_profile_url"
-          :url="mention.statusnet_profile_url"
+          :content="mention.content"
+          :url="mention.url"
           :first-mention="false"
         />
       </span><button
diff --git a/src/components/rich_content/rich_content.jsx b/src/components/rich_content/rich_content.jsx
index bb7ae739..db24ca0e 100644
--- a/src/components/rich_content/rich_content.jsx
+++ b/src/components/rich_content/rich_content.jsx
@@ -1,6 +1,7 @@
 import Vue from 'vue'
 import { unescape, flattenDeep } from 'lodash'
 import { convertHtml, getTagName, processTextForEmoji, getAttrs } from 'src/services/mini_html_converter/mini_html_converter.service.js'
+import { processHtml } from 'src/services/tiny_post_html_processor/tiny_post_html_processor.service.js'
 import StillImage from 'src/components/still-image/still-image.vue'
 import MentionLink from 'src/components/mention_link/mention_link.vue'
 
@@ -24,15 +25,25 @@ export default Vue.component('RichContent', {
       required: false,
       type: Boolean,
       default: false
+    },
+    // Meme arrows
+    greentext: {
+      required: false,
+      type: Boolean,
+      default: false
     }
   },
   render (h) {
+    // Pre-process HTML
+    const html = this.greentext ? addGreentext(this.html) : this.html
+
     const renderImage = (tag) => {
       return <StillImage
         {...{ attrs: getAttrs(tag) }}
         class="img"
       />
     }
+
     const renderMention = (attrs, children, encounteredText) => {
       return <MentionLink
         url={attrs.href}
@@ -41,10 +52,12 @@ export default Vue.component('RichContent', {
       />
     }
 
+    // We stop treating mentions as "first" ones when we encounter
+    // non-whitespace text
     let encounteredText = false
     // Processor to use with mini_html_converter
     const processItem = (item) => {
-      // Handle text noes - just add emoji
+      // Handle text nodes - just add emoji
       if (typeof item === 'string') {
         const emptyText = item.trim() === ''
         if (emptyText) {
@@ -72,6 +85,7 @@ export default Vue.component('RichContent', {
           return unescapedItem
         }
       }
+
       // Handle tag nodes
       if (Array.isArray(item)) {
         const [opener, children] = item
@@ -84,8 +98,14 @@ export default Vue.component('RichContent', {
             const attrs = getAttrs(opener)
             if (attrs['class'] && attrs['class'].includes('mention')) {
               return renderMention(attrs, children, encounteredText)
+            } else {
+              attrs.target = '_blank'
+              return <a {...{ attrs }}>
+                { children.map(processItem) }
+              </a>
             }
         }
+
         // Render tag as is
         if (children !== undefined) {
           return <Tag {...{ attrs: getAttrs(opener) }}>
@@ -97,7 +117,95 @@ export default Vue.component('RichContent', {
       }
     }
     return <span class="RichContent">
-      { convertHtml(this.html).map(processItem) }
+      { this.$slots.prefix }
+      { convertHtml(html).map(processItem) }
+      { this.$slots.suffix }
     </span>
   }
 })
+
+export const addGreentext = (html) => {
+  try {
+    if (html.includes('&gt;')) {
+      // This checks if post has '>' at the beginning, excluding mentions so that @mention >impying works
+      return processHtml(html, (string) => {
+        if (
+          string.includes('&gt;') && string
+            .replace(/<[^>]+?>/gi, '') // remove all tags
+            .replace(/@\w+/gi, '') // remove mentions (even failed ones)
+            .trim()
+            .startsWith('&gt;')
+        ) {
+          return `<span class='greentext'>${string}</span>`
+        } else {
+          return string
+        }
+      })
+    } else {
+      return html
+    }
+  } catch (e) {
+    console.error('Failed to process status html', e)
+    return html
+  }
+}
+
+export const getHeadTailLinks = (html) => {
+  // Exported object properties
+  const firstMentions = [] // Mentions that appear in the beginning of post body
+  const lastTags = [] // Tags that appear at the end of post body
+  const writtenMentions = [] // All mentions that appear in post body
+  const writtenTags = [] // All tags that appear in post body
+
+  let encounteredText = false
+  let processingFirstMentions = true
+  let index = 0 // unique index for vue "tag" property
+
+  const getLinkData = (attrs, children, index) => {
+    return {
+      index,
+      url: attrs.href,
+      hashtag: attrs['data-tag'],
+      content: flattenDeep(children).join('')
+    }
+  }
+
+  // Processor to use with mini_html_converter
+  const processItem = (item) => {
+    // Handle text nodes - stop treating mentions as "first" when text encountered
+    if (typeof item === 'string') {
+      const emptyText = item.trim() === ''
+      if (emptyText) return
+      if (!encounteredText) {
+        encounteredText = true
+        processingFirstMentions = false
+      }
+      // Encountered text? That means tags we've been collectings aren't "last"!
+      lastTags.splice(0)
+      return
+    }
+    // Handle tag nodes
+    if (Array.isArray(item)) {
+      const [opener, children] = item
+      const Tag = getTagName(opener)
+      if (Tag !== 'a') return children && children.forEach(processItem)
+      const attrs = getAttrs(opener)
+      if (attrs['class']) {
+        const linkData = getLinkData(attrs, children, index++)
+        if (attrs['class'].includes('mention')) {
+          if (processingFirstMentions) {
+            firstMentions.push(linkData)
+          }
+          writtenMentions.push(linkData)
+        } else if (attrs['class'].includes('hashtag')) {
+          lastTags.push(linkData)
+          writtenTags.push(linkData)
+        }
+        return // Stop processing, we don't care about link's contents
+      }
+      children && children.forEach(processItem)
+    }
+  }
+  convertHtml(html).forEach(processItem)
+  return { firstMentions, writtenMentions, writtenTags, lastTags }
+}
diff --git a/src/components/status/status.js b/src/components/status/status.js
index 54472525..0498f28a 100644
--- a/src/components/status/status.js
+++ b/src/components/status/status.js
@@ -19,6 +19,7 @@ import generateProfileLink from 'src/services/user_profile_link_generator/user_p
 import { highlightClass, highlightStyle } from '../../services/user_highlighter/user_highlighter.js'
 import { muteWordHits } from '../../services/status_parser/status_parser.js'
 import { unescape, uniqBy } from 'lodash'
+import { getHeadTailLinks } from 'src/components/rich_content/rich_content.jsx'
 
 import { library } from '@fortawesome/fontawesome-svg-core'
 import {
@@ -166,17 +167,33 @@ const Status = {
     muteWordHits () {
       return muteWordHits(this.status, this.muteWords)
     },
-    mentionsOwnLine () {
-      return this.mergedConfig.mentionsOwnLine
+    headTailLinks () {
+      return getHeadTailLinks(this.status.raw_html)
     },
     mentions () {
       return this.status.attentions.filter(attn => {
         return attn.screen_name !== this.replyToName &&
           attn.screen_name !== this.status.user.screen_name
+      }).map(attn => ({
+        url: attn.statusnet_profile_url,
+        content: attn.screen_name,
+        userId: attn.id
+      }))
+    },
+    alsoMentions () {
+      const set = new Set(this.headTailLinks.writtenMentions.map(m => m.url))
+      return this.headTailLinks.writtenMentions.filter(mention => {
+        return !set.has(mention.url)
       })
     },
-    hasMentions () {
-      return this.mentions.length > 0
+    mentionsLine () {
+      return this.mentionsOwnLine ? this.mentions : this.alsoMentions
+    },
+    mentionsOwnLine () {
+      return this.mergedConfig.mentionsOwnLine
+    },
+    hasMentionsLine () {
+      return this.mentionsLine.length > 0
     },
     muted () {
       if (this.statusoid.user.id === this.currentUser.id) return false
diff --git a/src/components/status/status.vue b/src/components/status/status.vue
index f27fbaa5..05d22232 100644
--- a/src/components/status/status.vue
+++ b/src/components/status/status.vue
@@ -294,7 +294,7 @@
             </div>
 
             <div
-              v-if="hasMentions && mentionsOwnLine"
+              v-if="hasMentionsLine"
               class="heading-mentions-row"
             >
               <div
@@ -316,7 +316,7 @@
                   </span>
                 </span>
                 <MentionsLine
-                  :attentions="mentions"
+                  :mentions="mentionsLine"
                   class="mentions-line"
                 />
               </div>
diff --git a/src/components/status_body/status_body.js b/src/components/status_body/status_body.js
index 3c092ac7..dbabd208 100644
--- a/src/components/status_body/status_body.js
+++ b/src/components/status_body/status_body.js
@@ -1,8 +1,6 @@
 import fileType from 'src/services/file_type/file_type.service'
-import RichContent from 'src/components/rich_content/rich_content.jsx'
+import RichContent, { getHeadTailLinks } from 'src/components/rich_content/rich_content.jsx'
 import MentionsLine from 'src/components/mentions_line/mentions_line.vue'
-import { processHtml } from 'src/services/tiny_post_html_processor/tiny_post_html_processor.service.js'
-import { extractTagFromUrl } from 'src/services/matcher/matcher.service.js'
 import { mapGetters } from 'vuex'
 import { library } from '@fortawesome/fontawesome-svg-core'
 import {
@@ -28,7 +26,10 @@ const StatusContent = {
     'focused',
     'noHeading',
     'fullContent',
-    'singleLine'
+    'singleLine',
+    // if this was computed at upper level it can be passed here, otherwise
+    // it will be in this component
+    'headTailLinks'
   ],
   data () {
     return {
@@ -72,44 +73,18 @@ const StatusContent = {
     showingMore () {
       return (this.mightHideBecauseTall && this.showingTall) || (this.mightHideBecauseSubject && this.expandingSubject)
     },
-    postBodyHtml () {
-      const html = this.status.raw_html
-
-      if (this.mergedConfig.greentext) {
-        try {
-          if (html.includes('&gt;')) {
-            // This checks if post has '>' at the beginning, excluding mentions so that @mention >impying works
-            return processHtml(html, (string) => {
-              if (string.includes('&gt;') &&
-                  string
-                    .replace(/<[^>]+?>/gi, '') // remove all tags
-                    .replace(/@\w+/gi, '') // remove mentions (even failed ones)
-                    .trim()
-                    .startsWith('&gt;')) {
-                return `<span class='greentext'>${string}</span>`
-              } else {
-                return string
-              }
-            })
-          } else {
-            return html
-          }
-        } catch (e) {
-          console.error('Failed to process status html', e)
-          return html
-        }
-      } else {
-        return html
-      }
-    },
     attachmentTypes () {
       return this.status.attachments.map(file => fileType.fileType(file.mimetype))
     },
     mentionsOwnLine () {
       return this.mergedConfig.mentionsOwnLine
     },
+    headTailLinksComputed () {
+      if (this.headTailLinks) return this.headTailLinks
+      return getHeadTailLinks(this.status.raw_html)
+    },
     mentions () {
-      return this.status.attentions
+      return this.headTailLinksComputed.firstMentions
     },
     ...mapGetters(['mergedConfig'])
   },
@@ -124,21 +99,6 @@ const StatusContent = {
     })
   },
   methods: {
-    linkClicked (event) {
-      const target = event.target.closest('.status-content a')
-      if (target) {
-        if (target.rel.match(/(?:^|\s)tag(?:$|\s)/) || target.className.match(/hashtag/)) {
-          // Extract tag name from dataset or link url
-          const tag = target.dataset.tag || extractTagFromUrl(target.href)
-          if (tag) {
-            const link = this.generateTagLink(tag)
-            this.$router.push(link)
-            return
-          }
-        }
-        window.open(target.href, '_blank')
-      }
-    },
     toggleShowMore () {
       if (this.mightHideBecauseTall) {
         this.showingTall = !this.showingTall
diff --git a/src/components/status_body/status_body.vue b/src/components/status_body/status_body.vue
index fae2d594..ff919211 100644
--- a/src/components/status_body/status_body.vue
+++ b/src/components/status_body/status_body.vue
@@ -10,7 +10,6 @@
           class="media-body summary"
           :html="status.summary_raw_html"
           :emoji="status.emojis"
-          @click.prevent="linkClicked"
         />
         <button
           v-if="longSubject && showingLongSubject"
@@ -43,19 +42,22 @@
           class="text-wrapper"
           v-if="!hideSubjectStatus && !(singleLine && status.summary_html)"
         >
-          <MentionsLine
-            v-if="!mentionsOwnLine"
-            :attentions="status.attentions"
-            class="mentions-line"
-          />
           <RichContent
             :class="{ '-single-line': singleLine }"
             class="text media-body"
-            :html="postBodyHtml"
+            :html="status.raw_html"
             :emoji="status.emojis"
             :handle-links="true"
-            @click.prevent="linkClicked"
-          />
+            :greentext="mergedConfig.greentext"
+          >
+            <template v-slot:prefix>
+              <MentionsLine
+                v-if="!mentionsOwnLine"
+                :mentions="mentions"
+                class="mentions-line"
+              />
+            </template>
+          </RichContent>
         </span>
 
         <button
-- 
cgit v1.2.3-70-g09d2


From 2cfff1b8b9c642e9284483d6658312d9a3763417 Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Thu, 12 Aug 2021 02:49:37 +0300
Subject: remove new options for style and separate line, now groups all
 chained mentions on a mentionsline regardless of placement. fixes spacing

---
 src/components/mention_link/mention_link.js        |   6 +-
 src/components/mention_link/mention_link.scss      |  41 ---
 src/components/mention_link/mention_link.vue       |   3 +-
 src/components/mentions_line/mentions_line.js      |  15 +-
 src/components/mentions_line/mentions_line.scss    |  15 +-
 src/components/mentions_line/mentions_line.vue     |   6 +-
 src/components/rich_content/rich_content.jsx       | 128 ++-----
 src/components/settings_modal/tabs/general_tab.vue |  10 -
 src/components/status/status.js                    |   5 +-
 src/components/status/status.vue                   |   1 -
 src/components/status_body/status_body.js          |   3 +-
 src/components/status_body/status_body.vue         |   1 -
 src/components/status_content/status_content.js    |   3 +-
 src/components/status_content/status_content.vue   |   1 -
 src/modules/config.js                              |   2 -
 test/unit/specs/components/rich_content.spec.js    | 399 +--------------------
 16 files changed, 55 insertions(+), 584 deletions(-)

(limited to 'src/components/mentions_line/mentions_line.vue')

diff --git a/src/components/mention_link/mention_link.js b/src/components/mention_link/mention_link.js
index eec116db..a60a8040 100644
--- a/src/components/mention_link/mention_link.js
+++ b/src/components/mention_link/mention_link.js
@@ -65,9 +65,6 @@ const MentionLink = {
     highlightClass () {
       if (this.highlight) return highlightClass(this.user)
     },
-    oldStyle () {
-      return !this.mergedConfig.mentionsNewStyle
-    },
     style () {
       if (this.highlight) {
         const {
@@ -83,8 +80,7 @@ const MentionLink = {
       return [
         {
           '-you': this.isYou,
-          '-highlighted': this.highlight,
-          '-oldStyle': this.oldStyle
+          '-highlighted': this.highlight
         },
         this.highlightType
       ]
diff --git a/src/components/mention_link/mention_link.scss b/src/components/mention_link/mention_link.scss
index 5f5da98f..ec2689f8 100644
--- a/src/components/mention_link/mention_link.scss
+++ b/src/components/mention_link/mention_link.scss
@@ -10,10 +10,6 @@
     border-radius: 2px;
   }
 
-  .original {
-    margin-right: 0.25em;
-  }
-
   .full {
     position: absolute;
     display: inline-block;
@@ -41,8 +37,6 @@
   }
 
   .new {
-    margin-right: 0.25em;
-
     &.-you {
       & .shortName,
       & .full {
@@ -61,41 +55,6 @@
       margin: 0;
     }
 
-    &:not(.-oldStyle) {
-      .short {
-        padding-left: 0.25em;
-        padding-right: 0;
-        padding-top: 0;
-        padding-bottom: 0;
-        line-height: 1.5;
-        font-size: inherit;
-
-        .at {
-          color: var(--faint);
-          opacity: 0.8;
-          padding-right: 0.25em;
-          vertical-align: -20%;
-        }
-      }
-
-      .you {
-        padding-right: 0.25em;
-      }
-
-      .userName {
-        display: inline-block;
-        color: var(--link);
-        line-height: inherit;
-        margin-left: 0;
-        padding-left: 0.125em;
-        padding-right: 0.25em;
-        padding-top: 0;
-        padding-bottom: 0;
-        border-top-right-radius: var(--btnRadius);
-        border-bottom-right-radius: var(--btnRadius);
-      }
-    }
-
     &.-striped {
       & .userName,
       & .full {
diff --git a/src/components/mention_link/mention_link.vue b/src/components/mention_link/mention_link.vue
index 514b7475..625eb727 100644
--- a/src/components/mention_link/mention_link.vue
+++ b/src/components/mention_link/mention_link.vue
@@ -18,8 +18,7 @@
       :class="classnames"
     >
       <button
-        class="short"
-        :class="[{ '-sublime': !highlight }, oldStyle ? 'button-unstyled' : 'button-default']"
+        class="short button-unstyled"
         @click.prevent="onClick"
       >
         <!-- eslint-disable vue/no-v-html -->
diff --git a/src/components/mentions_line/mentions_line.js b/src/components/mentions_line/mentions_line.js
index e52045ec..33e25391 100644
--- a/src/components/mentions_line/mentions_line.js
+++ b/src/components/mentions_line/mentions_line.js
@@ -14,11 +14,8 @@ const MentionsLine = {
     MentionLink
   },
   computed: {
-    oldStyle () {
-      return !this.mergedConfig.mentionsNewStyle
-    },
     limit () {
-      return 6
+      return 2
     },
     mentionsComputed () {
       return this.mentions.slice(0, this.limit)
@@ -29,16 +26,6 @@ const MentionsLine = {
     manyMentions () {
       return this.extraMentions.length > 0
     },
-    buttonClasses () {
-      return [
-        this.oldStyle
-          ? 'button-unstyled'
-          : 'button-default -sublime',
-        this.oldStyle
-          ? '-oldStyle'
-          : '-newStyle'
-      ]
-    },
     ...mapGetters(['mergedConfig'])
   },
   methods: {
diff --git a/src/components/mentions_line/mentions_line.scss b/src/components/mentions_line/mentions_line.scss
index 90d1e0a4..222940c8 100644
--- a/src/components/mentions_line/mentions_line.scss
+++ b/src/components/mentions_line/mentions_line.scss
@@ -1,17 +1,10 @@
 .MentionsLine {
   .showMoreLess {
     white-space: normal;
+    color: var(--link);
+  }
 
-    &.-newStyle {
-      line-height: 1.5;
-      font-size: inherit;
-      display: inline-block;
-      padding-top: 0;
-      padding-bottom: 0;
-    }
-
-    &.-oldStyle {
-      color: var(--link);
-    }
+  .mention-link:not(:last-child) {
+    margin-right: 0.25em;
   }
 }
diff --git a/src/components/mentions_line/mentions_line.vue b/src/components/mentions_line/mentions_line.vue
index f4b3abb9..f375e3b0 100644
--- a/src/components/mentions_line/mentions_line.vue
+++ b/src/components/mentions_line/mentions_line.vue
@@ -25,15 +25,13 @@
         />
       </span><button
         v-if="!expanded"
-        class="showMoreLess"
-        :class="buttonClasses"
+        class="button-unstyled showMoreLess"
         @click="toggleShowMore"
       >
         {{ $t('status.plus_more', { number: extraMentions.length }) }}
       </button><button
         v-if="expanded"
-        class="showMoreLess"
-        :class="buttonClasses"
+        class="button-unstyled showMoreLess"
         @click="toggleShowMore"
       >
         {{ $t('general.show_less') }}
diff --git a/src/components/rich_content/rich_content.jsx b/src/components/rich_content/rich_content.jsx
index cd73f2e5..4b7d4d37 100644
--- a/src/components/rich_content/rich_content.jsx
+++ b/src/components/rich_content/rich_content.jsx
@@ -56,25 +56,21 @@ export default Vue.component('RichContent', {
       required: false,
       type: Boolean,
       default: false
-    },
-    hideMentions: {
-      required: false,
-      type: Boolean,
-      default: false
     }
   },
   // NEVER EVER TOUCH DATA INSIDE RENDER
   render (h) {
     // Pre-process HTML
-    const { newHtml: html, lastMentions } = preProcessPerLine(this.html, this.greentext, this.handleLinks)
-    const firstMentions = [] // Mentions that appear in the beginning of post body
+    const { newHtml: html } = preProcessPerLine(this.html, this.greentext, this.handleLinks)
+    let currentMentions = null // Current chain of mentions, we group all mentions together
+    // to collapse too many mentions in a row
+
     const lastTags = [] // Tags that appear at the end of post body
     const writtenMentions = [] // All mentions that appear in post body
     const writtenTags = [] // All tags that appear in post body
     // unique index for vue "tag" property
     let mentionIndex = 0
     let tagsIndex = 0
-    let firstMentionReplaced = false
 
     const renderImage = (tag) => {
       return <StillImage
@@ -98,41 +94,32 @@ export default Vue.component('RichContent', {
     const renderMention = (attrs, children) => {
       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)
-      if (!encounteredText) {
-        firstMentions.push(linkData)
-        if (!firstMentionReplaced && !this.hideMentions) {
-          firstMentionReplaced = true
-          return <MentionsLine mentions={ firstMentions } />
-        } else {
-          return ''
-        }
+      if (currentMentions === null) {
+        currentMentions = []
+      }
+      currentMentions.push(linkData)
+      if (currentMentions.length === 1) {
+        return <MentionsLine mentions={ currentMentions } />
       } else {
-        return <MentionLink
-          url={attrs.href}
-          content={flattenDeep(children).join('')}
-        />
+        return ''
       }
     }
 
-    // We stop treating mentions as "first" ones when we encounter
-    // non-whitespace text
-    let encounteredText = false
     // Processor to use with html_tree_converter
     const processItem = (item, index, array, what) => {
       // Handle text nodes - just add emoji
       if (typeof item === 'string') {
         const emptyText = item.trim() === ''
-        if (emptyText) {
-          return encounteredText ? item : item.trim()
+        if (item.includes('\n')) {
+          currentMentions = null
         }
-        if (!encounteredText) {
-          item = item.trimStart()
-          encounteredText = true
+        if (emptyText) {
+          // don't include spaces when processing mentions - we'll include them
+          // in MentionsLine
+          return currentMentions !== null ? item.trim() : item
         }
+        currentMentions = null
         if (item.includes(':')) {
           item = ['', processTextForEmoji(
             item,
@@ -156,28 +143,25 @@ export default Vue.component('RichContent', {
         const Tag = getTagName(opener)
         const attrs = getAttrs(opener)
         switch (Tag) {
-          case 'span': // Replace last mentions class with mentionsline
-            if (attrs['class'] && attrs['class'].includes('lastMentions')) {
-              if (firstMentions.length > 1 && lastMentions.length > 1) {
-                break
-              } else {
-                return !this.hideMentions ? <MentionsLine mentions={lastMentions} /> : ''
-              }
-            } else {
-              break
-            }
+          case 'br':
+            currentMentions = null
+            break
           case 'img': // replace images with StillImage
             return 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, encounteredText)
+              return renderMention(attrs, children)
             } else {
               // Everything else will be handled in reverse pass
-              encounteredText = true
+              currentMentions = null
               return item // We'll handle it later
             }
+          case 'span':
+            if (attrs['class'].includes('h-card')) {
+              return ['', children.map(processItem), '']
+            }
         }
 
         if (children !== undefined) {
@@ -246,8 +230,6 @@ export default Vue.component('RichContent', {
     </span>
 
     const event = {
-      firstMentions,
-      lastMentions,
       lastTags,
       writtenMentions,
       writtenTags
@@ -284,15 +266,12 @@ export const preProcessPerLine = (html, greentext, handleLinks) => {
   const lastMentions = []
   const greentextHandle = new Set(['p', 'div'])
 
-  let nonEmptyIndex = -1
   const lines = convertHtmlToLines(html)
-  const linesNum = lines.filter(c => c.text).length
   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
-    nonEmptyIndex += 1
 
     // Greentext stuff
     if (
@@ -316,42 +295,19 @@ export const preProcessPerLine = (html, greentext, handleLinks) => {
     // Converting that line part into tree
     const tree = convertHtmlToTree(string)
 
-    // If line has loose text, i.e. text outside a mention or a tag
-    // we won't touch mentions.
-    let hasLooseText = false
-    let mentionsNum = 0
     const process = (item) => {
       if (Array.isArray(item)) {
         const [opener, children, closer] = item
         const tag = getTagName(opener)
-        // If we have a link we probably have mentions
-        if (tag === 'a') {
-          if (!handleLinks) return [opener, children, closer]
-          const attrs = getAttrs(opener)
-          if (attrs['class'] && attrs['class'].includes('mention')) {
-            // Got mentions
-            mentionsNum++
-            return [opener, children, closer]
-          } else {
-            // Not a mention? Means we have loose text or whatever
-            hasLooseText = true
-            return [opener, children, closer]
-          }
-        } else if (tag === 'span' || tag === 'p') {
+        if (tag === 'span' || tag === 'p') {
           // For span and p we need to go deeper
           return [opener, [...children].map(process), closer]
         } else {
-          // Everything else equals to a loose text
-          hasLooseText = true
           return [opener, children, closer]
         }
       }
 
       if (typeof item === 'string') {
-        if (item.trim() !== '') {
-          // only meaningful strings are loose text
-          hasLooseText = true
-        }
         return item
       }
     }
@@ -359,33 +315,7 @@ export const preProcessPerLine = (html, greentext, handleLinks) => {
     // We now processed our tree, now we need to mark line as lastMentions
     const result = [...tree].map(process)
 
-    if (
-      handleLinks && // Do we handle links at all?
-        mentionsNum > 1 && // Does it have more than one mention?
-        !hasLooseText && // Don't do anything if it has something besides mentions
-        nonEmptyIndex === 0 && // Only check last (first since list is reversed) line
-        nonEmptyIndex !== linesNum - 1 // Don't do anything if there's only one line
-    ) {
-      let mentionIndex = 0
-      const process = (item) => {
-        if (Array.isArray(item)) {
-          const [opener, children] = item
-          const tag = getTagName(opener)
-          if (tag === 'a') {
-            const attrs = getAttrs(opener)
-            lastMentions.push(getLinkData(attrs, children, mentionIndex++))
-          } else if (children) {
-            children.forEach(process)
-          }
-        }
-      }
-      result.forEach(process)
-      // we DO need mentions here so that we conditionally remove them if don't
-      // have first mentions
-      return ['<span class="lastMentions">', flattenDeep(result).join(''), '</span>'].join('')
-    } else {
-      return flattenDeep(result).join('')
-    }
+    return flattenDeep(result).join('')
   }).reverse().join('')
 
   return { newHtml, lastMentions }
diff --git a/src/components/settings_modal/tabs/general_tab.vue b/src/components/settings_modal/tabs/general_tab.vue
index 71780e00..d3e71b31 100644
--- a/src/components/settings_modal/tabs/general_tab.vue
+++ b/src/components/settings_modal/tabs/general_tab.vue
@@ -41,16 +41,6 @@
             {{ $t('settings.collapse_subject') }}
           </BooleanSetting>
         </li>
-        <li>
-          <BooleanSetting path="mentionsOwnLine">
-            {{ $t('settings.mentions_new_place') }}
-          </BooleanSetting>
-        </li>
-        <li>
-          <BooleanSetting path="mentionsNewStyle">
-            {{ $t('settings.mentions_new_style') }}
-          </BooleanSetting>
-        </li>
         <li>
           <BooleanSetting path="streaming">
             {{ $t('settings.streaming') }}
diff --git a/src/components/status/status.js b/src/components/status/status.js
index 3c21cb76..8aa73a22 100644
--- a/src/components/status/status.js
+++ b/src/components/status/status.js
@@ -184,10 +184,7 @@ const Status = {
       })
     },
     mentionsLine () {
-      return this.mentionsOwnLine ? this.mentions : this.alsoMentions
-    },
-    mentionsOwnLine () {
-      return this.mergedConfig.mentionsOwnLine
+      return this.alsoMentions
     },
     hasMentionsLine () {
       return this.mentionsLine.length > 0
diff --git a/src/components/status/status.vue b/src/components/status/status.vue
index a5f347a6..2684e415 100644
--- a/src/components/status/status.vue
+++ b/src/components/status/status.vue
@@ -306,7 +306,6 @@
             :no-heading="noHeading"
             :highlight="highlight"
             :focused="isFocused"
-            :hide-mentions="mentionsOwnLine && (isReply || true)"
             @mediaplay="addMediaPlaying($event)"
             @mediapause="removeMediaPlaying($event)"
             @parseReady="setHeadTailLinks"
diff --git a/src/components/status_body/status_body.js b/src/components/status_body/status_body.js
index d1736ba3..8757154d 100644
--- a/src/components/status_body/status_body.js
+++ b/src/components/status_body/status_body.js
@@ -25,8 +25,7 @@ const StatusContent = {
     'focused',
     'noHeading',
     'fullContent',
-    'singleLine',
-    'hideMentions'
+    'singleLine'
   ],
   data () {
     return {
diff --git a/src/components/status_body/status_body.vue b/src/components/status_body/status_body.vue
index d77ccd54..9f01c470 100644
--- a/src/components/status_body/status_body.vue
+++ b/src/components/status_body/status_body.vue
@@ -45,7 +45,6 @@
           :html="status.raw_html"
           :emoji="status.emojis"
           :handle-links="true"
-          :hide-mentions="hideMentions"
           :greentext="mergedConfig.greentext"
           :attentions="status.attentions"
           @parseReady="onParseReady"
diff --git a/src/components/status_content/status_content.js b/src/components/status_content/status_content.js
index 51895ef6..1b80ee09 100644
--- a/src/components/status_content/status_content.js
+++ b/src/components/status_content/status_content.js
@@ -31,8 +31,7 @@ const StatusContent = {
     'focused',
     'noHeading',
     'fullContent',
-    'singleLine',
-    'hideMentions'
+    'singleLine'
   ],
   computed: {
     hideAttachments () {
diff --git a/src/components/status_content/status_content.vue b/src/components/status_content/status_content.vue
index 2e71757d..23c90913 100644
--- a/src/components/status_content/status_content.vue
+++ b/src/components/status_content/status_content.vue
@@ -4,7 +4,6 @@
     <StatusBody
       :status="status"
       :single-line="singleLine"
-      :hide-mentions="hideMentions"
       @parseReady="$emit('parseReady', $event)"
     >
       <div v-if="status.poll && status.poll.options">
diff --git a/src/modules/config.js b/src/modules/config.js
index db9d5ffb..bdab3f4d 100644
--- a/src/modules/config.js
+++ b/src/modules/config.js
@@ -55,8 +55,6 @@ export const defaultState = {
   interfaceLanguage: browserLocale,
   hideScopeNotice: false,
   useStreamingApi: false,
-  mentionsOwnLine: false,
-  mentionsNewStyle: false,
   sidebarRight: undefined, // instance default
   scopeCopy: undefined, // instance default
   subjectLineBehavior: undefined, // instance default
diff --git a/test/unit/specs/components/rich_content.spec.js b/test/unit/specs/components/rich_content.spec.js
index 9ac9bedb..dfc229c0 100644
--- a/test/unit/specs/components/rich_content.spec.js
+++ b/test/unit/specs/components/rich_content.spec.js
@@ -8,11 +8,13 @@ const makeMention = (who) => {
   attentions.push({ statusnet_profile_url: `https://fake.tld/@${who}` })
   return `<span class="h-card"><a class="u-url mention" href="https://fake.tld/@${who}">@<span>${who}</span></a></span>`
 }
-const stubMention = (who) => `<span class="h-card"><mentionlink-stub url="https://fake.tld/@${who}" content="@<span>${who}</span>"></mentionlink-stub></span>`
-const lastMentions = (...data) => `<span class="lastMentions">${data.join('')}</span>`
 const p = (...data) => `<p>${data.join('')}</p>`
 const compwrap = (...data) => `<span class="RichContent">${data.join('')}</span>`
-const removedMentionSpan = '<span class="h-card"></span>'
+const mentionsLine = (times) => [
+  '<mentionsline-stub mentions="',
+  new Array(times).fill('[object Object]').join(','),
+  '"></mentionsline-stub>'
+].join('')
 
 describe('RichContent', () => {
   it('renders simple post without exploding', () => {
@@ -21,7 +23,6 @@ describe('RichContent', () => {
       localVue,
       propsData: {
         attentions,
-        hideMentions: true,
         handleLinks: true,
         greentext: true,
         emoji: [],
@@ -45,7 +46,6 @@ describe('RichContent', () => {
       localVue,
       propsData: {
         attentions,
-        hideMentions: true,
         handleLinks: true,
         greentext: true,
         emoji: [],
@@ -56,20 +56,15 @@ describe('RichContent', () => {
     expect(wrapper.html()).to.eql(compwrap(expected))
   })
 
-  it('removes mentions from the beginning of post', () => {
+  it('replaces first mention with mentionsline', () => {
     const html = p(
       makeMention('John'),
-      ' how are you doing thoday?'
-    )
-    const expected = p(
-      removedMentionSpan,
-      'how are you doing thoday?'
+      ' how are you doing today?'
     )
     const wrapper = shallowMount(RichContent, {
       localVue,
       propsData: {
         attentions,
-        hideMentions: true,
         handleLinks: true,
         greentext: true,
         emoji: [],
@@ -77,70 +72,13 @@ describe('RichContent', () => {
       }
     })
 
-    expect(wrapper.html()).to.eql(compwrap(expected))
+    expect(wrapper.html()).to.eql(compwrap(p(
+      mentionsLine(1),
+      ' how are you doing today?'
+    )))
   })
 
-  it('replaces first mention with mentionsline if hideMentions=false', () => {
-    const html = p(
-      makeMention('John'),
-      ' how are you doing thoday?'
-    )
-    const expected = p(
-      '<span class="h-card">',
-      '<mentionsline-stub mentions="',
-      '[object Object]',
-      '"></mentionsline-stub>',
-      '</span>',
-      'how are you doing thoday?'
-    )
-    const wrapper = shallowMount(RichContent, {
-      localVue,
-      propsData: {
-        attentions,
-        hideMentions: false,
-        handleLinks: true,
-        greentext: true,
-        emoji: [],
-        html
-      }
-    })
-
-    expect(wrapper.html()).to.eql(compwrap(expected))
-  })
-
-  it('removes mentions from the end of the hellpost (<p>)', () => {
-    const html = [
-      p('How are you doing today, fine gentlemen?'),
-      p(
-        makeMention('John'),
-        makeMention('Josh'),
-        makeMention('Jeremy')
-      )
-    ].join('')
-    const expected = [
-      p(
-        'How are you doing today, fine gentlemen?'
-      ),
-      // TODO fix this extra line somehow?
-      p()
-    ].join('')
-
-    const wrapper = shallowMount(RichContent, {
-      localVue,
-      propsData: {
-        attentions,
-        hideMentions: true,
-        handleLinks: true,
-        greentext: true,
-        emoji: [],
-        html
-      }
-    })
-
-    expect(wrapper.html()).to.eql(compwrap(expected))
-  })
-
-  it('replaces mentions at the end of the hellpost if hideMentions=false (<p>)', () => {
+  it('replaces mentions at the end of the hellpost', () => {
     const html = [
       p('How are you doing today, fine gentlemen?'),
       p(
@@ -167,189 +105,6 @@ describe('RichContent', () => {
       localVue,
       propsData: {
         attentions,
-        hideMentions: false,
-        handleLinks: true,
-        greentext: true,
-        emoji: [],
-        html
-      }
-    })
-
-    expect(wrapper.html()).to.eql(compwrap(expected))
-  })
-
-  it('removes mentions from the end of the hellpost (<br>)', () => {
-    const html = [
-      'How are you doing today, fine gentlemen?',
-      [
-        makeMention('John'),
-        makeMention('Josh'),
-        makeMention('Jeremy')
-      ].join('')
-    ].join('<br>')
-    const expected = [
-      'How are you doing today, fine gentlemen?',
-      // TODO fix this extra line somehow?
-      '<br>'
-    ].join('')
-
-    const wrapper = shallowMount(RichContent, {
-      localVue,
-      propsData: {
-        attentions,
-        hideMentions: true,
-        handleLinks: true,
-        greentext: true,
-        emoji: [],
-        html
-      }
-    })
-
-    expect(wrapper.html()).to.eql(compwrap(expected))
-  })
-
-  it('removes mentions from the end of the hellpost (\\n)', () => {
-    const html = [
-      'How are you doing today, fine gentlemen?',
-      [
-        makeMention('John'),
-        makeMention('Josh'),
-        makeMention('Jeremy')
-      ].join('')
-    ].join('\n')
-    const expected = [
-      'How are you doing today, fine gentlemen?',
-      // TODO fix this extra line somehow?
-      ''
-    ].join('\n')
-
-    const wrapper = shallowMount(RichContent, {
-      localVue,
-      propsData: {
-        attentions,
-        hideMentions: true,
-        handleLinks: true,
-        greentext: true,
-        emoji: [],
-        html
-      }
-    })
-
-    expect(wrapper.html()).to.eql(compwrap(expected))
-  })
-
-  it('Does not remove mentions in the middle or at the end of text string', () => {
-    const html = [
-      [
-        makeMention('Jack'),
-        'let\'s meet up with ',
-        makeMention('Janet')
-      ].join(''),
-      [
-        'cc: ',
-        makeMention('John'),
-        makeMention('Josh'),
-        makeMention('Jeremy')
-      ].join('')
-    ].join('\n')
-    const expected = [
-      [
-        removedMentionSpan,
-        'let\'s meet up with ',
-        stubMention('Janet')
-      ].join(''),
-      [
-        'cc: ',
-        stubMention('John'),
-        stubMention('Josh'),
-        stubMention('Jeremy')
-      ].join('')
-    ].join('\n')
-
-    const wrapper = shallowMount(RichContent, {
-      localVue,
-      propsData: {
-        attentions,
-        hideMentions: true,
-        handleLinks: true,
-        greentext: true,
-        emoji: [],
-        html
-      }
-    })
-
-    expect(wrapper.html()).to.eql(compwrap(expected))
-  })
-
-  it('removes mentions from the end if there\'s only one first mention', () => {
-    const html = [
-      p(
-        makeMention('Todd'),
-        'so anyway you are wrong'
-      ),
-      p(
-        makeMention('Tom'),
-        makeMention('Trace'),
-        makeMention('Theodor')
-      )
-    ].join('')
-    const expected = [
-      p(
-        removedMentionSpan,
-        'so anyway you are wrong'
-      ),
-      // TODO fix this extra line somehow?
-      p()
-    ].join('')
-
-    const wrapper = shallowMount(RichContent, {
-      localVue,
-      propsData: {
-        attentions,
-        hideMentions: true,
-        handleLinks: true,
-        greentext: true,
-        emoji: [],
-        html
-      }
-    })
-
-    expect(wrapper.html()).to.eql(compwrap(expected))
-  })
-
-  it('does not remove mentions from the end if there\'s more than one first mention', () => {
-    const html = [
-      p(
-        makeMention('Zacharie'),
-        makeMention('Zinaide'),
-        'you guys have cool names, and so do these guys: '
-      ),
-      p(
-        makeMention('Watson'),
-        makeMention('Wallace'),
-        makeMention('Wakamoto')
-      )
-    ].join('')
-    const expected = [
-      p(
-        removedMentionSpan,
-        removedMentionSpan,
-        'you guys have cool names, and so do these guys: '
-      ),
-      p(
-        lastMentions(
-          stubMention('Watson'),
-          stubMention('Wallace'),
-          stubMention('Wakamoto')
-        )
-      )
-    ].join('')
-
-    const wrapper = shallowMount(RichContent, {
-      localVue,
-      propsData: {
-        attentions,
-        hideMentions: true,
         handleLinks: true,
         greentext: true,
         emoji: [],
@@ -378,7 +133,6 @@ describe('RichContent', () => {
       localVue,
       propsData: {
         attentions,
-        hideMentions: true,
         handleLinks: false,
         greentext: true,
         emoji: [],
@@ -403,7 +157,6 @@ describe('RichContent', () => {
       localVue,
       propsData: {
         attentions,
-        hideMentions: true,
         handleLinks: false,
         greentext: true,
         emoji: [],
@@ -424,7 +177,6 @@ describe('RichContent', () => {
       localVue,
       propsData: {
         attentions,
-        hideMentions: true,
         handleLinks: false,
         greentext: false,
         emoji: [],
@@ -446,7 +198,6 @@ describe('RichContent', () => {
       localVue,
       propsData: {
         attentions,
-        hideMentions: true,
         handleLinks: false,
         greentext: false,
         emoji: [{ url: 'about:blank', shortcode: 'spurdo' }],
@@ -464,7 +215,6 @@ describe('RichContent', () => {
       localVue,
       propsData: {
         attentions,
-        hideMentions: true,
         handleLinks: false,
         greentext: false,
         emoji: [],
@@ -484,7 +234,7 @@ describe('RichContent', () => {
     ].join('\n')
     const expected = [
       '<span class="greentext">&gt;quote</span>',
-      stubMention('lol'),
+      mentionsLine(1)
       '<span class="greentext">&gt;quote</span>',
       '<span class="greentext">&gt;quote</span>'
     ].join('\n')
@@ -517,11 +267,7 @@ describe('RichContent', () => {
     const expected = [
       'Bruh',
       'Bruh',
-      [
-        stubMention('foo'),
-        stubMention('bar'),
-        stubMention('baz')
-      ].join(''),
+      mentionsLine(3)
       'Bruh'
     ].join('<br>')
 
@@ -529,119 +275,6 @@ describe('RichContent', () => {
       localVue,
       propsData: {
         attentions,
-        hideMentions: true,
-        handleLinks: true,
-        greentext: true,
-        emoji: [],
-        html
-      }
-    })
-
-    expect(wrapper.html()).to.eql(compwrap(expected))
-  })
-
-  it('Don\'t remove last mention if it\'s the only one', () => {
-    const html = [
-      'Bruh',
-      'Bruh',
-      makeMention('foo'),
-      makeMention('bar'),
-      makeMention('baz')
-    ].join('<br>')
-    const expected = [
-      'Bruh',
-      'Bruh',
-      stubMention('foo'),
-      stubMention('bar'),
-      stubMention('baz')
-    ].join('<br>')
-
-    const wrapper = shallowMount(RichContent, {
-      localVue,
-      propsData: {
-        attentions,
-        hideMentions: true,
-        handleLinks: true,
-        greentext: true,
-        emoji: [],
-        html
-      }
-    })
-
-    expect(wrapper.html()).to.eql(compwrap(expected))
-  })
-
-  it('Don\'t remove last mentions if there are more than one first mention - remove first instead', () => {
-    const html = [
-      [
-        makeMention('foo'),
-        makeMention('bar')
-      ].join(' '),
-      'Bruh',
-      'Bruh',
-      [
-        makeMention('foo'),
-        makeMention('bar'),
-        makeMention('baz')
-      ].join(' ')
-    ].join('\n')
-
-    const expected = [
-      [
-        removedMentionSpan,
-        removedMentionSpan,
-        'Bruh' // Due to trim we remove extra newline
-      ].join(''),
-      'Bruh',
-      lastMentions([
-        stubMention('foo'),
-        stubMention('bar'),
-        stubMention('baz')
-      ].join(' '))
-    ].join('\n')
-
-    const wrapper = shallowMount(RichContent, {
-      localVue,
-      propsData: {
-        attentions,
-        hideMentions: true,
-        handleLinks: true,
-        greentext: true,
-        emoji: [],
-        html
-      }
-    })
-
-    expect(wrapper.html()).to.eql(compwrap(expected))
-  })
-
-  it('Remove last mentions if there\'s just one first mention - remove all', () => {
-    const html = [
-      [
-        makeMention('foo')
-      ].join(' '),
-      'Bruh',
-      'Bruh',
-      [
-        makeMention('foo'),
-        makeMention('bar'),
-        makeMention('baz')
-      ].join(' ')
-    ].join('\n')
-
-    const expected = [
-      [
-        removedMentionSpan,
-        'Bruh' // Due to trim we remove extra newline
-      ].join(''),
-      'Bruh\n' // Can't remove this one yet
-    ].join('\n')
-
-    const wrapper = shallowMount(RichContent, {
-      localVue,
-      propsData: {
-        attentions,
-        hideMentions: true,
         handleLinks: true,
         greentext: true,
         emoji: [],
@@ -678,7 +311,6 @@ describe('RichContent', () => {
       localVue,
       propsData: {
         attentions,
-        hideMentions: true,
         handleLinks: true,
         greentext: true,
         emoji: [],
@@ -726,7 +358,6 @@ describe('RichContent', () => {
       localVue,
       propsData: {
         attentions,
-        hideMentions: false,
         handleLinks: true,
         greentext: true,
         emoji: [],
@@ -781,7 +412,6 @@ describe('RichContent', () => {
       },
       propsData: {
         attentions,
-        hideMentions: false,
         handleLinks: true,
         greentext: true,
         emoji: [],
@@ -826,7 +456,6 @@ describe('RichContent', () => {
       localVue,
       propsData: {
         attentions,
-        hideMentions: false,
         handleLinks: true,
         greentext: true,
         emoji: [],
-- 
cgit v1.2.3-70-g09d2

