npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@canva/prettier

v3.3.2-canva.0

Published

Prettier is an opinionated code formatter

Downloads

237,941

Readme

@canva/prettier

What is this?

This is Canva's fork of prettier so that we can customize it to suit our style. Prettier is (by intentional design) not very customizable, so in order for us to tweak the formatting we need to fork it. Because forking is a very heavy process to maintain whilst keeping up-to-date with upstream, we aim to make as few changes as possible.

Differences

Place Logical Operators at the start of the line

Prettier places logical operators at the end of the line. The canva style prefers operators at the start of the line.

Input:

function f() {
  const appEntities = getAppEntities(loadObject).filter(
    (entity) =>
      entity
      && entity.isInstallAvailable()
      && !entity.isQueue()
      && entity.isDisabled()
  );
}

prettier Upstream:

function f() {
  const appEntities = getAppEntities(loadObject).filter(
    (entity) =>
      entity &&
      entity.isInstallAvailable() &&
      !entity.isQueue() &&
      entity.isDisabled()
  );
}

@canva/prettier:

function f() {
  const appEntities = getAppEntities(loadObject).filter(
    (entity) =>
      entity
      && entity.isInstallAvailable()
      && !entity.isQueue()
      && entity.isDisabled()
  );
}

Array Pattern and Object Pattern newline retention

Prettier will forcefully remove newlines from array patterns and object patterns unless the node does not fit onto one line. Our previous formatter, dprint, would retain the manual newline. In order to reduce migration churn, we opted to retain these newlines.

Input:

// array

const [x, y] = [x, y];
const [
  x, y] = [x, y];
const [x, y] = [
  x, y];
const [
  x, y] = [
  x, y];

// object

const {x, y} = {x, y};
const {
  x, y} = {x, y};
const {x, y} = {
  x, y};
const {
  x, y} = {
  x, y};

prettier Upstream:

// array

const [x, y] = [x, y];
const [x, y] = [x, y];
const [x, y] = [x, y];
const [x, y] = [x, y];

// object

const { x, y } = { x, y };
const { x, y } = { x, y };
const { x, y } = {
  x,
  y,
};
const { x, y } = {
  x,
  y,
};

@canva/prettier:

// array

const [x, y] = [x, y];
const [
  x,
  y,
] = [x, y];
const [x, y] = [
  x,
  y,
];
const [
  x,
  y,
] = [
  x,
  y,
];

// object

const {x, y} = {x, y};
const {
  x,
  y,
} = {x, y};
const {x, y} = {
  x,
  y,
};
const {
  x,
  y,
} = {
  x,
  y,
};

Delimit Object Literal Types with , and Interfaces with ;

Prettier uses ; to delimit all object type-like members. The canva style uses , for object literal types so they look closer to object expressions.

Input:

type T = {
  a: 1
  b(): void
  new(): T
  [c: string]: 1
};
interface T {
  a: 1
  b(): void
  new(): T
  [c: string]: 1
}

prettier Upstream:

type T = {
  a: 1;
  b(): void;
  new(): T;
  [c: string]: 1;
};
interface T {
  a: 1;
  b(): void;
  new(): T;
  [c: string]: 1;
}

@canva/prettier:

type T = {
  a: 1,
  b(): void,
  new(): T,
  [c: string]: 1,
};
interface T {
  a: 1;
  b(): void;
  new(): T;
  [c: string]: 1;
}

Format intersection types the same as union types

Prettier formats intersections in their own, bespoke style that doesn't match union types or binary expressions.. This leads to many edge-cases of subpar formatting and also creates inconsistent styling between types.

Input:

type T1 = 'type one' & 'type two' & 'type three' & 'type four' & 'type five' & 'type six';
type T2 = Pick<TTTTTTTTTTTTTTTTTTTTTTTTTTT, 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'> & Fooooooooo;
type T3 =
  & {
    type: JSONSchema4TypeName[];
  }
  & JSONSchema4ObjectSchema
  & JSONSchema4ArraySchema
  & JSONSchema4StringSchema
  & JSONSchema4NumberSchema
  & JSONSchema4BoleanSchema
  & JSONSchema4NullSchema
  & JSONSchema4AnySchema;

prettier Upstream:

type T1 = "type one" &
  "type two" &
  "type three" &
  "type four" &
  "type five" &
  "type six";
type T2 = Pick<
  TTTTTTTTTTTTTTTTTTTTTTTTTTT,
  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
> &
  Fooooooooo;
