Compare commits

...

37 Commits

Author SHA1 Message Date
tamaina 67c4b7895e ✌️ 2023-08-09 03:56:43 +00:00
tamaina de956d8dee fix 2023-08-09 03:39:03 +00:00
tamaina 79d12d1ceb wrap? 2023-08-09 02:12:21 +00:00
tamaina 4ff9390194 triggerRef 2023-08-09 01:28:38 +00:00
tamaina 0e267f25a7 Merge branch 'develop' into noman 2023-08-09 01:19:02 +00:00
tamaina ccecf3cdd0 Merge branch 'fix-menu' into noman 2023-08-09 01:18:57 +00:00
syuilo dc8a130570 use node 20.5.0 2023-08-09 09:52:30 +09:00
HAL9000COM 41ba242c9c
Update node to 20.5.0 (#11463) 2023-08-09 09:52:01 +09:00
tamaina e6f3dd81ba
fix(frontend): MkPopupMenuがドロワーで子メニューの出現と同時にpopupをresolveさせるのをやめさせる (#11441)
* fix(frontend): MkPopupMenuがドロワーで子メニューの出現と同時にpopupをresolveさせるのをやめさせる

* fix

* noCache

* ✌️

* fix

* ????

* a

* a

* ✌️

* fix emoji picker

* ?????

* close

* 1

* fix2

* ✌️

* fix

* ✌️

* ✌️

* ✌️

* preferClick

* ✌️

* fix lint

* a

* rm nocache
2023-08-09 09:08:47 +09:00
Kagami Sascha Rosylight ec229dbd3b
fix(backend/ApNoteService): try retrieving again when failed by duplication (#11472)
* fix(backend/ApNoteService): try retrieving again when failed by duplication

* Update CHANGELOG.md

---------

Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>
2023-08-08 13:26:03 +09:00
tamaina f6a3f6f5f1
enhance(backend): Improve behavior of correctFilename (#11484)
* enhance(backend): Improve behavior of correctFilename

* ✌️

* 未知のファイル形式かつ拡張子がある場合は何もしない

* ✌️

* .ext

---------

Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>
2023-08-08 13:24:30 +09:00
anatawa12 b26e4dc505
fix: muteがapiからのuser list timeline取得で機能しない (#11480) 2023-08-08 13:23:25 +09:00
Srgr0 43375409f7
fix(frontend): webkit-text-size-adjustを100%に固定する (#11487)
* disable webkit-text-size-adjust

* Update CHANGELOG.md
2023-08-08 13:22:01 +09:00
tamaina fb924e6dc3 rm nocache 2023-08-06 12:41:53 +00:00
tamaina 89c245c5e4 Merge branch 'develop' into fix-menu 2023-08-05 13:17:07 +00:00
tamaina fe04bc6fb1 a 2023-08-05 13:16:32 +00:00
tamaina 58894838f0 fix lint 2023-08-04 14:53:47 +00:00
tamaina 5a3d7f9ef8 ✌️ 2023-08-04 14:14:09 +00:00
tamaina 68a2d9675f preferClick 2023-08-04 13:18:11 +00:00
tamaina 9165dc4493 ✌️ 2023-08-04 13:09:25 +00:00
tamaina 6eaadfac7b ✌️ 2023-08-04 13:01:26 +00:00
tamaina 1294f5f06f ✌️ 2023-08-04 12:56:06 +00:00
tamaina c73ec73920 fix 2023-08-04 12:48:11 +00:00
tamaina 8a3dbc1c99 ✌️ 2023-08-04 12:46:45 +00:00
tamaina d25c38911d fix2 2023-08-04 12:05:52 +00:00
tamaina f7511ac93c 1 2023-08-04 12:05:07 +00:00
tamaina ba6399fac6 close 2023-08-04 07:09:23 +00:00
tamaina da3ca548fe ????? 2023-08-03 05:16:25 +00:00
tamaina 01ff597e65 fix emoji picker 2023-08-03 03:57:27 +00:00
tamaina 615e25f4fa ✌️ 2023-08-03 03:07:28 +00:00
tamaina 225eabb19d a 2023-08-03 02:11:27 +00:00
tamaina 718021f15c a 2023-08-02 01:12:28 +00:00
tamaina 485f89d262 ???? 2023-08-01 14:28:44 +00:00
tamaina 93e8317da1 fix 2023-08-01 12:09:21 +00:00
tamaina 39d686ad11 ✌️ 2023-08-01 11:24:37 +00:00
tamaina d60aa72c63 noCache 2023-08-01 11:17:27 +00:00
tamaina ed36a08bad fix 2023-08-01 07:38:25 +00:00
18 changed files with 237 additions and 113 deletions

View File

@ -6,7 +6,7 @@
"features": {
"ghcr.io/devcontainers-contrib/features/pnpm:2": {},
"ghcr.io/devcontainers/features/node:1": {
"version": "20.3.1"
"version": "20.5.0"
}
},
"forwardPorts": [3000],

View File

@ -1 +1 @@
20.3.1
20.5.0

View File

@ -25,9 +25,13 @@
- Enhance: 自分が押したリアクションのデザインを改善
- Fix: サーバー情報画面(`/instance-info/{domain}`)でブロックができないのを修正
- Fix: 未読のお知らせの「わかった」をクリック・タップしてもその場で「わかった」が消えない問題を修正
- Fix: iOSで画面を回転させるとテキストサイズが変わる問題を修正
### Server
- cacheRemoteFilesの初期値はfalseになりました
- 一部のfeatured noteを照会できない問題を修正
- ファイルアップロード時等にファイル名の拡張子を修正する関数(correctFilename)の挙動を改善
- fix: muteがapiからのuser list timeline取得で機能しない問題を修正
## 13.14.2

View File

@ -1,6 +1,6 @@
# syntax = docker/dockerfile:1.4
ARG NODE_VERSION=20.3.1-bullseye
ARG NODE_VERSION=20.5.0-bullseye
# build assets & compile TypeScript

View File

@ -131,13 +131,13 @@ export class ApNoteService {
this.logger.debug(`Note fetched: ${JSON.stringify(note, null, 2)}`);
if (note.id && !checkHttps(note.id)) {
throw new Error('unexpected shcema of note.id: ' + note.id);
throw new Error('unexpected schema of note.id: ' + note.id);
}
const url = getOneApHrefNullable(note.url);
if (url && !checkHttps(url)) {
throw new Error('unexpected shcema of note url: ' + url);
throw new Error('unexpected schema of note url: ' + url);
}
this.logger.info(`Creating the Note: ${note.id}`);
@ -271,24 +271,36 @@ export class ApNoteService {
const poll = await this.apQuestionService.extractPollFromQuestion(note, resolver).catch(() => undefined);
return await this.noteCreateService.create(actor, {
createdAt: note.published ? new Date(note.published) : null,
files,
reply,
renote: quote,
name: note.name,
cw,
text,
localOnly: false,
visibility,
visibleUsers,
apMentions,
apHashtags,
apEmojis,
poll,
uri: note.id,
url: url,
}, silent);
try {
return await this.noteCreateService.create(actor, {
createdAt: note.published ? new Date(note.published) : null,
files,
reply,
renote: quote,
name: note.name,
cw,
text,
localOnly: false,
visibility,
visibleUsers,
apMentions,
apHashtags,
apEmojis,
poll,
uri: note.id,
url: url,
}, silent);
} catch (err: any) {
if (err.name !== 'duplicated') {
throw err;
}
this.logger.info('The note is already inserted while creating itself, reading again');
const duplicate = await this.fetchNote(value);
if (!duplicate) {
throw new Error('The note creation failed with duplication error even when there is no duplication');
}
return duplicate;
}
}
/**

View File

@ -3,18 +3,54 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
// 与えられた拡張子とファイル名が一致しているかどうかを確認し、
// 一致していない場合は拡張子を付与して返す
/**
* Array.includes()Set.has()
*/
const targetExtsToSkip = new Set([
'.gz',
'.tar',
'.tgz',
'.bz2',
'.xz',
'.zip',
'.7z',
]);
const extRegExp = /\.[0-9a-zA-Z]+$/i;
/**
*
*
*
* extはfile-typeのextを想定
*/
export function correctFilename(filename: string, ext: string | null) {
const dotExt = ext ? ext.startsWith('.') ? ext : `.${ext}` : '.unknown';
if (filename.endsWith(dotExt)) {
return filename;
}
if (ext === 'jpg' && filename.endsWith('.jpeg')) {
return filename;
}
if (ext === 'tif' && filename.endsWith('.tiff')) {
const dotExt = ext ? ext[0] === '.' ? ext : `.${ext}` : '.unknown';
const match = extRegExp.exec(filename);
if (!match || !match[0]) {
// filenameが拡張子を持っていない場合は拡張子をつける
return `${filename}${dotExt}`;
}
const filenameExt = match[0].toLowerCase();
if (
// 未知のファイル形式かつ拡張子がある場合は何もしない
ext === null ||
// 拡張子が一致している場合は何もしない
filenameExt === dotExt ||
// jpeg, tiffを同一視
dotExt === '.jpg' && filenameExt === '.jpeg' ||
dotExt === '.tif' && filenameExt === '.tiff' ||
// 圧縮形式っぽければ下手に拡張子を変えない
// https://github.com/misskey-dev/misskey/issues/11482
targetExtsToSkip.has(dotExt)
) {
return filename;
}
// 拡張子があるが一致していないなどの場合は拡張子を付け足す
return `${filename}${dotExt}`;
}

View File

@ -96,6 +96,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
.andWhere('userListJoining.userListId = :userListId', { userListId: list.id });
this.queryService.generateVisibilityQuery(query, me);
this.queryService.generateMutedUserQuery(query, me);
this.queryService.generateMutedNoteQuery(query, me);
this.queryService.generateBlockedUserQuery(query, me);
this.queryService.generateMutedUserRenotesQueryForNotes(query, me);
if (ps.includeMyRenotes === false) {
query.andWhere(new Brackets(qb => {

View File

@ -259,6 +259,21 @@ describe('ActivityPub', () => {
assert.strictEqual(note.text, 'test test foo');
assert.strictEqual(note.uri, actor2Note.id);
});
test('Fetch a note that is a featured note of the attributed actor', async () => {
const actor = createRandomActor();
actor.featured = `${actor.id}/collections/featured`;
const featured = createRandomFeaturedCollection(actor, 5);
const firstNote = (featured.items as NonTransientIPost[])[0];
resolver.register(actor.id, actor);
resolver.register(actor.featured, featured);
resolver.register(firstNote.id, firstNote);
const note = await noteService.createNote(firstNote.id as string, resolver);
assert.strictEqual(note?.uri, firstNote.id);
});
});
describe('Images', () => {

View File

@ -0,0 +1,48 @@
/*
* SPDX-FileCopyrightText: syuilo and other misskey contributors
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { correctFilename } from '@/misc/correct-filename.js';
describe(correctFilename, () => {
it('no ext to null', () => {
expect(correctFilename('test', null)).toBe('test.unknown');
});
it('no ext to jpg', () => {
expect(correctFilename('test', 'jpg')).toBe('test.jpg');
});
it('jpg to webp', () => {
expect(correctFilename('test.jpg', 'webp')).toBe('test.jpg.webp');
});
it('jpg to .webp', () => {
expect(correctFilename('test.jpg', '.webp')).toBe('test.jpg.webp');
});
it('jpeg to jpg', () => {
expect(correctFilename('test.jpeg', 'jpg')).toBe('test.jpeg');
});
it('JPEG to jpg', () => {
expect(correctFilename('test.JPEG', 'jpg')).toBe('test.JPEG');
});
it('jpg to jpg', () => {
expect(correctFilename('test.jpg', 'jpg')).toBe('test.jpg');
});
it('JPG to jpg', () => {
expect(correctFilename('test.JPG', 'jpg')).toBe('test.JPG');
});
it('tiff to tif', () => {
expect(correctFilename('test.tiff', 'tif')).toBe('test.tiff');
});
it('skip gz', () => {
expect(correctFilename('test.unitypackage', 'gz')).toBe('test.unitypackage');
});
it('skip text file', () => {
expect(correctFilename('test.txt', null)).toBe('test.txt');
});
it('unknown', () => {
expect(correctFilename('test.hoge', null)).toBe('test.hoge');
});
test('non ascii with space', () => {
expect(correctFilename('ファイル 名前', 'jpg')).toBe('ファイル 名前.jpg');
});
});

View File

@ -5,7 +5,6 @@
import { describe, test, expect } from '@jest/globals';
import { contentDisposition } from '@/misc/content-disposition.js';
import { correctFilename } from '@/misc/correct-filename.js';
describe('misc:content-disposition', () => {
test('inline', () => {
@ -18,30 +17,3 @@ describe('misc:content-disposition', () => {
expect(contentDisposition('attachment', 'ファイル名')).toBe('attachment; filename=\"_____\"; filename*=UTF-8\'\'%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E5%90%8D');
});
});
describe('misc:correct-filename', () => {
test('simple', () => {
expect(correctFilename('filename', 'jpg')).toBe('filename.jpg');
});
test('with same ext', () => {
expect(correctFilename('filename.jpg', 'jpg')).toBe('filename.jpg');
});
test('.ext', () => {
expect(correctFilename('filename.jpg', '.jpg')).toBe('filename.jpg');
});
test('with different ext', () => {
expect(correctFilename('filename.webp', 'jpg')).toBe('filename.webp.jpg');
});
test('non ascii with space', () => {
expect(correctFilename('ファイル 名前', 'jpg')).toBe('ファイル 名前.jpg');
});
test('jpeg', () => {
expect(correctFilename('filename.jpeg', 'jpg')).toBe('filename.jpeg');
});
test('tiff', () => {
expect(correctFilename('filename.tiff', 'tif')).toBe('filename.tiff');
});
test('null ext', () => {
expect(correctFilename('filename', null)).toBe('filename.unknown');
});
});

View File

@ -39,11 +39,11 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkSwitchButton :class="$style.switchButton" :checked="item.ref" :disabled="item.disabled" @toggle="switchItem(item)" />
<span :class="$style.switchText">{{ item.text }}</span>
</button>
<button v-else-if="item.type === 'parent'" role="menuitem" :tabindex="i" class="_button" :class="[$style.item, $style.parent, { [$style.childShowing]: childShowingItem === item }]" @mouseenter="showChildren(item, $event)">
<div v-else-if="item.type === 'parent'" role="menuitem" :tabindex="i" :class="[$style.item, $style.parent, { [$style.childShowing]: childShowingItem === item }]" @mouseenter="preferClick ? null : showChildren(item, $event)" @click="!preferClick ? null : showChildren(item, $event)">
<i v-if="item.icon" class="ti-fw" :class="[$style.icon, item.icon]"></i>
<span>{{ item.text }}</span>
<span :class="$style.caret"><i class="ti ti-chevron-right ti-fw"></i></span>
</button>
</div>
<button v-else :tabindex="i" class="_button" role="menuitem" :class="[$style.item, { [$style.danger]: item.danger, [$style.active]: item.active }]" :disabled="item.active" @click="clicked(item.action, $event)" @mouseenter.passive="onItemMouseEnter(item)" @mouseleave.passive="onItemMouseLeave(item)">
<i v-if="item.icon" class="ti-fw" :class="[$style.icon, item.icon]"></i>
<MkAvatar v-if="item.avatar" :user="item.avatar" :class="$style.avatar"/>
@ -56,19 +56,24 @@ SPDX-License-Identifier: AGPL-3.0-only
</span>
</div>
<div v-if="childMenu">
<XChild ref="child" :items="childMenu" :targetElement="childTarget" :rootElement="itemsEl" showing @actioned="childActioned"/>
<XChild ref="child" :items="childMenu" :targetElement="childTarget" :rootElement="itemsEl" showing @actioned="childActioned" @close="close(false)"/>
</div>
</div>
</template>
<script lang="ts" setup>
import { defineAsyncComponent, nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue';
<script lang="ts">
import { Ref, defineAsyncComponent, nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue';
import { focusPrev, focusNext } from '@/scripts/focus';
import MkSwitchButton from '@/components/MkSwitch.button.vue';
import { MenuItem, InnerMenuItem, OuterMenuItem, MenuPending, MenuAction, MenuSwitch, MenuParent } from '@/types/menu';
import { MenuItem, InnerMenuItem, MenuPending, MenuAction, MenuSwitch, MenuParent } from '@/types/menu';
import * as os from '@/os';
import { i18n } from '@/i18n';
import { isTouchUsing } from '@/scripts/touch';
const childrenCache = new WeakMap<MenuParent, MenuItem[]>();
</script>
<script lang="ts" setup>
const XChild = defineAsyncComponent(() => import('./MkMenu.child.vue'));
const props = defineProps<{
@ -99,6 +104,8 @@ let keymap = $computed(() => ({
let childShowingItem = $ref<MenuItem | null>();
let preferClick = isTouchUsing || props.asDrawer;
watch(() => props.items, () => {
const items: (MenuItem | MenuPending)[] = [...props.items].filter(item => item !== undefined);
@ -118,7 +125,7 @@ watch(() => props.items, () => {
immediate: true,
});
let childMenu = ref<MenuItem[] | null>();
const childMenu = ref<MenuItem[] | null>();
let childTarget = $shallowRef<HTMLElement | null>();
function closeChild() {
@ -131,11 +138,11 @@ function childActioned() {
close(true);
}
function onGlobalMousedown(event: MouseEvent) {
const onGlobalMousedown = (event: MouseEvent) => {
if (childTarget && (event.target === childTarget || childTarget.contains(event.target))) return;
if (child && child.checkHit(event)) return;
closeChild();
}
};
let childCloseTimer: null | number = null;
function onItemMouseEnter(item) {
@ -147,35 +154,30 @@ function onItemMouseLeave(item) {
if (childCloseTimer) window.clearTimeout(childCloseTimer);
}
let childrenCache = new WeakMap<MenuParent, OuterMenuItem[]>();
async function showChildren(item: MenuParent, ev: MouseEvent) {
const children = ref<OuterMenuItem[]>([]);
if (childrenCache.has(item)) {
children.value = childrenCache.get(item)!;
} else {
if (typeof item.children === 'function') {
children.value = [{
type: 'pending',
}];
Promise.resolve(item.children()).then(x => {
children.value = x;
childrenCache.set(item, x);
});
const children = await (async () => {
if (childrenCache.has(item)) {
return childrenCache.get(item)!;
} else {
children.value = item.children;
if (typeof item.children === 'function') {
return Promise.resolve(item.children());
} else {
return item.children;
}
}
}
})();
childrenCache.set(item, children);
if (props.asDrawer) {
os.popupMenu(children, ev.currentTarget ?? ev.target, {
onClosing: () => {
close();
}
os.popupMenu(children, ev.currentTarget ?? ev.target).finally(() => {
emit('close');
});
emit('hide');
} else {
childTarget = ev.currentTarget ?? ev.target;
childMenu = children;
//
childMenu.value = children;
childShowingItem = item;
}
}
@ -205,7 +207,7 @@ function switchItem(item: MenuSwitch & { ref: any }) {
onMounted(() => {
if (props.viaKeyboard) {
nextTick(() => {
focusNext(itemsEl.children[0], true, false);
if (itemsEl) focusNext(itemsEl.children[0], true, false);
});
}
@ -353,6 +355,7 @@ onBeforeUnmount(() => {
}
&.parent {
pointer-events: auto;
display: flex;
align-items: center;
cursor: default;

View File

@ -4,8 +4,8 @@ SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
<MkModal ref="modal" v-slot="{ type, maxHeight }" :zPriority="'high'" :src="src" :transparentBg="true" @click="close" @close="emit('closing')" @closed="emit('closed')">
<MkMenu :items="items" :align="align" :width="width" :max-height="maxHeight" :asDrawer="type === 'drawer'" :class="{ [$style.drawer]: type === 'drawer' }" @close="close" @hide="manualShowing = false"/>
<MkModal ref="modal" v-slot="{ type, maxHeight }" :manualShowing="manualShowing" :zPriority="'high'" :src="src" :transparentBg="true" @click="click" @close="onModalClose" @closed="onModalClosed">
<MkMenu :items="items" :align="align" :width="width" :max-height="maxHeight" :asDrawer="type === 'drawer'" :class="{ [$style.drawer]: type === 'drawer' }" @close="onMenuClose" @hide="hide"/>
</MkModal>
</template>
@ -30,11 +30,44 @@ const emit = defineEmits<{
let modal = $shallowRef<InstanceType<typeof MkModal>>();
const manualShowing = ref(true);
const hiding = ref(false);
function click() {
close();
}
function onModalClose() {
emit('closing');
}
function onMenuClose() {
close();
if (hiding.value) {
// hidingclosed
emit('closed');
}
}
function onModalClosed() {
if (!hiding.value) {
// hidingclosed
emit('closed');
}
}
function hide() {
manualShowing.value = false;
hiding.value = true;
// close
modal?.close();
}
function close() {
if (!modal) return;
manualShowing.value = false;
modal.close();
// close
modal?.close();
}
</script>

View File

@ -4,7 +4,7 @@
*/
import { Note, UserLite, DriveFile } from "misskey-js/built/entities";
import { Ref, ref, ComputedRef, computed, watch } from "vue";
import { Ref, ref, ComputedRef, computed, watch, triggerRef } from "vue";
import { api } from "./api";
import { useStream } from '@/stream';
import { Stream } from "misskey-js";
@ -314,7 +314,6 @@ export class NoteManager {
if (this.isDebuggerEnabled) console.log('NoteManager: onStreamNoteUpdated (not found)', id, note?.value);
this.connection?.send('un', { id });
this.captureing.delete(id);
this.notesComputed.delete(id);
this.updatedAt.delete(id);
return;
} else {
@ -384,7 +383,6 @@ export class NoteManager {
note.value = null;
this.connection?.send('un', { id });
this.captureing.delete(id);
this.notesComputed.delete(id);
this.updatedAt.delete(id);
break;
}
@ -394,6 +392,7 @@ export class NoteManager {
if (type !== 'deleted') {
if (!note.value) throw new Error('NoteManager: onStreamNoteUpdated (update) note.value is null');
note.value = { ...note.value, ...diff };
triggerRef(note);
}
this.updatedAt.set(id, Date.now());
}

View File

@ -417,7 +417,9 @@ export function getNoteMenu(props: {
const cleanup = () => {
if (_DEV_) console.log('note menu cleanup', cleanups);
cleanups.forEach(cleanup => cleanup());
for (const cl of cleanups) {
cl();
}
};
return {

View File

@ -330,7 +330,9 @@ export function getUserMenu(user: misskey.entities.UserDetailed, router: Router
const cleanup = () => {
if (_DEV_) console.log('user menu cleanup', cleanups);
cleanups.forEach(cleanup => cleanup());
for (const cl of cleanups) {
cl();
}
};
return {

View File

@ -40,6 +40,7 @@ html {
line-height: 1.35;
text-size-adjust: 100%;
tab-size: 2;
-webkit-text-size-adjust: 100%;
&, * {
scrollbar-color: var(--scrollbarHandle) transparent;

View File

@ -16,7 +16,7 @@ export type MenuA = { type: 'a', href: string, target?: string, download?: strin
export type MenuUser = { type: 'user', user: Misskey.entities.User, active?: boolean, indicate?: boolean, action: MenuAction };
export type MenuSwitch = { type: 'switch', ref: Ref<boolean>, text: string, disabled?: boolean };
export type MenuButton = { type?: 'button', text: string, icon?: string, indicate?: boolean, danger?: boolean, active?: boolean, avatar?: Misskey.entities.User; action: MenuAction };
export type MenuParent = { type: 'parent', text: string, icon?: string, children: OuterMenuItem[] | (() => Promise<OuterMenuItem[]> | OuterMenuItem[]) };
export type MenuParent = { type: 'parent', text: string, icon?: string, children: MenuItem[] | (() => Promise<MenuItem[]> | MenuItem[]) };
export type MenuPending = { type: 'pending' };

View File

@ -358,7 +358,7 @@ importers:
version: 2.1.0
summaly:
specifier: github:misskey-dev/summaly
version: github.com/misskey-dev/summaly/089a0ad8e8c780e5c088b1c528aa95c5827cbdcc
version: github.com/misskey-dev/summaly/d2d8db49943ccb201c1b1b283e9d0a630519fac7
systeminformation:
specifier: 5.18.9
version: 5.18.9
@ -1000,7 +1000,7 @@ importers:
version: github.com/misskey-dev/storybook-addon-misskey-theme/cf583db098365b2ccc81a82f63ca9c93bc32b640(@storybook/blocks@7.0.27)(@storybook/components@7.1.0)(@storybook/core-events@7.0.27)(@storybook/manager-api@7.0.27)(@storybook/preview-api@7.0.27)(@storybook/theming@7.0.27)(@storybook/types@7.0.27)(react-dom@18.2.0)(react@18.2.0)
summaly:
specifier: github:misskey-dev/summaly
version: github.com/misskey-dev/summaly/089a0ad8e8c780e5c088b1c528aa95c5827cbdcc
version: github.com/misskey-dev/summaly/d2d8db49943ccb201c1b1b283e9d0a630519fac7
vite-plugin-turbosnap:
specifier: 1.0.2
version: 1.0.2
@ -5348,7 +5348,7 @@ packages:
hasBin: true
requiresBuild: true
dependencies:
detect-libc: 2.0.1
detect-libc: 2.0.2
https-proxy-agent: 5.0.1
make-dir: 3.1.0
node-fetch: 2.6.11
@ -11499,13 +11499,6 @@ packages:
engines: {node: '>=8'}
dev: true
/detect-libc@2.0.1:
resolution: {integrity: sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==}
engines: {node: '>=8'}
requiresBuild: true
dev: false
optional: true
/detect-libc@2.0.2:
resolution: {integrity: sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==}
engines: {node: '>=8'}
@ -22136,8 +22129,8 @@ packages:
react-dom: 18.2.0(react@18.2.0)
dev: true
github.com/misskey-dev/summaly/089a0ad8e8c780e5c088b1c528aa95c5827cbdcc:
resolution: {tarball: https://codeload.github.com/misskey-dev/summaly/tar.gz/089a0ad8e8c780e5c088b1c528aa95c5827cbdcc}
github.com/misskey-dev/summaly/d2d8db49943ccb201c1b1b283e9d0a630519fac7:
resolution: {tarball: https://codeload.github.com/misskey-dev/summaly/tar.gz/d2d8db49943ccb201c1b1b283e9d0a630519fac7}
name: summaly
version: 4.0.2
dependencies: