Blockly Style Guide

Follow the Google TypeScript style guide.

Migration to TypeScript & ES6

Blockly was originally written in ES5.1 in compliance with an older, then-current version of the Google JavaScript style guide. Newly-written code should comply with the current style guide and use ES6 language features like let, const, class, destructuring assignment where applicable. Existing code may be updated or may be left out of compliance. The Blockly team tries to make the best decision taking into account code consistency and the experience for users of the library - for example, we may opt not to rename public functions that no longer comply with the style guide.

Do

  • Use linting and formatting tools.
    • We use eslint and have a .eslintrc.js file set up with rules for our preferred style.
    • We use prettier for automatic formatting.
    • Run npm run lint to run the linter and npm run format to run the formatter.
  • Indent with spaces, not tabs.
  • Use semicolons.
  • Use camelCase for variables and functions.
  • Use TitleCase for classes.
  • Use ALL_CAPS for constants.
  • Use braces for all control structures.
    • Exception: You may omit the braces for single-line if statements.
  • Use single quotes (except when writing JSON).
  • Redeclare variables in for loops. That is, always write for (const i = 0; ...) instead of for (i = 0; ...).
    • Not doing so raises the risk that after a refactor higher up in the function the variable will be orphaned and become a surprise global.
  • Start comments with capital letters and end them with periods.
  • Create GitHub issues with TODOs and link them using TODO(#issueNumber).
  • Annotate everything with TSDoc.

Don't

  • Indent with tabs.
  • Use underlines at the ends of variable or function names.
    • Some earlier code uses underscores for private or internal properties or functions. While these may continue to exist, no new code should be added following this convention.
  • Use snake_case.
  • Use double quotes (except when writing JSON).
  • Use malformed TSDoc.
    • Our TSDoc is automatically published as part of our documentation.
  • Write TODO (username).
    • Instead create GitHub issues with TODOs and link them using TODO(#issueNumber).
  • Use string.startsWith. Use Blockly.utils.string.startsWith instead.

TSDoc

The Blockly team uses TSDoc to annotate our code and generate documentation. We expect TSDoc for all public properties of classes, and for all exported functions.

TSDoc comments must start with /** and end with */ to be parsed correctly.

Types

Types are omitted from TSDoc because that information is in the TypeScript code directly. If you are editing one of the few remaining JavaScript files, include type annotations according to the Closure Compiler documentation.

Visibility

Functions or properties that should only be accessed within the Blockly library should be annotated with @internal. This prevents these properties from appearing in the public documentation. Other visibility modifiers should be placed in the TypeScript code directly, not in the TSDoc.

Properties

TSDoc for properties should include a description of the property. The description may be omitted for self-explanatory properties.

/**
  *   The location of the top left of this block (in workspace coordinates)
  *   relative to either its parent block, or the workspace origin if it has no
  *   parent.
  *
  *   @internal
  */
relativeCoords = new Coordinate(0, 0);

Functions

Annotations for functions should include

  • A description of the function
  • One @param tag per parameter, including
    • Name
    • Description
  • A @returns tag if the function will return a value, with a description of the returned value.

Descriptions may omitted for functions, parameters, or return values if they are self-explanatory.

For example:

/**
 *   Find the workspace with the specified ID.
 *
 *   @param id ID of workspace to find.
 *   @returns The sought after workspace or null if not found.
 */
export function getWorkspaceById(id: string): Workspace | null {
  return WorkspaceDB_[id] || null;
}