Contribution Guidelines
-
Include documentation reference(s) at the top of each file as a comment. For example:
// http://officeopenxml.com/WPdocument.phpIt can be a link to
officeopenxml.comordatypic.cometc. 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:
// <xsd:element name="tbl" type="CT_Tbl" minOccurs="0" maxOccurs="1"/> -
Format with
oxfmt(bun run format) and follow theoxlintrules (bun run lint).
Always think about the user
Put yourself in their position, and imagine how they would feel about the feature you wrote.
- Is it easy to use?
- Has it been documented well?
- Is it intuitive?
- Is it declarative?
- 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:
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 spellingDo
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:
public float(tableFloatOptions: ITableFloatOptions): TableDeclarative 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:
const paragraph = doc.createParagraph();
const text = paragraph.createText();
text.contents = "Hello World";Do
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:
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:
private get _level: string;Do
private get level: string;Types over interfaces
Using type aliases in TypeScript offers several advantages over interfaces:
-
Flexibility with Complex Types:
typesupports defining unions, intersections, and other complex type constructs thatinterfacescannot handle. For example:type StringOrNumber = string | number; type Combined = TypeA & TypeB; -
Support for Primitive Types:
typecan alias primitive types (e.g.,type ID = string), whileinterfacesare limited to object shapes. -
Tuple and Array Types:
typeallows defining tuples and specific array types easily (e.g.,type Point = [number, number]), whichinterfacescannot represent. -
Utility Types Compatibility:
typeworks seamlessly with TypeScript's utility types (e.g.,Partial<T>,Pick<T, K>), enabling more expressive type transformations. -
Functional Programming:
typeis 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
typefor all type definitions, so usingtypefor all type definitions maintains consistency and readability across the codebase.
Detailed discussion: https://stackoverflow.com/questions/37233735/typescript-interfaces-vs-types
Do not:
interface IRelationshipFileInfo {
id: number;
target: string;
}Do:
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:
type WeaponType = "bow" | "sword" | "wand";Do:
enum WeaponType = {
BOW = "bow",
SWORD = "sword",
WAND = "wand",
}Spell correctly, in full and in American English
Do not:
readdy; // misspelling
perm; // abbreviation
conf; // abbreviation
cnty; // abbreviation
relationFile; // abbreviation
colour; // U.K. EnglishDo:
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:
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.