بنقرة واحدة
add-mk-component
// Misskey フロントエンドの新規 Vue 3 コンポーネントを追加する。Mk* 命名 / SPDX (HTML コメント) / <script setup lang="ts"> / <style lang="scss" module> / *.stories.impl.ts 併設の規約をまとめて適用する。新しい共有 UI コンポーネントを packages/frontend/src/components/ に作る時に使う。
// Misskey フロントエンドの新規 Vue 3 コンポーネントを追加する。Mk* 命名 / SPDX (HTML コメント) / <script setup lang="ts"> / <style lang="scss" module> / *.stories.impl.ts 併設の規約をまとめて適用する。新しい共有 UI コンポーネントを packages/frontend/src/components/ に作る時に使う。
| name | add-mk-component |
| description | Misskey フロントエンドの新規 Vue 3 コンポーネントを追加する。Mk* 命名 / SPDX (HTML コメント) / <script setup lang="ts"> / <style lang="scss" module> / *.stories.impl.ts 併設の規約をまとめて適用する。新しい共有 UI コンポーネントを packages/frontend/src/components/ に作る時に使う。 |
packages/frontend/src/components/ に新しい共有コンポーネントを追加するための規約。
Mk プレフィックス (例: MkButton, MkInput)。ページ固有部品など Mk プレフィックスでないものは原則 pages/ 側に置く。<style lang="scss" module> (CSS Modules) を既定とする。古い scoped 形式が混在しているが、新規では使わない。i18n.ts.<key> 経由で参照する (新キーは add-i18n-key スキルを参照)。alert() / confirm() / window.prompt() は使わない。os.alert / os.confirm / os.popup などを使う。packages/frontend/src/components/Mk<Name>.vue に新規作成する。
ストーリーが必要 (= ほぼ常に必要) なら、同階層に Mk<Name>.stories.impl.ts も作る。Storybook の規約は *.stories.impl.ts であって、*.stories.ts ではない。
.vue ファイル冒頭に必須:
<!--
SPDX-FileCopyrightText: syuilo and misskey-project
SPDX-License-Identifier: AGPL-3.0-only
-->
/* ... */ (TS / JS 形式) ではなく HTML コメント で書くこと。既存の .vue ファイルがすべて HTML コメント形式を使っており、SFC の先頭として自然な形式に統一するため (CI の spdx ジョブはコメント形式ではなく SPDX 文字列の有無のみを検査する)。
MkInfo.vue をベースにする (シンプルな表示コンポーネント):
<!--
SPDX-FileCopyrightText: syuilo and misskey-project
SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
<div :class="$style.root">
<slot></slot>
</div>
</template>
<script lang="ts" setup>
const props = defineProps<{
variant?: 'primary' | 'secondary';
}>();
const emit = defineEmits<{
(ev: 'click'): void;
}>();
</script>
<style lang="scss" module>
.root {
padding: 12px 14px;
border-radius: var(--MI-radius);
background: var(--MI_THEME-panel);
}
</style>
| 項目 | 規約 |
|---|---|
<script> | <script lang="ts" setup>。型パラメータが必要なら generic="T extends ..." を付ける (MkInput.vue 参照) |
defineProps / defineEmits | type-only (<{ ... }>) 形式。runtime の object 形式は使わない |
<style> | lang="scss" module を既定。クラス参照は :class="$style.foo" |
| CSS 変数 | var(--MI_THEME-...) (テーマ) / var(--MI-radius) (UI 共通) — ハードコードしない |
| アイコン | Tabler icons のクラス (<i class="ti ti-info-circle">) を使う |
<script lang="ts" setup>
import { i18n } from '@/i18n.js';
import * as os from '@/os.js';
async function onClick() {
const { canceled } = await os.confirm({
type: 'warning',
text: i18n.ts._notes.deleteConfirm,
});
if (canceled) return;
os.toast(i18n.ts.deleted);
}
</script>
os の主なヘルパー (詳細は os.ts)| 関数 | 用途 |
|---|---|
os.alert({ type, title?, text }) | 単方向アラート |
os.confirm({ type, title, text }) | yes/no 確認 ({ canceled } を返す) |
os.toast(message) | 一時通知 |
os.popup(component, props, handlers) | 任意コンポーネントの非同期ポップアップ |
os.popupMenu(items, anchor?) | コンテキストメニュー |
os.form(title, fields) | フォームダイアログ |
os.apiWithDialog(endpoint, data) | API 呼出し + エラー時ダイアログ表示 |
MkButton.stories.impl.ts を雛形として参考にする。.stories.impl.ts も packages/frontend/src/ 配下の .ts ファイルなので AGENTS.md §1 SPDX ヘッダー必須 の対象であり、冒頭に SPDX ヘッダーを必ず付ける (HTML コメント形式ではなく /* */ 形式)。形式 (以下の MkXxx は実際のコンポーネント名に置換する):
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
/* eslint-disable @typescript-eslint/explicit-function-return-type */
/* eslint-disable import/no-default-export */
import type { StoryObj } from '@storybook/vue3';
import MkXxx from './MkXxx.vue';
export const Default = {
render(args) {
return {
components: { MkXxx },
setup() {
return { args };
},
template: '<MkXxx v-bind="args">slot content</MkXxx>',
};
},
args: {
variant: 'primary',
},
parameters: {
layout: 'centered',
},
} satisfies StoryObj<typeof MkXxx>;
Vue SFC は default export なので、import MkXxx from './MkXxx.vue'; のように名前付き import ではなく default import で書く。実行確認は pnpm --filter frontend storybook-dev。
pnpm --filter frontend lint
(typecheck = vue-tsc 等、ESLint = @misskey-dev/eslint-plugin 含む)
ESLint --fix をピンポイントで:
pnpm exec eslint --fix packages/frontend/src/components/Mk<Name>.vue
Mk* コンポーネントを参考に、スタイルやプロップ命名を揃える。_button / _panel / _selectable などの 共通 utility class (グローバルスタイルにある) を活用できるか確認する。Misskey の i18n キーを追加・修正する。locales/ja-JP.yml のみ編集可能で、他言語ファイル (en-US.yml 等 39 言語) は Crowdin の自動配信先のため絶対に触らない。型は packages/i18n が ja-JP.yml から自動再生成する。frontend からは i18n.ts.<key> または i18n.tsx.<key>(...) で参照する。
Misskey の REST API エンドポイント (/api/<category>/<name>) を NestJS DI + meta/paramDef 規約で追加する。バックエンドに新しい API ルートを足す時に必ず使う。endpoint-list.ts への手動登録、e2e テスト、misskey-js 再生成、CHANGELOG までの一連の手順を含む。
Claude Code セッションのコンテキスト窓消費を agents/skills/MCP/rules/CLAUDE.md ごとに見える化し、肥大化と冗長コンポーネントを検出して節約候補を提示する。"コンテキスト消費を見せて"、"context budget"、"context audit"、"トークン内訳"、"これ以上 MCP 入る?" 等の発話で起動する。
Misskey の TypeORM マイグレーションを公式 CLI (migration:generate / migration:create) で正しく生成し、SPDX ヘッダー付与・up/down 整合・check-migrations 確認まで誘導する。エンティティのスキーマ変更を含むあらゆる DB 変更、または手書き SQL によるデータ移行が必要な時に使用する。