Compare commits

...

10 commits

Author SHA1 Message Date
80e88cbdd2 update version 2025-04-28 07:05:00 +09:30
5802f61d56 Merge branch 'shark/merge' into merge/dev 2025-04-28 07:01:49 +09:30
Julia
baa75768ec merge: Merge stable into develop (!971)
View MR for information: https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/971
2025-04-27 21:26:13 +00:00
Julia Johannesen
ac905118cc
Merge branch 'stable' into merge-stable-into-develop 2025-04-27 16:19:44 -04:00
Julia
ae0ca28ae4 merge: Security fixes (!970)
View MR for information: https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/970
2025-04-27 20:06:59 +00:00
Julia Johannesen
b25f869a7a
Fix linter issue
ESLint my beloathed
2025-04-27 15:42:19 -04:00
Julia Johannesen
68d09f0e06
Use published summaly 2025-04-27 15:31:37 -04:00
Julia Johannesen
db9c8d8786
Update version 2025-04-27 13:33:09 -04:00
Julia Johannesen
35df3944c1
Update summaly 2025-04-27 13:31:27 -04:00
Julia Johannesen
0bb4e57b0c
Security fixes
Co-Authored-By: dakkar <dakkar@thenautilus.net>
2025-04-27 13:05:09 -04:00
20 changed files with 122 additions and 148 deletions

View file

