prettier/website/blog/2019-01-20-1.16.0.md

15 KiB
Raw Blame History

author authorURL title
Ika (@ikatyang) https://github.com/ikatyang Prettier 1.16: HTML improvements and better CRLF handling

This release improves HTML formatting and contains better CRLF handling, new syntax features, and fixes several bugs.

Highlights

HTML

Respect surrounding linebreaks (#5596 by @ikatyang)

Previously, Prettier always put elements in a single line if they didnt go past the printWidth, but this doesnt work for elements that are used as if-else blocks or are intended to contain several items. To solve this problem, well respect surrounding linebreaks for all elements since there is no reliable way to determine if theyre being used in these ways.

<!-- Input -->
<div class="list">
  <div class="item">Jan</div>
</div>
<a v-if="i !== -1" href="#" @click.prevent="select(i)">
  {{ i }}
</a>
<span v-else>
  <slot name="ellipsis">&hellip;</slot>
</span>

<!-- Output (Prettier 1.15) -->
<div class="list"><div class="item">Jan</div></div>
<a v-if="i !== -1" href="#" @click.prevent="select(i)"> {{ i }} </a>
<span v-else> <slot name="ellipsis">&hellip;</slot> </span>

<!-- Output (Prettier 1.16) -->
<div class="list">
  <div class="item">Jan</div>
</div>
<a v-if="i !== -1" href="#" @click.prevent="select(i)">
  {{ i }}
</a>
<span v-else>
  <slot name="ellipsis">&hellip;</slot>
</span>

General

Better CRLF handling (#5494 by @ikatyang)

You might have noticed a few weird formatting issues that only occurred on Windows. Many of these issues were caused by our handling of CR-LF line endings. In this release, we were able to resolve these issues by normalizing linebreaks both before and after formatting.

JavaScript

Improve the pattern used by React hooks (#5608 by @j-f1)

// Input
function helloWorld() {
  useEffect(() => {
    // do something
  }, [props.value])
}

// Output (Prettier 1.15)
function helloWorld() {
  useEffect(
    () => {
      // do something
    },
    [props.value]
  );
}

// Output (Prettier 1.16)
function helloWorld() {
  useEffect(() => {
    // do something
  }, [props.value]);
}

Rename babylon parser to babel (#5647 by @wuweiweiwu)

Babels parser, babylon, was renamed to @babel/parser in Babel 7. Weve renamed our babylon parser to babel as well to reduce confusion.

The babylon parser name is now deprecated but it still works.

If you need to change your config due to this change, please take a second to read our docs on the parser option, especially the note at the bottom.

Flow

Add babel-flow parser (#5685 by @ikatyang)

Both the babel and flow parsers support Flow syntax by default, but there are a few edge cases where Flow syntax is ambiguous. By default, Babels Flow parser will parse the ambiguous code as regular JS, while the native Flow parser will parse it as Flow syntax. To address this issue, we added the babel-flow parser option, which uses Babels parser, but prefers Flow syntax when ambiguities arise.

// Input
const Theme = React.createContext<"light" | "dark">("light");

// Output (Prettier 1.15, --parser babylon)
const Theme = (React.createContext < "light") | ("dark" > "light");

// Output (Prettier 1.16, --parser babel-flow)
const Theme = React.createContext<"light" | "dark">("light");

CLI

Add a --check flag (#5629 by @kachkaev)

Passing --list-different to the prettier CLI command will cause Prettier to exit with an error code if one or more of the files passed to it has not been formatted with Prettier. This works great, but it doesnt provide any information in the output except for the files which arent properly formatted. This isnt very friendly for new contributors and users in general, so we added a --check option that produces more human-friendly output.

# Prettier 1.15
$ prettier \*.js --list-different
unformatted.js

# Prettier 1.16
$ prettier \*.js --check
Checking formatting...
unformatted.js
Code style issues found in the above file(s). Forgot to run Prettier?

Other changes

General

Fix unexpected formatting caused by range format (#5632 by @lhchavez)

// Input
something("something", () => {
  const something = {
    something: [
      {
        long1: "longlonglonglonglonglonglonglonglonglonglonglong",
        long2: "longlonglonglonglonglonglonglonglonglonglonglong",
      }
    ]
  };
});

// Output (Prettier 1.15, --range-start 100 --range-end 120)
something("something", () => {
  const something = { something: [{ long1: "longlonglonglonglonglonglonglonglonglonglonglong", long2: "longlonglonglonglonglonglonglonglonglonglonglong" }] };
});

// Output (Prettier 1.16, --range-start 100 --range-end 120)
something("something", () => {
  const something = {
    something: [
      {
        long1: "longlonglonglonglonglonglonglonglonglonglonglong",
        long2: "longlonglonglonglonglonglonglonglonglonglonglong",
      }
    ]
  };
});

API

Allow plugin instances to be passed in the plugins field of format options (#5763 by @Kingwl)

Previously, plugin instances were somehow disallowed to be passed in the plugins field of format options but it should be allowed. We've fixed this issue in Prettier 1.16.

const prettier = require("prettier");
const fooPlugin = require("./path/to/foo-plugin");
const formatted = prettier.format("foo-code", {
  plugins: [fooPlugin],
  parser: "foo-parser"
});
// Prettier 1.15: Error
// Prettier 1.16: No error

Standalone

Remove the dynamic require() call in the standalone bundle (#5612 by @j-f1)

Previously, a dynamic require() call was present in the standalone.js file designed for usage in browsers. It was used in a way where it wasnt actually called, but tools like webpack to throw a warning. We adjusted the build script to remove this require() call in the standalone bundle in Prettier 1.16.

TypeScript

Correctly handle // in TSX (#5728 by @JamesHenry)

Previously, putting // as a child of a JSX element in TypeScript led to an error because it was interpreted as a comment. Prettier 1.16 fixes this issue.

// Input
const link = <a href="example.com">http://example.com</a>

// Output (Prettier 1.15)
// Error: Comment location overlaps with node location

// Output (Prettier 1.16)
const link = <a href="example.com">http://example.com</a>;

Remove redundant parentheses around type annotations (#5724 by @flurmbo)

// Input
class Foo {
  bar: (() => boolean);
}

// Output (Prettier 1.15)
class Foo {
  bar: (() => boolean);
}

// Output (Prettier 1.16)
class Foo {
  bar: () => boolean;
}

JavaScript

Do not treat something.connect() as functional composition (#5739 by @makepost)

A special format for connect() calls was introduced to improve formatting of Redux several versions ago, but there are many other uses for functions named connect that shouldnt be formatted that way. Since most of these cases involved a connect method, we no longer treat foo.connect() calls as functional composition.

// Input
app.connect("activate", async () => {
  await data.load();
  win.show_all();
});
const ConnectedComponent = connect(
  bar,
  baz
)(foo);

// Output (Prettier 1.15)
app.connect(
  "activate",
  async () => {
    await data.load();
    win.show_all();
  }
);
const ConnectedComponent = connect(
  bar,
  baz
)(foo);

// Output (Prettier 1.16)
app.connect("activate", async () => {
  await data.load();
  win.show_all();
});
const ConnectedComponent = connect(
  bar,
  baz
)(foo);

Add support for class private methods (#5637 by @existentialism)

// Input
class Hello {
  #world() {}
}

// Output (Prettier 1.15)
// SyntaxError

// Output (Prettier 1.16)
class Hello {
  #world() {}
}

Correct indentation for expressions in root template (#5607 by @ikatyang)

// Input
if (a) {
  return `
hello
${foo({
  bar,
  baz
})}
world
`;
}

// Output (Prettier 1.15)
if (a) {
  return `
hello
${foo({
    bar,
    baz
  })}
world
`;
}

// Output (Prettier 1.16)
if (a) {
  return `
hello
${foo({
  bar,
  baz
})}
world
`;
}

Remove unnecessary linebreaks from HTML template literals (#5771 by @ikatyang)

// Input
function HelloWorld() {
  return html`
    <h3>Bar List</h3>
    ${bars.map(bar => html`
       <p>${bar}</p>
    `)}
  `;
}

// Output (Prettier 1.15)
function HelloWorld() {
  return html`
    <h3>Bar List</h3>
    ${
      bars.map(
        bar => html`
          <p>${bar}</p>
        `
      )
    }
  `;
}

// Output (Prettier 1.16)
function HelloWorld() {
  return html`
    <h3>Bar List</h3>
    ${bars.map(
      bar => html`
        <p>${bar}</p>
      `
    )}
  `;
}

TypeScript/Flow

Correctly recognize /* HTML */ templates (#5658 by @ikatyang)

We added support for HTML template literal formatting using the /* HTML */ pseudo-tag in Prettier 1.15, but due to a bug, it only worked for JavaScript code. Weve fixed this issue in Prettier 1.16.

CSS

Fix broken output for lists caused by comments (#5710 by @jsnajdr)

// Input
$my-list2:
  a // a
  b
  c;

// Output (Prettier 1.15)
$my-list2: a// a
  bc;

// Output (Prettier 1.16)
$my-list2: a // a
  b c;

Correctly handle backslashes (#5597 by @sh7dm)

// Input
.figcaption {
    .margin-top-1\/2;
    .large\:none;
}

// Output (Prettier 1.15)
.figcaption {
  .margin-top-1\ / 2;
  .large\: none;
}

// Output (Prettier 1.16)
.figcaption {
  .margin-top-1\/2;
  .large\: none;
}

MDX

Correctly handle inline html (#5704 by @ikatyang)

<!-- Input -->
| Column 1 | Column 2 |
|---|---|
| Text | <Hello>Text</Hello> |

<!-- Output (Prettier 1.15) -->
<!-- SyntaxError -->

<!-- Output (Prettier 1.16) -->
| Column 1 | Column 2            |
| -------- | ------------------- |
| Text     | <Hello>Text</Hello> |

HTML

Format script with type "application/ld+json" (#5642 by @ikatyang)

<!-- Input -->
<script type="application/ld+json">
  {   "json":true  }
</script>

<!-- Output (Prettier 1.15) -->
<script type="application/ld+json">
  {   "json":true  }
</script>

<!-- Output (Prettier 1.16) -->
<script type="application/ld+json">
  { "json": true }
</script>

Treat .mjml files as HTML (#5505 by @n1ru4l)

MJML is a markup language that uses the same syntax as HTML. We added the .mjml file extension to the list of extensions that are recognized as HTML, so Prettier will format it.

Smart quote for attributes (#5590 by @ikatyang)

Previously, the quotes around HTML attribute values were always printed as double quotes. To improve readability, they are now printed as the quote type that results in fewer escape characters being required in the string, like we do for other strings.

<!-- Input -->
<div x='123"456'></div>
<div x="123'456"></div>

<!-- Output (Prettier 1.15) -->
<div x="123&quot;456"></div>
<div x="123'456"></div>

<!-- Output (Prettier 1.16) -->
<div x='123"456'></div>
<div x="123'456"></div>

Vue

Tag names are case-sensitive (#5606 by @ikatyang)

Previously, we lowercased tag names before querying tag definition while parsing, which caused <Input> component to be recognized as a native <input>. This would produce a syntax error when </Input> was encountered since <input> is a void element, and void elements cant have closing elements. Weve fixed this issue in 1.16.

<!-- Input -->
<template>
  <Input></Input>
</template>

<!-- Output (Prettier 1.15) -->
<!-- SyntaxError -->

<!-- Output (Prettier 1.16) -->
<template>
  <Input></Input>
</template>

Vue/Angular

Add parentheses to avoid unexpected }} in interpolations (#5657 by @ikatyang)

}} is not allowed to be used in a interpolation since itll be recognized as the end of the interpolation. Prettier 1.15 would sometimes output code that broke this rule. Prettier 1.16 now adds parentheses to prevent }} from appearing in interpolations.

<!-- Input -->
<p>{{ foo({ bar: {} }) }}</p>

<!-- First Output (Prettier 1.15, --no-bracket-spacing) -->
<p>{{ foo({bar: {}}) }}</p>

<!-- Second Output (Prettier 1.15, --no-bracket-spacing) -->
<!-- SyntaxError -->

<!-- Output (Prettier 1.16, --no-bracket-spacing) -->
<p>{{ foo({bar: ({})}) }}</p>