-
+
+ {Component => ()}
+
diff --git a/app/soapbox/features/ui/util/async-components.js b/app/soapbox/features/ui/util/async-components.js
index 9c2218f8e..1622ca575 100644
--- a/app/soapbox/features/ui/util/async-components.js
+++ b/app/soapbox/features/ui/util/async-components.js
@@ -465,3 +465,7 @@ export function CreateApp() {
export function SettingsStore() {
return import(/* webpackChunkName: "features/developers" */'../../developers/settings_store');
}
+
+export function DatePicker() {
+ return import(/* webpackChunkName: "date_picker" */'../../birthdays/date_picker');
+}
diff --git a/app/soapbox/normalizers/__tests__/account-test.js b/app/soapbox/normalizers/__tests__/account-test.js
index 9211a1cf8..8d12a935d 100644
--- a/app/soapbox/normalizers/__tests__/account-test.js
+++ b/app/soapbox/normalizers/__tests__/account-test.js
@@ -3,25 +3,27 @@ import { Record as ImmutableRecord, fromJS } from 'immutable';
import { normalizeAccount } from '../account';
const AVATAR_MISSING = require('images/avatar-missing.png');
+const HEADER_MISSING = require('images/header-missing.png');
describe('normalizeAccount()', () => {
it('adds base fields', () => {
- const account = fromJS({});
+ const account = {};
const result = normalizeAccount(account);
expect(ImmutableRecord.isRecord(result)).toBe(true);
expect(result.acct).toEqual('');
expect(result.note).toEqual('');
expect(result.avatar).toEqual(AVATAR_MISSING);
+ expect(result.header_static).toEqual(HEADER_MISSING);
});
it('normalizes a mention', () => {
- const mention = fromJS({
+ const mention = {
acct: 'NEETzsche@iddqd.social',
id: '9v5bw7hEGBPc9nrpzc',
url: 'https://iddqd.social/users/NEETzsche',
username: 'NEETzsche',
- });
+ };
const result = normalizeAccount(mention);
expect(result.emojis).toEqual(fromJS([]));
@@ -32,21 +34,21 @@ describe('normalizeAccount()', () => {
});
it('normalizes Fedibird birthday', () => {
- const account = fromJS(require('soapbox/__fixtures__/fedibird-account.json'));
+ const account = require('soapbox/__fixtures__/fedibird-account.json');
const result = normalizeAccount(account);
expect(result.birthday).toEqual('1993-07-03');
});
it('normalizes Pleroma birthday', () => {
- const account = fromJS(require('soapbox/__fixtures__/pleroma-account.json'));
+ const account = require('soapbox/__fixtures__/pleroma-account.json');
const result = normalizeAccount(account);
expect(result.birthday).toEqual('1993-07-03');
});
it('normalizes Pleroma legacy fields', () => {
- const account = fromJS(require('soapbox/__fixtures__/pleroma-2.2.2-account.json'));
+ const account = require('soapbox/__fixtures__/pleroma-2.2.2-account.json');
const result = normalizeAccount(account);
expect(result.getIn(['pleroma', 'is_active'])).toBe(true);
@@ -57,7 +59,7 @@ describe('normalizeAccount()', () => {
});
it('prefers new Pleroma fields', () => {
- const account = fromJS(require('soapbox/__fixtures__/pleroma-account.json'));
+ const account = require('soapbox/__fixtures__/pleroma-account.json');
const result = normalizeAccount(account);
expect(result.getIn(['pleroma', 'is_active'])).toBe(true);
@@ -66,76 +68,82 @@ describe('normalizeAccount()', () => {
});
it('normalizes a verified Pleroma user', () => {
- const account = fromJS(require('soapbox/__fixtures__/mk.json'));
+ const account = require('soapbox/__fixtures__/mk.json');
const result = normalizeAccount(account);
expect(result.verified).toBe(true);
});
it('normalizes an unverified Pleroma user', () => {
- const account = fromJS(require('soapbox/__fixtures__/pleroma-account.json'));
+ const account = require('soapbox/__fixtures__/pleroma-account.json');
const result = normalizeAccount(account);
expect(result.verified).toBe(false);
});
it('normalizes a verified Truth Social user', () => {
- const account = fromJS(require('soapbox/__fixtures__/realDonaldTrump.json'));
+ const account = require('soapbox/__fixtures__/realDonaldTrump.json');
const result = normalizeAccount(account);
expect(result.verified).toBe(true);
});
it('normalizes Fedibird location', () => {
- const account = fromJS(require('soapbox/__fixtures__/fedibird-account.json'));
+ const account = require('soapbox/__fixtures__/fedibird-account.json');
const result = normalizeAccount(account);
expect(result.location).toBe('Texas, USA');
});
it('normalizes Truth Social location', () => {
- const account = fromJS(require('soapbox/__fixtures__/truthsocial-account.json'));
+ const account = require('soapbox/__fixtures__/truthsocial-account.json');
const result = normalizeAccount(account);
expect(result.location).toBe('Texas');
});
+ it('normalizes Truth Social website', () => {
+ const account = require('soapbox/__fixtures__/truthsocial-account.json');
+ const result = normalizeAccount(account);
+ expect(result.website).toBe('https://soapbox.pub');
+ });
+
it('sets display_name from username', () => {
- const account = fromJS({ username: 'alex' });
+ const account = { username: 'alex' };
const result = normalizeAccount(account);
expect(result.display_name).toBe('alex');
});
it('sets display_name from acct', () => {
- const account = fromJS({ acct: 'alex@gleasonator.com' });
+ const account = { acct: 'alex@gleasonator.com' };
const result = normalizeAccount(account);
expect(result.display_name).toBe('alex');
});
it('overrides a whitespace display_name', () => {
- const account = fromJS({ username: 'alex', display_name: ' ' });
+ const account = { username: 'alex', display_name: ' ' };
const result = normalizeAccount(account);
expect(result.display_name).toBe('alex');
});
it('emojifies display name as `display_name_html`', () => {
- const account = fromJS(require('soapbox/__fixtures__/account-with-emojis.json'));
+ const account = require('soapbox/__fixtures__/account-with-emojis.json');
const result = normalizeAccount(account);
const expected = 'Alex Gleason
';
expect(result.display_name_html).toBe(expected);
});
it('emojifies note as `note_emojified`', () => {
- const account = fromJS(require('soapbox/__fixtures__/account-with-emojis.json'));
+ const account = require('soapbox/__fixtures__/account-with-emojis.json');
const result = normalizeAccount(account);
const expected = 'I create Fediverse software that empowers people online.
I'm vegan btw
Note: If you have a question for me, please tag me publicly. This gives the opportunity for others to chime in, and bystanders to learn.';
expect(result.note_emojified).toBe(expected);
});
it('unescapes HTML note as `note_plain`', () => {
- const account = fromJS(require('soapbox/__fixtures__/account-with-emojis.json'));
+ const account = require('soapbox/__fixtures__/account-with-emojis.json');
const result = normalizeAccount(account);
const expected = 'I create Fediverse software that empowers people online. :soapbox:\n\nI\'m vegan btw\n\nNote: If you have a question for me, please tag me publicly. This gives the opportunity for others to chime in, and bystanders to learn.';
expect(result.note_plain).toBe(expected);
});
it('emojifies custom profile field', () => {
- const account = fromJS(require('soapbox/__fixtures__/account-with-emojis.json'));
+ const account = require('soapbox/__fixtures__/account-with-emojis.json');
const result = normalizeAccount(account);
const field = result.fields.get(1);
@@ -143,4 +151,21 @@ describe('normalizeAccount()', () => {
expect(field.value_emojified).toBe('
https://soapbox.pub ');
expect(field.value_plain).toBe('https://soapbox.pub :soapbox:');
});
+
+ it('adds default avatar and banner to GoToSocial account', () => {
+ const account = require('soapbox/__fixtures__/gotosocial-account.json');
+ const result = normalizeAccount(account);
+
+ expect(result.avatar).toEqual(AVATAR_MISSING);
+ expect(result.avatar_static).toEqual(AVATAR_MISSING);
+ expect(result.header).toEqual(HEADER_MISSING);
+ expect(result.header_static).toEqual(HEADER_MISSING);
+ });
+
+ it('adds fqn to Mastodon account', () => {
+ const account = require('soapbox/__fixtures__/mastodon-account.json');
+ const result = normalizeAccount(account);
+
+ expect(result.fqn).toEqual('benis911@mastodon.social');
+ });
});
diff --git a/app/soapbox/normalizers/__tests__/attachment-test.js b/app/soapbox/normalizers/__tests__/attachment-test.js
index ecf3813e7..9647a55fa 100644
--- a/app/soapbox/normalizers/__tests__/attachment-test.js
+++ b/app/soapbox/normalizers/__tests__/attachment-test.js
@@ -1,10 +1,10 @@
-import { Record as ImmutableRecord, fromJS } from 'immutable';
+import { Record as ImmutableRecord } from 'immutable';
import { normalizeAttachment } from '../attachment';
describe('normalizeAttachment()', () => {
it('adds base fields', () => {
- const attachment = fromJS({});
+ const attachment = {};
const result = normalizeAttachment(attachment);
expect(ImmutableRecord.isRecord(result)).toBe(true);
@@ -13,7 +13,7 @@ describe('normalizeAttachment()', () => {
});
it('infers preview_url from url', () => {
- const attachment = fromJS({ url: 'https://site.fedi/123.png' });
+ const attachment = { url: 'https://site.fedi/123.png' };
const result = normalizeAttachment(attachment);
expect(result.preview_url).toEqual('https://site.fedi/123.png');
diff --git a/app/soapbox/normalizers/__tests__/card-test.js b/app/soapbox/normalizers/__tests__/card-test.js
index e8ac120b0..fc8d06221 100644
--- a/app/soapbox/normalizers/__tests__/card-test.js
+++ b/app/soapbox/normalizers/__tests__/card-test.js
@@ -1,10 +1,10 @@
-import { Record as ImmutableRecord, fromJS } from 'immutable';
+import { Record as ImmutableRecord } from 'immutable';
import { normalizeCard } from '../card';
describe('normalizeCard()', () => {
it('adds base fields', () => {
- const card = fromJS({});
+ const card = {};
const result = normalizeCard(card);
expect(ImmutableRecord.isRecord(result)).toBe(true);
diff --git a/app/soapbox/normalizers/__tests__/instance-test.js b/app/soapbox/normalizers/__tests__/instance-test.js
index 597fbbeee..f5fd4f6af 100644
--- a/app/soapbox/normalizers/__tests__/instance-test.js
+++ b/app/soapbox/normalizers/__tests__/instance-test.js
@@ -59,7 +59,7 @@ describe('normalizeInstance()', () => {
});
it('normalizes Pleroma instance with Mastodon configuration format', () => {
- const instance = fromJS(require('soapbox/__fixtures__/pleroma-instance.json'));
+ const instance = require('soapbox/__fixtures__/pleroma-instance.json');
const expected = {
configuration: {
@@ -81,7 +81,7 @@ describe('normalizeInstance()', () => {
});
it('normalizes Mastodon instance with retained configuration', () => {
- const instance = fromJS(require('soapbox/__fixtures__/mastodon-instance.json'));
+ const instance = require('soapbox/__fixtures__/mastodon-instance.json');
const expected = {
configuration: {
@@ -111,7 +111,7 @@ describe('normalizeInstance()', () => {
});
it('normalizes Mastodon 3.0.0 instance with default configuration', () => {
- const instance = fromJS(require('soapbox/__fixtures__/mastodon-3.0.0-instance.json'));
+ const instance = require('soapbox/__fixtures__/mastodon-3.0.0-instance.json');
const expected = {
configuration: {
@@ -133,18 +133,18 @@ describe('normalizeInstance()', () => {
});
it('normalizes Fedibird instance', () => {
- const instance = fromJS(require('soapbox/__fixtures__/fedibird-instance.json'));
+ const instance = require('soapbox/__fixtures__/fedibird-instance.json');
const result = normalizeInstance(instance);
// Sets description_limit
expect(result.description_limit).toEqual(1500);
// Preserves fedibird_capabilities
- expect(result.fedibird_capabilities).toEqual(instance.get('fedibird_capabilities'));
+ expect(result.fedibird_capabilities).toEqual(fromJS(instance.fedibird_capabilities));
});
it('normalizes Mitra instance', () => {
- const instance = fromJS(require('soapbox/__fixtures__/mitra-instance.json'));
+ const instance = require('soapbox/__fixtures__/mitra-instance.json');
const result = normalizeInstance(instance);
// Adds configuration and description_limit
@@ -153,7 +153,7 @@ describe('normalizeInstance()', () => {
});
it('normalizes GoToSocial instance', () => {
- const instance = fromJS(require('soapbox/__fixtures__/gotosocial-instance.json'));
+ const instance = require('soapbox/__fixtures__/gotosocial-instance.json');
const result = normalizeInstance(instance);
// Normalizes max_toot_chars
@@ -166,7 +166,7 @@ describe('normalizeInstance()', () => {
});
it('normalizes Friendica instance', () => {
- const instance = fromJS(require('soapbox/__fixtures__/friendica-instance.json'));
+ const instance = require('soapbox/__fixtures__/friendica-instance.json');
const result = normalizeInstance(instance);
// Normalizes max_toot_chars
@@ -177,4 +177,11 @@ describe('normalizeInstance()', () => {
expect(result.get('configuration') instanceof ImmutableMap).toBe(true);
expect(result.get('description_limit')).toBe(1500);
});
+
+ it('normalizes a Mastodon RC version', () => {
+ const instance = require('soapbox/__fixtures__/mastodon-instance-rc.json');
+ const result = normalizeInstance(instance);
+
+ expect(result.version).toEqual('3.5.0-rc1');
+ });
});
diff --git a/app/soapbox/normalizers/__tests__/mention-test.js b/app/soapbox/normalizers/__tests__/mention-test.js
index e429a03b1..03d712175 100644
--- a/app/soapbox/normalizers/__tests__/mention-test.js
+++ b/app/soapbox/normalizers/__tests__/mention-test.js
@@ -1,10 +1,10 @@
-import { Record as ImmutableRecord, fromJS } from 'immutable';
+import { Record as ImmutableRecord } from 'immutable';
import { normalizeMention } from '../mention';
describe('normalizeMention()', () => {
it('adds base fields', () => {
- const account = fromJS({});
+ const account = {};
const result = normalizeMention(account);
expect(ImmutableRecord.isRecord(result)).toBe(true);
@@ -15,7 +15,7 @@ describe('normalizeMention()', () => {
});
it('infers username from acct', () => {
- const account = fromJS({ acct: 'alex@gleasonator.com' });
+ const account = { acct: 'alex@gleasonator.com' };
const result = normalizeMention(account);
expect(result.username).toEqual('alex');
diff --git a/app/soapbox/normalizers/__tests__/notification-test.js b/app/soapbox/normalizers/__tests__/notification-test.js
index c90b5451e..b72f0d9aa 100644
--- a/app/soapbox/normalizers/__tests__/notification-test.js
+++ b/app/soapbox/normalizers/__tests__/notification-test.js
@@ -1,10 +1,10 @@
-import { Record as ImmutableRecord, fromJS } from 'immutable';
+import { Record as ImmutableRecord } from 'immutable';
import { normalizeNotification } from '../notification';
describe('normalizeNotification()', () => {
it('normalizes an empty map', () => {
- const notification = fromJS({});
+ const notification = {};
const result = normalizeNotification(notification);
expect(ImmutableRecord.isRecord(result)).toBe(true);
diff --git a/app/soapbox/normalizers/__tests__/poll-test.js b/app/soapbox/normalizers/__tests__/poll-test.js
index 4cc9dbbbc..31691f484 100644
--- a/app/soapbox/normalizers/__tests__/poll-test.js
+++ b/app/soapbox/normalizers/__tests__/poll-test.js
@@ -1,10 +1,10 @@
-import { Record as ImmutableRecord, fromJS } from 'immutable';
+import { Record as ImmutableRecord } from 'immutable';
import { normalizePoll } from '../poll';
describe('normalizePoll()', () => {
it('adds base fields', () => {
- const poll = fromJS({ options: [{ title: 'Apples' }] });
+ const poll = { options: [{ title: 'Apples' }] };
const result = normalizePoll(poll);
const expected = {
@@ -25,7 +25,7 @@ describe('normalizePoll()', () => {
});
it('normalizes a Pleroma logged-out poll', () => {
- const poll = fromJS(require('soapbox/__fixtures__/pleroma-status-with-poll.json')).get('poll');
+ const { poll } = require('soapbox/__fixtures__/pleroma-status-with-poll.json');
const result = normalizePoll(poll);
// Adds logged-in fields
@@ -34,7 +34,7 @@ describe('normalizePoll()', () => {
});
it('normalizes poll with emojis', () => {
- const poll = fromJS(require('soapbox/__fixtures__/pleroma-status-with-poll-with-emojis.json')).get('poll');
+ const { poll } = require('soapbox/__fixtures__/pleroma-status-with-poll-with-emojis.json');
const result = normalizePoll(poll);
// Emojifies poll options
diff --git a/app/soapbox/normalizers/__tests__/status-test.js b/app/soapbox/normalizers/__tests__/status-test.js
index 2824615cc..ebfcb3eee 100644
--- a/app/soapbox/normalizers/__tests__/status-test.js
+++ b/app/soapbox/normalizers/__tests__/status-test.js
@@ -4,7 +4,7 @@ import { normalizeStatus } from '../status';
describe('normalizeStatus()', () => {
it('adds base fields', () => {
- const status = fromJS({});
+ const status = {};
const result = normalizeStatus(status);
expect(ImmutableRecord.isRecord(result)).toBe(true);
@@ -17,7 +17,7 @@ describe('normalizeStatus()', () => {
});
it('fixes the order of mentions', () => {
- const status = fromJS(require('soapbox/__fixtures__/status-unordered-mentions.json'));
+ const status = require('soapbox/__fixtures__/status-unordered-mentions.json');
const expected = ['NEETzsche', 'alex', 'Lumeinshin', 'sneeden'];
@@ -30,7 +30,7 @@ describe('normalizeStatus()', () => {
});
it('adds mention to self in self-reply on Mastodon', () => {
- const status = fromJS(require('soapbox/__fixtures__/mastodon-reply-to-self.json'));
+ const status = require('soapbox/__fixtures__/mastodon-reply-to-self.json');
const expected = {
id: '106801667066418367',
@@ -48,7 +48,7 @@ describe('normalizeStatus()', () => {
});
it('normalizes mentions with only acct', () => {
- const status = fromJS({ mentions: [{ acct: 'alex@gleasonator.com' }] });
+ const status = { mentions: [{ acct: 'alex@gleasonator.com' }] };
const expected = [{
id: '',
@@ -63,7 +63,7 @@ describe('normalizeStatus()', () => {
});
it('normalizes Mitra attachments', () => {
- const status = fromJS(require('soapbox/__fixtures__/mitra-status-with-attachments.json'));
+ const status = require('soapbox/__fixtures__/mitra-status-with-attachments.json');
const expected = [{
id: '017eeb0e-e5df-30a4-77a7-a929145cb836',
@@ -97,7 +97,7 @@ describe('normalizeStatus()', () => {
});
it('leaves Pleroma attachments alone', () => {
- const status = fromJS(require('soapbox/__fixtures__/pleroma-status-with-attachments.json'));
+ const status = require('soapbox/__fixtures__/pleroma-status-with-attachments.json');
const result = normalizeStatus(status).media_attachments;
expect(result.size).toBe(4);
@@ -108,15 +108,15 @@ describe('normalizeStatus()', () => {
});
it('normalizes Pleroma quote post', () => {
- const status = fromJS(require('soapbox/__fixtures__/pleroma-quote-post.json'));
+ const status = require('soapbox/__fixtures__/pleroma-quote-post.json');
const result = normalizeStatus(status);
- expect(result.quote).toEqual(status.getIn(['pleroma', 'quote']));
+ expect(result.quote).toEqual(fromJS(status.pleroma.quote));
expect(result.pleroma.get('quote')).toBe(undefined);
});
it('normalizes GoToSocial status', () => {
- const status = fromJS(require('soapbox/__fixtures__/gotosocial-status.json'));
+ const status = require('soapbox/__fixtures__/gotosocial-status.json');
const result = normalizeStatus(status);
// Adds missing fields
@@ -132,7 +132,7 @@ describe('normalizeStatus()', () => {
});
it('normalizes Friendica status', () => {
- const status = fromJS(require('soapbox/__fixtures__/friendica-status.json'));
+ const status = require('soapbox/__fixtures__/friendica-status.json');
const result = normalizeStatus(status);
// Adds missing fields
@@ -145,7 +145,7 @@ describe('normalizeStatus()', () => {
});
it('normalizes poll and poll options', () => {
- const status = fromJS({ poll: { options: [{ title: 'Apples' }] } });
+ const status = { poll: { options: [{ title: 'Apples' }] } };
const result = normalizeStatus(status);
const expected = {
@@ -166,7 +166,7 @@ describe('normalizeStatus()', () => {
});
it('normalizes a Pleroma logged-out poll', () => {
- const status = fromJS(require('soapbox/__fixtures__/pleroma-status-with-poll.json'));
+ const status = require('soapbox/__fixtures__/pleroma-status-with-poll.json');
const result = normalizeStatus(status);
// Adds logged-in fields
@@ -175,7 +175,7 @@ describe('normalizeStatus()', () => {
});
it('normalizes poll with emojis', () => {
- const status = fromJS(require('soapbox/__fixtures__/pleroma-status-with-poll-with-emojis.json'));
+ const status = require('soapbox/__fixtures__/pleroma-status-with-poll-with-emojis.json');
const result = normalizeStatus(status);
// Emojifies poll options
@@ -188,7 +188,7 @@ describe('normalizeStatus()', () => {
});
it('normalizes a card', () => {
- const status = fromJS(require('soapbox/__fixtures__/status-with-card.json'));
+ const status = require('soapbox/__fixtures__/status-with-card.json');
const result = normalizeStatus(status);
expect(ImmutableRecord.isRecord(result.card)).toBe(true);
diff --git a/app/soapbox/normalizers/account.ts b/app/soapbox/normalizers/account.ts
index 7faa3282c..1c536ee4a 100644
--- a/app/soapbox/normalizers/account.ts
+++ b/app/soapbox/normalizers/account.ts
@@ -8,16 +8,18 @@ import {
Map as ImmutableMap,
List as ImmutableList,
Record as ImmutableRecord,
+ fromJS,
} from 'immutable';
import emojify from 'soapbox/features/emoji/emoji';
import { normalizeEmoji } from 'soapbox/normalizers/emoji';
import { IAccount } from 'soapbox/types';
+import { acctFull } from 'soapbox/utils/accounts';
import { unescapeHTML } from 'soapbox/utils/html';
import { mergeDefined, makeEmojiMap } from 'soapbox/utils/normalizers';
// https://docs.joinmastodon.org/entities/account/
-const AccountRecord = ImmutableRecord({
+export const AccountRecord = ImmutableRecord({
acct: '',
avatar: '',
avatar_static: '',
@@ -44,6 +46,7 @@ const AccountRecord = ImmutableRecord({
uri: '',
url: '',
username: '',
+ website: '',
verified: false,
// Internal fields
@@ -56,7 +59,7 @@ const AccountRecord = ImmutableRecord({
});
// https://docs.joinmastodon.org/entities/field/
-const FieldRecord = ImmutableRecord({
+export const FieldRecord = ImmutableRecord({
name: '',
value: '',
verified_at: null,
@@ -95,6 +98,18 @@ const normalizeAvatar = (account: ImmutableMap
) => {
});
};
+// Add header, if missing
+const normalizeHeader = (account: ImmutableMap) => {
+ const header = account.get('header');
+ const headerStatic = account.get('header_static');
+ const missing = require('images/header-missing.png');
+
+ return account.withMutations(account => {
+ account.set('header', header || headerStatic || missing);
+ account.set('header_static', headerStatic || header || missing);
+ });
+};
+
// Normalize custom fields
const normalizeFields = (account: ImmutableMap) => {
return account.update('fields', ImmutableList(), fields => fields.map(FieldRecord));
@@ -132,11 +147,12 @@ const normalizeVerified = (account: ImmutableMap) => {
});
};
-// Normalize Fedibird/Truth Social location
+// Normalize Fedibird/Truth Social/Pleroma location
const normalizeLocation = (account: ImmutableMap) => {
return account.update('location', location => {
return [
location,
+ account.getIn(['pleroma', 'location']),
account.getIn(['other_settings', 'location']),
].find(Boolean);
});
@@ -180,16 +196,22 @@ const addInternalFields = (account: ImmutableMap) => {
});
};
-export const normalizeAccount = (account: ImmutableMap): IAccount => {
+const normalizeFqn = (account: ImmutableMap) => {
+ return account.set('fqn', acctFull(account));
+};
+
+export const normalizeAccount = (account: Record): IAccount => {
return AccountRecord(
- account.withMutations(account => {
+ ImmutableMap(fromJS(account)).withMutations(account => {
normalizePleromaLegacyFields(account);
normalizeEmojis(account);
normalizeAvatar(account);
+ normalizeHeader(account);
normalizeFields(account);
normalizeVerified(account);
normalizeBirthday(account);
normalizeLocation(account);
+ normalizeFqn(account);
fixUsername(account);
fixDisplayName(account);
addInternalFields(account);
diff --git a/app/soapbox/normalizers/attachment.ts b/app/soapbox/normalizers/attachment.ts
index 9599fc1ce..26e616696 100644
--- a/app/soapbox/normalizers/attachment.ts
+++ b/app/soapbox/normalizers/attachment.ts
@@ -6,12 +6,13 @@
import {
Map as ImmutableMap,
Record as ImmutableRecord,
+ fromJS,
} from 'immutable';
import { mergeDefined } from 'soapbox/utils/normalizers';
// https://docs.joinmastodon.org/entities/attachment/
-const AttachmentRecord = ImmutableRecord({
+export const AttachmentRecord = ImmutableRecord({
blurhash: undefined,
description: '',
id: '',
@@ -29,7 +30,7 @@ const AttachmentRecord = ImmutableRecord({
});
// Ensure attachments have required fields
-export const normalizeAttachment = (attachment: ImmutableMap) => {
+const normalizeUrls = (attachment: ImmutableMap) => {
const url = [
attachment.get('url'),
attachment.get('preview_url'),
@@ -41,5 +42,11 @@ export const normalizeAttachment = (attachment: ImmutableMap) => {
preview_url: url,
});
- return AttachmentRecord(attachment.mergeWith(mergeDefined, base));
+ return attachment.mergeWith(mergeDefined, base);
+};
+
+export const normalizeAttachment = (attachment: Record) => {
+ return AttachmentRecord(
+ normalizeUrls(ImmutableMap(fromJS(attachment))),
+ );
};
diff --git a/app/soapbox/normalizers/card.ts b/app/soapbox/normalizers/card.ts
index c9ac76adb..169492647 100644
--- a/app/soapbox/normalizers/card.ts
+++ b/app/soapbox/normalizers/card.ts
@@ -3,10 +3,10 @@
* Converts API cards into our internal format.
* @see {@link https://docs.joinmastodon.org/entities/card/}
*/
-import { Record as ImmutableRecord, Map as ImmutableMap } from 'immutable';
+import { Record as ImmutableRecord, Map as ImmutableMap, fromJS } from 'immutable';
// https://docs.joinmastodon.org/entities/card/
-const CardRecord = ImmutableRecord({
+export const CardRecord = ImmutableRecord({
author_name: '',
author_url: '',
blurhash: null,
@@ -23,6 +23,8 @@ const CardRecord = ImmutableRecord({
width: 0,
});
-export const normalizeCard = (card: ImmutableMap) => {
- return CardRecord(card);
+export const normalizeCard = (card: Record) => {
+ return CardRecord(
+ ImmutableMap(fromJS(card)),
+ );
};
diff --git a/app/soapbox/normalizers/emoji.ts b/app/soapbox/normalizers/emoji.ts
index f450af253..8d973b175 100644
--- a/app/soapbox/normalizers/emoji.ts
+++ b/app/soapbox/normalizers/emoji.ts
@@ -3,10 +3,10 @@
* Converts API emojis into our internal format.
* @see {@link https://docs.joinmastodon.org/entities/emoji/}
*/
-import { Record as ImmutableRecord, Map as ImmutableMap } from 'immutable';
+import { Record as ImmutableRecord, Map as ImmutableMap, fromJS } from 'immutable';
// https://docs.joinmastodon.org/entities/emoji/
-const EmojiRecord = ImmutableRecord({
+export const EmojiRecord = ImmutableRecord({
category: '',
shortcode: '',
static_url: '',
@@ -14,6 +14,8 @@ const EmojiRecord = ImmutableRecord({
visible_in_picker: true,
});
-export const normalizeEmoji = (emoji: ImmutableMap) => {
- return EmojiRecord(emoji);
+export const normalizeEmoji = (emoji: Record) => {
+ return EmojiRecord(
+ ImmutableMap(fromJS(emoji)),
+ );
};
diff --git a/app/soapbox/normalizers/index.ts b/app/soapbox/normalizers/index.ts
new file mode 100644
index 000000000..c4a34d66c
--- /dev/null
+++ b/app/soapbox/normalizers/index.ts
@@ -0,0 +1,9 @@
+export { AccountRecord, FieldRecord, normalizeAccount } from './account';
+export { AttachmentRecord, normalizeAttachment } from './attachment';
+export { CardRecord, normalizeCard } from './card';
+export { EmojiRecord, normalizeEmoji } from './emoji';
+export { InstanceRecord, normalizeInstance } from './instance';
+export { MentionRecord, normalizeMention } from './mention';
+export { NotificationRecord, normalizeNotification } from './notification';
+export { PollRecord, PollOptionRecord, normalizePoll } from './poll';
+export { StatusRecord, normalizeStatus } from './status';
diff --git a/app/soapbox/normalizers/instance.ts b/app/soapbox/normalizers/instance.ts
index 8e0fe02a6..a33601bf9 100644
--- a/app/soapbox/normalizers/instance.ts
+++ b/app/soapbox/normalizers/instance.ts
@@ -7,6 +7,7 @@ import {
Map as ImmutableMap,
List as ImmutableList,
Record as ImmutableRecord,
+ fromJS,
} from 'immutable';
import { parseVersion, PLEROMA } from 'soapbox/utils/features';
@@ -15,7 +16,7 @@ import { isNumber } from 'soapbox/utils/numbers';
// Use Mastodon defaults
// https://docs.joinmastodon.org/entities/instance/
-const InstanceRecord = ImmutableRecord({
+export const InstanceRecord = ImmutableRecord({
approval_required: false,
contact_account: ImmutableMap(),
configuration: ImmutableMap({
@@ -83,13 +84,25 @@ const pleromaToMastodonConfig = (instance: ImmutableMap) => {
// Get the software's default attachment limit
const getAttachmentLimit = (software: string) => software === PLEROMA ? Infinity : 4;
-// Normalize instance (Pleroma, Mastodon, etc.) to Mastodon's format
-export const normalizeInstance = (instance: ImmutableMap) => {
- const { software } = parseVersion(instance.get('version'));
- const mastodonConfig = pleromaToMastodonConfig(instance);
+// Normalize version
+const normalizeVersion = (instance: ImmutableMap) => {
+ return instance.update('version', '0.0.0', version => {
+ // Handle Mastodon release candidates
+ if (new RegExp(/[0-9\.]+rc[0-9]+/g).test(version)) {
+ return version.split('rc').join('-rc');
+ } else {
+ return version;
+ }
+ });
+};
+// Normalize instance (Pleroma, Mastodon, etc.) to Mastodon's format
+export const normalizeInstance = (instance: Record) => {
return InstanceRecord(
- instance.withMutations(instance => {
+ ImmutableMap(fromJS(instance)).withMutations((instance: ImmutableMap) => {
+ const { software } = parseVersion(instance.get('version'));
+ const mastodonConfig = pleromaToMastodonConfig(instance);
+
// Merge configuration
instance.update('configuration', ImmutableMap(), configuration => (
configuration.mergeDeepWith(mergeDefined, mastodonConfig)
@@ -100,6 +113,9 @@ export const normalizeInstance = (instance: ImmutableMap) => {
return isNumber(value) ? value : getAttachmentLimit(software);
});
+ // Normalize version
+ normalizeVersion(instance);
+
// Merge defaults
instance.mergeDeepWith(mergeDefined, InstanceRecord());
}),
diff --git a/app/soapbox/normalizers/mention.ts b/app/soapbox/normalizers/mention.ts
index 998202065..5ff35ce16 100644
--- a/app/soapbox/normalizers/mention.ts
+++ b/app/soapbox/normalizers/mention.ts
@@ -3,22 +3,19 @@
* Converts API mentions into our internal format.
* @see {@link https://docs.joinmastodon.org/entities/mention/}
*/
-import {
- Map as ImmutableMap,
- Record as ImmutableRecord,
-} from 'immutable';
+import { Record as ImmutableRecord } from 'immutable';
import { normalizeAccount } from 'soapbox/normalizers/account';
// https://docs.joinmastodon.org/entities/mention/
-const MentionRecord = ImmutableRecord({
+export const MentionRecord = ImmutableRecord({
id: '',
acct: '',
username: '',
url: '',
});
-export const normalizeMention = (mention: ImmutableMap) => {
+export const normalizeMention = (mention: Record) => {
// Simply normalize it as an account then cast it as a mention Β―\_(γ)_/Β―
return MentionRecord(normalizeAccount(mention));
};
diff --git a/app/soapbox/normalizers/notification.ts b/app/soapbox/normalizers/notification.ts
index e0f466618..defd51215 100644
--- a/app/soapbox/normalizers/notification.ts
+++ b/app/soapbox/normalizers/notification.ts
@@ -6,10 +6,11 @@
import {
Map as ImmutableMap,
Record as ImmutableRecord,
+ fromJS,
} from 'immutable';
// https://docs.joinmastodon.org/entities/notification/
-const NotificationRecord = ImmutableRecord({
+export const NotificationRecord = ImmutableRecord({
account: null,
chat_message: null, // pleroma:chat_mention
created_at: new Date(),
@@ -20,6 +21,8 @@ const NotificationRecord = ImmutableRecord({
type: '',
});
-export const normalizeNotification = (notification: ImmutableMap) => {
- return NotificationRecord(notification);
+export const normalizeNotification = (notification: Record) => {
+ return NotificationRecord(
+ ImmutableMap(fromJS(notification)),
+ );
};
diff --git a/app/soapbox/normalizers/poll.ts b/app/soapbox/normalizers/poll.ts
index fa127702e..592f9aa65 100644
--- a/app/soapbox/normalizers/poll.ts
+++ b/app/soapbox/normalizers/poll.ts
@@ -8,6 +8,7 @@ import {
Map as ImmutableMap,
List as ImmutableList,
Record as ImmutableRecord,
+ fromJS,
} from 'immutable';
import emojify from 'soapbox/features/emoji/emoji';
@@ -15,7 +16,7 @@ import { normalizeEmoji } from 'soapbox/normalizers/emoji';
import { makeEmojiMap } from 'soapbox/utils/normalizers';
// https://docs.joinmastodon.org/entities/poll/
-const PollRecord = ImmutableRecord({
+export const PollRecord = ImmutableRecord({
emojis: ImmutableList(),
expired: false,
expires_at: new Date(),
@@ -29,7 +30,7 @@ const PollRecord = ImmutableRecord({
});
// Sub-entity of Poll
-const PollOptionRecord = ImmutableRecord({
+export const PollOptionRecord = ImmutableRecord({
title: '',
votes_count: 0,
@@ -76,9 +77,9 @@ const normalizePollVoted = (poll: ImmutableMap) => {
});
};
-export const normalizePoll = (poll: ImmutableMap) => {
+export const normalizePoll = (poll: Record) => {
return PollRecord(
- poll.withMutations((poll: ImmutableMap) => {
+ ImmutableMap(fromJS(poll)).withMutations((poll: ImmutableMap) => {
normalizeEmojis(poll);
normalizePollOptions(poll);
normalizePollOwnVotes(poll);
diff --git a/app/soapbox/normalizers/status.ts b/app/soapbox/normalizers/status.ts
index 2a1039f45..8db44ba39 100644
--- a/app/soapbox/normalizers/status.ts
+++ b/app/soapbox/normalizers/status.ts
@@ -7,6 +7,7 @@ import {
Map as ImmutableMap,
List as ImmutableList,
Record as ImmutableRecord,
+ fromJS,
} from 'immutable';
import { normalizeAttachment } from 'soapbox/normalizers/attachment';
@@ -17,7 +18,7 @@ import { normalizePoll } from 'soapbox/normalizers/poll';
import { IStatus } from 'soapbox/types';
// https://docs.joinmastodon.org/entities/status/
-const StatusRecord = ImmutableRecord({
+export const StatusRecord = ImmutableRecord({
account: null,
application: null,
bookmarked: false,
@@ -135,9 +136,9 @@ const fixQuote = (status: ImmutableMap) => {
});
};
-export const normalizeStatus = (status: ImmutableMap): IStatus => {
+export const normalizeStatus = (status: Record): IStatus => {
return StatusRecord(
- status.withMutations(status => {
+ ImmutableMap(fromJS(status)).withMutations(status => {
normalizeAttachments(status);
normalizeMentions(status);
normalizeEmojis(status);
diff --git a/app/soapbox/reducers/__tests__/compose-test.js b/app/soapbox/reducers/__tests__/compose-test.js
index 348739a6b..454c787ca 100644
--- a/app/soapbox/reducers/__tests__/compose-test.js
+++ b/app/soapbox/reducers/__tests__/compose-test.js
@@ -1,10 +1,11 @@
-import { Map as ImmutableMap } from 'immutable';
+import { Map as ImmutableMap, fromJS } from 'immutable';
import * as actions from 'soapbox/actions/compose';
import { ME_FETCH_SUCCESS, ME_PATCH_SUCCESS } from 'soapbox/actions/me';
import { SETTING_CHANGE } from 'soapbox/actions/settings';
-//import { REDRAFT } from 'soapbox/actions/statuses';
+import { REDRAFT } from 'soapbox/actions/statuses';
import { TIMELINE_DELETE } from 'soapbox/actions/timelines';
+import { normalizeStatus } from 'soapbox/normalizers/status';
import reducer from '../compose';
@@ -38,6 +39,29 @@ describe('compose reducer', () => {
expect(state.get('idempotencyKey').length === 36);
});
+ describe('REDRAFT', () => {
+ it('strips Pleroma integer attachments', () => {
+ const action = {
+ type: REDRAFT,
+ status: normalizeStatus(fromJS(require('soapbox/__fixtures__/pleroma-status-deleted.json'))),
+ v: { software: 'Pleroma' },
+ };
+
+ const result = reducer(undefined, action);
+ expect(result.get('media_attachments').isEmpty()).toBe(true);
+ });
+
+ it('leaves non-Pleroma integer attachments alone', () => {
+ const action = {
+ type: REDRAFT,
+ status: normalizeStatus(fromJS(require('soapbox/__fixtures__/pleroma-status-deleted.json'))),
+ };
+
+ const result = reducer(undefined, action);
+ expect(result.getIn(['media_attachments', 0, 'id'])).toEqual('508107650');
+ });
+ });
+
it('uses \'public\' scope as default', () => {
const action = {
type: actions.COMPOSE_REPLY,
@@ -325,30 +349,6 @@ describe('compose reducer', () => {
});
});
- // it('should handle COMPOSE_UPLOAD_UNDO', () => {
- // const state = ImmutableMap({
- // media_attachments: ImmutableList([
- // description: null,
- // id: '1375732379',
- // pleroma: {
- // mime_type: 'image/jpeg'
- // },
- // preview_url: 'https://media.gleasonator.com/media_attachments/files/000/853/856/original/7035d67937053e1d.jpg',
- // remote_url: 'https://media.gleasonator.com/media_attachments/files/000/853/856/original/7035d67937053e1d.jpg',
- // text_url: 'https://media.gleasonator.com/media_attachments/files/000/853/856/original/7035d67937053e1d.jpg',
- // type: 'image',
- // url: 'https://media.gleasonator.com/media_attachments/files/000/853/856/original/7035d67937053e1d.jpg'
- // ]),
- // });
- // const action = {
- // type: actions.COMPOSE_UPLOAD_UNDO,
- // mediaId: '1375732379',
- // };
- // expect(reducer(state, action)).toEqual({
- // media_attachments: [],
- // });
- // });
-
it('should handle COMPOSE_UPLOAD_PROGRESS', () => {
const state = ImmutableMap({ progress: 0 });
const action = {
@@ -361,203 +361,6 @@ describe('compose reducer', () => {
});
});
- // it('should handle COMPOSE_MENTION', () => {
- // const state = ImmutableMap({});
- // const account = {
- // '9w1HhmenIAKBHJiUs4': {
- // header_static: 'https://media.gleasonator.com/accounts/headers/000/000/001/original/9d0e4dbf1c9dbc8f.png',
- // display_name_html: 'Alex Gleason',
- // bot: false,
- // display_name: 'Alex Gleason',
- // created_at: '2020-06-12T21:47:28.000Z',
- // locked: false,
- // emojis: [],
- // header: 'https://media.gleasonator.com/accounts/headers/000/000/001/original/9d0e4dbf1c9dbc8f.png',
- // url: 'https://gleasonator.com/users/alex',
- // note: 'Fediverse developer. I come in peace. #vegan #freeculture #atheist #antiporn #gendercritical. Boosts β endorsements.',
- // acct: 'alex@gleasonator.com',
- // avatar_static: 'https://media.gleasonator.com/accounts/avatars/000/000/001/original/1a630e4c4c64c948.jpg',
- // username: 'alex',
- // avatar: 'https://media.gleasonator.com/accounts/avatars/000/000/001/original/1a630e4c4c64c948.jpg',
- // fields: [
- // {
- // name: 'Website',
- // value: 'https://alexgleason.me',
- // name_emojified: 'Website',
- // value_emojified: 'https://alexgleason.me',
- // value_plain: 'https://alexgleason.me'
- // },
- // {
- // name: 'Pleroma+Soapbox',
- // value: 'https://soapbox.pub',
- // name_emojified: 'Pleroma+Soapbox',
- // value_emojified: 'https://soapbox.pub',
- // value_plain: 'https://soapbox.pub'
- // },
- // {
- // name: 'Email',
- // value: 'alex@alexgleason.me',
- // name_emojified: 'Email',
- // value_emojified: 'alex@alexgleason.me',
- // value_plain: 'alex@alexgleason.me'
- // },
- // {
- // name: 'Gender identity',
- // value: 'Soyboy',
- // name_emojified: 'Gender identity',
- // value_emojified: 'Soyboy',
- // value_plain: 'Soyboy'
- // }
- // ],
- // pleroma: {
- // hide_follows: false,
- // hide_followers_count: false,
- // background_image: null,
- // confirmation_pending: false,
- // is_moderator: false,
- // hide_follows_count: false,
- // hide_followers: false,
- // relationship: {
- // showing_reblogs: true,
- // followed_by: false,
- // subscribing: false,
- // blocked_by: false,
- // requested: false,
- // domain_blocking: false,
- // following: false,
- // endorsed: false,
- // blocking: false,
- // muting: false,
- // id: '9w1HhmenIAKBHJiUs4',
- // muting_notifications: false
- // },
- // tags: [],
- // hide_favorites: true,
- // is_admin: false,
- // skip_thread_containment: false
- // },
- // source: {
- // fields: [],
- // note: 'Fediverse developer. I come in peace. #vegan #freeculture #atheist #antiporn #gendercritical. Boosts β endorsements.',
- // pleroma: {
- // actor_type: 'Person',
- // discoverable: false
- // },
- // sensitive: false
- // },
- // id: '9w1HhmenIAKBHJiUs4',
- // note_emojified: 'Fediverse developer. I come in peace. #vegan #freeculture #atheist #antiporn #gendercritical. Boosts β endorsements.'
- // },
- // };
- // const action = {
- // type: actions.COMPOSE_MENTION,
- // account: account,
- // };
- // expect(reducer(state, action).toJS()).toMatchObject({
- // text: '@alex@gleasonator.com',
- // caretPosition: null,
- // });
- // });
-
- // it('should handle COMPOSE_DIRECT', () => {
- // const state = ImmutableMap({});
- // const account = {
- // '9w1HhmenIAKBHJiUs4': {
- // header_static: 'https://media.gleasonator.com/accounts/headers/000/000/001/original/9d0e4dbf1c9dbc8f.png',
- // display_name_html: 'Alex Gleason',
- // bot: false,
- // display_name: 'Alex Gleason',
- // created_at: '2020-06-12T21:47:28.000Z',
- // locked: false,
- // emojis: [],
- // header: 'https://media.gleasonator.com/accounts/headers/000/000/001/original/9d0e4dbf1c9dbc8f.png',
- // url: 'https://gleasonator.com/users/alex',
- // note: 'Fediverse developer. I come in peace. #vegan #freeculture #atheist #antiporn #gendercritical. Boosts β endorsements.',
- // acct: 'alex@gleasonator.com',
- // avatar_static: 'https://media.gleasonator.com/accounts/avatars/000/000/001/original/1a630e4c4c64c948.jpg',
- // username: 'alex',
- // avatar: 'https://media.gleasonator.com/accounts/avatars/000/000/001/original/1a630e4c4c64c948.jpg',
- // fields: [
- // {
- // name: 'Website',
- // value: 'https://alexgleason.me',
- // name_emojified: 'Website',
- // value_emojified: 'https://alexgleason.me',
- // value_plain: 'https://alexgleason.me'
- // },
- // {
- // name: 'Pleroma+Soapbox',
- // value: 'https://soapbox.pub',
- // name_emojified: 'Pleroma+Soapbox',
- // value_emojified: 'https://soapbox.pub',
- // value_plain: 'https://soapbox.pub'
- // },
- // {
- // name: 'Email',
- // value: 'alex@alexgleason.me',
- // name_emojified: 'Email',
- // value_emojified: 'alex@alexgleason.me',
- // value_plain: 'alex@alexgleason.me'
- // },
- // {
- // name: 'Gender identity',
- // value: 'Soyboy',
- // name_emojified: 'Gender identity',
- // value_emojified: 'Soyboy',
- // value_plain: 'Soyboy'
- // }
- // ],
- // pleroma: {
- // hide_follows: false,
- // hide_followers_count: false,
- // background_image: null,
- // confirmation_pending: false,
- // is_moderator: false,
- // hide_follows_count: false,
- // hide_followers: false,
- // relationship: {
- // showing_reblogs: true,
- // followed_by: false,
- // subscribing: false,
- // blocked_by: false,
- // requested: false,
- // domain_blocking: false,
- // following: false,
- // endorsed: false,
- // blocking: false,
- // muting: false,
- // id: '9w1HhmenIAKBHJiUs4',
- // muting_notifications: false
- // },
- // tags: [],
- // hide_favorites: true,
- // is_admin: false,
- // skip_thread_containment: false
- // },
- // source: {
- // fields: [],
- // note: 'Fediverse developer. I come in peace. #vegan #freeculture #atheist #antiporn #gendercritical. Boosts β endorsements.',
- // pleroma: {
- // actor_type: 'Person',
- // discoverable: false
- // },
- // sensitive: false
- // },
- // id: '9w1HhmenIAKBHJiUs4',
- // note_emojified: 'Fediverse developer. I come in peace. #vegan #freeculture #atheist #antiporn #gendercritical. Boosts β endorsements.'
- // }
- // };
- // const action = {
- // type: actions.COMPOSE_DIRECT,
- // account: account,
- // };
- // expect(reducer(state, action).toJS()).toMatchObject({
- // text: '@alex@gleasonator.com',
- // caretPosition: null,
- // privacy: 'direct',
- // });
- // });
- //
it('should handle COMPOSE_SUGGESTIONS_CLEAR', () => {
const state = ImmutableMap({ });
const action = {
@@ -570,28 +373,6 @@ describe('compose reducer', () => {
});
});
- // it('should handle COMPOSE_SUGGESTIONS_READY', () => {
- // const state = ImmutableMap({ default_privacy: 'public', privacy: 'public'});
- // const action = {
- // type: actions.COMPOSE_SUGGESTIONS_READY,
- // };
- // expect(reducer(state, action).toJS()).toMatchObject({
- // default_privacy: 'unlisted',
- // privacy: 'public',
- // });
- // });
- //
- // it('should handle COMPOSE_SUGGESTION_SELECT', () => {
- // const state = ImmutableMap({ default_privacy: 'public', privacy: 'public'});
- // const action = {
- // type: actions.COMPOSE_SUGGESTION_SELECT,
- // };
- // expect(reducer(state, action).toJS()).toMatchObject({
- // default_privacy: 'unlisted',
- // privacy: 'public',
- // });
- // });
- //
it('should handle COMPOSE_SUGGESTION_TAGS_UPDATE', () => {
const state = ImmutableMap({ tagHistory: [ 'hashtag' ] });
const action = {
@@ -627,42 +408,6 @@ describe('compose reducer', () => {
});
});
- // it('should handle COMPOSE_EMOJI_INSERT', () => {
- // const state = ImmutableMap({ text: 'this is my' });
- // const action = {
- // type: actions.COMPOSE_EMOJI_INSERT,
- // position: 11,
- // emoji: [],
- // needsSpace, true,
- // };
- // expect(reducer(state, action).toJS()).toMatchObject({
- // text: 'this is my :emoji:',
- // caretPosition: 15,
- // });
- // });
- //
- // it('should handle COMPOSE_UPLOAD_CHANGE_SUCCESS', () => {
- // const state = ImmutableMap({ default_privacy: 'public' });
- // const action = {
- // type: actions.COMPOSE_UPLOAD_CHANGE_SUCCESS,
- // };
- // expect(reducer(state, action).toJS()).toMatchObject({
- // default_privacy: 'unlisted',
- // privacy: 'public',
- // });
- // });
- //
- // it('should handle REDRAFT', () => {
- // const state = ImmutableMap({ default_privacy: 'public' });
- // const action = {
- // type: REDRAFT,
- // };
- // expect(reducer(state, action).toJS()).toMatchObject({
- // default_privacy: 'unlisted',
- // privacy: 'public',
- // });
- // });
- //
it('should handle COMPOSE_POLL_ADD', () => {
const state = ImmutableMap({ poll: null });
const initialPoll = Object({
@@ -691,34 +436,6 @@ describe('compose reducer', () => {
});
});
- // it('should handle COMPOSE_POLL_OPTION_ADD', () => {
- // const initialPoll = Object({
- // options: [
- // 'option 1',
- // 'option 2',
- // ],
- // expires_in: 86400,
- // multiple: false
- // });
- // const state = ImmutableMap({ poll: initialPoll });
- // const action = {
- // type: actions.COMPOSE_POLL_OPTION_ADD,
- // title: 'option 3',
- // };
- // const updatedPoll = Object({
- // options: [
- // 'option 1',
- // 'option 2',
- // 'option 3',
- // ],
- // expires_in: 86400,
- // multiple: false,
- // });
- // expect(reducer(state, action).toJS()).toMatchObject({
- // poll: updatedPoll,
- // });
- // });
-
it('should handle COMPOSE_POLL_OPTION_CHANGE', () => {
const initialPoll = Object({
options: [
@@ -747,32 +464,6 @@ describe('compose reducer', () => {
});
});
- // it('should handle COMPOSE_POLL_OPTION_REMOVE', () => {
- // const initialPoll = Object({
- // options: [
- // 'option 1',
- // 'option 2',
- // ],
- // expires_in: 86400,
- // multiple: false,
- // });
- // const state = ImmutableMap({ poll: initialPoll });
- // const action = {
- // type: actions.COMPOSE_POLL_OPTION_REMOVE,
- // index: 1,
- // };
- // const updatedPoll = Object({
- // options: [
- // 'option 1',
- // ],
- // expires_in: 86400,
- // multiple: false,
- // });
- // expect(reducer(state, action).toJS()).toMatchObject({
- // poll: updatedPoll,
- // });
- // });
-
it('sets the post content-type', () => {
const action = {
type: actions.COMPOSE_TYPE_CHANGE,
diff --git a/app/soapbox/reducers/__tests__/notifications-test.js b/app/soapbox/reducers/__tests__/notifications-test.js
index 630aa61e3..aa5b7cd62 100644
--- a/app/soapbox/reducers/__tests__/notifications-test.js
+++ b/app/soapbox/reducers/__tests__/notifications-test.js
@@ -93,6 +93,22 @@ describe('notifications reducer', () => {
expect(result.items.size).toEqual(1);
expect(result.items.get('4').id).toEqual('4');
});
+
+ it('imports move notification', () => {
+ const action = {
+ type: NOTIFICATIONS_EXPAND_SUCCESS,
+ notifications: [
+ require('soapbox/__fixtures__/pleroma-notification-move.json'),
+ ],
+ next: null,
+ skipLoading: true,
+ };
+
+ const result = reducer(undefined, action).items.get('406814');
+
+ expect(result.account).toEqual('AFmHQ18XZ7Lco68MW8');
+ expect(result.target).toEqual('A5c5LK7EJTFR0u26Pg');
+ });
});
describe('NOTIFICATIONS_EXPAND_REQUEST', () => {
diff --git a/app/soapbox/reducers/accounts.js b/app/soapbox/reducers/accounts.js
index c601ed928..de7926feb 100644
--- a/app/soapbox/reducers/accounts.js
+++ b/app/soapbox/reducers/accounts.js
@@ -46,7 +46,7 @@ const minifyAccount = account => {
};
const fixAccount = (state, account) => {
- const normalized = minifyAccount(normalizeAccount(fromJS(account)));
+ const normalized = minifyAccount(normalizeAccount(account));
return state.set(account.id, normalized);
};
@@ -119,7 +119,7 @@ const removePermission = (state, accountIds, permissionGroup) => {
});
};
-const buildAccount = adminUser => normalizeAccount(fromJS({
+const buildAccount = adminUser => normalizeAccount({
id: adminUser.get('id'),
username: adminUser.get('nickname').split('@')[0],
acct: adminUser.get('nickname'),
@@ -142,7 +142,7 @@ const buildAccount = adminUser => normalizeAccount(fromJS({
},
},
should_refetch: true,
-}));
+});
const mergeAdminUser = (account, adminUser) => {
return account.withMutations(account => {
diff --git a/app/soapbox/reducers/compose.js b/app/soapbox/reducers/compose.js
index 2690b6637..43fd23154 100644
--- a/app/soapbox/reducers/compose.js
+++ b/app/soapbox/reducers/compose.js
@@ -1,6 +1,8 @@
import { Map as ImmutableMap, List as ImmutableList, OrderedSet as ImmutableOrderedSet, fromJS } from 'immutable';
import { tagHistory } from 'soapbox/settings';
+import { PLEROMA } from 'soapbox/utils/features';
+import { hasIntegerMediaIds } from 'soapbox/utils/status';
import {
COMPOSE_MOUNT,
@@ -431,13 +433,17 @@ export default function compose(state = initialState, action) {
map.set('to', action.explicitAddressing ? getExplicitMentions(action.status.get('account', 'id'), action.status) : undefined);
map.set('in_reply_to', action.status.get('in_reply_to_id'));
map.set('privacy', action.status.get('visibility'));
- // TODO: Actually fix this rather than just removing it
- // map.set('media_attachments', action.status.get('media_attachments'));
map.set('focusDate', new Date());
map.set('caretPosition', null);
map.set('idempotencyKey', uuid());
map.set('content_type', action.content_type || 'text/plain');
+ if (action.v?.software === PLEROMA && hasIntegerMediaIds(action.status)) {
+ map.set('media_attachments', ImmutableList());
+ } else {
+ map.set('media_attachments', action.status.get('media_attachments'));
+ }
+
if (action.status.get('spoiler_text').length > 0) {
map.set('spoiler', true);
map.set('spoiler_text', action.status.get('spoiler_text'));
diff --git a/app/soapbox/reducers/index.ts b/app/soapbox/reducers/index.ts
index 3c61591e3..d63400d27 100644
--- a/app/soapbox/reducers/index.ts
+++ b/app/soapbox/reducers/index.ts
@@ -116,7 +116,7 @@ const reducers = {
};
// Build a default state from all reducers: it has the key and `undefined`
-const StateRecord = ImmutableRecord(
+export const StateRecord = ImmutableRecord(
Object.keys(reducers).reduce((params: Record, reducer) => {
params[reducer] = undefined;
return params;
diff --git a/app/soapbox/reducers/notifications.js b/app/soapbox/reducers/notifications.js
index 02ffa58e9..fad2563c3 100644
--- a/app/soapbox/reducers/notifications.js
+++ b/app/soapbox/reducers/notifications.js
@@ -56,6 +56,7 @@ const comparator = (a, b) => {
const minifyNotification = notification => {
return notification.mergeWith((o, n) => n || o, {
account: notification.getIn(['account', 'id']),
+ target: notification.getIn(['target', 'id']),
status: notification.getIn(['status', 'id']),
});
};
diff --git a/app/soapbox/reducers/polls.js b/app/soapbox/reducers/polls.js
index f1a06fdc1..f9f220edc 100644
--- a/app/soapbox/reducers/polls.js
+++ b/app/soapbox/reducers/polls.js
@@ -1,4 +1,4 @@
-import { Map as ImmutableMap, fromJS } from 'immutable';
+import { Map as ImmutableMap } from 'immutable';
import { POLLS_IMPORT } from 'soapbox/actions/importer';
import { normalizeStatus } from 'soapbox/normalizers/status';
@@ -6,7 +6,7 @@ import { normalizeStatus } from 'soapbox/normalizers/status';
// HOTFIX: Convert the poll into a fake status to normalize it...
// TODO: get rid of POLLS_IMPORT and use STATUS_IMPORT here.
const normalizePoll = poll => {
- const status = fromJS({ poll });
+ const status = { poll };
return normalizeStatus(status).poll;
};
diff --git a/app/soapbox/test_helpers.js b/app/soapbox/test_helpers.js
index c9de38dc4..90f41119e 100644
--- a/app/soapbox/test_helpers.js
+++ b/app/soapbox/test_helpers.js
@@ -11,6 +11,9 @@ import thunk from 'redux-thunk';
import rootReducer from 'soapbox/reducers';
+export const rootState = rootReducer(undefined, {});
+export const getState = () => rootState;
+
// Mock Redux
// https://redux.js.org/recipes/writing-tests/
const middlewares = [thunk];
@@ -20,7 +23,7 @@ export const mockStore = configureMockStore(middlewares);
export const createComponent = (children, props = {}) => {
props = ImmutableMap({
locale: 'en',
- store: mockStore(rootReducer(ImmutableMap(), {})),
+ store: mockStore(rootState),
}).merge(props);
return renderer.create(
diff --git a/app/soapbox/utils/__tests__/numbers-test.js b/app/soapbox/utils/__tests__/numbers-test.js
new file mode 100644
index 000000000..86923a781
--- /dev/null
+++ b/app/soapbox/utils/__tests__/numbers-test.js
@@ -0,0 +1,13 @@
+import { isIntegerId } from '../numbers';
+
+test('isIntegerId()', () => {
+ expect(isIntegerId('0')).toBe(true);
+ expect(isIntegerId('1')).toBe(true);
+ expect(isIntegerId('508107650')).toBe(true);
+ expect(isIntegerId('-1764036199')).toBe(true);
+ expect(isIntegerId('106801667066418367')).toBe(true);
+ expect(isIntegerId('9v5bmRalQvjOy0ECcC')).toBe(false);
+ expect(isIntegerId(null)).toBe(false);
+ expect(isIntegerId(undefined)).toBe(false);
+ expect(isIntegerId()).toBe(false);
+});
diff --git a/app/soapbox/utils/__tests__/status-test.js b/app/soapbox/utils/__tests__/status-test.js
new file mode 100644
index 000000000..0dcb3e78a
--- /dev/null
+++ b/app/soapbox/utils/__tests__/status-test.js
@@ -0,0 +1,12 @@
+import { fromJS } from 'immutable';
+
+import { normalizeStatus } from 'soapbox/normalizers/status';
+
+import { hasIntegerMediaIds } from '../status';
+
+describe('hasIntegerMediaIds()', () => {
+ it('returns true for a Pleroma deleted status', () => {
+ const status = normalizeStatus(fromJS(require('soapbox/__fixtures__/pleroma-status-deleted.json')));
+ expect(hasIntegerMediaIds(status)).toBe(true);
+ });
+});
diff --git a/app/soapbox/utils/accounts.ts b/app/soapbox/utils/accounts.ts
index e93138c86..a97f76338 100644
--- a/app/soapbox/utils/accounts.ts
+++ b/app/soapbox/utils/accounts.ts
@@ -10,14 +10,14 @@ const getDomainFromURL = (account: ImmutableMap): string => {
};
export const getDomain = (account: ImmutableMap): string => {
- const domain = account.get('acct').split('@')[1];
+ const domain = account.get('acct', '').split('@')[1];
return domain ? domain : getDomainFromURL(account);
};
export const guessFqn = (account: ImmutableMap): string => {
- const [user, domain] = account.get('acct').split('@');
+ const [user, domain] = account.get('acct', '').split('@');
if (!domain) return [user, getDomainFromURL(account)].join('@');
- return account.get('acct');
+ return account.get('acct', '');
};
export const getBaseURL = (account: ImmutableMap): string => {
@@ -31,7 +31,7 @@ export const getBaseURL = (account: ImmutableMap): string => {
// user@domain even for local users
export const acctFull = (account: ImmutableMap): string => (
- account.get('fqn') || guessFqn(account)
+ account.get('fqn') || guessFqn(account) || ''
);
export const getAcct = (account: ImmutableMap, displayFqn: boolean): string => (
diff --git a/app/soapbox/utils/numbers.js b/app/soapbox/utils/numbers.js
index 8191692b3..18f4d5019 100644
--- a/app/soapbox/utils/numbers.js
+++ b/app/soapbox/utils/numbers.js
@@ -12,3 +12,5 @@ export const shortNumberFormat = number => {
return K;
}
};
+
+export const isIntegerId = id => new RegExp(/^-?[0-9]+$/g).test(id);
diff --git a/app/soapbox/utils/status.js b/app/soapbox/utils/status.js
index 48554ced9..acd69dc5e 100644
--- a/app/soapbox/utils/status.js
+++ b/app/soapbox/utils/status.js
@@ -1,3 +1,5 @@
+import { isIntegerId } from 'soapbox/utils/numbers';
+
export const getFirstExternalLink = status => {
try {
// Pulled from Pleroma's media parser
@@ -13,3 +15,8 @@ export const getFirstExternalLink = status => {
export const shouldHaveCard = status => {
return Boolean(getFirstExternalLink(status));
};
+
+// https://gitlab.com/soapbox-pub/soapbox-fe/-/merge_requests/1087
+export const hasIntegerMediaIds = status => {
+ return status.media_attachments.some(({ id }) => isIntegerId(id));
+};
diff --git a/app/styles/chats.scss b/app/styles/chats.scss
index 418d0eca8..6060e882f 100644
--- a/app/styles/chats.scss
+++ b/app/styles/chats.scss
@@ -487,6 +487,7 @@
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
+ max-height: 19px;
a {
color: var(--highlight-text-color);
diff --git a/package.json b/package.json
index da68d8759..6d8353b28 100644
--- a/package.json
+++ b/package.json
@@ -158,7 +158,6 @@
"substring-trie": "^1.0.2",
"terser-webpack-plugin": "^5.2.3",
"tiny-queue": "^0.2.1",
- "ts-jest": "^27.0.5",
"ts-loader": "^9.2.6",
"tslib": "^2.3.1",
"twemoji": "https://github.com/twitter/twemoji#v13.0.2",
@@ -173,6 +172,9 @@
"wicg-inert": "^3.1.1"
},
"devDependencies": {
+ "@jest/globals": "^27.5.1",
+ "@typescript-eslint/eslint-plugin": "^5.15.0",
+ "@typescript-eslint/parser": "^5.15.0",
"axios-mock-adapter": "^1.18.1",
"babel-eslint": "^10.1.0",
"babel-jest": "^27.1.0",
@@ -194,6 +196,7 @@
"stylelint": "^13.7.2",
"stylelint-config-standard": "^22.0.0",
"stylelint-scss": "^3.18.0",
+ "ts-jest": "^27.0.5",
"webpack-dev-server": "^4.1.0",
"yargs": "^16.0.3"
}
diff --git a/soapbox-screenshot.png b/soapbox-screenshot.png
index 4b3f82cbf..19c19e2c4 100644
Binary files a/soapbox-screenshot.png and b/soapbox-screenshot.png differ
diff --git a/tsconfig.json b/tsconfig.json
index b40a14711..fa80d5507 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -12,5 +12,5 @@
"allowSyntheticDefaultImports": true,
"typeRoots": [ "./types", "./node_modules/@types"]
},
- "exclude": ["node_modules", "types"]
+ "exclude": ["node_modules", "types", "**/*.test.*", "**/__mocks__/*", "**/__tests__/*"]
}
diff --git a/yarn.lock b/yarn.lock
index 01f6d2fab..e9ff6a500 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1453,6 +1453,16 @@
"@types/node" "*"
jest-mock "^27.1.1"
+"@jest/environment@^27.5.1":
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-27.5.1.tgz#d7425820511fe7158abbecc010140c3fd3be9c74"
+ integrity sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA==
+ dependencies:
+ "@jest/fake-timers" "^27.5.1"
+ "@jest/types" "^27.5.1"
+ "@types/node" "*"
+ jest-mock "^27.5.1"
+
"@jest/fake-timers@^27.2.0":
version "27.2.0"
resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-27.2.0.tgz#560841bc21ae7fbeff0cbff8de8f5cf43ad3561d"
@@ -1465,6 +1475,18 @@
jest-mock "^27.1.1"
jest-util "^27.2.0"
+"@jest/fake-timers@^27.5.1":
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-27.5.1.tgz#76979745ce0579c8a94a4678af7a748eda8ada74"
+ integrity sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ==
+ dependencies:
+ "@jest/types" "^27.5.1"
+ "@sinonjs/fake-timers" "^8.0.1"
+ "@types/node" "*"
+ jest-message-util "^27.5.1"
+ jest-mock "^27.5.1"
+ jest-util "^27.5.1"
+
"@jest/globals@^27.2.0":
version "27.2.0"
resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-27.2.0.tgz#4d7085f51df5ac70c8240eb3501289676503933d"
@@ -1474,6 +1496,15 @@
"@jest/types" "^27.1.1"
expect "^27.2.0"
+"@jest/globals@^27.5.1":
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-27.5.1.tgz#7ac06ce57ab966566c7963431cef458434601b2b"
+ integrity sha512-ZEJNB41OBQQgGzgyInAv0UUfDDj3upmHydjieSxFvTRuZElrx7tXg/uVQ5hYVEwiXs3+aMsAeEc9X7xiSKCm4Q==
+ dependencies:
+ "@jest/environment" "^27.5.1"
+ "@jest/types" "^27.5.1"
+ expect "^27.5.1"
+
"@jest/reporters@^27.2.0":
version "27.2.0"
resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-27.2.0.tgz#629886d9a42218e504a424889a293abb27919e25"
@@ -1565,6 +1596,17 @@
"@types/yargs" "^16.0.0"
chalk "^4.0.0"
+"@jest/types@^27.5.1":
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/@jest/types/-/types-27.5.1.tgz#3c79ec4a8ba61c170bf937bcf9e98a9df175ec80"
+ integrity sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==
+ dependencies:
+ "@types/istanbul-lib-coverage" "^2.0.0"
+ "@types/istanbul-reports" "^3.0.0"
+ "@types/node" "*"
+ "@types/yargs" "^16.0.0"
+ chalk "^4.0.0"
+
"@lcdp/offline-plugin@^5.1.0":
version "5.1.0"
resolved "https://registry.yarnpkg.com/@lcdp/offline-plugin/-/offline-plugin-5.1.0.tgz#826f3e10d618711bd002afd674edb36dc1d9a792"
@@ -1703,6 +1745,13 @@
dependencies:
"@sinonjs/commons" "^1.7.0"
+"@sinonjs/fake-timers@^8.0.1":
+ version "8.1.0"
+ resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-8.1.0.tgz#3fdc2b6cb58935b21bfb8d1625eb1300484316e7"
+ integrity sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg==
+ dependencies:
+ "@sinonjs/commons" "^1.7.0"
+
"@stylelint/postcss-css-in-js@^0.37.2":
version "0.37.2"
resolved "https://registry.yarnpkg.com/@stylelint/postcss-css-in-js/-/postcss-css-in-js-0.37.2.tgz#7e5a84ad181f4234a2480803422a47b8749af3d2"
@@ -1852,6 +1901,11 @@
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d"
integrity sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==
+"@types/json-schema@^7.0.9":
+ version "7.0.10"
+ resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.10.tgz#9b05b7896166cd00e9cbd59864853abf65d9ac23"
+ integrity sha512-BLO9bBq59vW3fxCpD4o0N4U+DXsvwvIcl+jofw0frQo/GrBFC+/jRZj1E7kgp6dvTyNmA4y6JCV5Id/r3mNP5A==
+
"@types/json5@^0.0.29":
version "0.0.29"
resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
@@ -1962,6 +2016,86 @@
dependencies:
"@types/yargs-parser" "*"
+"@typescript-eslint/eslint-plugin@^5.15.0":
+ version "5.15.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.15.0.tgz#c28ef7f2e688066db0b6a9d95fb74185c114fb9a"
+ integrity sha512-u6Db5JfF0Esn3tiAKELvoU5TpXVSkOpZ78cEGn/wXtT2RVqs2vkt4ge6N8cRCyw7YVKhmmLDbwI2pg92mlv7cA==
+ dependencies:
+ "@typescript-eslint/scope-manager" "5.15.0"
+ "@typescript-eslint/type-utils" "5.15.0"
+ "@typescript-eslint/utils" "5.15.0"
+ debug "^4.3.2"
+ functional-red-black-tree "^1.0.1"
+ ignore "^5.1.8"
+ regexpp "^3.2.0"
+ semver "^7.3.5"
+ tsutils "^3.21.0"
+
+"@typescript-eslint/parser@^5.15.0":
+ version "5.15.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.15.0.tgz#95f603f8fe6eca7952a99bfeef9b85992972e728"
+ integrity sha512-NGAYP/+RDM2sVfmKiKOCgJYPstAO40vPAgACoWPO/+yoYKSgAXIFaBKsV8P0Cc7fwKgvj27SjRNX4L7f4/jCKQ==
+ dependencies:
+ "@typescript-eslint/scope-manager" "5.15.0"
+ "@typescript-eslint/types" "5.15.0"
+ "@typescript-eslint/typescript-estree" "5.15.0"
+ debug "^4.3.2"
+
+"@typescript-eslint/scope-manager@5.15.0":
+ version "5.15.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.15.0.tgz#d97afab5e0abf4018d1289bd711be21676cdd0ee"
+ integrity sha512-EFiZcSKrHh4kWk0pZaa+YNJosvKE50EnmN4IfgjkA3bTHElPtYcd2U37QQkNTqwMCS7LXeDeZzEqnsOH8chjSg==
+ dependencies:
+ "@typescript-eslint/types" "5.15.0"
+ "@typescript-eslint/visitor-keys" "5.15.0"
+
+"@typescript-eslint/type-utils@5.15.0":
+ version "5.15.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.15.0.tgz#d2c02eb2bdf54d0a645ba3a173ceda78346cf248"
+ integrity sha512-KGeDoEQ7gHieLydujGEFLyLofipe9PIzfvA/41urz4hv+xVxPEbmMQonKSynZ0Ks2xDhJQ4VYjB3DnRiywvKDA==
+ dependencies:
+ "@typescript-eslint/utils" "5.15.0"
+ debug "^4.3.2"
+ tsutils "^3.21.0"
+
+"@typescript-eslint/types@5.15.0":
+ version "5.15.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.15.0.tgz#c7bdd103843b1abae97b5518219d3e2a0d79a501"
+ integrity sha512-yEiTN4MDy23vvsIksrShjNwQl2vl6kJeG9YkVJXjXZnkJElzVK8nfPsWKYxcsGWG8GhurYXP4/KGj3aZAxbeOA==
+
+"@typescript-eslint/typescript-estree@5.15.0":
+ version "5.15.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.15.0.tgz#81513a742a9c657587ad1ddbca88e76c6efb0aac"
+ integrity sha512-Hb0e3dGc35b75xLzixM3cSbG1sSbrTBQDfIScqdyvrfJZVEi4XWAT+UL/HMxEdrJNB8Yk28SKxPLtAhfCbBInA==
+ dependencies:
+ "@typescript-eslint/types" "5.15.0"
+ "@typescript-eslint/visitor-keys" "5.15.0"
+ debug "^4.3.2"
+ globby "^11.0.4"
+ is-glob "^4.0.3"
+ semver "^7.3.5"
+ tsutils "^3.21.0"
+
+"@typescript-eslint/utils@5.15.0":
+ version "5.15.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.15.0.tgz#468510a0974d3ced8342f37e6c662778c277f136"
+ integrity sha512-081rWu2IPKOgTOhHUk/QfxuFog8m4wxW43sXNOMSCdh578tGJ1PAaWPsj42LOa7pguh173tNlMigsbrHvh/mtA==
+ dependencies:
+ "@types/json-schema" "^7.0.9"
+ "@typescript-eslint/scope-manager" "5.15.0"
+ "@typescript-eslint/types" "5.15.0"
+ "@typescript-eslint/typescript-estree" "5.15.0"
+ eslint-scope "^5.1.1"
+ eslint-utils "^3.0.0"
+
+"@typescript-eslint/visitor-keys@5.15.0":
+ version "5.15.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.15.0.tgz#5669739fbf516df060f978be6a6dce75855a8027"
+ integrity sha512-+vX5FKtgvyHbmIJdxMJ2jKm9z2BIlXJiuewI8dsDYMp5LzPUcuTT78Ya5iwvQg3VqSVdmxyM8Anj1Jeq7733ZQ==
+ dependencies:
+ "@typescript-eslint/types" "5.15.0"
+ eslint-visitor-keys "^3.0.0"
+
"@webassemblyjs/ast@1.11.1":
version "1.11.1"
resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.1.tgz#2bfd767eae1a6996f432ff7e8d7fc75679c0b6a7"
@@ -2243,7 +2377,7 @@ ansi-regex@^2.0.0:
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8=
-ansi-regex@^5.0.0:
+ansi-regex@^5.0.0, ansi-regex@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304"
integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==
@@ -2866,9 +3000,9 @@ caniuse-api@^3.0.0:
lodash.uniq "^4.5.0"
caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001252, caniuse-lite@^1.0.30001254:
- version "1.0.30001257"
- resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001257.tgz#150aaf649a48bee531104cfeda57f92ce587f6e5"
- integrity sha512-JN49KplOgHSXpIsVSF+LUyhD8PUp6xPpAXeRrrcBh4KBeP7W864jHn6RvzJgDlrReyeVjMFJL3PLpPvKIxlIHA==
+ version "1.0.30001317"
+ resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001317.tgz"
+ integrity sha512-xIZLh8gBm4dqNX0gkzrBeyI86J2eCjWzYAs40q88smG844YIrN4tVQl/RhquHvKEKImWWFIVh1Lxe5n1G/N+GQ==
catharsis@^0.9.0:
version "0.9.0"
@@ -2989,6 +3123,11 @@ ci-info@^3.1.1:
resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.2.0.tgz#2876cb948a498797b5236f0095bc057d0dca38b6"
integrity sha512-dVqRX7fLUm8J6FgHJ418XuIgDLZDkYcDFTeL6TA2gt5WlIZUQrrH6EZrNClwT/H0FateUsZkGIOPRrLbP+PR9A==
+ci-info@^3.2.0:
+ version "3.3.0"
+ resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.3.0.tgz#b4ed1fb6818dea4803a55c623041f9165d2066b2"
+ integrity sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw==
+
cjs-module-lexer@^1.0.0:
version "1.2.2"
resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz#9f84ba3244a512f3a54e5277e8eef4c489864e40"
@@ -3556,6 +3695,13 @@ debug@^3.1.1, debug@^3.2.7:
dependencies:
ms "^2.1.1"
+debug@^4.3.2:
+ version "4.3.4"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
+ integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
+ dependencies:
+ ms "2.1.2"
+
decamelize-keys@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.0.tgz#d171a87933252807eb3cb61dc1c1445d078df2d9"
@@ -3681,6 +3827,11 @@ diff-sequences@^27.0.6:
resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-27.0.6.tgz#3305cb2e55a033924054695cc66019fd7f8e5723"
integrity sha512-ag6wfpBFyNXZ0p8pcuIDS//D8H062ZQJ3fzYxjpmeKjnz8W4pekL3AI8VohmyZmsWW2PWaHgjsmqR6L13101VQ==
+diff-sequences@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-27.5.1.tgz#eaecc0d327fd68c8d9672a1e64ab8dccb2ef5327"
+ integrity sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==
+
dir-glob@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f"
@@ -4237,6 +4388,13 @@ eslint-utils@^2.1.0:
dependencies:
eslint-visitor-keys "^1.1.0"
+eslint-utils@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-3.0.0.tgz#8aebaface7345bb33559db0a1f13a1d2d48c3672"
+ integrity sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==
+ dependencies:
+ eslint-visitor-keys "^2.0.0"
+
eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e"
@@ -4247,6 +4405,11 @@ eslint-visitor-keys@^2.0.0:
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303"
integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==
+eslint-visitor-keys@^3.0.0:
+ version "3.3.0"
+ resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826"
+ integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==
+
eslint@^7.0.0:
version "7.32.0"
resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.32.0.tgz#c6d328a14be3fb08c8d1d21e12c02fdb7a2a812d"
@@ -4405,6 +4568,16 @@ expect@^27.2.0:
jest-message-util "^27.2.0"
jest-regex-util "^27.0.6"
+expect@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/expect/-/expect-27.5.1.tgz#83ce59f1e5bdf5f9d2b94b61d2050db48f3fef74"
+ integrity sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw==
+ dependencies:
+ "@jest/types" "^27.5.1"
+ jest-get-type "^27.5.1"
+ jest-matcher-utils "^27.5.1"
+ jest-message-util "^27.5.1"
+
express@^4.17.1:
version "4.17.1"
resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134"
@@ -4469,6 +4642,17 @@ fast-glob@^3.1.1, fast-glob@^3.2.5:
merge2 "^1.3.0"
micromatch "^4.0.4"
+fast-glob@^3.2.9:
+ version "3.2.11"
+ resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.11.tgz#a1172ad95ceb8a16e20caa5c5e56480e5129c1d9"
+ integrity sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==
+ dependencies:
+ "@nodelib/fs.stat" "^2.0.2"
+ "@nodelib/fs.walk" "^1.2.3"
+ glob-parent "^5.1.2"
+ merge2 "^1.3.0"
+ micromatch "^4.0.4"
+
fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633"
@@ -4819,6 +5003,18 @@ globby@^11.0.1, globby@^11.0.3:
merge2 "^1.3.0"
slash "^3.0.0"
+globby@^11.0.4:
+ version "11.1.0"
+ resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b"
+ integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==
+ dependencies:
+ array-union "^2.1.0"
+ dir-glob "^3.0.1"
+ fast-glob "^3.2.9"
+ ignore "^5.2.0"
+ merge2 "^1.4.1"
+ slash "^3.0.0"
+
globjoin@^0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/globjoin/-/globjoin-0.1.4.tgz#2f4494ac8919e3767c5cbb691e9f463324285d43"
@@ -4836,6 +5032,11 @@ graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0,
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.8.tgz#e412b8d33f5e006593cbd3cee6df9f2cebbe802a"
integrity sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==
+graceful-fs@^4.2.9:
+ version "4.2.9"
+ resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.9.tgz#041b05df45755e587a24942279b9d113146e1c96"
+ integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==
+
gzip-size@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-6.0.0.tgz#065367fd50c239c0671cbcbad5be3e2eeb10e462"
@@ -5162,6 +5363,11 @@ ignore@^5.1.4, ignore@^5.1.8:
resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57"
integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==
+ignore@^5.2.0:
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a"
+ integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==
+
immediate@~3.0.5:
version "3.0.6"
resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b"
@@ -5832,6 +6038,16 @@ jest-diff@^27.2.0:
jest-get-type "^27.0.6"
pretty-format "^27.2.0"
+jest-diff@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-27.5.1.tgz#a07f5011ac9e6643cf8a95a462b7b1ecf6680def"
+ integrity sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==
+ dependencies:
+ chalk "^4.0.0"
+ diff-sequences "^27.5.1"
+ jest-get-type "^27.5.1"
+ pretty-format "^27.5.1"
+
jest-docblock@^27.0.6:
version "27.0.6"
resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-27.0.6.tgz#cc78266acf7fe693ca462cbbda0ea4e639e4e5f3"
@@ -5880,6 +6096,11 @@ jest-get-type@^27.0.6:
resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-27.0.6.tgz#0eb5c7f755854279ce9b68a9f1a4122f69047cfe"
integrity sha512-XTkK5exIeUbbveehcSR8w0bhH+c0yloW/Wpl+9vZrjzztCPWrxhHwkIFpZzCt71oRBsgxmuUfxEqOYoZI2macg==
+jest-get-type@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-27.5.1.tgz#3cd613c507b0f7ace013df407a1c1cd578bcb4f1"
+ integrity sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==
+
jest-haste-map@^27.2.0:
version "27.2.0"
resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-27.2.0.tgz#703b3a473e3f2e27d75ab07864ffd7bbaad0d75e"
@@ -5942,6 +6163,16 @@ jest-matcher-utils@^27.2.0:
jest-get-type "^27.0.6"
pretty-format "^27.2.0"
+jest-matcher-utils@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz#9c0cdbda8245bc22d2331729d1091308b40cf8ab"
+ integrity sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==
+ dependencies:
+ chalk "^4.0.0"
+ jest-diff "^27.5.1"
+ jest-get-type "^27.5.1"
+ pretty-format "^27.5.1"
+
jest-message-util@^27.2.0:
version "27.2.0"
resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-27.2.0.tgz#2f65c71df55267208686b1d7514e18106c91ceaf"
@@ -5957,6 +6188,21 @@ jest-message-util@^27.2.0:
slash "^3.0.0"
stack-utils "^2.0.3"
+jest-message-util@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-27.5.1.tgz#bdda72806da10d9ed6425e12afff38cd1458b6cf"
+ integrity sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==
+ dependencies:
+ "@babel/code-frame" "^7.12.13"
+ "@jest/types" "^27.5.1"
+ "@types/stack-utils" "^2.0.0"
+ chalk "^4.0.0"
+ graceful-fs "^4.2.9"
+ micromatch "^4.0.4"
+ pretty-format "^27.5.1"
+ slash "^3.0.0"
+ stack-utils "^2.0.3"
+
jest-mock@^27.1.1:
version "27.1.1"
resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-27.1.1.tgz#c7a2e81301fdcf3dab114931d23d89ec9d0c3a82"
@@ -5965,6 +6211,14 @@ jest-mock@^27.1.1:
"@jest/types" "^27.1.1"
"@types/node" "*"
+jest-mock@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-27.5.1.tgz#19948336d49ef4d9c52021d34ac7b5f36ff967d6"
+ integrity sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og==
+ dependencies:
+ "@jest/types" "^27.5.1"
+ "@types/node" "*"
+
jest-pnp-resolver@^1.2.2:
version "1.2.2"
resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz#b704ac0ae028a89108a4d040b3f919dfddc8e33c"
@@ -6116,6 +6370,18 @@ jest-util@^27.0.0, jest-util@^27.2.0:
is-ci "^3.0.0"
picomatch "^2.2.3"
+jest-util@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-27.5.1.tgz#3ba9771e8e31a0b85da48fe0b0891fb86c01c2f9"
+ integrity sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==
+ dependencies:
+ "@jest/types" "^27.5.1"
+ "@types/node" "*"
+ chalk "^4.0.0"
+ ci-info "^3.2.0"
+ graceful-fs "^4.2.9"
+ picomatch "^2.2.3"
+
jest-validate@^27.2.0:
version "27.2.0"
resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-27.2.0.tgz#b7535f12d95dd3b4382831f4047384ca098642ab"
@@ -6804,7 +7070,7 @@ merge-stream@^2.0.0:
resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60"
integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==
-merge2@^1.3.0:
+merge2@^1.3.0, merge2@^1.4.1:
version "1.4.1"
resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae"
integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==
@@ -7933,6 +8199,15 @@ pretty-format@^27.2.0:
ansi-styles "^5.0.0"
react-is "^17.0.1"
+pretty-format@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.5.1.tgz#2181879fdea51a7a5851fb39d920faa63f01d88e"
+ integrity sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==
+ dependencies:
+ ansi-regex "^5.0.1"
+ ansi-styles "^5.0.0"
+ react-is "^17.0.1"
+
process-nextick-args@~2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
@@ -8553,7 +8828,7 @@ regexp.prototype.flags@^1.2.0, regexp.prototype.flags@^1.3.1:
call-bind "^1.0.2"
define-properties "^1.1.3"
-regexpp@^3.1.0:
+regexpp@^3.1.0, regexpp@^3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2"
integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==
@@ -9714,7 +9989,7 @@ tsconfig-paths@^3.12.0:
minimist "^1.2.0"
strip-bom "^3.0.0"
-tslib@^1.9.0, tslib@^1.9.3:
+tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3:
version "1.14.1"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
@@ -9724,6 +9999,13 @@ tslib@^2.0.1, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.2.0, tslib@^2.3.1:
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01"
integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==
+tsutils@^3.21.0:
+ version "3.21.0"
+ resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623"
+ integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==
+ dependencies:
+ tslib "^1.8.1"
+
twemoji-parser@13.0.0:
version "13.0.0"
resolved "https://registry.yarnpkg.com/twemoji-parser/-/twemoji-parser-13.0.0.tgz#bd9d1b98474f1651dc174696b45cabefdfa405af"