refactor(frontend): remove redundant class names (#12618)
This commit is contained in:
parent
4c135a5ca1
commit
2217d0c050
9 changed files with 222 additions and 29 deletions
|
@ -180,7 +180,7 @@ import './photoswipe-!~{003}~.js';
|
||||||
const _hoisted_1 = createBaseVNode("i", {
|
const _hoisted_1 = createBaseVNode("i", {
|
||||||
class: "ti ti-photo"
|
class: "ti ti-photo"
|
||||||
}, null, -1);
|
}, null, -1);
|
||||||
const _sfc_main = defineComponent({
|
const index_photos = defineComponent({
|
||||||
__name: "index.photos",
|
__name: "index.photos",
|
||||||
props: {
|
props: {
|
||||||
user: {}
|
user: {}
|
||||||
|
@ -261,7 +261,6 @@ const style0 = {
|
||||||
const cssModules = {
|
const cssModules = {
|
||||||
"$style": style0
|
"$style": style0
|
||||||
};
|
};
|
||||||
const index_photos = _sfc_main;
|
|
||||||
export {index_photos as default};
|
export {index_photos as default};
|
||||||
`.slice(1));
|
`.slice(1));
|
||||||
});
|
});
|
||||||
|
|
|
@ -13,13 +13,13 @@ function isFalsyIdentifier(identifier: estree.Identifier): boolean {
|
||||||
return identifier.name === 'undefined' || identifier.name === 'NaN';
|
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 === 'Identifier') return isFalsyIdentifier(tree) ? '' : null;
|
||||||
if (tree.type === 'Literal') return typeof tree.value === 'string' ? tree.value : '';
|
if (tree.type === 'Literal') return typeof tree.value === 'string' ? tree.value : '';
|
||||||
if (tree.type === 'BinaryExpression') {
|
if (tree.type === 'BinaryExpression') {
|
||||||
if (tree.operator !== '+') return null;
|
if (tree.operator !== '+') return null;
|
||||||
const left = normalizeClassWalker(tree.left);
|
const left = normalizeClassWalker(tree.left, stack);
|
||||||
const right = normalizeClassWalker(tree.right);
|
const right = normalizeClassWalker(tree.right, stack);
|
||||||
if (left === null || right === null) return null;
|
if (left === null || right === null) return null;
|
||||||
return `${left}${right}`;
|
return `${left}${right}`;
|
||||||
}
|
}
|
||||||
|
@ -33,15 +33,15 @@ function normalizeClassWalker(tree: estree.Node): string | null {
|
||||||
if (tree.type === 'ArrayExpression') {
|
if (tree.type === 'ArrayExpression') {
|
||||||
const values = tree.elements.map((treeNode) => {
|
const values = tree.elements.map((treeNode) => {
|
||||||
if (treeNode === null) return '';
|
if (treeNode === null) return '';
|
||||||
if (treeNode.type === 'SpreadElement') return normalizeClassWalker(treeNode.argument);
|
if (treeNode.type === 'SpreadElement') return normalizeClassWalker(treeNode.argument, stack);
|
||||||
return normalizeClassWalker(treeNode);
|
return normalizeClassWalker(treeNode, stack);
|
||||||
});
|
});
|
||||||
if (values.some((x) => x === null)) return null;
|
if (values.some((x) => x === null)) return null;
|
||||||
return values.join(' ');
|
return values.join(' ');
|
||||||
}
|
}
|
||||||
if (tree.type === 'ObjectExpression') {
|
if (tree.type === 'ObjectExpression') {
|
||||||
const values = tree.properties.map((treeNode) => {
|
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 x = treeNode.value;
|
||||||
let inveted = false;
|
let inveted = false;
|
||||||
while (x.type === 'UnaryExpression' && x.operator === '!') {
|
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;
|
if (values.some((x) => x === null)) return null;
|
||||||
return values.join(' ');
|
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;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function normalizeClass(tree: estree.Node): string | null {
|
export function normalizeClass(tree: estree.Node, stack?: string): string | null {
|
||||||
const walked = normalizeClassWalker(tree);
|
const walked = normalizeClassWalker(tree, stack);
|
||||||
return walked && walked.replace(/^\s+|\s+(?=\s)|\s+$/g, '');
|
return walked && walked.replace(/^\s+|\s+(?=\s)|\s+$/g, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
export function unwindCssModuleClassName(ast: estree.Node): void {
|
export function unwindCssModuleClassName(ast: estree.Node): void {
|
||||||
(walk as typeof estreeWalker.walk)(ast, {
|
(walk as typeof estreeWalker.walk)(ast, {
|
||||||
enter(node, parent): void {
|
enter(node, parent): void {
|
||||||
|
//#region
|
||||||
if (parent?.type !== 'Program') return;
|
if (parent?.type !== 'Program') return;
|
||||||
if (node.type !== 'VariableDeclaration') return;
|
if (node.type !== 'VariableDeclaration') return;
|
||||||
if (node.declarations.length !== 1) return;
|
if (node.declarations.length !== 1) return;
|
||||||
|
@ -102,6 +110,14 @@ export function unwindCssModuleClassName(ast: estree.Node): void {
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
if (!~__cssModulesIndex) return;
|
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 cssModuleForestName = ((node.declarations[0].init.arguments[1].elements[__cssModulesIndex] as estree.ArrayExpression).elements[1] as estree.Identifier).name;
|
||||||
const cssModuleForestNode = parent.body.find((x) => {
|
const cssModuleForestNode = parent.body.find((x) => {
|
||||||
if (x.type !== 'VariableDeclaration') return false;
|
if (x.type !== 'VariableDeclaration') return false;
|
||||||
|
@ -117,6 +133,16 @@ export function unwindCssModuleClassName(ast: estree.Node): void {
|
||||||
if (property.value.type !== 'Identifier') return [];
|
if (property.value.type !== 'Identifier') return [];
|
||||||
return [[property.key.value as string, property.value.name as string]];
|
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) => {
|
const sfcMain = parent.body.find((x) => {
|
||||||
if (x.type !== 'VariableDeclaration') return false;
|
if (x.type !== 'VariableDeclaration') return false;
|
||||||
if (x.declarations.length !== 1) 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.type !== 'Identifier') return;
|
||||||
if (ctx.name !== '_ctx') return;
|
if (ctx.name !== '_ctx') return;
|
||||||
if (render.argument.body.type !== 'BlockStatement') 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) {
|
for (const [key, value] of moduleForest) {
|
||||||
|
//#region
|
||||||
const cssModuleTreeNode = parent.body.find((x) => {
|
const cssModuleTreeNode = parent.body.find((x) => {
|
||||||
if (x.type !== 'VariableDeclaration') return false;
|
if (x.type !== 'VariableDeclaration') return false;
|
||||||
if (x.declarations.length !== 1) 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 [];
|
if (actualValue.declarations[0].init?.type !== 'Literal') return [];
|
||||||
return [[actualKey, actualValue.declarations[0].init.value as string]];
|
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, {
|
(walk as typeof estreeWalker.walk)(render.argument.body, {
|
||||||
enter(childNode) {
|
enter(childNode) {
|
||||||
if (childNode.type !== 'MemberExpression') return;
|
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, {
|
(walk as typeof estreeWalker.walk)(render.argument.body, {
|
||||||
enter(childNode) {
|
enter(childNode) {
|
||||||
if (childNode.type !== 'MemberExpression') return;
|
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, {
|
(walk as typeof estreeWalker.walk)(render.argument.body, {
|
||||||
enter(childNode) {
|
enter(childNode) {
|
||||||
if (childNode.type !== 'CallExpression') return;
|
if (childNode.type !== 'CallExpression') return;
|
||||||
if (childNode.callee.type !== 'Identifier') return;
|
if (childNode.callee.type !== 'Identifier') return;
|
||||||
if (childNode.callee.name !== 'normalizeClass') return;
|
if (childNode.callee.name !== 'normalizeClass') return;
|
||||||
if (childNode.arguments.length !== 1) return;
|
if (childNode.arguments.length !== 1) return;
|
||||||
const normalized = normalizeClass(childNode.arguments[0]);
|
const normalized = normalizeClass(childNode.arguments[0], name);
|
||||||
if (normalized === null) return;
|
if (normalized === null) return;
|
||||||
this.replace({
|
this.replace({
|
||||||
type: 'Literal',
|
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) {
|
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({
|
this.replace({
|
||||||
type: 'VariableDeclaration',
|
type: 'VariableDeclaration',
|
||||||
declarations: [{
|
declarations: [{
|
||||||
|
@ -236,6 +409,7 @@ export function unwindCssModuleClassName(ast: estree.Node): void {
|
||||||
}],
|
}],
|
||||||
kind: 'const',
|
kind: 'const',
|
||||||
});
|
});
|
||||||
|
*/
|
||||||
} else {
|
} else {
|
||||||
this.replace({
|
this.replace({
|
||||||
type: 'VariableDeclaration',
|
type: 'VariableDeclaration',
|
||||||
|
@ -263,6 +437,35 @@ export function unwindCssModuleClassName(ast: estree.Node): void {
|
||||||
kind: 'const',
|
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
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div :class="[$style.codeEditorRoot, { [$style.disabled]: disabled, [$style.focused]: focused }]">
|
<div :class="[$style.codeEditorRoot, { [$style.focused]: focused }]">
|
||||||
<div :class="$style.codeEditorScroller">
|
<div :class="$style.codeEditorScroller">
|
||||||
<textarea
|
<textarea
|
||||||
ref="inputEl"
|
ref="inputEl"
|
||||||
|
|
|
@ -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>
|
<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>
|
<div>
|
||||||
<div v-if="tab === 'replies'" :class="$style.tab_replies">
|
<div v-if="tab === 'replies'">
|
||||||
<div v-if="!repliesLoaded" style="padding: 16px">
|
<div v-if="!repliesLoaded" style="padding: 16px">
|
||||||
<MkButton style="margin: 0 auto;" primary rounded @click="loadReplies">{{ i18n.ts.loadReplies }}</MkButton>
|
<MkButton style="margin: 0 auto;" primary rounded @click="loadReplies">{{ i18n.ts.loadReplies }}</MkButton>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -4,7 +4,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div :class="[$style.root, { [$style.disabled]: disabled, [$style.checked]: checked }]">
|
<div :class="[$style.root, { [$style.disabled]: disabled }]">
|
||||||
<input
|
<input
|
||||||
ref="input"
|
ref="input"
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
|
@ -64,9 +64,6 @@ const toggle = () => {
|
||||||
opacity: 0.6;
|
opacity: 0.6;
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
//&.checked {
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.input {
|
.input {
|
||||||
|
|
|
@ -134,10 +134,10 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<div v-else-if="tab === 'roles'" class="_gaps">
|
<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>
|
<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">
|
<div :class="$style.roleItemMain">
|
||||||
<MkRolePreview :class="$style.role" :role="role" :forModeration="true"/>
|
<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-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>
|
<button v-else class="_button" :class="$style.roleUnassign" disabled><i class="ti ti-ban"></i></button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -621,9 +621,6 @@ definePageMetadata(computed(() => ({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.roleItem {
|
|
||||||
}
|
|
||||||
|
|
||||||
.roleItemMain {
|
.roleItemMain {
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<MkTime :time="log.createdAt"/>
|
<MkTime :time="log.createdAt"/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<div :class="$style.root">
|
<div>
|
||||||
<div style="display: flex; gap: var(--margin); flex-wrap: wrap;">
|
<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.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>
|
<div style="flex: 1;">{{ i18n.ts.dateAndTime }}: <MkTime :time="log.createdAt" mode="detail"/></div>
|
||||||
|
@ -134,9 +134,6 @@ const props = defineProps<{
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" module>
|
<style lang="scss" module>
|
||||||
.root {
|
|
||||||
}
|
|
||||||
|
|
||||||
.avatar {
|
.avatar {
|
||||||
width: 18px;
|
width: 18px;
|
||||||
height: 18px;
|
height: 18px;
|
||||||
|
|
|
@ -8,7 +8,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<XSidebar v-if="!isMobile"/>
|
<XSidebar v-if="!isMobile"/>
|
||||||
|
|
||||||
<div :class="$style.main">
|
<div :class="$style.main">
|
||||||
<XAnnouncements v-if="$i" :class="$style.announcements"/>
|
<XAnnouncements v-if="$i"/>
|
||||||
<XStatusBars/>
|
<XStatusBars/>
|
||||||
<div ref="columnsEl" :class="[$style.sections, { [$style.center]: deckStore.reactiveState.columnAlign.value === 'center', [$style.snapScroll]: snapScroll }]" @contextmenu.self.prevent="onContextmenu" @wheel.self="onWheel">
|
<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を効かせるため -->
|
<!-- sectionを利用しているのは、deck.vue側でcolumnに対してfirst-of-typeを効かせるため -->
|
||||||
|
|
|
@ -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">
|
<MkStickyContainer ref="contents" :class="$style.contents" style="container-type: inline-size;" @contextmenu.stop="onContextmenu">
|
||||||
<template #header>
|
<template #header>
|
||||||
<div>
|
<div>
|
||||||
<XAnnouncements v-if="$i" :class="$style.announcements"/>
|
<XAnnouncements v-if="$i"/>
|
||||||
<XStatusBars :class="$style.statusbars"/>
|
<XStatusBars :class="$style.statusbars"/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
Loading…
Reference in a new issue