Merge branch 'develop' into iceshrimp_mastodon
This commit is contained in:
commit
870d625565
8 changed files with 157 additions and 123 deletions
19
packages/backend-rs/index.d.ts
vendored
19
packages/backend-rs/index.d.ts
vendored
|
@ -378,6 +378,13 @@ export function isSilencedServer(host: string): Promise<boolean>
|
|||
* ```
|
||||
*/
|
||||
export function isAllowedServer(host: string): Promise<boolean>
|
||||
export interface PartialNoteToCheckWordMute {
|
||||
fileIds: Array<string>
|
||||
text: string | null
|
||||
cw: string | null
|
||||
renoteId: string | null
|
||||
replyId: string | null
|
||||
}
|
||||
/**
|
||||
* Returns whether `note` should be hard-muted.
|
||||
*
|
||||
|
@ -390,11 +397,11 @@ export function isAllowedServer(host: string): Promise<boolean>
|
|||
*
|
||||
* # Arguments
|
||||
*
|
||||
* * `note` : [PartialNoteToElaborate] object
|
||||
* * `note` : [PartialNoteToCheckWordMute] object
|
||||
* * `muted_words` : list of muted keyword lists (each array item is a space-separated keyword list that represents an AND condition)
|
||||
* * `muted_patterns` : list of JavaScript-style (e.g., `/foo/i`) regular expressions
|
||||
*/
|
||||
export function checkWordMute(note: PartialNoteToElaborate, mutedWords: Array<string>, mutedPatterns: Array<string>): Promise<boolean>
|
||||
export function checkWordMute(note: PartialNoteToCheckWordMute, mutedWords: Array<string>, mutedPatterns: Array<string>): Promise<boolean>
|
||||
export function getFullApAccount(username: string, host?: string | undefined | null): string
|
||||
export function isSelfHost(host?: string | undefined | null): boolean
|
||||
export function isSameOrigin(uri: string): boolean
|
||||
|
@ -413,14 +420,6 @@ export interface ImageSize {
|
|||
height: number
|
||||
}
|
||||
export function getImageSizeFromUrl(url: string): Promise<ImageSize>
|
||||
export interface PartialNoteToElaborate {
|
||||
fileIds: Array<string>
|
||||
userId: string
|
||||
text: string | null
|
||||
cw: string | null
|
||||
renoteId: string | null
|
||||
replyId: string | null
|
||||
}
|
||||
export interface PartialNoteToSummarize {
|
||||
fileIds: Array<string>
|
||||
text: string | null
|
||||
|
|
|
@ -1,8 +1,17 @@
|
|||
use crate::misc::get_note_all_texts::{all_texts, PartialNoteToElaborate};
|
||||
use crate::misc::get_note_all_texts::all_texts;
|
||||
use once_cell::sync::Lazy;
|
||||
use regex::Regex;
|
||||
use sea_orm::DbErr;
|
||||
|
||||
#[crate::export(object)]
|
||||
pub struct PartialNoteToCheckWordMute {
|
||||
pub file_ids: Vec<String>,
|
||||
pub text: Option<String>,
|
||||
pub cw: Option<String>,
|
||||
pub renote_id: Option<String>,
|
||||
pub reply_id: Option<String>,
|
||||
}
|
||||
|
||||
fn convert_regex(js_regex: &str) -> String {
|
||||
static RE: Lazy<Regex> = Lazy::new(|| Regex::new(r"^/(.+)/(.*)$").unwrap());
|
||||
RE.replace(js_regex, "(?$2)$1").to_string()
|
||||
|
@ -37,12 +46,12 @@ fn check_word_mute_impl(
|
|||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `note` : [PartialNoteToElaborate] object
|
||||
/// * `note` : [PartialNoteToCheckWordMute] object
|
||||
/// * `muted_words` : list of muted keyword lists (each array item is a space-separated keyword list that represents an AND condition)
|
||||
/// * `muted_patterns` : list of JavaScript-style (e.g., `/foo/i`) regular expressions
|
||||
#[crate::export]
|
||||
pub async fn check_word_mute(
|
||||
note: PartialNoteToElaborate,
|
||||
note: PartialNoteToCheckWordMute,
|
||||
muted_words: &[String],
|
||||
muted_patterns: &[String],
|
||||
) -> Result<bool, DbErr> {
|
||||
|
@ -50,7 +59,7 @@ pub async fn check_word_mute(
|
|||
Ok(false)
|
||||
} else {
|
||||
Ok(check_word_mute_impl(
|
||||
&all_texts(note, true).await?,
|
||||
&all_texts!(note, true).await?,
|
||||
muted_words,
|
||||
muted_patterns,
|
||||
))
|
||||
|
|
|
@ -4,40 +4,33 @@ use crate::{
|
|||
};
|
||||
use sea_orm::{prelude::*, QuerySelect};
|
||||
|
||||
#[crate::export(object)]
|
||||
pub struct PartialNoteToElaborate {
|
||||
pub file_ids: Vec<String>,
|
||||
pub user_id: String,
|
||||
pub text: Option<String>,
|
||||
pub cw: Option<String>,
|
||||
pub renote_id: Option<String>,
|
||||
pub reply_id: Option<String>,
|
||||
}
|
||||
|
||||
/// Returns [`Vec<String>`] containing the post text, content warning,
|
||||
/// those of the "parent" (replied/quoted) posts, and alt texts of attached files.
|
||||
/// Consider using [`all_texts`] macro instead
|
||||
/// when dealing with a note ([`note::Model`])-like instance.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `note` : [PartialNoteToElaborate] object
|
||||
/// * `file_ids` : IDs of attached files ([`drive_file::Model`])
|
||||
/// * `text`, `cw`, `renote_id`, `reply_id` : note ([`note::Model`]) fields
|
||||
/// * `include_parent` : whether to take the reply-to post and quoted post into account
|
||||
pub async fn all_texts(
|
||||
note: PartialNoteToElaborate,
|
||||
pub async fn all_texts_impl(
|
||||
file_ids: &[String],
|
||||
text: Option<String>,
|
||||
cw: Option<String>,
|
||||
renote_id: &Option<String>,
|
||||
reply_id: &Option<String>,
|
||||
include_parent: bool,
|
||||
) -> Result<Vec<String>, DbErr> {
|
||||
let db = db_conn().await?;
|
||||
|
||||
let mut texts: Vec<String> = vec![];
|
||||
let is_renote: bool;
|
||||
let is_renote = text.is_none();
|
||||
|
||||
if let Some(text) = note.text {
|
||||
is_renote = false;
|
||||
if let Some(text) = text {
|
||||
texts.push(text);
|
||||
} else {
|
||||
is_renote = true;
|
||||
}
|
||||
|
||||
if let Some(cw) = note.cw {
|
||||
if let Some(cw) = cw {
|
||||
texts.push(cw);
|
||||
}
|
||||
|
||||
|
@ -45,7 +38,7 @@ pub async fn all_texts(
|
|||
drive_file::Entity::find()
|
||||
.select_only()
|
||||
.column(drive_file::Column::Comment)
|
||||
.filter(drive_file::Column::Id.is_in(note.file_ids))
|
||||
.filter(drive_file::Column::Id.is_in(file_ids))
|
||||
.into_tuple::<Option<String>>()
|
||||
.all(db)
|
||||
.await?
|
||||
|
@ -53,45 +46,87 @@ pub async fn all_texts(
|
|||
.flatten(),
|
||||
);
|
||||
|
||||
if note.renote_id.is_some() && (include_parent || is_renote) {
|
||||
let renote_id = note.renote_id.unwrap();
|
||||
|
||||
if let Some((text, cw)) = note::Entity::find_by_id(&renote_id)
|
||||
let mut query_note_ids = Vec::<&str>::with_capacity(2);
|
||||
if let Some(renote_id) = renote_id {
|
||||
if include_parent || is_renote {
|
||||
query_note_ids.push(renote_id);
|
||||
}
|
||||
}
|
||||
if let Some(reply_id) = reply_id {
|
||||
if include_parent {
|
||||
query_note_ids.push(reply_id);
|
||||
}
|
||||
}
|
||||
if !query_note_ids.is_empty() {
|
||||
texts.extend(
|
||||
note::Entity::find()
|
||||
.filter(note::Column::Id.is_in(query_note_ids))
|
||||
.select_only()
|
||||
.columns([note::Column::Text, note::Column::Cw])
|
||||
.into_tuple::<(Option<String>, Option<String>)>()
|
||||
.one(db)
|
||||
.await?
|
||||
{
|
||||
if let Some(t) = text {
|
||||
texts.push(t);
|
||||
}
|
||||
if let Some(c) = cw {
|
||||
texts.push(c);
|
||||
}
|
||||
} else {
|
||||
tracing::warn!("nonexistent renote id: {}", renote_id);
|
||||
}
|
||||
}
|
||||
|
||||
if include_parent && note.reply_id.is_some() {
|
||||
if let Some((text, cw)) = note::Entity::find_by_id(note.reply_id.as_ref().unwrap())
|
||||
.select_only()
|
||||
.columns([note::Column::Text, note::Column::Cw])
|
||||
.into_tuple::<(Option<String>, Option<String>)>()
|
||||
.one(db)
|
||||
.await?
|
||||
{
|
||||
if let Some(t) = text {
|
||||
texts.push(t);
|
||||
}
|
||||
if let Some(c) = cw {
|
||||
texts.push(c);
|
||||
}
|
||||
} else {
|
||||
tracing::warn!("nonexistent reply id: {}", note.reply_id.unwrap());
|
||||
}
|
||||
.into_iter()
|
||||
.flat_map(|(text, cw)| [text, cw])
|
||||
.flatten(),
|
||||
);
|
||||
}
|
||||
|
||||
Ok(texts)
|
||||
}
|
||||
|
||||
/// Returns [`Vec<String>`] containing the post text, content warning,
|
||||
/// those of the "parent" (replied/quoted) posts, and alt texts of attached files.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `note_like` : a note ([`note::Model`])-like instance containing
|
||||
/// `file_ids`, `text`, `cw`, `renote_id`, `reply_id` fields
|
||||
/// * `include_parent` ([bool]) : whether to take the reply-to post and quoted post into account
|
||||
///
|
||||
/// # Caveats
|
||||
///
|
||||
/// The `note_like` argument should not contain function calls
|
||||
/// (e.g., `all_texts!(note.clone(), false)`)
|
||||
/// since the function will be called multiple times after macro expansion.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # use backend_rs::misc::get_note_all_texts::all_texts;
|
||||
/// // note-like struct
|
||||
/// struct SomeNoteLikeStruct {
|
||||
/// // required fields
|
||||
/// file_ids: Vec<String>,
|
||||
/// text: Option<String>,
|
||||
/// cw: Option<String>,
|
||||
/// renote_id: Option<String>,
|
||||
/// reply_id: Option<String>,
|
||||
/// // arbitrary extra fields
|
||||
/// extra_field_1: u32,
|
||||
/// extra_field_2: Vec<String>,
|
||||
/// }
|
||||
///
|
||||
/// async fn all_texts_from_some_note_like_struct(
|
||||
/// note_like: &SomeNoteLikeStruct,
|
||||
/// include_parent: bool,
|
||||
/// ) -> Result<Vec<String>, sea_orm::DbErr> {
|
||||
/// all_texts!(note_like, include_parent).await
|
||||
/// }
|
||||
/// ```
|
||||
#[doc(hidden)] // hide the macro in the top doc page
|
||||
#[macro_export]
|
||||
macro_rules! all_texts {
|
||||
($note_like:expr, $include_parent:expr) => {
|
||||
$crate::misc::get_note_all_texts::all_texts_impl(
|
||||
&$note_like.file_ids,
|
||||
$note_like.text.clone(),
|
||||
$note_like.cw.clone(),
|
||||
&$note_like.renote_id,
|
||||
&$note_like.reply_id,
|
||||
$include_parent,
|
||||
)
|
||||
};
|
||||
}
|
||||
#[doc(inline)] // show the macro in the module doc page
|
||||
pub use all_texts;
|
||||
|
|
|
@ -2,24 +2,23 @@
|
|||
|
||||
use crate::{database::db_conn, model::entity::antenna};
|
||||
use sea_orm::prelude::*;
|
||||
use std::sync::Mutex;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
static CACHE: Mutex<Option<Vec<antenna::Model>>> = Mutex::new(None);
|
||||
static CACHE: Mutex<Option<Arc<[antenna::Model]>>> = Mutex::new(None);
|
||||
|
||||
fn set(antennas: &[antenna::Model]) {
|
||||
let _ = CACHE
|
||||
.lock()
|
||||
.map(|mut cache| *cache = Some(antennas.to_owned()));
|
||||
fn set(antennas: Arc<[antenna::Model]>) {
|
||||
let _ = CACHE.lock().map(|mut cache| *cache = Some(antennas));
|
||||
}
|
||||
|
||||
pub(super) async fn update() -> Result<Vec<antenna::Model>, DbErr> {
|
||||
pub(super) async fn update() -> Result<Arc<[antenna::Model]>, DbErr> {
|
||||
tracing::debug!("updating cache");
|
||||
let antennas = antenna::Entity::find().all(db_conn().await?).await?;
|
||||
set(&antennas);
|
||||
let antennas: Arc<[antenna::Model]> =
|
||||
antenna::Entity::find().all(db_conn().await?).await?.into();
|
||||
set(antennas.clone());
|
||||
Ok(antennas)
|
||||
}
|
||||
|
||||
pub(super) async fn get() -> Result<Vec<antenna::Model>, DbErr> {
|
||||
pub(super) async fn get() -> Result<Arc<[antenna::Model]>, DbErr> {
|
||||
if let Some(cache) = CACHE.lock().ok().and_then(|cache| cache.clone()) {
|
||||
return Ok(cache);
|
||||
}
|
||||
|
|
|
@ -12,8 +12,6 @@ pub enum AntennaCheckError {
|
|||
Db(#[from] DbErr),
|
||||
#[error("Cache error: {0}")]
|
||||
Cache(#[from] cache::Error),
|
||||
#[error("User profile not found: {0}")]
|
||||
UserProfileNotFound(String),
|
||||
}
|
||||
|
||||
fn match_all(space_separated_words: &str, text: &str, case_sensitive: bool) -> bool {
|
||||
|
@ -29,7 +27,7 @@ fn match_all(space_separated_words: &str, text: &str, case_sensitive: bool) -> b
|
|||
}
|
||||
}
|
||||
|
||||
pub async fn check_hit_antenna(
|
||||
pub(super) async fn check_hit_antenna(
|
||||
antenna: &antenna::Model,
|
||||
note: ¬e::Model,
|
||||
note_all_texts: &[String],
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::{
|
||||
database::{cache, redis_conn, redis_key, RedisConnError},
|
||||
federation::acct::Acct,
|
||||
misc::get_note_all_texts::{all_texts, PartialNoteToElaborate},
|
||||
misc::get_note_all_texts::all_texts,
|
||||
model::entity::note,
|
||||
service::{
|
||||
antenna,
|
||||
|
@ -37,31 +37,19 @@ type Note = note::Model;
|
|||
|
||||
#[crate::export]
|
||||
pub async fn update_antennas_on_new_note(
|
||||
note: Note,
|
||||
note: &Note,
|
||||
note_author: &Acct,
|
||||
note_muted_users: &[String],
|
||||
) -> Result<(), Error> {
|
||||
let note_cloned = note.clone();
|
||||
let note_all_texts = all_texts(
|
||||
PartialNoteToElaborate {
|
||||
file_ids: note.file_ids,
|
||||
user_id: note.user_id,
|
||||
text: note.text,
|
||||
cw: note.cw,
|
||||
renote_id: note.renote_id,
|
||||
reply_id: note.reply_id,
|
||||
},
|
||||
false,
|
||||
)
|
||||
.await?;
|
||||
let note_all_texts = all_texts!(note, false).await?;
|
||||
|
||||
// TODO: do this in parallel
|
||||
for antenna in antenna::cache::get().await?.iter() {
|
||||
if note_muted_users.contains(&antenna.user_id) {
|
||||
continue;
|
||||
}
|
||||
if check_hit_antenna(antenna, ¬e_cloned, ¬e_all_texts, note_author).await? {
|
||||
add_note_to_antenna(&antenna.id, ¬e_cloned).await?;
|
||||
if check_hit_antenna(antenna, note, ¬e_all_texts, note_author).await? {
|
||||
add_note_to_antenna(&antenna.id, note).await?;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -90,6 +90,6 @@
|
|||
"vue-draggable-plus": "0.5.0",
|
||||
"vue-plyr": "7.0.0",
|
||||
"vue-prism-editor": "2.0.0-alpha.2",
|
||||
"vue-tsc": "2.0.19"
|
||||
"vue-tsc": "2.0.21"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -762,8 +762,8 @@ importers:
|
|||
specifier: 2.0.0-alpha.2
|
||||
version: 2.0.0-alpha.2(vue@3.4.27(typescript@5.4.5))
|
||||
vue-tsc:
|
||||
specifier: 2.0.19
|
||||
version: 2.0.19(typescript@5.4.5)
|
||||
specifier: 2.0.21
|
||||
version: 2.0.21(typescript@5.4.5)
|
||||
|
||||
packages/firefish-js:
|
||||
dependencies:
|
||||
|
@ -2586,14 +2586,14 @@ packages:
|
|||
vite: ^5.0.0
|
||||
vue: ^3.2.25
|
||||
|
||||
'@volar/language-core@2.2.5':
|
||||
resolution: {integrity: sha512-2htyAuxRrAgETmFeUhT4XLELk3LiEcqoW/B8YUXMF6BrGWLMwIR09MFaZYvrA2UhbdAeSyeQ726HaWSWkexUcQ==}
|
||||
'@volar/language-core@2.3.0-alpha.15':
|
||||
resolution: {integrity: sha512-uSfn1Dsl1w9o2aN9nnS6N/4FcjSbmpY6P/ypfW4kRhasEyICstu4swIz2joNR6532R02JwJY9Ta0pxRmXbBOqw==}
|
||||
|
||||
'@volar/source-map@2.2.5':
|
||||
resolution: {integrity: sha512-wrOEIiZNf4E+PWB0AxyM4tfhkfldPsb3bxg8N6FHrxJH2ohar7aGu48e98bp3pR9HUA7P/pR9VrLmkTrgCCnWQ==}
|
||||
'@volar/source-map@2.3.0-alpha.15':
|
||||
resolution: {integrity: sha512-DQr3FwhRxtxX4W6BoJkwajWjj6BAF5H/SgtzFaUP9z8txn6Y5oFxZPPDG+3Xwu3pTV3gvVlE7AL5E/G1jUr5Yg==}
|
||||
|
||||
'@volar/typescript@2.2.5':
|
||||
resolution: {integrity: sha512-eSV/n75+ppfEVugMC/salZsI44nXDPAyL6+iTYCNLtiLHGJsnMv9GwiDMujrvAUj/aLQyqRJgYtXRoxop2clCw==}
|
||||
'@volar/typescript@2.3.0-alpha.15':
|
||||
resolution: {integrity: sha512-sTzUyqGC1wkzVyY0XZBO5smCPDRvIqxlMTUw7bZebuD/7sGaVfyk9ryE29aG6CLpuYDev/ugpQsKoFVhFaQQ8A==}
|
||||
|
||||
'@vue/compiler-core@3.4.27':
|
||||
resolution: {integrity: sha512-E+RyqY24KnyDXsCuQrI+mlcdW3ALND6U7Gqa/+bVwbcpcR3BRRIckFoz7Qyd4TTlnugtwuI7YgjbvsLmxb+yvg==}
|
||||
|
@ -2610,8 +2610,8 @@ packages:
|
|||
'@vue/compiler-ssr@3.4.27':
|
||||
resolution: {integrity: sha512-CVRzSJIltzMG5FcidsW0jKNQnNRYC8bT21VegyMMtHmhW3UOI7knmUehzswXLrExDLE6lQCZdrhD4ogI7c+vuw==}
|
||||
|
||||
'@vue/language-core@2.0.19':
|
||||
resolution: {integrity: sha512-A9EGOnvb51jOvnCYoRLnMP+CcoPlbZVxI9gZXE/y2GksRWM6j/PrLEIC++pnosWTN08tFpJgxhSS//E9v/Sg+Q==}
|
||||
'@vue/language-core@2.0.21':
|
||||
resolution: {integrity: sha512-vjs6KwnCK++kIXT+eI63BGpJHfHNVJcUCr3RnvJsccT3vbJnZV5IhHR2puEkoOkIbDdp0Gqi1wEnv3hEd3WsxQ==}
|
||||
peerDependencies:
|
||||
typescript: '*'
|
||||
peerDependenciesMeta:
|
||||
|
@ -7482,6 +7482,9 @@ packages:
|
|||
resolution: {integrity: sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
vscode-uri@3.0.8:
|
||||
resolution: {integrity: sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==}
|
||||
|
||||
vue-draggable-plus@0.5.0:
|
||||
resolution: {integrity: sha512-A5TT5+M5JceROSjPO9aDZTsrSN1TetEs419czPlboomarSiGIBIxTp2WD7XH53EHMrbO7Qo+leRiHWV/rMlyjA==}
|
||||
peerDependencies:
|
||||
|
@ -7509,8 +7512,8 @@ packages:
|
|||
vue-template-compiler@2.7.16:
|
||||
resolution: {integrity: sha512-AYbUWAJHLGGQM7+cNTELw+KsOG9nl2CnSv467WobS5Cv9uk3wFcnr1Etsz2sEIHEZvw1U+o9mRlEO6QbZvUPGQ==}
|
||||
|
||||
vue-tsc@2.0.19:
|
||||
resolution: {integrity: sha512-JWay5Zt2/871iodGF72cELIbcAoPyhJxq56mPPh+M2K7IwI688FMrFKc/+DvB05wDWEuCPexQJ6L10zSwzzapg==}
|
||||
vue-tsc@2.0.21:
|
||||
resolution: {integrity: sha512-E6x1p1HaHES6Doy8pqtm7kQern79zRtIewkf9fiv7Y43Zo4AFDS5hKi+iHi2RwEhqRmuiwliB1LCEFEGwvxQnw==}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
typescript: '*'
|
||||
|
@ -9677,18 +9680,19 @@ snapshots:
|
|||
vite: 5.2.13(@types/node@20.14.2)(sass@1.77.4)(stylus@0.57.0)(terser@5.31.0)
|
||||
vue: 3.4.27(typescript@5.4.5)
|
||||
|
||||
'@volar/language-core@2.2.5':
|
||||
'@volar/language-core@2.3.0-alpha.15':
|
||||
dependencies:
|
||||
'@volar/source-map': 2.2.5
|
||||
'@volar/source-map': 2.3.0-alpha.15
|
||||
|
||||
'@volar/source-map@2.2.5':
|
||||
'@volar/source-map@2.3.0-alpha.15':
|
||||
dependencies:
|
||||
muggle-string: 0.4.1
|
||||
|
||||
'@volar/typescript@2.2.5':
|
||||
'@volar/typescript@2.3.0-alpha.15':
|
||||
dependencies:
|
||||
'@volar/language-core': 2.2.5
|
||||
'@volar/language-core': 2.3.0-alpha.15
|
||||
path-browserify: 1.0.1
|
||||
vscode-uri: 3.0.8
|
||||
|
||||
'@vue/compiler-core@3.4.27':
|
||||
dependencies:
|
||||
|
@ -9728,9 +9732,9 @@ snapshots:
|
|||
'@vue/compiler-dom': 3.4.27
|
||||
'@vue/shared': 3.4.27
|
||||
|
||||
'@vue/language-core@2.0.19(typescript@5.4.5)':
|
||||
'@vue/language-core@2.0.21(typescript@5.4.5)':
|
||||
dependencies:
|
||||
'@volar/language-core': 2.2.5
|
||||
'@volar/language-core': 2.3.0-alpha.15
|
||||
'@vue/compiler-dom': 3.4.27
|
||||
'@vue/shared': 3.4.27
|
||||
computeds: 0.0.1
|
||||
|
@ -15167,6 +15171,8 @@ snapshots:
|
|||
|
||||
void-elements@3.1.0: {}
|
||||
|
||||
vscode-uri@3.0.8: {}
|
||||
|
||||
vue-draggable-plus@0.5.0(@types/sortablejs@1.15.8):
|
||||
dependencies:
|
||||
'@types/sortablejs': 1.15.8
|
||||
|
@ -15198,10 +15204,10 @@ snapshots:
|
|||
de-indent: 1.0.2
|
||||
he: 1.2.0
|
||||
|
||||
vue-tsc@2.0.19(typescript@5.4.5):
|
||||
vue-tsc@2.0.21(typescript@5.4.5):
|
||||
dependencies:
|
||||
'@volar/typescript': 2.2.5
|
||||
'@vue/language-core': 2.0.19(typescript@5.4.5)
|
||||
'@volar/typescript': 2.3.0-alpha.15
|
||||
'@vue/language-core': 2.0.21(typescript@5.4.5)
|
||||
semver: 7.6.2
|
||||
typescript: 5.4.5
|
||||
|
||||
|
|
Loading…
Reference in a new issue