2017-03-30 18:11:38 +02:00
|
|
|
# Contribution guide
|
2018-09-01 11:02:04 +02:00
|
|
|
:v: Thanks for your contributions :v:
|
2017-03-26 14:32:19 +02:00
|
|
|
|
2018-09-01 11:02:04 +02:00
|
|
|
## Issues
|
|
|
|
Feature suggestions and bug reports are filed in https://github.com/syuilo/misskey/issues .
|
|
|
|
Before creating a new issue, please search existing issues to avoid duplication.
|
|
|
|
If you find the existing issue, please add your reaction or comment to the issue.
|
2017-03-26 14:32:19 +02:00
|
|
|
|
2018-09-01 11:02:04 +02:00
|
|
|
## Localization (l10n)
|
2018-09-01 11:15:25 +02:00
|
|
|
Please use [Crowdin](https://crowdin.com/project/misskey) for localization.
|
2017-03-26 14:32:19 +02:00
|
|
|
|
2018-09-01 11:15:25 +02:00
|
|
|
![Crowdin](https://d322cqt584bo4o.cloudfront.net/misskey/localized.svg)
|
2017-03-26 14:32:19 +02:00
|
|
|
|
2018-11-09 16:47:36 +01:00
|
|
|
## Internationalization (i18n)
|
|
|
|
Misskey uses [vue-i18n](https://github.com/kazupon/vue-i18n).
|
|
|
|
|
2018-09-01 11:02:04 +02:00
|
|
|
## Documentation
|
|
|
|
* Documents for contributors are located in `/docs`.
|
|
|
|
* Documents for instance admins are located in `/docs`.
|
|
|
|
* Documents for end users are located in `src/docs`.
|
2017-03-26 14:32:19 +02:00
|
|
|
|
2018-09-01 11:02:04 +02:00
|
|
|
## Test
|
|
|
|
* Test codes are located in `/test`.
|
|
|
|
|
|
|
|
## Continuous integration
|
2018-11-05 02:52:07 +01:00
|
|
|
Misskey uses CircleCI for automated test.
|
|
|
|
Configuration files are located in `/.circleci`.
|
2018-12-19 19:01:02 +01:00
|
|
|
|
|
|
|
## Glossary
|
|
|
|
### AP
|
2018-12-19 19:02:19 +01:00
|
|
|
Stands for _**A**ctivity**P**ub_.
|
2018-12-19 19:01:02 +01:00
|
|
|
|
|
|
|
### MFM
|
2018-12-19 19:02:19 +01:00
|
|
|
Stands for _**M**isskey **F**lavored **M**arkdown_.
|
2018-12-19 19:01:02 +01:00
|
|
|
|
|
|
|
### Mk
|
2018-12-19 19:02:19 +01:00
|
|
|
Stands for _**M**iss**k**ey_.
|
2018-12-19 19:44:19 +01:00
|
|
|
|
|
|
|
### SW
|
|
|
|
Stands for _**S**ervice**W**orker_.
|
2019-01-24 11:52:00 +01:00
|
|
|
|
|
|
|
### Nyaize
|
2019-02-26 10:00:47 +01:00
|
|
|
Convert な(na) to にゃ(nya)
|
2019-01-24 11:52:00 +01:00
|
|
|
|
|
|
|
#### Denyaize
|
2019-02-26 10:00:47 +01:00
|
|
|
Revert Nyaize
|
2019-02-07 06:54:14 +01:00
|
|
|
|
|
|
|
## Code style
|
2019-03-15 18:53:35 +01:00
|
|
|
### Use semicolon
|
|
|
|
To avoid ASI Hazard
|
|
|
|
|
2019-02-07 06:54:14 +01:00
|
|
|
### Don't use `export default`
|
|
|
|
Bad:
|
|
|
|
``` ts
|
|
|
|
export default function(foo: string): string {
|
|
|
|
```
|
|
|
|
|
|
|
|
Good:
|
|
|
|
``` ts
|
|
|
|
export function something(foo: string): string {
|
|
|
|
```
|
2019-02-07 20:08:25 +01:00
|
|
|
|
|
|
|
## Directory structure
|
|
|
|
```
|
2019-02-26 10:00:47 +01:00
|
|
|
src ... Source code
|
|
|
|
@types ... Type definitions
|
|
|
|
prelude ... Independence utils for coding JavaScript without side effects
|
|
|
|
misc ... Independence utils for Misskey without side effects
|
|
|
|
service ... Common functions with side effects
|
|
|
|
queue ... Job queues and Jobs
|
|
|
|
server ... Web Server
|
|
|
|
client ... Client
|
2019-02-07 20:08:25 +01:00
|
|
|
mfm ... MFM
|
|
|
|
|
2019-02-26 10:00:47 +01:00
|
|
|
test ... Test code
|
2019-02-07 20:08:25 +01:00
|
|
|
|
|
|
|
```
|
2019-04-07 14:50:36 +02:00
|
|
|
|
|
|
|
## Notes
|
|
|
|
### placeholder
|
|
|
|
SQLをクエリビルダで組み立てる際、使用するプレースホルダは重複してはならない
|
|
|
|
例えば
|
|
|
|
``` ts
|
|
|
|
query.andWhere(new Brackets(qb => {
|
|
|
|
for (const type of ps.fileType) {
|
|
|
|
qb.orWhere(`:type = ANY(note.attachedFileTypes)`, { type: type });
|
|
|
|
}
|
|
|
|
}));
|
|
|
|
```
|
|
|
|
と書くと、ループ中で`type`というプレースホルダが複数回使われてしまいおかしくなる
|
|
|
|
だから次のようにする必要がある
|
|
|
|
```ts
|
|
|
|
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 });
|
|
|
|
}
|
|
|
|
}));
|
|
|
|
```
|
|
|
|
|
|
|
|
### `null` in SQL
|
|
|
|
SQLを発行する際、パラメータが`null`になる可能性のある場合はSQL文を出し分けなければならない
|
|
|
|
例えば
|
|
|
|
``` ts
|
|
|
|
query.where('file.folderId = :folderId', { folderId: ps.folderId });
|
|
|
|
```
|
|
|
|
という処理で、`ps.folderId`が`null`だと結果的に`file.folderId = null`のようなクエリが発行されてしまい、これは正しいSQLではないので期待した結果が得られない
|
|
|
|
だから次のようにする必要がある
|
|
|
|
``` ts
|
|
|
|
if (ps.folderId) {
|
|
|
|
query.where('file.folderId = :folderId', { folderId: ps.folderId });
|
|
|
|
} else {
|
|
|
|
query.where('file.folderId IS NULL');
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
### `[]` in SQL
|
|
|
|
SQLを発行する際、`IN`のパラメータが`[]`(空の配列)になる可能性のある場合はSQL文を出し分けなければならない
|
|
|
|
例えば
|
|
|
|
``` ts
|
|
|
|
const users = await Users.find({
|
|
|
|
id: In(userIds)
|
|
|
|
});
|
|
|
|
```
|
|
|
|
という処理で、`userIds`が`[]`だと結果的に`user.id IN ()`のようなクエリが発行されてしまい、これは正しいSQLではないので期待した結果が得られない
|
|
|
|
だから次のようにする必要がある
|
|
|
|
``` ts
|
|
|
|
const users = userIds.length > 0 ? await Users.find({
|
|
|
|
id: In(userIds)
|
|
|
|
}) : [];
|
|
|
|
```
|
|
|
|
|
|
|
|
### `undefined`にご用心
|
|
|
|
MongoDBの時とは違い、findOneでレコードを取得する時に対象レコードが存在しない場合 **`undefined`** が返ってくるので注意。
|
|
|
|
MongoDBは`null`で返してきてたので、その感覚で`if (x === null)`とか書くとバグる。代わりに`if (x == null)`と書いてください
|