mirror of
https://github.com/glitch-soc/mastodon.git
synced 2025-12-13 15:58:50 +00:00
Merge commit 'e91c7645905972d9663a0d944b133ff24670bce2' into glitch-soc/merge-4.5
This commit is contained in:
10
CHANGELOG.md
10
CHANGELOG.md
@@ -6,13 +6,14 @@ All notable changes to this project will be documented in this file.
|
|||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- **Add support for allowing and authoring quotes** (#35355, #35578, #35614, #35618, #35624, #35626, #35652, #35629, #35665, #35653, #35670, #35677, #35690, #35697, #35689, #35699, #35700, #35701, #35709, #35714, #35713, #35715, #35725, #35749, #35769, #35780, #35762, #35804, #35808, #35805, #35819, #35824, #35828, #35822, #35835, #35865, #35860, #35832, #35891, #35894, #35895, #35820, #35917, #35924, #35925, #35914, #35930, #35941, #35939, #35948, #35955, #35967, #35990, #35991, #35975, #35971, #36002, #35986, #36031, #36034, #36038, #36054, #36052, #36055, #36065, #36068, #36083, #36087, #36080, #36091, #36090, #36118, #36119, #36128, #36094, #36129, #36138, #36132, #36151, #36158, #36171, #36194, #36220, #36169, #36130, #36249, #36153, #36299, #36291, #36301, #36315, #36317, #36364, #36383, #36381, #36459, #36464, #36461, #36516, #36528, #36549, #36550 and #36559 by @ChaosExAnima, @ClearlyClaire, @Lycolia, @diondiondion, and @tribela)\
|
- **Add support for allowing and authoring quotes** (#35355, #35578, #35614, #35618, #35624, #35626, #35652, #35629, #35665, #35653, #35670, #35677, #35690, #35697, #35689, #35699, #35700, #35701, #35709, #35714, #35713, #35715, #35725, #35749, #35769, #35780, #35762, #35804, #35808, #35805, #35819, #35824, #35828, #35822, #35835, #35865, #35860, #35832, #35891, #35894, #35895, #35820, #35917, #35924, #35925, #35914, #35930, #35941, #35939, #35948, #35955, #35967, #35990, #35991, #35975, #35971, #36002, #35986, #36031, #36034, #36038, #36054, #36052, #36055, #36065, #36068, #36083, #36087, #36080, #36091, #36090, #36118, #36119, #36128, #36094, #36129, #36138, #36132, #36151, #36158, #36171, #36194, #36220, #36169, #36130, #36249, #36153, #36299, #36291, #36301, #36315, #36317, #36364, #36383, #36381, #36459, #36464, #36461, #36516, #36528, #36549, #36550, #36559, #36693, #36704, #36690, #36689, #36696, #36721 and #36695 by @ChaosExAnima, @ClearlyClaire, @Lycolia, @diondiondion, and @tribela)\
|
||||||
This includes a revamp of the composer interface.\
|
This includes a revamp of the composer interface.\
|
||||||
See https://blog.joinmastodon.org/2025/09/introducing-quote-posts/ for a user-centric overview of the feature, and https://docs.joinmastodon.org/client/quotes/ for API documentation.
|
See https://blog.joinmastodon.org/2025/09/introducing-quote-posts/ for a user-centric overview of the feature, and https://docs.joinmastodon.org/client/quotes/ for API documentation.
|
||||||
- **Add support for fetching and refreshing replies to the web UI** (#35210, #35496, #35575, #35500, #35577, #35602, #35603, #35654, #36141, #36237, #36172, #36256, #36271, #36334, #36382, #36239, #36484, #36481, #36583, #36627 and #36547 by @ClearlyClaire, @diondiondion, @Gargron and @renchap)
|
- **Add support for fetching and refreshing replies to the web UI** (#35210, #35496, #35575, #35500, #35577, #35602, #35603, #35654, #36141, #36237, #36172, #36256, #36271, #36334, #36382, #36239, #36484, #36481, #36583, #36627 and #36547 by @ClearlyClaire, @diondiondion, @Gargron and @renchap)
|
||||||
- **Add ability to block words in usernames** (#35407, #35655, and #35806 by @ClearlyClaire and @Gargron)
|
- **Add ability to block words in usernames** (#35407, #35655, and #35806 by @ClearlyClaire and @Gargron)
|
||||||
- Add ability to individually disable local or remote feeds for visitors or logged-in users `disabled` value to server setting for live and topic feeds, as well as user permission to bypass that (#36338, #36467, #36497, #36563, #36577, #36585, and #36607 by @ClearlyClaire)\
|
- Add ability to individually disable local or remote feeds for visitors or logged-in users `disabled` value to server setting for live and topic feeds, as well as user permission to bypass that (#36338, #36467, #36497, #36563, #36577, #36585, #36607 and #36703 by @ClearlyClaire)\
|
||||||
This splits the `timeline_preview` setting into four more granular settings controlling live feeds and topic (hashtag, trending link) feeds, with 3 values each: `public`, `authenticated`, `disabled`.\
|
This splits the `timeline_preview` setting into four more granular settings controlling live feeds and topic (hashtag, trending link) feeds.\
|
||||||
|
The setting for local topic feeds has 2 values: `public` and `authenticated`. Every other setting has 3 values: `public`, `authenticated`, `disabled`.\
|
||||||
When `disabled`, users with the “View live and topic feeds” will still be able to view them.
|
When `disabled`, users with the “View live and topic feeds” will still be able to view them.
|
||||||
- Add support for displaying of quote posts in Moderator UI (#35964 by @ThisIsMissEm)
|
- Add support for displaying of quote posts in Moderator UI (#35964 by @ThisIsMissEm)
|
||||||
- Add support for displaying link previews for Admin UI (#35958 by @ThisIsMissEm)
|
- Add support for displaying link previews for Admin UI (#35958 by @ThisIsMissEm)
|
||||||
@@ -44,6 +45,8 @@ All notable changes to this project will be documented in this file.
|
|||||||
- Change display of blocked and muted quoted users (#36619 by @ClearlyClaire)\
|
- Change display of blocked and muted quoted users (#36619 by @ClearlyClaire)\
|
||||||
This adds `blocked_account`, `blocked_domain` and `muted_account` values to the `state` attribute of `Quote` and `ShallowQuote` REST API entities.
|
This adds `blocked_account`, `blocked_domain` and `muted_account` values to the `state` attribute of `Quote` and `ShallowQuote` REST API entities.
|
||||||
- Change submitting an empty post to show an error rather than failing silently (#36650 by @diondiondion)
|
- Change submitting an empty post to show an error rather than failing silently (#36650 by @diondiondion)
|
||||||
|
- Change "Privacy and reach" settings from "Public profile" to their own top-level category (#27294 by @ChaelCodes)
|
||||||
|
- Change number of times quote verification is retried to better deal with temporary failures (#36698 by @ClearlyClaire)
|
||||||
- Change display of content warnings in Admin UI (#35935 by @ThisIsMissEm)
|
- Change display of content warnings in Admin UI (#35935 by @ThisIsMissEm)
|
||||||
- Change styling of column banners (#36531 by @ClearlyClaire)
|
- Change styling of column banners (#36531 by @ClearlyClaire)
|
||||||
- Change recommended Node version to 24 (LTS) (#36539 by @renchap)
|
- Change recommended Node version to 24 (LTS) (#36539 by @renchap)
|
||||||
@@ -75,6 +78,7 @@ All notable changes to this project will be documented in this file.
|
|||||||
- Fix URL comparison for mentions in case of empty path (#36613 and #36626 by @ClearlyClaire)
|
- Fix URL comparison for mentions in case of empty path (#36613 and #36626 by @ClearlyClaire)
|
||||||
- Fix hashtags not being picked up when full-width hash sign is used (#36103 and #36625 by @ClearlyClaire and @Gargron)
|
- Fix hashtags not being picked up when full-width hash sign is used (#36103 and #36625 by @ClearlyClaire and @Gargron)
|
||||||
- Fix layout of severed relationships when purged events are listed (#36593 by @mejofi)
|
- Fix layout of severed relationships when purged events are listed (#36593 by @mejofi)
|
||||||
|
- Fix Skeleton placeholders being animated when setting to reduce animations is enabled (#36716 by @ClearlyClaire)
|
||||||
- Fix vacuum tasks being interrupted by a single batch failure (#36606 by @Gargron)
|
- Fix vacuum tasks being interrupted by a single batch failure (#36606 by @Gargron)
|
||||||
- Fix handling of unreachable network error for search services (#36587 by @mjankowski)
|
- Fix handling of unreachable network error for search services (#36587 by @mjankowski)
|
||||||
- Fix bookmarks export when a bookmarked status is soft-deleted (#36576 by @ClearlyClaire)
|
- Fix bookmarks export when a bookmarked status is soft-deleted (#36576 by @ClearlyClaire)
|
||||||
|
|||||||
14
Gemfile.lock
14
Gemfile.lock
@@ -128,7 +128,7 @@ GEM
|
|||||||
blurhash (0.1.8)
|
blurhash (0.1.8)
|
||||||
bootsnap (1.18.6)
|
bootsnap (1.18.6)
|
||||||
msgpack (~> 1.2)
|
msgpack (~> 1.2)
|
||||||
brakeman (7.0.2)
|
brakeman (7.1.1)
|
||||||
racc
|
racc
|
||||||
browser (6.2.0)
|
browser (6.2.0)
|
||||||
builder (3.3.0)
|
builder (3.3.0)
|
||||||
@@ -224,7 +224,7 @@ GEM
|
|||||||
mail (~> 2.7)
|
mail (~> 2.7)
|
||||||
email_validator (2.2.4)
|
email_validator (2.2.4)
|
||||||
activemodel
|
activemodel
|
||||||
erb (5.1.1)
|
erb (5.1.3)
|
||||||
erubi (1.13.1)
|
erubi (1.13.1)
|
||||||
et-orbi (1.4.0)
|
et-orbi (1.4.0)
|
||||||
tzinfo
|
tzinfo
|
||||||
@@ -337,7 +337,7 @@ GEM
|
|||||||
activesupport (>= 3.0)
|
activesupport (>= 3.0)
|
||||||
nokogiri (>= 1.6)
|
nokogiri (>= 1.6)
|
||||||
io-console (0.8.1)
|
io-console (0.8.1)
|
||||||
irb (1.15.2)
|
irb (1.15.3)
|
||||||
pp (>= 0.6.0)
|
pp (>= 0.6.0)
|
||||||
rdoc (>= 4.0.0)
|
rdoc (>= 4.0.0)
|
||||||
reline (>= 0.4.2)
|
reline (>= 0.4.2)
|
||||||
@@ -621,7 +621,7 @@ GEM
|
|||||||
activesupport (>= 3.0.0)
|
activesupport (>= 3.0.0)
|
||||||
raabro (1.4.0)
|
raabro (1.4.0)
|
||||||
racc (1.8.1)
|
racc (1.8.1)
|
||||||
rack (3.2.3)
|
rack (3.2.4)
|
||||||
rack-attack (6.8.0)
|
rack-attack (6.8.0)
|
||||||
rack (>= 1.0, < 4)
|
rack (>= 1.0, < 4)
|
||||||
rack-cors (3.0.0)
|
rack-cors (3.0.0)
|
||||||
@@ -691,7 +691,7 @@ GEM
|
|||||||
readline (~> 0.0)
|
readline (~> 0.0)
|
||||||
rdf-normalize (0.7.0)
|
rdf-normalize (0.7.0)
|
||||||
rdf (~> 3.3)
|
rdf (~> 3.3)
|
||||||
rdoc (6.15.0)
|
rdoc (6.15.1)
|
||||||
erb
|
erb
|
||||||
psych (>= 4.0.0)
|
psych (>= 4.0.0)
|
||||||
tsort
|
tsort
|
||||||
@@ -791,7 +791,7 @@ GEM
|
|||||||
ruby-vips (2.2.5)
|
ruby-vips (2.2.5)
|
||||||
ffi (~> 1.12)
|
ffi (~> 1.12)
|
||||||
logger
|
logger
|
||||||
rubyzip (3.2.1)
|
rubyzip (3.2.2)
|
||||||
rufus-scheduler (3.9.2)
|
rufus-scheduler (3.9.2)
|
||||||
fugit (~> 1.1, >= 1.11.1)
|
fugit (~> 1.1, >= 1.11.1)
|
||||||
safety_net_attestation (0.5.0)
|
safety_net_attestation (0.5.0)
|
||||||
@@ -805,7 +805,7 @@ GEM
|
|||||||
securerandom (0.4.1)
|
securerandom (0.4.1)
|
||||||
shoulda-matchers (6.5.0)
|
shoulda-matchers (6.5.0)
|
||||||
activesupport (>= 5.2.0)
|
activesupport (>= 5.2.0)
|
||||||
sidekiq (8.0.8)
|
sidekiq (8.0.9)
|
||||||
connection_pool (>= 2.5.0)
|
connection_pool (>= 2.5.0)
|
||||||
json (>= 2.9.0)
|
json (>= 2.9.0)
|
||||||
logger (>= 1.6.2)
|
logger (>= 1.6.2)
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ class ActivityPub::QuoteAuthorizationsController < ActivityPub::BaseController
|
|||||||
before_action :set_quote_authorization
|
before_action :set_quote_authorization
|
||||||
|
|
||||||
def show
|
def show
|
||||||
expires_in 30.seconds, public: true if @quote.status.distributable? && public_fetch_mode?
|
expires_in 30.seconds, public: true if @quote.quoted_status.distributable? && public_fetch_mode?
|
||||||
render json: @quote, serializer: ActivityPub::QuoteAuthorizationSerializer, adapter: ActivityPub::Adapter, content_type: 'application/activity+json'
|
render json: @quote, serializer: ActivityPub::QuoteAuthorizationSerializer, adapter: ActivityPub::Adapter, content_type: 'application/activity+json'
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -23,7 +23,7 @@ class ActivityPub::QuoteAuthorizationsController < ActivityPub::BaseController
|
|||||||
@quote = Quote.accepted.where(quoted_account: @account).find(params[:id])
|
@quote = Quote.accepted.where(quoted_account: @account).find(params[:id])
|
||||||
return not_found unless @quote.status.present? && @quote.quoted_status.present?
|
return not_found unless @quote.status.present? && @quote.quoted_status.present?
|
||||||
|
|
||||||
authorize @quote.status, :show?
|
authorize @quote.quoted_status, :show?
|
||||||
rescue Mastodon::NotPermittedError
|
rescue Mastodon::NotPermittedError
|
||||||
not_found
|
not_found
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -56,7 +56,6 @@ export const COMPOSE_UNMOUNT = 'COMPOSE_UNMOUNT';
|
|||||||
export const COMPOSE_SENSITIVITY_CHANGE = 'COMPOSE_SENSITIVITY_CHANGE';
|
export const COMPOSE_SENSITIVITY_CHANGE = 'COMPOSE_SENSITIVITY_CHANGE';
|
||||||
export const COMPOSE_SPOILERNESS_CHANGE = 'COMPOSE_SPOILERNESS_CHANGE';
|
export const COMPOSE_SPOILERNESS_CHANGE = 'COMPOSE_SPOILERNESS_CHANGE';
|
||||||
export const COMPOSE_SPOILER_TEXT_CHANGE = 'COMPOSE_SPOILER_TEXT_CHANGE';
|
export const COMPOSE_SPOILER_TEXT_CHANGE = 'COMPOSE_SPOILER_TEXT_CHANGE';
|
||||||
export const COMPOSE_VISIBILITY_CHANGE = 'COMPOSE_VISIBILITY_CHANGE';
|
|
||||||
export const COMPOSE_COMPOSING_CHANGE = 'COMPOSE_COMPOSING_CHANGE';
|
export const COMPOSE_COMPOSING_CHANGE = 'COMPOSE_COMPOSING_CHANGE';
|
||||||
export const COMPOSE_LANGUAGE_CHANGE = 'COMPOSE_LANGUAGE_CHANGE';
|
export const COMPOSE_LANGUAGE_CHANGE = 'COMPOSE_LANGUAGE_CHANGE';
|
||||||
|
|
||||||
@@ -796,13 +795,6 @@ export function changeComposeSpoilerText(text) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function changeComposeVisibility(value) {
|
|
||||||
return {
|
|
||||||
type: COMPOSE_VISIBILITY_CHANGE,
|
|
||||||
value,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function insertEmojiCompose(position, emoji, needsSpace) {
|
export function insertEmojiCompose(position, emoji, needsSpace) {
|
||||||
return {
|
return {
|
||||||
type: COMPOSE_EMOJI_INSERT,
|
type: COMPOSE_EMOJI_INSERT,
|
||||||
|
|||||||
@@ -13,10 +13,11 @@ import {
|
|||||||
} from 'mastodon/store/typed_functions';
|
} from 'mastodon/store/typed_functions';
|
||||||
|
|
||||||
import type { ApiQuotePolicy } from '../api_types/quotes';
|
import type { ApiQuotePolicy } from '../api_types/quotes';
|
||||||
import type { Status } from '../models/status';
|
import type { Status, StatusVisibility } from '../models/status';
|
||||||
|
import type { RootState } from '../store';
|
||||||
|
|
||||||
import { showAlert } from './alerts';
|
import { showAlert } from './alerts';
|
||||||
import { focusCompose } from './compose';
|
import { changeCompose, focusCompose } from './compose';
|
||||||
import { importFetchedStatuses } from './importer';
|
import { importFetchedStatuses } from './importer';
|
||||||
import { openModal } from './modal';
|
import { openModal } from './modal';
|
||||||
|
|
||||||
@@ -41,6 +42,10 @@ const messages = defineMessages({
|
|||||||
id: 'quote_error.unauthorized',
|
id: 'quote_error.unauthorized',
|
||||||
defaultMessage: 'You are not authorized to quote this post.',
|
defaultMessage: 'You are not authorized to quote this post.',
|
||||||
},
|
},
|
||||||
|
quoteErrorPrivateMention: {
|
||||||
|
id: 'quote_error.private_mentions',
|
||||||
|
defaultMessage: 'Quoting is not allowed with direct mentions.',
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
type SimulatedMediaAttachmentJSON = ApiMediaAttachmentJSON & {
|
type SimulatedMediaAttachmentJSON = ApiMediaAttachmentJSON & {
|
||||||
@@ -67,6 +72,39 @@ const simulateModifiedApiResponse = (
|
|||||||
return data;
|
return data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const changeComposeVisibility = createAppThunk(
|
||||||
|
'compose/visibility_change',
|
||||||
|
(visibility: StatusVisibility, { dispatch, getState }) => {
|
||||||
|
if (visibility !== 'direct') {
|
||||||
|
return visibility;
|
||||||
|
}
|
||||||
|
|
||||||
|
const state = getState();
|
||||||
|
const quotedStatusId = state.compose.get('quoted_status_id') as
|
||||||
|
| string
|
||||||
|
| null;
|
||||||
|
if (!quotedStatusId) {
|
||||||
|
return visibility;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the quoted status
|
||||||
|
dispatch(quoteComposeCancel());
|
||||||
|
const quotedStatus = state.statuses.get(quotedStatusId) as Status | null;
|
||||||
|
if (!quotedStatus) {
|
||||||
|
return visibility;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append the quoted status URL to the compose text
|
||||||
|
const url = quotedStatus.get('url') as string;
|
||||||
|
const text = state.compose.get('text') as string;
|
||||||
|
if (!text.includes(url)) {
|
||||||
|
const newText = text.trim() ? `${text}\n\n${url}` : url;
|
||||||
|
dispatch(changeCompose(newText));
|
||||||
|
}
|
||||||
|
return visibility;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
export const changeUploadCompose = createDataLoadingThunk(
|
export const changeUploadCompose = createDataLoadingThunk(
|
||||||
'compose/changeUpload',
|
'compose/changeUpload',
|
||||||
async (
|
async (
|
||||||
@@ -130,6 +168,8 @@ export const quoteComposeByStatus = createAppThunk(
|
|||||||
|
|
||||||
if (composeState.get('id')) {
|
if (composeState.get('id')) {
|
||||||
dispatch(showAlert({ message: messages.quoteErrorEdit }));
|
dispatch(showAlert({ message: messages.quoteErrorEdit }));
|
||||||
|
} else if (composeState.get('privacy') === 'direct') {
|
||||||
|
dispatch(showAlert({ message: messages.quoteErrorPrivateMention }));
|
||||||
} else if (composeState.get('poll')) {
|
} else if (composeState.get('poll')) {
|
||||||
dispatch(showAlert({ message: messages.quoteErrorPoll }));
|
dispatch(showAlert({ message: messages.quoteErrorPoll }));
|
||||||
} else if (
|
} else if (
|
||||||
@@ -173,6 +213,17 @@ export const quoteComposeById = createAppThunk(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const composeStateForbidsLink = (composeState: RootState['compose']) => {
|
||||||
|
return (
|
||||||
|
composeState.get('quoted_status_id') ||
|
||||||
|
composeState.get('is_submitting') ||
|
||||||
|
composeState.get('poll') ||
|
||||||
|
composeState.get('is_uploading') ||
|
||||||
|
composeState.get('id') ||
|
||||||
|
composeState.get('privacy') === 'direct'
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export const pasteLinkCompose = createDataLoadingThunk(
|
export const pasteLinkCompose = createDataLoadingThunk(
|
||||||
'compose/pasteLink',
|
'compose/pasteLink',
|
||||||
async ({ url }: { url: string }) => {
|
async ({ url }: { url: string }) => {
|
||||||
@@ -183,15 +234,12 @@ export const pasteLinkCompose = createDataLoadingThunk(
|
|||||||
limit: 2,
|
limit: 2,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
(data, { dispatch, getState }) => {
|
(data, { dispatch, getState, requestId }) => {
|
||||||
const composeState = getState().compose;
|
const composeState = getState().compose;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
composeState.get('quoted_status_id') ||
|
composeStateForbidsLink(composeState) ||
|
||||||
composeState.get('is_submitting') ||
|
composeState.get('fetching_link') !== requestId // Request has been cancelled
|
||||||
composeState.get('poll') ||
|
|
||||||
composeState.get('is_uploading') ||
|
|
||||||
composeState.get('id')
|
|
||||||
)
|
)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -207,6 +255,17 @@ export const pasteLinkCompose = createDataLoadingThunk(
|
|||||||
dispatch(quoteComposeById(data.statuses[0].id));
|
dispatch(quoteComposeById(data.statuses[0].id));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
useLoadingBar: false,
|
||||||
|
condition: (_, { getState }) =>
|
||||||
|
!getState().compose.get('fetching_link') &&
|
||||||
|
!composeStateForbidsLink(getState().compose),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
// Ideally this would cancel the action and the HTTP request, but this is good enough
|
||||||
|
export const cancelPasteLinkCompose = createAction(
|
||||||
|
'compose/cancelPasteLinkCompose',
|
||||||
);
|
);
|
||||||
|
|
||||||
export const quoteComposeCancel = createAction('compose/quoteComposeCancel');
|
export const quoteComposeCancel = createAction('compose/quoteComposeCancel');
|
||||||
|
|||||||
@@ -140,7 +140,10 @@ class ComposeForm extends ImmutablePureComponent {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.props.onSubmit(missingAltTextModal && this.props.missingAltText && this.props.privacy !== 'direct');
|
this.props.onSubmit({
|
||||||
|
missingAltText: missingAltTextModal && this.props.missingAltText && this.props.privacy !== 'direct',
|
||||||
|
quoteToPrivate: this.props.quoteToPrivate,
|
||||||
|
});
|
||||||
|
|
||||||
if (e) {
|
if (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
import { useCallback } from 'react';
|
||||||
|
import type { FC } from 'react';
|
||||||
|
|
||||||
|
import { defineMessages, useIntl } from 'react-intl';
|
||||||
|
|
||||||
|
import { cancelPasteLinkCompose } from '@/mastodon/actions/compose_typed';
|
||||||
|
import { useAppDispatch } from '@/mastodon/store';
|
||||||
|
import CancelFillIcon from '@/material-icons/400-24px/cancel-fill.svg?react';
|
||||||
|
import { DisplayName } from 'mastodon/components/display_name';
|
||||||
|
import { IconButton } from 'mastodon/components/icon_button';
|
||||||
|
import { Skeleton } from 'mastodon/components/skeleton';
|
||||||
|
|
||||||
|
const messages = defineMessages({
|
||||||
|
quote_cancel: { id: 'status.quote.cancel', defaultMessage: 'Cancel quote' },
|
||||||
|
});
|
||||||
|
|
||||||
|
export const QuotePlaceholder: FC = () => {
|
||||||
|
const intl = useIntl();
|
||||||
|
const dispatch = useAppDispatch();
|
||||||
|
const handleQuoteCancel = useCallback(() => {
|
||||||
|
dispatch(cancelPasteLinkCompose());
|
||||||
|
}, [dispatch]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='status__quote'>
|
||||||
|
<div className='status'>
|
||||||
|
<div className='status__info'>
|
||||||
|
<div className='status__avatar'>
|
||||||
|
<Skeleton width='32px' height='32px' />
|
||||||
|
</div>
|
||||||
|
<div className='status__display-name'>
|
||||||
|
<DisplayName />
|
||||||
|
</div>
|
||||||
|
<IconButton
|
||||||
|
onClick={handleQuoteCancel}
|
||||||
|
className='status__quote-cancel'
|
||||||
|
title={intl.formatMessage(messages.quote_cancel)}
|
||||||
|
icon='cancel-fill'
|
||||||
|
iconComponent={CancelFillIcon}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className='status__content'>
|
||||||
|
<Skeleton />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -7,11 +7,17 @@ import { quoteComposeCancel } from '@/mastodon/actions/compose_typed';
|
|||||||
import { QuotedStatus } from '@/mastodon/components/status_quoted';
|
import { QuotedStatus } from '@/mastodon/components/status_quoted';
|
||||||
import { useAppDispatch, useAppSelector } from '@/mastodon/store';
|
import { useAppDispatch, useAppSelector } from '@/mastodon/store';
|
||||||
|
|
||||||
|
import { QuotePlaceholder } from './quote_placeholder';
|
||||||
|
|
||||||
export const ComposeQuotedStatus: FC = () => {
|
export const ComposeQuotedStatus: FC = () => {
|
||||||
const quotedStatusId = useAppSelector(
|
const quotedStatusId = useAppSelector(
|
||||||
(state) => state.compose.get('quoted_status_id') as string | null,
|
(state) => state.compose.get('quoted_status_id') as string | null,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const isFetchingLink = useAppSelector(
|
||||||
|
(state) => !!state.compose.get('fetching_link'),
|
||||||
|
);
|
||||||
|
|
||||||
const isEditing = useAppSelector((state) => !!state.compose.get('id'));
|
const isEditing = useAppSelector((state) => !!state.compose.get('id'));
|
||||||
|
|
||||||
const quote = useMemo(
|
const quote = useMemo(
|
||||||
@@ -30,7 +36,9 @@ export const ComposeQuotedStatus: FC = () => {
|
|||||||
dispatch(quoteComposeCancel());
|
dispatch(quoteComposeCancel());
|
||||||
}, [dispatch]);
|
}, [dispatch]);
|
||||||
|
|
||||||
if (!quote) {
|
if (isFetchingLink && !quote) {
|
||||||
|
return <QuotePlaceholder />;
|
||||||
|
} else if (!quote) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,8 +5,10 @@ import { defineMessages, useIntl } from 'react-intl';
|
|||||||
|
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
|
||||||
import { changeComposeVisibility } from '@/mastodon/actions/compose';
|
import {
|
||||||
import { setComposeQuotePolicy } from '@/mastodon/actions/compose_typed';
|
changeComposeVisibility,
|
||||||
|
setComposeQuotePolicy,
|
||||||
|
} from '@/mastodon/actions/compose_typed';
|
||||||
import { openModal } from '@/mastodon/actions/modal';
|
import { openModal } from '@/mastodon/actions/modal';
|
||||||
import type { ApiQuotePolicy } from '@/mastodon/api_types/quotes';
|
import type { ApiQuotePolicy } from '@/mastodon/api_types/quotes';
|
||||||
import type { StatusVisibility } from '@/mastodon/api_types/statuses';
|
import type { StatusVisibility } from '@/mastodon/api_types/statuses';
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import {
|
|||||||
} from 'mastodon/actions/compose';
|
} from 'mastodon/actions/compose';
|
||||||
import { pasteLinkCompose } from 'mastodon/actions/compose_typed';
|
import { pasteLinkCompose } from 'mastodon/actions/compose_typed';
|
||||||
import { openModal } from 'mastodon/actions/modal';
|
import { openModal } from 'mastodon/actions/modal';
|
||||||
|
import { PRIVATE_QUOTE_MODAL_ID } from 'mastodon/features/ui/components/confirmation_modals/private_quote_notify';
|
||||||
|
|
||||||
import ComposeForm from '../components/compose_form';
|
import ComposeForm from '../components/compose_form';
|
||||||
|
|
||||||
@@ -32,6 +33,10 @@ const mapStateToProps = state => ({
|
|||||||
isUploading: state.getIn(['compose', 'is_uploading']),
|
isUploading: state.getIn(['compose', 'is_uploading']),
|
||||||
anyMedia: state.getIn(['compose', 'media_attachments']).size > 0,
|
anyMedia: state.getIn(['compose', 'media_attachments']).size > 0,
|
||||||
missingAltText: state.getIn(['compose', 'media_attachments']).some(media => ['image', 'gifv'].includes(media.get('type')) && (media.get('description') ?? '').length === 0),
|
missingAltText: state.getIn(['compose', 'media_attachments']).some(media => ['image', 'gifv'].includes(media.get('type')) && (media.get('description') ?? '').length === 0),
|
||||||
|
quoteToPrivate:
|
||||||
|
!!state.getIn(['compose', 'quoted_status_id'])
|
||||||
|
&& state.getIn(['compose', 'privacy']) === 'private'
|
||||||
|
&& !state.getIn(['settings', 'dismissed_banners', PRIVATE_QUOTE_MODAL_ID]),
|
||||||
isInReply: state.getIn(['compose', 'in_reply_to']) !== null,
|
isInReply: state.getIn(['compose', 'in_reply_to']) !== null,
|
||||||
lang: state.getIn(['compose', 'language']),
|
lang: state.getIn(['compose', 'language']),
|
||||||
maxChars: state.getIn(['server', 'server', 'configuration', 'statuses', 'max_characters'], 500),
|
maxChars: state.getIn(['server', 'server', 'configuration', 'statuses', 'max_characters'], 500),
|
||||||
@@ -43,12 +48,17 @@ const mapDispatchToProps = (dispatch, props) => ({
|
|||||||
dispatch(changeCompose(text));
|
dispatch(changeCompose(text));
|
||||||
},
|
},
|
||||||
|
|
||||||
onSubmit (missingAltText) {
|
onSubmit ({ missingAltText, quoteToPrivate }) {
|
||||||
if (missingAltText) {
|
if (missingAltText) {
|
||||||
dispatch(openModal({
|
dispatch(openModal({
|
||||||
modalType: 'CONFIRM_MISSING_ALT_TEXT',
|
modalType: 'CONFIRM_MISSING_ALT_TEXT',
|
||||||
modalProps: {},
|
modalProps: {},
|
||||||
}));
|
}));
|
||||||
|
} else if (quoteToPrivate) {
|
||||||
|
dispatch(openModal({
|
||||||
|
modalType: 'CONFIRM_PRIVATE_QUOTE_NOTIFY',
|
||||||
|
modalProps: {},
|
||||||
|
}));
|
||||||
} else {
|
} else {
|
||||||
dispatch(submitCompose((status) => {
|
dispatch(submitCompose((status) => {
|
||||||
if (props.redirectOnSuccess) {
|
if (props.redirectOnSuccess) {
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
import { changeComposeVisibility } from '../../../actions/compose';
|
import { changeComposeVisibility } from '@/mastodon/actions/compose_typed';
|
||||||
import { openModal, closeModal } from '../../../actions/modal';
|
|
||||||
import { isUserTouching } from '../../../is_mobile';
|
|
||||||
import PrivacyDropdown from '../components/privacy_dropdown';
|
import PrivacyDropdown from '../components/privacy_dropdown';
|
||||||
|
|
||||||
const mapStateToProps = state => ({
|
const mapStateToProps = state => ({
|
||||||
|
|||||||
@@ -299,6 +299,12 @@ class Status extends ImmutablePureComponent {
|
|||||||
dispatch(openModal({ modalType: 'COMPOSE_PRIVACY', modalProps: { statusId, onChange: handleChange } }));
|
dispatch(openModal({ modalType: 'COMPOSE_PRIVACY', modalProps: { statusId, onChange: handleChange } }));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
handleQuote = (status) => {
|
||||||
|
const { dispatch } = this.props;
|
||||||
|
|
||||||
|
dispatch(quoteComposeById(status.get('id')));
|
||||||
|
};
|
||||||
|
|
||||||
handleEditClick = (status) => {
|
handleEditClick = (status) => {
|
||||||
const { dispatch, askReplyConfirmation } = this.props;
|
const { dispatch, askReplyConfirmation } = this.props;
|
||||||
|
|
||||||
@@ -625,6 +631,7 @@ class Status extends ImmutablePureComponent {
|
|||||||
onDelete={this.handleDeleteClick}
|
onDelete={this.handleDeleteClick}
|
||||||
onRevokeQuote={this.handleRevokeQuoteClick}
|
onRevokeQuote={this.handleRevokeQuoteClick}
|
||||||
onQuotePolicyChange={this.handleQuotePolicyChange}
|
onQuotePolicyChange={this.handleQuotePolicyChange}
|
||||||
|
onQuote={this.handleQuote}
|
||||||
onEdit={this.handleEditClick}
|
onEdit={this.handleEditClick}
|
||||||
onDirect={this.handleDirectClick}
|
onDirect={this.handleDirectClick}
|
||||||
onMention={this.handleMentionClick}
|
onMention={this.handleMentionClick}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ export const ConfirmationModal: React.FC<
|
|||||||
onSecondary?: () => void;
|
onSecondary?: () => void;
|
||||||
onConfirm: () => void;
|
onConfirm: () => void;
|
||||||
closeWhenConfirm?: boolean;
|
closeWhenConfirm?: boolean;
|
||||||
|
extraContent?: React.ReactNode;
|
||||||
} & BaseConfirmationModalProps
|
} & BaseConfirmationModalProps
|
||||||
> = ({
|
> = ({
|
||||||
title,
|
title,
|
||||||
@@ -29,6 +30,7 @@ export const ConfirmationModal: React.FC<
|
|||||||
secondary,
|
secondary,
|
||||||
onSecondary,
|
onSecondary,
|
||||||
closeWhenConfirm = true,
|
closeWhenConfirm = true,
|
||||||
|
extraContent,
|
||||||
}) => {
|
}) => {
|
||||||
const handleClick = useCallback(() => {
|
const handleClick = useCallback(() => {
|
||||||
if (closeWhenConfirm) {
|
if (closeWhenConfirm) {
|
||||||
@@ -49,6 +51,8 @@ export const ConfirmationModal: React.FC<
|
|||||||
<div className='safety-action-modal__confirmation'>
|
<div className='safety-action-modal__confirmation'>
|
||||||
<h1>{title}</h1>
|
<h1>{title}</h1>
|
||||||
{message && <p>{message}</p>}
|
{message && <p>{message}</p>}
|
||||||
|
|
||||||
|
{extraContent}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,88 @@
|
|||||||
|
import { forwardRef, useCallback, useState } from 'react';
|
||||||
|
|
||||||
|
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
|
||||||
|
|
||||||
|
import { submitCompose } from '@/mastodon/actions/compose';
|
||||||
|
import { changeSetting } from '@/mastodon/actions/settings';
|
||||||
|
import { CheckBox } from '@/mastodon/components/check_box';
|
||||||
|
import { useAppDispatch } from '@/mastodon/store';
|
||||||
|
|
||||||
|
import { ConfirmationModal } from './confirmation_modal';
|
||||||
|
import type { BaseConfirmationModalProps } from './confirmation_modal';
|
||||||
|
import classes from './styles.module.css';
|
||||||
|
|
||||||
|
export const PRIVATE_QUOTE_MODAL_ID = 'quote/private_notify';
|
||||||
|
|
||||||
|
const messages = defineMessages({
|
||||||
|
title: {
|
||||||
|
id: 'confirmations.private_quote_notify.title',
|
||||||
|
defaultMessage: 'Share with followers and mentioned users?',
|
||||||
|
},
|
||||||
|
message: {
|
||||||
|
id: 'confirmations.private_quote_notify.message',
|
||||||
|
defaultMessage:
|
||||||
|
'The person you are quoting and other mentions ' +
|
||||||
|
"will be notified and will be able to view your post, even if they're not following you.",
|
||||||
|
},
|
||||||
|
confirm: {
|
||||||
|
id: 'confirmations.private_quote_notify.confirm',
|
||||||
|
defaultMessage: 'Publish post',
|
||||||
|
},
|
||||||
|
cancel: {
|
||||||
|
id: 'confirmations.private_quote_notify.cancel',
|
||||||
|
defaultMessage: 'Back to editing',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const PrivateQuoteNotify = forwardRef<
|
||||||
|
HTMLDivElement,
|
||||||
|
BaseConfirmationModalProps
|
||||||
|
>(
|
||||||
|
(
|
||||||
|
{ onClose },
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
_ref,
|
||||||
|
) => {
|
||||||
|
const intl = useIntl();
|
||||||
|
|
||||||
|
const [dismiss, setDismissed] = useState(false);
|
||||||
|
const handleDismissToggle = useCallback(() => {
|
||||||
|
setDismissed((prev) => !prev);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const dispatch = useAppDispatch();
|
||||||
|
const handleConfirm = useCallback(() => {
|
||||||
|
dispatch(submitCompose());
|
||||||
|
if (dismiss) {
|
||||||
|
dispatch(
|
||||||
|
changeSetting(['dismissed_banners', PRIVATE_QUOTE_MODAL_ID], true),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}, [dismiss, dispatch]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ConfirmationModal
|
||||||
|
title={intl.formatMessage(messages.title)}
|
||||||
|
message={intl.formatMessage(messages.message)}
|
||||||
|
confirm={intl.formatMessage(messages.confirm)}
|
||||||
|
cancel={intl.formatMessage(messages.cancel)}
|
||||||
|
onConfirm={handleConfirm}
|
||||||
|
onClose={onClose}
|
||||||
|
extraContent={
|
||||||
|
<label className={classes.checkbox_wrapper}>
|
||||||
|
<CheckBox
|
||||||
|
value='hide'
|
||||||
|
checked={dismiss}
|
||||||
|
onChange={handleDismissToggle}
|
||||||
|
/>{' '}
|
||||||
|
<FormattedMessage
|
||||||
|
id='confirmations.private_quote_notify.do_not_show_again'
|
||||||
|
defaultMessage="Don't show me this message again"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
PrivateQuoteNotify.displayName = 'PrivateQuoteNotify';
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
.checkbox_wrapper {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
margin: 1rem 0;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
@@ -47,6 +47,7 @@ import MediaModal from './media_modal';
|
|||||||
import { ModalPlaceholder } from './modal_placeholder';
|
import { ModalPlaceholder } from './modal_placeholder';
|
||||||
import VideoModal from './video_modal';
|
import VideoModal from './video_modal';
|
||||||
import { VisibilityModal } from './visibility_modal';
|
import { VisibilityModal } from './visibility_modal';
|
||||||
|
import { PrivateQuoteNotify } from './confirmation_modals/private_quote_notify';
|
||||||
|
|
||||||
export const MODAL_COMPONENTS = {
|
export const MODAL_COMPONENTS = {
|
||||||
'MEDIA': () => Promise.resolve({ default: MediaModal }),
|
'MEDIA': () => Promise.resolve({ default: MediaModal }),
|
||||||
@@ -66,6 +67,7 @@ export const MODAL_COMPONENTS = {
|
|||||||
'CONFIRM_LOG_OUT': () => Promise.resolve({ default: ConfirmLogOutModal }),
|
'CONFIRM_LOG_OUT': () => Promise.resolve({ default: ConfirmLogOutModal }),
|
||||||
'CONFIRM_FOLLOW_TO_LIST': () => Promise.resolve({ default: ConfirmFollowToListModal }),
|
'CONFIRM_FOLLOW_TO_LIST': () => Promise.resolve({ default: ConfirmFollowToListModal }),
|
||||||
'CONFIRM_MISSING_ALT_TEXT': () => Promise.resolve({ default: ConfirmMissingAltTextModal }),
|
'CONFIRM_MISSING_ALT_TEXT': () => Promise.resolve({ default: ConfirmMissingAltTextModal }),
|
||||||
|
'CONFIRM_PRIVATE_QUOTE_NOTIFY': () => Promise.resolve({ default: PrivateQuoteNotify }),
|
||||||
'CONFIRM_REVOKE_QUOTE': () => Promise.resolve({ default: ConfirmRevokeQuoteModal }),
|
'CONFIRM_REVOKE_QUOTE': () => Promise.resolve({ default: ConfirmRevokeQuoteModal }),
|
||||||
'CONFIRM_QUIET_QUOTE': () => Promise.resolve({ default: QuietPostQuoteInfoModal }),
|
'CONFIRM_QUIET_QUOTE': () => Promise.resolve({ default: QuietPostQuoteInfoModal }),
|
||||||
'MUTE': MuteModal,
|
'MUTE': MuteModal,
|
||||||
|
|||||||
@@ -128,9 +128,12 @@ export const VisibilityModal: FC<VisibilityModalProps> = forwardRef(
|
|||||||
const disableVisibility = !!statusId;
|
const disableVisibility = !!statusId;
|
||||||
const disableQuotePolicy =
|
const disableQuotePolicy =
|
||||||
visibility === 'private' || visibility === 'direct';
|
visibility === 'private' || visibility === 'direct';
|
||||||
const disablePublicVisibilities: boolean = useAppSelector(
|
const disablePublicVisibilities = useAppSelector(
|
||||||
selectDisablePublicVisibilities,
|
selectDisablePublicVisibilities,
|
||||||
);
|
);
|
||||||
|
const isQuotePost = useAppSelector(
|
||||||
|
(state) => state.compose.get('quoted_status_id') !== null,
|
||||||
|
);
|
||||||
|
|
||||||
const visibilityItems = useMemo<SelectItem<StatusVisibility>[]>(() => {
|
const visibilityItems = useMemo<SelectItem<StatusVisibility>[]>(() => {
|
||||||
const items: SelectItem<StatusVisibility>[] = [
|
const items: SelectItem<StatusVisibility>[] = [
|
||||||
@@ -315,6 +318,21 @@ export const VisibilityModal: FC<VisibilityModalProps> = forwardRef(
|
|||||||
id={quoteDescriptionId}
|
id={quoteDescriptionId}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{isQuotePost && visibility === 'direct' && (
|
||||||
|
<div className='visibility-modal__quote-warning'>
|
||||||
|
<FormattedMessage
|
||||||
|
id='visibility_modal.direct_quote_warning.title'
|
||||||
|
defaultMessage="Quotes can't be embedded in private mentions"
|
||||||
|
tagName='h3'
|
||||||
|
/>
|
||||||
|
<FormattedMessage
|
||||||
|
id='visibility_modal.direct_quote_warning.text'
|
||||||
|
defaultMessage='If you save the current settings, the embedded quote will be converted to a link.'
|
||||||
|
tagName='p'
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className='dialog-modal__content__actions'>
|
<div className='dialog-modal__content__actions'>
|
||||||
<Button onClick={onClose} secondary>
|
<Button onClick={onClose} secondary>
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ interface InitialStateMeta {
|
|||||||
streaming_api_base_url: string;
|
streaming_api_base_url: string;
|
||||||
local_live_feed_access: 'public' | 'authenticated' | 'disabled';
|
local_live_feed_access: 'public' | 'authenticated' | 'disabled';
|
||||||
remote_live_feed_access: 'public' | 'authenticated' | 'disabled';
|
remote_live_feed_access: 'public' | 'authenticated' | 'disabled';
|
||||||
local_topic_feed_access: 'public' | 'authenticated' | 'disabled';
|
local_topic_feed_access: 'public' | 'authenticated';
|
||||||
remote_topic_feed_access: 'public' | 'authenticated' | 'disabled';
|
remote_topic_feed_access: 'public' | 'authenticated' | 'disabled';
|
||||||
title: string;
|
title: string;
|
||||||
show_trends: boolean;
|
show_trends: boolean;
|
||||||
|
|||||||
@@ -247,6 +247,11 @@
|
|||||||
"confirmations.missing_alt_text.secondary": "Post anyway",
|
"confirmations.missing_alt_text.secondary": "Post anyway",
|
||||||
"confirmations.missing_alt_text.title": "Add alt text?",
|
"confirmations.missing_alt_text.title": "Add alt text?",
|
||||||
"confirmations.mute.confirm": "Mute",
|
"confirmations.mute.confirm": "Mute",
|
||||||
|
"confirmations.private_quote_notify.cancel": "Back to editing",
|
||||||
|
"confirmations.private_quote_notify.confirm": "Publish post",
|
||||||
|
"confirmations.private_quote_notify.do_not_show_again": "Don't show me this message again",
|
||||||
|
"confirmations.private_quote_notify.message": "The person you are quoting and other mentions will be notified and will be able to view your post, even if they're not following you.",
|
||||||
|
"confirmations.private_quote_notify.title": "Share with followers and mentioned users?",
|
||||||
"confirmations.quiet_post_quote_info.dismiss": "Don't remind me again",
|
"confirmations.quiet_post_quote_info.dismiss": "Don't remind me again",
|
||||||
"confirmations.quiet_post_quote_info.got_it": "Got it",
|
"confirmations.quiet_post_quote_info.got_it": "Got it",
|
||||||
"confirmations.quiet_post_quote_info.message": "When quoting a quiet public post, your post will be hidden from trending timelines.",
|
"confirmations.quiet_post_quote_info.message": "When quoting a quiet public post, your post will be hidden from trending timelines.",
|
||||||
@@ -759,6 +764,7 @@
|
|||||||
"privacy_policy.title": "Privacy Policy",
|
"privacy_policy.title": "Privacy Policy",
|
||||||
"quote_error.edit": "Quotes cannot be added when editing a post.",
|
"quote_error.edit": "Quotes cannot be added when editing a post.",
|
||||||
"quote_error.poll": "Quoting is not allowed with polls.",
|
"quote_error.poll": "Quoting is not allowed with polls.",
|
||||||
|
"quote_error.private_mentions": "Quoting is not allowed with direct mentions.",
|
||||||
"quote_error.quote": "Only one quote at a time is allowed.",
|
"quote_error.quote": "Only one quote at a time is allowed.",
|
||||||
"quote_error.unauthorized": "You are not authorized to quote this post.",
|
"quote_error.unauthorized": "You are not authorized to quote this post.",
|
||||||
"quote_error.upload": "Quoting is not allowed with media attachments.",
|
"quote_error.upload": "Quoting is not allowed with media attachments.",
|
||||||
@@ -1012,6 +1018,8 @@
|
|||||||
"video.volume_down": "Volume down",
|
"video.volume_down": "Volume down",
|
||||||
"video.volume_up": "Volume up",
|
"video.volume_up": "Volume up",
|
||||||
"visibility_modal.button_title": "Set visibility",
|
"visibility_modal.button_title": "Set visibility",
|
||||||
|
"visibility_modal.direct_quote_warning.text": "If you save the current settings, the embedded quote will be converted to a link.",
|
||||||
|
"visibility_modal.direct_quote_warning.title": "Quotes can't be embedded in private mentions",
|
||||||
"visibility_modal.header": "Visibility and interaction",
|
"visibility_modal.header": "Visibility and interaction",
|
||||||
"visibility_modal.helper.direct_quoting": "Private mentions authored on Mastodon can't be quoted by others.",
|
"visibility_modal.helper.direct_quoting": "Private mentions authored on Mastodon can't be quoted by others.",
|
||||||
"visibility_modal.helper.privacy_editing": "Visibility can't be changed after a post is published.",
|
"visibility_modal.helper.privacy_editing": "Visibility can't be changed after a post is published.",
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
import { Map as ImmutableMap, List as ImmutableList, OrderedSet as ImmutableOrderedSet, fromJS } from 'immutable';
|
import { Map as ImmutableMap, List as ImmutableList, OrderedSet as ImmutableOrderedSet, fromJS } from 'immutable';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
changeComposeVisibility,
|
||||||
changeUploadCompose,
|
changeUploadCompose,
|
||||||
quoteCompose,
|
quoteCompose,
|
||||||
quoteComposeCancel,
|
quoteComposeCancel,
|
||||||
setComposeQuotePolicy,
|
setComposeQuotePolicy,
|
||||||
} from 'mastodon/actions/compose_typed';
|
pasteLinkCompose,
|
||||||
|
cancelPasteLinkCompose,
|
||||||
|
} from '@/mastodon/actions/compose_typed';
|
||||||
import { timelineDelete } from 'mastodon/actions/timelines_typed';
|
import { timelineDelete } from 'mastodon/actions/timelines_typed';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@@ -38,7 +41,6 @@ import {
|
|||||||
COMPOSE_SENSITIVITY_CHANGE,
|
COMPOSE_SENSITIVITY_CHANGE,
|
||||||
COMPOSE_SPOILERNESS_CHANGE,
|
COMPOSE_SPOILERNESS_CHANGE,
|
||||||
COMPOSE_SPOILER_TEXT_CHANGE,
|
COMPOSE_SPOILER_TEXT_CHANGE,
|
||||||
COMPOSE_VISIBILITY_CHANGE,
|
|
||||||
COMPOSE_LANGUAGE_CHANGE,
|
COMPOSE_LANGUAGE_CHANGE,
|
||||||
COMPOSE_COMPOSING_CHANGE,
|
COMPOSE_COMPOSING_CHANGE,
|
||||||
COMPOSE_EMOJI_INSERT,
|
COMPOSE_EMOJI_INSERT,
|
||||||
@@ -93,6 +95,7 @@ const initialState = ImmutableMap({
|
|||||||
quoted_status_id: null,
|
quoted_status_id: null,
|
||||||
quote_policy: 'public',
|
quote_policy: 'public',
|
||||||
default_quote_policy: 'public', // Set in hydration.
|
default_quote_policy: 'public', // Set in hydration.
|
||||||
|
fetching_link: null,
|
||||||
});
|
});
|
||||||
|
|
||||||
const initialPoll = ImmutableMap({
|
const initialPoll = ImmutableMap({
|
||||||
@@ -315,7 +318,11 @@ const calculateProgress = (loaded, total) => Math.min(Math.round((loaded / total
|
|||||||
|
|
||||||
/** @type {import('@reduxjs/toolkit').Reducer<typeof initialState>} */
|
/** @type {import('@reduxjs/toolkit').Reducer<typeof initialState>} */
|
||||||
export const composeReducer = (state = initialState, action) => {
|
export const composeReducer = (state = initialState, action) => {
|
||||||
if (changeUploadCompose.fulfilled.match(action)) {
|
if (changeComposeVisibility.match(action)) {
|
||||||
|
return state
|
||||||
|
.set('privacy', action.payload)
|
||||||
|
.set('idempotencyKey', uuid());
|
||||||
|
} else if (changeUploadCompose.fulfilled.match(action)) {
|
||||||
return state
|
return state
|
||||||
.set('is_changing_upload', false)
|
.set('is_changing_upload', false)
|
||||||
.update('media_attachments', list => list.map(item => {
|
.update('media_attachments', list => list.map(item => {
|
||||||
@@ -331,15 +338,27 @@ export const composeReducer = (state = initialState, action) => {
|
|||||||
return state.set('is_changing_upload', false);
|
return state.set('is_changing_upload', false);
|
||||||
} else if (quoteCompose.match(action)) {
|
} else if (quoteCompose.match(action)) {
|
||||||
const status = action.payload;
|
const status = action.payload;
|
||||||
|
const isDirect = state.get('privacy') === 'direct';
|
||||||
return state
|
return state
|
||||||
.set('quoted_status_id', status.get('id'))
|
.set('quoted_status_id', isDirect ? null : status.get('id'))
|
||||||
.set('spoiler', status.get('sensitive'))
|
.set('spoiler', status.get('sensitive'))
|
||||||
.set('spoiler_text', status.get('spoiler_text'))
|
.set('spoiler_text', status.get('spoiler_text'))
|
||||||
.update('privacy', (visibility) => ['public', 'unlisted'].includes(visibility) && status.get('visibility') === 'private' ? 'private' : visibility);
|
.update('privacy', (visibility) => {
|
||||||
|
if (['public', 'unlisted'].includes(visibility) && status.get('visibility') === 'private') {
|
||||||
|
return 'private';
|
||||||
|
}
|
||||||
|
return visibility;
|
||||||
|
});
|
||||||
} else if (quoteComposeCancel.match(action)) {
|
} else if (quoteComposeCancel.match(action)) {
|
||||||
return state.set('quoted_status_id', null);
|
return state.set('quoted_status_id', null);
|
||||||
} else if (setComposeQuotePolicy.match(action)) {
|
} else if (setComposeQuotePolicy.match(action)) {
|
||||||
return state.set('quote_policy', action.payload);
|
return state.set('quote_policy', action.payload);
|
||||||
|
} else if (pasteLinkCompose.pending.match(action)) {
|
||||||
|
return state.set('fetching_link', action.meta.requestId);
|
||||||
|
} else if (pasteLinkCompose.fulfilled.match(action) || pasteLinkCompose.rejected.match(action)) {
|
||||||
|
return action.meta.requestId === state.get('fetching_link') ? state.set('fetching_link', null) : state;
|
||||||
|
} else if (cancelPasteLinkCompose.match(action)) {
|
||||||
|
return state.set('fetching_link', null);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(action.type) {
|
switch(action.type) {
|
||||||
@@ -383,10 +402,6 @@ export const composeReducer = (state = initialState, action) => {
|
|||||||
return state
|
return state
|
||||||
.set('spoiler_text', action.text)
|
.set('spoiler_text', action.text)
|
||||||
.set('idempotencyKey', uuid());
|
.set('idempotencyKey', uuid());
|
||||||
case COMPOSE_VISIBILITY_CHANGE:
|
|
||||||
return state
|
|
||||||
.set('privacy', action.value)
|
|
||||||
.set('idempotencyKey', uuid());
|
|
||||||
case COMPOSE_CHANGE:
|
case COMPOSE_CHANGE:
|
||||||
return state
|
return state
|
||||||
.set('text', action.text)
|
.set('text', action.text)
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ interface AppThunkConfig {
|
|||||||
}
|
}
|
||||||
export type AppThunkApi = Pick<
|
export type AppThunkApi = Pick<
|
||||||
GetThunkAPI<AppThunkConfig>,
|
GetThunkAPI<AppThunkConfig>,
|
||||||
'getState' | 'dispatch'
|
'getState' | 'dispatch' | 'requestId'
|
||||||
>;
|
>;
|
||||||
|
|
||||||
interface AppThunkOptions<Arg> {
|
interface AppThunkOptions<Arg> {
|
||||||
@@ -60,7 +60,7 @@ type AppThunk<Arg = void, Returned = void> = (
|
|||||||
|
|
||||||
type AppThunkCreator<Arg = void, Returned = void, ExtraArg = unknown> = (
|
type AppThunkCreator<Arg = void, Returned = void, ExtraArg = unknown> = (
|
||||||
arg: Arg,
|
arg: Arg,
|
||||||
api: AppThunkApi,
|
api: Pick<AppThunkApi, 'getState' | 'dispatch'>,
|
||||||
extra?: ExtraArg,
|
extra?: ExtraArg,
|
||||||
) => Returned;
|
) => Returned;
|
||||||
|
|
||||||
@@ -143,10 +143,10 @@ export function createAsyncThunk<Arg = void, Returned = void>(
|
|||||||
name,
|
name,
|
||||||
async (
|
async (
|
||||||
arg: Arg,
|
arg: Arg,
|
||||||
{ getState, dispatch, fulfillWithValue, rejectWithValue },
|
{ getState, dispatch, requestId, fulfillWithValue, rejectWithValue },
|
||||||
) => {
|
) => {
|
||||||
try {
|
try {
|
||||||
const result = await creator(arg, { dispatch, getState });
|
const result = await creator(arg, { dispatch, getState, requestId });
|
||||||
|
|
||||||
return fulfillWithValue(result, {
|
return fulfillWithValue(result, {
|
||||||
useLoadingBar: options.useLoadingBar,
|
useLoadingBar: options.useLoadingBar,
|
||||||
@@ -280,10 +280,11 @@ export function createDataLoadingThunk<
|
|||||||
|
|
||||||
return createAsyncThunk<Args, Returned>(
|
return createAsyncThunk<Args, Returned>(
|
||||||
name,
|
name,
|
||||||
async (arg, { getState, dispatch }) => {
|
async (arg, { getState, dispatch, requestId }) => {
|
||||||
const data = await loadData(arg, {
|
const data = await loadData(arg, {
|
||||||
dispatch,
|
dispatch,
|
||||||
getState,
|
getState,
|
||||||
|
requestId,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!onData) return data as Returned;
|
if (!onData) return data as Returned;
|
||||||
@@ -291,6 +292,7 @@ export function createDataLoadingThunk<
|
|||||||
const result = await onData(data, {
|
const result = await onData(data, {
|
||||||
dispatch,
|
dispatch,
|
||||||
getState,
|
getState,
|
||||||
|
requestId,
|
||||||
discardLoadData: discardLoadDataInPayload,
|
discardLoadData: discardLoadDataInPayload,
|
||||||
actionArg: arg,
|
actionArg: arg,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1325,6 +1325,10 @@ a.sparkline {
|
|||||||
line-height: 1;
|
line-height: 1;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
animation: skeleton 1.2s ease-in-out infinite;
|
animation: skeleton 1.2s ease-in-out infinite;
|
||||||
|
|
||||||
|
.reduce-motion & {
|
||||||
|
animation: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes skeleton {
|
@keyframes skeleton {
|
||||||
|
|||||||
@@ -5743,6 +5743,34 @@ a.status-card {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.visibility-modal {
|
||||||
|
&__quote-warning {
|
||||||
|
color: var(--nested-card-text);
|
||||||
|
background:
|
||||||
|
/* This is a bit of a silly hack for layering two background colours
|
||||||
|
* since --nested-card-background is too transparent for a tooltip */
|
||||||
|
linear-gradient(
|
||||||
|
var(--nested-card-background),
|
||||||
|
var(--nested-card-background)
|
||||||
|
),
|
||||||
|
linear-gradient(var(--background-color), var(--background-color));
|
||||||
|
border: var(--nested-card-border);
|
||||||
|
padding: 16px;
|
||||||
|
border-radius: 4px;
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-weight: 500;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
color: $darker-text-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
font-size: 0.8em;
|
||||||
|
color: $dark-text-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.visibility-dropdown {
|
.visibility-dropdown {
|
||||||
&__overlay[data-popper-placement] {
|
&__overlay[data-popper-placement] {
|
||||||
z-index: 9999;
|
z-index: 9999;
|
||||||
|
|||||||
@@ -102,6 +102,7 @@ class Form::AdminSettings
|
|||||||
DOMAIN_BLOCK_AUDIENCES = %w(disabled users all).freeze
|
DOMAIN_BLOCK_AUDIENCES = %w(disabled users all).freeze
|
||||||
REGISTRATION_MODES = %w(open approved none).freeze
|
REGISTRATION_MODES = %w(open approved none).freeze
|
||||||
FEED_ACCESS_MODES = %w(public authenticated disabled).freeze
|
FEED_ACCESS_MODES = %w(public authenticated disabled).freeze
|
||||||
|
ALTERNATE_FEED_ACCESS_MODES = %w(public authenticated).freeze
|
||||||
LANDING_PAGE = %w(trends about local_feed).freeze
|
LANDING_PAGE = %w(trends about local_feed).freeze
|
||||||
|
|
||||||
attr_accessor(*KEYS)
|
attr_accessor(*KEYS)
|
||||||
@@ -114,7 +115,7 @@ class Form::AdminSettings
|
|||||||
validates :show_domain_blocks_rationale, inclusion: { in: DOMAIN_BLOCK_AUDIENCES }, if: -> { defined?(@show_domain_blocks_rationale) }
|
validates :show_domain_blocks_rationale, inclusion: { in: DOMAIN_BLOCK_AUDIENCES }, if: -> { defined?(@show_domain_blocks_rationale) }
|
||||||
validates :local_live_feed_access, inclusion: { in: FEED_ACCESS_MODES }, if: -> { defined?(@local_live_feed_access) }
|
validates :local_live_feed_access, inclusion: { in: FEED_ACCESS_MODES }, if: -> { defined?(@local_live_feed_access) }
|
||||||
validates :remote_live_feed_access, inclusion: { in: FEED_ACCESS_MODES }, if: -> { defined?(@remote_live_feed_access) }
|
validates :remote_live_feed_access, inclusion: { in: FEED_ACCESS_MODES }, if: -> { defined?(@remote_live_feed_access) }
|
||||||
validates :local_topic_feed_access, inclusion: { in: FEED_ACCESS_MODES }, if: -> { defined?(@local_topic_feed_access) }
|
validates :local_topic_feed_access, inclusion: { in: ALTERNATE_FEED_ACCESS_MODES }, if: -> { defined?(@local_topic_feed_access) }
|
||||||
validates :remote_topic_feed_access, inclusion: { in: FEED_ACCESS_MODES }, if: -> { defined?(@remote_topic_feed_access) }
|
validates :remote_topic_feed_access, inclusion: { in: FEED_ACCESS_MODES }, if: -> { defined?(@remote_topic_feed_access) }
|
||||||
validates :media_cache_retention_period, :content_cache_retention_period, :backups_retention_period, numericality: { only_integer: true }, allow_blank: true, if: -> { defined?(@media_cache_retention_period) || defined?(@content_cache_retention_period) || defined?(@backups_retention_period) }
|
validates :media_cache_retention_period, :content_cache_retention_period, :backups_retention_period, numericality: { only_integer: true }, allow_blank: true, if: -> { defined?(@media_cache_retention_period) || defined?(@content_cache_retention_period) || defined?(@backups_retention_period) }
|
||||||
validates :min_age, numericality: { only_integer: true }, allow_blank: true, if: -> { defined?(@min_age) }
|
validates :min_age, numericality: { only_integer: true }, allow_blank: true, if: -> { defined?(@min_age) }
|
||||||
|
|||||||
@@ -96,6 +96,7 @@ class PostStatusService < BaseService
|
|||||||
@status = @account.statuses.new(status_attributes)
|
@status = @account.statuses.new(status_attributes)
|
||||||
process_mentions_service.call(@status, save_records: false)
|
process_mentions_service.call(@status, save_records: false)
|
||||||
safeguard_mentions!(@status)
|
safeguard_mentions!(@status)
|
||||||
|
safeguard_private_mention_quote!(@status)
|
||||||
attach_quote!(@status)
|
attach_quote!(@status)
|
||||||
|
|
||||||
antispam = Antispam.new(@status)
|
antispam = Antispam.new(@status)
|
||||||
@@ -108,6 +109,16 @@ class PostStatusService < BaseService
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def safeguard_private_mention_quote!(status)
|
||||||
|
return if @quoted_status.nil? || @visibility.to_sym != :direct
|
||||||
|
|
||||||
|
# The mentions array test here is awkward because the relationship is not persisted at this time
|
||||||
|
return if @quoted_status.account_id == @account.id || status.mentions.to_a.any? { |mention| mention.account_id == @quoted_status.account_id && !mention.silent }
|
||||||
|
|
||||||
|
status.errors.add(:base, I18n.t('statuses.errors.quoted_user_not_mentioned'))
|
||||||
|
raise ActiveRecord::RecordInvalid, status
|
||||||
|
end
|
||||||
|
|
||||||
def attach_quote!(status)
|
def attach_quote!(status)
|
||||||
return if @quoted_status.nil?
|
return if @quoted_status.nil?
|
||||||
|
|
||||||
@@ -130,6 +141,7 @@ class PostStatusService < BaseService
|
|||||||
|
|
||||||
def schedule_status!
|
def schedule_status!
|
||||||
status_for_validation = @account.statuses.build(status_attributes)
|
status_for_validation = @account.statuses.build(status_attributes)
|
||||||
|
safeguard_private_mention_quote!(status_for_validation)
|
||||||
|
|
||||||
antispam = Antispam.new(status_for_validation)
|
antispam = Antispam.new(status_for_validation)
|
||||||
antispam.local_preflight_check!
|
antispam.local_preflight_check!
|
||||||
|
|||||||
@@ -46,7 +46,7 @@
|
|||||||
.fields-row
|
.fields-row
|
||||||
.fields-row__column.fields-row__column-6.fields-group
|
.fields-row__column.fields-row__column-6.fields-group
|
||||||
= f.input :local_topic_feed_access,
|
= f.input :local_topic_feed_access,
|
||||||
collection: f.object.class::FEED_ACCESS_MODES,
|
collection: f.object.class::ALTERNATE_FEED_ACCESS_MODES,
|
||||||
include_blank: false,
|
include_blank: false,
|
||||||
label_method: ->(mode) { I18n.t("admin.settings.feed_access.modes.#{mode}") },
|
label_method: ->(mode) { I18n.t("admin.settings.feed_access.modes.#{mode}") },
|
||||||
wrapper: :with_label
|
wrapper: :with_label
|
||||||
|
|||||||
@@ -2,8 +2,7 @@
|
|||||||
= t('privacy.title')
|
= t('privacy.title')
|
||||||
|
|
||||||
- content_for :heading do
|
- content_for :heading do
|
||||||
%h2= t('settings.profile')
|
%h2= t('privacy.title')
|
||||||
= render partial: 'settings/shared/profile_navigation'
|
|
||||||
|
|
||||||
= simple_form_for @account, url: settings_privacy_path do |f|
|
= simple_form_for @account, url: settings_privacy_path do |f|
|
||||||
= render 'shared/error_messages', object: @account
|
= render 'shared/error_messages', object: @account
|
||||||
|
|||||||
@@ -2,6 +2,5 @@
|
|||||||
= render_navigation renderer: :links do |primary|
|
= render_navigation renderer: :links do |primary|
|
||||||
:ruby
|
:ruby
|
||||||
primary.item :edit_profile, safe_join([material_symbol('person'), t('settings.edit_profile')]), settings_profile_path
|
primary.item :edit_profile, safe_join([material_symbol('person'), t('settings.edit_profile')]), settings_profile_path
|
||||||
primary.item :privacy_reach, safe_join([material_symbol('lock'), t('privacy.title')]), settings_privacy_path
|
|
||||||
primary.item :verification, safe_join([material_symbol('check'), t('verification.verification')]), settings_verification_path
|
primary.item :verification, safe_join([material_symbol('check'), t('verification.verification')]), settings_verification_path
|
||||||
primary.item :featured_tags, safe_join([material_symbol('tag'), t('settings.featured_tags')]), settings_featured_tags_path
|
primary.item :featured_tags, safe_join([material_symbol('tag'), t('settings.featured_tags')]), settings_featured_tags_path
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ class ActivityPub::RefetchAndVerifyQuoteWorker
|
|||||||
include ExponentialBackoff
|
include ExponentialBackoff
|
||||||
include JsonLdHelper
|
include JsonLdHelper
|
||||||
|
|
||||||
sidekiq_options queue: 'pull', retry: 3
|
sidekiq_options queue: 'pull', retry: 5
|
||||||
|
|
||||||
def perform(quote_id, quoted_uri, options = {})
|
def perform(quote_id, quoted_uri, options = {})
|
||||||
quote = Quote.find(quote_id)
|
quote = Quote.find(quote_id)
|
||||||
|
|||||||
@@ -1930,6 +1930,7 @@ en:
|
|||||||
errors:
|
errors:
|
||||||
in_reply_not_found: The post you are trying to reply to does not appear to exist.
|
in_reply_not_found: The post you are trying to reply to does not appear to exist.
|
||||||
quoted_status_not_found: The post you are trying to quote does not appear to exist.
|
quoted_status_not_found: The post you are trying to quote does not appear to exist.
|
||||||
|
quoted_user_not_mentioned: Cannot quote a non-mentioned user in a Private Mention post.
|
||||||
over_character_limit: character limit of %{max} exceeded
|
over_character_limit: character limit of %{max} exceeded
|
||||||
pin_errors:
|
pin_errors:
|
||||||
direct: Posts that are only visible to mentioned users cannot be pinned
|
direct: Posts that are only visible to mentioned users cannot be pinned
|
||||||
|
|||||||
@@ -12,7 +12,8 @@ SimpleNavigation::Configuration.run do |navigation|
|
|||||||
if: -> { Rails.configuration.x.mastodon.software_update_url.present? && current_user.can?(:view_devops) && SoftwareUpdate.urgent_pending? },
|
if: -> { Rails.configuration.x.mastodon.software_update_url.present? && current_user.can?(:view_devops) && SoftwareUpdate.urgent_pending? },
|
||||||
html: { class: 'warning' }
|
html: { class: 'warning' }
|
||||||
|
|
||||||
n.item :profile, safe_join([material_symbol('person'), t('settings.profile')]), settings_profile_path, if: -> { current_user.functional? && !self_destruct }, highlights_on: %r{/settings/profile|/settings/featured_tags|/settings/verification|/settings/privacy}
|
n.item :profile, safe_join([material_symbol('person'), t('settings.profile')]), settings_profile_path, if: -> { current_user.functional? && !self_destruct }, highlights_on: %r{/settings/profile|/settings/featured_tags|/settings/verification}
|
||||||
|
n.item :privacy, safe_join([material_symbol('globe'), t('privacy.title')]), settings_privacy_path, if: -> { current_user.functional? && !self_destruct }, highlights_on: %r{/settings/privacy}
|
||||||
|
|
||||||
n.item :preferences, safe_join([material_symbol('settings'), t('settings.preferences')]), settings_preferences_path, if: -> { current_user.functional? && !self_destruct } do |s|
|
n.item :preferences, safe_join([material_symbol('settings'), t('settings.preferences')]), settings_preferences_path, if: -> { current_user.functional? && !self_destruct } do |s|
|
||||||
s.item :appearance, safe_join([material_symbol('computer'), t('settings.appearance')]), settings_preferences_appearance_path
|
s.item :appearance, safe_join([material_symbol('computer'), t('settings.appearance')]), settings_preferences_appearance_path
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ module Mastodon
|
|||||||
end
|
end
|
||||||
|
|
||||||
def default_prerelease
|
def default_prerelease
|
||||||
'rc.2'
|
'rc.3'
|
||||||
end
|
end
|
||||||
|
|
||||||
def prerelease
|
def prerelease
|
||||||
|
|||||||
@@ -48,7 +48,7 @@
|
|||||||
"@gamestdio/websocket": "^0.3.2",
|
"@gamestdio/websocket": "^0.3.2",
|
||||||
"@github/webauthn-json": "^2.1.1",
|
"@github/webauthn-json": "^2.1.1",
|
||||||
"@optimize-lodash/rollup-plugin": "^5.0.2",
|
"@optimize-lodash/rollup-plugin": "^5.0.2",
|
||||||
"@rails/ujs": "7.1.502",
|
"@rails/ujs": "7.1.600",
|
||||||
"@react-spring/web": "^9.7.5",
|
"@react-spring/web": "^9.7.5",
|
||||||
"@reduxjs/toolkit": "^2.0.1",
|
"@reduxjs/toolkit": "^2.0.1",
|
||||||
"@use-gesture/react": "^10.3.1",
|
"@use-gesture/react": "^10.3.1",
|
||||||
@@ -194,6 +194,7 @@
|
|||||||
"stylelint-config-standard-scss": "^16.0.0",
|
"stylelint-config-standard-scss": "^16.0.0",
|
||||||
"typescript": "~5.9.0",
|
"typescript": "~5.9.0",
|
||||||
"typescript-eslint": "^8.45.0",
|
"typescript-eslint": "^8.45.0",
|
||||||
|
"typescript-plugin-css-modules": "^5.2.0",
|
||||||
"vitest": "^3.2.4"
|
"vitest": "^3.2.4"
|
||||||
},
|
},
|
||||||
"resolutions": {
|
"resolutions": {
|
||||||
|
|||||||
@@ -228,7 +228,7 @@ RSpec.describe '/api/v1/statuses' do
|
|||||||
end
|
end
|
||||||
|
|
||||||
context 'with a self-quote post' do
|
context 'with a self-quote post' do
|
||||||
let(:quoted_status) { Fabricate(:status, account: user.account) }
|
let!(:quoted_status) { Fabricate(:status, account: user.account) }
|
||||||
let(:params) do
|
let(:params) do
|
||||||
{
|
{
|
||||||
status: 'Hello world, this is a self-quote',
|
status: 'Hello world, this is a self-quote',
|
||||||
@@ -237,7 +237,48 @@ RSpec.describe '/api/v1/statuses' do
|
|||||||
end
|
end
|
||||||
|
|
||||||
it 'returns a quote post, as well as rate limit headers', :aggregate_failures do
|
it 'returns a quote post, as well as rate limit headers', :aggregate_failures do
|
||||||
subject
|
expect { subject }.to change(user.account.statuses, :count).by(1)
|
||||||
|
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
expect(response.content_type)
|
||||||
|
.to start_with('application/json')
|
||||||
|
expect(response.parsed_body[:quote]).to be_present
|
||||||
|
expect(response.headers['X-RateLimit-Limit']).to eq RateLimiter::FAMILIES[:statuses][:limit].to_s
|
||||||
|
expect(response.headers['X-RateLimit-Remaining']).to eq (RateLimiter::FAMILIES[:statuses][:limit] - 1).to_s
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with a quote to a non-mentioned user in a Private Mention' do
|
||||||
|
let!(:quoted_status) { Fabricate(:status, quote_approval_policy: Status::QUOTE_APPROVAL_POLICY_FLAGS[:public] << 16) }
|
||||||
|
let(:params) do
|
||||||
|
{
|
||||||
|
status: 'Hello, this is a quote',
|
||||||
|
quoted_status_id: quoted_status.id,
|
||||||
|
visibility: :direct,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns an error and does not create a post', :aggregate_failures do
|
||||||
|
expect { subject }.to_not change(user.account.statuses, :count)
|
||||||
|
|
||||||
|
expect(response).to have_http_status(422)
|
||||||
|
expect(response.content_type)
|
||||||
|
.to start_with('application/json')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with a quote to a mentioned user in a Private Mention' do
|
||||||
|
let!(:quoted_status) { Fabricate(:status, quote_approval_policy: Status::QUOTE_APPROVAL_POLICY_FLAGS[:public] << 16) }
|
||||||
|
let(:params) do
|
||||||
|
{
|
||||||
|
status: "Hello @#{quoted_status.account.acct}, this is a quote",
|
||||||
|
quoted_status_id: quoted_status.id,
|
||||||
|
visibility: :direct,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns a quote post, as well as rate limit headers', :aggregate_failures do
|
||||||
|
expect { subject }.to change(user.account.statuses, :count).by(1)
|
||||||
|
|
||||||
expect(response).to have_http_status(200)
|
expect(response).to have_http_status(200)
|
||||||
expect(response.content_type)
|
expect(response.content_type)
|
||||||
|
|||||||
@@ -26,7 +26,8 @@
|
|||||||
"flavours/glitch/*": ["app/javascript/flavours/glitch/*"],
|
"flavours/glitch/*": ["app/javascript/flavours/glitch/*"],
|
||||||
"images/*": ["app/javascript/images/*"],
|
"images/*": ["app/javascript/images/*"],
|
||||||
"styles/*": ["app/javascript/styles/*"]
|
"styles/*": ["app/javascript/styles/*"]
|
||||||
}
|
},
|
||||||
|
"plugins": [{ "name": "typescript-plugin-css-modules" }]
|
||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
"vite.config.mts",
|
"vite.config.mts",
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ import { MastodonAssetsManifest } from './config/vite/plugin-assets-manifest';
|
|||||||
|
|
||||||
const jsRoot = path.resolve(__dirname, 'app/javascript');
|
const jsRoot = path.resolve(__dirname, 'app/javascript');
|
||||||
|
|
||||||
|
const cssAliasClasses: ReadonlyArray<string> = ['components', 'features'];
|
||||||
|
|
||||||
export const config: UserConfigFnPromise = async ({ mode, command }) => {
|
export const config: UserConfigFnPromise = async ({ mode, command }) => {
|
||||||
const isProdBuild = mode === 'production' && command === 'build';
|
const isProdBuild = mode === 'production' && command === 'build';
|
||||||
|
|
||||||
@@ -49,6 +51,45 @@ export const config: UserConfigFnPromise = async ({ mode, command }) => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
css: {
|
css: {
|
||||||
|
modules: {
|
||||||
|
generateScopedName(name, filename) {
|
||||||
|
let prefix = '';
|
||||||
|
|
||||||
|
// Use the top two segments of the path as the prefix.
|
||||||
|
const [parentDirName, dirName] = path
|
||||||
|
.dirname(filename)
|
||||||
|
.split(path.sep)
|
||||||
|
.slice(-2)
|
||||||
|
.map((dir) => dir.toLowerCase());
|
||||||
|
|
||||||
|
// If the parent directory is in the cssAliasClasses list, use
|
||||||
|
// the first four letters of it as the prefix, otherwise use the full name.
|
||||||
|
if (parentDirName) {
|
||||||
|
if (cssAliasClasses.includes(parentDirName)) {
|
||||||
|
prefix = parentDirName.slice(0, 4);
|
||||||
|
} else {
|
||||||
|
prefix = parentDirName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we have a directory name, append it to the prefix.
|
||||||
|
if (dirName) {
|
||||||
|
prefix = `${prefix}_${dirName}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the file is not styles.module.scss or style.module.scss,
|
||||||
|
// append the file base name to the prefix.
|
||||||
|
const baseName = path.basename(
|
||||||
|
filename,
|
||||||
|
`.module${path.extname(filename)}`,
|
||||||
|
);
|
||||||
|
if (baseName !== 'styles' && baseName !== 'style') {
|
||||||
|
prefix = `${prefix}_${baseName}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return `_${prefix}__${name}`;
|
||||||
|
},
|
||||||
|
},
|
||||||
postcss: {
|
postcss: {
|
||||||
plugins: [
|
plugins: [
|
||||||
postcssPresetEnv({
|
postcssPresetEnv({
|
||||||
|
|||||||
332
yarn.lock
332
yarn.lock
@@ -19,6 +19,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"@adobe/css-tools@npm:~4.3.1":
|
||||||
|
version: 4.3.3
|
||||||
|
resolution: "@adobe/css-tools@npm:4.3.3"
|
||||||
|
checksum: 10c0/e76e712df713964b87cdf2aca1f0477f19bebd845484d5fcba726d3ec7782366e2f26ec8cb2dcfaf47081a5c891987d8a9f5c3f30d11e1eb3c1848adc27fcb24
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"@ampproject/remapping@npm:^2.3.0":
|
"@ampproject/remapping@npm:^2.3.0":
|
||||||
version: 2.3.0
|
version: 2.3.0
|
||||||
resolution: "@ampproject/remapping@npm:2.3.0"
|
resolution: "@ampproject/remapping@npm:2.3.0"
|
||||||
@@ -2795,7 +2802,7 @@ __metadata:
|
|||||||
"@gamestdio/websocket": "npm:^0.3.2"
|
"@gamestdio/websocket": "npm:^0.3.2"
|
||||||
"@github/webauthn-json": "npm:^2.1.1"
|
"@github/webauthn-json": "npm:^2.1.1"
|
||||||
"@optimize-lodash/rollup-plugin": "npm:^5.0.2"
|
"@optimize-lodash/rollup-plugin": "npm:^5.0.2"
|
||||||
"@rails/ujs": "npm:7.1.502"
|
"@rails/ujs": "npm:7.1.600"
|
||||||
"@react-spring/web": "npm:^9.7.5"
|
"@react-spring/web": "npm:^9.7.5"
|
||||||
"@reduxjs/toolkit": "npm:^2.0.1"
|
"@reduxjs/toolkit": "npm:^2.0.1"
|
||||||
"@storybook/addon-a11y": "npm:^9.1.1"
|
"@storybook/addon-a11y": "npm:^9.1.1"
|
||||||
@@ -2925,6 +2932,7 @@ __metadata:
|
|||||||
twitter-text: "npm:3.1.0"
|
twitter-text: "npm:3.1.0"
|
||||||
typescript: "npm:~5.9.0"
|
typescript: "npm:~5.9.0"
|
||||||
typescript-eslint: "npm:^8.45.0"
|
typescript-eslint: "npm:^8.45.0"
|
||||||
|
typescript-plugin-css-modules: "npm:^5.2.0"
|
||||||
use-debounce: "npm:^10.0.0"
|
use-debounce: "npm:^10.0.0"
|
||||||
vite: "npm:^7.1.1"
|
vite: "npm:^7.1.1"
|
||||||
vite-plugin-manifest-sri: "npm:^0.2.0"
|
vite-plugin-manifest-sri: "npm:^0.2.0"
|
||||||
@@ -3294,10 +3302,10 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@rails/ujs@npm:7.1.502":
|
"@rails/ujs@npm:7.1.600":
|
||||||
version: 7.1.502
|
version: 7.1.600
|
||||||
resolution: "@rails/ujs@npm:7.1.502"
|
resolution: "@rails/ujs@npm:7.1.600"
|
||||||
checksum: 10c0/79b46e8abd03e3fc633d93cc4e4c23838c628b775802fb38c2ce68b0e609ce287a67b81db112a93cc78c07ec82ca3b4cf87e74eb556d35148ce5f64c8be9201f
|
checksum: 10c0/0ccaa68a08fbc7b084ab89a1fe49520a5cba6d99f4b0feaf0cb3d00334c59d8d798932d7e49b84aa388875d039ea1e17eb115ed96a80ad157e408a13eceef53e
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
@@ -4346,6 +4354,24 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"@types/postcss-modules-local-by-default@npm:^4.0.2":
|
||||||
|
version: 4.0.2
|
||||||
|
resolution: "@types/postcss-modules-local-by-default@npm:4.0.2"
|
||||||
|
dependencies:
|
||||||
|
postcss: "npm:^8.0.0"
|
||||||
|
checksum: 10c0/af13e40673abf96f1427c467bc9d96986fc0fb702f65ef702de05f70e51af2212bc0bdf177bfd817e418f2238bf210fdee3541dd2d939fde9a4df5f8972ad716
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"@types/postcss-modules-scope@npm:^3.0.4":
|
||||||
|
version: 3.0.4
|
||||||
|
resolution: "@types/postcss-modules-scope@npm:3.0.4"
|
||||||
|
dependencies:
|
||||||
|
postcss: "npm:^8.0.0"
|
||||||
|
checksum: 10c0/6364674e429143fd686e0238d071377cf9ae1780a77f99e99292a06adc93057609146aaf55c09310ae99526c37e56be5a8a843086c0ff95513bd34c6bc4c7480
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"@types/prop-types@npm:*, @types/prop-types@npm:^15.7.5":
|
"@types/prop-types@npm:*, @types/prop-types@npm:^15.7.5":
|
||||||
version: 15.7.15
|
version: 15.7.15
|
||||||
resolution: "@types/prop-types@npm:15.7.15"
|
resolution: "@types/prop-types@npm:15.7.15"
|
||||||
@@ -6116,6 +6142,15 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"copy-anything@npm:^2.0.1":
|
||||||
|
version: 2.0.6
|
||||||
|
resolution: "copy-anything@npm:2.0.6"
|
||||||
|
dependencies:
|
||||||
|
is-what: "npm:^3.14.1"
|
||||||
|
checksum: 10c0/2702998a8cc015f9917385b7f16b0d85f1f6e5e2fd34d99f14df584838f492f49aa0c390d973684c687e895c5c58d08b308a0400ac3e1e3d6fa1e5884a5402ad
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"core-js-compat@npm:^3.43.0":
|
"core-js-compat@npm:^3.43.0":
|
||||||
version: 3.44.0
|
version: 3.44.0
|
||||||
resolution: "core-js-compat@npm:3.44.0"
|
resolution: "core-js-compat@npm:3.44.0"
|
||||||
@@ -6590,6 +6625,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"dotenv@npm:^16.4.2":
|
||||||
|
version: 16.6.1
|
||||||
|
resolution: "dotenv@npm:16.6.1"
|
||||||
|
checksum: 10c0/15ce56608326ea0d1d9414a5c8ee6dcf0fffc79d2c16422b4ac2268e7e2d76ff5a572d37ffe747c377de12005f14b3cc22361e79fc7f1061cce81f77d2c973dc
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"dunder-proto@npm:^1.0.0, dunder-proto@npm:^1.0.1":
|
"dunder-proto@npm:^1.0.0, dunder-proto@npm:^1.0.1":
|
||||||
version: 1.0.1
|
version: 1.0.1
|
||||||
resolution: "dunder-proto@npm:1.0.1"
|
resolution: "dunder-proto@npm:1.0.1"
|
||||||
@@ -6757,6 +6799,17 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"errno@npm:^0.1.1":
|
||||||
|
version: 0.1.8
|
||||||
|
resolution: "errno@npm:0.1.8"
|
||||||
|
dependencies:
|
||||||
|
prr: "npm:~1.0.1"
|
||||||
|
bin:
|
||||||
|
errno: cli.js
|
||||||
|
checksum: 10c0/83758951967ec57bf00b5f5b7dc797e6d65a6171e57ea57adcf1bd1a0b477fd9b5b35fae5be1ff18f4090ed156bce1db749fe7e317aac19d485a5d150f6a4936
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"error-ex@npm:^1.3.1":
|
"error-ex@npm:^1.3.1":
|
||||||
version: 1.3.2
|
version: 1.3.2
|
||||||
resolution: "error-ex@npm:1.3.2"
|
resolution: "error-ex@npm:1.3.2"
|
||||||
@@ -8053,7 +8106,7 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.6":
|
"graceful-fs@npm:^4.1.2, graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.6":
|
||||||
version: 4.2.11
|
version: 4.2.11
|
||||||
resolution: "graceful-fs@npm:4.2.11"
|
resolution: "graceful-fs@npm:4.2.11"
|
||||||
checksum: 10c0/386d011a553e02bc594ac2ca0bd6d9e4c22d7fa8cfbfc448a6d148c59ea881b092db9dbe3547ae4b88e55f1b01f7c4a2ecc53b310c042793e63aa44cf6c257f2
|
checksum: 10c0/386d011a553e02bc594ac2ca0bd6d9e4c22d7fa8cfbfc448a6d148c59ea881b092db9dbe3547ae4b88e55f1b01f7c4a2ecc53b310c042793e63aa44cf6c257f2
|
||||||
@@ -8270,7 +8323,7 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"iconv-lite@npm:0.6.3, iconv-lite@npm:^0.6.2":
|
"iconv-lite@npm:0.6.3, iconv-lite@npm:^0.6.2, iconv-lite@npm:^0.6.3":
|
||||||
version: 0.6.3
|
version: 0.6.3
|
||||||
resolution: "iconv-lite@npm:0.6.3"
|
resolution: "iconv-lite@npm:0.6.3"
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -8279,6 +8332,15 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"icss-utils@npm:^5.0.0, icss-utils@npm:^5.1.0":
|
||||||
|
version: 5.1.0
|
||||||
|
resolution: "icss-utils@npm:5.1.0"
|
||||||
|
peerDependencies:
|
||||||
|
postcss: ^8.1.0
|
||||||
|
checksum: 10c0/39c92936fabd23169c8611d2b5cc39e39d10b19b0d223352f20a7579f75b39d5f786114a6b8fc62bee8c5fed59ba9e0d38f7219a4db383e324fb3061664b043d
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"idb-keyval@npm:^6.2.0":
|
"idb-keyval@npm:^6.2.0":
|
||||||
version: 6.2.1
|
version: 6.2.1
|
||||||
resolution: "idb-keyval@npm:6.2.1"
|
resolution: "idb-keyval@npm:6.2.1"
|
||||||
@@ -8314,6 +8376,15 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"image-size@npm:~0.5.0":
|
||||||
|
version: 0.5.5
|
||||||
|
resolution: "image-size@npm:0.5.5"
|
||||||
|
bin:
|
||||||
|
image-size: bin/image-size.js
|
||||||
|
checksum: 10c0/655204163af06732f483a9fe7cce9dff4a29b7b2e88f5c957a5852e8143fa750f5e54b1955a2ca83de99c5220dbd680002d0d4e09140b01433520f4d5a0b1f4c
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"immer@npm:^10.0.3":
|
"immer@npm:^10.0.3":
|
||||||
version: 10.0.3
|
version: 10.0.3
|
||||||
resolution: "immer@npm:10.0.3"
|
resolution: "immer@npm:10.0.3"
|
||||||
@@ -8791,6 +8862,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"is-what@npm:^3.14.1":
|
||||||
|
version: 3.14.1
|
||||||
|
resolution: "is-what@npm:3.14.1"
|
||||||
|
checksum: 10c0/4b770b85454c877b6929a84fd47c318e1f8c2ff70fd72fd625bc3fde8e0c18a6e57345b6e7aa1ee9fbd1c608d27cfe885df473036c5c2e40cd2187250804a2c7
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"is-wsl@npm:^2.2.0":
|
"is-wsl@npm:^2.2.0":
|
||||||
version: 2.2.0
|
version: 2.2.0
|
||||||
resolution: "is-wsl@npm:2.2.0"
|
resolution: "is-wsl@npm:2.2.0"
|
||||||
@@ -9181,6 +9259,41 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"less@npm:^4.2.0":
|
||||||
|
version: 4.4.2
|
||||||
|
resolution: "less@npm:4.4.2"
|
||||||
|
dependencies:
|
||||||
|
copy-anything: "npm:^2.0.1"
|
||||||
|
errno: "npm:^0.1.1"
|
||||||
|
graceful-fs: "npm:^4.1.2"
|
||||||
|
image-size: "npm:~0.5.0"
|
||||||
|
make-dir: "npm:^2.1.0"
|
||||||
|
mime: "npm:^1.4.1"
|
||||||
|
needle: "npm:^3.1.0"
|
||||||
|
parse-node-version: "npm:^1.0.1"
|
||||||
|
source-map: "npm:~0.6.0"
|
||||||
|
tslib: "npm:^2.3.0"
|
||||||
|
dependenciesMeta:
|
||||||
|
errno:
|
||||||
|
optional: true
|
||||||
|
graceful-fs:
|
||||||
|
optional: true
|
||||||
|
image-size:
|
||||||
|
optional: true
|
||||||
|
make-dir:
|
||||||
|
optional: true
|
||||||
|
mime:
|
||||||
|
optional: true
|
||||||
|
needle:
|
||||||
|
optional: true
|
||||||
|
source-map:
|
||||||
|
optional: true
|
||||||
|
bin:
|
||||||
|
lessc: bin/lessc
|
||||||
|
checksum: 10c0/f8b796e45ef171adc390b5250f3018922cd046c256181dd9d4cbcbbdc5d6de7cb88c8327741c10eff7ff76421cd826fd95a664ea1b88fbf6f31742428d4a2dab
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"leven@npm:^3.1.0":
|
"leven@npm:^3.1.0":
|
||||||
version: 3.1.0
|
version: 3.1.0
|
||||||
resolution: "leven@npm:3.1.0"
|
resolution: "leven@npm:3.1.0"
|
||||||
@@ -9198,6 +9311,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"lilconfig@npm:^2.0.5":
|
||||||
|
version: 2.1.0
|
||||||
|
resolution: "lilconfig@npm:2.1.0"
|
||||||
|
checksum: 10c0/64645641aa8d274c99338e130554abd6a0190533c0d9eb2ce7ebfaf2e05c7d9961f3ffe2bfa39efd3b60c521ba3dd24fa236fe2775fc38501bf82bf49d4678b8
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"lines-and-columns@npm:^1.1.6":
|
"lines-and-columns@npm:^1.1.6":
|
||||||
version: 1.2.4
|
version: 1.2.4
|
||||||
resolution: "lines-and-columns@npm:1.2.4"
|
resolution: "lines-and-columns@npm:1.2.4"
|
||||||
@@ -9254,6 +9374,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"lodash.camelcase@npm:^4.3.0":
|
||||||
|
version: 4.3.0
|
||||||
|
resolution: "lodash.camelcase@npm:4.3.0"
|
||||||
|
checksum: 10c0/fcba15d21a458076dd309fce6b1b4bf611d84a0ec252cb92447c948c533ac250b95d2e00955801ebc367e5af5ed288b996d75d37d2035260a937008e14eaf432
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"lodash.debounce@npm:^4.0.8":
|
"lodash.debounce@npm:^4.0.8":
|
||||||
version: 4.0.8
|
version: 4.0.8
|
||||||
resolution: "lodash.debounce@npm:4.0.8"
|
resolution: "lodash.debounce@npm:4.0.8"
|
||||||
@@ -9404,6 +9531,16 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"make-dir@npm:^2.1.0":
|
||||||
|
version: 2.1.0
|
||||||
|
resolution: "make-dir@npm:2.1.0"
|
||||||
|
dependencies:
|
||||||
|
pify: "npm:^4.0.1"
|
||||||
|
semver: "npm:^5.6.0"
|
||||||
|
checksum: 10c0/ada869944d866229819735bee5548944caef560d7a8536ecbc6536edca28c72add47cc4f6fc39c54fb25d06b58da1f8994cf7d9df7dadea047064749efc085d8
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"make-dir@npm:^4.0.0":
|
"make-dir@npm:^4.0.0":
|
||||||
version: 4.0.0
|
version: 4.0.0
|
||||||
resolution: "make-dir@npm:4.0.0"
|
resolution: "make-dir@npm:4.0.0"
|
||||||
@@ -9535,7 +9672,7 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"mime@npm:1.6.0":
|
"mime@npm:1.6.0, mime@npm:^1.4.1":
|
||||||
version: 1.6.0
|
version: 1.6.0
|
||||||
resolution: "mime@npm:1.6.0"
|
resolution: "mime@npm:1.6.0"
|
||||||
bin:
|
bin:
|
||||||
@@ -9782,6 +9919,18 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"needle@npm:^3.1.0":
|
||||||
|
version: 3.3.1
|
||||||
|
resolution: "needle@npm:3.3.1"
|
||||||
|
dependencies:
|
||||||
|
iconv-lite: "npm:^0.6.3"
|
||||||
|
sax: "npm:^1.2.4"
|
||||||
|
bin:
|
||||||
|
needle: bin/needle
|
||||||
|
checksum: 10c0/233b9315d47b735867d03e7a018fb665ee6cacf3a83b991b19538019cf42b538a3e85ca745c840b4c5e9a0ffdca76472f941363bf7c166214ae8cbc650fd4d39
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"negotiator@npm:0.6.3":
|
"negotiator@npm:0.6.3":
|
||||||
version: 0.6.3
|
version: 0.6.3
|
||||||
resolution: "negotiator@npm:0.6.3"
|
resolution: "negotiator@npm:0.6.3"
|
||||||
@@ -10156,6 +10305,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"parse-node-version@npm:^1.0.1":
|
||||||
|
version: 1.0.1
|
||||||
|
resolution: "parse-node-version@npm:1.0.1"
|
||||||
|
checksum: 10c0/999cd3d7da1425c2e182dce82b226c6dc842562d3ed79ec47f5c719c32a7f6c1a5352495b894fc25df164be7f2ede4224758255da9902ddef81f2b77ba46bb2c
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"parse-statements@npm:1.0.11":
|
"parse-statements@npm:1.0.11":
|
||||||
version: 1.0.11
|
version: 1.0.11
|
||||||
resolution: "parse-statements@npm:1.0.11"
|
resolution: "parse-statements@npm:1.0.11"
|
||||||
@@ -10386,6 +10542,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"pify@npm:^4.0.1":
|
||||||
|
version: 4.0.1
|
||||||
|
resolution: "pify@npm:4.0.1"
|
||||||
|
checksum: 10c0/6f9d404b0d47a965437403c9b90eca8bb2536407f03de165940e62e72c8c8b75adda5516c6b9b23675a5877cc0bcac6bdfb0ef0e39414cd2476d5495da40e7cf
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"pino-abstract-transport@npm:^2.0.0":
|
"pino-abstract-transport@npm:^2.0.0":
|
||||||
version: 2.0.0
|
version: 2.0.0
|
||||||
resolution: "pino-abstract-transport@npm:2.0.0"
|
resolution: "pino-abstract-transport@npm:2.0.0"
|
||||||
@@ -10684,6 +10847,24 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"postcss-load-config@npm:^3.1.4":
|
||||||
|
version: 3.1.4
|
||||||
|
resolution: "postcss-load-config@npm:3.1.4"
|
||||||
|
dependencies:
|
||||||
|
lilconfig: "npm:^2.0.5"
|
||||||
|
yaml: "npm:^1.10.2"
|
||||||
|
peerDependencies:
|
||||||
|
postcss: ">=8.0.9"
|
||||||
|
ts-node: ">=9.0.0"
|
||||||
|
peerDependenciesMeta:
|
||||||
|
postcss:
|
||||||
|
optional: true
|
||||||
|
ts-node:
|
||||||
|
optional: true
|
||||||
|
checksum: 10c0/7d2cc6695c2fc063e4538316d651a687fdb55e48db453ff699de916a6ee55ab68eac2b120c28a6b8ca7aa746a588888351b810a215b5cd090eabea62c5762ede
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"postcss-logical@npm:^8.1.0":
|
"postcss-logical@npm:^8.1.0":
|
||||||
version: 8.1.0
|
version: 8.1.0
|
||||||
resolution: "postcss-logical@npm:8.1.0"
|
resolution: "postcss-logical@npm:8.1.0"
|
||||||
@@ -10702,6 +10883,39 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"postcss-modules-extract-imports@npm:^3.0.0":
|
||||||
|
version: 3.1.0
|
||||||
|
resolution: "postcss-modules-extract-imports@npm:3.1.0"
|
||||||
|
peerDependencies:
|
||||||
|
postcss: ^8.1.0
|
||||||
|
checksum: 10c0/402084bcab376083c4b1b5111b48ec92974ef86066f366f0b2d5b2ac2b647d561066705ade4db89875a13cb175b33dd6af40d16d32b2ea5eaf8bac63bd2bf219
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"postcss-modules-local-by-default@npm:^4.0.4":
|
||||||
|
version: 4.2.0
|
||||||
|
resolution: "postcss-modules-local-by-default@npm:4.2.0"
|
||||||
|
dependencies:
|
||||||
|
icss-utils: "npm:^5.0.0"
|
||||||
|
postcss-selector-parser: "npm:^7.0.0"
|
||||||
|
postcss-value-parser: "npm:^4.1.0"
|
||||||
|
peerDependencies:
|
||||||
|
postcss: ^8.1.0
|
||||||
|
checksum: 10c0/b0b83feb2a4b61f5383979d37f23116c99bc146eba1741ca3cf1acca0e4d0dbf293ac1810a6ab4eccbe1ee76440dd0a9eb2db5b3bba4f99fc1b3ded16baa6358
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"postcss-modules-scope@npm:^3.1.1":
|
||||||
|
version: 3.2.1
|
||||||
|
resolution: "postcss-modules-scope@npm:3.2.1"
|
||||||
|
dependencies:
|
||||||
|
postcss-selector-parser: "npm:^7.0.0"
|
||||||
|
peerDependencies:
|
||||||
|
postcss: ^8.1.0
|
||||||
|
checksum: 10c0/bd2d81f79e3da0ef6365b8e2c78cc91469d05b58046b4601592cdeef6c4050ed8fe1478ae000a1608042fc7e692cb51fecbd2d9bce3f4eace4d32e883ffca10b
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"postcss-nesting@npm:^13.0.2":
|
"postcss-nesting@npm:^13.0.2":
|
||||||
version: 13.0.2
|
version: 13.0.2
|
||||||
resolution: "postcss-nesting@npm:13.0.2"
|
resolution: "postcss-nesting@npm:13.0.2"
|
||||||
@@ -10898,14 +11112,14 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"postcss-value-parser@npm:^4.2.0":
|
"postcss-value-parser@npm:^4.1.0, postcss-value-parser@npm:^4.2.0":
|
||||||
version: 4.2.0
|
version: 4.2.0
|
||||||
resolution: "postcss-value-parser@npm:4.2.0"
|
resolution: "postcss-value-parser@npm:4.2.0"
|
||||||
checksum: 10c0/f4142a4f56565f77c1831168e04e3effd9ffcc5aebaf0f538eee4b2d465adfd4b85a44257bb48418202a63806a7da7fe9f56c330aebb3cac898e46b4cbf49161
|
checksum: 10c0/f4142a4f56565f77c1831168e04e3effd9ffcc5aebaf0f538eee4b2d465adfd4b85a44257bb48418202a63806a7da7fe9f56c330aebb3cac898e46b4cbf49161
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"postcss@npm:^8.5.6":
|
"postcss@npm:^8.0.0, postcss@npm:^8.4.35, postcss@npm:^8.5.6":
|
||||||
version: 8.5.6
|
version: 8.5.6
|
||||||
resolution: "postcss@npm:8.5.6"
|
resolution: "postcss@npm:8.5.6"
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -11059,6 +11273,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"prr@npm:~1.0.1":
|
||||||
|
version: 1.0.1
|
||||||
|
resolution: "prr@npm:1.0.1"
|
||||||
|
checksum: 10c0/5b9272c602e4f4472a215e58daff88f802923b84bc39c8860376bb1c0e42aaf18c25d69ad974bd06ec6db6f544b783edecd5502cd3d184748d99080d68e4be5f
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"pump@npm:^3.0.0":
|
"pump@npm:^3.0.0":
|
||||||
version: 3.0.0
|
version: 3.0.0
|
||||||
resolution: "pump@npm:3.0.0"
|
resolution: "pump@npm:3.0.0"
|
||||||
@@ -11775,6 +11996,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"reserved-words@npm:^0.1.2":
|
||||||
|
version: 0.1.2
|
||||||
|
resolution: "reserved-words@npm:0.1.2"
|
||||||
|
checksum: 10c0/88360388d88f4b36c1f5d47f8d596936dbf950bddd642c04ce940f1dab1fa58ef6fec23f5fab81a1bfe5cd0f223b2b635311496fcf0ef3db93ad4dfb6d7be186
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"resolve-from@npm:^4.0.0":
|
"resolve-from@npm:^4.0.0":
|
||||||
version: 4.0.0
|
version: 4.0.0
|
||||||
resolution: "resolve-from@npm:4.0.0"
|
resolution: "resolve-from@npm:4.0.0"
|
||||||
@@ -12084,7 +12312,7 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"sass@npm:^1.62.1":
|
"sass@npm:^1.62.1, sass@npm:^1.70.0":
|
||||||
version: 1.93.2
|
version: 1.93.2
|
||||||
resolution: "sass@npm:1.93.2"
|
resolution: "sass@npm:1.93.2"
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -12101,6 +12329,20 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"sax@npm:^1.2.4":
|
||||||
|
version: 1.4.1
|
||||||
|
resolution: "sax@npm:1.4.1"
|
||||||
|
checksum: 10c0/6bf86318a254c5d898ede6bd3ded15daf68ae08a5495a2739564eb265cd13bcc64a07ab466fb204f67ce472bb534eb8612dac587435515169593f4fffa11de7c
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"sax@npm:~1.3.0":
|
||||||
|
version: 1.3.0
|
||||||
|
resolution: "sax@npm:1.3.0"
|
||||||
|
checksum: 10c0/599dbe0ba9d8bd55e92d920239b21d101823a6cedff71e542589303fa0fa8f3ece6cf608baca0c51be846a2e88365fac94a9101a9c341d94b98e30c4deea5bea
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"saxes@npm:^6.0.0":
|
"saxes@npm:^6.0.0":
|
||||||
version: 6.0.0
|
version: 6.0.0
|
||||||
resolution: "saxes@npm:6.0.0"
|
resolution: "saxes@npm:6.0.0"
|
||||||
@@ -12144,6 +12386,15 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"semver@npm:^5.6.0":
|
||||||
|
version: 5.7.2
|
||||||
|
resolution: "semver@npm:5.7.2"
|
||||||
|
bin:
|
||||||
|
semver: bin/semver
|
||||||
|
checksum: 10c0/e4cf10f86f168db772ae95d86ba65b3fd6c5967c94d97c708ccb463b778c2ee53b914cd7167620950fc07faf5a564e6efe903836639e512a1aa15fbc9667fa25
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"semver@npm:^6.3.1":
|
"semver@npm:^6.3.1":
|
||||||
version: 6.3.1
|
version: 6.3.1
|
||||||
resolution: "semver@npm:6.3.1"
|
resolution: "semver@npm:6.3.1"
|
||||||
@@ -12433,7 +12684,7 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"source-map-js@npm:>=0.6.2 <2.0.0, source-map-js@npm:^1.0.1, source-map-js@npm:^1.2.0, source-map-js@npm:^1.2.1":
|
"source-map-js@npm:>=0.6.2 <2.0.0, source-map-js@npm:^1.0.1, source-map-js@npm:^1.0.2, source-map-js@npm:^1.2.0, source-map-js@npm:^1.2.1":
|
||||||
version: 1.2.1
|
version: 1.2.1
|
||||||
resolution: "source-map-js@npm:1.2.1"
|
resolution: "source-map-js@npm:1.2.1"
|
||||||
checksum: 10c0/7bda1fc4c197e3c6ff17de1b8b2c20e60af81b63a52cb32ec5a5d67a20a7d42651e2cb34ebe93833c5a2a084377e17455854fee3e21e7925c64a51b6a52b0faf
|
checksum: 10c0/7bda1fc4c197e3c6ff17de1b8b2c20e60af81b63a52cb32ec5a5d67a20a7d42651e2cb34ebe93833c5a2a084377e17455854fee3e21e7925c64a51b6a52b0faf
|
||||||
@@ -12464,13 +12715,20 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"source-map@npm:^0.6.0, source-map@npm:~0.6.1":
|
"source-map@npm:^0.6.0, source-map@npm:~0.6.0, source-map@npm:~0.6.1":
|
||||||
version: 0.6.1
|
version: 0.6.1
|
||||||
resolution: "source-map@npm:0.6.1"
|
resolution: "source-map@npm:0.6.1"
|
||||||
checksum: 10c0/ab55398007c5e5532957cb0beee2368529618ac0ab372d789806f5718123cc4367d57de3904b4e6a4170eb5a0b0f41373066d02ca0735a0c4d75c7d328d3e011
|
checksum: 10c0/ab55398007c5e5532957cb0beee2368529618ac0ab372d789806f5718123cc4367d57de3904b4e6a4170eb5a0b0f41373066d02ca0735a0c4d75c7d328d3e011
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"source-map@npm:^0.7.3":
|
||||||
|
version: 0.7.6
|
||||||
|
resolution: "source-map@npm:0.7.6"
|
||||||
|
checksum: 10c0/59f6f05538539b274ba771d2e9e32f6c65451982510564438e048bc1352f019c6efcdc6dd07909b1968144941c14015c2c7d4369fb7c4d7d53ae769716dcc16c
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"source-map@npm:^0.7.4":
|
"source-map@npm:^0.7.4":
|
||||||
version: 0.7.4
|
version: 0.7.4
|
||||||
resolution: "source-map@npm:0.7.4"
|
resolution: "source-map@npm:0.7.4"
|
||||||
@@ -13018,6 +13276,21 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"stylus@npm:^0.62.0":
|
||||||
|
version: 0.62.0
|
||||||
|
resolution: "stylus@npm:0.62.0"
|
||||||
|
dependencies:
|
||||||
|
"@adobe/css-tools": "npm:~4.3.1"
|
||||||
|
debug: "npm:^4.3.2"
|
||||||
|
glob: "npm:^7.1.6"
|
||||||
|
sax: "npm:~1.3.0"
|
||||||
|
source-map: "npm:^0.7.3"
|
||||||
|
bin:
|
||||||
|
stylus: bin/stylus
|
||||||
|
checksum: 10c0/62afe3a6d781f66d7d283e8218dc1a15530d7d89fc2f09457a723975b2073e96e0d32c61d7f0dd1bd2686aae4ab6cc6933dc85e1b72eebab8aa30167bd16962b
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"substring-trie@npm:^1.0.2":
|
"substring-trie@npm:^1.0.2":
|
||||||
version: 1.0.2
|
version: 1.0.2
|
||||||
resolution: "substring-trie@npm:1.0.2"
|
resolution: "substring-trie@npm:1.0.2"
|
||||||
@@ -13393,7 +13666,7 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"tslib@npm:^2.0.0, tslib@npm:^2.0.1, tslib@npm:^2.0.3, tslib@npm:^2.4.0, tslib@npm:^2.8.0":
|
"tslib@npm:^2.0.0, tslib@npm:^2.0.1, tslib@npm:^2.0.3, tslib@npm:^2.3.0, tslib@npm:^2.4.0, tslib@npm:^2.8.0":
|
||||||
version: 2.8.1
|
version: 2.8.1
|
||||||
resolution: "tslib@npm:2.8.1"
|
resolution: "tslib@npm:2.8.1"
|
||||||
checksum: 10c0/9c4759110a19c53f992d9aae23aac5ced636e99887b51b9e61def52611732872ff7668757d4e4c61f19691e36f4da981cd9485e869b4a7408d689f6bf1f14e62
|
checksum: 10c0/9c4759110a19c53f992d9aae23aac5ced636e99887b51b9e61def52611732872ff7668757d4e4c61f19691e36f4da981cd9485e869b4a7408d689f6bf1f14e62
|
||||||
@@ -13534,6 +13807,35 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"typescript-plugin-css-modules@npm:^5.2.0":
|
||||||
|
version: 5.2.0
|
||||||
|
resolution: "typescript-plugin-css-modules@npm:5.2.0"
|
||||||
|
dependencies:
|
||||||
|
"@types/postcss-modules-local-by-default": "npm:^4.0.2"
|
||||||
|
"@types/postcss-modules-scope": "npm:^3.0.4"
|
||||||
|
dotenv: "npm:^16.4.2"
|
||||||
|
icss-utils: "npm:^5.1.0"
|
||||||
|
less: "npm:^4.2.0"
|
||||||
|
lodash.camelcase: "npm:^4.3.0"
|
||||||
|
postcss: "npm:^8.4.35"
|
||||||
|
postcss-load-config: "npm:^3.1.4"
|
||||||
|
postcss-modules-extract-imports: "npm:^3.0.0"
|
||||||
|
postcss-modules-local-by-default: "npm:^4.0.4"
|
||||||
|
postcss-modules-scope: "npm:^3.1.1"
|
||||||
|
reserved-words: "npm:^0.1.2"
|
||||||
|
sass: "npm:^1.70.0"
|
||||||
|
source-map-js: "npm:^1.0.2"
|
||||||
|
stylus: "npm:^0.62.0"
|
||||||
|
tsconfig-paths: "npm:^4.2.0"
|
||||||
|
peerDependencies:
|
||||||
|
typescript: ">=4.0.0"
|
||||||
|
dependenciesMeta:
|
||||||
|
stylus:
|
||||||
|
optional: true
|
||||||
|
checksum: 10c0/7cd024f7145c0a29d9b78f2fb49c42cdf1747b50a43391f9993132ba42a727266f9b544fd868d905d5352e0a8676a19ae7a9aa56d516cc819c3ab39d66aa25e4
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"typescript@npm:^5.6.0, typescript@npm:~5.9.0":
|
"typescript@npm:^5.6.0, typescript@npm:~5.9.0":
|
||||||
version: 5.9.2
|
version: 5.9.2
|
||||||
resolution: "typescript@npm:5.9.2"
|
resolution: "typescript@npm:5.9.2"
|
||||||
@@ -14623,7 +14925,7 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"yaml@npm:^1.10.0":
|
"yaml@npm:^1.10.0, yaml@npm:^1.10.2":
|
||||||
version: 1.10.2
|
version: 1.10.2
|
||||||
resolution: "yaml@npm:1.10.2"
|
resolution: "yaml@npm:1.10.2"
|
||||||
checksum: 10c0/5c28b9eb7adc46544f28d9a8d20c5b3cb1215a886609a2fd41f51628d8aaa5878ccd628b755dbcd29f6bb4921bd04ffbc6dcc370689bb96e594e2f9813d2605f
|
checksum: 10c0/5c28b9eb7adc46544f28d9a8d20c5b3cb1215a886609a2fd41f51628d8aaa5878ccd628b755dbcd29f6bb4921bd04ffbc6dcc370689bb96e594e2f9813d2605f
|
||||||
|
|||||||
Reference in New Issue
Block a user