Skip to content

Latest commit

 

History

History
265 lines (220 loc) · 9.12 KB

CONTRIBUTING-ja.md

File metadata and controls

265 lines (220 loc) · 9.12 KB

コントリビューションの手引き

✌️ この度は、ご協力ありがとうございます ✌️

Issues

Feature suggestions and bug reports are filed in https://github.com/sakura-tel/milkey/issues . 機能の要望やバグ報告は https://github.com/sakura-tel/milkey/issues でお願いします

  • 重複を防ぐため、なるべく存在するissueがないか検索してください。もし既に同様の issue があれば、リアクションやコメントを追加して upvote してください。
  • もし複数の独立した issue があるならば、それぞれの issue は別々に作成してください。

ブランチ

  • master ブランチは、最新版の変更を含むブランチです。
  • develop ブランチは次期バージョンリリースのための作業ブランチです。

国際化 (i18n)

Groundpolis は Vue I18n という Vue.js 向けプラグインを使用しています。 Vue I18n の文書は http://kazupon.github.io/vue-i18n/introduction.html にあります。

文書

  • コントリビューター向けの文書は /docs にあります。
  • インスタンス管理者向けの文書は /docs にあります。
  • エンドユーザー向けの文書は /src/docs にあります。

テスト

  • テストコードは /test にあります。

Groundpolis Room へのアイテム追加

  • マテリアル、オブジェクト、テクスチャなどの名前は英語で書いてください。
  • 長さの単位にはメートルを使用してください。
  • (今後編集するために) プルリクエストにはモデルを構成する全てのソースファイル( .png, .blend など)を含めてください。
  • プルリクエストにはモデルの glTF バイナリファイル (.glb)を含めなければなりません。
  • room.furnitures.YOUR_ITEM といったロケールキーを /locales/ja-JP.yml に追加してください。
  • /src/client/app/common/scripts/room/furnitures.json5 に家具の定義を追加してください。

3D モデル制作の経験をお持ちでなければ、我々はフリーの 3DCG ソフトウェア Blender をお勧めします。 glTF 2.0 に関する資料は glTF 2.0 — Blender Manual にあります。

よくある質問

yarn.lock で発生したコンフリクトはどうすれば良いですか?

単純に yarn コマンドを実行してください。

Glossary

AP

ActivityPub の略。

GPFM

GroundPolis Flavored MFM の略。

MFM

Misskey Flavored Markdown の略。

Mk

Misskey の略。

SW

ServiceWorker の略。

Nyaize

「な」が「にゃ」ににゃりますにゃん。

Denyaize

Nyaize を元にもどすにゃん。

TypeScript コーディング規約

セミコロンを省かない

自動セミコロン挿入(ASI) ハザードを防ぐために。

詳細:

基本的に括弧を省かない

ダメ:

if (foo)
	bar;
else
	baz;

良い:

if (foo) {
	bar;
} else {
	baz;
}

次のような特殊なケースにおいて、括弧を省いても構いません:

  • if ステートメントが 1 つのステートメントのみを持ち、
  • else を含まない場合

良い:

if (foo) bar;

条件および、本体となるステートメントを同一行に記述してください。

=== が使える場合、 == を使わない

🥰

真偽値 (もしくは null 系) の値のみ if ステートメントの条件に使うこ

ダメ:

if (foo.length)

良い:

if (foo.length > 0)

export default を使用しない

現在の言語サポートが export default と相性が悪いので...

参照:

ダメ:

export default function(foo: string): string {

良い:

export function something(foo: string): string {

ディレクトリ構造

src ... ソースコード
	@types ... 型定義
	prelude ... 副作用のない JS コーディングのための独立したユーティリティ
	misc ... 副作用のない Groundpolis のための独立したユーティリティ
	service ... 副作用を含む共通の関数
	queue ... ジョブキューとジョブ
	server ... ウェブサーバー
	client ... クライアント
	mfm ... MFM

test ... テストコード

Notes

placeholder

SQLをクエリビルダで組み立てる際、使用するプレースホルダは重複してはならない 例えば

query.andWhere(new Brackets(qb => {
	for (const type of ps.fileType) {
		qb.orWhere(`:type = ANY(note.attachedFileTypes)`, { type: type });
	}
}));

と書くと、ループ中でtypeというプレースホルダが複数回使われてしまいおかしくなる だから次のようにする必要がある

query.andWhere(new Brackets(qb => {
	for (const type of ps.fileType) {
		const i = ps.fileType.indexOf(type);
		qb.orWhere(`:type${i} = ANY(note.attachedFileTypes)`, { [`type${i}`]: type });
	}
}));

Not null in TypeORM

const foo = await Foos.findOne({
	bar: Not(null)
});

のようなクエリ(barnullではない)は期待通りに動作しない。 次のようにします:

const foo = await Foos.findOne({
	bar: Not(IsNull())
});

null in SQL

SQLを発行する際、パラメータがnullになる可能性のある場合はSQL文を出し分けなければならない 例えば

query.where('file.folderId = :folderId', { folderId: ps.folderId });

という処理で、ps.folderIdnullだと結果的にfile.folderId = nullのようなクエリが発行されてしまい、これは正しいSQLではないので期待した結果が得られない だから次のようにする必要がある

if (ps.folderId) {
	query.where('file.folderId = :folderId', { folderId: ps.folderId });
} else {
	query.where('file.folderId IS NULL');
}

[] in SQL

SQLを発行する際、INのパラメータが[](空の配列)になる可能性のある場合はSQL文を出し分けなければならない 例えば

const users = await Users.find({
	id: In(userIds)
});

という処理で、userIds[]だと結果的にuser.id IN ()のようなクエリが発行されてしまい、これは正しいSQLではないので期待した結果が得られない だから次のようにする必要がある

const users = userIds.length > 0 ? await Users.find({
	id: In(userIds)
}) : [];

配列のインデックス in SQL

SQLでは配列のインデックスは1始まり[a, b, c]aにアクセスしたいなら[0]ではなく[1]と書く

undefinedにご用心

MongoDBの時とは違い、findOneでレコードを取得する時に対象レコードが存在しない場合 undefined が返ってくるので注意。 MongoDBはnullで返してきてたので、その感覚でif (x === null)とか書くとバグる。代わりにif (x == null)と書いてください

簡素なundefinedチェック

データベースからレコードを取得するときに、プログラムの流れ的に(ほぼ)絶対undefinedにはならない場合でも、undefinedチェックしないとTypeScriptに怒られます。 でもいちいち複数行を費やして、発生するはずのないundefinedをチェックするのも面倒なので、ensureというユーティリティ関数を用意しています。 例えば、

const user = await Users.findOne(userId);
// この時点で user の型は User | undefined
if (user == null) {
	throw 'missing user';
}
// この時点で user の型は User

という処理をensureを使うと

const user = await Users.findOne(userId).then(ensure);
// この時点で user の型は User

という風に書けます。 もちろんensure内部でエラーを握りつぶすようなことはしておらず、万が一undefinedだった場合はPromiseがRejectされ後続の処理は実行されません。

const user = await Users.findOne(userId).then(ensure);
// 万が一 Users.findOne の結果が undefined だったら、ensure でエラーが発生するので
// この行に到達することは無い
// なので、.then(ensure) は
// if (user == null) {
//	throw 'missing user';
// }
// の糖衣構文のような扱いです

Migration作成方法

npx ts-node ./node_modules/typeorm/cli.js migration:generate -n 変更の名前

作成されたスクリプトは不必要な変更を含むため除去してください。

その他

HTMLのクラス名で follow という単語は使わない

広告ブロッカーで誤ってブロックされる