Compare commits
4 Commits
dd99bfe578
...
b5782fbacd
| Author | SHA1 | Date |
|---|---|---|
|
|
b5782fbacd | |
|
|
65e51463c8 | |
|
|
39362f78a6 | |
|
|
8cce6dff51 |
|
|
@ -31,6 +31,7 @@
|
|||
- JSONによるClient Information Discoveryを行うには、レスポンスの`Content-Type`ヘッダーが`application/json`である必要があります
|
||||
- 従来の実装(12 February 2022版・HTML Microformat形式)も引き続きサポートされます
|
||||
- Enhance: メモリ使用量を削減
|
||||
- Fix: `/admin/get-user-ips` エンドポイントのアクセス権限を管理者のみに修正
|
||||
|
||||
## 2025.12.2
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import fs from 'node:fs';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { dirname, join } from 'node:path';
|
||||
import { build } from 'esbuild';
|
||||
import * as esbuild from 'esbuild';
|
||||
import { swcPlugin } from 'esbuild-plugin-swc';
|
||||
|
||||
const _filename = fileURLToPath(import.meta.url);
|
||||
|
|
@ -103,12 +103,16 @@ if (!args.includes('--no-clean')) {
|
|||
fs.rmSync('./built', { recursive: true, force: true });
|
||||
}
|
||||
|
||||
//await minifyJsFiles(join(_dirname, 'node_modules'));
|
||||
|
||||
await minifyJsFiles(join(_dirname, '../../node_modules'));
|
||||
|
||||
await buildSrc();
|
||||
|
||||
async function buildSrc() {
|
||||
console.log(`[${_package.name}] start building...`);
|
||||
|
||||
await build(options)
|
||||
await esbuild.build(options)
|
||||
.then(() => {
|
||||
console.log(`[${_package.name}] build succeeded.`);
|
||||
})
|
||||
|
|
@ -119,3 +123,58 @@ async function buildSrc() {
|
|||
|
||||
console.log(`[${_package.name}] finish building.`);
|
||||
}
|
||||
|
||||
async function minifyJsFile(fullPath) {
|
||||
if (!fullPath.includes('node_modules') || fullPath.includes('storybook') || fullPath.includes('tensorflow') || fullPath.includes('vite') || fullPath.includes('vue') || fullPath.includes('esbuild') || fullPath.includes('typescript') || fullPath.includes('css') || fullPath.includes('lint') || fullPath.includes('roll') || fullPath.includes('sass')) {
|
||||
console.log(`Skipped: ${fullPath}`);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const data = fs.readFileSync(fullPath, 'utf-8');
|
||||
if (data.includes('0 && (module.exports')) {
|
||||
console.log(`Skipped: ${fullPath}`);
|
||||
return;
|
||||
}
|
||||
//await esbuild.build({
|
||||
// entryPoints: [fullPath],
|
||||
// minifyWhitespace: true,
|
||||
// outdir: dirname(fullPath),
|
||||
// allowOverwrite: true,
|
||||
//});
|
||||
const result = await esbuild.transform(data, {
|
||||
minifyWhitespace: true,
|
||||
minifyIdentifiers: true,
|
||||
minifySyntax: false, // nestjsが壊れる
|
||||
treeShaking: false,
|
||||
});
|
||||
fs.writeFileSync(fullPath, result.code, 'utf-8');
|
||||
console.log(`Minified: ${fullPath}`);
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
} catch (err) {
|
||||
console.log(`Skipped (error): ${fullPath}`);
|
||||
}
|
||||
}
|
||||
|
||||
async function minifyJsFiles(dir) {
|
||||
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
||||
for (const entry of entries) {
|
||||
const fullPath = join(dir, entry.name);
|
||||
if (entry.isDirectory()) {
|
||||
await minifyJsFiles(fullPath);
|
||||
} else if (entry.isFile() && entry.name.endsWith('.js')) {
|
||||
await minifyJsFile(fullPath);
|
||||
} else {
|
||||
// resolve symbolic link
|
||||
const stats = fs.lstatSync(fullPath);
|
||||
if (stats.isSymbolicLink()) {
|
||||
const realPath = fs.realpathSync(fullPath);
|
||||
const realStats = fs.statSync(realPath);
|
||||
if (realStats.isDirectory()) {
|
||||
await minifyJsFiles(realPath);
|
||||
} else if (realStats.isFile() && realPath.endsWith('.js')) {
|
||||
await minifyJsFile(realPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ export const meta = {
|
|||
tags: ['admin'],
|
||||
|
||||
requireCredential: true,
|
||||
requireModerator: true,
|
||||
requireAdmin: true,
|
||||
kind: 'read:admin:user-ips',
|
||||
res: {
|
||||
type: 'array',
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<div :class="$style.body">
|
||||
<div :class="$style.top">
|
||||
<button v-tooltip.noDelay.right="instance.name ?? i18n.ts.instance" class="_button" :class="$style.instance" @click="openInstanceMenu">
|
||||
<img :src="instance.iconUrl || '/favicon.ico'" alt="" :class="$style.instanceIcon" style="viewTransitionName: navbar-serverIcon;"/>
|
||||
<img :src="instance.iconUrl || '/favicon.ico'" alt="" :class="$style.instanceIcon" style="view-transition-name: navbar-serverIcon;"/>
|
||||
</button>
|
||||
<button v-if="!iconOnly" v-tooltip.noDelay.right="i18n.ts.realtimeMode" class="_button" :class="[$style.realtimeMode, store.r.realtimeMode.value ? $style.on : null]" @click="toggleRealtimeMode">
|
||||
<i v-if="store.r.realtimeMode.value" class="ti ti-bolt ti-fw"></i>
|
||||
|
|
@ -20,7 +20,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</div>
|
||||
<div :class="$style.middle">
|
||||
<MkA v-tooltip.noDelay.right="i18n.ts.timeline" :class="$style.item" :activeClass="$style.active" to="/" exact>
|
||||
<i :class="$style.itemIcon" class="ti ti-home ti-fw" style="viewTransitionName: navbar-homeIcon;"></i><span :class="$style.itemText">{{ i18n.ts.timeline }}</span>
|
||||
<i :class="$style.itemIcon" class="ti ti-home ti-fw" style="view-transition-name: navbar-homeIcon;"></i><span :class="$style.itemText">{{ i18n.ts.timeline }}</span>
|
||||
</MkA>
|
||||
<template v-for="item in prefer.r.menu.value">
|
||||
<div v-if="item === '-'" :class="$style.divider"></div>
|
||||
|
|
@ -43,14 +43,14 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
<div :class="$style.divider"></div>
|
||||
<MkA v-if="$i != null && ($i.isAdmin || $i.isModerator)" v-tooltip.noDelay.right="i18n.ts.controlPanel" :class="$style.item" :activeClass="$style.active" to="/admin">
|
||||
<i :class="$style.itemIcon" class="ti ti-dashboard ti-fw" style="viewTransitionName: navbar-controlPanel;"></i><span :class="$style.itemText">{{ i18n.ts.controlPanel }}</span>
|
||||
<i :class="$style.itemIcon" class="ti ti-dashboard ti-fw" style="view-transition-name: navbar-controlPanel;"></i><span :class="$style.itemText">{{ i18n.ts.controlPanel }}</span>
|
||||
</MkA>
|
||||
<button class="_button" :class="$style.item" @click="more">
|
||||
<i :class="$style.itemIcon" class="ti ti-grid-dots ti-fw" style="viewTransitionName: navbar-more;"></i><span :class="$style.itemText">{{ i18n.ts.more }}</span>
|
||||
<i :class="$style.itemIcon" class="ti ti-grid-dots ti-fw" style="view-transition-name: navbar-more;"></i><span :class="$style.itemText">{{ i18n.ts.more }}</span>
|
||||
<span v-if="otherMenuItemIndicated" :class="$style.itemIndicator" class="_blink"><i class="_indicatorCircle"></i></span>
|
||||
</button>
|
||||
<MkA v-tooltip.noDelay.right="i18n.ts.settings" :class="$style.item" :activeClass="$style.active" to="/settings">
|
||||
<i :class="$style.itemIcon" class="ti ti-settings ti-fw" style="viewTransitionName: navbar-settings;"></i><span :class="$style.itemText">{{ i18n.ts.settings }}</span>
|
||||
<i :class="$style.itemIcon" class="ti ti-settings ti-fw" style="view-transition-name: navbar-settings;"></i><span :class="$style.itemText">{{ i18n.ts.settings }}</span>
|
||||
</MkA>
|
||||
</div>
|
||||
<div :class="$style.bottom">
|
||||
|
|
@ -65,7 +65,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<i class="ti ti-pencil ti-fw" :class="$style.postIcon"></i><span :class="$style.postText">{{ i18n.ts.note }}</span>
|
||||
</button>
|
||||
<button v-if="$i != null" v-tooltip.noDelay.right="`${i18n.ts.account}: @${$i.username}`" class="_button" :class="[$style.account]" @click="openAccountMenu">
|
||||
<MkAvatar :user="$i" :class="$style.avatar" style="viewTransitionName: navbar-avatar;"/><MkAcct class="_nowrap" :class="$style.acct" :user="$i"/>
|
||||
<MkAvatar :user="$i" :class="$style.avatar" style="view-transition-name: navbar-avatar;"/><MkAcct class="_nowrap" :class="$style.acct" :user="$i"/>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Reference in New Issue