diff --git a/js/package.json b/js/package.json index 0bfcdb343..cabd2a04d 100644 --- a/js/package.json +++ b/js/package.json @@ -30,7 +30,6 @@ "graphql": "^15.0.0", "graphql-tag": "^2.10.3", "intersection-observer": "^0.11.0", - "javascript-time-ago": "^2.0.4", "leaflet": "^1.4.0", "leaflet.locatecontrol": "^0.72.0", "lodash": "^4.17.11", @@ -54,7 +53,6 @@ }, "devDependencies": { "@types/chai": "^4.2.11", - "@types/javascript-time-ago": "^2.0.1", "@types/leaflet": "^1.5.2", "@types/leaflet.locatecontrol": "^0.60.7", "@types/lodash": "^4.14.141", diff --git a/js/src/common.scss b/js/src/common.scss index 2178b6398..cf93afa73 100644 --- a/js/src/common.scss +++ b/js/src/common.scss @@ -1,5 +1,9 @@ @import "variables.scss"; +@import "~bulma"; +@import "~bulma-divider"; +@import "~buefy/src/scss/buefy"; + // a { // color: $violet-2; // } diff --git a/js/src/components/Account/ActorCard.vue b/js/src/components/Account/ActorCard.vue index 4f910e534..0141a639a 100644 --- a/js/src/components/Account/ActorCard.vue +++ b/js/src/components/Account/ActorCard.vue @@ -46,8 +46,6 @@ export default class ActorCard extends Vue { </style> <style lang="scss"> -@import "../../variables.scss"; - .tooltip { display: block !important; z-index: 10000; diff --git a/js/src/components/Account/ParticipantCard.vue b/js/src/components/Account/ParticipantCard.vue index 8816e85bd..5284361d9 100644 --- a/js/src/components/Account/ParticipantCard.vue +++ b/js/src/components/Account/ParticipantCard.vue @@ -88,7 +88,6 @@ export default class ParticipantCard extends Vue { </script> <style lang="scss"> -@import "../../variables.scss"; .card-footer-item { height: $control-height; } diff --git a/js/src/components/Admin/Followers.vue b/js/src/components/Admin/Followers.vue index 73d65c186..82962e7ee 100644 --- a/js/src/components/Admin/Followers.vue +++ b/js/src/components/Admin/Followers.vue @@ -51,7 +51,7 @@ <b-table-column field="targetActor.updatedAt" :label="$t('Date')" sortable v-slot="props"> <span :title="$options.filters.formatDateTimeString(props.row.updatedAt)">{{ - timeago(props.row.updatedAt) + formatDistanceToNow(new Date(props.row.updatedAt), { locale: $dateFnsLocale }) }}</span></b-table-column > @@ -102,6 +102,7 @@ <script lang="ts"> import { Component, Mixins } from "vue-property-decorator"; import { SnackbarProgrammatic as Snackbar } from "buefy"; +import { formatDistanceToNow } from "date-fns"; import { ACCEPT_RELAY, REJECT_RELAY, RELAY_FOLLOWERS } from "../../graphql/admin"; import { Paginate } from "../../types/paginate"; import { IFollower } from "../../types/actor/follower.model"; @@ -126,6 +127,8 @@ export default class Followers extends Mixins(RelayMixin) { RelayMixin = RelayMixin; + formatDistanceToNow = formatDistanceToNow; + async acceptRelays(): Promise<void> { await this.checkedRows.forEach((row: IFollower) => { this.acceptRelay(`${row.actor.preferredUsername}@${row.actor.domain}`); diff --git a/js/src/components/Admin/Followings.vue b/js/src/components/Admin/Followings.vue index 031839500..79bcff133 100644 --- a/js/src/components/Admin/Followings.vue +++ b/js/src/components/Admin/Followings.vue @@ -64,7 +64,7 @@ <b-table-column field="targetActor.updatedAt" :label="$t('Date')" sortable v-slot="props"> <span :title="$options.filters.formatDateTimeString(props.row.updatedAt)">{{ - timeago(props.row.updatedAt) + formatDistanceToNow(new Date(props.row.updatedAt), { locale: $dateFnsLocale }) }}</span></b-table-column > @@ -100,6 +100,7 @@ <script lang="ts"> import { Component, Mixins } from "vue-property-decorator"; import { SnackbarProgrammatic as Snackbar } from "buefy"; +import { formatDistanceToNow } from "date-fns"; import { ADD_RELAY, RELAY_FOLLOWINGS, REMOVE_RELAY } from "../../graphql/admin"; import { IFollower } from "../../types/actor/follower.model"; import { Paginate } from "../../types/paginate"; @@ -126,6 +127,8 @@ export default class Followings extends Mixins(RelayMixin) { RelayMixin = RelayMixin; + formatDistanceToNow = formatDistanceToNow; + async followRelay(e: Event): Promise<void> { e.preventDefault(); try { diff --git a/js/src/components/Comment/Comment.vue b/js/src/components/Comment/Comment.vue index d700a2bb8..c5cb07bfa 100644 --- a/js/src/components/Comment/Comment.vue +++ b/js/src/components/Comment/Comment.vue @@ -24,7 +24,12 @@ <strong :class="{ organizer: commentFromOrganizer }">{{ comment.actor.name }}</strong> <small>@{{ usernameWithDomain(comment.actor) }}</small> <a class="comment-link has-text-grey" :href="commentURL"> - <small>{{ timeago(new Date(comment.updatedAt)) }}</small> + <small>{{ + formatDistanceToNow(new Date(comment.updatedAt), { + locale: $dateFnsLocale, + addSuffix: true, + }) + }}</small> </a> </span> <a v-else class="comment-link has-text-grey" :href="commentURL"> @@ -130,8 +135,8 @@ <script lang="ts"> import { Component, Prop, Vue, Ref } from "vue-property-decorator"; import EditorComponent from "@/components/Editor.vue"; -import TimeAgo from "javascript-time-ago"; import { SnackbarProgrammatic as Snackbar } from "buefy"; +import { formatDistanceToNow } from "date-fns"; import { CommentModel, IComment } from "../../types/comment.model"; import { CURRENT_ACTOR_CLIENT } from "../../graphql/actor"; import { IPerson, usernameWithDomain } from "../../types/actor"; @@ -171,18 +176,13 @@ export default class Comment extends Vue { showReplies = false; - timeAgoInstance: TimeAgo | null = null; - CommentModeration = CommentModeration; usernameWithDomain = usernameWithDomain; - async mounted(): Promise<void> { - const localeName = this.$i18n.locale; - const locale = await import(`javascript-time-ago/locale/${localeName}`); - TimeAgo.addLocale(locale); - this.timeAgoInstance = new TimeAgo(localeName); + formatDistanceToNow = formatDistanceToNow; + async mounted(): Promise<void> { const { hash } = this.$route; if (hash.includes(`#comment-${this.comment.uuid}`)) { this.fetchReplies(); @@ -243,13 +243,6 @@ export default class Comment extends Vue { this.showReplies = true; } - timeago(dateTime: Date): string { - if (this.timeAgoInstance != null) { - return this.timeAgoInstance.format(dateTime); - } - return ""; - } - get commentSelected(): boolean { return this.commentId === this.$route.hash; } @@ -316,8 +309,6 @@ export default class Comment extends Vue { } </script> <style lang="scss" scoped> -@import "@/variables.scss"; - form.reply { padding-bottom: 1rem; } diff --git a/js/src/components/Discussion/DiscussionComment.vue b/js/src/components/Discussion/DiscussionComment.vue index 38d71967c..c6db3188d 100644 --- a/js/src/components/Discussion/DiscussionComment.vue +++ b/js/src/components/Discussion/DiscussionComment.vue @@ -43,7 +43,10 @@ </span> <div class="post-infos"> <span :title="comment.insertedAt | formatDateTimeString"> - {{ $timeAgo.format(new Date(comment.updatedAt), "twitter") || $t("Right now") }}</span + {{ + formatDistanceToNow(new Date(comment.updatedAt), { locale: $dateFnsLocale }) || + $t("Right now") + }}</span > </div> </div> @@ -53,7 +56,13 @@ v-if="comment.insertedAt.getTime() !== comment.updatedAt.getTime()" :title="comment.updatedAt | formatDateTimeString" > - {{ $t("Edited {ago}", { ago: $timeAgo.format(new Date(comment.updatedAt)) }) }} + {{ + $t("Edited {ago}", { + ago: formatDistanceToNow(new Date(comment.updatedAt), { + locale: $dateFnsLocale, + }), + }) + }} </p> </div> <div class="comment-deleted" v-else-if="!editMode"> @@ -76,7 +85,8 @@ </template> <script lang="ts"> import { Component, Prop, Vue } from "vue-property-decorator"; -import { IComment, CommentModel } from "../../types/comment.model"; +import { formatDistanceToNow } from "date-fns"; +import { IComment } from "../../types/comment.model"; import { usernameWithDomain, IPerson } from "../../types/actor"; import { CURRENT_ACTOR_CLIENT } from "../../graphql/actor"; @@ -99,14 +109,16 @@ export default class DiscussionComment extends Vue { usernameWithDomain = usernameWithDomain; + formatDistanceToNow = formatDistanceToNow; + // isReportModalActive: boolean = false; - toggleEditMode() { + toggleEditMode(): void { this.updatedComment = this.comment.text; this.editMode = !this.editMode; } - updateComment() { + updateComment(): void { this.comment.text = this.updatedComment; this.$emit("update-comment", this.comment); this.toggleEditMode(); @@ -114,8 +126,6 @@ export default class DiscussionComment extends Vue { } </script> <style lang="scss" scoped> -@import "@/variables.scss"; - article.comment { display: flex; border-top: 1px solid #e9e9e9; diff --git a/js/src/components/Discussion/DiscussionListItem.vue b/js/src/components/Discussion/DiscussionListItem.vue index ab6bc2938..31f14a1e7 100644 --- a/js/src/components/Discussion/DiscussionListItem.vue +++ b/js/src/components/Discussion/DiscussionListItem.vue @@ -16,7 +16,10 @@ <div class="title-and-date"> <p class="discussion-minimalist-title">{{ discussion.title }}</p> <span :title="actualDate | formatDateTimeString"> - {{ $timeAgo.format(new Date(actualDate), "twitter") || $t("Right now") }}</span + {{ + formatDistanceToNowStrict(new Date(actualDate), { locale: $dateFnsLocale }) || + $t("Right now") + }}</span > </div> <div class="has-text-grey" v-if="!discussion.lastComment.deletedAt"> @@ -28,6 +31,7 @@ </template> <script lang="ts"> import { Component, Prop, Vue } from "vue-property-decorator"; +import { formatDistanceToNowStrict } from "date-fns"; import { IDiscussion } from "../../types/discussions"; import RouteName from "../../router/name"; @@ -37,7 +41,9 @@ export default class DiscussionListItem extends Vue { RouteName = RouteName; - get htmlTextEllipsis() { + formatDistanceToNowStrict = formatDistanceToNowStrict; + + get htmlTextEllipsis(): string { const element = document.createElement("div"); if (this.discussion.lastComment && this.discussion.lastComment.text) { element.innerHTML = this.discussion.lastComment.text @@ -47,7 +53,7 @@ export default class DiscussionListItem extends Vue { return element.innerText; } - get actualDate() { + get actualDate(): string | Date | undefined { if (this.discussion.updatedAt === this.discussion.insertedAt && this.discussion.lastComment) { return this.discussion.lastComment.publishedAt; } diff --git a/js/src/components/Editor.vue b/js/src/components/Editor.vue index ca4f6e82e..c162e4564 100644 --- a/js/src/components/Editor.vue +++ b/js/src/components/Editor.vue @@ -552,8 +552,6 @@ export default class EditorComponent extends Vue { } </script> <style lang="scss"> -@import "@/variables.scss"; - $color-black: #000; $color-white: #eee; diff --git a/js/src/components/Event/DateCalendarIcon.vue b/js/src/components/Event/DateCalendarIcon.vue index 21d72c23c..c90216f71 100644 --- a/js/src/components/Event/DateCalendarIcon.vue +++ b/js/src/components/Event/DateCalendarIcon.vue @@ -27,23 +27,21 @@ export default class DateCalendarIcon extends Vue { */ @Prop({ required: true }) date!: string; - get dateObj() { + get dateObj(): Date { return new Date(this.$props.date); } - get month() { + get month(): string { return this.dateObj.toLocaleString(undefined, { month: "short" }); } - get day() { + get day(): string { return this.dateObj.toLocaleString(undefined, { day: "numeric" }); } } </script> <style lang="scss" scoped> -@import "../../variables.scss"; - time.datetime-container { background: $backgrounds; border: 1px solid $borders; diff --git a/js/src/components/Event/EventCard.vue b/js/src/components/Event/EventCard.vue index 5f0815685..6067ce8a7 100644 --- a/js/src/components/Event/EventCard.vue +++ b/js/src/components/Event/EventCard.vue @@ -115,8 +115,6 @@ export default class EventCard extends Vue { </script> <style lang="scss" scoped> -@import "../../variables"; - a.card { display: block; background: $secondary; diff --git a/js/src/components/Event/EventListCard.vue b/js/src/components/Event/EventListCard.vue index 3a02d2759..670f811ba 100644 --- a/js/src/components/Event/EventListCard.vue +++ b/js/src/components/Event/EventListCard.vue @@ -275,8 +275,6 @@ export default class EventListCard extends mixins(ActorMixin, EventMixin) { </script> <style lang="scss" scoped> -@import "../../variables"; - article.box { div.tag-container { position: absolute; diff --git a/js/src/components/Event/EventListViewCard.vue b/js/src/components/Event/EventListViewCard.vue index be744e239..c08b4b322 100644 --- a/js/src/components/Event/EventListViewCard.vue +++ b/js/src/components/Event/EventListViewCard.vue @@ -104,8 +104,6 @@ export default class EventListViewCard extends mixins(ActorMixin, EventMixin) { </script> <style lang="scss" scoped> -@import "../../variables"; - article.box { div.content { padding: 5px; diff --git a/js/src/components/Event/EventMetadataBlock.vue b/js/src/components/Event/EventMetadataBlock.vue index 79d9af5b3..4aab57660 100644 --- a/js/src/components/Event/EventMetadataBlock.vue +++ b/js/src/components/Event/EventMetadataBlock.vue @@ -20,8 +20,6 @@ export default class EventMetadataBlock extends Vue { } </script> <style lang="scss" scoped> -@import "../../variables.scss"; - h2 { font-size: 1.8rem; font-weight: 500; diff --git a/js/src/components/Footer.vue b/js/src/components/Footer.vue index 27105abb3..7be53b1bc 100644 --- a/js/src/components/Footer.vue +++ b/js/src/components/Footer.vue @@ -44,8 +44,6 @@ export default class Footer extends Vue { } </script> <style lang="scss" scoped> -@import "../variables.scss"; - footer.footer { color: $secondary; display: flex; diff --git a/js/src/components/Group/GroupSection.vue b/js/src/components/Group/GroupSection.vue index 56d7f9c33..de4c305f4 100644 --- a/js/src/components/Group/GroupSection.vue +++ b/js/src/components/Group/GroupSection.vue @@ -32,8 +32,6 @@ export default class GroupSection extends Vue { } </script> <style lang="scss" scoped> -@import "@/variables.scss"; - section { display: flex; flex-direction: column; diff --git a/js/src/components/Group/InvitationCard.vue b/js/src/components/Group/InvitationCard.vue index 13fece9fd..9292bb264 100644 --- a/js/src/components/Group/InvitationCard.vue +++ b/js/src/components/Group/InvitationCard.vue @@ -54,7 +54,7 @@ <script lang="ts"> import { Component, Prop, Vue } from "vue-property-decorator"; -import { IGroup, IMember, usernameWithDomain } from "@/types/actor"; +import { IMember, usernameWithDomain } from "@/types/actor"; import RouteName from "../../router/name"; @Component @@ -68,8 +68,6 @@ export default class InvitationCard extends Vue { </script> <style lang="scss" scoped> -@import "@/variables.scss"; - .media:not(.subfield) { background: lighten($primary, 40%); padding: 10px; diff --git a/js/src/components/Logo.vue b/js/src/components/Logo.vue index b2c07567e..be7e20083 100644 --- a/js/src/components/Logo.vue +++ b/js/src/components/Logo.vue @@ -4,7 +4,7 @@ <script lang="ts"> import { Component, Prop, Vue } from "vue-property-decorator"; -// eslint-disable-next-line @typescript-eslint/ban-ts-ignore +// eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore import MobilizonLogo from "../assets/mobilizon_logo.svg?inline"; @@ -18,8 +18,6 @@ export default class Logo extends Vue { } </script> <style lang="scss" scoped> -@import "../variables.scss"; - svg { fill: $background-color; diff --git a/js/src/components/NavBar.vue b/js/src/components/NavBar.vue index db75dd2a6..04e6638be 100644 --- a/js/src/components/NavBar.vue +++ b/js/src/components/NavBar.vue @@ -216,8 +216,6 @@ export default class NavBar extends Vue { } </script> <style lang="scss" scoped> -@import "../variables.scss"; - nav { .navbar-item { a.button { diff --git a/js/src/components/Post/PostListItem.vue b/js/src/components/Post/PostListItem.vue index 8a3940518..570a0e898 100644 --- a/js/src/components/Post/PostListItem.vue +++ b/js/src/components/Post/PostListItem.vue @@ -5,11 +5,17 @@ > <div class="title-info-wrapper"> <p class="post-minimalist-title">{{ post.title }}</p> - <small class="has-text-grey">{{ $timeAgo.format(new Date(post.insertedAt)) }}</small> + <small class="has-text-grey">{{ + formatDistanceToNow(new Date(post.publishAt || post.insertedAt), { + locale: $dateFnsLocale, + addSuffix: true, + }) + }}</small> </div> </router-link> </template> <script lang="ts"> +import { formatDistanceToNow } from "date-fns"; import { Component, Prop, Vue } from "vue-property-decorator"; import RouteName from "../../router/name"; import { IPost } from "../../types/post.model"; @@ -19,6 +25,8 @@ export default class PostListItem extends Vue { @Prop({ required: true, type: Object }) post!: IPost; RouteName = RouteName; + + formatDistanceToNow = formatDistanceToNow; } </script> <style lang="scss" scoped> diff --git a/js/src/components/Resource/FolderItem.vue b/js/src/components/Resource/FolderItem.vue index e4bd9063d..76ef70537 100644 --- a/js/src/components/Resource/FolderItem.vue +++ b/js/src/components/Resource/FolderItem.vue @@ -114,8 +114,6 @@ export default class FolderItem extends Mixins(ResourceMixin) { } </script> <style lang="scss" scoped> -@import "@/variables.scss"; - .resource-wrapper { display: flex; flex: 1; diff --git a/js/src/components/Resource/ResourceItem.vue b/js/src/components/Resource/ResourceItem.vue index fcb8e84fa..50f4e7a3e 100644 --- a/js/src/components/Resource/ResourceItem.vue +++ b/js/src/components/Resource/ResourceItem.vue @@ -57,8 +57,6 @@ export default class ResourceItem extends Vue { } </script> <style lang="scss" scoped> -@import "@/variables.scss"; - .resource-wrapper { display: flex; flex: 1; diff --git a/js/src/components/Resource/ResourceSelector.vue b/js/src/components/Resource/ResourceSelector.vue index 6cc5ebd8e..755604055 100644 --- a/js/src/components/Resource/ResourceSelector.vue +++ b/js/src/components/Resource/ResourceSelector.vue @@ -111,8 +111,6 @@ export default class ResourceSelector extends Vue { } </script> <style lang="scss" scoped> -@import "../../variables.scss"; - .panel { a.panel-block { cursor: default; diff --git a/js/src/components/Settings/SettingMenuItem.vue b/js/src/components/Settings/SettingMenuItem.vue index 73a07a157..2f201ae94 100644 --- a/js/src/components/Settings/SettingMenuItem.vue +++ b/js/src/components/Settings/SettingMenuItem.vue @@ -30,8 +30,6 @@ export default class SettingMenuItem extends Vue { </script> <style lang="scss" scoped> -@import "@/variables.scss"; - li.setting-menu-item { font-size: 1.05rem; background-color: #fff1de; diff --git a/js/src/components/Settings/SettingMenuSection.vue b/js/src/components/Settings/SettingMenuSection.vue index 5eb5d8946..cc2d1953a 100644 --- a/js/src/components/Settings/SettingMenuSection.vue +++ b/js/src/components/Settings/SettingMenuSection.vue @@ -37,8 +37,6 @@ export default class SettingMenuSection extends Vue { </script> <style lang="scss" scoped> -@import "@/variables.scss"; - li { font-size: 1.3rem; background-color: $secondary; diff --git a/js/src/components/Tag.vue b/js/src/components/Tag.vue index efc45ecc9..64eff4b5d 100644 --- a/js/src/components/Tag.vue +++ b/js/src/components/Tag.vue @@ -13,8 +13,6 @@ export default class Tag extends Vue {} </script> <style lang="scss" scoped> -@import "../variables.scss"; - span.tag { background: $purple-3; color: $violet-2; diff --git a/js/src/components/Utils/Subtitle.vue b/js/src/components/Utils/Subtitle.vue index 30d746adf..6f88cc423 100644 --- a/js/src/components/Utils/Subtitle.vue +++ b/js/src/components/Utils/Subtitle.vue @@ -12,8 +12,6 @@ import { Component, Vue } from "vue-property-decorator"; export default class Subtitle extends Vue {} </script> <style lang="scss" scoped> -@import "@/variables.scss"; - h2 { display: block; margin: 15px 0 30px; diff --git a/js/src/components/Utils/VerticalDivider.vue b/js/src/components/Utils/VerticalDivider.vue index 76516562d..5e1dbe2e9 100644 --- a/js/src/components/Utils/VerticalDivider.vue +++ b/js/src/components/Utils/VerticalDivider.vue @@ -8,14 +8,12 @@ import { Component, Prop, Vue } from "vue-property-decorator"; export default class VerticalDivider extends Vue { @Prop({ default: "Or" }) content!: string; - get dataContent() { + get dataContent(): string { return this.content.toLocaleUpperCase(); } } </script> <style lang="scss" scoped> -@import "@/variables.scss"; - .is-divider-vertical[data-content]::after { background-color: $body-background-color; } diff --git a/js/src/filters/index.ts b/js/src/filters/index.ts index ae2108db8..71339a88a 100644 --- a/js/src/filters/index.ts +++ b/js/src/filters/index.ts @@ -2,7 +2,7 @@ import nl2br from "@/filters/utils"; import { formatDateString, formatTimeString, formatDateTimeString } from "./datetime"; export default { - install(vue: any) { + install(vue: any): void { vue.filter("formatDateString", formatDateString); vue.filter("formatTimeString", formatTimeString); vue.filter("formatDateTimeString", formatDateTimeString); diff --git a/js/src/i18n/fr_FR.json b/js/src/i18n/fr_FR.json index d3f370f76..49de14720 100644 --- a/js/src/i18n/fr_FR.json +++ b/js/src/i18n/fr_FR.json @@ -204,7 +204,7 @@ "Duplicate": "Dupliquer", "Edit": "Modifier", "Edit post": "Éditer le billet", - "Edited {ago}": "Édité {ago}", + "Edited {ago}": "Édité il y a {ago}", "Eg: Stockholm, Dance, Chess…": "Par exemple : Lyon, Danse, Bridge…", "Either on the {instance} instance or on another instance.": "Sur l'instance {instance} ou bien sur une autre instance.", "Either the account is already validated, either the validation token is incorrect.": "Soit le compte est déjà validé, soit le jeton de validation est incorrect.", diff --git a/js/src/i18n/index.ts b/js/src/i18n/index.ts deleted file mode 100644 index af920d2e7..000000000 --- a/js/src/i18n/index.ts +++ /dev/null @@ -1,43 +0,0 @@ -/* eslint-disable @typescript-eslint/camelcase */ - -import ar from "./ar.json"; -import be from "./be.json"; -import ca from "./ca.json"; -import cs from "./cs.json"; -import de from "./de.json"; -import en_US from "./en_US.json"; -import es from "./es.json"; -import fi from "./fi.json"; -import fr_FR from "./fr_FR.json"; -import it from "./it.json"; -import ja from "./ja.json"; -import nl from "./nl.json"; -import oc from "./oc.json"; -import pl from "./pl.json"; -import pt from "./pt.json"; -import pt_BR from "./pt_BR.json"; -import ru from "./ru.json"; -import sv from "./sv.json"; - -export default { - ar, - be, - ca, - cs, - de, - en: en_US, - en_US, - es, - fi, - fr: fr_FR, - fr_FR, - it, - ja, - nl, - oc, - pl, - pt, - pt_BR, - ru, - sv, -}; diff --git a/js/src/i18n/langs.json b/js/src/i18n/langs.json index d9916fb71..a7c51b6fa 100644 --- a/js/src/i18n/langs.json +++ b/js/src/i18n/langs.json @@ -1,19 +1,14 @@ { "ar": "العربية", - "bg": "Български", "be": "Беларуская мова", - "br": "Brezhoneg", "ca": "Català", - "co": "Corsu", "cs": "čeština", "de": "Deutsch", "en": "English", - "eo": "Esperanto", "es": "Español", "fi": "suomi", "fr": "Français", "gl": "Galego", - "hu": "Magyar", "it": "Italiano", "ja": "日本語", "nl": "Dutch", @@ -22,9 +17,5 @@ "pt": "Português", "pt_PT": "Português (Portugal)", "ru": "Русский", - "sq": "Shqip", - "sv": "Svenska", - "tr": "Türkçe", - "vi": "Tiếng Việt", - "zh_Hant_TW": "繁體中文(台灣)" + "sv": "Svenska" } diff --git a/js/src/main.ts b/js/src/main.ts index b425b56ee..5fcc4addb 100644 --- a/js/src/main.ts +++ b/js/src/main.ts @@ -6,33 +6,17 @@ import Component from "vue-class-component"; import VueScrollTo from "vue-scrollto"; import VueMeta from "vue-meta"; import VTooltip from "v-tooltip"; -import TimeAgo from "javascript-time-ago"; import App from "./App.vue"; import router from "./router"; import { NotifierPlugin } from "./plugins/notifier"; -import { DateFnsPlugin } from "./plugins/dateFns"; import filters from "./filters"; import { i18n } from "./utils/i18n"; -import messages from "./i18n"; import apolloProvider from "./vue-apollo"; Vue.config.productionTip = false; -let language = document.documentElement.getAttribute("lang") as string; -language = - language || - ((window.navigator as any).userLanguage || window.navigator.language).replace(/-/, "_"); -export const locale = - language && messages.hasOwnProperty(language) ? language : language.split("-")[0]; - -import(`javascript-time-ago/locale/${locale}`).then((localeFile) => { - TimeAgo.addLocale(localeFile); - Vue.prototype.$timeAgo = new TimeAgo(locale); -}); - Vue.use(Buefy); Vue.use(NotifierPlugin); -Vue.use(DateFnsPlugin, { locale }); Vue.use(filters); Vue.use(VueMeta); Vue.use(VueScrollTo); diff --git a/js/src/mixins/relay.ts b/js/src/mixins/relay.ts index a01fbdb46..295bccec9 100644 --- a/js/src/mixins/relay.ts +++ b/js/src/mixins/relay.ts @@ -1,7 +1,6 @@ import { Component, Vue, Ref } from "vue-property-decorator"; import { ActorType, IActor } from "@/types/actor"; import { IFollower } from "@/types/actor/follower.model"; -import TimeAgo from "javascript-time-ago"; @Component export default class RelayMixin extends Vue { @@ -13,20 +12,11 @@ export default class RelayMixin extends Vue { perPage = 10; - timeAgoInstance: TimeAgo | null = null; - - async mounted() { - const localeName = this.$i18n.locale; - const locale = await import(`javascript-time-ago/locale/${localeName}`); - TimeAgo.addLocale(locale); - this.timeAgoInstance = new TimeAgo(localeName); - } - - toggle(row: object) { + toggle(row: Record<string, unknown>): void { this.table.toggleDetails(row); } - async onPageChange(page: number) { + async onPageChange(page: number): Promise<void> { this.page = page; await this.$apollo.queries.relayFollowings.fetchMore({ variables: { @@ -53,11 +43,4 @@ export default class RelayMixin extends Vue { (actor.preferredUsername === "relay" || actor.preferredUsername === actor.domain) ); } - - timeago(dateTime: string): string { - if (this.timeAgoInstance != null) { - return this.timeAgoInstance.format(new Date(dateTime)); - } - return ""; - } } diff --git a/js/src/plugins/dateFns.ts b/js/src/plugins/dateFns.ts index c989092f6..cf2114721 100644 --- a/js/src/plugins/dateFns.ts +++ b/js/src/plugins/dateFns.ts @@ -1,5 +1,5 @@ -import Vue from "vue"; import Locale from "date-fns"; +import VueInstance from "vue"; declare module "vue/types/vue" { interface Vue { @@ -7,8 +7,8 @@ declare module "vue/types/vue" { } } -export function DateFnsPlugin(vue: typeof Vue, { locale }: { locale: string }): void { +export function DateFnsPlugin(vue: typeof VueInstance, { locale }: { locale: string }): void { import(`date-fns/locale/${locale}/index.js`).then((localeEntity) => { - Vue.prototype.$dateFnsLocale = localeEntity; + VueInstance.prototype.$dateFnsLocale = localeEntity; }); } diff --git a/js/src/plugins/notifier.ts b/js/src/plugins/notifier.ts index 8341faa66..5000bf986 100644 --- a/js/src/plugins/notifier.ts +++ b/js/src/plugins/notifier.ts @@ -1,4 +1,5 @@ -import Vue from "vue"; +/* eslint-disable no-shadow */ +import VueInstance from "vue"; import { ColorModifiers } from "buefy/types/helpers.d"; import { Route, RawLocation } from "vue-router"; @@ -12,39 +13,39 @@ declare module "vue/types/vue" { beforeRouteEnter?( to: Route, from: Route, - next: (to?: RawLocation | false | ((vm: Vue) => void)) => void + next: (to?: RawLocation | false | ((vm: VueInstance) => void)) => void ): void; beforeRouteLeave?( to: Route, from: Route, - next: (to?: RawLocation | false | ((vm: Vue) => void)) => void + next: (to?: RawLocation | false | ((vm: VueInstance) => void)) => void ): void; beforeRouteUpdate?( to: Route, from: Route, - next: (to?: RawLocation | false | ((vm: Vue) => void)) => void + next: (to?: RawLocation | false | ((vm: VueInstance) => void)) => void ): void; } } export class Notifier { - private readonly vue: typeof Vue; + private readonly vue: typeof VueInstance; - constructor(vue: typeof Vue) { + constructor(vue: typeof VueInstance) { this.vue = vue; } - success(message: string) { + success(message: string): void { this.notification(message, "is-success"); } - error(message: string) { + error(message: string): void { this.notification(message, "is-danger"); } - info(message: string) { + info(message: string): void { this.notification(message, "is-info"); } @@ -60,6 +61,6 @@ export class Notifier { } /* eslint-disable */ -export function NotifierPlugin(vue: typeof Vue): void { +export function NotifierPlugin(vue: typeof VueInstance): void { vue.prototype.$notifier = new Notifier(vue); } diff --git a/js/src/utils/i18n.ts b/js/src/utils/i18n.ts index a6c867c10..7c412204d 100644 --- a/js/src/utils/i18n.ts +++ b/js/src/utils/i18n.ts @@ -1,18 +1,70 @@ import Vue from "vue"; import VueI18n from "vue-i18n"; -import messages from "../i18n/index"; +import { DateFnsPlugin } from "@/plugins/dateFns"; +import en from "../i18n/en_US.json"; +import langs from "../i18n/langs.json"; + +const DEFAULT_LOCALE = "en"; let language = document.documentElement.getAttribute("lang") as string; language = language || ((window.navigator as any).userLanguage || window.navigator.language).replace(/-/, "_"); -export const locale = language && messages.hasOwnProperty(language) ? language : language.split("-")[0]; +export const locale = + language && Object.prototype.hasOwnProperty.call(langs, language) ? language : language.split("-")[0]; Vue.use(VueI18n); +console.log(en); +console.log(locale); export const i18n = new VueI18n({ - locale, // set locale - messages, // set locale messages - fallbackLocale: "en_US", + locale: DEFAULT_LOCALE, // set locale + messages: (en as unknown) as VueI18n.LocaleMessages, // set locale messages + fallbackLocale: "en", }); +console.log(i18n); + +Vue.use(DateFnsPlugin, { locale }); + +const loadedLanguages = ["en"]; + +function setI18nLanguage(lang: string): string { + i18n.locale = lang; + return lang; +} + +function fileForLanguage(lang: string) { + const matches: Record<string, string> = { + fr: "fr_FR", + en: "en_US", + }; + if (Object.prototype.hasOwnProperty.call(matches, lang)) { + return matches[lang]; + } + return lang; +} + +export async function loadLanguageAsync(lang: string): Promise<string> { + // If the same language + if (i18n.locale === lang) { + return Promise.resolve(setI18nLanguage(lang)); + } + + // If the language was already loaded + if (loadedLanguages.includes(lang)) { + return Promise.resolve(setI18nLanguage(lang)); + } + + console.log(fileForLanguage(lang)); + // If the language hasn't been loaded yet + return import(/* webpackChunkName: "lang-[request]" */ `@/i18n/${fileForLanguage(lang)}.json`).then( + (newMessages: any) => { + i18n.setLocaleMessage(lang, newMessages.default); + loadedLanguages.push(lang); + return setI18nLanguage(lang); + } + ); +} + +loadLanguageAsync(locale); export function formatList(list: string[]): string { if (window.Intl && Intl.ListFormat) { diff --git a/js/src/variables.scss b/js/src/variables.scss index c005c974a..9323842af 100644 --- a/js/src/variables.scss +++ b/js/src/variables.scss @@ -135,7 +135,3 @@ $subtitle-sup-size: 15px; $breadcrumb-item-color: $primary; $checkbox-background-color: #fff; $title-color: $violet-3; - -@import "~bulma"; -@import "~bulma-divider"; -@import "~buefy/src/scss/buefy"; diff --git a/js/src/views/About.vue b/js/src/views/About.vue index dc16f4e23..1061e72b6 100644 --- a/js/src/views/About.vue +++ b/js/src/views/About.vue @@ -119,8 +119,6 @@ export default class About extends Vue { </script> <style lang="scss" scoped> -@import "../variables.scss"; - .hero.is-primary { background: $background-color; diff --git a/js/src/views/About/AboutInstance.vue b/js/src/views/About/AboutInstance.vue index 175bca407..13416dec4 100644 --- a/js/src/views/About/AboutInstance.vue +++ b/js/src/views/About/AboutInstance.vue @@ -122,8 +122,6 @@ export default class AboutInstance extends Vue { </script> <style lang="scss" scoped> -@import "../../variables.scss"; - section { &:not(:first-child) { margin: 2rem auto; diff --git a/js/src/views/About/AboutMobilizon.vue b/js/src/views/About/AboutMobilizon.vue index 0e36abe5c..0f26324b9 100644 --- a/js/src/views/About/AboutMobilizon.vue +++ b/js/src/views/About/AboutMobilizon.vue @@ -166,8 +166,6 @@ export default class AboutMobilizon extends Vue {} </script> <style lang="scss" scoped> -@import "../../variables.scss"; - .hero.is-primary { background: $background-color; .subtitle { diff --git a/js/src/views/About/Privacy.vue b/js/src/views/About/Privacy.vue index b6ee7e69f..8f99c52af 100644 --- a/js/src/views/About/Privacy.vue +++ b/js/src/views/About/Privacy.vue @@ -51,8 +51,6 @@ export default class Privacy extends Vue { } </script> <style lang="scss" scoped> -@import "@/variables.scss"; - main > .container { background: $white; diff --git a/js/src/views/About/Rules.vue b/js/src/views/About/Rules.vue index 3750b5acc..c154ba2c4 100644 --- a/js/src/views/About/Rules.vue +++ b/js/src/views/About/Rules.vue @@ -27,8 +27,6 @@ export default class Rules extends Vue { } </script> <style lang="scss" scoped> -@import "@/variables.scss"; - main > .container { background: $white; } diff --git a/js/src/views/Account/Profile.vue b/js/src/views/Account/Profile.vue index cfc4bb5b9..9cd1b8e00 100644 --- a/js/src/views/Account/Profile.vue +++ b/js/src/views/Account/Profile.vue @@ -144,8 +144,3 @@ export default class Profile extends Vue { } } </script> -<style lang="scss"> -@import "../../variables"; -@import "~bulma/sass/utilities/_all"; -@import "~bulma/sass/components/dropdown.sass"; -</style> diff --git a/js/src/views/Account/Register.vue b/js/src/views/Account/Register.vue index 1b7a62536..99fb4b2fc 100644 --- a/js/src/views/Account/Register.vue +++ b/js/src/views/Account/Register.vue @@ -168,7 +168,6 @@ export default class Register extends mixins(identityEditionMixin) { </script> <style lang="scss" scoped> -@import "../../variables.scss"; .avatar-enter-active { transition: opacity 1s ease; } diff --git a/js/src/views/Admin/Settings.vue b/js/src/views/Admin/Settings.vue index 214faa8ca..61d108e7a 100644 --- a/js/src/views/Admin/Settings.vue +++ b/js/src/views/Admin/Settings.vue @@ -359,8 +359,6 @@ export default class Settings extends Vue { } </script> <style lang="scss" scoped> -@import "../../variables.scss"; - .notification a { color: $primary !important; text-decoration: underline !important; diff --git a/js/src/views/Admin/Users.vue b/js/src/views/Admin/Users.vue index 218e1f28a..b554328bb 100644 --- a/js/src/views/Admin/Users.vue +++ b/js/src/views/Admin/Users.vue @@ -145,14 +145,13 @@ export default class Users extends Vue { }); } - onFiltersChange({ email }: { email: string }) { + onFiltersChange({ email }: { email: string }): void { this.email = email; } } </script> <style lang="scss" scoped> -@import "../../variables.scss"; a.profile, a.user-profile { text-decoration: none; diff --git a/js/src/views/Event/Edit.vue b/js/src/views/Event/Edit.vue index f58bed173..2fb16432b 100644 --- a/js/src/views/Event/Edit.vue +++ b/js/src/views/Event/Edit.vue @@ -296,8 +296,6 @@ </template> <style lang="scss" scoped> -@import "@/variables.scss"; - main section > .container { background: $white; } diff --git a/js/src/views/Event/Event.vue b/js/src/views/Event/Event.vue index a19ff0983..d02327424 100644 --- a/js/src/views/Event/Event.vue +++ b/js/src/views/Event/Event.vue @@ -1044,8 +1044,6 @@ export default class Event extends EventMixin { } </script> <style lang="scss" scoped> -@import "../../variables"; - .section { padding: 1rem 2rem 4rem; } diff --git a/js/src/views/Event/MyEvents.vue b/js/src/views/Event/MyEvents.vue index de6bc03e2..fe172894b 100644 --- a/js/src/views/Event/MyEvents.vue +++ b/js/src/views/Event/MyEvents.vue @@ -278,8 +278,6 @@ export default class MyEvents extends Vue { <!-- Add "scoped" attribute to limit CSS to this component only --> <style lang="scss" scoped> -@import "../../variables"; - main > .container { background: $white; } diff --git a/js/src/views/Event/Participants.vue b/js/src/views/Event/Participants.vue index 116f16536..139b37620 100644 --- a/js/src/views/Event/Participants.vue +++ b/js/src/views/Event/Participants.vue @@ -365,7 +365,7 @@ export default class Participants extends Vue { nl2br = nl2br; - toggleQueueDetails(row: IParticipant) { + toggleQueueDetails(row: IParticipant): void { if (row.metadata.message && row.metadata.message.length < MESSAGE_ELLIPSIS_LENGTH) return; this.queueTable.toggleDetails(row); } @@ -374,8 +374,6 @@ export default class Participants extends Vue { <!-- Add "scoped" attribute to limit CSS to this component only --> <style lang="scss" scoped> -@import "../../variables.scss"; - section { padding: 1rem 0; } diff --git a/js/src/views/Group/Group.vue b/js/src/views/Group/Group.vue index d0b811d29..cbc85e31e 100644 --- a/js/src/views/Group/Group.vue +++ b/js/src/views/Group/Group.vue @@ -546,8 +546,6 @@ export default class Group extends mixins(GroupMixin) { } </script> <style lang="scss" scoped> -@import "../../variables.scss"; - div.container { background: white; margin-bottom: 3rem; diff --git a/js/src/views/Group/MyGroups.vue b/js/src/views/Group/MyGroups.vue index a09232a32..ae9ee9494 100644 --- a/js/src/views/Group/MyGroups.vue +++ b/js/src/views/Group/MyGroups.vue @@ -120,8 +120,6 @@ export default class MyEvents extends Vue { <!-- Add "scoped" attribute to limit CSS to this component only --> <style lang="scss" scoped> -@import "../../variables"; - main > .container { background: $white; } diff --git a/js/src/views/Home.vue b/js/src/views/Home.vue index 6933aff6e..3478c1001 100644 --- a/js/src/views/Home.vue +++ b/js/src/views/Home.vue @@ -338,8 +338,6 @@ export default class Home extends Vue { </script> <style lang="scss" scoped> -@import "@/variables.scss"; - main > div > .container { background: $white; } diff --git a/js/src/views/Interact.vue b/js/src/views/Interact.vue index 898ab60ac..1c018c6f4 100644 --- a/js/src/views/Interact.vue +++ b/js/src/views/Interact.vue @@ -58,8 +58,6 @@ export default class Interact extends Vue { } </script> <style lang="scss"> -@import "@/variables.scss"; - main > .container { background: $white; } diff --git a/js/src/views/Moderation/Report.vue b/js/src/views/Moderation/Report.vue index 990d137db..94c3b4f4e 100644 --- a/js/src/views/Moderation/Report.vue +++ b/js/src/views/Moderation/Report.vue @@ -443,8 +443,6 @@ export default class Report extends Vue { } </script> <style lang="scss" scoped> -@import "@/variables.scss"; - tbody td img.image, .note img.image { display: inline; diff --git a/js/src/views/Posts/Post.vue b/js/src/views/Posts/Post.vue index 50663a539..9e5228af6 100644 --- a/js/src/views/Posts/Post.vue +++ b/js/src/views/Posts/Post.vue @@ -129,8 +129,6 @@ export default class Post extends Vue { } </script> <style lang="scss" scoped> -@import "../../variables.scss"; - article { section.heading-section { text-align: center; diff --git a/js/src/views/Search.vue b/js/src/views/Search.vue index d19a55011..b101bcc4e 100644 --- a/js/src/views/Search.vue +++ b/js/src/views/Search.vue @@ -366,8 +366,6 @@ export default class Search extends Vue { </script> <style scoped lang="scss"> -@import "@/variables.scss"; - main > .container { background: $white; diff --git a/js/src/views/Settings/AccountSettings.vue b/js/src/views/Settings/AccountSettings.vue index 6b84d531f..8e92b7167 100644 --- a/js/src/views/Settings/AccountSettings.vue +++ b/js/src/views/Settings/AccountSettings.vue @@ -323,8 +323,6 @@ export default class AccountSettings extends Vue { } </script> <style lang="scss"> -@import "@/variables.scss"; - .setting-title { margin-top: 2rem; margin-bottom: 1rem; diff --git a/js/src/views/Settings/Notifications.vue b/js/src/views/Settings/Notifications.vue index 9518b25e1..f020bf16d 100644 --- a/js/src/views/Settings/Notifications.vue +++ b/js/src/views/Settings/Notifications.vue @@ -155,8 +155,6 @@ export default class Notifications extends Vue { </script> <style lang="scss" scoped> -@import "../../variables.scss"; - .field { &:not(:last-child) { margin-bottom: 1.5rem; diff --git a/js/src/views/Settings/Preferences.vue b/js/src/views/Settings/Preferences.vue index 12238d850..7e82a5c3b 100644 --- a/js/src/views/Settings/Preferences.vue +++ b/js/src/views/Settings/Preferences.vue @@ -17,7 +17,7 @@ v-model="$i18n.locale" :placeholder="$t('Select a language')" > - <option v-for="(language, lang) in languages" :value="lang" :key="lang"> + <option v-for="(language, lang) in langs" :value="lang" :key="lang"> {{ language }} </option> </b-select> @@ -73,8 +73,10 @@ export default class Preferences extends Vue { RouteName = RouteName; + langs: Record<string, string> = langs; + @Watch("loggedUser") - setSavedTimezone(loggedUser: IUser) { + setSavedTimezone(loggedUser: IUser): void { if (loggedUser && loggedUser.settings.timezone) { this.selectedTimezone = loggedUser.settings.timezone; } else { @@ -87,22 +89,24 @@ export default class Preferences extends Vue { } } + // eslint-disable-next-line class-methods-use-this sanitize(timezone: string): string { return timezone.split("_").join(" ").replace("St ", "St. ").split("/").join(" - "); } - get timezones() { + get timezones(): Record<string, string[]> { if (!this.config || !this.config.timezones) return {}; return this.config.timezones.reduce((acc: { [key: string]: Array<string> }, val: string) => { const components = val.split("/"); const [prefix, suffix] = [components.shift() as string, components.join("/")]; const pushOrCreate = ( - acc: { [key: string]: Array<string> }, - prefix: string, - suffix: string + acc2: { [key: string]: Array<string> }, + prefix2: string, + suffix2: string ) => { - (acc[prefix] = acc[prefix] || []).push(suffix); - return acc; + // eslint-disable-next-line no-param-reassign + (acc2[prefix2] = acc2[prefix2] || []).push(suffix2); + return acc2; }; if (suffix) { return pushOrCreate(acc, prefix, suffix); @@ -111,22 +115,8 @@ export default class Preferences extends Vue { }, {}); } - get languages(): object { - return this.$i18n.availableLocales.reduce((acc: object, lang: string) => { - // @ts-ignore - if (langs[lang]) { - return { - ...acc, - // @ts-ignore - [lang]: langs[lang], - }; - } - return acc; - }, {} as object); - } - @Watch("selectedTimezone") - async updateTimezone() { + async updateTimezone(): Promise<void> { if (this.selectedTimezone !== this.loggedUser.settings.timezone) { await this.$apollo.mutate<{ setUserSetting: string }>({ mutation: SET_USER_SETTINGS, @@ -138,7 +128,7 @@ export default class Preferences extends Vue { } @Watch("$i18n.locale") - async updateLocale() { + async updateLocale(): Promise<void> { await this.$apollo.mutate({ mutation: UPDATE_USER_LOCALE, variables: { diff --git a/js/src/views/User/Register.vue b/js/src/views/User/Register.vue index 43c7a37fd..f57f6dcf4 100644 --- a/js/src/views/User/Register.vue +++ b/js/src/views/User/Register.vue @@ -212,9 +212,6 @@ export default class Register extends Vue { </script> <style lang="scss" scoped> -@import "../../variables"; -@import "../../common.scss"; - .avatar-enter-active { transition: opacity 1s ease; } diff --git a/js/tsconfig.json b/js/tsconfig.json index d1299c7f8..692d8f578 100644 --- a/js/tsconfig.json +++ b/js/tsconfig.json @@ -7,6 +7,7 @@ "importHelpers": true, "moduleResolution": "node", "experimentalDecorators": true, + "skipLibCheck": true, "esModuleInterop": true, "allowSyntheticDefaultImports": true, "resolveJsonModule": true, diff --git a/js/vue.config.js b/js/vue.config.js index 7ed74eb13..e10400d19 100644 --- a/js/vue.config.js +++ b/js/vue.config.js @@ -5,6 +5,7 @@ module.exports = { runtimeCompiler: true, lintOnSave: true, filenameHashing: true, + productionSourceMap: false, outputDir: path.resolve(__dirname, "../priv/static"), configureWebpack: (config) => { // Limit the used memory when building @@ -25,6 +26,17 @@ module.exports = { config.plugins.push(new ForkTsCheckerWebpackPlugin(forkTsCheckerOptions)); }, + chainWebpack: (config) => { + // remove the prefetch plugin + config.plugins.delete("prefetch"); + }, + css: { + loaderOptions: { + scss: { + additionalData: `@import "@/variables.scss";`, + }, + }, + }, // configureWebpack: { // optimization: { // splitChunks: { diff --git a/js/yarn.lock b/js/yarn.lock index 2dc473f07..e6d5cfacf 100644 --- a/js/yarn.lock +++ b/js/yarn.lock @@ -1352,11 +1352,6 @@ dependencies: "@types/node" "*" -"@types/javascript-time-ago@^2.0.1": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@types/javascript-time-ago/-/javascript-time-ago-2.0.1.tgz#819ec39b467409e2fd6acb42bc53ae7d631bbdb0" - integrity sha512-6QWXsuqzfUMfsg1DTJan/MfUi80LGS1TOohSqxlgpBZEHH344xpl3LzgANTp7PPWf7Z/9S0l14RMQPF0vH7MIg== - "@types/json-schema@^7.0.3", "@types/json-schema@^7.0.4", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.6": version "7.0.6" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.6.tgz#f4c7ec43e81b319a9815115031709f26987891f0" @@ -7988,13 +7983,6 @@ javascript-stringify@^2.0.0, javascript-stringify@^2.0.1: resolved "https://registry.yarnpkg.com/javascript-stringify/-/javascript-stringify-2.0.1.tgz#6ef358035310e35d667c675ed63d3eb7c1aa19e5" integrity sha512-yV+gqbd5vaOYjqlbk16EG89xB5udgjqQF3C5FAORDg4f/IS1Yc5ERCv5e/57yBcfJYw05V5JyIXabhwb75Xxow== -javascript-time-ago@^2.0.4: - version "2.2.8" - resolved "https://registry.yarnpkg.com/javascript-time-ago/-/javascript-time-ago-2.2.8.tgz#d2821816a648f4659f605e030418af7949f0564e" - integrity sha512-VU2GZ88QYl7zEfnKe2VecnPlXunr1awIAf21S13CRUUYlk6cVbmA81GApMXHIbDUfYfsJVcPjjB76KLEPO4fGA== - dependencies: - relative-time-format "^1.0.5" - jest-worker@^25.4.0: version "25.5.0" resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-25.5.0.tgz#2611d071b79cea0f43ee57a3d118593ac1547db1" @@ -11941,11 +11929,6 @@ relateurl@0.2.x: resolved "https://registry.yarnpkg.com/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9" integrity sha1-VNvzd+UUQKypCkzSdGANP/LYiKk= -relative-time-format@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/relative-time-format/-/relative-time-format-1.0.5.tgz#3fb7c76ae39156afe0a3a7ff0cb7bf30aa0f0fb6" - integrity sha512-MAgx/YKcUQYJpIaWcfetPstElnWf26JxVis4PirdwVrrymFdbxyCSm6yENpfB1YuwFbtHSHksN3aBajVNxk10Q== - remark-parse@^7.0.0: version "7.0.2" resolved "https://registry.yarnpkg.com/remark-parse/-/remark-parse-7.0.2.tgz#41e7170d9c1d96c3d32cf1109600a9ed50dba7cf"