mirror of
https://git.kescher.at/CatCatNya/catstodon.git
synced 2024-11-22 22:18:06 +01:00
Merge commit '1cb978bcc3d291a045f367e072ca0af1a1c4dbbc' into glitch-soc/merge-upstream
This commit is contained in:
commit
10404aece8
22 changed files with 237 additions and 27 deletions
|
@ -532,7 +532,7 @@ GEM
|
|||
premailer (~> 1.7, >= 1.7.9)
|
||||
private_address_check (0.5.0)
|
||||
public_suffix (5.0.3)
|
||||
puma (6.3.0)
|
||||
puma (6.3.1)
|
||||
nio4r (~> 2.0)
|
||||
pundit (2.3.0)
|
||||
activesupport (>= 3.0.0)
|
||||
|
|
|
@ -18,7 +18,7 @@ class Settings::PrivacyController < Settings::BaseController
|
|||
private
|
||||
|
||||
def account_params
|
||||
params.require(:account).permit(:discoverable, :locked, :hide_collections, settings: UserSettings.keys)
|
||||
params.require(:account).permit(:discoverable, :unlocked, :show_collections, settings: UserSettings.keys)
|
||||
end
|
||||
|
||||
def set_account
|
||||
|
|
|
@ -8,6 +8,7 @@ import classNames from 'classnames';
|
|||
import api from 'mastodon/api';
|
||||
|
||||
const messages = defineMessages({
|
||||
legal: { id: 'report.categories.legal', defaultMessage: 'Legal' },
|
||||
other: { id: 'report.categories.other', defaultMessage: 'Other' },
|
||||
spam: { id: 'report.categories.spam', defaultMessage: 'Spam' },
|
||||
violation: { id: 'report.categories.violation', defaultMessage: 'Content violates one or more server rules' },
|
||||
|
@ -150,6 +151,7 @@ class ReportReasonSelector extends PureComponent {
|
|||
return (
|
||||
<div className='report-reason-selector'>
|
||||
<Category id='other' text={intl.formatMessage(messages.other)} selected={category === 'other'} onSelect={this.handleSelect} disabled={disabled} />
|
||||
<Category id='legal' text={intl.formatMessage(messages.legal)} selected={category === 'legal'} onSelect={this.handleSelect} disabled={disabled} />
|
||||
<Category id='spam' text={intl.formatMessage(messages.spam)} selected={category === 'spam'} onSelect={this.handleSelect} disabled={disabled} />
|
||||
<Category id='violation' text={intl.formatMessage(messages.violation)} selected={category === 'violation'} onSelect={this.handleSelect} disabled={disabled}>
|
||||
{rules.map(rule => <Rule key={rule.id} id={rule.id} text={rule.text} selected={rule_ids.includes(rule.id)} onToggle={this.handleToggle} disabled={disabled} />)}
|
||||
|
|
50
app/javascript/mastodon/components/hashtag_bar.jsx
Normal file
50
app/javascript/mastodon/components/hashtag_bar.jsx
Normal file
|
@ -0,0 +1,50 @@
|
|||
import PropTypes from 'prop-types';
|
||||
import { useMemo, useState, useCallback } from 'react';
|
||||
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
|
||||
const domParser = new DOMParser();
|
||||
|
||||
// About two lines on desktop
|
||||
const VISIBLE_HASHTAGS = 7;
|
||||
|
||||
export const HashtagBar = ({ hashtags, text }) => {
|
||||
const renderedHashtags = useMemo(() => {
|
||||
const body = domParser.parseFromString(text, 'text/html').documentElement;
|
||||
return [].filter.call(body.querySelectorAll('a[href]'), link => link.textContent[0] === '#' || (link.previousSibling?.textContent?.[link.previousSibling.textContent.length - 1] === '#')).map(node => node.textContent);
|
||||
}, [text]);
|
||||
|
||||
const invisibleHashtags = useMemo(() => (
|
||||
hashtags.filter(hashtag => !renderedHashtags.some(textContent => textContent.localeCompare(`#${hashtag.get('name')}`, undefined, { sensitivity: 'accent' }) === 0 || textContent.localeCompare(hashtag.get('name'), undefined, { sensitivity: 'accent' }) === 0))
|
||||
), [hashtags, renderedHashtags]);
|
||||
|
||||
const [expanded, setExpanded] = useState(false);
|
||||
const handleClick = useCallback(() => setExpanded(true), []);
|
||||
|
||||
if (invisibleHashtags.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const revealedHashtags = expanded ? invisibleHashtags : invisibleHashtags.take(VISIBLE_HASHTAGS);
|
||||
|
||||
return (
|
||||
<div className='hashtag-bar'>
|
||||
{revealedHashtags.map(hashtag => (
|
||||
<Link key={hashtag.get('name')} to={`/tags/${hashtag.get('name')}`}>
|
||||
#{hashtag.get('name')}
|
||||
</Link>
|
||||
))}
|
||||
|
||||
{!expanded && invisibleHashtags.size > VISIBLE_HASHTAGS && <button className='link-button' onClick={handleClick}><FormattedMessage id='hashtags.and_other' defaultMessage='…and {count, plural, other {# more}}' values={{ count: invisibleHashtags.size - VISIBLE_HASHTAGS }} /></button>}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
HashtagBar.propTypes = {
|
||||
hashtags: ImmutablePropTypes.list,
|
||||
text: PropTypes.string,
|
||||
};
|
|
@ -22,6 +22,7 @@ import { displayMedia } from '../initial_state';
|
|||
import { Avatar } from './avatar';
|
||||
import { AvatarOverlay } from './avatar_overlay';
|
||||
import { DisplayName } from './display_name';
|
||||
import { HashtagBar } from './hashtag_bar';
|
||||
import { RelativeTimestamp } from './relative_timestamp';
|
||||
import StatusActionBar from './status_action_bar';
|
||||
import StatusContent from './status_content';
|
||||
|
@ -580,6 +581,8 @@ class Status extends ImmutablePureComponent {
|
|||
|
||||
{media}
|
||||
|
||||
<HashtagBar hashtags={status.get('tags')} text={status.get('content')} />
|
||||
|
||||
<StatusActionBar scrollKey={scrollKey} status={status} account={account} onFilter={matchedFilters ? this.handleFilterClick : null} {...other} />
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -10,6 +10,7 @@ import ImmutablePureComponent from 'react-immutable-pure-component';
|
|||
|
||||
import { AnimatedNumber } from 'mastodon/components/animated_number';
|
||||
import EditedTimestamp from 'mastodon/components/edited_timestamp';
|
||||
import { HashtagBar } from 'mastodon/components/hashtag_bar';
|
||||
import { Icon } from 'mastodon/components/icon';
|
||||
import PictureInPicturePlaceholder from 'mastodon/components/picture_in_picture_placeholder';
|
||||
|
||||
|
@ -314,6 +315,8 @@ class DetailedStatus extends ImmutablePureComponent {
|
|||
|
||||
{media}
|
||||
|
||||
<HashtagBar hashtags={status.get('tags')} text={status.get('content')} />
|
||||
|
||||
<div className='detailed-status__meta'>
|
||||
<a className='detailed-status__datetime' href={`/@${status.getIn(['account', 'acct'])}/${status.get('id')}`} target='_blank' rel='noopener noreferrer'>
|
||||
<FormattedDate value={new Date(status.get('created_at'))} hour12={false} year='numeric' month='short' day='2-digit' hour='2-digit' minute='2-digit' />
|
||||
|
|
|
@ -300,6 +300,7 @@
|
|||
"hashtag.counter_by_uses_today": "{count, plural, one {{counter} post} other {{counter} posts}} today",
|
||||
"hashtag.follow": "Follow hashtag",
|
||||
"hashtag.unfollow": "Unfollow hashtag",
|
||||
"hashtags.and_other": "…and {count, plural, other {# more}}",
|
||||
"home.actions.go_to_explore": "See what's trending",
|
||||
"home.actions.go_to_suggestions": "Find people to follow",
|
||||
"home.column_settings.basic": "Basic",
|
||||
|
@ -532,6 +533,7 @@
|
|||
"reply_indicator.cancel": "Cancel",
|
||||
"report.block": "Block",
|
||||
"report.block_explanation": "You will not see their posts. They will not be able to see your posts or follow you. They will be able to tell that they are blocked.",
|
||||
"report.categories.legal": "Legal",
|
||||
"report.categories.other": "Other",
|
||||
"report.categories.spam": "Spam",
|
||||
"report.categories.violation": "Content violates one or more server rules",
|
||||
|
|
|
@ -1111,7 +1111,8 @@ body > [data-popper-placement] {
|
|||
.audio-player,
|
||||
.attachment-list,
|
||||
.picture-in-picture-placeholder,
|
||||
.status-card {
|
||||
.status-card,
|
||||
.hashtag-bar {
|
||||
margin-inline-start: $thread-margin;
|
||||
width: calc(100% - ($thread-margin));
|
||||
}
|
||||
|
@ -9256,3 +9257,26 @@ noscript {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
.hashtag-bar {
|
||||
margin-top: 16px;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
font-size: 14px;
|
||||
gap: 4px;
|
||||
|
||||
a {
|
||||
display: inline-flex;
|
||||
border-radius: 4px;
|
||||
background: rgba($highlight-text-color, 0.2);
|
||||
color: $highlight-text-color;
|
||||
padding: 0.4em 0.6em;
|
||||
text-decoration: none;
|
||||
|
||||
&:hover,
|
||||
&:focus,
|
||||
&:active {
|
||||
background: rgba($highlight-text-color, 0.3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,8 +2,14 @@
|
|||
|
||||
class CacheBuster
|
||||
def initialize(options = {})
|
||||
@secret_header = options[:secret_header] || 'Secret-Header'
|
||||
@secret = options[:secret] || 'True'
|
||||
ActiveSupport::Deprecation.warn('Default values for the cache buster secret header name and values will be removed in Mastodon 4.3. Please set them explicitely if you rely on those.') unless options[:http_method] || (options[:secret] && options[:secret_header])
|
||||
|
||||
@secret_header = options[:secret_header] ||
|
||||
(options[:http_method] ? nil : 'Secret-Header')
|
||||
@secret = options[:secret] ||
|
||||
(options[:http_method] ? nil : 'True')
|
||||
|
||||
@http_method = options[:http_method] || 'GET'
|
||||
end
|
||||
|
||||
def bust(url)
|
||||
|
@ -21,8 +27,9 @@ class CacheBuster
|
|||
end
|
||||
|
||||
def build_request(url, http_client)
|
||||
Request.new(:get, url, http_client: http_client).tap do |request|
|
||||
request.add_headers(@secret_header => @secret)
|
||||
end
|
||||
request = Request.new(@http_method.downcase.to_sym, url, http_client: http_client)
|
||||
request.add_headers(@secret_header => @secret) if @secret_header.present? && @secret && !@secret.empty?
|
||||
|
||||
request
|
||||
end
|
||||
end
|
||||
|
|
|
@ -117,7 +117,7 @@ class Request
|
|||
|
||||
def perform
|
||||
begin
|
||||
response = http_client.public_send(@verb, @url.to_s, @options.merge(headers: headers))
|
||||
response = http_client.request(@verb, @url.to_s, @options.merge(headers: headers))
|
||||
rescue => e
|
||||
raise e.class, "#{e.message} on #{@url}", e.backtrace[0]
|
||||
end
|
||||
|
|
|
@ -43,6 +43,9 @@ class VideoMetadataExtractor
|
|||
@height = video_stream[:height]
|
||||
@frame_rate = video_stream[:avg_frame_rate] == '0/0' ? nil : Rational(video_stream[:avg_frame_rate])
|
||||
@r_frame_rate = video_stream[:r_frame_rate] == '0/0' ? nil : Rational(video_stream[:r_frame_rate])
|
||||
# For some video streams the frame_rate reported by `ffprobe` will be 0/0, but for these streams we
|
||||
# should use `r_frame_rate` instead. Video screencast generated by Gnome Screencast have this issue.
|
||||
@frame_rate ||= @r_frame_rate
|
||||
end
|
||||
|
||||
if (audio_stream = audio_streams.first)
|
||||
|
|
|
@ -440,8 +440,21 @@ class Account < ApplicationRecord
|
|||
EntityCache.instance.mention(username, domain)
|
||||
end
|
||||
end
|
||||
|
||||
def inverse_alias(key, original_key)
|
||||
define_method("#{key}=") do |value|
|
||||
public_send("#{original_key}=", !ActiveModel::Type::Boolean.new.cast(value))
|
||||
end
|
||||
|
||||
define_method(key) do
|
||||
!public_send(original_key)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
inverse_alias :show_collections, :hide_collections
|
||||
inverse_alias :unlocked, :locked
|
||||
|
||||
def emojis
|
||||
@emojis ||= CustomEmoji.from_text(emojifiable_text, domain)
|
||||
end
|
||||
|
|
|
@ -48,7 +48,10 @@ class Report < ApplicationRecord
|
|||
|
||||
validate :validate_rule_ids
|
||||
|
||||
# entries here needs to be kept in sync with app/javascript/mastodon/features/notifications/components/report.jsx
|
||||
# entries here need to be kept in sync with the front-end:
|
||||
# - app/javascript/mastodon/features/notifications/components/report.jsx
|
||||
# - app/javascript/mastodon/features/report/category.jsx
|
||||
# - app/javascript/mastodon/components/admin/ReportReasonSelector.jsx
|
||||
enum category: {
|
||||
other: 0,
|
||||
spam: 1_000,
|
||||
|
|
|
@ -410,13 +410,25 @@ class Status < ApplicationRecord
|
|||
|
||||
account_ids.uniq!
|
||||
|
||||
status_ids = cached_items.map { |item| item.reblog? ? item.reblog_of_id : item.id }.uniq
|
||||
|
||||
return if account_ids.empty?
|
||||
|
||||
accounts = Account.where(id: account_ids).includes(:account_stat, :user).index_by(&:id)
|
||||
|
||||
status_stats = StatusStat.where(status_id: status_ids).index_by(&:status_id)
|
||||
|
||||
cached_items.each do |item|
|
||||
item.account = accounts[item.account_id]
|
||||
item.reblog.account = accounts[item.reblog.account_id] if item.reblog?
|
||||
|
||||
if item.reblog?
|
||||
status_stat = status_stats[item.reblog.id]
|
||||
item.reblog.status_stat = status_stat if status_stat.present?
|
||||
else
|
||||
status_stat = status_stats[item.id]
|
||||
item.status_stat = status_stat if status_stat.present?
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
= f.input :discoverable, as: :boolean, wrapper: :with_label, recommended: true
|
||||
|
||||
.fields-group
|
||||
= f.input :locked, as: :boolean, wrapper: :with_label
|
||||
= f.input :unlocked, as: :boolean, wrapper: :with_label
|
||||
|
||||
%h4= t('privacy.search')
|
||||
|
||||
|
@ -33,7 +33,7 @@
|
|||
%p.lead= t('privacy.privacy_hint_html')
|
||||
|
||||
.fields-group
|
||||
= f.input :hide_collections, as: :boolean, wrapper: :with_label
|
||||
= f.input :show_collections, as: :boolean, wrapper: :with_label
|
||||
|
||||
= f.simple_fields_for :settings, current_user.settings do |ff|
|
||||
.fields-group
|
||||
|
|
|
@ -51,6 +51,7 @@ require_relative '../lib/rails/engine_extensions'
|
|||
require_relative '../lib/active_record/database_tasks_extensions'
|
||||
require_relative '../lib/active_record/batches'
|
||||
require_relative '../lib/simple_navigation/item_extensions'
|
||||
require_relative '../lib/http_extensions'
|
||||
|
||||
Dotenv::Railtie.load
|
||||
|
||||
|
|
|
@ -6,5 +6,6 @@ Rails.application.configure do
|
|||
config.x.cache_buster = {
|
||||
secret_header: ENV['CACHE_BUSTER_SECRET_HEADER'],
|
||||
secret: ENV['CACHE_BUSTER_SECRET'],
|
||||
http_method: ENV['CACHE_BUSTER_HTTP_METHOD'] || 'GET',
|
||||
}
|
||||
end
|
||||
|
|
|
@ -6,9 +6,9 @@ en:
|
|||
discoverable: Your public posts and profile may be featured or recommended in various areas of Mastodon and your profile may be suggested to other users.
|
||||
display_name: Your full name or your fun name.
|
||||
fields: Your homepage, pronouns, age, anything you want.
|
||||
hide_collections: People will not be able to browse through your follows and followers. People that you follow will see that you follow them regardless.
|
||||
locked: People will request to follow you and you will be able to either accept or reject new followers.
|
||||
note: 'You can @mention other people or #hashtags.'
|
||||
show_collections: People will be able to browse through your follows and followers. People that you follow will see that you follow them regardless.
|
||||
unlocked: People will be able to follow you without requesting approval. Uncheck if you want to review follow requests and chose whether to accept or reject new followers.
|
||||
account_alias:
|
||||
acct: Specify the username@domain of the account you want to move from
|
||||
account_migration:
|
||||
|
@ -143,8 +143,8 @@ en:
|
|||
fields:
|
||||
name: Label
|
||||
value: Content
|
||||
hide_collections: Hide follows and followers from profile
|
||||
locked: Manually review new followers
|
||||
show_collections: Show follows and followers on profile
|
||||
unlocked: Automatically accept new followers
|
||||
account_alias:
|
||||
acct: Handle of the old account
|
||||
account_migration:
|
||||
|
|
10
lib/http_extensions.rb
Normal file
10
lib/http_extensions.rb
Normal file
|
@ -0,0 +1,10 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# Monkey patching until https://github.com/httprb/http/pull/757 is merged
|
||||
unless HTTP::Request::METHODS.include?(:purge)
|
||||
module HTTP
|
||||
class Request
|
||||
METHODS = METHODS.dup.push(:purge).freeze
|
||||
end
|
||||
end
|
||||
end
|
|
@ -13,12 +13,17 @@ RSpec.describe CacheConcern do
|
|||
def empty_relation
|
||||
render plain: cache_collection(Status.none, Status).size
|
||||
end
|
||||
|
||||
def account_statuses_favourites
|
||||
render plain: cache_collection(Status.where(account_id: params[:id]), Status).map(&:favourites_count)
|
||||
end
|
||||
end
|
||||
|
||||
before do
|
||||
routes.draw do
|
||||
get 'empty_array' => 'anonymous#empty_array'
|
||||
post 'empty_relation' => 'anonymous#empty_relation'
|
||||
get 'empty_array' => 'anonymous#empty_array'
|
||||
get 'empty_relation' => 'anonymous#empty_relation'
|
||||
get 'account_statuses_favourites' => 'anonymous#account_statuses_favourites'
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -36,5 +41,20 @@ RSpec.describe CacheConcern do
|
|||
expect(response.body).to eq '0'
|
||||
end
|
||||
end
|
||||
|
||||
context 'when given a collection of statuses' do
|
||||
let!(:account) { Fabricate(:account) }
|
||||
let!(:status) { Fabricate(:status, account: account) }
|
||||
|
||||
it 'correctly updates with new interactions' do
|
||||
get :account_statuses_favourites, params: { id: account.id }
|
||||
expect(response.body).to eq '[0]'
|
||||
|
||||
FavouriteService.new.call(account, status)
|
||||
|
||||
get :account_statuses_favourites, params: { id: account.id }
|
||||
expect(response.body).to eq '[1]'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
56
spec/lib/cache_buster_spec.rb
Normal file
56
spec/lib/cache_buster_spec.rb
Normal file
|
@ -0,0 +1,56 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe CacheBuster do
|
||||
subject { described_class.new(secret_header: secret_header, secret: secret, http_method: http_method) }
|
||||
|
||||
let(:secret_header) { nil }
|
||||
let(:secret) { nil }
|
||||
let(:http_method) { nil }
|
||||
|
||||
let(:purge_url) { 'https://example.com/test_purge' }
|
||||
|
||||
describe '#bust' do
|
||||
shared_examples 'makes_request' do
|
||||
it 'makes an HTTP purging request' do
|
||||
method = http_method&.to_sym || :get
|
||||
stub_request(method, purge_url).to_return(status: 200)
|
||||
|
||||
subject.bust(purge_url)
|
||||
|
||||
test_request = a_request(method, purge_url)
|
||||
|
||||
test_request = test_request.with(headers: { secret_header => secret }) if secret && secret_header
|
||||
|
||||
expect(test_request).to have_been_made.once
|
||||
end
|
||||
end
|
||||
|
||||
context 'when using default options' do
|
||||
include_examples 'makes_request'
|
||||
end
|
||||
|
||||
context 'when specifying a secret header' do
|
||||
let(:secret_header) { 'X-Purge-Secret' }
|
||||
let(:secret) { SecureRandom.hex(20) }
|
||||
|
||||
include_examples 'makes_request'
|
||||
end
|
||||
|
||||
context 'when specifying a PURGE method' do
|
||||
let(:http_method) { 'purge' }
|
||||
|
||||
context 'when not using headers' do
|
||||
include_examples 'makes_request'
|
||||
end
|
||||
|
||||
context 'when specifying a secret header' do
|
||||
let(:secret_header) { 'X-Purge-Secret' }
|
||||
let(:secret) { SecureRandom.hex(20) }
|
||||
|
||||
include_examples 'makes_request'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
18
yarn.lock
18
yarn.lock
|
@ -1677,9 +1677,9 @@
|
|||
"@jridgewell/sourcemap-codec" "^1.4.14"
|
||||
|
||||
"@material-design-icons/svg@^0.14.10":
|
||||
version "0.14.10"
|
||||
resolved "https://registry.yarnpkg.com/@material-design-icons/svg/-/svg-0.14.10.tgz#25804b66d0740b0bf8d6841fa343dfdd60f22e82"
|
||||
integrity sha512-rXxfqj5Su8i51aG8s8QRIe7mX1gB+C/ZCroLu3JvIsO3+Vx6PcWP97HLwIl7AQH/jYIHQlKq0E6OMqU91u5fCg==
|
||||
version "0.14.11"
|
||||
resolved "https://registry.yarnpkg.com/@material-design-icons/svg/-/svg-0.14.11.tgz#f90a2c8de801523c3b17e606c89313121c8bb3b4"
|
||||
integrity sha512-jpAksWZIVLB5/qTAeqANns7pH/faIQR3jgV2yROUNKZkzpJ428h7e1/byJB+rFZNI0hgZpY9nOVMLhc1J41HtA==
|
||||
|
||||
"@nodelib/fs.scandir@2.1.5":
|
||||
version "2.1.5"
|
||||
|
@ -9199,9 +9199,9 @@ pg-types@^4.0.1:
|
|||
postgres-range "^1.1.1"
|
||||
|
||||
pg@^8.5.0:
|
||||
version "8.11.2"
|
||||
resolved "https://registry.yarnpkg.com/pg/-/pg-8.11.2.tgz#1a23f6de7bfb65ba56e4dd15df96668d319900c4"
|
||||
integrity sha512-l4rmVeV8qTIrrPrIR3kZQqBgSN93331s9i6wiUiLOSk0Q7PmUxZD/m1rQI622l3NfqBby9Ar5PABfS/SulfieQ==
|
||||
version "8.11.3"
|
||||
resolved "https://registry.yarnpkg.com/pg/-/pg-8.11.3.tgz#d7db6e3fe268fcedd65b8e4599cda0b8b4bf76cb"
|
||||
integrity sha512-+9iuvG8QfaaUrrph+kpF24cXkH1YOOUeArRNYIxq1viYHZagBxrTno7cecY1Fa44tJeZvaoG+Djpkc3JwehN5g==
|
||||
dependencies:
|
||||
buffer-writer "2.0.0"
|
||||
packet-reader "1.0.0"
|
||||
|
@ -9564,9 +9564,9 @@ postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0:
|
|||
integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==
|
||||
|
||||
postcss@^8.2.15, postcss@^8.4.24, postcss@^8.4.25:
|
||||
version "8.4.27"
|
||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.27.tgz#234d7e4b72e34ba5a92c29636734349e0d9c3057"
|
||||
integrity sha512-gY/ACJtJPSmUFPDCHtX78+01fHa64FaU4zaaWfuh1MhGJISufJAH4cun6k/8fwsHYeK4UQmENQK+tRLCFJE8JQ==
|
||||
version "8.4.28"
|
||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.28.tgz#c6cc681ed00109072816e1557f889ef51cf950a5"
|
||||
integrity sha512-Z7V5j0cq8oEKyejIKfpD8b4eBy9cwW2JWPk0+fB1HOAMsfHbnAXLLS+PfVWlzMSLQaWttKDt607I0XHmpE67Vw==
|
||||
dependencies:
|
||||
nanoid "^3.3.6"
|
||||
picocolors "^1.0.0"
|
||||
|
|
Loading…
Reference in a new issue