summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAcid Chicken (硫酸鶏) <root@acid-chicken.com>2023-12-10 17:53:38 +0900
committerGitHub <noreply@github.com>2023-12-10 17:53:38 +0900
commit2217d0c050d16aa195a65780ffd6c450ba202dc1 (patch)
tree7c0d81c4e1d254418725001e5c17b66a1d58d3ae
parentFix indentation (#12615) (diff)
downloadmisskey-2217d0c050d16aa195a65780ffd6c450ba202dc1.tar.gz
misskey-2217d0c050d16aa195a65780ffd6c450ba202dc1.tar.bz2
misskey-2217d0c050d16aa195a65780ffd6c450ba202dc1.zip
refactor(frontend): remove redundant class names (#12618)
-rw-r--r--packages/frontend/lib/rollup-plugin-unwind-css-module-class-name.test.ts3
-rw-r--r--packages/frontend/lib/rollup-plugin-unwind-css-module-class-name.ts223
-rw-r--r--packages/frontend/src/components/MkCodeEditor.vue2
-rw-r--r--packages/frontend/src/components/MkNoteDetailed.vue2
-rw-r--r--packages/frontend/src/components/MkSwitch.vue5
-rw-r--r--packages/frontend/src/pages/admin-user.vue7
-rw-r--r--packages/frontend/src/pages/admin/modlog.ModLog.vue5
-rw-r--r--packages/frontend/src/ui/deck.vue2
-rw-r--r--packages/frontend/src/ui/universal.vue2
9 files changed, 222 insertions, 29 deletions
diff --git a/packages/frontend/lib/rollup-plugin-unwind-css-module-class-name.test.ts b/packages/frontend/lib/rollup-plugin-unwind-css-module-class-name.test.ts
index 759f270393..550e08d7f7 100644
--- a/packages/frontend/lib/rollup-plugin-unwind-css-module-class-name.test.ts
+++ b/packages/frontend/lib/rollup-plugin-unwind-css-module-class-name.test.ts
@@ -180,7 +180,7 @@ import './photoswipe-!~{003}~.js';
const _hoisted_1 = createBaseVNode("i", {
class: "ti ti-photo"
}, null, -1);
-const _sfc_main = defineComponent({
+const index_photos = defineComponent({
__name: "index.photos",
props: {
user: {}
@@ -261,7 +261,6 @@ const style0 = {
const cssModules = {
"$style": style0
};
-const index_photos = _sfc_main;
export {index_photos as default};
`.slice(1));
});
diff --git a/packages/frontend/lib/rollup-plugin-unwind-css-module-class-name.ts b/packages/frontend/lib/rollup-plugin-unwind-css-module-class-name.ts
index 18c817e0f5..68cdc0bc78 100644
--- a/packages/frontend/lib/rollup-plugin-unwind-css-module-class-name.ts
+++ b/packages/frontend/lib/rollup-plugin-unwind-css-module-class-name.ts
@@ -13,13 +13,13 @@ function isFalsyIdentifier(identifier: estree.Identifier): boolean {
return identifier.name === 'undefined' || identifier.name === 'NaN';
}
-function normalizeClassWalker(tree: estree.Node): string | null {
+function normalizeClassWalker(tree: estree.Node, stack: string | undefined): string | null {
if (tree.type === 'Identifier') return isFalsyIdentifier(tree) ? '' : null;
if (tree.type === 'Literal') return typeof tree.value === 'string' ? tree.value : '';
if (tree.type === 'BinaryExpression') {
if (tree.operator !== '+') return null;
- const left = normalizeClassWalker(tree.left);
- const right = normalizeClassWalker(tree.right);
+ const left = normalizeClassWalker(tree.left, stack);
+ const right = normalizeClassWalker(tree.right, stack);
if (left === null || right === null) return null;
return `${left}${right}`;
}
@@ -33,15 +33,15 @@ function normalizeClassWalker(tree: estree.Node): string | null {
if (tree.type === 'ArrayExpression') {
const values = tree.elements.map((treeNode) => {
if (treeNode === null) return '';
- if (treeNode.type === 'SpreadElement') return normalizeClassWalker(treeNode.argument);
- return normalizeClassWalker(treeNode);
+ if (treeNode.type === 'SpreadElement') return normalizeClassWalker(treeNode.argument, stack);
+ return normalizeClassWalker(treeNode, stack);
});
if (values.some((x) => x === null)) return null;
return values.join(' ');
}
if (tree.type === 'ObjectExpression') {
const values = tree.properties.map((treeNode) => {
- if (treeNode.type === 'SpreadElement') return normalizeClassWalker(treeNode.argument);
+ if (treeNode.type === 'SpreadElement') return normalizeClassWalker(treeNode.argument, stack);
let x = treeNode.value;
let inveted = false;
while (x.type === 'UnaryExpression' && x.operator === '!') {
@@ -67,18 +67,26 @@ function normalizeClassWalker(tree: estree.Node): string | null {
if (values.some((x) => x === null)) return null;
return values.join(' ');
}
- console.error(`Unexpected node type: ${tree.type}`);
+ if (
+ tree.type !== 'CallExpression' &&
+ tree.type !== 'ChainExpression' &&
+ tree.type !== 'ConditionalExpression' &&
+ tree.type !== 'LogicalExpression' &&
+ tree.type !== 'MemberExpression') {
+ console.error(stack ? `Unexpected node type: ${tree.type} (in ${stack})` : `Unexpected node type: ${tree.type}`);
+ }
return null;
}
-export function normalizeClass(tree: estree.Node): string | null {
- const walked = normalizeClassWalker(tree);
+export function normalizeClass(tree: estree.Node, stack?: string): string | null {
+ const walked = normalizeClassWalker(tree, stack);
return walked && walked.replace(/^\s+|\s+(?=\s)|\s+$/g, '');
}
export function unwindCssModuleClassName(ast: estree.Node): void {
(walk as typeof estreeWalker.walk)(ast, {
enter(node, parent): void {
+ //#region
if (parent?.type !== 'Program') return;
if (node.type !== 'VariableDeclaration') return;
if (node.declarations.length !== 1) return;
@@ -102,6 +110,14 @@ export function unwindCssModuleClassName(ast: estree.Node): void {
return true;
});
if (!~__cssModulesIndex) return;
+ /* This region assumeed that the entered node looks like the following code.
+ *
+ * ```ts
+ * const SomeComponent = _export_sfc(_sfc_main, [["foo", bar], ["__cssModules", cssModules]]);
+ * ```
+ */
+ //#endregion
+ //#region
const cssModuleForestName = ((node.declarations[0].init.arguments[1].elements[__cssModulesIndex] as estree.ArrayExpression).elements[1] as estree.Identifier).name;
const cssModuleForestNode = parent.body.find((x) => {
if (x.type !== 'VariableDeclaration') return false;
@@ -117,6 +133,16 @@ export function unwindCssModuleClassName(ast: estree.Node): void {
if (property.value.type !== 'Identifier') return [];
return [[property.key.value as string, property.value.name as string]];
}));
+ /* This region collected a VariableDeclaration node in the module that looks like the following code.
+ *
+ * ```ts
+ * const cssModules = {
+ * "$style": style0,
+ * };
+ * ```
+ */
+ //#endregion
+ //#region
const sfcMain = parent.body.find((x) => {
if (x.type !== 'VariableDeclaration') return false;
if (x.declarations.length !== 1) return false;
@@ -146,7 +172,22 @@ export function unwindCssModuleClassName(ast: estree.Node): void {
if (ctx.type !== 'Identifier') return;
if (ctx.name !== '_ctx') return;
if (render.argument.body.type !== 'BlockStatement') return;
+ /* This region assumed that `sfcMain` looks like the following code.
+ *
+ * ```ts
+ * const _sfc_main = defineComponent({
+ * setup(_props) {
+ * ...
+ * return (_ctx, _cache) => {
+ * ...
+ * };
+ * },
+ * });
+ * ```
+ */
+ //#endregion
for (const [key, value] of moduleForest) {
+ //#region
const cssModuleTreeNode = parent.body.find((x) => {
if (x.type !== 'VariableDeclaration') return false;
if (x.declarations.length !== 1) return false;
@@ -172,6 +213,19 @@ export function unwindCssModuleClassName(ast: estree.Node): void {
if (actualValue.declarations[0].init?.type !== 'Literal') return [];
return [[actualKey, actualValue.declarations[0].init.value as string]];
}));
+ /* This region collected VariableDeclaration nodes in the module that looks like the following code.
+ *
+ * ```ts
+ * const foo = "bar";
+ * const baz = "qux";
+ * const style0 = {
+ * foo: foo,
+ * baz: baz,
+ * };
+ * ```
+ */
+ //#endregion
+ //#region
(walk as typeof estreeWalker.walk)(render.argument.body, {
enter(childNode) {
if (childNode.type !== 'MemberExpression') return;
@@ -189,6 +243,39 @@ export function unwindCssModuleClassName(ast: estree.Node): void {
});
},
});
+ /* This region inlined the reference identifier of the class name in the render function into the actual literal, as in the following code.
+ *
+ * ```ts
+ * const _sfc_main = defineComponent({
+ * setup(_props) {
+ * ...
+ * return (_ctx, _cache) => {
+ * ...
+ * return openBlock(), createElementBlock("div", {
+ * class: normalizeClass(_ctx.$style.foo),
+ * }, null);
+ * };
+ * },
+ * });
+ * ```
+ *
+ * ↓
+ *
+ * ```ts
+ * const _sfc_main = defineComponent({
+ * setup(_props) {
+ * ...
+ * return (_ctx, _cache) => {
+ * ...
+ * return openBlock(), createElementBlock("div", {
+ * class: normalizeClass("bar"),
+ * }, null);
+ * };
+ * },
+ * });
+ */
+ //#endregion
+ //#region
(walk as typeof estreeWalker.walk)(render.argument.body, {
enter(childNode) {
if (childNode.type !== 'MemberExpression') return;
@@ -205,13 +292,47 @@ export function unwindCssModuleClassName(ast: estree.Node): void {
});
},
});
+ /* This region replaced the reference identifier of missing class names in the render function with `undefined`, as in the following code.
+ *
+ * ```ts
+ * const _sfc_main = defineComponent({
+ * setup(_props) {
+ * ...
+ * return (_ctx, _cache) => {
+ * ...
+ * return openBlock(), createElementBlock("div", {
+ * class: normalizeClass(_ctx.$style.hoge),
+ * }, null);
+ * };
+ * },
+ * });
+ * ```
+ *
+ * ↓
+ *
+ * ```ts
+ * const _sfc_main = defineComponent({
+ * setup(_props) {
+ * ...
+ * return (_ctx, _cache) => {
+ * ...
+ * return openBlock(), createElementBlock("div", {
+ * class: normalizeClass(undefined),
+ * }, null);
+ * };
+ * },
+ * });
+ * ```
+ */
+ //#endregion
+ //#region
(walk as typeof estreeWalker.walk)(render.argument.body, {
enter(childNode) {
if (childNode.type !== 'CallExpression') return;
if (childNode.callee.type !== 'Identifier') return;
if (childNode.callee.name !== 'normalizeClass') return;
if (childNode.arguments.length !== 1) return;
- const normalized = normalizeClass(childNode.arguments[0]);
+ const normalized = normalizeClass(childNode.arguments[0], name);
if (normalized === null) return;
this.replace({
type: 'Literal',
@@ -219,8 +340,60 @@ export function unwindCssModuleClassName(ast: estree.Node): void {
});
},
});
+ /* This region compiled the `normalizeClass` call into a pseudo-AOT compilation, as in the following code.
+ *
+ * ```ts
+ * const _sfc_main = defineComponent({
+ * setup(_props) {
+ * ...
+ * return (_ctx, _cache) => {
+ * ...
+ * return openBlock(), createElementBlock("div", {
+ * class: normalizeClass("bar"),
+ * }, null);
+ * };
+ * },
+ * });
+ * ```
+ *
+ * ↓
+ *
+ * ```ts
+ * const _sfc_main = defineComponent({
+ * setup(_props) {
+ * ...
+ * return (_ctx, _cache) => {
+ * ...
+ * return openBlock(), createElementBlock("div", {
+ * class: "bar",
+ * }, null);
+ * };
+ * },
+ * });
+ * ```
+ */
+ //#endregion
}
+ //#region
if (node.declarations[0].init.arguments[1].elements.length === 1) {
+ (walk as typeof estreeWalker.walk)(ast, {
+ enter(childNode) {
+ if (childNode.type !== 'Identifier') return;
+ if (childNode.name !== ident) return;
+ this.replace({
+ type: 'Identifier',
+ name: node.declarations[0].id.name,
+ });
+ },
+ });
+ this.remove();
+ /* NOTE: The above logic is valid as long as the following two conditions are met.
+ *
+ * - the uniqueness of `ident` is kept throughout the module
+ * - `_export_sfc` is noop when the second argument is an empty array
+ *
+ * Otherwise, the below logic should be used instead.
+
this.replace({
type: 'VariableDeclaration',
declarations: [{
@@ -236,6 +409,7 @@ export function unwindCssModuleClassName(ast: estree.Node): void {
}],
kind: 'const',
});
+ */
} else {
this.replace({
type: 'VariableDeclaration',
@@ -263,6 +437,35 @@ export function unwindCssModuleClassName(ast: estree.Node): void {
kind: 'const',
});
}
+ /* This region removed the `__cssModules` reference from the second argument of `_export_sfc`, as in the following code.
+ *
+ * ```ts
+ * const SomeComponent = _export_sfc(_sfc_main, [["foo", bar], ["__cssModules", cssModules]]);
+ * ```
+ *
+ * ↓
+ *
+ * ```ts
+ * const SomeComponent = _export_sfc(_sfc_main, [["foo", bar]]);
+ * ```
+ *
+ * When the declaration becomes noop, it is removed as follows.
+ *
+ * ```ts
+ * const _sfc_main = defineComponent({
+ * ...
+ * });
+ * const SomeComponent = _export_sfc(_sfc_main, []);
+ * ```
+ *
+ * ↓
+ *
+ * ```ts
+ * const SomeComponent = defineComponent({
+ * ...
+ * });
+ */
+ //#endregion
},
});
}
diff --git a/packages/frontend/src/components/MkCodeEditor.vue b/packages/frontend/src/components/MkCodeEditor.vue
index 03788af21e..60f16f285f 100644
--- a/packages/frontend/src/components/MkCodeEditor.vue
+++ b/packages/frontend/src/components/MkCodeEditor.vue
@@ -4,7 +4,7 @@ SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
-<div :class="[$style.codeEditorRoot, { [$style.disabled]: disabled, [$style.focused]: focused }]">
+<div :class="[$style.codeEditorRoot, { [$style.focused]: focused }]">
<div :class="$style.codeEditorScroller">
<textarea
ref="inputEl"
diff --git a/packages/frontend/src/components/MkNoteDetailed.vue b/packages/frontend/src/components/MkNoteDetailed.vue
index a8ccf26c4c..48d90522c4 100644
--- a/packages/frontend/src/components/MkNoteDetailed.vue
+++ b/packages/frontend/src/components/MkNoteDetailed.vue
@@ -145,7 +145,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<button class="_button" :class="[$style.tab, { [$style.tabActive]: tab === 'reactions' }]" @click="tab = 'reactions'"><i class="ti ti-icons"></i> {{ i18n.ts.reactions }}</button>
</div>
<div>
- <div v-if="tab === 'replies'" :class="$style.tab_replies">
+ <div v-if="tab === 'replies'">
<div v-if="!repliesLoaded" style="padding: 16px">
<MkButton style="margin: 0 auto;" primary rounded @click="loadReplies">{{ i18n.ts.loadReplies }}</MkButton>
</div>
diff --git a/packages/frontend/src/components/MkSwitch.vue b/packages/frontend/src/components/MkSwitch.vue
index 8e946e7437..2e2c0e15a2 100644
--- a/packages/frontend/src/components/MkSwitch.vue
+++ b/packages/frontend/src/components/MkSwitch.vue
@@ -4,7 +4,7 @@ SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
-<div :class="[$style.root, { [$style.disabled]: disabled, [$style.checked]: checked }]">
+<div :class="[$style.root, { [$style.disabled]: disabled }]">
<input
ref="input"
type="checkbox"
@@ -64,9 +64,6 @@ const toggle = () => {
opacity: 0.6;
cursor: not-allowed;
}
-
- //&.checked {
- //}
}
.input {
diff --git a/packages/frontend/src/pages/admin-user.vue b/packages/frontend/src/pages/admin-user.vue
index 55ad1e2ab1..4ad8cc58c5 100644
--- a/packages/frontend/src/pages/admin-user.vue
+++ b/packages/frontend/src/pages/admin-user.vue
@@ -134,10 +134,10 @@ SPDX-License-Identifier: AGPL-3.0-only
<div v-else-if="tab === 'roles'" class="_gaps">
<MkButton v-if="user.host == null" primary rounded @click="assignRole"><i class="ti ti-plus"></i> {{ i18n.ts.assign }}</MkButton>
- <div v-for="role in info.roles" :key="role.id" :class="$style.roleItem">
+ <div v-for="role in info.roles" :key="role.id">
<div :class="$style.roleItemMain">
<MkRolePreview :class="$style.role" :role="role" :forModeration="true"/>
- <button class="_button" :class="$style.roleToggle" @click="toggleRoleItem(role)"><i class="ti ti-chevron-down"></i></button>
+ <button class="_button" @click="toggleRoleItem(role)"><i class="ti ti-chevron-down"></i></button>
<button v-if="role.target === 'manual'" class="_button" :class="$style.roleUnassign" @click="unassignRole(role, $event)"><i class="ti ti-x"></i></button>
<button v-else class="_button" :class="$style.roleUnassign" disabled><i class="ti ti-ban"></i></button>
</div>
@@ -621,9 +621,6 @@ definePageMetadata(computed(() => ({
}
}
-.roleItem {
-}
-
.roleItemMain {
display: flex;
}
diff --git a/packages/frontend/src/pages/admin/modlog.ModLog.vue b/packages/frontend/src/pages/admin/modlog.ModLog.vue
index bceefcf6c8..fe825613fa 100644
--- a/packages/frontend/src/pages/admin/modlog.ModLog.vue
+++ b/packages/frontend/src/pages/admin/modlog.ModLog.vue
@@ -48,7 +48,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkTime :time="log.createdAt"/>
</template>
- <div :class="$style.root">
+ <div>
<div style="display: flex; gap: var(--margin); flex-wrap: wrap;">
<div style="flex: 1;">{{ i18n.ts.moderator }}: <MkA :to="`/admin/user/${log.userId}`" class="_link">@{{ log.user?.username }}</MkA></div>
<div style="flex: 1;">{{ i18n.ts.dateAndTime }}: <MkTime :time="log.createdAt" mode="detail"/></div>
@@ -134,9 +134,6 @@ const props = defineProps<{
</script>
<style lang="scss" module>
-.root {
-}
-
.avatar {
width: 18px;
height: 18px;
diff --git a/packages/frontend/src/ui/deck.vue b/packages/frontend/src/ui/deck.vue
index 10a073243b..3e3e2b949c 100644
--- a/packages/frontend/src/ui/deck.vue
+++ b/packages/frontend/src/ui/deck.vue
@@ -8,7 +8,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<XSidebar v-if="!isMobile"/>
<div :class="$style.main">
- <XAnnouncements v-if="$i" :class="$style.announcements"/>
+ <XAnnouncements v-if="$i"/>
<XStatusBars/>
<div ref="columnsEl" :class="[$style.sections, { [$style.center]: deckStore.reactiveState.columnAlign.value === 'center', [$style.snapScroll]: snapScroll }]" @contextmenu.self.prevent="onContextmenu" @wheel.self="onWheel">
<!-- sectionを利用しているのは、deck.vue側でcolumnに対してfirst-of-typeを効かせるため -->
diff --git a/packages/frontend/src/ui/universal.vue b/packages/frontend/src/ui/universal.vue
index cba7b82610..f46f55d988 100644
--- a/packages/frontend/src/ui/universal.vue
+++ b/packages/frontend/src/ui/universal.vue
@@ -10,7 +10,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkStickyContainer ref="contents" :class="$style.contents" style="container-type: inline-size;" @contextmenu.stop="onContextmenu">
<template #header>
<div>
- <XAnnouncements v-if="$i" :class="$style.announcements"/>
+ <XAnnouncements v-if="$i"/>
<XStatusBars :class="$style.statusbars"/>
</div>
</template>