Skip to content

Latest commit

 

History

History
178 lines (128 loc) · 8.99 KB

CONTRIBUTING.md

File metadata and controls

178 lines (128 loc) · 8.99 KB

Contributing to foundry-vtt-types

First off, thank you for your interest in contributing to foundry-vtt-types—we need all the help we can get!

The following is a set of guidelines for contributing to foundry-vtt-types. These are mostly guidelines, not rules. Use your best judgment, and feel free to propose changes to this document in a pull request.

Important Resources

Ways of contributing

Reporting bugs (i.e. wrong or missing types)

This section guides you through submitting a bug report for foundry-vtt-types. Following these guidelines helps maintainers and the community understand your report and reproduce the behavior.

Before submitting a bug report

  • Make sure you are using the latest version of foundry-vtt-types for the corresponding Foundry VTT Version.
  • Check if the problem has already been reported in our issue tracker.

How to submit a (good) bug report

Bugs are tracked in our issue tracker. When creating a bug report, please provide the following information by using the template.

  • Provide the exact version of Foundry VTT and foundry-vtt-types that exhibits the problem.
  • Provide minimal steps to reproduce the behavior.
  • Describe the problem in a clear and concise way. This includes the actual behavior.
  • Describe the expected behavior.
  • Optionally, add any additional context if it makes sense.

Requesting features

You can also suggest ideas for the project beyond plain Foundry VTT types. The guidelines are similar to those for bug reporting. The most important one being: Use the template to give all the relevant information about your request.

Your first contribution

If you are unsure where to start, you can look through issues tagged with help wanted. These are issues that we would like to have help with.

We also recommend to take a look at the corresponding project board to make sure that nobody is working on your issue yet. Additionally, please let us know if you start working on a specific issue (by writing a comment in that issue) so that we can avoid doing duplicate work.

Pull requests

Branching model

We use a very simple branching model. We have a branch for every supported Foundry VTT version called foundry-<major>.<minor>.x (e.g. foundry-0.8.x). All changes for the type definitions for a given Foundry VTT version need to be made through Pull Requests towards the corresponding branch.

Submitting pull requests

When creating a pull request, please provide the following information:

  • What issue does this pull request correspond to (if any)?
  • What does this pull request implement?
  • What changes are made in this pull request?

Styleguides, General Guidelines, and Common Patterns

Style

We use prettier to automatically format the code and have ESlint check for the correct formatting. This even runs automatically as a pre-commit hook so usually you don't have to care for much here. However, there is one additional style guideline that prettier doesn't enforce for us:

In TSDoc comments, always make sure to align the - for all @params.

In very rare occasions, it is acceptable to disable prettier for a specific part of the code to improve the formatting manually, e.g. for deeply nested conditional types, which are simply unreadable if we let prettier format them. See Prettier – Ignoring Code to find out how to do this.

General Guidelines

  1. Try to match the source code Foundry VTT as closely as possible in your type definitions. In particular, the order of declarations should be exactly the same. This allows for easy side by side viewing of the original source code and the type definitions, making the life of code reviewers much easier :)
  2. Try not to pollute the global namespace with custom types that are not declared by Foundry VTT itself (typedefs from from Foundry VTT should be declared). Instead use a namespace named like the related class and put your custom type in there. Alternatively, if you don't want the type to be easily accessible at all, make your declaration file a a module (e.g. by adding an empty export), declare the things should should be visible globally in a declare global {} block and simply put the things that should not be visible globally outside of that block.
  3. The file structure follows the structure of Foundry VTT but additionally, every class has its own file and the files are structured by class hierarchy. Declarations for code that is not a class should be structured in a sensible way but there are no clear guidelines.
  4. Generic utility types not defined in Foundry VTT belong in src/types/utils.d.ts.
  5. Utility types that are specific to Foundry VTT belong in src/types/helperTypes.d.ts.
  6. Augments for libraries bundled with Foundry VTT belong in their corresponding file in src/types/augments.
  7. Write tests where applicable. Not everything needs to be tested, these are just type definitions after all. But in particular for complicated type definitions it makes a lot of sense to add tests. That way you can also verify for yourself that your type definitions are actually working as intended.

Common Patterns

Adding type definitions for a getDefaultOptions static property

If the type of the options is different from that of the parent class, provide a new Options interface in the namespace of the class you are adding types for. It makes sense to add the default values in that type via @defaultValue TSDoc. Use this interface as return type for for getDefaultOptions.

If the type does not differ, just use the Options interface from the parent class.

In both cases, provide the default value for getDefaultOptions in TSDoc.

Example:

declare class ActorSheet<
    Options extends ActorSheet.Options = ActorSheet.Options,
    Data extends object = ActorSheet.Data<Options>
  > extends DocumentSheet<Options, Data, InstanceType<ConfiguredDocumentClass<typeof Actor>>> {
  /**
   * @defaultValue
   * ```typescript
   * foundry.utils.mergeObject(super.defaultOptions, {
   *   height: 720,
   *   width: 800,
   *   template: 'templates/sheets/actor-sheet.html',
   *   closeOnSubmit: false,
   *   submitOnClose: true,
   *   submitOnChange: true,
   *   resizable: true,
   *   baseApplication: 'ActorSheet',
   *   dragDrop: [{ dragSelector: '.item-list .item', dropSelector: null }],
   *   token: null,
   * });
   * ```
   */
  static get defaultOptions(): ActorSheet.Options;
  /* ... */
}

Type for a class being used as a value (e.g. assigned to a variable)

If the type is not configurable by the user, it should most likely be ConstructorOf<NameOfTheClass>. This will also allow deriving classes to be used as value. In rare occasions (i.e. when really only instances of this specific class may be assigned, no deriving classes), typeof NameOfTheClass can be used.

Example (documentClass is configurable, sheetClass is not):

    /**
     * Configuration for the ActiveEffect embedded document type
     */
    ActiveEffect: {
      /**
       * @defaultValue `ActiveEffect`
       */
      documentClass: ConfiguredDocumentClassOrDefault<typeof ActiveEffect>;

      /**
       * @defaultValue `ActiveEffectConfig`
       */
      sheetClass: ConstructorOf<ActiveEffectConfig>;
    };

A property in SCREAMING_SNAKE_CASE is being assigned to a class after its definition in Foundry VTT

This is just a static property of the class. Add it to the class at the very bottom.

Example:

In Foundry VTT

class AVSettings {
  /* ... */
}

AVSettings.AV_MODES = {
  DISABLED: 0,
  AUDIO: 1,
  VIDEO: 2,
  AUDIO_VIDEO: 3
};

Type definition

declare class AVSettings {
  /* ... */

  static AV_MODES: {
    DISABLED: 0;
    AUDIO: 1;
    VIDEO: 2;
    AUDIO_VIDEO: 3;
  };
}

Final Words

If you've made it this far: Thanks for reading and for trying to contribute. It is much appreciated. We're hoping to see you soon on the League Discord!