type T3 = {
  type: JSONSchema4TypeName[],
} & JSONSchema4ObjectSchema &
  JSONSchema4ArraySchema &
  JSONSchema4StringSchema &
  JSONSchema4NumberSchema &
  JSONSchema4BoleanSchema &
  JSONSchema4NullSchema &
  JSONSchema4AnySchema;

@canva/prettier:

type T1 =
  & "type one"
  & "type two"
  & "type three"
  & "type four"
  & "type five"
  & "type six";
type T2 =
  & Pick<TTTTTTTTTTTTTTTTTTTTTTTTTTT, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa">
  & Fooooooooo;
type T3 =
  & {
      type: JSONSchema4TypeName[],
    }
  & JSONSchema4ObjectSchema
  & JSONSchema4ArraySchema
  & JSONSchema4StringSchema
  & JSONSchema4NumberSchema
  & JSONSchema4BoleanSchema
  & JSONSchema4NullSchema
  & JSONSchema4AnySchema;

Don't apply special formatting to 2D arrays

Prettier applies special logic to detect 2-dimensional arrays and enforces that each sub-array is placed on its own line. This detection is inconsistent, however, as it requires all sub-arrays to be at least of length 2; if even one sub-array isn't that long then the formatting uses different.

Input:

const x = [[1, 2], [1, 2], [1, 2]];
const x = [[1, 2], [1, 2], [1]];

prettier Upstream:

const x = [
  [1, 2],
  [1, 2],
  [1, 2],
];
const x = [[1, 2], [1, 2], [1]];

@canva/prettier:

const x = [[1, 2], [1, 2], [1, 2]];
const x = [[1, 2], [1, 2], [1]];

Enforce that control-flow statements must have a block body

Prettier endeavors to avoid changing the AST with its formatting pass. It does this on purpose because it makes it easy to prevent accidental runtime changes, however it does limit the scope of formats a little. In our ESLint config we use the curly ESLint rule which enforce that all control flow statements have their body "wrapped in curly braces".

Instead of relying on a lint rule and applying its fixer after prettier runs, we instead integrate this directly into prettier itself so that the formatting can be done in one pass.

Input:

if (true) expression;

if (true) expression; else expression;

if (true) expression; else if (true) expression;

while (true) expression;

for (; ;) expression;

for (let x of y) expression;

for (let x in y) expression;

do expression; while (true);

prettier Upstream:

if (true) expression;

if (true) expression;
else expression;

if (true) expression;
else if (true) expression;

while (true) expression;

for (;;) expression;

for (let x of y) expression;

for (let x in y) expression;

do expression;
while (true);

@canva/prettier:

if (true) {
  expression;
}

if (true) {
  expression;
} else {
  expression;
}

if (true) {
  expression;
} else if (true) {
  expression;
}

while (true) {
  expression;
}

for (;;) {
  expression;
}

for (let x of y) {
  expression;
}

for (let x in y) {
  expression;
}

do {
  expression;
} while (true);

Ignore files with // @formatter:off in their contents

By default prettier formats every single file unless it's listed in the .prettierignore. At canva this can be cumbersome to list every ignored file in the config and sometimes we opt files out by adding a // @formatter:off comment in the code.

Input:

  // @formatter:off

  const yolo              =           "";

prettier Upstream:

  // @formatter:off

  const yolo = '';

@canva/prettier:

  // @formatter:off

  const yolo              =           "";

Contributing

Merging upstream

  1. Clone this repo
  2. Add a new remote git remote add upstream [email protected]:prettier/prettier.git
  3. Fetch upstream git fetch upstream
  4. Checkout the local upstream branch git switch -c prettier/main origin/prettier/main
  5. Merge the upstream changes git merge upstream/main
  6. Push the changes git push
  7. Checkout our fork's main branch git checkout main
  8. Merge the upstream branch git merge prettier/main
  9. Push the changes git push

Making changes

  1. Clone this repo
  2. yarn install
  3. Make your changes
  4. Add tests for your changes
  5. Ensure all snapshots are updated yarn test -u
  6. Ensure lints pass yarn lint
  7. Commit your changes
  8. Raise a PR titled Prettiest: <change you made>

Publishing

  1. Draft a new release
    • The tag must be named in the form X.X.X-canva.Y - where X.X.X is the current prettier version and Y is the incremental release number starting at 0.
  2. Once you're ready, Publish the release.
    • Publishing will trigger the canva-npm-publish workflow on the tag and do the actual publish to npm.