1
0
mirror of https://github.com/misskey-dev/misskey.git synced 2026-05-06 02:26:04 +02:00

deps: Update vite to v8 (#17238)

* deps: Update vite to v8

* fix

* migrate some plugins to rolldown-based

* fix broken lockfile

* wip

* update rolldown

* override rolldown version

* perf

* spdx

* fix

* update vite to 8.0.1

* chore: rewrite rollup-plugin-unwind-css-module-class-name with MagicString

* format

* swap type definitions

* replace using MagicString

* provided magicString

* fix code style

* fix

* fix

* fix

* fix

* fix

---------

Co-authored-by: kakkokari-gtyih <67428053+kakkokari-gtyih@users.noreply.github.com>

* fix: lint fixes

* swap sass with sass-embedded

* fix lint

* fix: インライン化されたVue SFC出力に対してCSS Module定義削除が効かないのを修正

* fix

* fix: バックエンドのCSS読み込みの方法が悪いのを修正

* fix: 使用されないpreloadを削除

* fix lint [ci skip]

* Apply suggestion from @syuilo

* Add comment in pnpm-workspace.yaml [ci skip]

* update vite/rolldown

* remove magic-string

---------

Co-authored-by: cm-ayf <cm.ayf2734@gmail.com>
Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
This commit is contained in:
かっこかり
2026-04-01 17:05:57 +09:00
committed by GitHub
parent 5361a3819b
commit e601fcb729
16 changed files with 1287 additions and 469 deletions

View File

@@ -3,15 +3,15 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { parse } from 'acorn';
import { generate } from 'astring';
import { describe, expect, it } from 'vitest';
import { normalizeClass, unwindCssModuleClassName } from './rollup-plugin-unwind-css-module-class-name.js';
import type * as estree from 'estree';
import { parseAst } from 'rolldown/parseAst';
import type { ESTree } from 'rolldown/utils';
import { RolldownMagicString } from 'rolldown';
function parseExpression(code: string): estree.Expression {
const program = parse(code, { ecmaVersion: 'latest', sourceType: 'module' }) as unknown as estree.Program;
const statement = program.body[0] as estree.ExpressionStatement;
function parseExpression(code: string): ESTree.Expression {
const program = parseAst(code, { sourceType: 'module' });
const statement = program.body[0] as ESTree.ExpressionStatement;
return statement.expression;
}
@@ -57,7 +57,7 @@ describe(normalizeClass.name, () => {
});
it('Composition API (standard)', () => {
const ast = parse(`
const code = `
import { c as api, d as store, i as i18n, aD as notePage, bN as ImgWithBlurhash, bY as getStaticImageUrl, _ as _export_sfc } from './app-!~{001}~.js';
import { M as MkContainer } from './MkContainer-!~{03M}~.js';
import { b as defineComponent, a as ref, e as onMounted, z as resolveComponent, g as openBlock, h as createBlock, i as withCtx, K as createTextVNode, E as toDisplayString, u as unref, l as createBaseVNode, q as normalizeClass, B as createCommentVNode, k as createElementBlock, F as Fragment, C as renderList, A as createVNode } from './vue-!~{002}~.js';
@@ -170,17 +170,19 @@ const cssModules = {
const index_photos = /* @__PURE__ */ _export_sfc(_sfc_main, [["__cssModules", cssModules]]);
export { index_photos as default };
`.slice(1), { ecmaVersion: 'latest', sourceType: 'module' });
unwindCssModuleClassName(ast);
expect(generate(ast)).toBe(`
import {c as api, d as store, i as i18n, aD as notePage, bN as ImgWithBlurhash, bY as getStaticImageUrl, _ as _export_sfc} from './app-!~{001}~.js';
import {M as MkContainer} from './MkContainer-!~{03M}~.js';
import {b as defineComponent, a as ref, e as onMounted, z as resolveComponent, g as openBlock, h as createBlock, i as withCtx, K as createTextVNode, E as toDisplayString, u as unref, l as createBaseVNode, q as normalizeClass, B as createCommentVNode, k as createElementBlock, F as Fragment, C as renderList, A as createVNode} from './vue-!~{002}~.js';
`.slice(1);
const ast = parseAst(code, { sourceType: 'module' });
const magicString = new RolldownMagicString(code);
unwindCssModuleClassName(ast, magicString);
expect(magicString.toString()).toBe(
`
import { c as api, d as store, i as i18n, aD as notePage, bN as ImgWithBlurhash, bY as getStaticImageUrl, _ as _export_sfc } from './app-!~{001}~.js';
import { M as MkContainer } from './MkContainer-!~{03M}~.js';
import { b as defineComponent, a as ref, e as onMounted, z as resolveComponent, g as openBlock, h as createBlock, i as withCtx, K as createTextVNode, E as toDisplayString, u as unref, l as createBaseVNode, q as normalizeClass, B as createCommentVNode, k as createElementBlock, F as Fragment, C as renderList, A as createVNode } from './vue-!~{002}~.js';
import './photoswipe-!~{003}~.js';
const _hoisted_1 = createBaseVNode("i", {
class: "ti ti-photo"
}, null, -1);
const index_photos = defineComponent({
const _hoisted_1 = /* @__PURE__ */ createBaseVNode("i", { class: "ti ti-photo" }, null, -1);
const index_photos = /* @__PURE__ */ defineComponent({
__name: "index.photos",
props: {
user: {}
@@ -193,12 +195,20 @@ const index_photos = defineComponent({
return store.s.disableShowingAnimatedImages ? getStaticImageUrl(image.url) : image.thumbnailUrl;
}
onMounted(() => {
const image = ["image/jpeg", "image/webp", "image/avif", "image/png", "image/gif", "image/apng", "image/vnd.mozilla.apng"];
const image = [
"image/jpeg",
"image/webp",
"image/avif",
"image/png",
"image/gif",
"image/apng",
"image/vnd.mozilla.apng"
];
api("users/notes", {
userId: props.user.id,
fileType: image,
limit: 10
}).then(notes => {
}).then((notes) => {
for (const note of notes) {
for (const file of note.files) {
images.value.push({
@@ -213,60 +223,77 @@ const index_photos = defineComponent({
return (_ctx, _cache) => {
const _component_MkLoading = resolveComponent("MkLoading");
const _component_MkA = resolveComponent("MkA");
return (openBlock(), createBlock(MkContainer, {
return openBlock(), createBlock(MkContainer, {
"max-height": 300,
foldable: true
}, {
icon: withCtx(() => [_hoisted_1]),
header: withCtx(() => [createTextVNode(toDisplayString(unref(i18n).ts.images), 1)]),
default: withCtx(() => [createBaseVNode("div", {
class: "xenMW"
}, [unref(fetching) ? (openBlock(), createBlock(_component_MkLoading, {
key: 0
})) : createCommentVNode("", true), !unref(fetching) && unref(images).length > 0 ? (openBlock(), createElementBlock("div", {
key: 1,
class: "xaZzf"
}, [(openBlock(true), createElementBlock(Fragment, null, renderList(unref(images), image => {
return (openBlock(), createBlock(_component_MkA, {
key: image.note.id + image.file.id,
class: "xtA8t",
to: unref(notePage)(image.note)
}, {
default: withCtx(() => [createVNode(ImgWithBlurhash, {
hash: image.file.blurhash,
src: thumbnail(image.file),
title: image.file.name
}, null, 8, ["hash", "src", "title"])]),
_: 2
}, 1032, ["class", "to"]));
}), 128))], 2)) : createCommentVNode("", true), !unref(fetching) && unref(images).length == 0 ? (openBlock(), createElementBlock("p", {
key: 2,
class: "xhYKj"
}, toDisplayString(unref(i18n).ts.nothing), 3)) : createCommentVNode("", true)], 2)]),
icon: withCtx(() => [
_hoisted_1
]),
header: withCtx(() => [
createTextVNode(toDisplayString(unref(i18n).ts.images), 1)
]),
default: withCtx(() => [
createBaseVNode("div", {
class: "xenMW"
}, [
unref(fetching) ? (openBlock(), createBlock(_component_MkLoading, { key: 0 })) : createCommentVNode("", true),
!unref(fetching) && unref(images).length > 0 ? (openBlock(), createElementBlock("div", {
key: 1,
class: "xaZzf"
}, [
(openBlock(true), createElementBlock(Fragment, null, renderList(unref(images), (image) => {
return openBlock(), createBlock(_component_MkA, {
key: image.note.id + image.file.id,
class: "xtA8t",
to: unref(notePage)(image.note)
}, {
default: withCtx(() => [
createVNode(ImgWithBlurhash, {
hash: image.file.blurhash,
src: thumbnail(image.file),
title: image.file.name
}, null, 8, ["hash", "src", "title"])
]),
_: 2
}, 1032, ["class", "to"]);
}), 128))
], 2)) : createCommentVNode("", true),
!unref(fetching) && unref(images).length == 0 ? (openBlock(), createElementBlock("p", {
key: 2,
class: "xhYKj"
}, toDisplayString(unref(i18n).ts.nothing), 3)) : createCommentVNode("", true)
], 2)
]),
_: 1
}));
});
};
}
});
const root = "xenMW";
const stream = "xaZzf";
const img = "xtA8t";
const empty = "xhYKj";
const style0 = {
root: root,
stream: stream,
img: img,
empty: empty
root: root,
stream: stream,
img: img,
empty: empty
};
const cssModules = {
"$style": style0
};
export {index_photos as default};
`.slice(1));
export { index_photos as default };
`.slice(1),
);
});
it('Composition API (with `useCssModule()`)', () => {
const ast = parse(`
const code = `
import { a7 as getCurrentInstance, b as defineComponent, G as useCssModule, a1 as h, H as TransitionGroup } from './!~{002}~.js';
import { d as store, aK as toast, b5 as MkAd, i as i18n, _ as _export_sfc } from './app-!~{001}~.js';
@@ -437,11 +464,15 @@ const cssModules = {
const MkDateSeparatedList = /* @__PURE__ */ _export_sfc(_sfc_main, [["__cssModules", cssModules]]);
export { MkDateSeparatedList as M };
`.slice(1), { ecmaVersion: 'latest', sourceType: 'module' });
unwindCssModuleClassName(ast);
expect(generate(ast)).toBe(`
import {a7 as getCurrentInstance, b as defineComponent, G as useCssModule, a1 as h, H as TransitionGroup} from './!~{002}~.js';
import {d as store, aK as toast, b5 as MkAd, i as i18n, _ as _export_sfc} from './app-!~{001}~.js';
`.slice(1);
const ast = parseAst(code, { sourceType: 'module' });
const magicString = new RolldownMagicString(code);
unwindCssModuleClassName(ast, magicString);
expect(magicString.toString()).toBe(
`
import { a7 as getCurrentInstance, b as defineComponent, G as useCssModule, a1 as h, H as TransitionGroup } from './!~{002}~.js';
import { d as store, aK as toast, b5 as MkAd, i as i18n, _ as _export_sfc } from './app-!~{001}~.js';
function isDebuggerEnabled(id) {
try {
return localStorage.getItem(\`DEBUG_\${id}\`) !== null;
@@ -458,6 +489,7 @@ function stackTraceInstances() {
}
return stack;
}
const _sfc_main = defineComponent({
props: {
items: {
@@ -485,7 +517,7 @@ const _sfc_main = defineComponent({
default: false
}
},
setup(props, {slots, expose}) {
setup(props, { slots, expose }) {
const $style = useCssModule();
function getDateText(time) {
const date = new Date(time).getDate();
@@ -495,28 +527,40 @@ const _sfc_main = defineComponent({
day: date.toString()
});
}
if (props.items.length === 0) return;
if (props.items.length === 0)
return;
const renderChildrenImpl = () => props.items.map((item, i) => {
if (!slots || !slots.default) return;
if (!slots || !slots.default)
return;
const el = slots.default({
item
})[0];
if (el.key == null && item.id) el.key = item.id;
if (el.key == null && item.id)
el.key = item.id;
if (i !== props.items.length - 1 && new Date(item.createdAt).getDate() !== new Date(props.items[i + 1].createdAt).getDate()) {
const separator = h("div", {
class: $style["separator"],
key: item.id + ":separator"
}, h("p", {
class: $style["date"]
}, [h("span", {
class: $style["date-1"]
}, [h("i", {
class: \`ti ti-chevron-up \${$style["date-1-icon"]}\`
}), getDateText(item.createdAt)]), h("span", {
class: $style["date-2"]
}, [getDateText(props.items[i + 1].createdAt), h("i", {
class: \`ti ti-chevron-down \${$style["date-2-icon"]}\`
})])]));
}, [
h("span", {
class: $style["date-1"]
}, [
h("i", {
class: \`ti ti-chevron-up \${$style["date-1-icon"]}\`
}),
getDateText(item.createdAt)
]),
h("span", {
class: $style["date-2"]
}, [
getDateText(props.items[i + 1].createdAt),
h("i", {
class: \`ti ti-chevron-down \${$style["date-2-icon"]}\`
})
])
]));
return [el, separator];
} else {
if (props.ad && item._shouldInsertAd_) {
@@ -532,17 +576,13 @@ const _sfc_main = defineComponent({
const renderChildren = () => {
const children = renderChildrenImpl();
if (isDebuggerEnabled(6864)) {
const nodes = children.flatMap(node => node ?? []);
const keys = new Set(nodes.map(node => node.key));
const nodes = children.flatMap((node) => node ?? []);
const keys = new Set(nodes.map((node) => node.key));
if (keys.size !== nodes.length) {
const id = crypto.randomUUID();
const instances = stackTraceInstances();
toast(instances.reduce((a, c) => \`\${a} at \${c.type.name}\`, \`[DEBUG_6864 (\${id})]: \${nodes.length - keys.size} duplicated keys found\`));
console.warn({
id,
debugId: 6864,
stack: instances
});
console.warn({ id, debugId: 6864, stack: instances });
}
}
return children;
@@ -555,45 +595,136 @@ const _sfc_main = defineComponent({
el.style.top = "";
el.style.left = "";
}
return () => h(prefer.s.animation ? TransitionGroup : "div", {
class: {
[$style["date-separated-list"]]: true,
[$style["date-separated-list-nogap"]]: props.noGap,
[$style["reversed"]]: props.reversed,
[$style["direction-down"]]: props.direction === "down",
[$style["direction-up"]]: props.direction === "up"
return () => h(
prefer.s.animation ? TransitionGroup : "div",
{
class: {
[$style["date-separated-list"]]: true,
[$style["date-separated-list-nogap"]]: props.noGap,
[$style["reversed"]]: props.reversed,
[$style["direction-down"]]: props.direction === "down",
[$style["direction-up"]]: props.direction === "up"
},
...prefer.s.animation ? {
name: "list",
tag: "div",
onBeforeLeave,
onLeaveCanceled
} : {}
},
...prefer.s.animation ? {
name: "list",
tag: "div",
onBeforeLeave,
onLeaveCanceled
} : {}
}, {
default: renderChildren
});
{ default: renderChildren }
);
}
});
const reversed = "xxiZh";
const separator = "xxeDx";
const date = "xxawD";
const style0 = {
"date-separated-list": "xfKPa",
"date-separated-list-nogap": "xf9zr",
"direction-up": "x7AeO",
"direction-down": "xBIqc",
reversed: reversed,
separator: separator,
date: date,
"date-1": "xwtmh",
"date-1-icon": "xsNPa",
"date-2": "x1xvw",
"date-2-icon": "x9ZiG"
"date-separated-list": "xfKPa",
"date-separated-list-nogap": "xf9zr",
"direction-up": "x7AeO",
"direction-down": "xBIqc",
reversed: reversed,
separator: separator,
date: date,
"date-1": "xwtmh",
"date-1-icon": "xsNPa",
"date-2": "x1xvw",
"date-2-icon": "x9ZiG"
};
const cssModules = {
"$style": style0
};
const MkDateSeparatedList = _export_sfc(_sfc_main, [["__cssModules", cssModules]]);
export {MkDateSeparatedList as M};
const MkDateSeparatedList = /* @__PURE__ */ _export_sfc(_sfc_main, [["__cssModules", cssModules]]);
export { MkDateSeparatedList as M };
`.slice(1));
});
it('Composition API (inlined output)', () => {
const code = `
import { a as normalizeClass, b as defineComponent, c as _export_sfc } from './runtime.js';
const CurrentComponent = /* @__PURE__ */ _export_sfc(defineComponent({
__name: "CurrentComponent",
setup() {
return (e, n) => h("div", {
class: normalizeClass([e.$style.root, "extra"])
}, null, 2);
}
}), [["__cssModules", {
"$style": {
root: "x1234"
}
}]]);
export { CurrentComponent as default };
`.slice(1);
const ast = parseAst(code, { sourceType: 'module' });
const magicString = new RolldownMagicString(code);
unwindCssModuleClassName(ast, magicString);
const output = magicString.toString();
expect(output).toContain('class: "x1234 extra"');
expect(output).toContain('defineComponent({');
expect(output).toContain('}), []);');
expect(output).not.toContain('$style');
});
it('should keep cssModules when unresolved references remain', () => {
const code = `
import { a as normalizeClass, b as defineComponent, c as _export_sfc } from './runtime.js';
const CurrentComponent = /* @__PURE__ */ _export_sfc(defineComponent({
__name: "CurrentComponent",
setup() {
return (e, n) => h("div", {
class: normalizeClass([e.$style.root, e.$style[side]])
}, null, 2);
}
}), [["__cssModules", {
"$style": {
root: "x1234"
}
}]]);
export { CurrentComponent as default };
`.slice(1);
const ast = parseAst(code, { sourceType: 'module' });
const magicString = new RolldownMagicString(code);
unwindCssModuleClassName(ast, magicString);
const output = magicString.toString();
expect(output).toContain('e.$style[side]');
expect(output).toContain('__cssModules');
expect(output).not.toContain('}), []);');
});
it('should inline cssModules references used inside class expressions', () => {
const code = `
import { a as classHelper, b as defineComponent, c as _export_sfc } from './runtime.js';
const CurrentComponent = /* @__PURE__ */ _export_sfc(defineComponent({
__name: "CurrentComponent",
setup() {
return (e, n) => h("div", {
class: classHelper([e.$style.root, { [e.$style.main]: isActive }])
}, null, 2);
}
}), [["__cssModules", {
"$style": {
root: "x1234",
main: "x5678"
}
}]]);
export { CurrentComponent as default };
`.slice(1);
const ast = parseAst(code, { sourceType: 'module' });
const magicString = new RolldownMagicString(code);
unwindCssModuleClassName(ast, magicString);
const output = magicString.toString();
expect(output).toContain('class: classHelper(["x1234", { ["x5678"]: isActive }])');
expect(output).toContain('}), []);');
expect(output).not.toContain('$style');
});