generated from nhcarrigan/template
feat: write style guide (#52)
Reviewed-on: https://codeberg.org/nhcarrigan/docs/pulls/52 Co-authored-by: Naomi Carrigan <commits@nhcarrigan.com> Co-committed-by: Naomi Carrigan <commits@nhcarrigan.com>
This commit is contained in:
parent
82d9038cdd
commit
691b5390bf
@ -89,6 +89,10 @@ export const navigation = [
|
||||
label: "Contributor Covenant",
|
||||
link: "/dev/covenant"
|
||||
},
|
||||
{
|
||||
label: "Style Guide",
|
||||
link: "/dev/style"
|
||||
},
|
||||
{
|
||||
label: "Issue/PR Labels",
|
||||
link: "/dev/labels"
|
||||
|
@ -329,10 +329,16 @@ Implement JWT-based authentication for API endpoints.
|
||||
|
||||
### 5.7 Testing Your Changes
|
||||
|
||||
- Run the linter to ensure your code complies with [our style guidelines](/dev/style).
|
||||
|
||||
```bash
|
||||
pnpm lint # or the appropriate lint command for your project
|
||||
```
|
||||
|
||||
- Run any existing tests to ensure your changes haven't broken anything:
|
||||
|
||||
```bash
|
||||
pnpm test # or the appropriate test command for your project
|
||||
pnpm test # or the appropriate test command for your project
|
||||
```
|
||||
|
||||
- Add new tests for your changes if applicable.
|
||||
@ -383,7 +389,8 @@ git push -u origin <branchname>
|
||||
- A clear description of the changes
|
||||
- The issue number(s) your pull request addresses
|
||||
- Any additional context or explanations
|
||||
3. If your changes include visual elements, consider adding screenshots or GIFs to illustrate the modifications.
|
||||
3. Fill out the rest of the pull request form *completely*.
|
||||
4. If your changes include visual elements, consider adding screenshots or GIFs to illustrate the modifications.
|
||||
|
||||
### 6.4 Pull Request Best Practices
|
||||
|
||||
|
595
src/content/docs/dev/style.md
Normal file
595
src/content/docs/dev/style.md
Normal file
@ -0,0 +1,595 @@
|
||||
---
|
||||
title: Style Guide
|
||||
---
|
||||
|
||||
This document outlines the style guide that applies to all of our projects.
|
||||
|
||||
## 1. Global Conventions
|
||||
|
||||
These sections apply to all code in any of our projects.
|
||||
|
||||
### 1.1. Copyright Notice
|
||||
|
||||
All code files should begin with a comment section containing the copyright information:
|
||||
|
||||
```js
|
||||
/**
|
||||
* @copyright nhcarrigan
|
||||
* @license Naomi's Public License
|
||||
* @author Naomi Carrigan
|
||||
*/
|
||||
```
|
||||
|
||||
Note that `copyright` _must_ be assigned to `nhcarrigan`, and our `license` must be applied, but when checking in new code you may attribute yourself as the author, or add yourself to the list for existing code.
|
||||
|
||||
## 2. JavaScript Projects
|
||||
|
||||
The following sections apply to our JavaScript/TypeScript projects. Style conventions are enforced through our [custom ESLint package](/projects/eslint).
|
||||
|
||||
:::caution
|
||||
We do _not_ use Prettier in any of our projects. Instead, our linter package also handles code styling.
|
||||
|
||||
If you are using VSCode, you can add this to your `.vscode/settings.json` file in the project directory to enable auto-formatting on save.
|
||||
|
||||
```json
|
||||
{
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.eslint": "explicit"
|
||||
},
|
||||
"eslint.validate": ["typescript"]
|
||||
}
|
||||
```
|
||||
|
||||
Because of this, our style guide will not cover the formatting section of our linter package.
|
||||
:::
|
||||
|
||||
## 2.1. Main Rules
|
||||
|
||||
These rules apply to all TypeScript code, and will run on files in `src/**/*.ts`.
|
||||
|
||||
### 2.1.1. `eslint` Enforced Rules
|
||||
|
||||
- Setters must have a corresponding getter.
|
||||
- Array methods which return a value must return a value in the callback.
|
||||
- Arrow functions should always use curly braces.
|
||||
- Variables must be used within the scope they are defined.
|
||||
- Comments should always start with a capital letter.
|
||||
- Avoid overly complex functions.
|
||||
- `return` statements must either never return a value, or always return a value.
|
||||
- `if` statements and similar control blocks should always use curly braces.
|
||||
- Switch statements must always have a default case, and the default case must always come last.
|
||||
- Never use loose equality.
|
||||
- A `for` loops iteration direction must match the conditional bound.
|
||||
- Functions assigned to a property must match the name of the property.
|
||||
- With the exception of callback functions, all functions should be assigned a name.
|
||||
- When using the `function` keyword, prefer `function name()` declarations over `const name = function()` expressions.
|
||||
- Getters should always return a value.
|
||||
- Getters and setters should be grouped together.
|
||||
- You should never use logical assignment operators.
|
||||
- You should never have more than one class per file.
|
||||
- Logical blocks should not be nested more than five levels deep. Prefer extracting into separate functions.
|
||||
- Files should not have more than 300 lines. Prefer extracting into modular functions.
|
||||
- Functions should not have more than 50 lines. Prefer breaking down into smaller logic.
|
||||
- Callbacks should not be nested more than two levels.
|
||||
- Functions should not have more than 20 logical statements/branches.
|
||||
- Constructor names should begin with a capital letter.
|
||||
- Do not use the `alert` API.
|
||||
- Promise executor functions should not be async.
|
||||
- Do not use `await` within loops.
|
||||
- Do not use bitwise operators.
|
||||
- Do not use `arguments.caller` or `arguments.callee`.
|
||||
- Do not declare variables within switch case statements.
|
||||
- Do not reassign class definitions.
|
||||
- Do not compare with `-0`.
|
||||
- Do not perform assignments in conditions e.g. `if (name = "Naomi")`.
|
||||
- Do not use the `console` API, prefer our custom logger.
|
||||
- Avoid confusing operator combinations e.g. `a + b ?? c`.
|
||||
- Avoid constant conditions e.g. `if(false)` or `while(true)`.
|
||||
- Constructors should not return a value. They implicitly return the instance.
|
||||
- Do not use control characters `\x00` in regular expressions.
|
||||
- Do not use `debugger` statements.
|
||||
- Do not use `delete` on variables.
|
||||
- Do not start a regular expression with `=` (confusing with `/=` operator).
|
||||
- Functions should not have multiple parameters with the same name.
|
||||
- Classes should not have multiple members with the same name.
|
||||
- Objects should not have multiple keys with the same name.
|
||||
- If/else statements should not use the same condition.
|
||||
- Switch statements should not have duplicate case conditions.
|
||||
- Import statements should not have duplicate imports.
|
||||
- Prefer using early return over if/else.
|
||||
- Block statements should not be empty.
|
||||
- Character classes in regular expressions should not be empty.
|
||||
- Destructured values should not be empty.
|
||||
- Static class blocks should not be empty.
|
||||
- You should not use loose equality with `null`.
|
||||
- You should not use `eval`.
|
||||
- Do not reassign the error parameter in a catch block.
|
||||
- Do not extend native prototypes.
|
||||
- Do not call `bind` unnecessarily.
|
||||
- Do not cast to a boolean in conditions.
|
||||
- Do not use `continue` or `break` unnecessarily.
|
||||
- All case statements should have a break statement.
|
||||
- Do not reassign function declarations.
|
||||
- Do not reassign global values (e.g. `window`).
|
||||
- Do not use implicit coercion (e.g. `!!bool`, `+num`).
|
||||
- Do not declare global variables. All values should be scoped to a module.
|
||||
- Do not reassign to imported variables.
|
||||
- Do not declare functions in logical blocks.
|
||||
- Do not pass invalid regular expression strings to `RegExp()`.
|
||||
- Do not use `this` outside of classes.
|
||||
- Do not use unusual space characters.
|
||||
- Do not access `__iterator__`.
|
||||
- Do not use loop labels.
|
||||
- Do not create unnecessary blocks.
|
||||
- Do not nest `if` within `else`, use `else if`.
|
||||
- Do not use multi-code characters (such as emotes) within character classes.
|
||||
- Do not chain assignment operators.
|
||||
- Do not use `\` to create multi-line strings. Use concatenation or template strings.
|
||||
- `if` conditions should not be in the negative (e.g. `!bool`).
|
||||
- Do not nest ternary statements.
|
||||
- Do not use `new` outside of an assignment.
|
||||
- Do not use `new` with `BigInt` or `Symbol`.
|
||||
- Do not use `new` with `String`, `Number`, or `Boolean`.
|
||||
- Do not use octal escapes (e.g. `\8`, `\2`).
|
||||
- Do not call the `Math`, `JSON`, `Reflect`, `Atomics`, or `Intl` objects as functions or constructors.
|
||||
- Do not call `new Object()` without an argument.
|
||||
- Do not use octal literals e.g. `071`.
|
||||
- Do not reassign function parameters.
|
||||
- Do not use the `++` operator.
|
||||
- Do not use `return` in promise executors.
|
||||
- Do not use the `__proto__` property.
|
||||
- Prefer calling the Object prototype over builtins (e.g. `Object.prototype.hasOwnProperty.call(foo, "bar")` over `foo.hasOwnProperty("bar")`).
|
||||
- Do not use literal spaces in regular expressions, use the escape sequence `\s`.
|
||||
- Do not return assignment operations.
|
||||
- Do not use `javascript:void` URLs.
|
||||
- Do not assign a variable to itself.
|
||||
- Do not compare a variable with itself.
|
||||
- Do not use the comma operator to evaluate multiple expressions.
|
||||
- Setters should not return a value.
|
||||
- Do not allow sparse arrays.
|
||||
- Do not use `${foo}` template interpolation in regular strings.
|
||||
- Do not reference `this` before calling `super` in constructors that call `super`.
|
||||
- Do not reference variables that are not declared.
|
||||
- Do not initialise variables to `undefined`.
|
||||
- With the exception of trailing underscores for unused variables, do not use dangling underscores.
|
||||
- Do not insert line breaks in confusing locations, such as the middle of a variable assignment.
|
||||
- Do not use a variable in a loop condition that is not modified within the loop.
|
||||
- Do not use a ternary if a simpler approach exists.
|
||||
- There should be no unreachable code.
|
||||
- Do not use control statements in `finally` blocks.
|
||||
- You must use parentheses when negating `in` or `instanceOf`, e.g. `if (!(key in obj))`.
|
||||
- Do not use optional chaining where an undefined value is not allowed.
|
||||
- Do not declare private class members that are not consumed by the class.
|
||||
- Do not declare variables that are unused.
|
||||
- Avoid backreferences in regular expressions when they would match nothing.
|
||||
- Do not use `.call()` or `.apply()` unnecessarily.
|
||||
- `catch` statements should _handle_ an error, not turn around and throw the error.
|
||||
- Do not use computed-key syntax for literal keys e.g. `{["a"]: "b"}`.
|
||||
- Do not concatenate string literals without variables.
|
||||
- Do not escape characters unnecessarily.
|
||||
- Do not rename a reference to the same name e.g. `let { a: a } = b;`.
|
||||
- Do not use redundant `return` statements.
|
||||
- No use of the `var` keyword.
|
||||
- Do not merge `TODO` or `FIX` comments into the main branch.
|
||||
- Do not use the `with` statement.
|
||||
- An object must use either all long-form definitions `{a : a}` or all short-form definitions `{ a }`, but never a mix of the two `{ a, b: c}`.
|
||||
- Avoid shorthand operators `+=`, prefer the explicit `x = x + y`.
|
||||
- Callback functions should be anonymous arrow functions.
|
||||
- Use `const` for all variables that are not reassigned.
|
||||
- Capture groups should be named.
|
||||
- Prefer `Object.hasOwn()`.
|
||||
- Prefer the spread operator over `Object.assign`.
|
||||
- Prefer regular expression literals over the RegExp constructor.
|
||||
- Prefer using the `...` operator instead of `arguments`.
|
||||
- Prefer the spread operator over `.apply()`.
|
||||
- Prefer template literals over string concatenation.
|
||||
- `parseInt()` should always be given a radix.
|
||||
- When an asynchronous function relies on an argument that might change (such as an object reference), care must be taken to avoid race conditions within that function.
|
||||
- Generator functions must use the `yield` keyword.
|
||||
- Object keys must be sorted alphabetically.
|
||||
- Variables within the same declaration block must be sorted alphabetically.
|
||||
- If using the `Symbol` function, you must include a description.
|
||||
- Do not compare to `NaN`, use `Number.isNaN()`.
|
||||
- `typeof` comparators must be a vaild return type of `typeof`.
|
||||
- Conditions should always start with the variable, not the constant.
|
||||
|
||||
### 2.1.2. `typescript-eslint` Enforced Rules
|
||||
|
||||
- Do not use `await` on functions that do not return a Promise.
|
||||
- Exported type definitions should use the `export type` keyword.
|
||||
- Use dot notation for property access, unless such syntax would be invalid.
|
||||
- Do not use the `delete` keyword with arrays.
|
||||
- Do not use `<Object>.toString()` on objects. Prefer `JSON.stringify()`.
|
||||
- Do not assign void values to variables, such as `const log = console.log("Bad");`.
|
||||
- Do not duplicate types (e.g. `type myType = "A" | "A"`).
|
||||
- Promises should always be awaited.
|
||||
- Do not implicitly evaluate code, such as with `new Function()`.
|
||||
- Do not use `void` with functions that do not return a value.
|
||||
- Do not use Promises in places that do not consume them (such as callbacks).
|
||||
- Do not combine string and number values in an enum.
|
||||
- Do not use unions/intersections with overriding values (such as `any` or `unknown`).
|
||||
- Do not use comparison operators with boolean values (e.g. `variable === false`).
|
||||
- Do not pass values to a conditional statement that are always truthy or falsy.
|
||||
- Do not use unnecessary namespace references.
|
||||
- Do not use template strings without interpolated values.
|
||||
- Do not pass type arguments to a function that match the default value of that parameter.
|
||||
- Do not define unused type parameters in a function.
|
||||
- Values with an `any` type should not be passed to function calls.
|
||||
- Values with an `any` type should not be assigned to variables.
|
||||
- Values which have an `any` type should not be called as functions.
|
||||
- Do not merge declarations (instead of `interface Foo` and `class Foo`, use `interface Foo` and `class Bar implements Foo`).
|
||||
- Do not compare enum values against arbitrary values.
|
||||
- Do not use the `Function` type. Functions should have a specific type signature.
|
||||
- Values with an `any` type cannot have properties, and such properties should not be accessed.
|
||||
- Functions should not return an `any` value.
|
||||
- The unary minus operator should only be used on numbers.
|
||||
- `throw` statements should only throw an `Error` instance.
|
||||
- Object properties should be destructured, rather than assigned to variables via direct access.
|
||||
- Use `<Array>.find()` instead of `<Array>.filter()[0]` to find an element in an array.
|
||||
- Use `<Array>.includes()` instead of `<Array>.indexOf() === -1`.
|
||||
- Use `??` instead of `||`.
|
||||
- Use optional chaining when possible.
|
||||
- Promises that reject should always return an Error.
|
||||
- Class members that are not modified outside of the constructor should be `readonly`.
|
||||
- The `.reduce()` callback should have typed parameters.
|
||||
- When using a non-global regular expression, use `<RegExp>.exec` over `<String>.match()`.
|
||||
- Class methods that return `this` should have `this` as the return type, not the class.
|
||||
- When testing the beginning or end of a string, use `<String>.startsWith()` or `<String>.endsWith()`.
|
||||
- Functions which return a Promise must use the `async` keyword.
|
||||
- `<Array>.sort()` should always be given a compare function.
|
||||
- `async` functions must use `await`, or be rewritten without the promise.
|
||||
- The `+` operator can only be used with operands of the same type.
|
||||
- Values interpolated in a template string must be of type `string`.
|
||||
- Functions which return a promise should await that return value.
|
||||
- Conditions should not use nullable values - you must always explicitly compare against `null` or `undefined`.
|
||||
- Switch statements are not preferred, but when you must use them it should have exhaustive cases.
|
||||
- Unbound class methods must be called with the expected scope (e.g. `myClass.method.bind(myClass)`).
|
||||
- The `error` parameter in a catch statement is of type `unknown`.
|
||||
- Function overload signatures must be grouped together.
|
||||
- Array type definitions should use the generic `Array<T>` over `T[]`.
|
||||
- `@ts` directives are disallowed, except for `@ts-expect-error` which requires a description.
|
||||
- Classes with static public properties should have a getter for each property.
|
||||
- Class methods which are not static must make use of `this` or be converted to static.
|
||||
- Prefer passing type arguments to a constructor instead of a type annotation.
|
||||
- Prefer `Record<string, T>` over `{ [key: string]: T}`.
|
||||
- Do not use any type assertions (`x as T`).
|
||||
- Object types should be defined with `interface` over `type`.
|
||||
- Imported values which are only used as types should be imported with `type`.
|
||||
- Function parameters which are optional or have a default value should come after all mandatory parameters.
|
||||
- Functions should always have an explicit return type.
|
||||
- All class members should have an accessibility modifier (`public`, `protected`, `private`).
|
||||
- All exported functions and public class methods should have explicit parameter and return types.
|
||||
- Variables should always be initialised with a value.
|
||||
- Functions which take more than three arguments should take a single object instead.
|
||||
- Class members should be ordered as `constructor`, `fields`, `statics`, `getters`, `setters`, then `methods`.
|
||||
- Method types should use the property signature `func: (arg: string) => string`.
|
||||
- Variables should use `camelCase`, types and classes should use `PascalCase`. Only variables may use a leading underscore to indicate they are unused.
|
||||
- Never use the `Array` constructor.
|
||||
- Do not use non-null assertions.
|
||||
- Enums should not have duplicate values.
|
||||
- Do not use the `delete` operator on dynamic property accesses.
|
||||
- Functions, interfaces, and object types should never be empty.
|
||||
- Do not use `any`.
|
||||
- Classes should not consist solely of static members.
|
||||
- The `for...in` loop should not be used.
|
||||
- When all imported members are type imports, use `import type { a, b }` over `import { type a, type b }`.
|
||||
- Do not use type annotations for variables with a string, number, or boolean value. These can be inferred.
|
||||
- The `void` type should only be used as the _sole_ return type of a function. `(): void | string` is invalid.
|
||||
- Do not reference unsafe values in a loop.
|
||||
- Do not use number literals which would lose precision due to memory constraints.
|
||||
- Classes should use `constructor()`, not `new()`. Interfaces for the class should use `new()`, not `constructor()`.
|
||||
- Do not use namespaces.
|
||||
- Do not use `require()`.
|
||||
- Do not declare variables in an inner scope that share a name with a variable in the outer scope.
|
||||
- Do not alias `this`.
|
||||
- Do not needlessly assign constructor parameters to class members of the same name.
|
||||
- Do not `extends` `any` or `unknown`.
|
||||
- Unused expressions should be removed.
|
||||
- Unused variables should be removed.
|
||||
- Do not access a variable before its definition.
|
||||
- Do not define empty constructors.
|
||||
- Do not define empty exports.
|
||||
- Do not use wrapper types (e.g. use `boolean`, not `Boolean`).
|
||||
- Use `as const` over literal types.
|
||||
- Enum values should always be explicitly initialised.
|
||||
- The `for...of` loop should be used over the `for` loop, when the index _value_ is not needed.
|
||||
- Enum values should always be literal values.
|
||||
- Do not use TypeScript's `///` reference.
|
||||
- Do not use overloads when the same result can be achieved via union types or optional parameters.
|
||||
|
||||
### 2.1.3. `eslint-comments` Enforced Rules
|
||||
|
||||
- Do not use blanket `eslint-disable` directives. All `disable` directives must target specific rules.
|
||||
- All `disable` directives must include a comment explaining why the linter is being bypassed.
|
||||
|
||||
### 2.1.4. `deprecation` Enforced Rules
|
||||
|
||||
- Do not use deprecated methods/features, even if the package still supports them.
|
||||
|
||||
### 2.1.5. `import` Enforced Rules
|
||||
|
||||
- Do not use default imports if the module does not have a default export.
|
||||
- Do not import modules simply to re-export them.
|
||||
- Exports should always be at the end of the file.
|
||||
- With the exception of packages, imports should always have a file extension.
|
||||
- Imports should always be at the beginning of the file.
|
||||
- If a module has multiple named exports, group them in a single `export { a, b }` declaration.
|
||||
- Import statements should be followed by a newline.
|
||||
- Import paths should never be absolute
|
||||
- You should not use AMD syntax
|
||||
- You should not use CJS syntax
|
||||
- You should not define cyclical imports (if file a imports file b, file b CANNOT import file a)
|
||||
- Modules should not use a default export.
|
||||
- A module should not import the same file multiple times.
|
||||
- You should not use dynamic `require` calls.
|
||||
- Named import blocks cannot be empty.
|
||||
- You should not import packages that are not included in the `package.json` file.
|
||||
- You cannot `import` a CommonJS module.
|
||||
- Exports must always be declared with `const`.
|
||||
- You cannot use a named export as the default export.
|
||||
- You cannot use a named export as the property of a default export.
|
||||
- You should not have orphaned modules (modules without any exports, or a module which is never imported).
|
||||
- You cannot use webpack loader syntax.
|
||||
- Imports must be sorted alphabetically, first grouped by: builtin node modules, external packages, internal packages, modules in parent directory, modules in current directory, type-only imports.
|
||||
- There should be no new lines between these groups.
|
||||
|
||||
### 2.1.6. `jsdoc` Enforced Rules
|
||||
|
||||
- `@access` tags should be one of `package`, `private`, `protected`, or `public`.
|
||||
- Asterisks should be aligned.
|
||||
- Lines should not be improperly indented.
|
||||
- `@param` names should reflect the actual parameters.
|
||||
- `@property` names should reflect the actual properties.
|
||||
- Should not use `=` (GCC syntax).
|
||||
- All tags must be valid JSDoc tags.
|
||||
- `@template` names should be used in the `@typedef`.
|
||||
- `@license` tag MUST be set to `Naomi's Public License`.
|
||||
- Tags that do not expect content should not have content.
|
||||
- `@implements` should only be used on constructors or classes.
|
||||
- Tag descriptions should not be just a reflection of the name.
|
||||
- Description tags must be complete sentences.
|
||||
- JSDocs must be multiple lines. The first and last line cannot have text content.
|
||||
- JSDoc syntax must be valid.
|
||||
- JSDocs must have a description.
|
||||
- JSDocs cannot be empty.
|
||||
- A hyphen should separate the parameter name from the description.
|
||||
- JSDocs are required on all public functions, classes, and methods. They are encouraged on all public exports.
|
||||
- Parameters must have a name and description.
|
||||
- Properties must have a name and description.
|
||||
- If a function returns a value, it must be documented in `@returns`.
|
||||
- If a function throws an unhandled error intentionally, it must be documented in `@throws`.
|
||||
- If a generator yields a value, it must be documented in `@yields`.
|
||||
- Tags must be sorted alphabetically.
|
||||
- There should be no blank lines between tags.
|
||||
- Any types referenced must be valid types.
|
||||
|
||||
### 2.1.7. `unicorn` Enforced Rules
|
||||
|
||||
- Regular expressions should use special shorthand where possible.
|
||||
- `catch` blocks should always have `error` as the parameter.
|
||||
- When destructuring an object, all consumed properties should be destructured. Do not perform direct property access on an object that is previously destructured.
|
||||
- When spreading a ternary in an array, both sides of the expression must be of the same type.
|
||||
- Functions should be declared in the highest scope possible.
|
||||
- `Error()` constructor calls must always be given a message.
|
||||
- Escape sequences must use uppercase text.
|
||||
- Files should be named in camelCase.
|
||||
- Do not pass function references as callbacks to array methods.
|
||||
- Do not use `.forEach()`.
|
||||
- Do not use `this` in array methods.
|
||||
- Do not chain `.push()` calls.
|
||||
- Do not use `.reduce()`.
|
||||
- Do not access properties directly from an `await` expression.
|
||||
- Do not use `await` in Promise methods such as `.all()`.
|
||||
- Files should not be empty.
|
||||
- Do not use a `for` loop when you can use a `for...of` loop.
|
||||
- Use Unicode escape sequences over hexadecimal escape sequences.
|
||||
- Use `Array.isArray()` over `instanceof Array`.
|
||||
- `GET` or `HEAD` requests should never have a body.
|
||||
- Do not declare variables that start with `new` or `class`.
|
||||
- Do not use `.length` as the argument to `.slice()`.
|
||||
- Use `Buffer.from()`, not `new Buffer()`.
|
||||
- Do not use objects as default parameters.
|
||||
- Do not pass single-element arrays to Promise methods.
|
||||
- Do not define a class that only has static members.
|
||||
- Do not use `.then()`.
|
||||
- Do not assign to `this`.
|
||||
- Do not use `typeof x === "undefined"`.
|
||||
- `await` cannot be used on non-promise values.
|
||||
- You cannot ignore consecutive values when destructuring an array, e.g. `[,,,, val]`.
|
||||
- You cannot use IIFEs.
|
||||
- Promises should not return `.resolve()` or `.reject()`.
|
||||
- You should not spread an array into a new array without adding values.
|
||||
- You should not associate any case statements with the default statement.
|
||||
- Number literals cannot have trailing zeroes after the decimal place.
|
||||
- Number literals must use proper case.
|
||||
- Numbers over 9999 should use `_` to separate each group of three digits, e.g. `10_000`.
|
||||
- If you need to flatten an array, use `Array.flat()`.
|
||||
- Prefer `.flatMap()` over `.map().flat()`.
|
||||
- Prefer `indexOf` over `findIndex`.
|
||||
- Prefer `.some()` over `.filter().length`.
|
||||
- Prefer `.at()` for accessing array and string indices.
|
||||
- Prefer `.codePointAt()` over `.charCodeAt()`.
|
||||
- Prefer `Date.now()` over `new Date().getTime()`.
|
||||
- Use default parameters instead of reassigning undefined values.
|
||||
- Use `Math.trunc` to round numbers, not bitwise operators.
|
||||
- Use ESM modules, not CJS.
|
||||
- Use coercion functions such as `String()` directly.
|
||||
- Use a negative index instead of `.legnth - 1`.
|
||||
- Use the `node:` protocol when importing built-in packages.
|
||||
- Use `Number` properties instead of global helpers e.g. `Number.isNaN()` over `isNaN()`.
|
||||
- Use `Object.fromEntries` to create an object from key-value pairs.
|
||||
- If a `catch` block does not use the `error` parameter, the parameter should be omitted.
|
||||
- Prefer calling prototype methods over instance methods.
|
||||
- Prefer using `Set.has()` over `Array.includes` to check for existence.
|
||||
- Prefer using `Set.size` over `Array.length`.
|
||||
- Prefer using the spread operator over `Array.concat()` or `String.split("")`.
|
||||
- Prefer using `String.replaceAll()` over regex searches.
|
||||
- Prefer `String.slice()` over `String.substr[ing]()`.
|
||||
- Prefer `String.startsWith()` or `.endsWith()` over `RegExp.test()`.
|
||||
- Prefer `String.trim[Start|End]()` over `String.trim[Left|Right]()`.
|
||||
- Use `structuredClone` to create a deep clone of an object.
|
||||
- Use top-level await instead of IIFEs.
|
||||
- Variable names should not be abbreviated.
|
||||
- `Array.join()` must always be given a separator.
|
||||
- `Number.toFixed()` must always be given a digits argument.
|
||||
|
||||
## 2.2. React Rules
|
||||
|
||||
These rules apply to TSX, and will run on files in `src/**/*.tsx`.
|
||||
|
||||
- Boolean properties should be named accordingly, such as `isEnabled` instead of `enabled`.
|
||||
- Buttons must always have a `type` attribute.
|
||||
- If a radio button or checkbox is checked, it must be `readonly` or have an `onChange` handler.
|
||||
- Default properties should match the property types.
|
||||
- Properties, state, and context should always be destructured.
|
||||
- Components must always have a nmae.
|
||||
- A component cannot consume another component's propTypes.
|
||||
- PropTypes cannot use `any`, `array`, or `object`.
|
||||
- `forwardRef` components must use `ref`.
|
||||
- Components should always be defined as named arrow functions.
|
||||
- State should have matching names, e.g. `[color, setColor]`.
|
||||
- `iframes` should always use the `sandbox` attribute.
|
||||
- Boolean properties should always be explicitly written: `<Component prop={true}>`.
|
||||
- Spaces between JSX elements must be explicitly written: `{' '}`.
|
||||
- Files that contain JSX must have the extension `.jsx` or `.tsx`.
|
||||
- Fragments should always use the shorthand syntax.
|
||||
- Event handlers must be appropriately named: `onChange={this.handleChange}`
|
||||
- Iterators must always have a `key` prop, and it should never be the index.
|
||||
- You should not use `.bind()` in component props
|
||||
- You should not insert comments as text nodes.
|
||||
- Contexts should not use mutable values (e.g. objects), to prevent re-renders.
|
||||
- Components should not have duplicate properties.
|
||||
- Avoid leaking conditional values. Prefer `condition ? <Component> : null` over `condition && <Component>`.
|
||||
- Element text should always be wrapped in JSX containers.
|
||||
- You should never use `javascript:` urls.
|
||||
- `target=_blank` must always be accompanied with `rel=noreferrer`.
|
||||
- You should not use variables that are not declared.
|
||||
- You should not use fragments unless there is no singular wrapping element.
|
||||
- Components should use PascalCase.
|
||||
- You should not spread props multiple times.
|
||||
- Props should be sorted alphabetically.
|
||||
- You should not access `this.state` inside any `setState` functions.
|
||||
- You should not use arrow functions for lifecycle methods.
|
||||
- Children cannot be passed as props.
|
||||
- You cannot use dangerous properties (`dangerouslySetInnerHTML`).
|
||||
- You cannot use deprecated methods.
|
||||
- You cannot use `setState` in `componentDidMount` or `componentDidUpdate` or `componentWillUpdate`.
|
||||
- You cannot directly mutate `this.state`.
|
||||
- You cannot use `findDOMNode`.
|
||||
- You cannot use `isMounted`.
|
||||
- Each file should have only one component.
|
||||
- `ReactDOM.render`'s return value should not be used.
|
||||
- You should not use string references.
|
||||
- `this` cannot be used in stateless functional components.
|
||||
- HTML entities must be escaped.
|
||||
- You cannot use unknown HTML properties.
|
||||
- You cannot use unsafe lifecycle methods.
|
||||
- You cannot define a component within another component.
|
||||
- Class components should not have unused methods.
|
||||
- Components should not have unused propTypes or state
|
||||
- Class components should use the ES6 `class Component extends React.Component` syntax.
|
||||
- Props should be readonly.
|
||||
- Stateless components should be pure functions.
|
||||
- Property accesses must be reflected in the propTypes.
|
||||
- Any optional property must have a default value.
|
||||
- Classes using the `render` method MUST return a value.
|
||||
- Components without children must still have a separate closing tag.
|
||||
- State initialisation must always happen in the constructor.
|
||||
- Static properties should be defined as `static name = `.
|
||||
- The `style` property must always be an object.
|
||||
- Void elements `img`, `br` etc. must never have children.
|
||||
|
||||
## 2.3. Playwright Rules
|
||||
|
||||
These files apply to Playwright End-to-end tests, and will run on `e2e/**/*.spec.ts`.
|
||||
|
||||
- All tests must have at least one `expect` assertion.
|
||||
- `describe` calls cannot be nested more than two levels deep.
|
||||
- Playwright APIs must be `await`ed.
|
||||
- Tests cannot be commented out.
|
||||
- `expect` cannot be called conditionally.
|
||||
- Tests cannot contain conditional logic.
|
||||
- Setup and teardown hooks cannot be duplicated.
|
||||
- You cannot use element handles (`page.$`).
|
||||
- You cannot use `page.$eval()`.
|
||||
- Tests cannot be focused with `.only()`.
|
||||
- Tests cannot be forced with `{ force: true }`.
|
||||
- You cannot use `getByTitle()`.
|
||||
- You cannot use the `networkidle` option.
|
||||
- You cannot use `first()`, `lat()`, or `nth()`.
|
||||
- You cannot use `page.pause()`.
|
||||
- You cannot use `page.locator()`. Prefer specific methods like `page.getByRole()`.
|
||||
- Tests cannot be skipped with `.skip()`.
|
||||
- `expect` can only be called within test blocks.
|
||||
- You cannot reference variables in `page.evaluate()`.
|
||||
- Some Playwright methods are synchronous - these cannot be `await`ed.
|
||||
- You cannot use `.not()` when a specific matcher exists.
|
||||
- You cannot use `page.waitForSelector()` or `page.waitForTimeout()`.
|
||||
- Prefer `.toBeGreaterThan()` over `(x > 5).toBe(true)`.
|
||||
- Prefer `.toBe(5)` over `(x === 5).toBe(true)`
|
||||
- Hooks should be ordered as Playwright calls them: `beforeAll`, `beforeEach`, `afterEach`, `afterAll`.
|
||||
- Hooks should be at the top of the test.
|
||||
- Test names should be lowercase.
|
||||
- Use `.toStrictEqual()` over `.toEqual()`.
|
||||
- Use `.toBe()` over `.toStrictEqual()` for primitive values.
|
||||
- Use `.toContain()` over `.includes()`.
|
||||
- Use `.toHaveCount()` over `locator.count()` and `.toHaveLength()` over `.length`.
|
||||
- Prefer assertions like `.toBeVisible()` over `(locator.isVisible()).toBe(true)`.
|
||||
- Setup and teardown code must be in a hook.
|
||||
- `.toThrow()` assertions require a message.
|
||||
- Tests must be within a `describe` block.
|
||||
- All `expect()` calls must have a custom message.
|
||||
- Promises that contain an `expect` must be awaited.
|
||||
- Tests must have a title that is not empty.
|
||||
|
||||
## 2.4. Vitest Rules
|
||||
|
||||
These files apply to Vitest unit tests, and will run on `test/**/*.spec.ts`.
|
||||
|
||||
:::warn
|
||||
We also mandate the use of `describe`, `it`, and `expect` over `suite`, `test`, and `assert`.
|
||||
:::
|
||||
|
||||
- Files must have `.spec.ts` extension.
|
||||
- consistent-test-it
|
||||
- Tests must have at least one `expect`.
|
||||
- `describe` calls cannot be nested more than two levels deep.
|
||||
- Prefer `.toHaveBeenCalled()` over `.toBeCalled()`.
|
||||
- Tests cannot be commented out.
|
||||
- `expect` cannot be called conditionally.
|
||||
- Tests cannot contain conditional logic.
|
||||
- Tests cannot be run conditionally.
|
||||
- Tests cannot be disabled.
|
||||
- You cannot use the `done()` callback.
|
||||
- Setup and teardown hooks cannot be duplicated.
|
||||
- Tests cannot be focused with `.only()`.
|
||||
- Test titles must be unique.
|
||||
- `node:test` cannot be imported.
|
||||
- Snapshots cannot use string interpolation.
|
||||
- `expect` must be within `it` or `test`.
|
||||
- Tests cannot use `return`.
|
||||
- Prefer `toHaveBeenCalledWith()` over `toHaveBeenCalled()`.
|
||||
- Prefer `.toBeGreaterThan()` over `(x > 5).toBe(true)`.
|
||||
- Use `describe.each` instead of manual loops.
|
||||
- Prefer `.toBe(5)` over `(x === 5).toBe(true)`.
|
||||
- All tests must start with `expect.assertions(number)`.
|
||||
- Use `expect.resolves(fn)` over `expect(await fn)`.
|
||||
- Hooks should be ordered as Vitest calls them: `beforeAll`, `beforeEach`, `afterEach`, `afterAll`.
|
||||
- Hooks should be at the top of the test.
|
||||
- Test titles should be lowercase.
|
||||
- Prefer `vi.fn().mockResolvedValue(val)` over `vi.fn().mockImplementation(() => Promise.resolve(val))`.
|
||||
- Prefer `vi.spyOn(Date, "now")` instead of overwriting the global `Date.now = vi.fn()`.
|
||||
- Use `.toStrictEqual()` over `.toEqual()`.
|
||||
- Use `.toBe()` over `.toStrictEqual()` for primitive values.
|
||||
- Use `.toBeFalsy()` over `.toBe(false)`.
|
||||
- Use `.toBeObject()` over `.toBeInstanceOf(Object)`.
|
||||
- Use `.toBeTruthy()` over `.toBe(true)`.
|
||||
- Use `.toContain()` over `.includes()`.
|
||||
- Use `.toHaveLength()` over `.length`.
|
||||
- Use `test.todo()` instead of `test.skip()`.
|
||||
- Setup and teardown code must be in a hook.
|
||||
- `.toThrow()` assertions require a message.
|
||||
- Tests must be within a `describe` block.
|
||||
- The `describe` callback should not have any parameters and cannot use `return`.
|
||||
- All `expect()` calls must have a custom message.
|
||||
- Tests must have a title that is not empty.
|
@ -6,14 +6,9 @@ title: Join Our Staff Team
|
||||
|
||||
Unless explicitly stated otherwise in a separate written agreement, all positions within our organization are on a voluntary basis. No compensation, monetary or otherwise, should be expected for these roles.
|
||||
|
||||
## 2. Selection Process
|
||||
## 2. Application Process
|
||||
|
||||
Our team member selection process is based on the following criteria:
|
||||
1. Active participation in the community
|
||||
2. Length of membership in the community
|
||||
3. Quality and nature of interactions with other community members
|
||||
|
||||
If you are selected as a potential team member, our representative, Naomi, will contact you directly with further information and instructions.
|
||||
If you feel ready to apply to join our team, please complete the [application form](https://nhcarrigan.com/apply).
|
||||
|
||||
## 3. Legal Disclaimer
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user