@ -1,6 +1,6 @@
{
"name": "quollkey",
"version": "2025.3.8-dev",
"version": "2025.3.9-dev",
"codename": "quoll",
"repository": {
"type": "git",

View file

@ -80,7 +80,7 @@
"@fastify/static": "8.0.2",
"@fastify/view": "10.0.1",
"@misskey-dev/sharp-read-bmp": "1.2.0",
"@misskey-dev/summaly": "5.1.0",
"@transfem-org/summaly": "5.2.1",
"@nestjs/common": "10.4.7",
"@nestjs/core": "10.4.7",
"@nestjs/testing": "10.4.7",

View file

@ -506,9 +506,7 @@ export class ApRendererService {
const attachment = profile.fields.map(field => ({
type: 'PropertyValue',
name: field.name,
value: (field.value.startsWith('http://') || field.value.startsWith('https://'))
? `<a href="${new URL(field.value).href}" rel="me nofollow noopener" target="_blank">${new URL(field.value).href}</a>`
: field.value,
value: this.mfmService.toHtml(mfm.parse(field.value)),
}));
const emojis = await this.getEmojis(user.emojis);

View file

@ -4,8 +4,8 @@
*/
import { Inject, Injectable } from '@nestjs/common';
import { summaly } from '@misskey-dev/summaly';
import { SummalyResult } from '@misskey-dev/summaly/built/summary.js';
import { summaly } from '@transfem-org/summaly';
import { SummalyResult } from '@transfem-org/summaly/built/summary.js';
import * as Redis from 'ioredis';
import { DI } from '@/di-symbols.js';
import type { Config } from '@/config.js';
@ -54,12 +54,10 @@ export class UrlPreviewService {
@bindThis
private wrap(url?: string | null): string | null {
return url != null
? url.match(/^https?:\/\//)
? `${this.config.mediaProxy}/preview.webp?${query({
url,
preview: '1',
})}`
: url
: null;
}

View file

@ -38,7 +38,7 @@
"vue": "3.5.12"
},
"devDependencies": {
"@misskey-dev/summaly": "5.1.0",
"@transfem-org/summaly": "5.2.1",
"@testing-library/vue": "8.1.0",
"@types/estree": "1.0.6",
"@types/micromatch": "4.0.9",

View file

@ -0,0 +1,10 @@
/*
* SPDX-FileCopyrightText: dakkar and other Sharkey contributors
* SPDX-License-Identifier: AGPL-3.0-only
*/
export function clamp(value: number, min: number, max: number) {
if (value > max) return max;
if (value < min) return min;
return value;
}

View file

@ -26,3 +26,20 @@ export function extractDomain(url: string) {
const match = url.match(/^(?:https?:)?(?:\/\/)?(?:[^@\n]+@)?([^:\/\n]+)/im);
return match ? match[1] : null;
}
export function maybeMakeRelative(urlStr: string, baseStr: string): string {
try {
const baseObj = new URL(baseStr);
const urlObj = new URL(urlStr);
/* in all places where maybeMakeRelative is used, baseStr is the
* instance's public URL, which can't have path components, so the
* relative URL will always have the whole path from the urlStr
*/
if (urlObj.origin === baseObj.origin) {
return urlObj.pathname + urlObj.search + urlObj.hash;
}
return urlStr;
} catch (error) {
return '';
}
}

View file

@ -81,7 +81,7 @@
"cypress": "13.15.2"
},
"devDependencies": {
"@misskey-dev/summaly": "5.1.0",
"@transfem-org/summaly": "5.2.1",
"@storybook/addon-actions": "8.4.4",
"@storybook/addon-essentials": "8.4.4",
"@storybook/addon-interactions": "8.4.4",

View file

@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<component
:is="self ? 'MkA' : 'a'" ref="el" style="word-break: break-all;" class="_link" :[attr]="self ? url.substring(local.length) : url" :rel="rel ?? 'nofollow noopener'" :target="target"
:is="self ? 'MkA' : 'a'" ref="el" style="word-break: break-all;" class="_link" :[attr]="maybeRelativeUrl" :rel="rel ?? 'nofollow noopener'" :target="target"
:behavior="props.navigationBehavior"
:title="url"
@click.prevent="self ? true : warningExternalWebsite(url)"
@ -24,6 +24,7 @@ import * as os from '@/os.js';
import { isEnabledUrlPreview } from '@/instance.js';
import { MkABehavior } from '@/components/global/MkA.vue';
import { warningExternalWebsite } from '@/scripts/warning-external-website.js';
import { maybeMakeRelative } from '@@/js/url.js';
const props = withDefaults(defineProps<{
url: string;
@ -32,7 +33,8 @@ const props = withDefaults(defineProps<{
}>(), {
});
const self = props.url.startsWith(local);
const maybeRelativeUrl = maybeMakeRelative(props.url, local);
const self = maybeRelativeUrl !== props.url;
const attr = self ? 'to' : 'href';
const target = self ? null : '_blank';

View file

@ -45,8 +45,8 @@ SPDX-License-Identifier: AGPL-3.0-only
</template>
<div v-else-if="theNote" :class="[$style.link, { [$style.compact]: compact }]"><XNoteSimple :note="theNote" :class="$style.body"/></div>
<div v-else-if="!hidePreview">
<component :is="self ? 'MkA' : 'a'" :class="[$style.link, { [$style.compact]: compact }]" :[attr]="self ? url.substring(local.length) : url" rel="nofollow noopener" :target="target" :title="url" @click.prevent="self ? true : warningExternalWebsite(url)" @click.stop>
<div v-if="thumbnail && !sensitive" :class="$style.thumbnail" :style="defaultStore.state.dataSaver.urlPreview ? '' : `background-image: url('${thumbnail}')`">
<component :is="self ? 'MkA' : 'a'" :class="[$style.link, { [$style.compact]: compact }]" :[attr]="maybeRelativeUrl" rel="nofollow noopener" :target="target" :title="url" @click.prevent="self ? true : warningExternalWebsite(url)" @click.stop>
<div v-if="thumbnail && !sensitive" :class="$style.thumbnail" :style="defaultStore.state.dataSaver.urlPreview ? '' : { backgroundImage: `url('${thumbnail}')` }">
</div>
<article :class="$style.body">
<header :class="$style.header">
@ -93,7 +93,7 @@ import { defineAsyncComponent, onDeactivated, onUnmounted, ref, watch } from 'vu
import { url as local } from '@@/js/config.js';
import { versatileLang } from '@@/js/intl-const.js';
import * as Misskey from 'misskey-js';
import type { summaly } from '@misskey-dev/summaly';
import type { summaly } from '@transfem-org/summaly';
import type MkNoteSimple from '@/components/MkNoteSimple.vue';
import type SkNoteSimple from '@/components/SkNoteSimple.vue';
import { i18n } from '@/i18n.js';
@ -104,6 +104,7 @@ import { transformPlayerUrl } from '@/scripts/player-url-transform.js';
import { defaultStore } from '@/store.js';
import { misskeyApi } from '@/scripts/misskey-api.js';
import { warningExternalWebsite } from '@/scripts/warning-external-website.js';
import { maybeMakeRelative } from '@@/js/url.js';
const XNoteSimple = defineAsyncComponent<typeof MkNoteSimple | typeof SkNoteSimple>(() =>
defaultStore.state.noteDesign === 'misskey'
@ -132,7 +133,8 @@ const MOBILE_THRESHOLD = 500;
const isMobile = ref(deviceKind === 'smartphone' || window.innerWidth <= MOBILE_THRESHOLD);
const hidePreview = ref<boolean>(false);
const self = props.url.startsWith(local);
const maybeRelativeUrl = maybeMakeRelative(props.url, local);
const self = maybeRelativeUrl !== props.url;
const attr = self ? 'to' : 'href';
const target = self ? null : '_blank';
const fetching = ref(true);

View file

@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<div class="_panel" :class="$style.root">
<div :class="$style.banner" :style="user.bannerUrl ? `background-image: url(${defaultStore.state.disableShowingAnimatedImages ? getStaticImageUrl(user.bannerUrl) : user.bannerUrl})` : ''"></div>
<div :class="$style.banner" :style="user.bannerUrl ? { backgroundImage: `url(${defaultStore.state.disableShowingAnimatedImages ? getStaticImageUrl(user.bannerUrl) : user.bannerUrl})` } : ''"></div>
<MkAvatar :class="$style.avatar" :user="user" indicator/>
<div :class="$style.title">
<MkA :class="$style.name" :to="userPage(user)"><MkUserName :user="user" :nowrap="false"/></MkA>

View file

@ -13,7 +13,7 @@ SPDX-License-Identifier: AGPL-3.0-only
>
<div v-if="showing" :class="$style.root" class="_popup _shadow" :style="{ zIndex, top: top + 'px', left: left + 'px' }" @mouseover="() => { emit('mouseover'); }" @mouseleave="() => { emit('mouseleave'); }">
<div v-if="user != null">
<div :class="$style.banner" :style="user.bannerUrl ? `background-image: url(${defaultStore.state.disableShowingAnimatedImages ? getStaticImageUrl(user.bannerUrl) : user.bannerUrl})` : ''">
<div :class="$style.banner" :style="user.bannerUrl ? { backgroundImage: `url(${defaultStore.state.disableShowingAnimatedImages ? getStaticImageUrl(user.bannerUrl) : user.bannerUrl})` } : ''">
<span v-if="$i && $i.id != user.id && user.isFollowed && user.isFollowing" :class="$style.followed">{{ i18n.ts.mutuals }}</span>
<span v-else-if="$i && $i.id != user.id && user.isFollowed" :class="$style.followed">{{ i18n.ts.followsYou }}</span>
<span v-else-if="$i && $i.id != user.id && user.isFollowing" :class="$style.followed">{{ i18n.ts.following }}</span>

View file

@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<div v-adaptive-bg class="_panel" style="position: relative;">
<div :class="$style.banner" :style="user.bannerUrl ? `background-image: url(${user.bannerUrl})` : ''"></div>
<div :class="$style.banner" :style="user.bannerUrl ? { backgroundImage: `url(${user.bannerUrl})` } : ''"></div>
<MkAvatar :class="$style.avatar" :user="user" indicator/>
<div :class="$style.title">
<div :class="$style.name"><MkUserName :user="user" :nowrap="false"/></div>

View file

@ -20,6 +20,7 @@ import MkGoogle from '@/components/MkGoogle.vue';
import MkSparkle from '@/components/MkSparkle.vue';
import MkA, { MkABehavior } from '@/components/global/MkA.vue';
import { defaultStore } from '@/store.js';
import { clamp } from '@@/js/math.js';
function safeParseFloat(str: unknown): number | null {
if (typeof str !== 'string' || str === '') return null;
@ -309,10 +310,10 @@ export default function (props: MfmProps, { emit }: { emit: SetupContext<MfmEven
style = '';
break;
}
const x = Math.min(safeParseFloat(token.props.args.x) ?? 1, 5);
const y = Math.min(safeParseFloat(token.props.args.y) ?? 1, 5);
const x = clamp(safeParseFloat(token.props.args.x) ?? 1, -5, 5);
const y = clamp(safeParseFloat(token.props.args.y) ?? 1, -5, 5);
style = `transform: scale(${x}, ${y});`;
scale = scale * Math.max(x, y);
scale = scale * Math.max(Math.abs(x), Math.abs(y));
break;
}
case 'fg': {

View file

@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<component
:is="self ? 'MkA' : 'a'" ref="el" :class="$style.root" class="_link" :[attr]="self ? props.url.substring(local.length) : props.url" :rel="rel ?? 'nofollow noopener'" :target="target"
:is="self ? 'MkA' : 'a'" ref="el" :class="$style.root" class="_link" :[attr]="maybeRelativeUrl" :rel="rel ?? 'nofollow noopener'" :target="target"
:behavior="props.navigationBehavior"
@contextmenu.stop="() => {}"
@click.prevent="self ? true : warningExternalWebsite(props.url)"
@ -35,6 +35,7 @@ import { useTooltip } from '@/scripts/use-tooltip.js';
import { isEnabledUrlPreview } from '@/instance.js';
import { MkABehavior } from '@/components/global/MkA.vue';
import { warningExternalWebsite } from '@/scripts/warning-external-website.js';
import { maybeMakeRelative } from '@@/js/url.js';
function safeURIDecode(str: string): string {
try {
@ -53,7 +54,8 @@ const props = withDefaults(defineProps<{
showUrlPreview: true,
});
const self = props.url.startsWith(local);
const maybeRelativeUrl = maybeMakeRelative(props.url, local);
const self = maybeRelativeUrl !== props.url;
const url = new URL(props.url);
if (!['http:', 'https:'].includes(url.protocol)) throw new Error('invalid url');
const el = ref();

View file

@ -68,7 +68,7 @@ export function createAiScriptEnv(opts: { storageKey: string, token?: string })
}),
'Mk:api': values.FN_NATIVE(async ([ep, param, token]) => {
utils.assertString(ep);
if (ep.value.includes('://')) {
if (ep.value.includes('://') || ep.value.includes('..')) {
throw new errors.AiScriptRuntimeError('invalid endpoint');
}
if (token) {

View file

@ -14,7 +14,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<div
v-for="(image, i) in images" :key="i"
:class="$style.img"
:style="`background-image: url(${thumbnail(image)})`"
:style="{ backgroundImage: `url(${thumbnail(image)})` }"
></div>
</div>
</div>

View file

@ -34,7 +34,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<rect
x="-2" y="-2"
:width="viewBoxX + 4" :height="viewBoxY + 4"
:style="`stroke: none; fill: url(#${ cpuGradientId }); mask: url(#${ cpuMaskId })`"
:style="{ stroke: 'none', fill: `url(#${ cpuGradientId })`, mask: `url(#${ cpuMaskId })` }"
/>
<text x="1" y="5">CPU <tspan>{{ cpuP }}%</tspan></text>
</svg>
@ -67,7 +67,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<rect
x="-2" y="-2"
:width="viewBoxX + 4" :height="viewBoxY + 4"
:style="`stroke: none; fill: url(#${ memGradientId }); mask: url(#${ memMaskId })`"
:style="{ stroke: 'none', fill: `url(#${ memGradientId })`, mask: `url(#${ memMaskId })` }"
/>
<text x="1" y="5">MEM <tspan>{{ memP }}%</tspan></text>
</svg>

View file

@ -6,7 +6,7 @@
import { describe, test, assert, afterEach } from 'vitest';
import { render, cleanup, type RenderResult } from '@testing-library/vue';
import './init';
import type { summaly } from '@misskey-dev/summaly';
import type { summaly } from '@transfem-org/summaly';
import { components } from '@/components/index.js';
import { directives } from '@/directives/index.js';
import MkUrlPreview from '@/components/MkUrlPreview.vue';

172
pnpm-lock.yaml generated
View file

@ -125,9 +125,6 @@ importers:
'@misskey-dev/sharp-read-bmp':
specifier: 1.2.0
version: 1.2.0
'@misskey-dev/summaly':
specifier: 5.1.0
version: 5.1.0
'@nestjs/common':
specifier: 10.4.7
version: 10.4.7(reflect-metadata@0.2.2)(rxjs@7.8.1)
@ -164,6 +161,9 @@ importers:
'@transfem-org/sfm-js':
specifier: 0.24.6
version: 0.24.6
'@transfem-org/summaly':
specifier: 5.2.1
version: 5.2.1
'@twemoji/parser':
specifier: 15.1.1
version: 15.1.1
@ -894,9 +894,6 @@ importers:
specifier: 13.15.2
version: 13.15.2
devDependencies:
'@misskey-dev/summaly':
specifier: 5.1.0
version: 5.1.0
'@storybook/addon-actions':
specifier: 8.4.4
version: 8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))
@ -954,6 +951,9 @@ importers:
'@testing-library/vue':
specifier: 8.1.0
version: 8.1.0(@vue/compiler-sfc@3.5.12)(@vue/server-renderer@3.5.12(vue@3.5.12(typescript@5.6.3)))(vue@3.5.12(typescript@5.6.3))
'@transfem-org/summaly':
specifier: 5.2.1
version: 5.2.1
'@types/canvas-confetti':
specifier: ^1.6.4
version: 1.6.4
@ -1159,12 +1159,12 @@ importers:
specifier: 3.5.12
version: 3.5.12(typescript@5.6.3)
devDependencies:
'@misskey-dev/summaly':
specifier: 5.1.0
version: 5.1.0
'@testing-library/vue':
specifier: 8.1.0
version: 8.1.0(@vue/compiler-sfc@3.5.12)(@vue/server-renderer@3.5.12(vue@3.5.12(typescript@5.6.3)))(vue@3.5.12(typescript@5.6.3))
'@transfem-org/summaly':
specifier: 5.2.1
version: 5.2.1
'@types/estree':
specifier: 1.0.6
version: 1.0.6
@ -2022,6 +2022,9 @@ packages:
'@canvas/image-data@1.0.0':
resolution: {integrity: sha512-BxOqI5LgsIQP1odU5KMwV9yoijleOPzHL18/YvNqF9KFSGF2K/DLlYAbDQsWqd/1nbaFuSkYD/191dpMtNh4vw==}
'@chainsafe/is-ip@2.1.0':
resolution: {integrity: sha512-KIjt+6IfysQ4GCv66xihEitBjvhU/bixbbbFxdJ1sqCp4uJ0wuZiYBPhksZoy4lfaF0k9cwNzY5upEW/VWdw3w==}
'@colors/colors@1.5.0':
resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==}
engines: {node: '>=0.1.90'}
@ -2968,9 +2971,6 @@ packages:
'@misskey-dev/sharp-read-bmp@1.2.0':
resolution: {integrity: sha512-er4pRakXzHYfEgOFAFfQagqDouG+wLm+kwNq1I30oSdIHDa0wM3KjFpfIGQ25Fks4GcmOl1s7Zh6xoQu5dNjTw==}
'@misskey-dev/summaly@5.1.0':
resolution: {integrity: sha512-WAUrgX3/z4h4aI8Y/WVwmJcJ6Fa1Zf2LJCSS651t9MHoWVGABLsQ2KCXRGmlpk4i+cMDNIwweObUroosE7j8rg==}
'@mole-inc/bin-wrapper@8.0.1':
resolution: {integrity: sha512-sTGoeZnjI8N4KS+sW2AN95gDBErhAguvkw/tWdCjeM8bvxpz5lqrnd0vOJABA1A+Ic3zED7PYoLP/RANLgVotA==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
@ -3611,10 +3611,6 @@ packages:
resolution: {integrity: sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==}
engines: {node: '>=10'}
'@sindresorhus/is@5.3.0':
resolution: {integrity: sha512-CX6t4SYQ37lzxicAqsBtxA3OseeoVrh9cSJ5PFYam0GksYlupRfy1A+Q4aYD3zvcfECLc0zO2u+ZnR2UYKvCrw==}
engines: {node: '>=14.16'}
'@sindresorhus/is@7.0.1':
resolution: {integrity: sha512-QWLl2P+rsCJeofkDNIT3WFmb6NrRud1SUYW8dIhXK/46XFV8Q/g7Bsvib0Askb0reRLe+WYPeeE+l5cH7SlkuQ==}
engines: {node: '>=18'}
@ -4289,6 +4285,8 @@ packages:
'@transfem-org/sfm-js@0.24.6':
resolution: {integrity: sha1-7t+TkCd3PZk+RbbrGbZ/iMs2y7o=, tarball: https://activitypub.software/api/v4/projects/2/packages/npm/@transfem-org/sfm-js/-/@transfem-org/sfm-js-0.24.6.tgz}
'@transfem-org/summaly@5.2.1':
resolution: {integrity: sha1-bSQjLRWt0g/UkhYnGjT5/UPig20=, tarball: https://activitypub.software/api/v4/projects/217/packages/npm/@transfem-org/summaly/-/@transfem-org/summaly-5.2.1.tgz}
'@trysound/sax@0.2.0':
resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==}
@ -5453,10 +5451,6 @@ packages:
resolution: {integrity: sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==}
engines: {node: '>=14.16'}
cacheable-request@10.2.14:
resolution: {integrity: sha512-zkDT5WAF4hSSoUgyfg5tFIxz8XQK+25W/TLVojJTMKBaxevLBBtLxgqguAuVQB8PVW79FVjHcU+GJ9tVbDZ9mQ==}
engines: {node: '>=14.16'}
cacheable-request@12.0.1:
resolution: {integrity: sha512-Yo9wGIQUaAfIbk+qY0X4cDQgCosecfBe3V9NSyeY4qPC2SAkbCS4Xj79VP8WOzitpJUZKc/wsRCYF5ariDIwkg==}
engines: {node: '>=18'}
@ -5611,10 +5605,6 @@ packages:
resolution: {integrity: sha512-quS9HgjQpdaXOvsZz82Oz7uxtXiy6UIsIQcpBj7HRw2M63Skasm9qlDocAM7jNuaxdhpPU7c4kJN+gA5MCu4ww==}
engines: {node: '>=18.17'}
cheerio@1.0.0-rc.12:
resolution: {integrity: sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==}
engines: {node: '>= 6'}
chokidar@3.5.3:
resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==}
engines: {node: '>= 8.10.0'}
@ -6798,10 +6788,6 @@ packages:
forever-agent@0.6.1:
resolution: {integrity: sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==}
form-data-encoder@2.1.4:
resolution: {integrity: sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==}
engines: {node: '>= 14.17'}
form-data-encoder@4.0.2:
resolution: {integrity: sha512-KQVhvhK8ZkWzxKxOr56CPulAhH3dobtuQ4+hNQ+HekH/Wp5gSOafqRAeTphQUJAIk0GBvHZgJ2ZGRWd5kphMuw==}
engines: {node: '>= 18'}
@ -7004,14 +6990,14 @@ packages:
resolution: {integrity: sha512-o0Je4NvQObAuZPHLFoRSkdG2lTgtcynqymzg2Vupdx6PorhaT5MCbIyXG6d4D94kk8ZG57QeosgdiqfJWhEhlQ==}
engines: {node: '>=10.19.0'}
got@12.6.1:
resolution: {integrity: sha512-mThBblvlAF1d4O5oqyvN+ZxLAYwIJK7bpMxgYqPD9okW0C3qm5FFn7k811QrcuEBwaogR3ngOFoCfs6mRv7teQ==}
engines: {node: '>=14.16'}
got@14.4.4:
resolution: {integrity: sha512-tqiF7eSgTBwQkxb1LxsEpva8TaMYVisbhplrFVmw9GQE3855Z+MH/mnsXLLOkDxR6hZJRFMj5VTAZ8lmTF8ZOA==}
engines: {node: '>=20'}
got@14.4.7:
resolution: {integrity: sha512-DI8zV1231tqiGzOiOzQWDhsBmncFW7oQDH6Zgy6pDPrqJuVZMtoSgPLLsBZQj8Jg4JFfwoOsDA8NGtLQLnIx2g==}
engines: {node: '>=20'}
graceful-fs@4.2.11:
resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
@ -7127,8 +7113,8 @@ packages:
resolution: {integrity: sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==}
engines: {node: '>=18'}
html-entities@2.3.2:
resolution: {integrity: sha512-c3Ab/url5ksaT0WyleslpBEthOzWhrjQbg75y7XUsfSzi3Dgzt0l8w5e7DylRn15MTlMMD58dTfzddNS2kcAjQ==}
html-entities@2.5.2:
resolution: {integrity: sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==}
html-escaper@2.0.2:
resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==}
@ -7304,9 +7290,9 @@ packages:
resolution: {integrity: sha512-KifhLKBjdS/hB3TD4UUOalVp1BpzPFvRpgJvXcP0Ya98tuSQTUQ71iI7EW7CKddkBJTYB3GfTWl5eJwpLOXj2A==}
engines: {node: '>=16.14.0'}
ip-regex@4.3.0:
resolution: {integrity: sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q==}
engines: {node: '>=8'}
ip-regex@5.0.0:
resolution: {integrity: sha512-fOCG6lhoKKakwv+C6KdsOnGvgXnmgfmp0myi3bcNwj3qfwPAxRKWEuFhvEFF7ceYIz6+1jRZ+yguLFAmUNPEfw==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
ip@2.0.1:
resolution: {integrity: sha512-lJUL9imLTNi1ZfXT+DU6rBBdbiKGBuay9B6xGSPVjUeQwaH1RIGqef8RZkUtHioLmSNpPR5M4HVKJGm1j8FWVQ==}
@ -7405,10 +7391,6 @@ packages:
resolution: {integrity: sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==}
engines: {node: '>=10'}
is-ip@3.1.0:
resolution: {integrity: sha512-35vd5necO7IitFPjd/YBeqwWnyDWbuLH9ZXQdMfDA8TEo7pv5X8yfrvVO3xbJbLUlERCMvf6X0hTUamQxCYJ9Q==}
engines: {node: '>=8'}
is-lambda@1.0.1:
resolution: {integrity: sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==}
@ -7762,8 +7744,8 @@ packages:
jsbn@1.1.0:
resolution: {integrity: sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==}
jschardet@3.0.0:
resolution: {integrity: sha512-lJH6tJ77V8Nzd5QWRkFYCLc13a3vADkh3r/Fi8HupZGWk2OVVDfnZP8V/VgQgZ+lzW0kG2UGb5hFgt3V3ndotQ==}
jschardet@3.1.4:
resolution: {integrity: sha512-/kmVISmrwVwtyYU40iQUOp3SUPk2dhNCMsZBQX0R1/jZ8maaXJ/oZIzUOiyOqcgtLnETFKYChbJ5iDC/eWmFHg==}
engines: {node: '>=0.1.90'}
jsdoc-type-pratt-parser@4.1.0:
@ -8751,10 +8733,6 @@ packages:
resolution: {integrity: sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==}
engines: {node: '>=8'}
p-cancelable@3.0.0:
resolution: {integrity: sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==}
engines: {node: '>=12.20'}
p-cancelable@4.0.1:
resolution: {integrity: sha512-wBowNApzd45EIKdO1LaU+LrMBwAcjfPaYtVzV3lmfM3gf8Z4CHZsiIqlM8TZZ8okYvh5A1cP6gTfCRQtwUpaUg==}
engines: {node: '>=14.16'}
@ -9281,8 +9259,9 @@ packages:
resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
private-ip@2.3.3:
resolution: {integrity: sha512-5zyFfekIVUOTVbL92hc8LJOtE/gyGHeREHkJ2yTyByP8Q2YZVoBqLg3EfYLeF0oVvGqtaEX2t2Qovja0/gStXw==}
private-ip@3.0.2:
resolution: {integrity: sha512-2pkOVPGYD/4QyAg95c6E/4bLYXPthT5Xw4ocXYzIIsMBhskOMn6IwkWXmg6ZiA6K58+O6VD/n02r1hDhk7vDPw==}
engines: {node: '>=14.16'}
probe-image-size@7.2.3:
resolution: {integrity: sha512-HubhG4Rb2UH8YtV4ba0Vp5bQ7L78RTONYu/ujmCu5nBI8wGv24s4E9xSKBi0N1MowRpxk76pFCpJtW0KPzOK0w==}
@ -10450,9 +10429,6 @@ packages:
resolution: {integrity: sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==}
engines: {node: '>=18'}
trace-redirect@1.0.6:
resolution: {integrity: sha512-UUfa1DjjU5flcjMdaFIiIEGDTyu2y/IiMjOX4uGXa7meKBS4vD4f2Uy/tken9Qkd4Jsm4sRsfZcIIPqrRVF3Mg==}
tree-kill@1.2.2:
resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==}
hasBin: true
@ -10982,8 +10958,8 @@ packages:
vue-component-type-helpers@2.1.10:
resolution: {integrity: sha512-lfgdSLQKrUmADiSV6PbBvYgQ33KF3Ztv6gP85MfGaGaSGMTXORVaHT1EHfsqCgzRNBstPKYDmvAV9Do5CmJ07A==}
vue-component-type-helpers@2.2.8:
resolution: {integrity: sha512-4bjIsC284coDO9om4HPA62M7wfsTvcmZyzdfR0aUlFXqq4tXxM1APyXpNVxPC8QazKw9OhmZNHBVDA6ODaZsrA==}
vue-component-type-helpers@2.2.10:
resolution: {integrity: sha512-iDUO7uQK+Sab2tYuiP9D1oLujCWlhHELHMgV/cB13cuGbG4qwkLHvtfWb6FzvxrIOPDnU0oHsz2MlQjhYDeaHA==}
vue-demi@0.14.7:
resolution: {integrity: sha512-EOG8KXDQNwkJILkx/gPcoL/7vH+hORoBaKgGe+6W7VFMvCYJfmF2dGbvgDroVnI8LU7/kTu8mbjRZGBU1z9NTA==}
@ -12223,6 +12199,8 @@ snapshots:
'@canvas/image-data@1.0.0': {}
'@chainsafe/is-ip@2.1.0': {}
'@colors/colors@1.5.0':
optional: true
@ -13167,17 +13145,6 @@ snapshots:
decode-ico: 0.4.1
sharp: 0.33.5
'@misskey-dev/summaly@5.1.0':
dependencies:
cheerio: 1.0.0-rc.12
escape-regexp: 0.0.1
got: 12.6.1
html-entities: 2.3.2
iconv-lite: 0.6.3
jschardet: 3.0.0
private-ip: 2.3.3
trace-redirect: 1.0.6
'@mole-inc/bin-wrapper@8.0.1':
dependencies:
bin-check: 4.1.0
@ -13946,8 +13913,6 @@ snapshots:
'@sindresorhus/is@4.6.0': {}
'@sindresorhus/is@5.3.0': {}
'@sindresorhus/is@7.0.1': {}
'@sinonjs/commons@2.0.0':
@ -14620,7 +14585,7 @@ snapshots:
ts-dedent: 2.2.0
type-fest: 2.19.0
vue: 3.5.12(typescript@5.6.3)
vue-component-type-helpers: 2.2.8
vue-component-type-helpers: 2.2.10
'@swc/cli@0.3.12(@swc/core@1.9.2)(chokidar@3.5.3)':
dependencies:
@ -14809,6 +14774,15 @@ snapshots:
'@transfem-org/sfm-js@0.24.6':
dependencies:
'@twemoji/parser': 15.0.0
'@transfem-org/summaly@5.2.1':
dependencies:
cheerio: 1.0.0
escape-regexp: 0.0.1
got: 14.4.7
html-entities: 2.5.2
iconv-lite: 0.6.3
jschardet: 3.1.4
private-ip: 3.0.2
'@trysound/sax@0.2.0': {}
@ -16317,16 +16291,6 @@ snapshots:
cacheable-lookup@7.0.0: {}
cacheable-request@10.2.14:
dependencies:
'@types/http-cache-semantics': 4.0.4
get-stream: 6.0.1
http-cache-semantics: 4.1.1
keyv: 4.5.4
mimic-response: 4.0.0
normalize-url: 8.0.1
responselike: 3.0.0
cacheable-request@12.0.1:
dependencies:
'@types/http-cache-semantics': 4.0.4
@ -16495,7 +16459,7 @@ snapshots:
css-what: 6.1.0
domelementtype: 2.3.0
domhandler: 5.0.3
domutils: 3.0.1
domutils: 3.1.0
cheerio@1.0.0:
dependencies:
@ -16511,16 +16475,6 @@ snapshots:
undici: 6.20.0
whatwg-mimetype: 4.0.0
cheerio@1.0.0-rc.12:
dependencies:
cheerio-select: 2.1.0
dom-serializer: 2.0.0
domhandler: 5.0.3
domutils: 3.0.1
htmlparser2: 8.0.1
parse5: 7.2.1
parse5-htmlparser2-tree-adapter: 7.0.0
chokidar@3.5.3:
dependencies:
anymatch: 3.1.3
@ -16797,7 +16751,7 @@ snapshots:
boolbase: 1.0.0
css-what: 6.1.0
domhandler: 5.0.3
domutils: 3.0.1
domutils: 3.1.0
nth-check: 2.1.1
css-tree@2.2.1:
@ -18154,8 +18108,6 @@ snapshots:
forever-agent@0.6.1:
optional: true
form-data-encoder@2.1.4: {}
form-data-encoder@4.0.2: {}
form-data@4.0.0:
@ -18390,21 +18342,21 @@ snapshots:
p-cancelable: 2.1.1
responselike: 2.0.1
got@12.6.1:
got@14.4.4:
dependencies:
'@sindresorhus/is': 5.3.0
'@sindresorhus/is': 7.0.1
'@szmarczak/http-timer': 5.0.1
cacheable-lookup: 7.0.0
cacheable-request: 10.2.14
cacheable-request: 12.0.1
decompress-response: 6.0.0
form-data-encoder: 2.1.4
get-stream: 6.0.1
form-data-encoder: 4.0.2
http2-wrapper: 2.2.1
lowercase-keys: 3.0.0
p-cancelable: 3.0.0
p-cancelable: 4.0.1
responselike: 3.0.0
type-fest: 4.27.0
got@14.4.4:
got@14.4.7:
dependencies:
'@sindresorhus/is': 7.0.1
'@szmarczak/http-timer': 5.0.1
@ -18525,7 +18477,7 @@ snapshots:
dependencies:
whatwg-encoding: 3.1.1
html-entities@2.3.2: {}
html-entities@2.5.2: {}
html-escaper@2.0.2: {}
@ -18715,7 +18667,7 @@ snapshots:
dependencies:
ip-address: 9.0.5
ip-regex@4.3.0: {}
ip-regex@5.0.0: {}
ip@2.0.1: {}
@ -18805,10 +18757,6 @@ snapshots:
is-path-inside: 3.0.3
optional: true
is-ip@3.1.0:
dependencies:
ip-regex: 4.3.0
is-lambda@1.0.1: {}
is-map@2.0.2: {}
@ -19351,7 +19299,7 @@ snapshots:
jsbn@1.1.0: {}
jschardet@3.0.0: {}
jschardet@3.1.4: {}
jsdoc-type-pratt-parser@4.1.0: {}
@ -20600,8 +20548,6 @@ snapshots:
p-cancelable@2.1.1: {}
p-cancelable@3.0.0: {}
p-cancelable@4.0.1: {}
p-finally@1.0.0: {}
@ -21090,11 +21036,11 @@ snapshots:
ansi-styles: 5.2.0
react-is: 18.2.0
private-ip@2.3.3:
private-ip@3.0.2:
dependencies:
ip-regex: 4.3.0
'@chainsafe/is-ip': 2.1.0
ip-regex: 5.0.0
ipaddr.js: 2.2.0
is-ip: 3.1.0
netmask: 2.0.2
probe-image-size@7.2.3:
@ -22408,8 +22354,6 @@ snapshots:
dependencies:
punycode: 2.3.1
trace-redirect@1.0.6: {}
tree-kill@1.2.2:
optional: true
@ -22993,7 +22937,7 @@ snapshots:
vue-component-type-helpers@2.1.10: {}
vue-component-type-helpers@2.2.8: {}
vue-component-type-helpers@2.2.10: {}
vue-demi@0.14.7(vue@3.5.12(typescript@5.6.3)):
dependencies: