Merge remote-tracking branch 'origin/develop' into shigusegubu-vue3
* origin/develop: Use dedicated indicator for non-ascii domain names Update dependency sinon-chai to v3 Update dependency semver to v7 Update dependency vue-router to v4.1.5 Update dependency eslint to v8.23.0 Update dependency vue-template-compiler to v2.7.10 Update dependency @vue/babel-helper-vue-jsx-merge-props to v1.4.0 Update dependency eslint-plugin-promise to v6.0.1 Remove isparta Update dependency @babel/core to v7.18.13
This commit is contained in:
commit
e9adee4517
25 changed files with 285 additions and 600 deletions
17
package.json
17
package.json
|
@ -44,19 +44,19 @@
|
||||||
"utf8": "3.0.0",
|
"utf8": "3.0.0",
|
||||||
"vue": "3.2.37",
|
"vue": "3.2.37",
|
||||||
"vue-i18n": "9.2.2",
|
"vue-i18n": "9.2.2",
|
||||||
"vue-router": "4.1.3",
|
"vue-router": "4.1.5",
|
||||||
"vue-template-compiler": "2.7.9",
|
"vue-template-compiler": "2.7.10",
|
||||||
"vuex": "4.0.2"
|
"vuex": "4.0.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "7.18.10",
|
"@babel/core": "7.18.13",
|
||||||
"@babel/eslint-parser": "7.18.9",
|
"@babel/eslint-parser": "7.18.9",
|
||||||
"@babel/plugin-transform-runtime": "7.18.10",
|
"@babel/plugin-transform-runtime": "7.18.10",
|
||||||
"@babel/preset-env": "7.18.10",
|
"@babel/preset-env": "7.18.10",
|
||||||
"@babel/register": "7.18.9",
|
"@babel/register": "7.18.9",
|
||||||
"@intlify/vue-i18n-loader": "5.0.0",
|
"@intlify/vue-i18n-loader": "5.0.0",
|
||||||
"@ungap/event-target": "0.2.3",
|
"@ungap/event-target": "0.2.3",
|
||||||
"@vue/babel-helper-vue-jsx-merge-props": "1.2.1",
|
"@vue/babel-helper-vue-jsx-merge-props": "1.4.0",
|
||||||
"@vue/babel-plugin-jsx": "1.1.1",
|
"@vue/babel-plugin-jsx": "1.1.1",
|
||||||
"@vue/compiler-sfc": "3.2.37",
|
"@vue/compiler-sfc": "3.2.37",
|
||||||
"@vue/test-utils": "2.0.2",
|
"@vue/test-utils": "2.0.2",
|
||||||
|
@ -72,12 +72,12 @@
|
||||||
"css-loader": "6.7.1",
|
"css-loader": "6.7.1",
|
||||||
"css-minimizer-webpack-plugin": "4.0.0",
|
"css-minimizer-webpack-plugin": "4.0.0",
|
||||||
"custom-event-polyfill": "1.0.7",
|
"custom-event-polyfill": "1.0.7",
|
||||||
"eslint": "8.22.0",
|
"eslint": "8.23.0",
|
||||||
"eslint-config-standard": "17.0.0",
|
"eslint-config-standard": "17.0.0",
|
||||||
"eslint-formatter-friendly": "7.0.0",
|
"eslint-formatter-friendly": "7.0.0",
|
||||||
"eslint-plugin-import": "2.26.0",
|
"eslint-plugin-import": "2.26.0",
|
||||||
"eslint-plugin-n": "15.2.5",
|
"eslint-plugin-n": "15.2.5",
|
||||||
"eslint-plugin-promise": "6.0.0",
|
"eslint-plugin-promise": "6.0.1",
|
||||||
"eslint-plugin-vue": "9.4.0",
|
"eslint-plugin-vue": "9.4.0",
|
||||||
"eslint-webpack-plugin": "3.2.0",
|
"eslint-webpack-plugin": "3.2.0",
|
||||||
"eventsource-polyfill": "0.9.6",
|
"eventsource-polyfill": "0.9.6",
|
||||||
|
@ -86,7 +86,6 @@
|
||||||
"html-webpack-plugin": "5.5.0",
|
"html-webpack-plugin": "5.5.0",
|
||||||
"http-proxy-middleware": "2.0.6",
|
"http-proxy-middleware": "2.0.6",
|
||||||
"iso-639-1": "2.1.15",
|
"iso-639-1": "2.1.15",
|
||||||
"isparta-loader": "2.0.0",
|
|
||||||
"json-loader": "0.5.7",
|
"json-loader": "0.5.7",
|
||||||
"karma": "6.4.0",
|
"karma": "6.4.0",
|
||||||
"karma-coverage": "2.2.0",
|
"karma-coverage": "2.2.0",
|
||||||
|
@ -109,11 +108,11 @@
|
||||||
"sass": "1.54.5",
|
"sass": "1.54.5",
|
||||||
"sass-loader": "13.0.2",
|
"sass-loader": "13.0.2",
|
||||||
"selenium-server": "2.53.1",
|
"selenium-server": "2.53.1",
|
||||||
"semver": "5.7.1",
|
"semver": "7.3.7",
|
||||||
"serviceworker-webpack5-plugin": "2.0.0",
|
"serviceworker-webpack5-plugin": "2.0.0",
|
||||||
"shelljs": "0.8.5",
|
"shelljs": "0.8.5",
|
||||||
"sinon": "2.4.1",
|
"sinon": "2.4.1",
|
||||||
"sinon-chai": "2.14.0",
|
"sinon-chai": "3.7.0",
|
||||||
"stylelint": "13.13.1",
|
"stylelint": "13.13.1",
|
||||||
"stylelint-config-standard": "20.0.0",
|
"stylelint-config-standard": "20.0.0",
|
||||||
"stylelint-rscss": "0.4.0",
|
"stylelint-rscss": "0.4.0",
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import UserPopover from '../user_popover/user_popover.vue'
|
import UserPopover from '../user_popover/user_popover.vue'
|
||||||
import UserAvatar from '../user_avatar/user_avatar.vue'
|
import UserAvatar from '../user_avatar/user_avatar.vue'
|
||||||
|
import UserLink from '../user_link/user_link.vue'
|
||||||
import RichContent from 'src/components/rich_content/rich_content.jsx'
|
import RichContent from 'src/components/rich_content/rich_content.jsx'
|
||||||
import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'
|
import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'
|
||||||
|
|
||||||
|
@ -10,7 +11,8 @@ const BasicUserCard = {
|
||||||
components: {
|
components: {
|
||||||
UserPopover,
|
UserPopover,
|
||||||
UserAvatar,
|
UserAvatar,
|
||||||
RichContent
|
RichContent,
|
||||||
|
UserLink
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
userProfileLink (user) {
|
userProfileLink (user) {
|
||||||
|
|
|
@ -30,12 +30,10 @@
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<router-link
|
<user-link
|
||||||
class="basic-user-card-screen-name"
|
class="basic-user-card-screen-name"
|
||||||
:to="userProfileLink(user)"
|
:user="user"
|
||||||
>
|
/>
|
||||||
@{{ user.screen_name_ui }}
|
|
||||||
</router-link>
|
|
||||||
</div>
|
</div>
|
||||||
<slot />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import Completion from '../../services/completion/completion.js'
|
import Completion from '../../services/completion/completion.js'
|
||||||
import EmojiPicker from '../emoji_picker/emoji_picker.vue'
|
import EmojiPicker from '../emoji_picker/emoji_picker.vue'
|
||||||
|
import UnicodeDomainIndicator from '../unicode_domain_indicator/unicode_domain_indicator.vue'
|
||||||
import { take } from 'lodash'
|
import { take } from 'lodash'
|
||||||
import { findOffset } from '../../services/offset_finder/offset_finder.service.js'
|
import { findOffset } from '../../services/offset_finder/offset_finder.service.js'
|
||||||
|
|
||||||
|
@ -120,7 +121,8 @@ const EmojiInput = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
EmojiPicker
|
EmojiPicker,
|
||||||
|
UnicodeDomainIndicator
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
padEmoji () {
|
padEmoji () {
|
||||||
|
|
|
@ -51,7 +51,21 @@
|
||||||
<span v-else>{{ suggestion.replacement }}</span>
|
<span v-else>{{ suggestion.replacement }}</span>
|
||||||
</span>
|
</span>
|
||||||
<div class="label">
|
<div class="label">
|
||||||
<span class="displayText">{{ suggestion.displayText }}</span>
|
<span
|
||||||
|
v-if="suggestion.user"
|
||||||
|
class="displayText"
|
||||||
|
>
|
||||||
|
{{ suggestion.displayText }}<UnicodeDomainIndicator
|
||||||
|
:user="suggestion.user"
|
||||||
|
:at="false"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
v-if="!suggestion.user"
|
||||||
|
class="displayText"
|
||||||
|
>
|
||||||
|
{{ suggestion.displayText }}
|
||||||
|
</span>
|
||||||
<span class="detailText">{{ suggestion.detailText }}</span>
|
<span class="detailText">{{ suggestion.detailText }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -116,11 +116,12 @@ export const suggestUsers = ({ dispatch, state }) => {
|
||||||
|
|
||||||
return diff + nameAlphabetically + screenNameAlphabetically
|
return diff + nameAlphabetically + screenNameAlphabetically
|
||||||
/* eslint-disable camelcase */
|
/* eslint-disable camelcase */
|
||||||
}).map(({ screen_name, screen_name_ui, name, profile_image_url_original }) => ({
|
}).map((user) => ({
|
||||||
displayText: screen_name_ui,
|
user,
|
||||||
detailText: name,
|
displayText: user.screen_name_ui,
|
||||||
imageUrl: profile_image_url_original,
|
detailText: user.name,
|
||||||
replacement: '@' + screen_name + ' '
|
imageUrl: user.profile_image_url_original,
|
||||||
|
replacement: '@' + user.screen_name + ' '
|
||||||
}))
|
}))
|
||||||
/* eslint-enable camelcase */
|
/* eslint-enable camelcase */
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ import generateProfileLink from 'src/services/user_profile_link_generator/user_p
|
||||||
import { mapGetters, mapState } from 'vuex'
|
import { mapGetters, mapState } from 'vuex'
|
||||||
import { highlightClass, highlightStyle } from '../../services/user_highlighter/user_highlighter.js'
|
import { highlightClass, highlightStyle } from '../../services/user_highlighter/user_highlighter.js'
|
||||||
import UserAvatar from '../user_avatar/user_avatar.vue'
|
import UserAvatar from '../user_avatar/user_avatar.vue'
|
||||||
|
import UnicodeDomainIndicator from '../unicode_domain_indicator/unicode_domain_indicator.vue'
|
||||||
import { defineAsyncComponent } from 'vue'
|
import { defineAsyncComponent } from 'vue'
|
||||||
import { library } from '@fortawesome/fontawesome-svg-core'
|
import { library } from '@fortawesome/fontawesome-svg-core'
|
||||||
import {
|
import {
|
||||||
|
@ -16,6 +17,7 @@ const MentionLink = {
|
||||||
name: 'MentionLink',
|
name: 'MentionLink',
|
||||||
components: {
|
components: {
|
||||||
UserAvatar,
|
UserAvatar,
|
||||||
|
UnicodeDomainIndicator,
|
||||||
UserPopover: defineAsyncComponent(() => import('../user_popover/user_popover.vue'))
|
UserPopover: defineAsyncComponent(() => import('../user_popover/user_popover.vue'))
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
|
|
|
@ -47,6 +47,9 @@
|
||||||
class="serverName"
|
class="serverName"
|
||||||
:class="{ '-faded': shouldFadeDomain }"
|
:class="{ '-faded': shouldFadeDomain }"
|
||||||
v-html="'@' + serverName"
|
v-html="'@' + serverName"
|
||||||
|
/><UnicodeDomainIndicator
|
||||||
|
v-if="shouldShowFullUserName"
|
||||||
|
:user="user"
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
|
|
|
@ -5,6 +5,7 @@ import UserAvatar from '../user_avatar/user_avatar.vue'
|
||||||
import UserCard from '../user_card/user_card.vue'
|
import UserCard from '../user_card/user_card.vue'
|
||||||
import Timeago from '../timeago/timeago.vue'
|
import Timeago from '../timeago/timeago.vue'
|
||||||
import Report from '../report/report.vue'
|
import Report from '../report/report.vue'
|
||||||
|
import UserLink from '../user_link/user_link.vue'
|
||||||
import RichContent from 'src/components/rich_content/rich_content.jsx'
|
import RichContent from 'src/components/rich_content/rich_content.jsx'
|
||||||
import UserPopover from '../user_popover/user_popover.vue'
|
import UserPopover from '../user_popover/user_popover.vue'
|
||||||
import { isStatusNotification } from '../../services/notification_utils/notification_utils.js'
|
import { isStatusNotification } from '../../services/notification_utils/notification_utils.js'
|
||||||
|
@ -50,7 +51,8 @@ const Notification = {
|
||||||
Status,
|
Status,
|
||||||
Report,
|
Report,
|
||||||
RichContent,
|
RichContent,
|
||||||
UserPopover
|
UserPopover,
|
||||||
|
UserLink
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
toggleUserExpanded () {
|
toggleUserExpanded () {
|
||||||
|
|
|
@ -11,9 +11,10 @@
|
||||||
class="Notification container -muted"
|
class="Notification container -muted"
|
||||||
>
|
>
|
||||||
<small>
|
<small>
|
||||||
<router-link :to="userProfileLink">
|
<user-link
|
||||||
{{ notification.from_profile.screen_name_ui }}
|
:user="notification.from_profile"
|
||||||
</router-link>
|
:at="false"
|
||||||
|
/>
|
||||||
</small>
|
</small>
|
||||||
<button
|
<button
|
||||||
class="button-unstyled unmute"
|
class="button-unstyled unmute"
|
||||||
|
@ -174,12 +175,10 @@
|
||||||
v-if="notification.type === 'follow' || notification.type === 'follow_request'"
|
v-if="notification.type === 'follow' || notification.type === 'follow_request'"
|
||||||
class="follow-text"
|
class="follow-text"
|
||||||
>
|
>
|
||||||
<router-link
|
<user-link
|
||||||
:to="userProfileLink"
|
|
||||||
class="follow-name"
|
class="follow-name"
|
||||||
>
|
:user="notification.from_profile"
|
||||||
@{{ notification.from_profile.screen_name_ui }}
|
/>
|
||||||
</router-link>
|
|
||||||
<div
|
<div
|
||||||
v-if="notification.type === 'follow_request'"
|
v-if="notification.type === 'follow_request'"
|
||||||
style="white-space: nowrap;"
|
style="white-space: nowrap;"
|
||||||
|
@ -210,9 +209,9 @@
|
||||||
v-else-if="notification.type === 'move'"
|
v-else-if="notification.type === 'move'"
|
||||||
class="move-text"
|
class="move-text"
|
||||||
>
|
>
|
||||||
<router-link :to="targetUserProfileLink">
|
<user-link
|
||||||
@{{ notification.target.screen_name_ui }}
|
:user="notification.target"
|
||||||
</router-link>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<Report
|
<Report
|
||||||
v-else-if="notification.type === 'pleroma:report'"
|
v-else-if="notification.type === 'pleroma:report'"
|
||||||
|
|
|
@ -13,6 +13,7 @@ import StatusPopover from '../status_popover/status_popover.vue'
|
||||||
import UserPopover from '../user_popover/user_popover.vue'
|
import UserPopover from '../user_popover/user_popover.vue'
|
||||||
import UserListPopover from '../user_list_popover/user_list_popover.vue'
|
import UserListPopover from '../user_list_popover/user_list_popover.vue'
|
||||||
import EmojiReactions from '../emoji_reactions/emoji_reactions.vue'
|
import EmojiReactions from '../emoji_reactions/emoji_reactions.vue'
|
||||||
|
import UserLink from '../user_link/user_link.vue'
|
||||||
import MentionsLine from 'src/components/mentions_line/mentions_line.vue'
|
import MentionsLine from 'src/components/mentions_line/mentions_line.vue'
|
||||||
import MentionLink from 'src/components/mention_link/mention_link.vue'
|
import MentionLink from 'src/components/mention_link/mention_link.vue'
|
||||||
import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'
|
import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'
|
||||||
|
@ -115,7 +116,8 @@ const Status = {
|
||||||
RichContent,
|
RichContent,
|
||||||
MentionLink,
|
MentionLink,
|
||||||
MentionsLine,
|
MentionsLine,
|
||||||
UserPopover
|
UserPopover,
|
||||||
|
UserLink
|
||||||
},
|
},
|
||||||
props: [
|
props: [
|
||||||
'statusoid',
|
'statusoid',
|
||||||
|
|
|
@ -25,9 +25,10 @@
|
||||||
class="fa-scale-110 fa-old-padding repeat-icon"
|
class="fa-scale-110 fa-old-padding repeat-icon"
|
||||||
icon="retweet"
|
icon="retweet"
|
||||||
/>
|
/>
|
||||||
<router-link :to="userProfileLink">
|
<user-link
|
||||||
{{ status.user.screen_name_ui }}
|
:user="status.user"
|
||||||
</router-link>
|
:at="false"
|
||||||
|
/>
|
||||||
</small>
|
</small>
|
||||||
<small
|
<small
|
||||||
v-if="showReasonMutedThread"
|
v-if="showReasonMutedThread"
|
||||||
|
@ -164,13 +165,12 @@
|
||||||
>
|
>
|
||||||
{{ status.user.name }}
|
{{ status.user.name }}
|
||||||
</h4>
|
</h4>
|
||||||
<router-link
|
<user-link
|
||||||
class="account-name"
|
class="account-name"
|
||||||
:title="status.user.screen_name_ui"
|
:title="status.user.screen_name_ui"
|
||||||
:to="userProfileLink"
|
:user="status.user"
|
||||||
>
|
:at="false"
|
||||||
{{ status.user.screen_name_ui }}
|
/>
|
||||||
</router-link>
|
|
||||||
<img
|
<img
|
||||||
v-if="!!(status.user && status.user.favicon)"
|
v-if="!!(status.user && status.user.favicon)"
|
||||||
class="status-favicon"
|
class="status-favicon"
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
<template>
|
||||||
|
<FAIcon
|
||||||
|
v-if="user && user.screen_name_ui_contains_non_ascii"
|
||||||
|
icon="code"
|
||||||
|
:title="$t('unicode_domain_indicator.tooltip')"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { library } from '@fortawesome/fontawesome-svg-core'
|
||||||
|
import {
|
||||||
|
faCode
|
||||||
|
} from '@fortawesome/free-solid-svg-icons'
|
||||||
|
|
||||||
|
library.add(
|
||||||
|
faCode
|
||||||
|
)
|
||||||
|
|
||||||
|
const UnicodeDomainIndicator = {
|
||||||
|
props: {
|
||||||
|
user: Object
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default UnicodeDomainIndicator
|
||||||
|
</script>
|
|
@ -5,6 +5,7 @@ import FollowButton from '../follow_button/follow_button.vue'
|
||||||
import ModerationTools from '../moderation_tools/moderation_tools.vue'
|
import ModerationTools from '../moderation_tools/moderation_tools.vue'
|
||||||
import AccountActions from '../account_actions/account_actions.vue'
|
import AccountActions from '../account_actions/account_actions.vue'
|
||||||
import Select from '../select/select.vue'
|
import Select from '../select/select.vue'
|
||||||
|
import UserLink from '../user_link/user_link.vue'
|
||||||
import RichContent from 'src/components/rich_content/rich_content.jsx'
|
import RichContent from 'src/components/rich_content/rich_content.jsx'
|
||||||
import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'
|
import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'
|
||||||
import { mapGetters } from 'vuex'
|
import { mapGetters } from 'vuex'
|
||||||
|
@ -134,7 +135,8 @@ export default {
|
||||||
ProgressButton,
|
ProgressButton,
|
||||||
FollowButton,
|
FollowButton,
|
||||||
Select,
|
Select,
|
||||||
RichContent
|
RichContent,
|
||||||
|
UserLink
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
muteUser () {
|
muteUser () {
|
||||||
|
|
|
@ -106,13 +106,10 @@
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="bottom-line">
|
<div class="bottom-line">
|
||||||
<router-link
|
<user-link
|
||||||
class="user-screen-name"
|
class="user-screen-name"
|
||||||
:title="user.screen_name_ui"
|
:user="user"
|
||||||
:to="userProfileLink(user)"
|
/>
|
||||||
>
|
|
||||||
@{{ user.screen_name_ui }}
|
|
||||||
</router-link>
|
|
||||||
<template v-if="!hideBio">
|
<template v-if="!hideBio">
|
||||||
<span
|
<span
|
||||||
v-if="user.deactivated"
|
v-if="user.deactivated"
|
||||||
|
|
38
src/components/user_link/user_link.vue
Normal file
38
src/components/user_link/user_link.vue
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
<template>
|
||||||
|
<router-link
|
||||||
|
:title="user.screen_name_ui"
|
||||||
|
:to="userProfileLink(user)"
|
||||||
|
>
|
||||||
|
{{ at ? '@' : '' }}{{ user.screen_name_ui }}<UnicodeDomainIndicator
|
||||||
|
:user="user"
|
||||||
|
/>
|
||||||
|
</router-link>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import UnicodeDomainIndicator from '../unicode_domain_indicator/unicode_domain_indicator.vue'
|
||||||
|
import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'
|
||||||
|
|
||||||
|
const UserLink = {
|
||||||
|
props: {
|
||||||
|
user: Object,
|
||||||
|
at: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
UnicodeDomainIndicator
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
userProfileLink (user) {
|
||||||
|
return generateProfileLink(
|
||||||
|
user.id, user.screen_name,
|
||||||
|
this.$store.state.instance.restrictedNicknames
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default UserLink
|
||||||
|
</script>
|
|
@ -1,5 +1,6 @@
|
||||||
import { defineAsyncComponent } from 'vue'
|
import { defineAsyncComponent } from 'vue'
|
||||||
import RichContent from 'src/components/rich_content/rich_content.jsx'
|
import RichContent from 'src/components/rich_content/rich_content.jsx'
|
||||||
|
import UnicodeDomainIndicator from '../unicode_domain_indicator/unicode_domain_indicator.vue'
|
||||||
|
|
||||||
import { library } from '@fortawesome/fontawesome-svg-core'
|
import { library } from '@fortawesome/fontawesome-svg-core'
|
||||||
import { faCircleNotch } from '@fortawesome/free-solid-svg-icons'
|
import { faCircleNotch } from '@fortawesome/free-solid-svg-icons'
|
||||||
|
@ -15,6 +16,7 @@ const UserListPopover = {
|
||||||
],
|
],
|
||||||
components: {
|
components: {
|
||||||
RichContent,
|
RichContent,
|
||||||
|
UnicodeDomainIndicator,
|
||||||
Popover: defineAsyncComponent(() => import('../popover/popover.vue')),
|
Popover: defineAsyncComponent(() => import('../popover/popover.vue')),
|
||||||
UserAvatar: defineAsyncComponent(() => import('../user_avatar/user_avatar.vue'))
|
UserAvatar: defineAsyncComponent(() => import('../user_avatar/user_avatar.vue'))
|
||||||
},
|
},
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
:emoji="user.emoji"
|
:emoji="user.emoji"
|
||||||
/>
|
/>
|
||||||
<!-- eslint-enable vue/no-v-html -->
|
<!-- eslint-enable vue/no-v-html -->
|
||||||
<span class="user-list-screen-name">{{ user.screen_name_ui }}</span>
|
<span class="user-list-screen-name">{{ user.screen_name_ui }}</span><UnicodeDomainIndicator :user="user" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -2,13 +2,15 @@ import Status from '../status/status.vue'
|
||||||
import List from '../list/list.vue'
|
import List from '../list/list.vue'
|
||||||
import Checkbox from '../checkbox/checkbox.vue'
|
import Checkbox from '../checkbox/checkbox.vue'
|
||||||
import Modal from '../modal/modal.vue'
|
import Modal from '../modal/modal.vue'
|
||||||
|
import UserLink from '../user_link/user_link.vue'
|
||||||
|
|
||||||
const UserReportingModal = {
|
const UserReportingModal = {
|
||||||
components: {
|
components: {
|
||||||
Status,
|
Status,
|
||||||
List,
|
List,
|
||||||
Checkbox,
|
Checkbox,
|
||||||
Modal
|
Modal,
|
||||||
|
UserLink
|
||||||
},
|
},
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -5,9 +5,13 @@
|
||||||
>
|
>
|
||||||
<div class="user-reporting-panel panel">
|
<div class="user-reporting-panel panel">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
<div class="title">
|
<i18n-t
|
||||||
{{ $t('user_reporting.title', [user.screen_name_ui]) }}
|
tag="div"
|
||||||
</div>
|
keypath="user_reporting.title"
|
||||||
|
class="title"
|
||||||
|
>
|
||||||
|
<UserLink :user="user" />
|
||||||
|
</i18n-t>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
<div class="user-reporting-panel-left">
|
<div class="user-reporting-panel-left">
|
||||||
|
|
|
@ -1036,5 +1036,8 @@
|
||||||
"update_changelog": "For more details on what's changed, see {theFullChangelog}.",
|
"update_changelog": "For more details on what's changed, see {theFullChangelog}.",
|
||||||
"update_changelog_here": "the full changelog",
|
"update_changelog_here": "the full changelog",
|
||||||
"art_by": "Art by {linkToArtist}"
|
"art_by": "Art by {linkToArtist}"
|
||||||
|
},
|
||||||
|
"unicode_domain_indicator": {
|
||||||
|
"tooltip": "This domain contains non-ascii characters."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -216,12 +216,14 @@ export const parseUser = (data) => {
|
||||||
output.screen_name_ui = output.screen_name
|
output.screen_name_ui = output.screen_name
|
||||||
if (output.screen_name && output.screen_name.includes('@')) {
|
if (output.screen_name && output.screen_name.includes('@')) {
|
||||||
const parts = output.screen_name.split('@')
|
const parts = output.screen_name.split('@')
|
||||||
let unicodeDomain = punycode.toUnicode(parts[1])
|
const unicodeDomain = punycode.toUnicode(parts[1])
|
||||||
if (unicodeDomain !== parts[1]) {
|
if (unicodeDomain !== parts[1]) {
|
||||||
// Add some identifier so users can potentially spot spoofing attempts:
|
// Add some identifier so users can potentially spot spoofing attempts:
|
||||||
// lain.com and xn--lin-6cd.com would appear identical otherwise.
|
// lain.com and xn--lin-6cd.com would appear identical otherwise.
|
||||||
unicodeDomain = '🌏' + unicodeDomain
|
output.screen_name_ui_contains_non_ascii = true
|
||||||
output.screen_name_ui = [parts[0], unicodeDomain].join('@')
|
output.screen_name_ui = [parts[0], unicodeDomain].join('@')
|
||||||
|
} else {
|
||||||
|
output.screen_name_ui_contains_non_ascii = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,11 +17,6 @@ const webpackConfig = merge(baseConfig, {
|
||||||
rules: utils.styleLoaders()
|
rules: utils.styleLoaders()
|
||||||
},
|
},
|
||||||
devtool: 'inline-source-map',
|
devtool: 'inline-source-map',
|
||||||
// vue: {
|
|
||||||
// loaders: {
|
|
||||||
// js: 'isparta'
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
plugins: [
|
plugins: [
|
||||||
new webpack.DefinePlugin({
|
new webpack.DefinePlugin({
|
||||||
'process.env': require('../../config/test.env')
|
'process.env': require('../../config/test.env')
|
||||||
|
@ -37,22 +32,6 @@ const webpackConfig = merge(baseConfig, {
|
||||||
// no need for app entry during tests
|
// no need for app entry during tests
|
||||||
delete webpackConfig.entry
|
delete webpackConfig.entry
|
||||||
|
|
||||||
// make sure isparta loader is applied before eslint
|
|
||||||
// webpackConfig.module.preLoaders = webpackConfig.module.preLoaders || []
|
|
||||||
// webpackConfig.module.preLoaders.unshift({
|
|
||||||
// test: /\.js$/,
|
|
||||||
// loader: 'isparta',
|
|
||||||
// include: path.resolve(projectRoot, 'src')
|
|
||||||
// })
|
|
||||||
|
|
||||||
// // only apply babel for test files when using isparta
|
|
||||||
// webpackConfig.module.loaders.some(function (loader, i) {
|
|
||||||
// if (loader.loader === 'babel') {
|
|
||||||
// loader.include = path.resolve(projectRoot, 'test/unit')
|
|
||||||
// return true
|
|
||||||
// }
|
|
||||||
// })
|
|
||||||
|
|
||||||
module.exports = function (config) {
|
module.exports = function (config) {
|
||||||
config.set({
|
config.set({
|
||||||
// to run in additional browsers:
|
// to run in additional browsers:
|
||||||
|
|
|
@ -269,7 +269,8 @@ describe('API Entities normalizer', () => {
|
||||||
it('converts IDN to unicode and marks it as internatonal', () => {
|
it('converts IDN to unicode and marks it as internatonal', () => {
|
||||||
const user = makeMockUserMasto({ acct: 'lain@xn--lin-6cd.com' })
|
const user = makeMockUserMasto({ acct: 'lain@xn--lin-6cd.com' })
|
||||||
|
|
||||||
expect(parseUser(user)).to.have.property('screen_name_ui').that.equal('lain@🌏lаin.com')
|
expect(parseUser(user)).to.have.property('screen_name_ui').that.equal('lain@lаin.com')
|
||||||
|
expect(parseUser(user)).to.have.property('screen_name_ui_contains_non_ascii').that.equal(true)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue