Files
docx-js/docs/contribution-guidelines.md
2025-04-17 00:41:04 +01:00

226 lines
5.7 KiB
Markdown

# Contribution Guidelines
- Include documentation reference(s) at the top of each file as a comment. For example:
```ts
// http://officeopenxml.com/WPdocument.php
```
<!-- cSpell:ignore datypic -->
It can be a link to `officeopenxml.com` or `datypic.com` etc.
It could also be a reference to the official ECMA-376 standard: https://www.ecma-international.org/publications-and-standards/standards/ecma-376/
- Include a portion of the schema as a comment for cross reference. For example:
```ts
// <xsd:element name="tbl" type="CT_Tbl" minOccurs="0" maxOccurs="1"/>
```
- Follow Prettier standards, and consider using the [Prettier VSCode](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode) plugin.
- Follow the `ESLint` rules
## Always think about the user
Put yourself in their position, and imagine how they would feel about the feature you wrote.
1. Is it easy to use?
2. Has it been documented well?
3. Is it intuitive?
4. Is it declarative?
5. Is it fun to use?
## Good Commit Names
Please write good commit messages when making a commit: https://chris.beams.io/posts/git-commit/
**Do not:**
<!-- cspell:disable -->
```
c // What?
rtl // Adding acronyms without explaining anything else is not helpful
works! // Glad its working, but the message is not helpful
demo updated // Getting better, but capitalize the first letter
Unesesary coment removed // Make sure to use correct spelling
```
<!-- cspell:enable -->
**Do**
`ITableFloatOptions` is an interface for a JSON of primitives. The end user would need to pass in a json object and not need to worry about the internals:
```ts
public float(tableFloatOptions: ITableFloatOptions): Table
```
## Declarative API
Make sure the API is declarative, so no _method calling_ or _mutation_. This is a design decision, consistent with the rest of the project. There are benefits to declarative code over other styles of code, explained here: https://dzone.com/articles/why-declarative-coding-makes-you-a-better-programm
**Do not:**
```ts
const paragraph = doc.createParagraph();
const text = paragraph.createText();
text.contents = "Hello World";
```
**Do**
```ts
const doc = new Document({
sections: [{
children: [
new Paragraph({
children: [new TextRun("Hello World")],
}),
],
}];
});
```
## Getters and Setters
Getters and Setters are done with a capital letter like so:
```ts
public get Level() {
...
}
```
This is the convention of this project. There is no performance advantage by doing this. It means we don't need to prefix all private variables with `_`:
**Do not:**
```ts
private get _level: string;
```
**Do**
```ts
private get level: string;
```
## Types over interfaces
Using `type` aliases in TypeScript offers several advantages over `interfaces`:
- **Flexibility with Complex Types**: `type` supports defining unions, intersections, and other complex type constructs that `interfaces` cannot handle. For example:
```typescript
type StringOrNumber = string | number;
type Combined = TypeA & TypeB;
```
- **Support for Primitive Types**: `type` can alias primitive types (e.g., `type ID = string`), while `interfaces` are limited to object shapes.
- **Tuple and Array Types**: `type` allows defining tuples and specific array types easily (e.g., `type Point = [number, number]`), which `interfaces` cannot represent.
- **Utility Types Compatibility**: `type` works seamlessly with TypeScript's utility types (e.g., `Partial<T>`, `Pick<T, K>`), enabling more expressive type transformations.
- **Functional Programming**: `type` is ideal for functional programming patterns, such as defining function signatures or mapped types, due to its versatility.
- **No Declaration Merging**: Unlike `interfaces`, type does not support declaration merging, which can prevent accidental type extensions and ensure predictable type definitions.
- **Consistent Pattern**: This project uses `type` for all type definitions, so using `type` for all type definitions maintains consistency and readability across the codebase.
Detailed discussion: https://stackoverflow.com/questions/37233735/typescript-interfaces-vs-types
**Do not:**
```ts
interface IRelationshipFileInfo {
id: number;
target: string;
}
```
**Do:**
```ts
type RelationshipFileInfo = { id: number; target: string };
```
## String enums vs type
To take full advantage of TypeScript's typing system, its best to use `string enums`:
**Do not:**
```ts
type WeaponType = "bow" | "sword" | "wand";
```
**Do:**
```ts
enum WeaponType = {
BOW = "bow",
SWORD = "sword",
WAND = "wand",
}
```
## Spell correctly, in full and in American English
**Do not:**
```ts
readdy; // misspelling
perm; // abbreviation
conf; // abbreviation
cnty; // abbreviation
relationFile; // abbreviation
colour; // U.K. English
```
**Do:**
```ts
ready;
permission;
config;
country;
relationshipFile;
color;
```
## Keep files small (within reason)
To minimize merge conflicts, reduce complexity, and improve readability, keep the files small.
## Name files and folders with `/foo-bar/kebab-case.ts`
To be consistent and in-line with the project, name files `like-this.ts`.
https://stackoverflow.com/questions/7273316/what-is-the-javascript-filename-naming-convention
## Testing
Please write a test of every file you make and suffix it with `.spec.ts`.
Here is a template of a test:
```ts
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
describe("ClassName", () => {
afterEach(() => {
// TODO
});
beforeEach(() => {
// TODO
});
describe("#methodName()", () => {
it("should ", () => {
// TODO
});
});
});
```
Try not to use the `tests/utility.ts` file as this is being deprecated.