Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: prettier/prettier
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 3.1.1
Choose a base ref
...
head repository: prettier/prettier
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 3.2.0
Choose a head ref

Commits on Dec 10, 2023

  1. Update dependents count

    sosukesuzuki committed Dec 10, 2023
    Copy the full SHA
    ea4c9af View commit details
  2. Copy the full SHA
    1178b4d View commit details
  3. Git blame ignore 3.1.1

    sosukesuzuki committed Dec 10, 2023
    Copy the full SHA
    1de9db5 View commit details
  4. Fix yarn.lock

    sosukesuzuki committed Dec 10, 2023
    Copy the full SHA
    711e7b5 View commit details
  5. chore(deps): update dependency typescript to v5.3.3 (#15701)

    Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
    renovate[bot] authored Dec 10, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    c1ebae2 View commit details

Commits on Dec 12, 2023

  1. Update contributing.md to mention options philosophy (#15648)

    Co-authored-by: fisker Cheung <lionkay@gmail.com>
    Co-authored-by: Georgii Dolzhykov <thorn.mailbox@gmail.com>
    3 people authored Dec 12, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    e04f0b0 View commit details

Commits on Dec 13, 2023

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    be2fe89 View commit details
  2. Stabilize member chain with empty line (#15522)

    Co-authored-by: fisker Cheung <lionkay@gmail.com>
    seiyab and fisker authored Dec 13, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    224f70f View commit details
  3. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    8227c0a View commit details
  4. chore(deps): update typescript-eslint to v6.14.0 (#15695)

    Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
    renovate[bot] authored Dec 13, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    3728294 View commit details
  5. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    ddf223a View commit details
  6. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    44949eb View commit details
  7. fix(printer-glimmer): preserve path literal segments (#15605)

    * fix(glimmer): preserve path literal segments
    
    This change fixes scenarios where an input handlebars file containing literal segments would be
    reformatted to unwrap the literal segments, causing syntax errors in the resulting output. An
    example of this is below:
    
    ```
    <!-- wrong: input.funky<api!response -->
    {{input.[funky<api!response]}}
    <!-- wrong: input.this one has spaces -->
    {{input.[this one has spaces]}}
    ```
    
    This also handles a scenario where the input contained deprecated '/' delimited paths, ensuring
    that those paths are not wrapped with brackets. This exists to prevent breaking an existing test
    `sub-expressions.hbs`. Handling it this way does lead to some minor ambiguity since glimmer does
    not support these paths, but the ambiguity is probably better than breaking them entirely.
    
    fixes #14207, preventing removal of brackets where necessary
    
    ---------
    
    Co-authored-by: fisker <lionkay@gmail.com>
    maxpowa and fisker authored Dec 13, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    2c689f3 View commit details
  8. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    23b3ca2 View commit details

Commits on Dec 14, 2023

  1. Support formatting for Angular ICU expression (#15777)

    Co-authored-by: fisker <lionkay@gmail.com>
    sosukesuzuki and fisker authored Dec 14, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    153ffd5 View commit details
  2. Switch wcwidth to wcwidth.js

    fisker committed Dec 14, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    7ffc3cc View commit details
  3. chore(deps): update github/codeql-action action to v3 (#15799)

    Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
    renovate[bot] authored Dec 14, 2023
    Copy the full SHA
    7799bfa View commit details
  4. chore(deps): update babel to v7.23.6 (#15800)

    Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
    renovate[bot] authored Dec 14, 2023
    Copy the full SHA
    449eda6 View commit details
  5. chore(deps): update actions/upload-artifact and actions/download-arti…

    …fact action to v4 (#15798)
    
    Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
    Co-authored-by: fisker Cheung <lionkay@gmail.com>
    renovate[bot] and fisker authored Dec 14, 2023
    Copy the full SHA
    1300702 View commit details
  6. chore(deps): update babel to v7.23.6 (#15801)

    Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
    Co-authored-by: fisker Cheung <lionkay@gmail.com>
    renovate[bot] and fisker authored Dec 14, 2023
    Copy the full SHA
    d761a9a View commit details
  7. chore(deps): update dependency esbuild-visualizer to v0.5.0 (#15803)

    Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
    renovate[bot] authored Dec 14, 2023
    Copy the full SHA
    4d4b219 View commit details
  8. chore(deps): update dependency @babel/parser to v7.23.6 (#15802)

    Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
    renovate[bot] authored Dec 14, 2023
    Copy the full SHA
    ad5eeaa View commit details
  9. chore(deps): update dependency flow-parser to v0.224.0 (#15804)

    Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
    Co-authored-by: fisker Cheung <lionkay@gmail.com>
    renovate[bot] and fisker authored Dec 14, 2023
    Copy the full SHA
    aaef1bc View commit details

Commits on Dec 15, 2023

  1. Copy the full SHA
    2ee0016 View commit details
  2. Upgrade to yarn 4 (#15548)

    fisker authored Dec 15, 2023
    Copy the full SHA
    03f05fa View commit details
  3. chore(deps): update dependency esbuild to v0.19.9 (#15808)

    Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
    renovate[bot] authored Dec 15, 2023
    Copy the full SHA
    d09e26b View commit details

Commits on Dec 16, 2023

  1. Copy the full SHA
    65e72a2 View commit details
  2. Copy the full SHA
    d541f0d View commit details

Commits on Dec 17, 2023

  1. Copy the full SHA
    cb6fea8 View commit details
  2. Improve shouldHugType (#15813)

    fisker authored Dec 17, 2023
    Copy the full SHA
    176ff48 View commit details
  3. Copy the full SHA
    6a6b699 View commit details
  4. Add --next flag to release script (#15816)

    Co-authored-by: fisker <lionkay@gmail.com>
    sosukesuzuki and fisker authored Dec 17, 2023
    Copy the full SHA
    863368e View commit details
  5. Copy the full SHA
    1ea2fd0 View commit details
  6. Copy the full SHA
    02c80dc View commit details
  7. Update build script

    fisker authored Dec 17, 2023
    Copy the full SHA
    442a5ce View commit details
  8. Revert "Update build script"

    This reverts commit 442a5ce.
    fisker committed Dec 17, 2023
    Copy the full SHA
    3b3eba8 View commit details
  9. Copy the full SHA
    0ff9efd View commit details

Commits on Dec 18, 2023

  1. Copy the full SHA
    8c7ea9c View commit details
  2. Simplify loadPlugin (#15820)

    fisker authored Dec 18, 2023
    Copy the full SHA
    2189528 View commit details
  3. Improve loadEditorconfig (#15821)

    fisker authored Dec 18, 2023
    Copy the full SHA
    bc0be70 View commit details
  4. Copy the full SHA
    4c3cf0c View commit details
  5. Copy the full SHA
    39fd805 View commit details

Commits on Dec 20, 2023

  1. Copy the full SHA
    8d464ff View commit details
  2. chore(deps): update dependency flow-parser to v0.225.0 (#15839)

    Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
    renovate[bot] authored Dec 20, 2023
    Copy the full SHA
    1fbba57 View commit details

Commits on Dec 25, 2023

  1. chore(deps): update glimmer to v0.87.1 (#15842)

    Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
    renovate[bot] authored Dec 25, 2023
    Copy the full SHA
    f3fff2e View commit details

Commits on Dec 28, 2023

  1. Re-enable tests/dts/unit/cases/parsers.ts - take 2 (#15789)

    Re-enable tests/dts/unit/cases/parsers.ts
    ExplodingCabbage authored Dec 28, 2023
    Copy the full SHA
    2c3e42b View commit details
  2. Use Array#findLast() (#15805)

    fisker authored Dec 28, 2023
    Copy the full SHA
    b9d0c99 View commit details
  3. Somewhat improve conditional type alias (#15811)

    Co-authored-by: fisker Cheung <lionkay@gmail.com>
    seiyab and fisker authored Dec 28, 2023
    Copy the full SHA
    82db5fc View commit details
  4. Run fix:eslint (#15847)

    sosukesuzuki authored Dec 28, 2023
    Copy the full SHA
    66a23c9 View commit details

Commits on Jan 2, 2024

  1. Add jsonc parser (#15831)

    fisker authored Jan 2, 2024
    Copy the full SHA
    1dc924f View commit details
Showing 471 changed files with 13,364 additions and 9,733 deletions.
26 changes: 13 additions & 13 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
.tmp
!/*.js
/tests/format/**/*.js
/tests/integration/cli/
!/tests/format/**/jsfmt.spec.js
!/**/.eslintrc.js
/test*.*
/scripts/release/node_modules
/coverage/
/dist*/
# Do not use `tests/format/**/*`, since it will ignore directories
# https://github.com/eslint/eslint/issues/17964#issuecomment-1879772142
tests/format/**/*.*
!tests/format/**/jsfmt.spec.js
tests/integration/cli/
test*.*
scripts/release/node_modules
coverage/
dist*/
**/node_modules/**
/website/build/
/website/static/playground.js
/website/static/lib/
/scripts/benchmark/*/
website/build/
website/static/playground.js
website/static/lib/
scripts/benchmark/*/
**/.yarn/**
**/.pnp.*
435 changes: 0 additions & 435 deletions .eslintrc.cjs

This file was deleted.

2 changes: 2 additions & 0 deletions .git-blame-ignore-revs
Original file line number Diff line number Diff line change
@@ -5,6 +5,8 @@
# See https://git-scm.com/docs/git-blame#Documentation/git-blame.txt---ignore-revs-fileltfilegt

# Prettier bump after release
# 3.1.1
1178b4dff2cd78c76e8028b6deb5882348c970d9
# 3.1.0
eebf0e4b5ec8ac24393c56ced4b4819d4c551f31
# 3.0.3
3 changes: 3 additions & 0 deletions .github/ISSUE_TEMPLATE/config.yml
Original file line number Diff line number Diff line change
@@ -3,3 +3,6 @@ contact_links:
- name: 🤔 Support question
url: https://stackoverflow.com/questions/ask?tags=prettier
about: Issues are dedicated to development purposes. If you have questions, please use Stack Overflow.
- name: 📝 Help with Visual Studio Code extension for Prettier
url: https://github.com/prettier/prettier-vscode/issues
about: Bugs and feature requests for the Visual Studio Code extension for Prettier
12 changes: 10 additions & 2 deletions .github/ISSUE_TEMPLATE/formatting.md
Original file line number Diff line number Diff line change
@@ -26,7 +26,7 @@ Don't fill the form below manually! Let a program create a report for you:
-->

**Prettier 3.1.1**
**Prettier 3.2.0**
[Playground link](https://prettier.io/playground/#.....)

```sh
@@ -46,4 +46,12 @@ Don't fill the form below manually! Let a program create a report for you:
// code snippet
```

**Expected behavior:**
**Expected output:**

```jsx
// code snippet
```

**Why?**

<!-- short explanation of expected output -->
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/integration.md
Original file line number Diff line number Diff line change
@@ -20,7 +20,7 @@ BEFORE SUBMITTING AN ISSUE:

**Environments:**

- Prettier Version: 3.1.1
- Prettier Version: 3.2.0
- Running Prettier via: <!-- CLI, Node.js API, Browser API, etc. -->
- Runtime: <!-- Node.js v14, Chrome v83, etc. -->
- Operating System: <!-- Windows, Linux, macOS, etc. -->
4 changes: 4 additions & 0 deletions .github/renovate.json5
Original file line number Diff line number Diff line change
@@ -39,6 +39,10 @@
],
labels: ["dependency:tools"],
},
{
matchManagers: ["github-actions"],
groupName: "GitHub Actions",
},
],
ignoreDeps: [
// It's a dependency of `remark-parse`, use same version to reduce size
2 changes: 1 addition & 1 deletion .github/workflows/_build.yml
Original file line number Diff line number Diff line change
@@ -26,7 +26,7 @@ jobs:
run: yarn build --clean

- name: Upload Artifact
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: dist
path: dist
2 changes: 1 addition & 1 deletion .github/workflows/bundler-friendly.yml
Original file line number Diff line number Diff line change
@@ -41,7 +41,7 @@ jobs:
run: yarn install --immutable

- name: Download Artifact
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
with:
name: dist
path: dist
4 changes: 2 additions & 2 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
@@ -32,9 +32,9 @@ jobs:
uses: actions/checkout@v4

- name: Initialize CodeQL
uses: github/codeql-action/init@v2
uses: github/codeql-action/init@v3
with:
config-file: ./.github/codeql/codeql-config.yml

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
uses: github/codeql-action/analyze@v3
3 changes: 1 addition & 2 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
@@ -53,8 +53,7 @@ jobs:
run: yarn lint:blog

- name: Lint docs code block
# TODO: Lint files in `website/versioned_docs/version-stable` too
run: yarn "docs/**/*.md"
run: yarn prettier "{docs,website/versioned_docs/version-stable}/**/*.md" --check
env:
# Make Prettier throws on embeded format
PRETTIER_DEBUG: true
18 changes: 15 additions & 3 deletions .github/workflows/prod-test.yml
Original file line number Diff line number Diff line change
@@ -37,7 +37,7 @@ jobs:
run: yarn install --immutable

- name: Download Artifact
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
with:
name: dist
path: dist
@@ -79,17 +79,29 @@ jobs:
- name: Checkout
uses: actions/checkout@v4

- name: Install yarn@3
if: ${{ matrix.node == '14' || matrix.node == '16' }}
run: |
yarn set version 3
cat .yarnrc.yml
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
cache: "yarn"

- name: Install Dependencies(yarn@3,mutable)
env:
YARN_ENABLE_IMMUTABLE_INSTALLS: false
if: ${{ matrix.node == '14' || matrix.node == '16' }}
run: yarn install

- name: Install Dependencies
run: yarn install --immutable

- name: Download Artifact
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
with:
name: dist
path: dist
@@ -114,7 +126,7 @@ jobs:
node-version: "0.10.48"

- name: Download Artifact
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
with:
name: dist
path: dist
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -10,7 +10,9 @@
*.log
/errors
/test*.*
/.vscode
/.vscode/**/*
!/.vscode/extensions.json
!/.vscode/settings.example.json
/dist*
/website/build
/website/i18n
19 changes: 0 additions & 19 deletions .gitpod.yml
Original file line number Diff line number Diff line change
@@ -4,22 +4,3 @@ tasks:
- init: |
brew install hyperfine
yarn
github:
# https://www.gitpod.io/docs/prebuilds/#configure-prebuilds
prebuilds:
master: true # enable for the default branch (even if it's not named "master")
branches: true
pullRequests: true
pullRequestsFromForks: true
addCheck: true
addComment: false
addBadge: true
addLabel: false

vscode:
extensions:
- esbenp.prettier-vscode
- dbaeumer.vscode-eslint
- editorconfig.editorconfig
- streetsidesoftware.code-spell-checker
4 changes: 4 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -5,3 +5,7 @@ overrides:
- files: "bin/prettier.cjs"
options:
trailingComma: none
# TODO: Enable this after `jsonc` parser released
# - files: ".vscode/*.json"
# options:
# parser: jsonc
8 changes: 8 additions & 0 deletions .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"recommendations": [
"esbenp.prettier-vscode",
"editorconfig.editorconfig",
"dbaeumer.vscode-eslint",
"streetsidesoftware.code-spell-checker"
]
}
15 changes: 15 additions & 0 deletions .vscode/settings.example.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"[javascript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true,
"editor.codeActionsOnSave": ["source.fixAll.eslint"]
},
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit"
},
"prettier.requireConfig": true,
"eslint.experimental.useFlatConfig": true,
"files.exclude": {
"dist*": true
}
}
30 changes: 30 additions & 0 deletions .yarn/plugins/plugin-setup-editor.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
const fs = require("node:fs");
const path = require("node:path");

module.exports = {
name: "plugin-setup-editor",
factory: () => ({
hooks: {
afterAllInstalled() {
const settingsFile = path.join(
__dirname,
"../../.vscode/settings.json",
);

const settingsExampleFile = path.join(
__dirname,
"../../.vscode/settings.example.json",
);

if (
fs.existsSync(settingsFile) ||
!fs.existsSync(settingsExampleFile)
) {
return;
}

fs.copyFileSync(settingsExampleFile, settingsFile);
},
},
}),
};
875 changes: 0 additions & 875 deletions .yarn/releases/yarn-3.7.0.cjs

This file was deleted.

893 changes: 893 additions & 0 deletions .yarn/releases/yarn-4.0.2.cjs

Large diffs are not rendered by default.

7 changes: 6 additions & 1 deletion .yarnrc.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
compressionLevel: mixed

defaultSemverRangePrefix: ""

enableGlobalCache: true

nodeLinker: node-modules

yarnPath: .yarn/releases/yarn-3.7.0.cjs
plugins:
- .yarn/plugins/plugin-setup-editor.cjs

yarnPath: .yarn/releases/yarn-4.0.2.cjs
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
# 3.2.0

[diff](https://github.com/prettier/prettier/compare/3.1.1...3.2.0)

🔗 [Release Notes](https://prettier.io/blog/2024/01/13/3.2.0.html)

# 3.1.1

[diff](https://github.com/prettier/prettier/compare/3.1.0...3.1.1)
@@ -2053,7 +2059,7 @@ Test <a href="https://prettier.io">abc</a>.
#### Fix broken format for `...infer T` ([#9044](https://github.com/prettier/prettier/pull/9044) by [@fisker](https://github.com/fisker))

<!-- prettier-ignore -->
```typescript
```ts
// Input
type Tail<T extends any[]> = T extends [infer U, ...infer R] ? R : never;

4 changes: 4 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -62,6 +62,10 @@ To debug Prettier locally, you can either debug it in Node (recommended) or the
- The easiest way to debug it in Node is to create a local test file with some example code you want formatted and either run it in an editor like VS Code or run it directly via `./bin/prettier.js <your_test_file>`.
- The easiest way to debug it in the browser is to build Prettier's website locally (see [`website/README.md`](website/README.md)).
## No New Options
Prettier is an opinionated formatter and is not accepting pull requests that add new formatting options. You can [read more about our options philosophy here](docs/option-philosophy.md).
## Pull requests
The project uses ESLint for linting and Prettier for formatting. If your editor isn't set up to work with them, you can lint and format all files from the command line using `yarn fix`.
19 changes: 19 additions & 0 deletions changelog_unreleased/angular/15777.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#### Support formatting for Angular ICU expression (#15777 by @sosukesuzuki)

Support two kinds of Angular ICU expressions: [`plural`](https://angular.dev/guide/i18n/translation-files#translate-plurals) and [`select`](https://angular.dev/guide/i18n/translation-files#translate-alternate-expressions).

<!-- prettier-ignore -->
```html
<span i18n>
Updated:
{minutes, plural,
=0 {just now}
=1 {one minute ago}
other {{{minutes}} minutes ago}
}
</span>

<span i18n>
The author is {gender, select, male {male} female {female} other {other}}
</span>
```
30 changes: 30 additions & 0 deletions changelog_unreleased/angular/15827.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#### Fix `prettier-ignore`d angular control flow block (#15827 by @fisker)

<!-- prettier-ignore -->
```html
<!-- Input -->
<!-- prettier-ignore -->
@if (condition) {
Foo
} @else {
Other
}

<!-- Prettier stable -->
<!-- prettier-ignore -->
@if (condition) {
Foo
}
} @else {
Other
}

<!-- Prettier main -->
<!-- prettier-ignore -->
@if (condition) {
Foo
}
@else {
Other
}
```
13 changes: 13 additions & 0 deletions changelog_unreleased/angular/15887.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#### Avoid adding colon for `track` in 3rd expression of `for` blocks (#15887 by @sosukesuzuki)

<!-- prettier-ignore -->
```html
<!-- Input -->
@for (item of items; let i = $index; track block) {}

<!-- Prettier stable -->
@for (item of items; let i = $index; track: block) {}

<!-- Prettier main -->
@for (item of items; let i = $index; track block) {}
```
19 changes: 0 additions & 19 deletions changelog_unreleased/api/15363.md

This file was deleted.

3 changes: 0 additions & 3 deletions changelog_unreleased/api/15663.md

This file was deleted.

15 changes: 15 additions & 0 deletions changelog_unreleased/api/15666.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#### Support absolute path as plugin in config file (#15666 by @fisker)

```js
// prettier.config.cjs
module.exports = {
plugins: [
// posix style
"/path/to/plugin.js",
// Windows style
"D:\\\\path\\to\\plugin.js",
// Use `require.resolve`
require.resolve("my-awesome-prettier-plugin"),
],
};
```
11 changes: 11 additions & 0 deletions changelog_unreleased/api/15854.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#### Fix `getFileInfo` and `getSupportInfo` type definitions (#15854 by @auvred)

```ts
const plugin: Plugin = {};

prettier.getFileInfo("./file.ext", {
plugins: [plugin],
});

prettier.getSupportInfo({ plugins: [plugin], showDeprecated: true });
```
5 changes: 0 additions & 5 deletions changelog_unreleased/cli/15533.md

This file was deleted.

29 changes: 29 additions & 0 deletions changelog_unreleased/graphql/15870.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#### Improve GraphQL union types formatting (#15870 by @ArchitGajjar)

<!-- prettier-ignore -->
```gql
# Input
union SearchResult = Conference| Festival | Concert | Venue | Conference| Festival | Concert | Venue

# Prettier stable
union SearchResult =
Conference
| Festival
| Concert
| Venue
| Conference
| Festival
| Concert
| Venue

# Prettier main
union SearchResult =
| Conference
| Festival
| Concert
| Venue
| Conference
| Festival
| Concert
| Venue
```
21 changes: 21 additions & 0 deletions changelog_unreleased/handlebars/15605.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#### Preserve path literal segments (#15605 by @maxpowa)

Fixes scenarios where an input handlebars file containing literal segments would be reformatted to unwrap the literal segments, causing syntax errors in the resulting output.

<!-- prettier-ignore -->
```hbs
<!-- Input -->
{{input.[funky<api!response]}}
{{input.[this one has spaces]}}
{{input.[anotherone].[0]}}
<!-- Prettier stable -->
{{input.funky<api!response}}
{{input.this one has spaces}}
{{input.anotherone.0}}
<!-- Prettier main -->
{{input.[funky<api!response]}}
{{input.[this one has spaces]}}
{{input.anotherone.[0]}}
```
18 changes: 18 additions & 0 deletions changelog_unreleased/html/15748.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#### Fix formatting of prettier-ignored unclosed elements (#15748 by @fisker)

<!-- prettier-ignore -->
```html
<!-- Input -->
<!-- prettier-ignore -->
<h1>
Hello <span>world!

<!-- Prettier stable -->
<!-- prettier-ignore -->
<h1>

<!-- Prettier main -->
<!-- prettier-ignore -->
<h1>
Hello <span>world!
```
21 changes: 21 additions & 0 deletions changelog_unreleased/javascript/15209.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#### Avoid introducing linebreaks in template interpolations (#15209 by @bakkot)

In a template string like

<!-- prettier-ignore -->
```js
`this is a long message which contains an interpolation: ${format(data)} <- like this`;
```

avoid adding a linebreak when formatting the expression unless one is already present or it's unavoidable due to e.g. a nested function. Previously a linebreak could be introduced whenever some interpolation in the template was sufficiently "not simple":

<!-- prettier-ignore -->
```js
`this is a long message which contains an interpolation: ${format(
data,
)} <- like this`;
```

Now it will instead be left alone.

If a linebreak is already present within the `${...}`, format as normal.
22 changes: 22 additions & 0 deletions changelog_unreleased/javascript/15522.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#### Fix non-idempotent formatting of method chain with empty line (#15522 by @seiyab)

<!-- prettier-ignore -->
```js
// Input
Foo.a()

.b();

// Prettier stable (first format)
Foo.a()
.b();

// Prettier stable (second format)
Foo.a().b();


// Prettier main
Foo.a()

.b();
```
31 changes: 0 additions & 31 deletions changelog_unreleased/javascript/15662.md

This file was deleted.

19 changes: 19 additions & 0 deletions changelog_unreleased/javascript/15677.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#### Fix formatting of ternary in function call (#15677 by @fisker)

<!-- prettier-ignore -->
```jsx
// Input
stopDirectory = await (useCache
? memoizedFindProjectRoot
: findProjectRootWithoutCache)(path.dirname(path.resolve(filePath)));

// Prettier stable
stopDirectory = await (useCache
? memoizedFindProjectRoot
: findProjectRootWithoutCache)(path.dirname(path.resolve(filePath)));

// Prettier main
stopDirectory = await (
useCache ? memoizedFindProjectRoot : findProjectRootWithoutCache
)(path.dirname(path.resolve(filePath)));
```
16 changes: 0 additions & 16 deletions changelog_unreleased/javascript/15756.md

This file was deleted.

16 changes: 0 additions & 16 deletions changelog_unreleased/javascript/15757.md

This file was deleted.

51 changes: 51 additions & 0 deletions changelog_unreleased/javascript/15806.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#### Fix inconsistencies for optional-chaining (#15806 by @fisker)

Only happens when using `typescript`, `meriyah` or other ESTree parsers except `babel`.

<!-- prettier-ignore -->
```js
// Input
function someFunctionName() {
return isEqual(a.map(([t, _]) => t?.id), b.map(([t, _]) => t?.id));
return isEqual(a?.map(([t, _]) => t?.id), b?.map(([t, _]) => t?.id));
}
theValue = Object.entries(someLongObjectName).filter(
([listingId]) => someListToCompareToHere.includes(listingId),
);
theValue = Object.entries(someLongObjectName).filter(
([listingId]) => someListToCompareToHere?.includes(listingId),
);

// Prettier stable
function someFunctionName() {
return isEqual(
a.map(([t, _]) => t?.id),
b.map(([t, _]) => t?.id),
);
return isEqual(a?.map(([t, _]) => t?.id), b?.map(([t, _]) => t?.id));
}
theValue = Object.entries(someLongObjectName).filter(([listingId]) =>
someListToCompareToHere.includes(listingId),
);
theValue = Object.entries(someLongObjectName).filter(
([listingId]) => someListToCompareToHere?.includes(listingId),
);

// Prettier main
function someFunctionName() {
return isEqual(
a.map(([t, _]) => t?.id),
b.map(([t, _]) => t?.id),
);
return isEqual(
a?.map(([t, _]) => t?.id),
b?.map(([t, _]) => t?.id),
);
}
theValue = Object.entries(someLongObjectName).filter(([listingId]) =>
someListToCompareToHere.includes(listingId),
);
theValue = Object.entries(someLongObjectName).filter(([listingId]) =>
someListToCompareToHere?.includes(listingId),
);
```
27 changes: 27 additions & 0 deletions changelog_unreleased/javascript/15826.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#### Fix comments in `if` (#15826 by @fisker)

<!-- prettier-ignore -->
```js
// Input
if (foo) for (i = 2; i > 0; i--) console.log(i); // comment 1
else bar();

for (;;){
if (foo) continue; // comment 2
else bar();
}

// Prettier stable
Error: Comment "comment 2" was not printed. Please report this error!

// Prettier main
if (foo)
for (i = 2; i > 0; i--) console.log(i); // comment 1
else bar();

for (;;) {
if (foo)
continue; // comment 2
else bar();
}
```
9 changes: 9 additions & 0 deletions changelog_unreleased/json/15831.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#### [Highlight] New `jsonc` parser added (#15831 by @fisker)

Previously, we infer the parser of `.jsonc` files to be `json`, but if we want keep the trailing comma, we'll have to use a hacky workaround config `{parser: "json5", quoteProps: "preserve", singleQuote: false}`.

The new added `jsonc` parser:

- Always quote the object keys.
- Wrap strings with double quotes.
- Of course, respect the [`trailingComma`](https://prettier.io/docs/en/options#trailing-commas) option.
31 changes: 0 additions & 31 deletions changelog_unreleased/typescript/15708.md

This file was deleted.

7 changes: 0 additions & 7 deletions changelog_unreleased/typescript/15718.md

This file was deleted.

24 changes: 24 additions & 0 deletions changelog_unreleased/typescript/15811.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#### Improve conditional type alias layout (#15811 by @seiyab)

<!-- prettier-ignore -->
```ts
// Input
type FallbackFlags<F extends Flags | undefined> =
Equals<NonNullableFlag<F>["flags"], {}> extends true
? Dict<any>
: NonNullableFlag<F>["flags"];

// Prettier stable
type FallbackFlags<F extends Flags | undefined> = Equals<
NonNullableFlag<F>["flags"],
{}
> extends true
? Dict<any>
: NonNullableFlag<F>["flags"];

// Prettier main
type FallbackFlags<F extends Flags | undefined> =
Equals<NonNullableFlag<F>["flags"], {}> extends true
? Dict<any>
: NonNullableFlag<F>["flags"];
```
32 changes: 16 additions & 16 deletions docs/browser.md
Original file line number Diff line number Diff line change
@@ -18,7 +18,7 @@ Required options:

- **[`parser`](options.md#parser) (or [`filepath`](options.md#file-path))**: One of these options has to be specified for Prettier to know which parser to use.

- **`plugins`**: Unlike the `format` function from the [Node.js-based API](api.md#prettierformatsource--options), this function doesn’t load plugins automatically. The `plugins` option is required because all the parsers included in the Prettier package come as plugins (for reasons of file size). These plugins are files in <https://unpkg.com/browse/prettier@3.1.1/plugins/>. Note that `estree` plugin should be loaded when printing JavaScript, TypeScript, Flow, or JSON.
- **`plugins`**: Unlike the `format` function from the [Node.js-based API](api.md#prettierformatsource--options), this function doesn’t load plugins automatically. The `plugins` option is required because all the parsers included in the Prettier package come as plugins (for reasons of file size). These plugins are files in <https://unpkg.com/browse/prettier@3.2.0/plugins/>. Note that `estree` plugin should be loaded when printing JavaScript, TypeScript, Flow, or JSON.

You need to load the ones that you’re going to use and pass them to `prettier.format` using the `plugins` option.

@@ -29,8 +29,8 @@ See below for examples.
### Global

```html
<script src="https://unpkg.com/prettier@3.1.1/standalone.js"></script>
<script src="https://unpkg.com/prettier@3.1.1/plugins/graphql.js"></script>
<script src="https://unpkg.com/prettier@3.2.0/standalone.js"></script>
<script src="https://unpkg.com/prettier@3.2.0/plugins/graphql.js"></script>
<script>
(async () => {
const formatted = await prettier.format("type Query { hello: String }", {
@@ -47,8 +47,8 @@ Note that the [`unpkg` field](https://unpkg.com/#examples) in Prettier’s `pack

```html
<script type="module">
import * as prettier from "https://unpkg.com/prettier@3.1.1/standalone.mjs";
import prettierPluginGraphql from "https://unpkg.com/prettier@3.1.1/plugins/graphql.mjs";
import * as prettier from "https://unpkg.com/prettier@3.2.0/standalone.mjs";
import prettierPluginGraphql from "https://unpkg.com/prettier@3.2.0/plugins/graphql.mjs";
const formatted = await prettier.format("type Query { hello: String }", {
parser: "graphql",
@@ -61,8 +61,8 @@ Note that the [`unpkg` field](https://unpkg.com/#examples) in Prettier’s `pack

```js
define([
"https://unpkg.com/prettier@3.1.1/standalone.js",
"https://unpkg.com/prettier@3.1.1/plugins/graphql.js",
"https://unpkg.com/prettier@3.2.0/standalone.js",
"https://unpkg.com/prettier@3.2.0/plugins/graphql.js",
], async (prettier, ...plugins) => {
const formatted = await prettier.format("type Query { hello: String }", {
parser: "graphql",
@@ -90,8 +90,8 @@ This syntax doesn’t necessarily work in the browser, but it can be used when b
### Worker

```js
importScripts("https://unpkg.com/prettier@3.1.1/standalone.js");
importScripts("https://unpkg.com/prettier@3.1.1/plugins/graphql.js");
importScripts("https://unpkg.com/prettier@3.2.0/standalone.js");
importScripts("https://unpkg.com/prettier@3.2.0/plugins/graphql.js");

(async () => {
const formatted = await prettier.format("type Query { hello: String }", {
@@ -107,9 +107,9 @@ If you want to format [embedded code](options.md#embedded-language-formatting),

```html
<script type="module">
import * as prettier from "https://unpkg.com/prettier@3.1.1/standalone.mjs";
import prettierPluginBabel from "https://unpkg.com/prettier@3.1.1/plugins/babel.mjs";
import prettierPluginEstree from "https://unpkg.com/prettier@3.1.1/plugins/estree.mjs";
import * as prettier from "https://unpkg.com/prettier@3.2.0/standalone.mjs";
import prettierPluginBabel from "https://unpkg.com/prettier@3.2.0/plugins/babel.mjs";
import prettierPluginEstree from "https://unpkg.com/prettier@3.2.0/plugins/estree.mjs";
console.log(
await prettier.format("const html=/* HTML */ `<DIV> </DIV>`", {
@@ -125,10 +125,10 @@ The HTML code embedded in JavaScript stays unformatted because the `html` parser

```html
<script type="module">
import * as prettier from "https://unpkg.com/prettier@3.1.1/standalone.mjs";
import prettierPluginBabel from "https://unpkg.com/prettier@3.1.1/plugins/babel.mjs";
import prettierPluginEstree from "https://unpkg.com/prettier@3.1.1/plugins/estree.mjs";
import prettierPluginHtml from "https://unpkg.com/prettier@3.1.1/plugins/html.mjs";
import * as prettier from "https://unpkg.com/prettier@3.2.0/standalone.mjs";
import prettierPluginBabel from "https://unpkg.com/prettier@3.2.0/plugins/babel.mjs";
import prettierPluginEstree from "https://unpkg.com/prettier@3.2.0/plugins/estree.mjs";
import prettierPluginHtml from "https://unpkg.com/prettier@3.2.0/plugins/html.mjs";
console.log(
await prettier.format("const html=/* HTML */ `<DIV> </DIV>`", {
2 changes: 1 addition & 1 deletion docs/install.md
Original file line number Diff line number Diff line change
@@ -167,7 +167,7 @@ See [Pre-commit Hook](precommit.md) for more information.
To summarize, we have learned to:

- Install an exact version of Prettier locally in your project. This makes sure that everyone in the project gets the exact same version of Prettier. Even a patch release of Prettier can result in slightly different formatting, so you wouldn’t want different team members using different versions and formatting each other’s changes back and forth.
- Add a `.prettierrc.json` to let your editor know that you are using Prettier.
- Add a `.prettierrc` to let your editor know that you are using Prettier.
- Add a `.prettierignore` to let your editor know which files _not_ to touch, as well as for being able to run `prettier --write .` to format the entire project (without mangling files you don’t want, or choking on generated files).
- Run `prettier --check .` in CI to make sure that your project stays formatted.
- Run Prettier from your editor for the best experience.
3 changes: 1 addition & 2 deletions docs/options.md
Original file line number Diff line number Diff line change
@@ -115,8 +115,6 @@ Note that Prettier never unquotes numeric property names in Angular expressions,
[quote-props-flow]: https://flow.org/try/#0PQKgBAAgZgNg9gdzCYAoVBjOA7AzgFzAA8wBeMAb1TDAAYAuMARlQF8g
[quote-props-vue]: https://github.com/prettier/prettier/issues/10127

If this option is set to `preserve`, `singleQuote` to `false` (default value), and `parser` to `json5`, double quotes are always used for strings. This effectively allows using the `json5` parser for “JSON with comments and trailing commas”.

## JSX Quotes

Use single quotes instead of double quotes in JSX.
@@ -282,6 +280,7 @@ Valid options:
- `"less"` (via [postcss-less](https://github.com/shellscape/postcss-less)) _First available in v1.7.1_
- `"json"` (via [@babel/parser parseExpression](https://babeljs.io/docs/en/next/babel-parser.html#babelparserparseexpressioncode-options)) _First available in v1.5.0_
- `"json5"` (same parser as `"json"`, but outputs as [json5](https://json5.org/)) _First available in v1.13.0_
- `"jsonc"` (same parser as `"json"`, but outputs as "JSON with Comments") _First available in v3.2.0_
- `"json-stringify"` (same parser as `"json"`, but outputs like `JSON.stringify`) _First available in v1.13.0_
- `"graphql"` (via [graphql/language](https://github.com/graphql/graphql-js/tree/master/src/language)) _First available in v1.5.0_
- `"markdown"` (via [remark-parse](https://github.com/wooorm/remark/tree/main/packages/remark-parse)) _First available in v1.8.0_
23 changes: 19 additions & 4 deletions docs/rationale.md
Original file line number Diff line number Diff line change
@@ -87,7 +87,7 @@ const user = {

Just like with objects, decorators are used for a lot of different things. Sometimes it makes sense to write decorators _above_ the line they're decorating, sometimes it’s nicer if they're on the _same_ line. We haven’t been able to find a good rule for this, so Prettier keeps your decorator positioned like you wrote them (if they fit on the line). This isn’t ideal, but a pragmatic solution to a difficult problem.

```js
```ts
@Component({
selector: "hero-button",
template: `<button>{{ label }}</button>`,
@@ -108,14 +108,14 @@ class HeroButtonComponent {
There’s one exception: classes. We don’t think it ever makes sense to inline the decorators for them, so they are always moved to their own line.

<!-- prettier-ignore -->
```js
```ts
// Before running Prettier:
@observer class OrderLine {
@observable price: number = 0;
}
```

```js
```ts
// After running Prettier:
@observer
class OrderLine {
@@ -125,7 +125,7 @@ class OrderLine {

Note: Prettier 1.14.x and older tried to automatically move your decorators, so if you've run an older Prettier version on your code you might need to manually join up some decorators here and there to avoid inconsistencies:

```js
```ts
@observer
class OrderLine {
@observable price: number = 0;
@@ -143,6 +143,21 @@ One final thing: TC39 has [not yet decided if decorators come before or after `e
export @decorator class Foo {}
```

### Template literals

Template literals can contain interpolations. Deciding whether it's appropriate to insert a linebreak within an interpolation unfortunately depends on the semantic content of the template - for example, introducing a linebreak in the middle of a natural-language sentence is usually undesirable. Since Prettier doesn't have enough information to make this decision itself, it uses a heuristic similar to that used for objects: it will only split an interpolation expression across multiple lines if there was already a linebreak within that interpolation.

This means that a literal like the following will not be broken onto multiple lines, even if it exceeds the print width:

<!-- prettier-ignore -->
```js
`this is a long message which contains an interpolation: ${format(data)} <- like this`;
```

If you want Prettier to split up an interpolation, you'll need to ensure there's a linebreak somewhere within the `${...}`. Otherwise it will keep everything on a single line, no matter how long it is.

The team would prefer not to depend on the original formatting in this way, but it's the best heuristic we have at the moment.

### Semicolons

This is about using the [noSemi](options.md#semicolons) option.
455 changes: 455 additions & 0 deletions eslint.config.js

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import path from "node:path";

import createEsmUtils from "esm-utils";

import installPrettier from "./tests/config/install-prettier.js";

const { dirname: PROJECT_ROOT } = createEsmUtils(import.meta);
70 changes: 37 additions & 33 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "prettier",
"version": "3.1.1",
"version": "3.2.0",
"description": "Prettier is an opinionated code formatter",
"bin": "./bin/prettier.cjs",
"repository": "prettier/prettier",
@@ -32,18 +32,18 @@
"dependencies": {
"@angular/compiler": "17.0.2",
"@babel/code-frame": "7.23.5",
"@babel/parser": "7.23.5",
"@babel/types": "7.23.5",
"@glimmer/syntax": "0.85.13",
"@babel/parser": "7.23.6",
"@babel/types": "7.23.6",
"@glimmer/syntax": "0.87.1",
"@iarna/toml": "2.2.5",
"@prettier/is-es5-identifier-name": "0.2.0",
"@prettier/parse-srcset": "3.1.0",
"@typescript-eslint/typescript-estree": "6.13.2",
"@typescript-eslint/visitor-keys": "6.13.2",
"acorn": "8.11.2",
"@typescript-eslint/typescript-estree": "6.17.0",
"@typescript-eslint/visitor-keys": "6.17.0",
"acorn": "8.11.3",
"acorn-jsx": "5.3.2",
"angular-estree-parser": "9.0.0",
"angular-html-parser": "5.0.2",
"angular-html-parser": "5.2.0",
"camelcase": "8.0.0",
"chalk": "5.3.0",
"ci-info": "4.0.0",
@@ -60,11 +60,11 @@
"fast-json-stable-stringify": "2.1.0",
"file-entry-cache": "7.0.2",
"find-cache-dir": "5.0.0",
"flow-parser": "0.223.3",
"flow-parser": "0.225.1",
"get-east-asian-width": "1.2.0",
"get-stdin": "9.0.0",
"graphql": "16.8.1",
"hermes-parser": "0.18.0",
"hermes-parser": "0.18.2",
"html-element-attributes": "3.3.0",
"html-tag-names": "2.1.0",
"html-ua-styles": "0.0.3",
@@ -77,15 +77,14 @@
"leven": "4.0.0",
"lines-and-columns": "2.0.4",
"linguist-languages": "7.27.0",
"mem": "9.0.2",
"meriyah": "4.3.9",
"micromatch": "4.0.5",
"minimist": "1.2.8",
"n-readlines": "1.0.1",
"outdent": "0.8.0",
"parse-json": "8.1.0",
"please-upgrade-node": "3.2.0",
"postcss": "8.4.32",
"postcss": "8.4.33",
"postcss-less": "6.0.0",
"postcss-media-query-parser": "0.2.3",
"postcss-scss": "4.0.9",
@@ -98,42 +97,47 @@
"sdbm": "2.0.0",
"strip-ansi": "7.1.0",
"to-fast-properties": "4.0.0",
"typescript": "5.3.2",
"typescript": "5.3.3",
"unicode-regex": "4.0.0",
"unified": "9.2.2",
"url-or-path": "2.3.0",
"vnopts": "2.0.0",
"wcwidth": "1.0.1",
"wcwidth.js": "1.1.2",
"yaml-unist-parser": "2.0.1"
},
"devDependencies": {
"@babel/generator": "7.23.5",
"@glimmer/reference": "0.85.13",
"@babel/generator": "7.23.6",
"@eslint/eslintrc": "3.0.0",
"@eslint/js": "8.56.0",
"@glimmer/reference": "0.87.1",
"@stylistic/eslint-plugin-js": "1.5.3",
"@types/eslint__js": "8.42.3",
"@types/estree": "1.0.5",
"@types/file-entry-cache": "5.0.4",
"@types/find-cache-dir": "3.2.1",
"@types/jest": "29.5.8",
"@typescript-eslint/eslint-plugin": "6.13.2",
"@typescript-eslint/eslint-plugin": "6.17.0",
"benchmark": "2.1.4",
"browserslist-to-esbuild": "1.2.0",
"c8": "8.0.1",
"browserslist": "4.22.2",
"browserslist-to-esbuild": "2.1.0",
"c8": "9.0.0",
"cross-env": "7.0.3",
"cspell": "8.0.0",
"cspell": "8.3.2",
"enquirer": "2.4.1",
"esbuild": "0.19.5",
"esbuild": "0.19.11",
"esbuild-plugins-node-modules-polyfill": "1.6.1",
"esbuild-visualizer": "0.4.1",
"eslint": "8.53.0",
"esbuild-visualizer": "0.6.0",
"eslint": "8.56.0",
"eslint-config-prettier": "9.1.0",
"eslint-formatter-friendly": "7.0.0",
"eslint-plugin-compat": "4.2.0",
"eslint-plugin-import": "2.29.0",
"eslint-plugin-jest": "27.6.0",
"eslint-plugin-n": "16.3.1",
"eslint-plugin-prettier-internal-rules": "2.0.1",
"eslint-plugin-import": "2.29.1",
"eslint-plugin-jest": "27.6.1",
"eslint-plugin-n": "16.6.1",
"eslint-plugin-react": "7.33.2",
"eslint-plugin-regexp": "2.1.1",
"eslint-plugin-unicorn": "49.0.0",
"eslint-plugin-regexp": "2.1.2",
"eslint-plugin-simple-import-sort": "10.0.0",
"eslint-plugin-unicorn": "50.0.1",
"esm-utils": "4.2.1",
"execa": "7.2.0",
"jest": "30.0.0-alpha.2",
@@ -143,11 +147,11 @@
"jest-watch-typeahead": "2.2.2",
"magic-string": "0.30.5",
"npm-run-all2": "6.1.1",
"prettier": "3.1.0",
"prettier": "3.1.1",
"pretty-bytes": "6.1.1",
"rollup-plugin-license": "3.2.0",
"semver": "7.5.4",
"serialize-javascript": "6.0.1",
"serialize-javascript": "6.0.2",
"snapshot-diff": "0.10.0",
"tempy": "3.1.0",
"ts-expect": "1.3.0"
@@ -161,7 +165,7 @@
"test:dev-package": "cross-env INSTALL_PACKAGE=1 yarn test",
"test:dist": "cross-env NODE_ENV=production yarn test",
"test:dist-standalone": "cross-env TEST_STANDALONE=1 yarn test:dist",
"test:dist-lint": "eslint --no-eslintrc --no-ignore --no-inline-config --config=./scripts/bundle-eslint-config.cjs \"dist/**/*.{js,cjs,mjs}\"",
"test:dist-lint": "eslint --no-ignore --no-inline-config --config=./scripts/bundle-eslint-config.js dist",
"perf": "yarn && yarn build && cross-env NODE_ENV=production node ./dist/bin/prettier.cjs",
"perf:inspect": "yarn && yarn build && cross-env NODE_ENV=production node --inspect-brk ./dist/bin/prettier.cjs",
"perf:benchmark": "yarn perf --debug-benchmark",
@@ -208,5 +212,5 @@
"not op_mini all"
],
"preferUnplugged": true,
"packageManager": "yarn@3.7.0"
"packageManager": "yarn@4.0.2"
}
12 changes: 7 additions & 5 deletions scripts/build-website.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
#!/usr/bin/env node

import path from "node:path";
import fs from "node:fs/promises";
import path from "node:path";
import url from "node:url";
import fastGlob from "fast-glob";

import createEsmUtils from "esm-utils";
import { execa } from "execa";
import fastGlob from "fast-glob";

import { format } from "../src/index.js";
import {
PROJECT_ROOT,
copyFile,
DIST_DIR,
PROJECT_ROOT,
WEBSITE_DIR,
writeJson,
copyFile,
writeFile,
writeJson,
} from "./utils/index.js";

const { require } = createEsmUtils(import.meta);
22 changes: 12 additions & 10 deletions scripts/build/build-javascript-module.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
import path from "node:path";
import { createRequire } from "node:module";
import createEsmUtils from "esm-utils";
import path from "node:path";

import browserslistToEsbuild from "browserslist-to-esbuild";
import esbuild from "esbuild";
import { nodeModulesPolyfillPlugin as esbuildPluginNodeModulePolyfills } from "esbuild-plugins-node-modules-polyfill";
import browserslistToEsbuild from "browserslist-to-esbuild";
import { PROJECT_ROOT, DIST_DIR } from "../utils/index.js";
import createEsmUtils from "esm-utils";

import { DIST_DIR, PROJECT_ROOT } from "../utils/index.js";
import esbuildPluginAddDefaultExport from "./esbuild-plugins/add-default-export.js";
import esbuildPluginEvaluate from "./esbuild-plugins/evaluate.js";
import esbuildPluginReplaceModule from "./esbuild-plugins/replace-module.js";
import esbuildPluginLicense from "./esbuild-plugins/license.js";
import esbuildPluginUmd from "./esbuild-plugins/umd.js";
import esbuildPluginVisualizer from "./esbuild-plugins/visualizer.js";
import esbuildPluginPrimitiveDefine from "./esbuild-plugins/primitive-define.js";
import esbuildPluginReplaceModule from "./esbuild-plugins/replace-module.js";
import esbuildPluginShimCommonjsObjects from "./esbuild-plugins/shim-commonjs-objects.js";
import esbuildPluginStripNodeProtocol from "./esbuild-plugins/strip-node-protocol.js";
import esbuildPluginThrowWarnings from "./esbuild-plugins/throw-warnings.js";
import esbuildPluginShimCommonjsObjects from "./esbuild-plugins/shim-commonjs-objects.js";
import esbuildPluginPrimitiveDefine from "./esbuild-plugins/primitive-define.js";
import esbuildPluginAddDefaultExport from "./esbuild-plugins/add-default-export.js";
import esbuildPluginUmd from "./esbuild-plugins/umd.js";
import esbuildPluginVisualizer from "./esbuild-plugins/visualizer.js";
import transform from "./transform/index.js";
import { getPackageFile } from "./utils.js";

4 changes: 3 additions & 1 deletion scripts/build/build-license.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import path from "node:path";
import fs from "node:fs/promises";
import path from "node:path";

import { outdent } from "outdent";

import { DIST_DIR, PROJECT_ROOT } from "../utils/index.js";

const PROJECT_LICENSE_FILE = path.join(PROJECT_ROOT, "LICENSE");
3 changes: 2 additions & 1 deletion scripts/build/build-package-json.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import path from "node:path";
import { PROJECT_ROOT, DIST_DIR, readJson, writeJson } from "../utils/index.js";

import { DIST_DIR, PROJECT_ROOT, readJson, writeJson } from "../utils/index.js";

const keysToKeep = [
"name",
4 changes: 3 additions & 1 deletion scripts/build/build-types.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import fs from "node:fs";
import path from "node:path";
import url from "node:url";

import { isValidIdentifier } from "@babel/types";
import { outdent } from "outdent";
import { PROJECT_ROOT, DIST_DIR, writeFile } from "../utils/index.js";

import { DIST_DIR, PROJECT_ROOT, writeFile } from "../utils/index.js";

async function typesFileBuilder({ file }) {
/**
6 changes: 4 additions & 2 deletions scripts/build/build.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
#!/usr/bin/env node

import path from "node:path";
import fs from "node:fs/promises";
import path from "node:path";
import readline from "node:readline";

import chalk from "chalk";
import prettyBytes from "pretty-bytes";
import createEsmUtils from "esm-utils";
import prettyBytes from "pretty-bytes";

import { DIST_DIR } from "../utils/index.js";
import files from "./config.js";
import parseArguments from "./parse-arguments.js";
22 changes: 18 additions & 4 deletions scripts/build/config.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import fs from "node:fs";
import path from "node:path";
import url from "node:url";
import fs from "node:fs";

import createEsmUtils from "esm-utils";
import { PROJECT_ROOT, DIST_DIR, copyFile } from "../utils/index.js";

import { copyFile, DIST_DIR, PROJECT_ROOT } from "../utils/index.js";
import buildJavascriptModule from "./build-javascript-module.js";
import buildPackageJson from "./build-package-json.js";
import buildLicense from "./build-license.js";
import buildPackageJson from "./build-package-json.js";
import buildTypes from "./build-types.js";
import modifyTypescriptModule from "./modify-typescript-module.js";
import { getPackageFile } from "./utils.js";
@@ -208,6 +210,12 @@ const pluginFiles = [
),
text: "exports.typescriptVersionIsAtLeast = new Proxy({}, {get: () => true})",
},
{
module: getPackageFile(
"@typescript-eslint/typescript-estree/dist/jsx/xhtml-entities.js",
),
text: "exports.xhtmlEntities = {};",
},
{
module: getPackageFile(
"@typescript-eslint/typescript-estree/dist/create-program/createProjectService.js",
@@ -601,7 +609,8 @@ const nodejsFiles = [
},
{
module: getPackageFile("js-yaml/dist/js-yaml.mjs"),
path: getPackageFile("js-yaml/lib/loader.js"),
find: "var dump = dumper.dump;",
replacement: "var dump;",
},
// `parse-json` use another copy of `@babel/code-frame`
{
@@ -610,6 +619,11 @@ const nodejsFiles = [
}),
path: require.resolve("@babel/code-frame"),
},
{
module: getPackageFile("json5/dist/index.mjs"),
find: "export default lib;",
replacement: "export default { parse };",
},
],
addDefaultExport: true,
},
2 changes: 1 addition & 1 deletion scripts/build/esbuild-plugins/evaluate.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { isValidIdentifier } from "@babel/types";
import createEsmUtils from "esm-utils";
import serialize from "serialize-javascript";
import { isValidIdentifier } from "@babel/types";

const { importModule } = createEsmUtils(import.meta);

1 change: 1 addition & 0 deletions scripts/build/esbuild-plugins/shim-commonjs-objects.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import fs from "node:fs";

import { outdent } from "outdent";

export default function esbuildPluginShimCommonjsObjects() {
1 change: 1 addition & 0 deletions scripts/build/esbuild-plugins/umd.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import fs from "node:fs";

import camelCase from "camelcase";
import { outdent } from "outdent";

1 change: 1 addition & 0 deletions scripts/build/esbuild-plugins/visualizer.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import fs from "node:fs/promises";

import { visualizer as esbuildVisualizer } from "esbuild-visualizer/dist/plugin/index.js";

export default function esbuildPluginVisualizer({ formats }) {
6 changes: 4 additions & 2 deletions scripts/build/modify-typescript-module.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import path from "node:path";

import escapeStringRegexp from "escape-string-regexp";
import { outdent } from "outdent";
import MagicString from "magic-string";
import { writeFile, PROJECT_ROOT } from "../utils/index.js";
import { outdent } from "outdent";

import { PROJECT_ROOT, writeFile } from "../utils/index.js";

function* getModules(text) {
const parts = text.split(/(?<=\n)( {2}\/\/ src\/\S+\n)/);
3 changes: 2 additions & 1 deletion scripts/build/parse-arguments.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { parseArgs } from "node:util";
import path from "node:path";
import { parseArgs } from "node:util";

import { DIST_DIR } from "../utils/index.js";

function parseArguments() {
18 changes: 18 additions & 0 deletions scripts/build/shims/array-find-last.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
const arrayFindLast = (isOptionalObject, array, callback) => {
if (isOptionalObject && (array === undefined || array === null)) {
return;
}

if (array.findLast) {
return array.findLast(callback);
}

for (let index = array.length - 1; index >= 0; index--) {
const element = array[index];
if (callback(element, index, array)) {
return element;
}
}
};

export default arrayFindLast;
6 changes: 4 additions & 2 deletions scripts/build/transform/index.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import path from "node:path";

import babelGenerator from "@babel/generator";
import { parse } from "@babel/parser";
import { traverseFast as traverse } from "@babel/types";
import babelGenerator from "@babel/generator";
import { outdent } from "outdent";
import { SOURCE_DIR, PROJECT_ROOT } from "../../utils/index.js";

import { PROJECT_ROOT, SOURCE_DIR } from "../../utils/index.js";
import allTransforms from "./transforms/index.js";

const generate = babelGenerator.default;
2 changes: 2 additions & 0 deletions scripts/build/transform/transforms/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import transformArrayFindLast from "./transform-array-find-last.js";
import transformObjectHasOwnCall from "./transform-object-has-own.js";
import transformRelativeIndexing from "./transform-relative-indexing.js";
import transformStringReplaceAll from "./transform-string-replace-all.js";
@@ -6,4 +7,5 @@ export default [
transformObjectHasOwnCall,
transformRelativeIndexing,
transformStringReplaceAll,
transformArrayFindLast,
];
13 changes: 13 additions & 0 deletions scripts/build/transform/transforms/transform-array-find-last.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import createMethodCallTransform from "./create-method-call-transform.js";

const transformArrayFindLast = createMethodCallTransform({
methodName: "findLast",
argumentsLength: 1,
functionName: "__arrayFindLast",
functionImplementationUrl: new URL(
"../../shims/array-find-last.js",
import.meta.url,
),
});

export default transformArrayFindLast;
3 changes: 2 additions & 1 deletion scripts/build/utils.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import path from "node:path";
import fs from "node:fs";
import path from "node:path";

import { PROJECT_ROOT } from "../utils/index.js";

function getPackageFile(file) {
117 changes: 0 additions & 117 deletions scripts/bundle-eslint-config.cjs

This file was deleted.

114 changes: 114 additions & 0 deletions scripts/bundle-eslint-config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import fs from "node:fs/promises";
import url from "node:url";

import { FlatCompat } from "@eslint/eslintrc";
import eslintPluginCompat from "eslint-plugin-compat";

const { browserslist: targets } = JSON.parse(
await fs.readFile(new URL("../package.json", import.meta.url)),
);

const toPath = (file) => url.fileURLToPath(new URL(file, import.meta.url));
const compat = new FlatCompat({ baseDirectory: toPath("./") });

/* TODO[@fisker]: Fix `no-restricted-syntax` */

export default [
{
plugins: {
compat: eslintPluginCompat,
},
settings: {
targets,
lintAllEsApis: true,
polyfills: [
// These are not really polyfilled, but seems safe to use in target browsers
"BigInt",
"Symbol.asyncIterator",
],
},
rules: {
"no-restricted-syntax": [
"error",
// Forbid `require()` .mjs file
{
selector:
'CallExpression[callee.name="require"][arguments.0.value=/^\\..*?\\.mjs$/]',
message: ".mjs file can't be `require()`d",
},
],
},
},

{
files: [
"doc.js",
"doc.mjs",
"standalone.js",
"standalone.mjs",
"plugins/*",
],
...compat.env({ browser: true }),
rules: {
"compat/compat": "error",
// "no-restricted-syntax": [
// "error",
// // Forbid `require()`
// {
// selector: 'CallExpression[callee.name="require"]',
// message:
// "Universal bundles should not include any `require()` call.",
// },
// {
// selector: "ImportDeclaration",
// message:
// "Universal bundles should not include any `import` declaration.",
// },
// {
// selector:
// ":matches(ExportAllDeclaration, ExportDefaultDeclaration, ExportNamedDeclaration)[source]",
// message: "Universal bundles should not `export` from other files.",
// },
// {
// selector: "ImportExpression",
// message: "Universal bundles should not include any `import()`.",
// },
// ],
},
},
{
files: ["index.cjs", "index.mjs", "bin/*", "internal/*"],
rules: {
// "no-restricted-syntax": [
// "error",
// // Forbid top level `require()` parsers
// {
// selector:
// 'CallExpression:not(:function *)[callee.name="require"][arguments.0.value=/plugins/]',
// message: "Parsers should be inline `require()`d.",
// },
// // Forbid top level `import()` parsers
// {
// selector:
// "ImportExpression:not(:function *)[source.value=/plugins/]",
// message: "Parsers should be inline `import()`ed.",
// },
// // Forbid `import`/`export` parsers
// {
// selector:
// ":matches(ImportDeclaration, ExportAllDeclaration, ExportDefaultDeclaration, ExportNamedDeclaration)[source.value=/plugins/]",
// message: "Parsers should be inline `import()`ed.",
// },
// ],
},
},
{
files: ["bin/prettier.cjs"],
languageOptions: {
ecmaVersion: 5,
},
rules: {
"compat/compat": "error",
},
},
];
2 changes: 2 additions & 0 deletions scripts/changelog-for-patch.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
#!/usr/bin/env node

import path from "node:path";

import minimist from "minimist";
import semver from "semver";

import {
changelogUnreleasedDirPath,
changelogUnreleasedDirs,
1 change: 1 addition & 0 deletions scripts/check-deps.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import fs from "node:fs/promises";

import chalk from "chalk";

const packageJson = JSON.parse(
17 changes: 0 additions & 17 deletions scripts/clean-changelog-unreleased.js

This file was deleted.

1 change: 1 addition & 0 deletions scripts/clean-cspell.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#!/usr/bin/env node

import fs from "node:fs/promises";

import { execa } from "execa";

const CSPELL_CONFIG_FILE = new URL("../cspell.json", import.meta.url);
6 changes: 4 additions & 2 deletions scripts/draft-blog-post.js
Original file line number Diff line number Diff line change
@@ -2,15 +2,17 @@

import fs from "node:fs";
import path from "node:path";

import createEsmUtils from "esm-utils";
import fg from "fast-glob";
import semver from "semver";

import {
getEntries,
replaceVersions,
changelogUnreleasedDirPath,
changelogUnreleasedDirs,
getEntries,
printEntries,
replaceVersions,
} from "./utils/changelog.js";

const { __dirname, require } = createEsmUtils(import.meta);
4 changes: 3 additions & 1 deletion scripts/generate-changelog.js
Original file line number Diff line number Diff line change
@@ -11,8 +11,10 @@

import fs from "node:fs/promises";
import path from "node:path";
import createEsmUtils from "esm-utils";

import enquirer from "enquirer";
import createEsmUtils from "esm-utils";

import { CHANGELOG_CATEGORIES } from "./utils/changelog-categories.js";

const { __dirname } = createEsmUtils(import.meta);
6 changes: 4 additions & 2 deletions scripts/lint-changelog.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
#!/usr/bin/env node

import path from "node:path";
import fs from "node:fs";
import { outdent } from "outdent";
import path from "node:path";

import createEsmUtils from "esm-utils";
import { LinesAndColumns } from "lines-and-columns";
import { outdent } from "outdent";

import { CHANGELOG_CATEGORIES } from "./utils/changelog-categories.js";

const { __dirname } = createEsmUtils(import.meta);
9 changes: 6 additions & 3 deletions scripts/release/README.md
Original file line number Diff line number Diff line change
@@ -10,9 +10,12 @@ The script has its own `package.json` so we can reinstall the root's `node_modul

## Flags

- `--manual` Manual run release process instead of publish from GitHub actions
- `--dry` Dry run
- `--skip-dependencies-install` Skip dependencies installation
| Flag | Description |
| ----------------------------- | --------------------------------------------------------------------------------------- |
| `--manual` | Manual run release process instead of publish from GitHub actions |
| `--dry` | Dry run |
| `--skip-dependencies-install` | Skip dependencies installation |
| `--next` | Pre-release such as alpha and beta. It must be run on the `next` branch or it will fail |

## Credits

3 changes: 2 additions & 1 deletion scripts/release/package.json
Original file line number Diff line number Diff line change
@@ -8,11 +8,12 @@
"chalk": "5.3.0",
"enquirer": "2.4.1",
"execa": "8.0.1",
"fast-glob": "3.3.2",
"outdent": "0.8.0",
"semver": "7.5.4"
},
"engines": {
"node": ">=18"
},
"packageManager": "yarn@3.7.0"
"packageManager": "yarn@4.0.2"
}
5 changes: 5 additions & 0 deletions scripts/release/parse-arguments.js
Original file line number Diff line number Diff line change
@@ -8,6 +8,7 @@ function parseArguments() {
manual = false,
dry = false,
"skip-dependencies-install": skipDependenciesInstall = false,
next = false,
},
} = parseArgs({
options: {
@@ -26,6 +27,9 @@ function parseArguments() {
"skip-dependencies-install": {
type: "boolean",
},
next: {
type: "boolean",
},
},
});

@@ -35,6 +39,7 @@ function parseArguments() {
manual,
dry,
skipDependenciesInstall,
next,
};
}

2 changes: 1 addition & 1 deletion scripts/release/release.js
Original file line number Diff line number Diff line change
@@ -2,8 +2,8 @@

/* This file can't use any dependency since the dependencies may not installed yet */
import { exec } from "node:child_process";
import { fileURLToPath } from "node:url";
import path from "node:path";
import { fileURLToPath } from "node:url";

const directory = path.dirname(fileURLToPath(import.meta.url));
function runCommand(command) {
8 changes: 7 additions & 1 deletion scripts/release/run.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import semver from "semver";
import { runGit, readJson, logPromise } from "./utils.js";

import parseArguments from "./parse-arguments.js";
import * as steps from "./steps/index.js";
import { logPromise, readJson, runGit } from "./utils.js";

const params = parseArguments();
const { stdout: previousVersion } = await runGit([
@@ -54,6 +55,11 @@ for (let step of [
steps.showInstructionsAfterNpmPublish,
steps.updateDependentsCount,
steps.bumpPrettier,
{
name: "Cleaning changelog",
process: steps.cleanChangelog,
skip: params.dry || params.next,
},
steps.postPublishSteps,
]) {
if (typeof step === "function") {
8 changes: 5 additions & 3 deletions scripts/release/steps/bump-prettier.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import fs from "node:fs";

import semver from "semver";
import { runYarn, runGit, logPromise, readJson, writeJson } from "../utils.js";

import { logPromise, readJson, runGit, runYarn, writeJson } from "../utils.js";

async function format() {
await runYarn(["lint:eslint", "--fix"]);
@@ -37,9 +39,9 @@ async function bump({
}

export default async function bumpPrettier(params) {
const { dry, version } = params;
const { dry, version, next } = params;

if (dry) {
if (dry || next) {
return;
}

11 changes: 10 additions & 1 deletion scripts/release/steps/check-git-status.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { runGit } from "../utils.js";

export default async function checkGitStatus() {
export default async function checkGitStatus({ next }) {
const { stdout: status } = await runGit(["status", "--porcelain"]);

if (status) {
@@ -9,4 +9,13 @@ export default async function checkGitStatus() {
"Please revert or commit all local changes before making a release.",
);
}

if (next) {
const { stdout: branch } = await runGit(["branch", "--show-current"]);
if (branch !== "next") {
throw new Error(
`Expected to be on "next" branch, but currently on "${branch}"`,
);
}
}
}
22 changes: 22 additions & 0 deletions scripts/release/steps/clean-changelog.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import fs from "node:fs/promises";
import { fileURLToPath } from "node:url";

import fastGlob from "fast-glob";

import { runGit } from "../utils.js";

export default async function cleanChangelog({ repo }) {
const changelogUnreleasedDir = fileURLToPath(
new URL("../changelog_unreleased", import.meta.url),
);

const files = await fastGlob(["blog-post-intro.md", "*/*.md"], {
cwd: changelogUnreleasedDir,
absolute: true,
});

await Promise.all(files.map((file) => fs.unlink(file)));

await runGit(["commit", "-am", "Clean changelog_unreleased"]);
await runGit(["push", "--repo", repo]);
}
3 changes: 2 additions & 1 deletion scripts/release/steps/generate-bundles.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import chalk from "chalk";
import { runYarn, logPromise, readJson } from "../utils.js";

import { logPromise, readJson, runYarn } from "../utils.js";

export default async function generateBundles({ dry, version, manual }) {
if (!manual) {
17 changes: 9 additions & 8 deletions scripts/release/steps/index.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
export { default as validateNewVersion } from "./validate-new-version.js";
export { default as bumpPrettier } from "./bump-prettier.js";
export { default as checkGitStatus } from "./check-git-status.js";
export { default as cleanChangelog } from "./clean-changelog.js";
export { default as generateBundles } from "./generate-bundles.js";
export { default as installDependencies } from "./install-dependencies.js";
export { default as lintFiles } from "./lint-files.js";
export { default as updateVersion } from "./update-version.js";
export { default as generateBundles } from "./generate-bundles.js";
export { default as updateChangelog } from "./update-changelog.js";
export { default as pushToGit } from "./push-to-git.js";
export { default as postPublishSteps } from "./post-publish-steps.js";
export { default as publishToNpm } from "./publish-to-npm.js";
export { default as waitForBotRelease } from "./wait-for-bot-release.js";
export { default as pushToGit } from "./push-to-git.js";
export { default as showInstructionsAfterNpmPublish } from "./show-instructions-after-npm-publish.js";
export { default as updateChangelog } from "./update-changelog.js";
export { default as updateDependentsCount } from "./update-dependents-count.js";
export { default as bumpPrettier } from "./bump-prettier.js";
export { default as postPublishSteps } from "./post-publish-steps.js";
export { default as updateVersion } from "./update-version.js";
export { default as validateNewVersion } from "./validate-new-version.js";
export { default as waitForBotRelease } from "./wait-for-bot-release.js";
3 changes: 2 additions & 1 deletion scripts/release/steps/install-dependencies.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { execa } from "execa";
import { runYarn, runGit } from "../utils.js";

import { runGit, runYarn } from "../utils.js";

export default async function installDependencies() {
await execa("rm", ["-rf", "node_modules"]);
7 changes: 4 additions & 3 deletions scripts/release/steps/post-publish-steps.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import chalk from "chalk";
import outdent from "outdent";
import { execa } from "execa";
import outdent from "outdent";

import { fetchText, logPromise } from "../utils.js";

const SCHEMA_REPO = "SchemaStore/schemastore";
@@ -45,10 +46,10 @@ function twitterAnnouncement() {
`;
}

export default async function postPublishSteps({ dry }) {
export default async function postPublishSteps({ dry, next }) {
console.log(chalk.bold.green("The script has finished!\n"));

if (dry) {
if (dry || next) {
return;
}

3 changes: 2 additions & 1 deletion scripts/release/steps/publish-to-npm.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { execa } from "execa";
import enquirer from "enquirer";
import { execa } from "execa";

import { waitForEnter } from "../utils.js";

export default async function publishToNpm({ dry }) {
9 changes: 8 additions & 1 deletion scripts/release/steps/show-instructions-after-npm-publish.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import chalk from "chalk";
import outdent from "outdent";
import semver from "semver";

import {
getBlogPostInfo,
getChangelogContent,
@@ -36,9 +37,15 @@ export function getReleaseUrl(version, previousVersion) {
export default async function showInstructionsAfterNpmPublish({
version,
previousVersion,
next,
}) {
const releaseUrl = getReleaseUrl(version, previousVersion);
if (next) {
console.log(`${chalk.green.bold(`Prettier ${version} published!`)}`);
await waitForEnter();
return;
}

const releaseUrl = getReleaseUrl(version, previousVersion);
console.log(
outdent`
${chalk.green.bold(`Prettier ${version} published!`)}
13 changes: 8 additions & 5 deletions scripts/release/steps/update-changelog.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import fs from "node:fs";
import { execa } from "execa";

import chalk from "chalk";
import { execa } from "execa";
import semver from "semver";

import {
waitForEnter,
runYarn,
logPromise,
getBlogPostInfo,
getChangelogContent,
logPromise,
runYarn,
waitForEnter,
} from "../utils.js";

function writeChangelog(params) {
@@ -31,8 +33,9 @@ export default async function updateChangelog({
dry,
version,
previousVersion,
next,
}) {
if (dry) {
if (dry || next) {
return;
}

7 changes: 4 additions & 3 deletions scripts/release/steps/update-dependents-count.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import chalk from "chalk";
import { runGit, fetchText, logPromise, processFile } from "../utils.js";

import { fetchText, logPromise, processFile, runGit } from "../utils.js";

async function update() {
const npmPage = await logPromise(
@@ -71,8 +72,8 @@ function formatNumber(value) {
return Math.floor(value / 1e5) / 10 + " million";
}

export default async function updateDependentsCount({ dry }) {
if (dry) {
export default async function updateDependentsCount({ dry, next }) {
if (dry || next) {
return;
}

9 changes: 7 additions & 2 deletions scripts/release/steps/update-version.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
import { runYarn, readJson, writeJson, processFile } from "../utils.js";
import { processFile, readJson, runYarn, writeJson } from "../utils.js";

export default async function updateVersion({ version }) {
export default async function updateVersion({ version, next }) {
const pkg = await readJson("package.json");
pkg.version = version;
await writeJson("package.json", pkg);

// For pre-release, just update package.json
if (next) {
return;
}

// Update github issue templates
processFile(".github/ISSUE_TEMPLATE/formatting.md", (content) =>
content.replace(/^(\*\*Prettier ).*?(\*\*)$/m, `$1${version}$2`),
10 changes: 9 additions & 1 deletion scripts/release/steps/validate-new-version.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import chalk from "chalk";
import semver from "semver";

export default function validateNewVersion({ version, previousVersion }) {
export default function validateNewVersion({ version, previousVersion, next }) {
if (!version) {
throw new Error("'--version' is required");
}
@@ -17,4 +17,12 @@ export default function validateNewVersion({ version, previousVersion }) {
`Version '${chalk.yellow.underline(version)}' has already been published`,
);
}

if (next && semver.prerelease(version) === null) {
throw new Error(
`Version '${chalk.yellow.underline(
version,
)}' is not a prerelease version`,
);
}
}
11 changes: 6 additions & 5 deletions scripts/release/steps/wait-for-bot-release.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import chalk from "chalk";
import outdent from "outdent";
import { waitForEnter, logPromise } from "../utils.js";

import { logPromise, waitForEnter } from "../utils.js";

export async function isVersionReleased(version) {
const response = await fetch("https://registry.npmjs.org/prettier/");
@@ -26,7 +27,7 @@ const sleep = () =>
setTimeout(resolve, 30_000);
});

export default async function waitForBotRelease({ dry, version }) {
export default async function waitForBotRelease({ dry, version, next }) {
if (dry) {
return;
}
@@ -68,9 +69,9 @@ export default async function waitForBotRelease({ dry, version }) {
"Run workflow",
)}" button, type "${chalk.yellow.underline(
version,
)}" in "Version to release", uncheck all checkboxes, hit the "${chalk.bgGreen(
"Run workflow",
)}" button.
)}" in "Version to release", ${
next ? 'check only "Unstable version"' : "uncheck all checkboxes"
}, hit the "${chalk.bgGreen("Run workflow")}" button.
`,
);

3 changes: 2 additions & 1 deletion scripts/release/tests/publish-to-npm.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import assert from "node:assert/strict";
import { URLSearchParams } from "node:url";
import { describe, it } from "node:test";
import { URLSearchParams } from "node:url";

import { getReleaseUrl } from "../steps/show-instructions-after-npm-publish.js";

const RELEASE_URL_BASE = "https://github.com/prettier/prettier/releases/new?";
2 changes: 2 additions & 0 deletions scripts/release/tests/validate-new-version.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import assert from "node:assert/strict";
import { describe, it } from "node:test";

import chalk from "chalk";

import validateNewVersion from "../steps/validate-new-version.js";

describe("validate-new-version", () => {
1 change: 1 addition & 0 deletions scripts/release/tests/version-check.test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import assert from "node:assert/strict";
import { describe, it } from "node:test";

import { isVersionReleased } from "../steps/wait-for-bot-release.js";

describe("isVersionReleased", () => {
12 changes: 7 additions & 5 deletions scripts/release/utils.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import fs from "node:fs";
import readline from "node:readline";

import chalk from "chalk";
import { execa } from "execa";
import outdent from "outdent";

import getFormattedDate from "./get-formatted-date.js";

readline.emitKeypressEvents(process.stdin);
@@ -128,14 +130,14 @@ function getChangelogContent({ version, previousVersion, body }) {
}

export {
runYarn,
runGit,
fetchText,
getBlogPostInfo,
getChangelogContent,
logPromise,
processFile,
readJson,
writeJson,
runGit,
runYarn,
waitForEnter,
getBlogPostInfo,
getChangelogContent,
writeJson,
};
242 changes: 199 additions & 43 deletions scripts/release/yarn.lock
Original file line number Diff line number Diff line change
@@ -2,13 +2,40 @@
# Manual changes might be lost - proceed with caution!

__metadata:
version: 6
cacheKey: 8
version: 8
cacheKey: 10

"@nodelib/fs.scandir@npm:2.1.5":
version: 2.1.5
resolution: "@nodelib/fs.scandir@npm:2.1.5"
dependencies:
"@nodelib/fs.stat": "npm:2.0.5"
run-parallel: "npm:^1.1.9"
checksum: 6ab2a9b8a1d67b067922c36f259e3b3dfd6b97b219c540877a4944549a4d49ea5ceba5663905ab5289682f1f3c15ff441d02f0447f620a42e1cb5e1937174d4b
languageName: node
linkType: hard

"@nodelib/fs.stat@npm:2.0.5, @nodelib/fs.stat@npm:^2.0.2":
version: 2.0.5
resolution: "@nodelib/fs.stat@npm:2.0.5"
checksum: 012480b5ca9d97bff9261571dbbec7bbc6033f69cc92908bc1ecfad0792361a5a1994bc48674b9ef76419d056a03efadfce5a6cf6dbc0a36559571a7a483f6f0
languageName: node
linkType: hard

"@nodelib/fs.walk@npm:^1.2.3":
version: 1.2.8
resolution: "@nodelib/fs.walk@npm:1.2.8"
dependencies:
"@nodelib/fs.scandir": "npm:2.1.5"
fastq: "npm:^1.6.0"
checksum: 40033e33e96e97d77fba5a238e4bba4487b8284678906a9f616b5579ddaf868a18874c0054a75402c9fbaaa033a25ceae093af58c9c30278e35c23c9479e79b0
languageName: node
linkType: hard

"ansi-colors@npm:^4.1.1":
version: 4.1.3
resolution: "ansi-colors@npm:4.1.3"
checksum: a9c2ec842038a1fabc7db9ece7d3177e2fe1c5dc6f0c51ecfbf5f39911427b89c00b5dc6b8bd95f82a26e9b16aaae2e83d45f060e98070ce4d1333038edceb0e
checksum: 43d6e2fc7b1c6e4dc373de708ee76311ec2e0433e7e8bd3194e7ff123ea6a747428fc61afdcf5969da5be3a5f0fd054602bec56fc0ebe249ce2fcde6e649e3c2
languageName: node
linkType: hard

@@ -19,62 +46,134 @@ __metadata:
languageName: node
linkType: hard

"braces@npm:^3.0.2":
version: 3.0.2
resolution: "braces@npm:3.0.2"
dependencies:
fill-range: "npm:^7.0.1"
checksum: 966b1fb48d193b9d155f810e5efd1790962f2c4e0829f8440b8ad236ba009222c501f70185ef732fef17a4c490bb33a03b90dab0631feafbdf447da91e8165b1
languageName: node
linkType: hard

"chalk@npm:5.3.0":
version: 5.3.0
resolution: "chalk@npm:5.3.0"
checksum: 623922e077b7d1e9dedaea6f8b9e9352921f8ae3afe739132e0e00c275971bdd331268183b2628cf4ab1727c45ea1f28d7e24ac23ce1db1eb653c414ca8a5a80
checksum: 6373caaab21bd64c405bfc4bd9672b145647fc9482657b5ea1d549b3b2765054e9d3d928870cdf764fb4aad67555f5061538ff247b8310f110c5c888d92397ea
languageName: node
linkType: hard

"cross-spawn@npm:^7.0.3":
version: 7.0.3
resolution: "cross-spawn@npm:7.0.3"
dependencies:
path-key: ^3.1.0
shebang-command: ^2.0.0
which: ^2.0.1
checksum: 671cc7c7288c3a8406f3c69a3ae2fc85555c04169e9d611def9a675635472614f1c0ed0ef80955d5b6d4e724f6ced67f0ad1bb006c2ea643488fcfef994d7f52
path-key: "npm:^3.1.0"
shebang-command: "npm:^2.0.0"
which: "npm:^2.0.1"
checksum: e1a13869d2f57d974de0d9ef7acbf69dc6937db20b918525a01dacb5032129bd552d290d886d981e99f1b624cb03657084cc87bd40f115c07ecf376821c729ce
languageName: node
linkType: hard

"enquirer@npm:2.4.1":
version: 2.4.1
resolution: "enquirer@npm:2.4.1"
dependencies:
ansi-colors: ^4.1.1
strip-ansi: ^6.0.1
checksum: f080f11a74209647dbf347a7c6a83c8a47ae1ebf1e75073a808bc1088eb780aa54075bfecd1bcdb3e3c724520edb8e6ee05da031529436b421b71066fcc48cb5
ansi-colors: "npm:^4.1.1"
strip-ansi: "npm:^6.0.1"
checksum: b3726486cd98f0d458a851a03326a2a5dd4d84f37ff94ff2a2960c915e0fc865865da3b78f0877dc36ac5c1189069eca603e82ec63d5bc6b0dd9985bf6426d7a
languageName: node
linkType: hard

"execa@npm:8.0.1":
version: 8.0.1
resolution: "execa@npm:8.0.1"
dependencies:
cross-spawn: ^7.0.3
get-stream: ^8.0.1
human-signals: ^5.0.0
is-stream: ^3.0.0
merge-stream: ^2.0.0
npm-run-path: ^5.1.0
onetime: ^6.0.0
signal-exit: ^4.1.0
strip-final-newline: ^3.0.0
checksum: cac1bf86589d1d9b73bdc5dda65c52012d1a9619c44c526891956745f7b366ca2603d29fe3f7460bacc2b48c6eab5d6a4f7afe0534b31473d3708d1265545e1f
cross-spawn: "npm:^7.0.3"
get-stream: "npm:^8.0.1"
human-signals: "npm:^5.0.0"
is-stream: "npm:^3.0.0"
merge-stream: "npm:^2.0.0"
npm-run-path: "npm:^5.1.0"
onetime: "npm:^6.0.0"
signal-exit: "npm:^4.1.0"
strip-final-newline: "npm:^3.0.0"
checksum: d2ab5fe1e2bb92b9788864d0713f1fce9a07c4594e272c0c97bc18c90569897ab262e4ea58d27a694d288227a2e24f16f5e2575b44224ad9983b799dc7f1098d
languageName: node
linkType: hard

"fast-glob@npm:3.3.2":
version: 3.3.2
resolution: "fast-glob@npm:3.3.2"
dependencies:
"@nodelib/fs.stat": "npm:^2.0.2"
"@nodelib/fs.walk": "npm:^1.2.3"
glob-parent: "npm:^5.1.2"
merge2: "npm:^1.3.0"
micromatch: "npm:^4.0.4"
checksum: 222512e9315a0efca1276af9adb2127f02105d7288fa746145bf45e2716383fb79eb983c89601a72a399a56b7c18d38ce70457c5466218c5f13fad957cee16df
languageName: node
linkType: hard

"fastq@npm:^1.6.0":
version: 1.16.0
resolution: "fastq@npm:1.16.0"
dependencies:
reusify: "npm:^1.0.4"
checksum: de151543aab9d91900ed5da88860c46987ece925c628df586fac664235f25e020ec20729e1c032edb5fd2520fd4aa5b537d69e39b689e65e82112cfbecb4479e
languageName: node
linkType: hard

"fill-range@npm:^7.0.1":
version: 7.0.1
resolution: "fill-range@npm:7.0.1"
dependencies:
to-regex-range: "npm:^5.0.1"
checksum: e260f7592fd196b4421504d3597cc76f4a1ca7a9488260d533b611fc3cefd61e9a9be1417cb82d3b01ad9f9c0ff2dbf258e1026d2445e26b0cf5148ff4250429
languageName: node
linkType: hard

"get-stream@npm:^8.0.1":
version: 8.0.1
resolution: "get-stream@npm:8.0.1"
checksum: 01e3d3cf29e1393f05f44d2f00445c5f9ec3d1c49e8179b31795484b9c117f4c695e5e07b88b50785d5c8248a788c85d9913a79266fc77e3ef11f78f10f1b974
checksum: dde5511e2e65a48e9af80fea64aff11b4921b14b6e874c6f8294c50975095af08f41bfb0b680c887f28b566dd6ec2cb2f960f9d36a323359be324ce98b766e9e
languageName: node
linkType: hard

"glob-parent@npm:^5.1.2":
version: 5.1.2
resolution: "glob-parent@npm:5.1.2"
dependencies:
is-glob: "npm:^4.0.1"
checksum: 32cd106ce8c0d83731966d31517adb766d02c3812de49c30cfe0675c7c0ae6630c11214c54a5ae67aca882cf738d27fd7768f21aa19118b9245950554be07247
languageName: node
linkType: hard

"human-signals@npm:^5.0.0":
version: 5.0.0
resolution: "human-signals@npm:5.0.0"
checksum: 6504560d5ed91444f16bea3bd9dfc66110a339442084e56c3e7fa7bbdf3f406426d6563d662bdce67064b165eac31eeabfc0857ed170aaa612cf14ec9f9a464c
checksum: 30f8870d831cdcd2d6ec0486a7d35d49384996742052cee792854273fa9dd9e7d5db06bb7985d4953e337e10714e994e0302e90dc6848069171b05ec836d65b0
languageName: node
linkType: hard

"is-extglob@npm:^2.1.1":
version: 2.1.1
resolution: "is-extglob@npm:2.1.1"
checksum: df033653d06d0eb567461e58a7a8c9f940bd8c22274b94bf7671ab36df5719791aae15eef6d83bbb5e23283967f2f984b8914559d4449efda578c775c4be6f85
languageName: node
linkType: hard

"is-glob@npm:^4.0.1":
version: 4.0.3
resolution: "is-glob@npm:4.0.3"
dependencies:
is-extglob: "npm:^2.1.1"
checksum: 3ed74f2b0cdf4f401f38edb0442ddfde3092d79d7d35c9919c86641efdbcbb32e45aa3c0f70ce5eecc946896cd5a0f26e4188b9f2b881876f7cb6c505b82da11
languageName: node
linkType: hard

"is-number@npm:^7.0.0":
version: 7.0.0
resolution: "is-number@npm:7.0.0"
checksum: 6a6c3383f68afa1e05b286af866017c78f1226d43ac8cb064e115ff9ed85eb33f5c4f7216c96a71e4dfea289ef52c5da3aef5bbfade8ffe47a0465d70c0c8e86
languageName: node
linkType: hard

@@ -88,16 +187,16 @@ __metadata:
"isexe@npm:^2.0.0":
version: 2.0.0
resolution: "isexe@npm:2.0.0"
checksum: 26bf6c5480dda5161c820c5b5c751ae1e766c587b1f951ea3fcfc973bafb7831ae5b54a31a69bd670220e42e99ec154475025a468eae58ea262f813fdc8d1c62
checksum: 7c9f715c03aff08f35e98b1fadae1b9267b38f0615d501824f9743f3aab99ef10e303ce7db3f186763a0b70a19de5791ebfc854ff884d5a8c4d92211f642ec92
languageName: node
linkType: hard

"lru-cache@npm:^6.0.0":
version: 6.0.0
resolution: "lru-cache@npm:6.0.0"
dependencies:
yallist: ^4.0.0
checksum: f97f499f898f23e4585742138a22f22526254fdba6d75d41a1c2526b3b6cc5747ef59c5612ba7375f42aca4f8461950e925ba08c991ead0651b4918b7c978297
yallist: "npm:^4.0.0"
checksum: fc1fe2ee205f7c8855fa0f34c1ab0bcf14b6229e35579ec1fd1079f31d6fc8ef8eb6fd17f2f4d99788d7e339f50e047555551ebd5e434dda503696e7c6591825
languageName: node
linkType: hard

@@ -108,6 +207,23 @@ __metadata:
languageName: node
linkType: hard

"merge2@npm:^1.3.0":
version: 1.4.1
resolution: "merge2@npm:1.4.1"
checksum: 7268db63ed5169466540b6fb947aec313200bcf6d40c5ab722c22e242f651994619bcd85601602972d3c85bd2cc45a358a4c61937e9f11a061919a1da569b0c2
languageName: node
linkType: hard

"micromatch@npm:^4.0.4":
version: 4.0.5
resolution: "micromatch@npm:4.0.5"
dependencies:
braces: "npm:^3.0.2"
picomatch: "npm:^2.3.1"
checksum: a749888789fc15cac0e03273844dbd749f9f8e8d64e70c564bcf06a033129554c789bb9e30d7566d7ff6596611a08e58ac12cf2a05f6e3c9c47c50c4c7e12fa2
languageName: node
linkType: hard

"mimic-fn@npm:^4.0.0":
version: 4.0.0
resolution: "mimic-fn@npm:4.0.0"
@@ -119,7 +235,7 @@ __metadata:
version: 5.1.0
resolution: "npm-run-path@npm:5.1.0"
dependencies:
path-key: ^4.0.0
path-key: "npm:^4.0.0"
checksum: dc184eb5ec239d6a2b990b43236845332ef12f4e0beaa9701de724aa797fe40b6bbd0157fb7639d24d3ab13f5d5cf22d223a19c6300846b8126f335f788bee66
languageName: node
linkType: hard
@@ -128,15 +244,15 @@ __metadata:
version: 6.0.0
resolution: "onetime@npm:6.0.0"
dependencies:
mimic-fn: ^4.0.0
mimic-fn: "npm:^4.0.0"
checksum: 0846ce78e440841335d4e9182ef69d5762e9f38aa7499b19f42ea1c4cd40f0b4446094c455c713f9adac3f4ae86f613bb5e30c99e52652764d06a89f709b3788
languageName: node
linkType: hard

"outdent@npm:0.8.0":
version: 0.8.0
resolution: "outdent@npm:0.8.0"
checksum: 72b7c1a287674317ea477999ec24e73a9eda21de35eb9429218f4a5bab899e964afaee7508265898118fee5cbee1d79397916b66dd8aeee285cd948ea5b1f562
checksum: a556c5c308705ad4e3441be435f2b2cf014cb5f9753a24cbd080eadc473b988c77d0d529a6a9a57c3931fb4178e5a81d668cc4bc49892b668191a5d0ba3df76e
languageName: node
linkType: hard

@@ -154,34 +270,65 @@ __metadata:
languageName: node
linkType: hard

"picomatch@npm:^2.3.1":
version: 2.3.1
resolution: "picomatch@npm:2.3.1"
checksum: 60c2595003b05e4535394d1da94850f5372c9427ca4413b71210f437f7b2ca091dbd611c45e8b37d10036fa8eade25c1b8951654f9d3973bfa66a2ff4d3b08bc
languageName: node
linkType: hard

"queue-microtask@npm:^1.2.2":
version: 1.2.3
resolution: "queue-microtask@npm:1.2.3"
checksum: 72900df0616e473e824202113c3df6abae59150dfb73ed13273503127235320e9c8ca4aaaaccfd58cf417c6ca92a6e68ee9a5c3182886ae949a768639b388a7b
languageName: node
linkType: hard

"reusify@npm:^1.0.4":
version: 1.0.4
resolution: "reusify@npm:1.0.4"
checksum: 14222c9e1d3f9ae01480c50d96057228a8524706db79cdeb5a2ce5bb7070dd9f409a6f84a02cbef8cdc80d39aef86f2dd03d155188a1300c599b05437dcd2ffb
languageName: node
linkType: hard

"root-workspace-0b6124@workspace:.":
version: 0.0.0-use.local
resolution: "root-workspace-0b6124@workspace:."
dependencies:
chalk: 5.3.0
enquirer: 2.4.1
execa: 8.0.1
outdent: 0.8.0
semver: 7.5.4
chalk: "npm:5.3.0"
enquirer: "npm:2.4.1"
execa: "npm:8.0.1"
fast-glob: "npm:3.3.2"
outdent: "npm:0.8.0"
semver: "npm:7.5.4"
languageName: unknown
linkType: soft

"run-parallel@npm:^1.1.9":
version: 1.2.0
resolution: "run-parallel@npm:1.2.0"
dependencies:
queue-microtask: "npm:^1.2.2"
checksum: cb4f97ad25a75ebc11a8ef4e33bb962f8af8516bb2001082ceabd8902e15b98f4b84b4f8a9b222e5d57fc3bd1379c483886ed4619367a7680dad65316993021d
languageName: node
linkType: hard

"semver@npm:7.5.4":
version: 7.5.4
resolution: "semver@npm:7.5.4"
dependencies:
lru-cache: ^6.0.0
lru-cache: "npm:^6.0.0"
bin:
semver: bin/semver.js
checksum: 12d8ad952fa353b0995bf180cdac205a4068b759a140e5d3c608317098b3575ac2f1e09182206bf2eb26120e1c0ed8fb92c48c592f6099680de56bb071423ca3
checksum: 985dec0d372370229a262c737063860fabd4a1c730662c1ea3200a2f649117761a42184c96df62a0e885e76fbd5dace41087d6c1ac0351b13c0df5d6bcb1b5ac
languageName: node
linkType: hard

"shebang-command@npm:^2.0.0":
version: 2.0.0
resolution: "shebang-command@npm:2.0.0"
dependencies:
shebang-regex: ^3.0.0
shebang-regex: "npm:^3.0.0"
checksum: 6b52fe87271c12968f6a054e60f6bde5f0f3d2db483a1e5c3e12d657c488a15474121a1d55cd958f6df026a54374ec38a4a963988c213b7570e1d51575cea7fa
languageName: node
linkType: hard
@@ -196,16 +343,16 @@ __metadata:
"signal-exit@npm:^4.1.0":
version: 4.1.0
resolution: "signal-exit@npm:4.1.0"
checksum: 64c757b498cb8629ffa5f75485340594d2f8189e9b08700e69199069c8e3070fb3e255f7ab873c05dc0b3cec412aea7402e10a5990cb6a050bd33ba062a6c549
checksum: c9fa63bbbd7431066174a48ba2dd9986dfd930c3a8b59de9c29d7b6854ec1c12a80d15310869ea5166d413b99f041bfa3dd80a7947bcd44ea8e6eb3ffeabfa1f
languageName: node
linkType: hard

"strip-ansi@npm:^6.0.1":
version: 6.0.1
resolution: "strip-ansi@npm:6.0.1"
dependencies:
ansi-regex: ^5.0.1
checksum: f3cd25890aef3ba6e1a74e20896c21a46f482e93df4a06567cebf2b57edabb15133f1f94e57434e0a958d61186087b1008e89c94875d019910a213181a14fc8c
ansi-regex: "npm:^5.0.1"
checksum: ae3b5436d34fadeb6096367626ce987057713c566e1e7768818797e00ac5d62023d0f198c4e681eae9e20701721980b26a64a8f5b91238869592a9c6800719a2
languageName: node
linkType: hard

@@ -216,20 +363,29 @@ __metadata:
languageName: node
linkType: hard

"to-regex-range@npm:^5.0.1":
version: 5.0.1
resolution: "to-regex-range@npm:5.0.1"
dependencies:
is-number: "npm:^7.0.0"
checksum: 10dda13571e1f5ad37546827e9b6d4252d2e0bc176c24a101252153ef435d83696e2557fe128c4678e4e78f5f01e83711c703eef9814eb12dab028580d45980a
languageName: node
linkType: hard

"which@npm:^2.0.1":
version: 2.0.2
resolution: "which@npm:2.0.2"
dependencies:
isexe: ^2.0.0
isexe: "npm:^2.0.0"
bin:
node-which: ./bin/node-which
checksum: 1a5c563d3c1b52d5f893c8b61afe11abc3bab4afac492e8da5bde69d550de701cf9806235f20a47b5c8fa8a1d6a9135841de2596535e998027a54589000e66d1
checksum: 4782f8a1d6b8fc12c65e968fea49f59752bf6302dc43036c3bf87da718a80710f61a062516e9764c70008b487929a73546125570acea95c5b5dcc8ac3052c70f
languageName: node
linkType: hard

"yallist@npm:^4.0.0":
version: 4.0.0
resolution: "yallist@npm:4.0.0"
checksum: 343617202af32df2a15a3be36a5a8c0c8545208f3d3dfbc6bb7c3e3b7e8c6f8e7485432e4f3b88da3031a6e20afa7c711eded32ddfb122896ac5d914e75848d5
checksum: 4cb02b42b8a93b5cf50caf5d8e9beb409400a8a4d85e83bb0685c1457e9ac0b7a00819e9f5991ac25ffabb56a78e2f017c1acc010b3a1babfe6de690ba531abd
languageName: node
linkType: hard
8 changes: 5 additions & 3 deletions scripts/tools/bundle-test/index.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import url from "node:url";
import path from "node:path";
import { createRequire } from "node:module";
import path from "node:path";
import url from "node:url";

import webpack from "webpack";
import { DIST_DIR } from "../../utils/index.js";

import files from "../../build/config.js";
import { DIST_DIR } from "../../utils/index.js";

function runWebpack(config) {
return new Promise((resolve, reject) => {
2 changes: 1 addition & 1 deletion scripts/tools/bundle-test/package.json
Original file line number Diff line number Diff line change
@@ -9,5 +9,5 @@
"scripts": {
"test": "node ./index.js"
},
"packageManager": "yarn@3.7.0"
"packageManager": "yarn@4.0.2"
}
360 changes: 180 additions & 180 deletions scripts/tools/bundle-test/yarn.lock

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -11,5 +11,5 @@
"test": "node test.js",
"test-coverage": "npx nyc node test.js"
},
"packageManager": "yarn@3.7.0"
"packageManager": "yarn@4.0.2"
}
Original file line number Diff line number Diff line change
@@ -164,9 +164,7 @@ module.exports = {
fixable: "code",
},
create(context) {
const { ignoreSingleType, onlyTopLevelFunctions } = {
ignoreSingleType: false,
onlyTopLevelFunctions: false,
const { ignoreSingleType = false, onlyTopLevelFunctions = false } = {
...context.options[0],
};
const sourceCode = context.getSourceCode();
Original file line number Diff line number Diff line change
@@ -2,7 +2,8 @@
# Manual changes might be lost - proceed with caution!

__metadata:
version: 6
version: 8
cacheKey: 10

"eslint-plugin-prettier-internal-rules@workspace:.":
version: 0.0.0-use.local
1 change: 1 addition & 0 deletions scripts/utils/changelog.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import fs from "node:fs";
import path from "node:path";

import createEsmUtils from "esm-utils";
import semver from "semver";

23 changes: 13 additions & 10 deletions scripts/utils/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import fs from "node:fs/promises";
import url from "node:url";
import path from "node:path";
import url from "node:url";

const toPath = (path) => (path instanceof URL ? url.fileURLToPath(path) : path);

@@ -15,17 +15,20 @@ function writeJson(file, content) {
}

async function copyFile(from, to) {
const data = await fs.readFile(from);
return writeFile(to, data);
await createDirectory(path.dirname(toPath(to)));
return fs.copyFile(from, to);
}

async function writeFile(file, content) {
const directory = path.dirname(toPath(file));
async function createDirectory(directory) {
try {
await fs.mkdir(directory, { recursive: true });
} catch {
// noop
}
}

async function writeFile(file, content) {
await createDirectory(path.dirname(toPath(file)));
return fs.writeFile(file, content);
}

@@ -35,12 +38,12 @@ const WEBSITE_DIR = path.join(PROJECT_ROOT, "website");
const SOURCE_DIR = path.join(PROJECT_ROOT, "src");

export {
PROJECT_ROOT,
copyFile,
DIST_DIR,
WEBSITE_DIR,
SOURCE_DIR,
PROJECT_ROOT,
readJson,
writeJson,
SOURCE_DIR,
WEBSITE_DIR,
writeFile,
copyFile,
writeJson,
};
1 change: 1 addition & 0 deletions src/cli/cli-options.evaluate.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { outdent } from "outdent";

import { optionCategories } from "./prettier-internal.js";

/**
1 change: 1 addition & 0 deletions src/cli/constants.evaluate.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { outdent } from "outdent";

import { optionCategories } from "./prettier-internal.js";

const categoryOrder = [
3 changes: 2 additions & 1 deletion src/cli/expand-patterns.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import path from "node:path";
import { lstatSafe, normalizeToPosix } from "./utils.js";

import { fastGlob } from "./prettier-internal.js";
import { lstatSafe, normalizeToPosix } from "./utils.js";

/** @typedef {import('./context').Context} Context */

1 change: 1 addition & 0 deletions src/cli/file-info.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import stringify from "fast-json-stable-stringify";

import { format, getFileInfo } from "../index.js";
import { printToScreen } from "./utils.js";

4 changes: 3 additions & 1 deletion src/cli/find-cache-file.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import fs from "node:fs/promises";
import os from "node:os";
import path from "node:path";

import findCacheDir from "find-cache-dir";
import { statSafe, isJson } from "./utils.js";

import { isJson, statSafe } from "./utils.js";

/**
* Find default cache file (`./node_modules/.cache/prettier/.prettier-cache`) using https://github.com/avajs/find-cache-dir
3 changes: 2 additions & 1 deletion src/cli/find-config-path.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import path from "node:path";

import { resolveConfigFile } from "../index.js";
import { printToScreen, normalizeToPosix } from "./utils.js";
import { normalizeToPosix, printToScreen } from "./utils.js";

async function logResolvedConfigPathOrDie(context) {
const file = context.argv.findConfigPath;
3 changes: 2 additions & 1 deletion src/cli/format-results-cache.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
// Inspired by LintResultsCache from ESLint
// https://github.com/eslint/eslint/blob/c2d0a830754b6099a3325e6d3348c3ba983a677a/lib/cli-engine/lint-result-cache.js

import fileEntryCache from "file-entry-cache";
import stringify from "fast-json-stable-stringify";
import fileEntryCache from "file-entry-cache";

import { version as prettierVersion } from "../index.js";
import { createHash } from "./utils.js";

16 changes: 9 additions & 7 deletions src/cli/format.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
import fs from "node:fs/promises";
import path from "node:path";

import chalk from "chalk";
import { createTwoFilesPatch } from "diff";

import * as prettier from "../index.js";
import { expandPatterns } from "./expand-patterns.js";
import findCacheFile from "./find-cache-file.js";
import FormatResultsCache from "./format-results-cache.js";
import isTTY from "./is-tty.js";
import getOptionsForFile from "./options/get-options-for-file.js";
import {
createIsIgnoredFunction,
errors,
mockable,
} from "./prettier-internal.js";
import { expandPatterns } from "./expand-patterns.js";
import getOptionsForFile from "./options/get-options-for-file.js";
import isTTY from "./is-tty.js";
import findCacheFile from "./find-cache-file.js";
import FormatResultsCache from "./format-results-cache.js";
import { statSafe, normalizeToPosix } from "./utils.js";
import { normalizeToPosix, statSafe } from "./utils.js";

const { getStdin, writeFormattedFile } = mockable;

@@ -506,4 +508,4 @@ async function formatFiles(context) {
}
}

export { formatStdin, formatFiles };
export { formatFiles, formatStdin };
10 changes: 5 additions & 5 deletions src/cli/index.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import * as prettier from "../index.js";
import createLogger from "./logger.js";
import Context from "./context.js";
import { parseArgvWithoutPlugins } from "./options/parse-cli-arguments.js";
import { createDetailedUsage, createUsage } from "./usage.js";
import { formatStdin, formatFiles } from "./format.js";
import logFileInfoOrDie from "./file-info.js";
import logResolvedConfigPathOrDie from "./find-config-path.js";
import { printToScreen } from "./utils.js";
import { formatFiles, formatStdin } from "./format.js";
import createLogger from "./logger.js";
import { parseArgvWithoutPlugins } from "./options/parse-cli-arguments.js";
import printSupportInfo from "./print-support-info.js";
import { createDetailedUsage, createUsage } from "./usage.js";
import { printToScreen } from "./utils.js";

async function run(rawArguments = process.argv.slice(2)) {
// Create a default level logger, so we can log errors during `logLevel` parsing
3 changes: 2 additions & 1 deletion src/cli/logger.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import readline from "node:readline";

import chalk, { chalkStderr } from "chalk";
import stripAnsi from "strip-ansi";
import wcwidth from "wcwidth";
import wcwidth from "wcwidth.js";

const countLines = (stream, text) => {
const columns = stream.columns || 80;
5 changes: 3 additions & 2 deletions src/cli/options/get-context-options.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import dashify from "dashify";

import { getSupportInfo } from "../../index.js";
import cliOptions from "../cli-options.evaluate.js";
import {
optionCategories,
getSupportInfoWithoutPlugins,
normalizeOptionSettings,
optionCategories,
} from "../prettier-internal.js";
import cliOptions from "../cli-options.evaluate.js";

const detailedCliOptions = normalizeOptionSettings(cliOptions).map((option) =>
normalizeDetailedOption(option),
3 changes: 2 additions & 1 deletion src/cli/options/get-options-for-file.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import dashify from "dashify";

import { resolveConfig } from "../../index.js";
import { normalizeOptions as normalizeApiOptions } from "../prettier-internal.js";
import minimist from "./minimist.js";
import createMinimistOptions from "./create-minimist-options.js";
import minimist from "./minimist.js";
import normalizeCliOptions from "./normalize-cli-options.js";

function getOptions(argv, detailedOptions) {
1 change: 1 addition & 0 deletions src/cli/options/normalize-cli-options.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import chalk from "chalk";
import leven from "leven";

import { normalizeOptions, vnopts } from "../prettier-internal.js";

const descriptor = {
3 changes: 2 additions & 1 deletion src/cli/options/parse-cli-arguments.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import camelCase from "camelcase";

import { pick } from "../utils.js";
import createMinimistOptions from "./create-minimist-options.js";
import { getContextOptionsWithoutPlugins } from "./get-context-options.js";
import minimist from "./minimist.js";
import createMinimistOptions from "./create-minimist-options.js";
import normalizeCliOptions from "./normalize-cli-options.js";

function parseArgv(rawArguments, detailedOptions, logger, keys) {
5 changes: 3 additions & 2 deletions src/cli/print-support-info.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import stringify from "fast-json-stable-stringify";
import { getSupportInfo, format } from "../index.js";
import { printToScreen, omit } from "./utils.js";

import { format, getSupportInfo } from "../index.js";
import { omit, printToScreen } from "./utils.js";

const sortByName = (array) =>
array.sort((a, b) => a.name.localeCompare(b.name));
5 changes: 3 additions & 2 deletions src/cli/usage.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import camelCase from "camelcase";

import { categoryOrder, usageSummary } from "./constants.evaluate.js";
import { groupBy } from "./utils.js";
import { formatOptionsHiddenDefaults } from "./prettier-internal.js";
import { groupBy } from "./utils.js";

const OPTION_USAGE_THRESHOLD = 25;
const CHOICE_USAGE_MARGIN = 3;
@@ -193,4 +194,4 @@ function createDetailedUsage(context, flag) {
return `${header}${description}${choices}${defaults}${pluginDefaults}`;
}

export { createUsage, createDetailedUsage };
export { createDetailedUsage, createUsage };
12 changes: 7 additions & 5 deletions src/cli/utils.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import fs from "node:fs/promises";
import path from "node:path";

import sdbm from "sdbm";

// @ts-expect-error
import { __internal as sharedWithCli } from "../index.js";

@@ -107,12 +109,12 @@ const normalizeToPosix =

export const { isNonEmptyArray, partition, omit } = sharedWithCli.utils;
export {
printToScreen,
groupBy,
pick,
createHash,
statSafe,
lstatSafe,
groupBy,
isJson,
lstatSafe,
normalizeToPosix,
pick,
printToScreen,
statSafe,
};
2 changes: 1 addition & 1 deletion src/common/end-of-line.js
Original file line number Diff line number Diff line change
@@ -44,8 +44,8 @@ function normalizeEndOfLine(text) {
}

export {
guessEndOfLine,
convertEndOfLineToChars,
countEndOfLineChars,
guessEndOfLine,
normalizeEndOfLine,
};
2 changes: 1 addition & 1 deletion src/common/errors.js
Original file line number Diff line number Diff line change
@@ -10,4 +10,4 @@ class ArgExpansionBailout extends Error {
name = "ArgExpansionBailout";
}

export { ConfigError, UndefinedParserError, ArgExpansionBailout };
export { ArgExpansionBailout, ConfigError, UndefinedParserError };
2 changes: 1 addition & 1 deletion src/common/get-file-info.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import inferParser from "../utils/infer-parser.js";
import { resolveConfig } from "../config/resolve-config.js";
import { isIgnored } from "../utils/ignore.js";
import inferParser from "../utils/infer-parser.js";

/**
* @typedef {{ ignorePath?: string | URL | (string | URL)[], withNodeModules?: boolean, plugins: object, resolveConfig?: boolean }} FileInfoOptions
4 changes: 2 additions & 2 deletions src/common/mockable.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import fs from "node:fs/promises";
import getStdin from "get-stdin";

import { isCI } from "ci-info";
import getStdin from "get-stdin";

function writeFormattedFile(file, data) {
return fs.writeFile(file, data);
}

const mockable = {
// eslint-disable-next-line unicorn/no-useless-undefined
getPrettierConfigSearchStopDirectory: () => undefined,
getStdin,
isCI: () => isCI,
File renamed without changes.
44 changes: 44 additions & 0 deletions src/config/editorconfig/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import path from "node:path";

import editorconfig from "editorconfig";

import {
clearFindProjectRootCache,
findProjectRoot,
} from "../find-project-root.js";
import editorConfigToPrettier from "./editorconfig-to-prettier.js";

const editorconfigCache = new Map();

function clearEditorconfigCache() {
clearFindProjectRootCache();
editorconfigCache.clear();
}

async function loadEditorconfigInternal(file, { shouldCache }) {
const directory = path.dirname(file);
const root = await findProjectRoot(directory, { shouldCache });
const editorConfig = await editorconfig.parse(file, { root });
const config = editorConfigToPrettier(editorConfig);
return config;
}

/**
* @param {string} file
* @param {{shouldCache?: boolean}} options
*/
function loadEditorconfig(file, { shouldCache }) {
file = path.resolve(file);

if (!shouldCache || !editorconfigCache.has(file)) {
// Even if `shouldCache` is false, we still cache the result, so we can use it when `shouldCache` is true
editorconfigCache.set(
file,
loadEditorconfigInternal(file, { shouldCache }),
);
}

return editorconfigCache.get(file);
}

export { clearEditorconfigCache, loadEditorconfig };
31 changes: 19 additions & 12 deletions src/config/find-project-root.js
Original file line number Diff line number Diff line change
@@ -1,27 +1,34 @@
// Simple version of `find-project-root`
// https://github.com/kirstein/find-project-root/blob/master/index.js

import path from "node:path";
import iterateDirectoryUp from "iterate-directory-up";
import * as path from "node:path";

import isDirectory from "../utils/is-directory.js";
import Searcher from "./searcher.js";

const MARKERS = [".git", ".hg"];
let searcher;
const searchOptions = {
names: MARKERS,
filter: ({ path: directory }) =>
isDirectory(directory, { allowSymlinks: false }),
};

/**
* Find the directory contains a version control system directory
* @param {string} startDirectory
* @param {{shouldCache?: boolean}} options
* @returns {Promise<string | undefined>}
*/
async function findProjectRoot(startDirectory) {
for (const directory of iterateDirectoryUp(startDirectory)) {
for (const name of MARKERS) {
const directoryPath = path.join(directory, name);
async function findProjectRoot(startDirectory, options) {
searcher ??= new Searcher(searchOptions);
const mark = await searcher.search(startDirectory, options);

return mark ? path.dirname(mark) : undefined;
}

if (await isDirectory(directoryPath, { allowSymlinks: false })) {
return directory;
}
}
}
function clearFindProjectRootCache() {
searcher?.clearCache();
}

export default findProjectRoot;
export { clearFindProjectRootCache, findProjectRoot };
119 changes: 0 additions & 119 deletions src/config/prettier-config-explorer/config-searcher.js

This file was deleted.

64 changes: 0 additions & 64 deletions src/config/prettier-config-explorer/index.js

This file was deleted.

41 changes: 41 additions & 0 deletions src/config/prettier-config/config-searcher.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import isFile from "../../utils/is-file.js";
import Searcher from "../searcher.js";
import { loadConfigFromPackageJson } from "./loaders.js";

const CONFIG_FILE_NAMES = [
"package.json",
".prettierrc",
".prettierrc.json",
".prettierrc.yaml",
".prettierrc.yml",
".prettierrc.json5",
".prettierrc.js",
".prettierrc.mjs",
".prettierrc.cjs",
"prettier.config.js",
"prettier.config.mjs",
"prettier.config.cjs",
".prettierrc.toml",
];

async function filter({ name, path: file }) {
if (!(await isFile(file))) {
return false;
}

if (name === "package.json") {
try {
return Boolean(await loadConfigFromPackageJson(file));
} catch {
return false;
}
}

return true;
}

function getSearcher(stopDirectory) {
return new Searcher({ names: CONFIG_FILE_NAMES, filter, stopDirectory });
}

export default getSearcher;
62 changes: 62 additions & 0 deletions src/config/prettier-config/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import path from "node:path";

import mockable from "../../common/mockable.js";
import getConfigSearcher from "./config-searcher.js";
import loadConfig from "./load-config.js";

const loadCache = new Map();
const searchCache = new Map();
function clearPrettierConfigCache() {
loadCache.clear();
searchCache.clear();
}

/**
* @param {string} configFile
* @param {{shouldCache?: boolean}} param1
* @returns {Promise<ReturnType<loadConfig>>}
*/
function loadPrettierConfig(configFile, { shouldCache }) {
configFile = path.resolve(configFile);

if (!shouldCache || !loadCache.has(configFile)) {
// Even if `shouldCache` is false, we still cache the result, so we can use it when `shouldCache` is true
loadCache.set(configFile, loadConfig(configFile));
}

return loadCache.get(configFile);
}

/**
* @param {string} stopDirectory
*/
function getSearchFunction(stopDirectory) {
stopDirectory = stopDirectory ? path.resolve(stopDirectory) : undefined;

if (!searchCache.has(stopDirectory)) {
const searcher = getConfigSearcher(stopDirectory);
const searchFunction = searcher.search.bind(searcher);
searchCache.set(stopDirectory, searchFunction);
}

return searchCache.get(stopDirectory);
}

/**
* @param {string} startDirectory
* @param {{shouldCache?: boolean}} options
* @returns {Promise<string>}
*/
function searchPrettierConfig(startDirectory, options = {}) {
startDirectory = startDirectory
? path.resolve(startDirectory)
: process.cwd();

const stopDirectory = mockable.getPrettierConfigSearchStopDirectory();

const search = getSearchFunction(stopDirectory);

return search(startDirectory, { shouldCache: options.shouldCache });
}

export { clearPrettierConfigCache, loadPrettierConfig, searchPrettierConfig };
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import path from "node:path";

import loadExternalConfig from "./load-external-config.js";
import loaders, { loadConfigFromPackageJson } from "./loaders.js";

Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import requireFromFile from "../../utils/require-from-file.js";
import importFromFile from "../../utils/import-from-file.js";
import requireFromFile from "../../utils/require-from-file.js";

const requireErrorCodesShouldBeIgnored = new Set([
"MODULE_NOT_FOUND",
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { pathToFileURL } from "node:url";

import parseToml from "@iarna/toml/parse-async.js";
import parseJson5 from "json5/lib/parse.js";
import jsYaml from "js-yaml";
import { load as parseYaml } from "js-yaml";
import json5 from "json5";
import parseJson from "parse-json";

import readFile from "../../utils/read-file.js";

async function readJson(file) {
@@ -28,7 +30,7 @@ async function loadConfigFromPackageJson(file) {
async function loadYaml(file) {
const content = await readFile(file);
try {
return jsYaml.load(content);
return parseYaml(content);
} catch (/** @type {any} */ error) {
error.message = `YAML Error in ${file}:\n${error.message}`;
throw error;
@@ -48,7 +50,7 @@ const loaders = {
async ".json5"(file) {
const content = await readFile(file);
try {
return parseJson5(content);
return json5.parse(content);
} catch (/** @type {any} */ error) {
error.message = `JSON5 Error in ${file}:\n${error.message}`;
throw error;
@@ -65,4 +67,4 @@ const loaders = {
};

export default loaders;
export { readJson, loadConfigFromPackageJson };
export { loadConfigFromPackageJson, readJson };
38 changes: 19 additions & 19 deletions src/config/resolve-config.js
Original file line number Diff line number Diff line change
@@ -1,39 +1,39 @@
import path from "node:path";

import micromatch from "micromatch";
import mem, { memClear } from "mem";
import { toPath } from "url-or-path";

import partition from "../utils/partition.js";
import {
searchConfig as searchPrettierConfig,
loadConfig as loadPrettierConfigFile,
clearCache as clearPrettierConfigCache,
} from "./prettier-config-explorer/index.js";
import loadEditorConfigWithoutCache from "./resolve-editorconfig.js";
clearEditorconfigCache,
loadEditorconfig as loadEditorconfigForFile,
} from "./editorconfig/index.js";
import {
clearPrettierConfigCache,
loadPrettierConfig as loadPrettierConfigFile,
searchPrettierConfig,
} from "./prettier-config/index.js";

const memoizedLoadEditorConfig = mem(loadEditorConfigWithoutCache);
function clearCache() {
clearPrettierConfigCache();
memClear(memoizedLoadEditorConfig);
clearEditorconfigCache();
}

function loadEditorConfig(filePath, options) {
if (!filePath || !options.editorconfig) {
function loadEditorconfig(file, options) {
if (!file || !options.editorconfig) {
return;
}

return (
options.useCache ? memoizedLoadEditorConfig : loadEditorConfigWithoutCache
)(filePath);
const shouldCache = options.useCache;
return loadEditorconfigForFile(file, { shouldCache });
}

async function loadPrettierConfig(filePath, options) {
async function loadPrettierConfig(file, options) {
const shouldCache = options.useCache;
let configFile = options.config;

if (!configFile) {
const directory = filePath
? path.dirname(path.resolve(filePath))
: undefined;
const directory = file ? path.dirname(path.resolve(file)) : undefined;
configFile = await searchPrettierConfig(directory, { shouldCache });
}

@@ -52,7 +52,7 @@ async function resolveConfig(fileUrlOrPath, options) {

const [result, editorConfigured] = await Promise.all([
loadPrettierConfig(filePath, options),
loadEditorConfig(filePath, options),
loadEditorconfig(filePath, options),
]);

if (!result && !editorConfigured) {
@@ -127,4 +127,4 @@ function pathMatchesGlobs(filePath, patterns, excludedPatterns) {
);
}

export { resolveConfig, resolveConfigFile, clearCache };
export { clearCache, resolveConfig, resolveConfigFile };
16 changes: 0 additions & 16 deletions src/config/resolve-editorconfig.js

This file was deleted.

72 changes: 72 additions & 0 deletions src/config/searcher.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import path from "node:path";

import iterateDirectoryUp from "iterate-directory-up";

class Searcher {
#names;
#filter;
#stopDirectory;
#cache = new Map();

/**
* @param {{
* names: string[],
* filter: (fileOrDirectory: {name: string, path: string}) => Promise<boolean>,
* stopDirectory?: string,
* }} param0
*/
constructor({ names, filter, stopDirectory }) {
this.#names = names;
this.#filter = filter;
this.#stopDirectory = stopDirectory;
}

async #searchInDirectory(directory, shouldCache) {
const cache = this.#cache;
if (shouldCache && cache.has(directory)) {
return cache.get(directory);
}

for (const name of this.#names) {
const fileOrDirectory = path.join(directory, name);

if (await this.#filter({ name, path: fileOrDirectory })) {
return fileOrDirectory;
}
}
}

async search(startDirectory, { shouldCache }) {
const cache = this.#cache;
if (shouldCache && cache.has(startDirectory)) {
return cache.get(startDirectory);
}

const searchedDirectories = [];
let result;
for (const directory of iterateDirectoryUp(
startDirectory,
this.#stopDirectory,
)) {
searchedDirectories.push(directory);
result = await this.#searchInDirectory(directory, shouldCache);

if (result) {
break;
}
}

// Always cache the result, so we can use it when `useCache` is set to true
for (const directory of searchedDirectories) {
cache.set(directory, result);
}

return result;
}

clearCache() {
this.#cache.clear();
}
}

export default Searcher;
50 changes: 25 additions & 25 deletions src/document/builders.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import {
DOC_TYPE_CURSOR,
DOC_TYPE_INDENT,
DOC_TYPE_ALIGN,
DOC_TYPE_TRIM,
DOC_TYPE_GROUP,
DOC_TYPE_BREAK_PARENT,
DOC_TYPE_CURSOR,
DOC_TYPE_FILL,
DOC_TYPE_GROUP,
DOC_TYPE_IF_BREAK,
DOC_TYPE_INDENT,
DOC_TYPE_INDENT_IF_BREAK,
DOC_TYPE_LABEL,
DOC_TYPE_LINE,
DOC_TYPE_LINE_SUFFIX,
DOC_TYPE_LINE_SUFFIX_BOUNDARY,
DOC_TYPE_LINE,
DOC_TYPE_LABEL,
DOC_TYPE_BREAK_PARENT,
DOC_TYPE_TRIM,
} from "./constants.js";
import { assertDoc, assertDocArray } from "./utils/assert-doc.js";

@@ -233,28 +233,28 @@ function label(label, contents) {
}

export {
join,
line,
softline,
hardline,
literalline,
group,
addAlignmentToDoc,
align,
breakParent,
conditionalGroup,
fill,
lineSuffix,
lineSuffixBoundary,
cursor,
breakParent,
dedent,
dedentToRoot,
fill,
group,
hardline,
hardlineWithoutBreakParent,
ifBreak,
trim,
indent,
indentIfBreak,
align,
addAlignmentToDoc,
markAsRoot,
dedentToRoot,
dedent,
hardlineWithoutBreakParent,
literallineWithoutBreakParent,
join,
label,
line,
lineSuffix,
lineSuffixBoundary,
literalline,
literallineWithoutBreakParent,
markAsRoot,
softline,
trim,
};
12 changes: 6 additions & 6 deletions src/document/debug.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import {
DOC_TYPE_INDENT,
DOC_TYPE_ALIGN,
DOC_TYPE_TRIM,
DOC_TYPE_GROUP,
DOC_TYPE_BREAK_PARENT,
DOC_TYPE_FILL,
DOC_TYPE_GROUP,
DOC_TYPE_IF_BREAK,
DOC_TYPE_INDENT,
DOC_TYPE_INDENT_IF_BREAK,
DOC_TYPE_LABEL,
DOC_TYPE_LINE,
DOC_TYPE_LINE_SUFFIX,
DOC_TYPE_LINE_SUFFIX_BOUNDARY,
DOC_TYPE_LINE,
DOC_TYPE_LABEL,
DOC_TYPE_BREAK_PARENT,
DOC_TYPE_TRIM,
} from "./constants.js";

function flattenDoc(doc) {
20 changes: 10 additions & 10 deletions src/document/printer.js
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
import { convertEndOfLineToChars } from "../common/end-of-line.js";
import getStringWidth from "../utils/get-string-width.js";
import { fill, hardlineWithoutBreakParent, indent } from "./builders.js";
import {
DOC_TYPE_STRING,
DOC_TYPE_ALIGN,
DOC_TYPE_ARRAY,
DOC_TYPE_BREAK_PARENT,
DOC_TYPE_CURSOR,
DOC_TYPE_INDENT,
DOC_TYPE_ALIGN,
DOC_TYPE_TRIM,
DOC_TYPE_GROUP,
DOC_TYPE_FILL,
DOC_TYPE_GROUP,
DOC_TYPE_IF_BREAK,
DOC_TYPE_INDENT,
DOC_TYPE_INDENT_IF_BREAK,
DOC_TYPE_LABEL,
DOC_TYPE_LINE,
DOC_TYPE_LINE_SUFFIX,
DOC_TYPE_LINE_SUFFIX_BOUNDARY,
DOC_TYPE_LINE,
DOC_TYPE_LABEL,
DOC_TYPE_BREAK_PARENT,
DOC_TYPE_STRING,
DOC_TYPE_TRIM,
} from "./constants.js";
import { fill, indent, hardlineWithoutBreakParent } from "./builders.js";
import { getDocParts, getDocType, propagateBreaks } from "./utils.js";
import InvalidDocError from "./invalid-doc-error.js";
import { getDocParts, getDocType, propagateBreaks } from "./utils.js";

/** @typedef {typeof MODE_BREAK | typeof MODE_FLAT} Mode */
/** @typedef {{ ind: any, doc: any, mode: Mode }} Command */
44 changes: 22 additions & 22 deletions src/document/public.js
Original file line number Diff line number Diff line change
@@ -1,39 +1,39 @@
import {
join,
line,
softline,
hardline,
literalline,
group,
addAlignmentToDoc,
align,
breakParent,
conditionalGroup,
fill,
lineSuffix,
lineSuffixBoundary,
cursor,
breakParent,
dedent,
dedentToRoot,
fill,
group,
hardline,
hardlineWithoutBreakParent,
ifBreak,
trim,
indent,
indentIfBreak,
align,
addAlignmentToDoc,
markAsRoot,
dedentToRoot,
dedent,
hardlineWithoutBreakParent,
literallineWithoutBreakParent,
join,
label,
line,
lineSuffix,
lineSuffixBoundary,
literalline,
literallineWithoutBreakParent,
markAsRoot,
softline,
trim,
} from "./builders.js";
import { printDocToString } from "./printer.js";
import {
willBreak,
traverseDoc,
canBreak,
findInDoc,
mapDoc,
removeLines,
stripTrailingHardline,
replaceEndOfLine,
canBreak,
stripTrailingHardline,
traverseDoc,
willBreak,
} from "./utils.js";

export const builders = {
40 changes: 20 additions & 20 deletions src/document/utils.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
import { join, literalline } from "./builders.js";
import {
DOC_TYPE_STRING,
DOC_TYPE_ALIGN,
DOC_TYPE_ARRAY,
DOC_TYPE_BREAK_PARENT,
DOC_TYPE_CURSOR,
DOC_TYPE_INDENT,
DOC_TYPE_ALIGN,
DOC_TYPE_TRIM,
DOC_TYPE_GROUP,
DOC_TYPE_FILL,
DOC_TYPE_GROUP,
DOC_TYPE_IF_BREAK,
DOC_TYPE_INDENT,
DOC_TYPE_INDENT_IF_BREAK,
DOC_TYPE_LABEL,
DOC_TYPE_LINE,
DOC_TYPE_LINE_SUFFIX,
DOC_TYPE_LINE_SUFFIX_BOUNDARY,
DOC_TYPE_LINE,
DOC_TYPE_LABEL,
DOC_TYPE_BREAK_PARENT,
DOC_TYPE_STRING,
DOC_TYPE_TRIM,
} from "./constants.js";
import { literalline, join } from "./builders.js";
import InvalidDocError from "./invalid-doc-error.js";
import getDocType from "./utils/get-doc-type.js";
import traverseDoc from "./utils/traverse-doc.js";
import InvalidDocError from "./invalid-doc-error.js";

const getDocParts = (doc) => {
if (Array.isArray(doc)) {
@@ -429,19 +429,19 @@ function inheritLabel(doc, fn) {
}

export {
getDocParts,
willBreak,
traverseDoc,
canBreak,
cleanDoc,
findInDoc,
getDocParts,
getDocType,
inheritLabel,
mapDoc,
normalizeDoc,
normalizeParts,
propagateBreaks,
removeLines,
stripTrailingHardline,
normalizeParts,
normalizeDoc,
cleanDoc,
replaceEndOfLine,
canBreak,
getDocType,
inheritLabel,
stripTrailingHardline,
traverseDoc,
willBreak,
};
2 changes: 1 addition & 1 deletion src/document/utils/get-doc-type.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {
DOC_TYPE_STRING,
DOC_TYPE_ARRAY,
DOC_TYPE_STRING,
VALID_OBJECT_DOC_TYPES,
} from "../constants.js";

16 changes: 8 additions & 8 deletions src/document/utils/traverse-doc.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
import {
DOC_TYPE_STRING,
DOC_TYPE_ALIGN,
DOC_TYPE_ARRAY,
DOC_TYPE_BREAK_PARENT,
DOC_TYPE_CURSOR,
DOC_TYPE_INDENT,
DOC_TYPE_ALIGN,
DOC_TYPE_TRIM,
DOC_TYPE_GROUP,
DOC_TYPE_FILL,
DOC_TYPE_GROUP,
DOC_TYPE_IF_BREAK,
DOC_TYPE_INDENT,
DOC_TYPE_INDENT_IF_BREAK,
DOC_TYPE_LABEL,
DOC_TYPE_LINE,
DOC_TYPE_LINE_SUFFIX,
DOC_TYPE_LINE_SUFFIX_BOUNDARY,
DOC_TYPE_LINE,
DOC_TYPE_LABEL,
DOC_TYPE_BREAK_PARENT,
DOC_TYPE_STRING,
DOC_TYPE_TRIM,
} from "../constants.js";
import InvalidDocError from "../invalid-doc-error.js";
import getDocType from "./get-doc-type.js";
34 changes: 26 additions & 8 deletions src/index.d.ts
Original file line number Diff line number Diff line change
@@ -291,6 +291,7 @@ export type BuiltInParserName =
| "json-stringify"
| "json"
| "json5"
| "jsonc"
| "less"
| "lwc"
| "markdown"
@@ -347,12 +348,6 @@ export interface RequiredOptions extends doc.printer.Options {
* @default false
*/
bracketSameLine: boolean;
/**
* Put the `>` of a multi-line JSX element at the end of the last line instead of being alone on the next line.
* @default false
* @deprecated use bracketSameLine instead
*/
jsxBracketSameLine: boolean;
/**
* Format only a segment of a file.
* @default 0
@@ -430,6 +425,22 @@ export interface RequiredOptions extends doc.printer.Options {
* @default false
*/
singleAttributePerLine: boolean;
/**
* Use curious ternaries, with the question mark after the condition, instead
* of on the same line as the consequent.
* @default false
*/
experimentalTernaries: boolean;
/**
* Put the `>` of a multi-line JSX element at the end of the last line instead of being alone on the next line.
* @default false
* @deprecated use bracketSameLine instead
*/
jsxBracketSameLine?: boolean;
/**
* Arbitrary additional values on an options object are always allowed.
*/
[_: string]: unknown;
}

export interface ParserOptions<T = any> extends RequiredOptions {
@@ -780,7 +791,7 @@ export interface SupportInfo {
export interface FileInfoOptions {
ignorePath?: string | URL | (string | URL)[] | undefined;
withNodeModules?: boolean | undefined;
plugins?: string[] | undefined;
plugins?: Array<string | Plugin> | undefined;
resolveConfig?: boolean | undefined;
}

@@ -794,10 +805,17 @@ export function getFileInfo(
options?: FileInfoOptions,
): Promise<FileInfoResult>;

export interface SupportInfoOptions {
plugins?: Array<string | Plugin> | undefined;
showDeprecated?: boolean | undefined;
}

/**
* Returns an object representing the parsers, languages and file types Prettier supports for the current version.
*/
export function getSupportInfo(): Promise<SupportInfo>;
export function getSupportInfo(
options?: SupportInfoOptions,
): Promise<SupportInfo>;

/**
* `version` field in `package.json`
49 changes: 25 additions & 24 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,31 +1,32 @@
import * as vnopts from "vnopts";
// "fast-glob" is bundled here since the API uses `micromatch` too
import fastGlob from "fast-glob";
import * as core from "./main/core.js";
import {
getSupportInfo as getSupportInfoWithoutPlugins,
normalizeOptionSettings,
} from "./main/support.js";
import * as vnopts from "vnopts";

import * as errors from "./common/errors.js";
import getFileInfoWithoutPlugins from "./common/get-file-info.js";
import mockable from "./common/mockable.js";
import {
loadBuiltinPlugins,
loadPlugins,
clearCache as clearPluginCache,
} from "./main/plugins/index.js";
import {
clearCache as clearConfigCache,
resolveConfig,
resolveConfigFile,
clearCache as clearConfigCache,
} from "./config/resolve-config.js";
import * as errors from "./common/errors.js";
import * as optionCategories from "./main/option-categories.js";
import { createIsIgnoredFunction } from "./utils/ignore.js";
import * as core from "./main/core.js";
import { formatOptionsHiddenDefaults } from "./main/normalize-format-options.js";
import normalizeOptions from "./main/normalize-options.js";
import partition from "./utils/partition.js";
import * as optionCategories from "./main/option-categories.js";
import {
clearCache as clearPluginCache,
loadBuiltinPlugins,
loadPlugins,
} from "./main/plugins/index.js";
import {
getSupportInfo as getSupportInfoWithoutPlugins,
normalizeOptionSettings,
} from "./main/support.js";
import { createIsIgnoredFunction } from "./utils/ignore.js";
import isNonEmptyArray from "./utils/is-non-empty-array.js";
import omit from "./utils/object-omit.js";
import mockable from "./common/mockable.js";
import partition from "./utils/partition.js";

/**
* @param {*} fn
@@ -113,17 +114,17 @@ const debugApis = {
};

export {
formatWithCursor,
format,
debugApis as __debug,
sharedWithCli as __internal,
check,
resolveConfig,
resolveConfigFile,
clearCache as clearConfigCache,
format,
formatWithCursor,
getFileInfo,
getSupportInfo,
sharedWithCli as __internal,
debugApis as __debug,
resolveConfig,
resolveConfigFile,
};
export * as util from "./utils/public.js";
export * as doc from "./document/public.js";
export { default as version } from "./main/version.evaluate.cjs";
export * as util from "./utils/public.js";
2 changes: 1 addition & 1 deletion src/language-css/index.js
Original file line number Diff line number Diff line change
@@ -3,6 +3,6 @@ import printer from "./printer-postcss.js";
export const printers = {
postcss: printer,
};
export * as parsers from "./parser-postcss.js";
export { default as languages } from "./languages.evaluate.js";
export { default as options } from "./options.js";
export * as parsers from "./parser-postcss.js";
1 change: 1 addition & 0 deletions src/language-css/languages.evaluate.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import linguistLanguages from "linguist-languages";

import createLanguage from "../utils/create-language.js";

const languages = [
4 changes: 2 additions & 2 deletions src/language-css/loc.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { skipEverythingButNewLine } from "../utils/skip.js";
import isNonEmptyArray from "../utils/is-non-empty-array.js";
import lineColumnToIndex from "../utils/line-column-to-index.js";
import { skipEverythingButNewLine } from "../utils/skip.js";

function calculateLocStart(node, text) {
// `postcss>=8`
@@ -238,4 +238,4 @@ function locEnd(node) {
return node.source?.endOffset;
}

export { locStart, locEnd, calculateLoc, replaceQuotesInInlineComments };
export { calculateLoc, locEnd, locStart, replaceQuotesInInlineComments };
3 changes: 2 additions & 1 deletion src/language-css/parse/parse-media-query.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import postcssMediaQueryParser from "postcss-media-query-parser";
import { addTypePrefix, addMissingType } from "./utils.js";

import { addMissingType, addTypePrefix } from "./utils.js";

const parse = postcssMediaQueryParser.default;

1 change: 1 addition & 0 deletions src/language-css/parse/parse-selector.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import PostcssSelectorParser from "postcss-selector-parser/dist/processor.js";

import { addTypePrefix } from "./utils.js";

function parseSelector(selector) {
1 change: 1 addition & 0 deletions src/language-css/parse/parse-value.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import PostcssValuesParser from "postcss-values-parser/lib/parser.js";

import getFunctionArgumentsText from "../utils/get-function-arguments-text.js";
import getValueRoot from "../utils/get-value-root.js";
import hasSCSSInterpolation from "../utils/has-scss-interpolation.js";
2 changes: 1 addition & 1 deletion src/language-css/parse/utils.js
Original file line number Diff line number Diff line change
@@ -29,4 +29,4 @@ function addMissingType(node) {
return node;
}

export { addTypePrefix, addMissingType };
export { addMissingType, addTypePrefix };
15 changes: 8 additions & 7 deletions src/language-css/parser-postcss.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
import postcssParse from "postcss/lib/parse";
import postcssLess from "postcss-less";
import postcssScssParse from "postcss-scss/lib/scss-parse";

import createError from "../common/parser-create-error.js";
import parseFrontMatter from "../utils/front-matter/parse.js";
import { hasPragma } from "./pragma.js";
import {
locStart,
locEnd,
calculateLoc,
locEnd,
locStart,
replaceQuotesInInlineComments,
} from "./loc.js";
import isSCSSNestedPropertyNode from "./utils/is-scss-nested-property-node.js";
import isModuleRuleName from "./utils/is-module-rule-name.js";
import parseValue from "./parse/parse-value.js";
import parseSelector from "./parse/parse-selector.js";
import parseMediaQuery from "./parse/parse-media-query.js";
import parseSelector from "./parse/parse-selector.js";
import parseValue from "./parse/parse-value.js";
import { addTypePrefix } from "./parse/utils.js";
import { hasPragma } from "./pragma.js";
import isModuleRuleName from "./utils/is-module-rule-name.js";
import isSCSSNestedPropertyNode from "./utils/is-scss-nested-property-node.js";

const DEFAULT_SCSS_DIRECTIVE = /(\s*)(!default).*$/;
const GLOBAL_SCSS_DIRECTIVE = /(\s*)(!global).*$/;
44 changes: 22 additions & 22 deletions src/language-css/print/comma-separated-value-group.js
Original file line number Diff line number Diff line change
@@ -1,42 +1,42 @@
import {
line,
hardline,
softline,
group,
breakParent,
dedent,
fill,
group,
hardline,
indent,
dedent,
breakParent,
line,
softline,
} from "../../document/builders.js";
import { locEnd, locStart } from "../loc.js";
import {
getPropOfDeclNode,
insideValueFunctionNode,
hasEmptyRawBefore,
insideAtRuleNode,
insideURLFunctionInImportAtRuleNode,
isSCSSControlDirectiveNode,
isRelationalOperatorNode,
isEqualityOperatorNode,
isMultiplicationNode,
isDivisionNode,
insideValueFunctionNode,
isAdditionNode,
isSubtractionNode,
isMathOperatorNode,
isAtWordPlaceholderNode,
isColonNode,
isColorAdjusterFuncNode,
isDivisionNode,
isEachKeywordNode,
isEqualityOperatorNode,
isForKeywordNode,
isHashNode,
isIfElseKeywordNode,
hasEmptyRawBefore,
isPostcssSimpleVarNode,
isInlineValueCommentNode,
isHashNode,
isLeftCurlyBraceNode,
isMathOperatorNode,
isMultiplicationNode,
isParenGroupNode,
isPostcssSimpleVarNode,
isRelationalOperatorNode,
isRightCurlyBraceNode,
isSCSSControlDirectiveNode,
isSubtractionNode,
isWordNode,
isColonNode,
isColorAdjusterFuncNode,
isAtWordPlaceholderNode,
isParenGroupNode,
} from "../utils/index.js";
import { locStart, locEnd } from "../loc.js";

function printCommaSeparatedValueGroup(path, options, print) {
const { node } = path;
6 changes: 3 additions & 3 deletions src/language-css/print/misc.js
Original file line number Diff line number Diff line change
@@ -56,10 +56,10 @@ function shouldPrintTrailingComma(options) {
}

export {
adjustStrings,
adjustNumbers,
adjustStrings,
printCssNumber,
printUnit,
quoteAttributeValue,
shouldPrintTrailingComma,
printUnit,
printCssNumber,
};
24 changes: 12 additions & 12 deletions src/language-css/print/parenthesized-value-group.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
import isNextLineEmpty from "../../utils/is-next-line-empty.js";
import isNonEmptyArray from "../../utils/is-non-empty-array.js";
import {
dedent,
fill,
group,
hardline,
ifBreak,
indent,
join,
line,
hardline,
softline,
group,
fill,
indent,
dedent,
ifBreak,
} from "../../document/builders.js";
import { getDocParts } from "../../document/utils.js";
import isNextLineEmpty from "../../utils/is-next-line-empty.js";
import isNonEmptyArray from "../../utils/is-non-empty-array.js";
import { locEnd, locStart } from "../loc.js";
import {
isURLFunctionNode,
isKeyValuePairNode,
isConfigurationNode,
isKeyInValuePairNode,
isKeyValuePairNode,
isSCSSMapItemNode,
isConfigurationNode,
isURLFunctionNode,
isVarFunctionNode,
} from "../utils/index.js";
import { locStart, locEnd } from "../loc.js";
import { shouldPrintTrailingComma } from "./misc.js";

function hasComma({ node, parent }, options) {
6 changes: 3 additions & 3 deletions src/language-css/print/sequence.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { hardline, line } from "../../document/builders.js";
import isFrontMatter from "../../utils/front-matter/is-front-matter.js";
import hasNewline from "../../utils/has-newline.js";
import isNextLineEmpty from "../../utils/is-next-line-empty.js";
import isFrontMatter from "../../utils/front-matter/is-front-matter.js";
import { line, hardline } from "../../document/builders.js";
import { locStart, locEnd } from "../loc.js";
import { locEnd, locStart } from "../loc.js";

function printSequence(path, options, print) {
const parts = [];
64 changes: 32 additions & 32 deletions src/language-css/printer-postcss.js
Original file line number Diff line number Diff line change
@@ -1,54 +1,54 @@
import printString from "../utils/print-string.js";
import isNonEmptyArray from "../utils/is-non-empty-array.js";
import {
breakParent,
dedent,
group,
hardline,
ifBreak,
indent,
join,
line,
hardline,
softline,
group,
indent,
dedent,
ifBreak,
breakParent,
} from "../document/builders.js";
import { removeLines } from "../document/utils.js";
import isNonEmptyArray from "../utils/is-non-empty-array.js";
import printString from "../utils/print-string.js";
import UnexpectedNodeError from "../utils/unexpected-node-error.js";
import clean from "./clean.js";
import embed from "./embed.js";
import { insertPragma } from "./pragma.js";
import getVisitorKeys from "./get-visitor-keys.js";
import { locEnd, locStart } from "./loc.js";
import { insertPragma } from "./pragma.js";
import printCommaSeparatedValueGroup from "./print/comma-separated-value-group.js";
import {
maybeToLowerCase,
insideValueFunctionNode,
insideICSSRuleNode,
insideAtRuleNode,
isKeyframeAtRuleKeywords,
isWideKeywords,
isLastNode,
isSCSSControlDirectiveNode,
isDetachedRulesetDeclarationNode,
hasComposesNode,
hasParensAroundNode,
isDetachedRulesetCallNode,
isTemplatePlaceholderNode,
isTemplatePropNode,
isMediaAndSupportsKeywords,
lastLineHasInlineComment,
} from "./utils/index.js";
import { locStart, locEnd } from "./loc.js";
import {
adjustStrings,
adjustNumbers,
quoteAttributeValue,
printUnit,
adjustStrings,
printCssNumber,
printUnit,
quoteAttributeValue,
} from "./print/misc.js";
import printCommaSeparatedValueGroup from "./print/comma-separated-value-group.js";
import {
printParenthesizedValueGroup,
shouldBreakList,
} from "./print/parenthesized-value-group.js";
import printSequence from "./print/sequence.js";
import {
hasComposesNode,
hasParensAroundNode,
insideAtRuleNode,
insideICSSRuleNode,
insideValueFunctionNode,
isDetachedRulesetCallNode,
isDetachedRulesetDeclarationNode,
isKeyframeAtRuleKeywords,
isLastNode,
isMediaAndSupportsKeywords,
isSCSSControlDirectiveNode,
isTemplatePlaceholderNode,
isTemplatePropNode,
isWideKeywords,
lastLineHasInlineComment,
maybeToLowerCase,
} from "./utils/index.js";

function genericPrint(path, options, print) {
const { node } = path;
68 changes: 34 additions & 34 deletions src/language-css/utils/index.js
Original file line number Diff line number Diff line change
@@ -387,50 +387,50 @@ function isParenGroupNode(node) {

export {
getPropOfDeclNode,
maybeToLowerCase,
insideValueFunctionNode,
insideICSSRuleNode,
hasComposesNode,
hasEmptyRawBefore,
hasParensAroundNode,
insideAtRuleNode,
insideICSSRuleNode,
insideURLFunctionInImportAtRuleNode,
isKeyframeAtRuleKeywords,
isWideKeywords,
isLastNode,
isSCSSControlDirectiveNode,
insideValueFunctionNode,
isAdditionNode,
isAtWordPlaceholderNode,
isColonNode,
isColorAdjusterFuncNode,
isConfigurationNode,
isDetachedRulesetCallNode,
isDetachedRulesetDeclarationNode,
isRelationalOperatorNode,
isEqualityOperatorNode,
isMultiplicationNode,
isDivisionNode,
isAdditionNode,
isSubtractionNode,
isModuloNode,
isMathOperatorNode,
isEachKeywordNode,
isEqualityOperatorNode,
isForKeywordNode,
isURLFunctionNode,
isHashNode,
isIfElseKeywordNode,
hasComposesNode,
hasParensAroundNode,
hasEmptyRawBefore,
isDetachedRulesetCallNode,
isTemplatePlaceholderNode,
isTemplatePropNode,
isPostcssSimpleVarNode,
isKeyValuePairNode,
isKeyValuePairInParenGroupNode,
isKeyInValuePairNode,
isSCSSMapItemNode,
isInlineValueCommentNode,
isHashNode,
isKeyframeAtRuleKeywords,
isKeyInValuePairNode,
isKeyValuePairInParenGroupNode,
isKeyValuePairNode,
isLastNode,
isLeftCurlyBraceNode,
isRightCurlyBraceNode,
isWordNode,
isColonNode,
isMathOperatorNode,
isMediaAndSupportsKeywords,
isColorAdjusterFuncNode,
lastLineHasInlineComment,
isAtWordPlaceholderNode,
isConfigurationNode,
isModuloNode,
isMultiplicationNode,
isParenGroupNode,
isPostcssSimpleVarNode,
isRelationalOperatorNode,
isRightCurlyBraceNode,
isSCSSControlDirectiveNode,
isSCSSMapItemNode,
isSubtractionNode,
isTemplatePlaceholderNode,
isTemplatePropNode,
isURLFunctionNode,
isVarFunctionNode,
isWideKeywords,
isWordNode,
lastLineHasInlineComment,
maybeToLowerCase,
};
2 changes: 1 addition & 1 deletion src/language-graphql/index.js
Original file line number Diff line number Diff line change
@@ -3,6 +3,6 @@ import printer from "./printer-graphql.js";
export const printers = {
graphql: printer,
};
export * as parsers from "./parser-graphql.js";
export { default as languages } from "./languages.evaluate.js";
export { default as options } from "./options.js";
export * as parsers from "./parser-graphql.js";
1 change: 1 addition & 0 deletions src/language-graphql/languages.evaluate.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import linguistLanguages from "linguist-languages";

import createLanguage from "../utils/create-language.js";

const languages = [
2 changes: 1 addition & 1 deletion src/language-graphql/loc.js
Original file line number Diff line number Diff line change
@@ -8,4 +8,4 @@ function locEnd(nodeOrToken) {
return nodeOrToken.kind === "Comment" ? nodeOrToken.end : nodeOrToken.loc.end;
}

export { locStart, locEnd };
export { locEnd, locStart };
3 changes: 2 additions & 1 deletion src/language-graphql/parser-graphql.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { parse as parseGraphql } from "graphql/language/parser.mjs";

import createError from "../common/parser-create-error.js";
import { locEnd, locStart } from "./loc.js";
import { hasPragma } from "./pragma.js";
import { locStart, locEnd } from "./loc.js";

function parseComments(ast) {
const comments = [];
14 changes: 7 additions & 7 deletions src/language-graphql/printer-graphql.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import {
join,
group,
hardline,
ifBreak,
indent,
join,
line,
softline,
group,
indent,
ifBreak,
} from "../document/builders.js";
import isNextLineEmpty from "../utils/is-next-line-empty.js";
import isNonEmptyArray from "../utils/is-non-empty-array.js";
import UnexpectedNodeError from "../utils/unexpected-node-error.js";
import { insertPragma } from "./pragma.js";
import { locStart, locEnd } from "./loc.js";
import getVisitorKeys from "./get-visitor-keys.js";
import { locEnd, locStart } from "./loc.js";
import { insertPragma } from "./pragma.js";
import printDescription from "./print/description.js";

function genericPrint(path, options, print) {
@@ -384,7 +384,7 @@ function genericPrint(path, options, print) {
" =",
ifBreak("", " "),
indent([
ifBreak([line, " "]),
ifBreak([line, "| "]),
join([line, "| "], path.map(print, "types")),
]),
]
2 changes: 1 addition & 1 deletion src/language-handlebars/index.js
Original file line number Diff line number Diff line change
@@ -3,5 +3,5 @@ import printer from "./printer-glimmer.js";
export const printers = {
glimmer: printer,
};
export * as parsers from "./parser-glimmer.js";
export { default as languages } from "./languages.evaluate.js";
export * as parsers from "./parser-glimmer.js";
1 change: 1 addition & 0 deletions src/language-handlebars/languages.evaluate.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import linguistLanguages from "linguist-languages";

import createLanguage from "../utils/create-language.js";

const languages = [
2 changes: 1 addition & 1 deletion src/language-handlebars/loc.js
Original file line number Diff line number Diff line change
@@ -6,4 +6,4 @@ function locEnd(node) {
return node.loc.end.offset;
}

export { locStart, locEnd };
export { locEnd, locStart };
3 changes: 2 additions & 1 deletion src/language-handlebars/parser-glimmer.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { preprocess as parseGlimmer } from "@glimmer/syntax";
import { LinesAndColumns } from "lines-and-columns";

import createError from "../common/parser-create-error.js";
import { locStart, locEnd } from "./loc.js";
import { locEnd, locStart } from "./loc.js";

/* from the following template: `non-escaped mustache \\{{helper}}`
* glimmer parser will produce an AST missing a backslash
44 changes: 40 additions & 4 deletions src/language-handlebars/printer-glimmer.js
Original file line number Diff line number Diff line change
@@ -11,13 +11,13 @@ import {
} from "../document/builders.js";
import { replaceEndOfLine } from "../document/utils.js";
import getPreferredQuote from "../utils/get-preferred-quote.js";
import htmlWhitespaceUtils from "../utils/html-whitespace-utils.js";
import isNonEmptyArray from "../utils/is-non-empty-array.js";
import UnexpectedNodeError from "../utils/unexpected-node-error.js";
import htmlWhitespaceUtils from "../utils/html-whitespace-utils.js";
import { locStart, locEnd } from "./loc.js";
import clean from "./clean.js";
import { hasPrettierIgnore, isVoidElement, isWhitespaceNode } from "./utils.js";
import getVisitorKeys from "./get-visitor-keys.js";
import { locEnd, locStart } from "./loc.js";
import { hasPrettierIgnore, isVoidElement, isWhitespaceNode } from "./utils.js";

/**
* @typedef {import("../document/builders.js").Doc} Doc
@@ -366,7 +366,7 @@ function print(path, options, print) {
];
}
case "PathExpression":
return node.original;
return printPathExpression(node);

case "BooleanLiteral":
return String(node.value);
@@ -764,6 +764,42 @@ function printBlockParams(node) {
return ["as |", node.blockParams.join(" "), "|"];
}

// https://handlebarsjs.com/guide/expressions.html#literal-segments
const PATH_EXPRESSION_FORBIDDEN_CHARACTERS = new Set(
"!\"#%&'()*+,./;<=>@[\\]^`{|}~",
);
const PATH_EXPRESSION_FORBIDDEN_IN_FIRST_PART = new Set([
"true",
"false",
"null",
"undefined",
]);
const isPathExpressionPartNeedBrackets = (part, index) =>
(index !== 0 && PATH_EXPRESSION_FORBIDDEN_IN_FIRST_PART.has(part)) ||
/\s/.test(part) ||
/^\d/.test(part) ||
Array.prototype.some.call(part, (character) =>
PATH_EXPRESSION_FORBIDDEN_CHARACTERS.has(character),
);
function printPathExpression(node) {
if (node.data || (node.parts.length === 1 && node.original.includes("/"))) {
// check if node has data, or
// check if node is a legacy path expression (and leave it alone)
return node.original;
}

let { parts } = node;
if (node.this) {
parts = ["this", ...parts];
}

return parts
.map((part, index) =>
isPathExpressionPartNeedBrackets(part, index) ? `[${part}]` : part,
)
.join(".");
}

const printer = {
print,
massageAstNode: clean,
6 changes: 4 additions & 2 deletions src/language-html/ast.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
const NODES_KEYS = {
attrs: true,
children: true,
cases: true, // plural and select
expression: true, // for expansionCase
};

const NON_ENUMERABLE_PROPERTIES = new Set(["parent"]);
@@ -136,12 +138,12 @@ class Node {

get prev() {
// @ts-expect-error
return this.parent?.children[this.parent.children.indexOf(this) - 1];
return this.parent?.children?.[this.parent.children.indexOf(this) - 1];
}

get next() {
// @ts-expect-error
return this.parent?.children[this.parent.children.indexOf(this) + 1];
return this.parent?.children?.[this.parent.children.indexOf(this) + 1];
}

// for element and attribute
7 changes: 7 additions & 0 deletions src/language-html/clean.js
Original file line number Diff line number Diff line change
@@ -10,6 +10,9 @@ const ignoredProperties = new Set([
"tagDefinition",
"tokens",
"valueTokens",
"switchValueSourceSpan",
"expSourceSpan",
"valueSourceSpan",
]);

const embeddedAngularControlFlowBlocks = new Set([
@@ -47,6 +50,10 @@ function clean(ast, newNode) {
}
}
}

if (ast.type === "angularIcuExpression") {
newNode.switchValue = ast.switchValue.trim();
}
}

clean.ignoredProperties = ignoredProperties;
4 changes: 2 additions & 2 deletions src/language-html/constants.evaluate.js
Original file line number Diff line number Diff line change
@@ -50,8 +50,8 @@ const CSS_WHITE_SPACE_TAGS = getCssStyleTags("white-space");
const CSS_WHITE_SPACE_DEFAULT = "normal";

export {
CSS_DISPLAY_TAGS,
CSS_DISPLAY_DEFAULT,
CSS_WHITE_SPACE_TAGS,
CSS_DISPLAY_TAGS,
CSS_WHITE_SPACE_DEFAULT,
CSS_WHITE_SPACE_TAGS,
};
20 changes: 9 additions & 11 deletions src/language-html/embed.js
Original file line number Diff line number Diff line change
@@ -6,24 +6,24 @@ import {
line,
} from "../document/builders.js";
import printFrontMatter from "../utils/front-matter/print.js";
import printAngularControlFlowBlockParameters from "./embed/angular-control-flow-block-parameters.js";
import printAttribute from "./embed/attribute.js";
import getNodeContent from "./get-node-content.js";
import {
needsToBorrowPrevClosingTagEndMarker,
printClosingTag,
printClosingTagSuffix,
needsToBorrowPrevClosingTagEndMarker,
printOpeningTagPrefix,
printOpeningTag,
printOpeningTagPrefix,
} from "./print/tag.js";
import {
dedentString,
htmlTrimPreserveIndentation,
inferElementParser,
isScriptLikeTag,
isVueNonHtmlBlock,
inferElementParser,
htmlTrimPreserveIndentation,
dedentString,
} from "./utils/index.js";
import isVueSfcWithTypescriptScript from "./utils/is-vue-sfc-with-typescript-script.js";
import getNodeContent from "./get-node-content.js";
import printAttribute from "./embed/attribute.js";
import printAngularControlFlowBlockParameters from "./embed/angular-control-flow-block-parameters.js";

const embeddedAngularControlFlowBlocks = new Set([
"if",
@@ -101,9 +101,7 @@ function embed(path, options) {
return [
breakParent,
printOpeningTagPrefix(node, options),
await textToDoc(value, textToDocOptions, {
stripTrailingHardline: true,
}),
await textToDoc(value, textToDocOptions),
printClosingTagSuffix(node, options),
];
};
12 changes: 6 additions & 6 deletions src/language-html/embed/angular-attributes.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import { fill } from "../../document/builders.js";
import {
getUnescapedAttributeValue,
getTextValueParts,
getUnescapedAttributeValue,
} from "../utils/index.js";
import { fill } from "../../document/builders.js";
import {
interpolationRegex as angularInterpolationRegex,
printAngularInterpolation,
} from "./angular-interpolation.js";
import {
formatAttributeValue,
printExpand,
shouldHugJsExpression,
} from "./utils.js";
import {
interpolationRegex as angularInterpolationRegex,
printAngularInterpolation,
} from "./angular-interpolation.js";

function createAngularPrinter({ parser }) {
return (textToDoc, print, path /*, options*/) =>
4 changes: 2 additions & 2 deletions src/language-html/embed/attribute.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { group } from "../../document/builders.js";
import { mapDoc } from "../../document/utils.js";
import printSrcset from "./srcset.js";
import printAngularAttribute from "./angular-attributes.js";
import printClassNames from "./class-names.js";
import printSrcset from "./srcset.js";
import { printStyleAttribute } from "./style.js";
import printVueAttribute from "./vue-attributes.js";
import printAngularAttribute from "./angular-attributes.js";

/**
* @typedef {import("../../document/builders.js").Doc} Doc
1 change: 1 addition & 0 deletions src/language-html/embed/srcset.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import parseSrcset from "@prettier/parse-srcset";

import { ifBreak, join, line } from "../../document/builders.js";
import { getUnescapedAttributeValue } from "../utils/index.js";
import { printExpand } from "./utils.js";
2 changes: 1 addition & 1 deletion src/language-html/embed/utils.js
Original file line number Diff line number Diff line change
@@ -62,4 +62,4 @@ async function formatAttributeValue(
return shouldHug ? group(doc) : printExpand(doc);
}

export { printExpand, formatAttributeValue, shouldHugJsExpression };
export { formatAttributeValue, printExpand, shouldHugJsExpression };
8 changes: 4 additions & 4 deletions src/language-html/embed/vue-attributes.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import {
isVueSlotAttribute,
isVueSfcBindingsAttribute,
getUnescapedAttributeValue,
isVueScriptTag,
isVueSfcBindingsAttribute,
isVueSlotAttribute,
} from "../utils/index.js";
import isVueSfcWithTypescriptScript from "../utils/is-vue-sfc-with-typescript-script.js";
import { printVueVForDirective } from "./vue-v-for-directive.js";
import { printVueScriptGenericAttributeValue } from "./print-vue-script-generic-attribute-value.js";
import { formatAttributeValue, shouldHugJsExpression } from "./utils.js";
import {
printVueBindings,
isVueEventBindingExpression,
printVueBindings,
} from "./vue-bindings.js";
import { printVueVForDirective } from "./vue-v-for-directive.js";

/**
* @typedef {import("../../document/builders.js").Doc} Doc
6 changes: 3 additions & 3 deletions src/language-html/get-node-content.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import {
needsToBorrowParentClosingTagStartMarker,
printClosingTagStartMarker,
needsToBorrowLastChildClosingTagEndMarker,
printClosingTagEndMarker,
needsToBorrowParentClosingTagStartMarker,
needsToBorrowParentOpeningTagEndMarker,
printClosingTagEndMarker,
printClosingTagStartMarker,
printOpeningTagEndMarker,
} from "./print/tag.js";

2 changes: 1 addition & 1 deletion src/language-html/index.js
Original file line number Diff line number Diff line change
@@ -3,6 +3,6 @@ import printer from "./printer-html.js";
export const printers = {
html: printer,
};
export * as parsers from "./parser-html.js";
export { default as languages } from "./languages.evaluate.js";
export { default as options } from "./options.js";
export * as parsers from "./parser-html.js";
1 change: 1 addition & 0 deletions src/language-html/languages.evaluate.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import linguistLanguages from "linguist-languages";

import createLanguage from "../utils/create-language.js";

const languages = [
2 changes: 1 addition & 1 deletion src/language-html/loc.js
Original file line number Diff line number Diff line change
@@ -6,4 +6,4 @@ function locEnd(node) {
return node.sourceSpan.end.offset;
}

export { locStart, locEnd };
export { locEnd, locStart };
42 changes: 32 additions & 10 deletions src/language-html/parser-html.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,25 @@
import {
ParseSourceFile,
getHtmlTagDefinition,
parse as parseHtml,
ParseLocation,
ParseSourceFile,
ParseSourceSpan,
parse as parseHtml,
RecursiveVisitor,
visitAll,
getHtmlTagDefinition,
TagContentType,
visitAll,
} from "angular-html-parser";

import createError from "../common/parser-create-error.js";
import parseFrontMatter from "../utils/front-matter/parse.js";
import inferParser from "../utils/infer-parser.js";
import createError from "../common/parser-create-error.js";
import isNonEmptyArray from "../utils/is-non-empty-array.js";
import HTML_TAGS from "./utils/html-tag-names.evaluate.js";
import HTML_ELEMENT_ATTRIBUTES from "./utils/html-elements-attributes.evaluate.js";
import isUnknownNamespace from "./utils/is-unknown-namespace.js";
import { hasPragma } from "./pragma.js";
import { Node } from "./ast.js";
import { parseIeConditionalComment } from "./conditional-comment.js";
import { locStart, locEnd } from "./loc.js";
import { locEnd, locStart } from "./loc.js";
import { hasPragma } from "./pragma.js";
import HTML_ELEMENT_ATTRIBUTES from "./utils/html-elements-attributes.evaluate.js";
import HTML_TAGS from "./utils/html-tag-names.evaluate.js";
import isUnknownNamespace from "./utils/is-unknown-namespace.js";

/**
* @typedef {import('angular-html-parser')} AngularHtmlParser
@@ -67,6 +68,16 @@ function normalizeAngularControlFlowBlock(node) {
};
}

function normalizeAngularIcuExpression(node) {
if (node.type === "plural" || node.type === "select") {
node.clause = node.type;
node.type = "angularIcuExpression";
}
if (node.type === "expansionCase") {
node.type = "angularIcuCase";
}
}

/**
* @param {string} input
* @param {ParseOptions} parseOptions
@@ -261,6 +272,16 @@ function ngHtmlParser(input, parseOptions, options) {

visitAll(
new (class extends RecursiveVisitor {
// Angular does not visit to the children of expansionCase
// https://github.com/angular/angular/blob/e3a6bf9b6c3bef03df9bfc8f05b817bc875cbad6/packages/compiler/src/ml_parser/ast.ts#L161
visitExpansionCase(ast, context) {
if (name === "angular") {
// @ts-expect-error
this.visitChildren(context, (visit) => {
visit(ast.expression);
});
}
}
visit(node) {
restoreNameAndValue(node);
addTagDefinition(node);
@@ -374,6 +395,7 @@ function parse(
}

normalizeAngularControlFlowBlock(node);
normalizeAngularIcuExpression(node);
});

return ast;
3 changes: 2 additions & 1 deletion src/language-html/print-preprocess.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { ParseSourceSpan } from "angular-html-parser/lib/compiler/src/parse_util.js";

import htmlWhitespaceUtils from "../utils/html-whitespace-utils.js";
import {
getLeadingAndTrailingHtmlWhitespace,
canHaveInterpolation,
getLeadingAndTrailingHtmlWhitespace,
getNodeCssStyleDisplay,
isDanglingSpaceSensitiveNode,
isIndentationSensitiveNode,
10 changes: 6 additions & 4 deletions src/language-html/print/angular-control-flow-block.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import {
group,
hardline,
softline,
line,
indent,
join,
line,
softline,
} from "../../document/builders.js";
import { printChildren } from "./children.js";
import { hasPrettierIgnore } from "../utils/index.js";
import ANGULAR_CONTROL_FLOW_BLOCK_SETTINGS from "./angular-control-flow-block-settings.evaluate.js";
import { printChildren } from "./children.js";

function printAngularControlFlowBlock(path, options, print) {
const { node } = path;
@@ -51,7 +52,8 @@ function isPreviousBlockUnClosed(path) {
const { previous } = path;
return (
previous?.type === "angularControlFlowBlock" &&
!shouldCloseBlock(path.previous)
!hasPrettierIgnore(previous) &&
!shouldCloseBlock(previous)
);
}

62 changes: 62 additions & 0 deletions src/language-html/print/angular-icu-expression.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import {
group,
indent,
join,
line,
softline,
} from "../../document/builders.js";
import htmlWhitespaceUtils from "../../utils/html-whitespace-utils.js";
import { printClosingTagEnd, printOpeningTagStart } from "./tag.js";

/*
<span i18n>
Updated {minutes, plural,
=0 {just now}
=1 {one minute ago}
other {{{minutes}} minutes ago}
}
</span>
*/

function printAngularIcuExpression(path, options, print) {
const { node } = path;
return [
printOpeningTagStart(node, options),
group([
node.switchValue.trim(),
", ",
node.clause,
node.cases.length > 0
? [",", indent([line, join(line, path.map(print, "cases"))])]
: "",
softline,
]),
printClosingTagEnd(node, options),
];
}

function printAngularIcuCase(path, options, print) {
const { node } = path;
return [
node.value,
" {",
group([
indent([
softline,
path.map(({ node }) => {
// FIXME: We need a fundamental solution.
// Like this: https://github.com/prettier/prettier/blob/c1ebae2e8303841e59bc02e9e719a93e964ab0e9/src/language-html/print-preprocess.js#L254
if (node.type === "text" && !htmlWhitespaceUtils.trim(node.value)) {
return "";
}

return print();
}, "expression"),
]),
softline,
]),
"}",
];
}

export { printAngularIcuCase, printAngularIcuExpression };
51 changes: 36 additions & 15 deletions src/language-html/print/children.js
Original file line number Diff line number Diff line change
@@ -1,46 +1,67 @@
import {
breakParent,
group,
hardline,
ifBreak,
line,
softline,
hardline,
} from "../../document/builders.js";
import { replaceEndOfLine } from "../../document/utils.js";
import { locStart, locEnd } from "../loc.js";
import htmlWhitespaceUtils from "../../utils/html-whitespace-utils.js";
import isNonEmptyArray from "../../utils/is-non-empty-array.js";
import { locEnd, locStart } from "../loc.js";
import {
forceBreakChildren,
forceNextEmptyLine,
isTextLikeNode,
hasPrettierIgnore,
isTextLikeNode,
preferHardlineAsLeadingSpaces,
} from "../utils/index.js";
import {
printOpeningTagPrefix,
needsToBorrowNextOpeningTagStartMarker,
printOpeningTagStartMarker,
needsToBorrowParentClosingTagStartMarker,
needsToBorrowPrevClosingTagEndMarker,
printClosingTagEndMarker,
printClosingTagSuffix,
needsToBorrowParentClosingTagStartMarker,
printOpeningTagPrefix,
printOpeningTagStartMarker,
} from "./tag.js";

function getEndLocation(node) {
const endLocation = locEnd(node);

// Element can be unclosed
if (
node.type === "element" &&
!node.endSourceSpan &&
isNonEmptyArray(node.children)
) {
return Math.max(endLocation, getEndLocation(node.children.at(-1)));
}

return endLocation;
}

function printChild(childPath, options, print) {
const child = childPath.node;

if (hasPrettierIgnore(child)) {
const endLocation = getEndLocation(child);

return [
printOpeningTagPrefix(child, options),
replaceEndOfLine(
options.originalText.slice(
locStart(child) +
(child.prev && needsToBorrowNextOpeningTagStartMarker(child.prev)
? printOpeningTagStartMarker(child).length
: 0),
locEnd(child) -
(child.next && needsToBorrowPrevClosingTagEndMarker(child.next)
? printClosingTagEndMarker(child, options).length
: 0),
htmlWhitespaceUtils.trimEnd(
options.originalText.slice(
locStart(child) +
(child.prev && needsToBorrowNextOpeningTagStartMarker(child.prev)
? printOpeningTagStartMarker(child).length
: 0),
endLocation -
(child.next && needsToBorrowPrevClosingTagEndMarker(child.next)
? printClosingTagEndMarker(child, options).length
: 0),
),
),
),
printClosingTagSuffix(child, options),
21 changes: 11 additions & 10 deletions src/language-html/print/element.js
Original file line number Diff line number Diff line change
@@ -3,28 +3,28 @@ import {
dedentToRoot,
group,
ifBreak,
indentIfBreak,
indent,
indentIfBreak,
line,
softline,
} from "../../document/builders.js";
import { replaceEndOfLine } from "../../document/utils.js";
import getNodeContent from "../get-node-content.js";
import {
shouldPreserveContent,
forceBreakContent,
isScriptLikeTag,
isVueCustomBlock,
forceBreakContent,
shouldPreserveContent,
} from "../utils/index.js";
import { printChildren } from "./children.js";
import {
printOpeningTagPrefix,
printOpeningTag,
printClosingTagSuffix,
printClosingTag,
needsToBorrowPrevClosingTagEndMarker,
needsToBorrowLastChildClosingTagEndMarker,
needsToBorrowPrevClosingTagEndMarker,
printClosingTag,
printClosingTagSuffix,
printOpeningTag,
printOpeningTagPrefix,
} from "./tag.js";
import { printChildren } from "./children.js";

function printElement(path, options, print) {
const { node } = path;
@@ -60,7 +60,8 @@ function printElement(path, options, print) {
*/
const shouldHugContent =
node.children.length === 1 &&
node.firstChild.type === "interpolation" &&
(node.firstChild.type === "interpolation" ||
node.firstChild.type === "angularIcuExpression") &&
node.firstChild.isLeadingSpaceSensitive &&
!node.firstChild.hasLeadingSpaces &&
node.lastChild.isTrailingSpaceSensitive &&
35 changes: 20 additions & 15 deletions src/language-html/print/tag.js
Original file line number Diff line number Diff line change
@@ -3,23 +3,24 @@
*/

import assert from "node:assert";
import isNonEmptyArray from "../../utils/is-non-empty-array.js";

import {
hardline,
indent,
join,
line,
softline,
hardline,
} from "../../document/builders.js";
import { replaceEndOfLine } from "../../document/utils.js";
import { locStart, locEnd } from "../loc.js";
import isNonEmptyArray from "../../utils/is-non-empty-array.js";
import { locEnd, locStart } from "../loc.js";
import {
isTextLikeNode,
getLastDescendant,
isPreLikeNode,
hasPrettierIgnore,
shouldPreserveContent,
isPreLikeNode,
isTextLikeNode,
isVueSfcBlock,
shouldPreserveContent,
} from "../utils/index.js";

function printClosingTag(node, options) {
@@ -97,6 +98,8 @@ function printClosingTagEndMarker(node, options) {
return "]><!-->";
case "interpolation":
return "}}";
case "angularIcuExpression":
return "}";
case "element":
if (node.isSelfClosing) {
return "/>";
@@ -345,6 +348,8 @@ function printOpeningTagStartMarker(node) {
return "{{";
case "docType":
return node.value === "html" ? "<!doctype" : "<!DOCTYPE";
case "angularIcuExpression":
return "{";
case "element":
if (node.condition) {
return `<!--[if ${node.condition}]><!--><${node.rawName}`;
@@ -371,20 +376,20 @@ function printOpeningTagEndMarker(node) {
}

export {
needsToBorrowLastChildClosingTagEndMarker,
needsToBorrowNextOpeningTagStartMarker,
needsToBorrowParentClosingTagStartMarker,
needsToBorrowParentOpeningTagEndMarker,
needsToBorrowPrevClosingTagEndMarker,
printClosingTag,
printClosingTagEnd,
printClosingTagEndMarker,
printClosingTagStart,
printClosingTagStartMarker,
printClosingTagEndMarker,
printClosingTagSuffix,
printClosingTagEnd,
needsToBorrowLastChildClosingTagEndMarker,
needsToBorrowParentClosingTagStartMarker,
needsToBorrowPrevClosingTagEndMarker,
printOpeningTag,
printOpeningTagStart,
printOpeningTagEndMarker,
printOpeningTagPrefix,
printOpeningTagStart,
printOpeningTagStartMarker,
printOpeningTagEndMarker,
needsToBorrowNextOpeningTagStartMarker,
needsToBorrowParentOpeningTagEndMarker,
};
35 changes: 22 additions & 13 deletions src/language-html/printer-html.js
Original file line number Diff line number Diff line change
@@ -4,28 +4,32 @@

import { fill, group, hardline } from "../document/builders.js";
import { cleanDoc, replaceEndOfLine } from "../document/utils.js";
import UnexpectedNodeError from "../utils/unexpected-node-error.js";
import getPreferredQuote from "../utils/get-preferred-quote.js";
import htmlWhitespaceUtils from "../utils/html-whitespace-utils.js";
import UnexpectedNodeError from "../utils/unexpected-node-error.js";
import clean from "./clean.js";
import { unescapeQuoteEntities, getTextValueParts } from "./utils/index.js";
import preprocess from "./print-preprocess.js";
import { insertPragma } from "./pragma.js";
import { locStart, locEnd } from "./loc.js";
import embed from "./embed.js";
import getVisitorKeys from "./get-visitor-keys.js";
import { locEnd, locStart } from "./loc.js";
import { insertPragma } from "./pragma.js";
import {
printAngularControlFlowBlock,
printAngularControlFlowBlockParameters,
} from "./print/angular-control-flow-block.js";
import {
printAngularIcuCase,
printAngularIcuExpression,
} from "./print/angular-icu-expression.js";
import { printChildren } from "./print/children.js";
import { printElement } from "./print/element.js";
import {
printClosingTagSuffix,
printClosingTagEnd,
printClosingTagSuffix,
printOpeningTagPrefix,
printOpeningTagStart,
} from "./print/tag.js";
import { printElement } from "./print/element.js";
import { printChildren } from "./print/children.js";
import {
printAngularControlFlowBlock,
printAngularControlFlowBlockParameters,
} from "./print/angular-control-flow-block.js";
import getVisitorKeys from "./get-visitor-keys.js";
import preprocess from "./print-preprocess.js";
import { getTextValueParts, unescapeQuoteEntities } from "./utils/index.js";

function genericPrint(path, options, print) {
const { node } = path;
@@ -49,6 +53,11 @@ function genericPrint(path, options, print) {
case "angularControlFlowBlockParameter":
return htmlWhitespaceUtils.trim(node.expression);

case "angularIcuExpression":
return printAngularIcuExpression(path, options, print);
case "angularIcuCase":
return printAngularIcuCase(path, options, print);

case "ieConditionalStartComment":
case "ieConditionalEndComment":
return [printOpeningTagStart(node), printClosingTagEnd(node)];
34 changes: 17 additions & 17 deletions src/language-html/utils/index.js
Original file line number Diff line number Diff line change
@@ -2,17 +2,17 @@
* @typedef {import("../../common/ast-path.js").default} AstPath
*/

import { hardline, join, line } from "../../document/builders.js";
import { replaceEndOfLine } from "../../document/utils.js";
import isFrontMatter from "../../utils/front-matter/is-front-matter.js";
import htmlWhitespaceUtils from "../../utils/html-whitespace-utils.js";
import inferParser from "../../utils/infer-parser.js";
import { line, hardline, join } from "../../document/builders.js";
import { replaceEndOfLine } from "../../document/utils.js";
import {
CSS_DISPLAY_TAGS,
CSS_DISPLAY_DEFAULT,
CSS_WHITE_SPACE_TAGS,
CSS_DISPLAY_TAGS,
CSS_WHITE_SPACE_DEFAULT,
CSS_WHITE_SPACE_TAGS,
} from "../constants.evaluate.js";
import htmlWhitespaceUtils from "../../utils/html-whitespace-utils.js";
import isUnknownNamespace from "./is-unknown-namespace.js";

const htmlTrimLeadingBlankLines = (string) =>
@@ -622,38 +622,38 @@ function isVueScriptTag(node, options) {
}

export {
htmlTrimPreserveIndentation,
getLeadingAndTrailingHtmlWhitespace,
canHaveInterpolation,
dedentString,
forceBreakChildren,
forceBreakContent,
forceNextEmptyLine,
getLastDescendant,
getLeadingAndTrailingHtmlWhitespace,
getNodeCssStyleDisplay,
getNodeCssStyleWhiteSpace,
getTextValueParts,
getUnescapedAttributeValue,
hasPrettierIgnore,
htmlTrimPreserveIndentation,
htmlWhitespaceUtils,
inferElementParser,
isVueCustomBlock,
isVueNonHtmlBlock,
isVueScriptTag,
isVueSlotAttribute,
isVueSfcBindingsAttribute,
isVueSfcBlock,
isDanglingSpaceSensitiveNode,
isIndentationSensitiveNode,
isLeadingSpaceSensitiveNode,
isPreLikeNode,
isScriptLikeTag,
isTextLikeNode,
isTrailingSpaceSensitiveNode,
isWhitespaceSensitiveNode,
isUnknownNamespace,
isVueCustomBlock,
isVueNonHtmlBlock,
isVueScriptTag,
isVueSfcBindingsAttribute,
isVueSfcBlock,
isVueSlotAttribute,
isWhitespaceSensitiveNode,
preferHardlineAsLeadingSpaces,
preferHardlineAsTrailingSpaces,
shouldPreserveContent,
unescapeQuoteEntities,
getTextValueParts,
htmlWhitespaceUtils,
getUnescapedAttributeValue,
};
2 changes: 2 additions & 0 deletions src/language-html/visitor-keys.js
Original file line number Diff line number Diff line change
@@ -14,6 +14,8 @@ const visitorKeys = {
angularControlFlowBlock: ["children", "parameters"],
angularControlFlowBlockParameters: ["children"],
angularControlFlowBlockParameter: [],
angularIcuExpression: ["cases"],
angularIcuCase: ["expression"],
};

export default visitorKeys;
2 changes: 1 addition & 1 deletion src/language-js/clean.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import isBlockComment from "./utils/is-block-comment.js";
import { isArrayOrTupleExpression } from "./utils/index.js";
import isBlockComment from "./utils/is-block-comment.js";

const ignoredProperties = new Set([
"range",
60 changes: 23 additions & 37 deletions src/language-js/comments/handle-comments.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,27 @@
import hasNewline from "../../utils/has-newline.js";
import getNextNonSpaceNonCommentCharacter from "../../utils/get-next-non-space-non-comment-character.js";
import getNextNonSpaceNonCommentCharacterIndex from "../../utils/get-next-non-space-non-comment-character-index.js";
import hasNewlineInRange from "../../utils/has-newline-in-range.js";
import isNonEmptyArray from "../../utils/is-non-empty-array.js";
import {
addDanglingComment,
addLeadingComment,
addTrailingComment,
addDanglingComment,
} from "../../main/comments/utils.js";
import getNextNonSpaceNonCommentCharacter from "../../utils/get-next-non-space-non-comment-character.js";
import getNextNonSpaceNonCommentCharacterIndex from "../../utils/get-next-non-space-non-comment-character-index.js";
import hasNewline from "../../utils/has-newline.js";
import hasNewlineInRange from "../../utils/has-newline-in-range.js";
import isNonEmptyArray from "../../utils/is-non-empty-array.js";
import { locEnd, locStart } from "../loc.js";
import {
getFunctionParameters,
isPrettierIgnoreComment,
isCallLikeExpression,
createTypeCheckFunction,
getCallArguments,
getFunctionParameters,
isCallExpression,
isCallLikeExpression,
isIntersectionType,
isLineComment,
isMemberExpression,
isObjectProperty,
isLineComment,
markerForIfWithoutBlockAndSameLineComment,
createTypeCheckFunction,
isPrettierIgnoreComment,
isUnionType,
} from "../utils/index.js";
import { locStart, locEnd } from "../loc.js";
import isBlockComment from "../utils/is-block-comment.js";
import isTypeCastComment from "../utils/is-type-cast-comment.js";

@@ -200,7 +201,7 @@ function handleIfStatementComments({
addTrailingComment(precedingNode, comment);
} else {
const isSingleLineComment =
comment.type === "SingleLine" ||
isLineComment(comment) ||
comment.loc.start.line === comment.loc.end.line;
const isSameLineComment =
comment.loc.start.line === precedingNode.loc.start.line;
@@ -209,13 +210,7 @@ function handleIfStatementComments({
// if (cond1) expr1; // comment A
// else if (cond2) expr2; // comment A
// else expr3;
addDanglingComment(
precedingNode,
comment,
precedingNode.type === "ExpressionStatement"
? markerForIfWithoutBlockAndSameLineComment
: undefined,
);
addTrailingComment(precedingNode, comment);
} else {
addDanglingComment(enclosingNode, comment);
}
@@ -702,10 +697,7 @@ function handleUnionTypeComments({
enclosingNode,
followingNode,
}) {
if (
enclosingNode?.type === "UnionTypeAnnotation" ||
enclosingNode?.type === "TSUnionType"
) {
if (isUnionType(enclosingNode)) {
if (isPrettierIgnoreComment(comment)) {
followingNode.prettierIgnore = true;
comment.unignore = true;
@@ -717,11 +709,7 @@ function handleUnionTypeComments({
return false;
}

if (
(followingNode?.type === "UnionTypeAnnotation" ||
followingNode?.type === "TSUnionType") &&
isPrettierIgnoreComment(comment)
) {
if (isUnionType(followingNode) && isPrettierIgnoreComment(comment)) {
followingNode.types[0].prettierIgnore = true;
comment.unignore = true;
}
@@ -962,15 +950,13 @@ function handleLastUnionElementInExpression({
followingNode,
}) {
if (
precedingNode &&
(precedingNode.type === "TSUnionType" ||
precedingNode.type === "UnionTypeAnnotation") &&
isUnionType(precedingNode) &&
(((enclosingNode.type === "TSArrayType" ||
enclosingNode.type === "ArrayTypeAnnotation") &&
followingNode === undefined) ||
enclosingNode.type === "TSIntersectionType" ||
enclosingNode.type === "IntersectionTypeAnnotation")
!followingNode) ||
isIntersectionType(enclosingNode))
) {
// @ts-expect-error -- types exits in TSUnionType and UnionTypeAnnotation
addTrailingComment(precedingNode.types.at(-1), comment);
return true;
}
@@ -1035,7 +1021,7 @@ const isRealFunctionLikeNode = createTypeCheckFunction([
]);

export {
handleOwnLineComment as ownLine,
handleEndOfLineComment as endOfLine,
handleOwnLineComment as ownLine,
handleRemainingComment as remaining,
};
12 changes: 5 additions & 7 deletions src/language-js/comments/printer-methods.js
Original file line number Diff line number Diff line change
@@ -3,6 +3,7 @@ import {
getFunctionParameters,
hasNodeIgnoreComment,
isJsxElement,
isUnionType,
} from "../utils/index.js";

/**
@@ -71,14 +72,11 @@ function willPrintOwnComments(path) {
(parent &&
(parent.type === "JSXSpreadAttribute" ||
parent.type === "JSXSpreadChild" ||
parent.type === "UnionTypeAnnotation" ||
parent.type === "TSUnionType" ||
isUnionType(parent) ||
((parent.type === "ClassDeclaration" ||
parent.type === "ClassExpression") &&
parent.superClass === node)))) &&
(!hasNodeIgnoreComment(node) ||
parent.type === "UnionTypeAnnotation" ||
parent.type === "TSUnionType")
(!hasNodeIgnoreComment(node) || isUnionType(parent))
);
}

@@ -91,7 +89,7 @@ function isGap(text, { parser }) {
}
}

export * as handleComments from "./handle-comments.js";
export { printComment } from "../print/comment.js";
export { default as isBlockComment } from "../utils/is-block-comment.js";
export { canAttachComment, getCommentChildNodes, willPrintOwnComments, isGap };
export * as handleComments from "./handle-comments.js";
export { canAttachComment, getCommentChildNodes, isGap, willPrintOwnComments };
4 changes: 2 additions & 2 deletions src/language-js/embed/css.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { hardline, indent, softline } from "../../document/builders.js";
import { cleanDoc, mapDoc, replaceEndOfLine } from "../../document/utils.js";
import isNonEmptyArray from "../../utils/is-non-empty-array.js";
import { indent, hardline, softline } from "../../document/builders.js";
import { mapDoc, replaceEndOfLine, cleanDoc } from "../../document/utils.js";
import { printTemplateExpressions } from "../print/template-literal.js";
import { isAngularComponentStyles } from "./utils.js";

2 changes: 1 addition & 1 deletion src/language-js/embed/graphql.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { indent, join, hardline } from "../../document/builders.js";
import { hardline, indent, join } from "../../document/builders.js";
import {
escapeTemplateCharacters,
printTemplateExpressions,
8 changes: 4 additions & 4 deletions src/language-js/embed/html.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import {
indent,
line,
hardline,
group,
hardline,
indent,
label,
line,
} from "../../document/builders.js";
import { mapDoc } from "../../document/utils.js";
import {
printTemplateExpressions,
uncookTemplateElementValue,
} from "../print/template-literal.js";
import { isAngularComponentTemplate, hasLanguageComment } from "./utils.js";
import { hasLanguageComment, isAngularComponentTemplate } from "./utils.js";

// The counter is needed to distinguish nested embeds.
let htmlTemplateLiteralCounter = 0;
4 changes: 2 additions & 2 deletions src/language-js/embed/markdown.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import {
dedentToRoot,
indent,
softline,
literalline,
dedentToRoot,
softline,
} from "../../document/builders.js";
import { escapeTemplateCharacters } from "../print/template-literal.js";

6 changes: 3 additions & 3 deletions src/language-js/embed/utils.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import {
hasComment,
CommentCheckFlags,
isObjectProperty,
hasComment,
isArrayOrTupleExpression,
isObjectProperty,
} from "../utils/index.js";

const angularComponentObjectExpressionPredicates = [
@@ -84,8 +84,8 @@ function isAsConstExpression(node) {
}

export {
hasLanguageComment,
isAngularComponentStyles,
isAngularComponentTemplate,
hasLanguageComment,
isAsConstExpression,
};
1 change: 1 addition & 0 deletions src/language-js/languages.evaluate.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import linguistLanguages from "linguist-languages";

import createLanguage from "../utils/create-language.js";

const languages = [
2 changes: 1 addition & 1 deletion src/language-js/loc.js
Original file line number Diff line number Diff line change
@@ -49,4 +49,4 @@ function hasSameLoc(nodeA, nodeB) {
return hasSameLocStart(nodeA, nodeB) && hasSameLocEnd(nodeA, nodeB);
}

export { locStart, locEnd, hasSameLocStart, hasSameLoc };
export { hasSameLoc, hasSameLocStart, locEnd, locStart };
14 changes: 7 additions & 7 deletions src/language-js/needs-parens.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
import isNonEmptyArray from "../utils/is-non-empty-array.js";
import {
createTypeCheckFunction,
getFunctionParameters,
getLeftSidePathName,
getPrecedence,
hasNakedLeftSide,
hasNode,
isArrayOrTupleExpression,
isBinaryCastExpression,
isBitwiseOperator,
startsWithNoLookaheadToken,
shouldFlatten,
getPrecedence,
isCallExpression,
isMemberExpression,
isObjectProperty,
isBinaryCastExpression,
isArrayOrTupleExpression,
isObjectOrRecordExpression,
createTypeCheckFunction,
isObjectProperty,
shouldFlatten,
startsWithNoLookaheadToken,
} from "./utils/index.js";

function needsParens(path, options) {
3 changes: 2 additions & 1 deletion src/language-js/parse/acorn.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { Parser as AcornParser } from "acorn";
import acornJsx from "acorn-jsx";

import createError from "../../common/parser-create-error.js";
import tryCombinations from "../../utils/try-combinations.js";
import createParser from "./utils/create-parser.js";
import postprocess from "./postprocess/index.js";
import createParser from "./utils/create-parser.js";
import getSourceType from "./utils/get-source-type.js";

/** @type {import("acorn").Options} */
3 changes: 2 additions & 1 deletion src/language-js/parse/angular.js
Original file line number Diff line number Diff line change
@@ -4,7 +4,8 @@ import {
parseInterpolationExpression,
parseTemplateBindings,
} from "angular-estree-parser";
import { locStart, locEnd } from "../loc.js";

import { locEnd, locStart } from "../loc.js";

/**
* @param {parseAction | parseBinding | parseInterpolationExpression | parseTemplateBindings} parseMethod
7 changes: 4 additions & 3 deletions src/language-js/parse/babel.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { parse as babelParse, parseExpression } from "@babel/parser";

import getNextNonSpaceNonCommentCharacterIndex from "../../utils/get-next-non-space-non-comment-character-index.js";
import tryCombinations from "../../utils/try-combinations.js";
import getShebang from "../utils/get-shebang.js";
import getNextNonSpaceNonCommentCharacterIndex from "../../utils/get-next-non-space-non-comment-character-index.js";
import createParser from "./utils/create-parser.js";
import createBabelParseError from "./utils/create-babel-parse-error.js";
import postprocess from "./postprocess/index.js";
import createBabelParseError from "./utils/create-babel-parse-error.js";
import createParser from "./utils/create-parser.js";
import getSourceType from "./utils/get-source-type.js";
import wrapBabelExpression from "./utils/wrap-babel-expression.js";

3 changes: 2 additions & 1 deletion src/language-js/parse/espree.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { parse as espreeParse } from "espree";

import createError from "../../common/parser-create-error.js";
import tryCombinations from "../../utils/try-combinations.js";
import createParser from "./utils/create-parser.js";
import postprocess from "./postprocess/index.js";
import createParser from "./utils/create-parser.js";
import getSourceType from "./utils/get-source-type.js";

/** @type {import("espree").Options} */
3 changes: 2 additions & 1 deletion src/language-js/parse/flow.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import flowParser from "flow-parser";

import createError from "../../common/parser-create-error.js";
import postprocess from "./postprocess/index.js";
import createParser from "./utils/create-parser.js";
import replaceHashbang from "./utils/replace-hashbang.js";
import postprocess from "./postprocess/index.js";

// https://github.com/facebook/flow/tree/main/packages/flow-parser#options
// Keep this sync with `/scripts/sync-flow-test.js`
3 changes: 2 additions & 1 deletion src/language-js/parse/meriyah.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { parse as meriyahParse } from "meriyah";

import createError from "../../common/parser-create-error.js";
import tryCombinations from "../../utils/try-combinations.js";
import createParser from "./utils/create-parser.js";
import postprocess from "./postprocess/index.js";
import createParser from "./utils/create-parser.js";
import getSourceType from "./utils/get-source-type.js";

// https://github.com/meriyah/meriyah/blob/4676f60b6c149d7082bde2c9147f9ae2359c8075/src/parser.ts#L185
4 changes: 2 additions & 2 deletions src/language-js/parse/postprocess/index.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { locStart, locEnd } from "../../loc.js";
import isTypeCastComment from "../../utils/is-type-cast-comment.js";
import isNonEmptyArray from "../../../utils/is-non-empty-array.js";
import { locEnd, locStart } from "../../loc.js";
import isBlockComment from "../../utils/is-block-comment.js";
import isIndentableBlockComment from "../../utils/is-indentable-block-comment.js";
import isTypeCastComment from "../../utils/is-type-cast-comment.js";
import visitNode from "./visit-node.js";

/**
3 changes: 2 additions & 1 deletion src/language-js/parse/typescript.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { parse as parseTypeScript } from "@typescript-eslint/typescript-estree";

import createError from "../../common/parser-create-error.js";
import tryCombinations from "../../utils/try-combinations.js";
import postprocess from "./postprocess/index.js";
import createParser from "./utils/create-parser.js";
import replaceHashbang from "./utils/replace-hashbang.js";
import postprocess from "./postprocess/index.js";

/** @type {import("@typescript-eslint/typescript-estree").TSESTreeOptions} */
const baseParseOptions = {
2 changes: 1 addition & 1 deletion src/language-js/parse/utils/create-parser.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { locEnd, locStart } from "../../loc.js";
import { hasPragma } from "../../pragma.js";
import { locStart, locEnd } from "../../loc.js";

function createParser(options) {
options = typeof options === "function" ? { parse: options } : options;
3 changes: 2 additions & 1 deletion src/language-js/pragma.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { parseWithComments, strip, extract, print } from "jest-docblock";
import { extract, parseWithComments, print, strip } from "jest-docblock";

import { normalizeEndOfLine } from "../common/end-of-line.js";
import getShebang from "./utils/get-shebang.js";

10 changes: 5 additions & 5 deletions src/language-js/print/angular.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { join, line, group } from "../../document/builders.js";
import { group, join, line } from "../../document/builders.js";
import UnexpectedNodeError from "../../utils/unexpected-node-error.js";
import {
hasNode,
hasComment,
getComments,
createTypeCheckFunction,
getComments,
hasComment,
hasNode,
} from "../utils/index.js";
import { printBinaryishExpression } from "./binaryish.js";

@@ -66,7 +66,7 @@ function printAngular(path, options, print) {
(node.key.name === "then" ||
node.key.name === "else" ||
node.key.name === "as")) ||
(index === 2 &&
((index === 2 || index === 3) &&
((node.key.name === "else" &&
parent.body[index - 1].type === "NGMicrosyntaxKeyedExpression" &&
parent.body[index - 1].key.name === "then") ||
25 changes: 12 additions & 13 deletions src/language-js/print/array.js
Original file line number Diff line number Diff line change
@@ -1,28 +1,27 @@
import { printDanglingComments } from "../../main/comments/print.js";
import {
line,
softline,
hardline,
fill,
group,
indent,
hardline,
ifBreak,
fill,
indent,
line,
softline,
} from "../../document/builders.js";
import { printDanglingComments } from "../../main/comments/print.js";
import hasNewline from "../../utils/has-newline.js";
import isNextLineEmptyAfterIndex from "../../utils/is-next-line-empty.js";
import skipInlineComment from "../../utils/skip-inline-comment.js";
import skipTrailingComment from "../../utils/skip-trailing-comment.js";
import { locEnd, locStart } from "../loc.js";
import {
shouldPrintComma,
hasComment,
CommentCheckFlags,
isNumericLiteral,
isSignedNumericLiteral,
hasComment,
isArrayOrTupleExpression,
isNumericLiteral,
isObjectOrRecordExpression,
isSignedNumericLiteral,
shouldPrintComma,
} from "../utils/index.js";
import { locStart, locEnd } from "../loc.js";

import { printOptionalToken } from "./misc.js";
import { printTypeAnnotationProperty } from "./type-annotation.js";

@@ -222,4 +221,4 @@ function printArrayElementsConcisely(path, options, print, trailingComma) {
return fill(parts);
}

export { printArray, isConciselyPrintedArray };
export { isConciselyPrintedArray, printArray };
34 changes: 17 additions & 17 deletions src/language-js/print/arrow-function.js
Original file line number Diff line number Diff line change
@@ -1,35 +1,35 @@
import { ArgExpansionBailout } from "../../common/errors.js";
import {
printDanglingComments,
printCommentsSeparately,
} from "../../main/comments/print.js";
import getNextNonSpaceNonCommentCharacterIndex from "../../utils/get-next-non-space-non-comment-character-index.js";
import {
line,
softline,
group,
indent,
ifBreak,
join,
indent,
indentIfBreak,
join,
line,
softline,
} from "../../document/builders.js";
import { removeLines, willBreak } from "../../document/utils.js";
import { ArgExpansionBailout } from "../../common/errors.js";
import {
printCommentsSeparately,
printDanglingComments,
} from "../../main/comments/print.js";
import getNextNonSpaceNonCommentCharacterIndex from "../../utils/get-next-non-space-non-comment-character-index.js";
import { locEnd } from "../loc.js";
import {
getFunctionParameters,
hasComment,
hasLeadingOwnLineComment,
isArrayOrTupleExpression,
isBinaryish,
isCallLikeExpression,
isJsxElement,
isObjectOrRecordExpression,
isTemplateOnItsOwnLine,
shouldPrintComma,
startsWithNoLookaheadToken,
isBinaryish,
hasComment,
isCallLikeExpression,
isArrayOrTupleExpression,
isObjectOrRecordExpression,
} from "../utils/index.js";
import { locEnd } from "../loc.js";
import { printFunctionParameters } from "./function-parameters.js";
import { printReturnType, shouldPrintParamsWithoutParens } from "./function.js";
import { printFunctionParameters } from "./function-parameters.js";

/**
* @typedef {import("../../common/ast-path.js").default} AstPath
63 changes: 45 additions & 18 deletions src/language-js/print/assignment.js
Original file line number Diff line number Diff line change
@@ -1,28 +1,34 @@
import isNonEmptyArray from "../../utils/is-non-empty-array.js";
import getStringWidth from "../../utils/get-string-width.js";
import {
line,
group,
indent,
indentIfBreak,
line,
lineSuffixBoundary,
} from "../../document/builders.js";
import { cleanDoc, willBreak, canBreak } from "../../document/utils.js";
import { canBreak, cleanDoc, willBreak } from "../../document/utils.js";
import getStringWidth from "../../utils/get-string-width.js";
import isNonEmptyArray from "../../utils/is-non-empty-array.js";
import {
createTypeCheckFunction,
getCallArguments,
hasLeadingOwnLineComment,
isBinaryish,
isStringLiteral,
isNumericLiteral,
isCallExpression,
isMemberExpression,
getCallArguments,
isIntersectionType,
isLoneShortArgument,
isMemberExpression,
isNumericLiteral,
isObjectProperty,
createTypeCheckFunction,
isStringLiteral,
isUnionType,
} from "../utils/index.js";
import { shouldInlineLogicalExpression } from "./binaryish.js";
import { printCallExpression } from "./call-expression.js";

/**
* @typedef {import("../../common/ast-path.js").default} AstPath
*/

function printAssignment(
path,
options,
@@ -136,6 +142,7 @@ function chooseLayout(path, options, print, leftDoc, rightPropertyName) {
rightNode.callee.name === "require") ||
// do not put values on a separate line from the key in json
options.parser === "json5" ||
options.parser === "jsonc" ||
options.parser === "json"
) {
return "never-break-after-operator";
@@ -145,7 +152,6 @@ function chooseLayout(path, options, print, leftDoc, rightPropertyName) {

if (
isComplexDestructuring(node) ||
isComplexTypeAliasParams(node) ||
hasComplexTypeAnnotation(node) ||
(isArrowFunctionVariableDeclarator(node) && canBreakLeftDoc)
) {
@@ -164,6 +170,10 @@ function chooseLayout(path, options, print, leftDoc, rightPropertyName) {
return "break-after-operator";
}

if (isComplexTypeAliasParams(node)) {
return "break-lhs";
}

if (
!canBreakLeftDoc &&
(hasShortKey ||
@@ -192,7 +202,10 @@ function shouldBreakAfterOperator(path, options, print, hasShortKey) {
return true;
case "TSConditionalType":
case "ConditionalTypeAnnotation":
if (!options.experimentalTernaries) {
if (
!options.experimentalTernaries &&
!shouldBreakBeforeConditionalType(rightNode)
) {
break;
}
return true;
@@ -411,10 +424,8 @@ function isCallExpressionWithComplexTypeArguments(node, print) {
if (typeArgs.length === 1) {
const firstArg = typeArgs[0];
if (
firstArg.type === "TSUnionType" ||
firstArg.type === "UnionTypeAnnotation" ||
firstArg.type === "TSIntersectionType" ||
firstArg.type === "IntersectionTypeAnnotation" ||
isUnionType(firstArg) ||
isIntersectionType(firstArg) ||
firstArg.type === "TSTypeLiteral" ||
firstArg.type === "ObjectTypeAnnotation"
) {
@@ -435,9 +446,25 @@ function getTypeArgumentsFromCallExpression(node) {
return (node.typeParameters ?? node.typeArguments)?.params;
}

function shouldBreakBeforeConditionalType(node) {
function isGeneric(subNode) {
switch (subNode.type) {
case "FunctionTypeAnnotation":
case "GenericTypeAnnotation":
case "TSFunctionType":
case "TSTypeReference":
return Boolean(subNode.typeParameters);
default:
return false;
}
}

return isGeneric(node.checkType) || isGeneric(node.extendsType);
}

export {
printVariableDeclarator,
printAssignmentExpression,
printAssignment,
isArrowFunctionVariableDeclarator,
printAssignment,
printAssignmentExpression,
printVariableDeclarator,
};
24 changes: 12 additions & 12 deletions src/language-js/print/binaryish.js
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
import { printComments } from "../../main/comments/print.js";
import { DOC_TYPE_FILL, DOC_TYPE_GROUP } from "../../document/constants.js";
import {
join,
line,
softline,
align,
group,
indent,
align,
indentIfBreak,
join,
line,
softline,
} from "../../document/builders.js";
import { DOC_TYPE_FILL, DOC_TYPE_GROUP } from "../../document/constants.js";
import { cleanDoc, getDocParts } from "../../document/utils.js";
import { printComments } from "../../main/comments/print.js";
import {
CommentCheckFlags,
hasComment,
hasLeadingOwnLineComment,
isArrayOrTupleExpression,
isBinaryish,
isJsxElement,
shouldFlatten,
hasComment,
CommentCheckFlags,
isCallExpression,
isJsxElement,
isMemberExpression,
isObjectProperty,
isArrayOrTupleExpression,
isObjectOrRecordExpression,
isObjectProperty,
shouldFlatten,
} from "../utils/index.js";

/** @typedef {import("../../document/builders.js").Doc} Doc */
4 changes: 2 additions & 2 deletions src/language-js/print/block.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { hardline, indent } from "../../document/builders.js";
import { printDanglingComments } from "../../main/comments/print.js";
import isNonEmptyArray from "../../utils/is-non-empty-array.js";
import { hardline, indent } from "../../document/builders.js";
import {
hasComment,
CommentCheckFlags,
hasComment,
isNextLineEmpty,
} from "../utils/index.js";
import { printStatementSequence } from "./statement.js";
52 changes: 25 additions & 27 deletions src/language-js/print/call-arguments.js
Original file line number Diff line number Diff line change
@@ -1,42 +1,40 @@
import { ArgExpansionBailout } from "../../common/errors.js";
import {
breakParent,
conditionalGroup,
group,
hardline,
ifBreak,
indent,
line,
softline,
} from "../../document/builders.js";
import { willBreak } from "../../document/utils.js";
import { printDanglingComments } from "../../main/comments/print.js";
import {
CommentCheckFlags,
getCallArguments,
getCallArgumentSelector,
getFunctionParameters,
hasComment,
CommentCheckFlags,
isArrayOrTupleExpression,
isBinaryCastExpression,
isBinaryish,
isCallExpression,
isCallLikeExpression,
isFunctionCompositionArgs,
isJsxElement,
isLongCurriedCallExpression,
shouldPrintComma,
getCallArguments,
iterateCallArgumentsPath,
isNextLineEmpty,
isCallExpression,
isStringLiteral,
isObjectOrRecordExpression,
isObjectProperty,
getCallArgumentSelector,
isSimpleCallArgument,
isBinaryish,
isRegExpLiteral,
isSimpleCallArgument,
isSimpleType,
isCallLikeExpression,
isBinaryCastExpression,
isArrayOrTupleExpression,
isObjectOrRecordExpression,
isStringLiteral,
iterateCallArgumentsPath,
shouldPrintComma,
} from "../utils/index.js";

import {
line,
hardline,
softline,
group,
indent,
conditionalGroup,
ifBreak,
breakParent,
} from "../../document/builders.js";
import { willBreak } from "../../document/utils.js";

import { ArgExpansionBailout } from "../../common/errors.js";
import { isConciselyPrintedArray } from "./array.js";

function printCallArguments(path, options, print) {
12 changes: 8 additions & 4 deletions src/language-js/print/call-expression.js
2 changes: 1 addition & 1 deletion src/language-js/print/cast-expression.js
36 changes: 18 additions & 18 deletions src/language-js/print/class.js
7 changes: 3 additions & 4 deletions src/language-js/print/comment.js
18 changes: 9 additions & 9 deletions src/language-js/print/decorators.js
2 changes: 1 addition & 1 deletion src/language-js/print/enum.js
91 changes: 45 additions & 46 deletions src/language-js/print/estree.js
21 changes: 0 additions & 21 deletions src/language-js/print/expression-statement.js
56 changes: 29 additions & 27 deletions src/language-js/print/flow.js
39 changes: 19 additions & 20 deletions src/language-js/print/function-parameters.js
33 changes: 17 additions & 16 deletions src/language-js/print/function.js
4 changes: 2 additions & 2 deletions src/language-js/print/html-binding.js
12 changes: 6 additions & 6 deletions src/language-js/print/index.js
6 changes: 3 additions & 3 deletions src/language-js/print/interface.js
43 changes: 21 additions & 22 deletions src/language-js/print/jsx.js
6 changes: 3 additions & 3 deletions src/language-js/print/literal.js
12 changes: 6 additions & 6 deletions src/language-js/print/mapped-type.js
69 changes: 47 additions & 22 deletions src/language-js/print/member-chain.js
31 changes: 20 additions & 11 deletions src/language-js/print/member.js
10 changes: 5 additions & 5 deletions src/language-js/print/misc.js
60 changes: 25 additions & 35 deletions src/language-js/print/module.js
25 changes: 12 additions & 13 deletions src/language-js/print/object.js
3 changes: 2 additions & 1 deletion src/language-js/print/property.js
2 changes: 1 addition & 1 deletion src/language-js/print/semicolon.js
13 changes: 3 additions & 10 deletions src/language-js/print/statement.js
64 changes: 45 additions & 19 deletions src/language-js/print/template-literal.js
29 changes: 15 additions & 14 deletions src/language-js/print/ternary-old.js
40 changes: 20 additions & 20 deletions src/language-js/print/ternary.js
96 changes: 53 additions & 43 deletions src/language-js/print/type-annotation.js
28 changes: 14 additions & 14 deletions src/language-js/print/type-parameters.js
61 changes: 30 additions & 31 deletions src/language-js/print/typescript.js
4 changes: 2 additions & 2 deletions src/language-js/printer.js
2 changes: 1 addition & 1 deletion src/language-js/traverse/visitor-keys.evaluate.js
11 changes: 9 additions & 2 deletions src/language-js/utils/create-type-check-function.js
178 changes: 82 additions & 96 deletions src/language-js/utils/index.js
6 changes: 3 additions & 3 deletions src/language-json/languages.evaluate.js
6 changes: 4 additions & 2 deletions src/language-json/parser-json.js
2 changes: 1 addition & 1 deletion src/language-json/printer-estree-json.js
1 change: 1 addition & 0 deletions src/language-markdown/clean.js
2 changes: 1 addition & 1 deletion src/language-markdown/embed.js
2 changes: 1 addition & 1 deletion src/language-markdown/index.js
1 change: 1 addition & 0 deletions src/language-markdown/languages.evaluate.js
2 changes: 1 addition & 1 deletion src/language-markdown/loc.js
2 changes: 1 addition & 1 deletion src/language-markdown/mdx.js
11 changes: 6 additions & 5 deletions src/language-markdown/parser-markdown.js
2 changes: 1 addition & 1 deletion src/language-markdown/pragma.js
2 changes: 1 addition & 1 deletion src/language-markdown/print-whitespace.js
37 changes: 19 additions & 18 deletions src/language-markdown/printer-markdown.js
2 changes: 1 addition & 1 deletion src/language-markdown/unified-plugins/html-to-jsx.js
11 changes: 6 additions & 5 deletions src/language-markdown/utils.js
2 changes: 1 addition & 1 deletion src/language-yaml/index.js
1 change: 1 addition & 0 deletions src/language-yaml/languages.evaluate.js
2 changes: 1 addition & 1 deletion src/language-yaml/loc.js
3 changes: 2 additions & 1 deletion src/language-yaml/parser-yaml.js
2 changes: 1 addition & 1 deletion src/language-yaml/pragma.js
8 changes: 4 additions & 4 deletions src/language-yaml/print/flow-mapping-sequence.js
4 changes: 2 additions & 2 deletions src/language-yaml/print/mapping-item.js
4 changes: 2 additions & 2 deletions src/language-yaml/print/misc.js
36 changes: 18 additions & 18 deletions src/language-yaml/printer-yaml.js
18 changes: 9 additions & 9 deletions src/language-yaml/utils.js
6 changes: 3 additions & 3 deletions src/main/ast-to-doc.js
6 changes: 4 additions & 2 deletions src/main/comments/attach.js
14 changes: 7 additions & 7 deletions src/main/comments/print.js
2 changes: 1 addition & 1 deletion src/main/comments/utils.js
4 changes: 3 additions & 1 deletion src/main/core-options.evaluate.js
24 changes: 12 additions & 12 deletions src/main/core.js
2 changes: 1 addition & 1 deletion src/main/multiparser.js
1 change: 1 addition & 0 deletions src/main/parse.js
22 changes: 11 additions & 11 deletions src/main/parser-and-printer.js
2 changes: 1 addition & 1 deletion src/main/plugins/index.js
49 changes: 26 additions & 23 deletions src/main/plugins/load-plugin.js
7 changes: 6 additions & 1 deletion src/main/range-util.js
20 changes: 7 additions & 13 deletions src/plugins/builtin-plugins-proxy.js
4 changes: 2 additions & 2 deletions src/plugins/estree.js
8 changes: 4 additions & 4 deletions src/standalone.js
2 changes: 1 addition & 1 deletion src/utils/ast-utils.js
1 change: 1 addition & 0 deletions src/utils/get-interpreter.js
4 changes: 3 additions & 1 deletion src/utils/ignore.js
1 change: 1 addition & 0 deletions src/utils/import-from-directory.js
1 change: 1 addition & 0 deletions src/utils/import-from-file.js
1 change: 1 addition & 0 deletions src/utils/is-directory.js
1 change: 1 addition & 0 deletions src/utils/is-file.js
4 changes: 2 additions & 2 deletions src/utils/is-next-line-empty.js
2 changes: 1 addition & 1 deletion src/utils/is-previous-line-empty.js
7 changes: 7 additions & 0 deletions src/utils/print-string.js
28 changes: 14 additions & 14 deletions src/utils/public.js
1 change: 1 addition & 0 deletions src/utils/read-file.js
4 changes: 2 additions & 2 deletions src/utils/skip.js
7 changes: 5 additions & 2 deletions tests/config/format-test.js
2 changes: 1 addition & 1 deletion tests/config/get-prettier.js
7 changes: 4 additions & 3 deletions tests/config/install-prettier.js
9 changes: 5 additions & 4 deletions tests/config/utils/check-parsers.js
3 changes: 2 additions & 1 deletion tests/config/utils/create-snapshot.js
2 changes: 1 addition & 1 deletion tests/config/utils/visualize-range.js
2 changes: 2 additions & 0 deletions tests/dts/unit/cases/index.ts
88 changes: 68 additions & 20 deletions tests/dts/unit/cases/parsers.ts
2 changes: 2 additions & 0 deletions tests/dts/unit/cases/plugins.ts
35 changes: 30 additions & 5 deletions tests/dts/unit/run.js
54 changes: 54 additions & 0 deletions tests/format/angular/control-flow/__snapshots__/jsfmt.spec.js.snap
6 changes: 6 additions & 0 deletions tests/format/angular/control-flow/for.html
15 changes: 15 additions & 0 deletions tests/format/angular/control-flow/ignore.html
198 changes: 198 additions & 0 deletions tests/format/angular/icu-expression/__snapshots__/jsfmt.spec.js.snap
1 change: 1 addition & 0 deletions tests/format/angular/icu-expression/basic-plural-01.html
13 changes: 13 additions & 0 deletions tests/format/angular/icu-expression/basic-plural-02.html
4 changes: 4 additions & 0 deletions tests/format/angular/icu-expression/basic-plural-03.html
3 changes: 3 additions & 0 deletions tests/format/angular/icu-expression/basic-plural-04.html
1 change: 1 addition & 0 deletions tests/format/angular/icu-expression/basic-select-01.html
2 changes: 2 additions & 0 deletions tests/format/angular/icu-expression/basic-select-02.html
5 changes: 5 additions & 0 deletions tests/format/angular/icu-expression/combination-01.html
1 change: 1 addition & 0 deletions tests/format/angular/icu-expression/jsfmt.spec.js
84 changes: 84 additions & 0 deletions tests/format/flow/type-alias/__snapshots__/jsfmt.spec.js.snap
34 changes: 34 additions & 0 deletions tests/format/flow/type-alias/conditional.js
6 changes: 5 additions & 1 deletion tests/format/flow/type-alias/jsfmt.spec.js
18 changes: 15 additions & 3 deletions tests/format/graphql/union-types/__snapshots__/jsfmt.spec.js.snap
2 changes: 2 additions & 0 deletions tests/format/graphql/union-types/union_types.graphql
1 change: 1 addition & 0 deletions tests/format/handlebars/path-expressions/jsfmt.spec.js
10 changes: 10 additions & 0 deletions tests/format/handlebars/path-expressions/keyword-expressions.hbs
11 changes: 11 additions & 0 deletions tests/format/handlebars/path-expressions/literal-expressions.hbs
22 changes: 22 additions & 0 deletions tests/format/handlebars/path-expressions/numeric-expressions.hbs
327 changes: 327 additions & 0 deletions tests/format/html/cursor/__snapshots__/jsfmt.spec.js.snap
10 changes: 10 additions & 0 deletions tests/format/html/cursor/cursor-0.html
15 changes: 15 additions & 0 deletions tests/format/html/cursor/cursor-1.html
9 changes: 9 additions & 0 deletions tests/format/html/cursor/cursor-2.html
9 changes: 9 additions & 0 deletions tests/format/html/cursor/cursor-3.html
15 changes: 15 additions & 0 deletions tests/format/html/cursor/cursor-4.html
9 changes: 9 additions & 0 deletions tests/format/html/cursor/cursor-5.html
18 changes: 18 additions & 0 deletions tests/format/html/cursor/cursor-6.html
16 changes: 16 additions & 0 deletions tests/format/html/cursor/cursor-7.html
9 changes: 9 additions & 0 deletions tests/format/html/cursor/cursor-8.html
1 change: 1 addition & 0 deletions tests/format/html/cursor/jsfmt.spec.js
95 changes: 95 additions & 0 deletions tests/format/html/prettier_ignore/__snapshots__/jsfmt.spec.js.snap
19 changes: 19 additions & 0 deletions tests/format/html/prettier_ignore/issue-15738.html
4 changes: 4 additions & 0 deletions tests/format/html/prettier_ignore/unclosed.html
4 changes: 4 additions & 0 deletions tests/format/html/prettier_ignore/unclosed2.html
189 changes: 189 additions & 0 deletions tests/format/js/chain-expression/__snapshots__/jsfmt.spec.js.snap
8 changes: 8 additions & 0 deletions tests/format/js/chain-expression/issue-15785-1.js
6 changes: 6 additions & 0 deletions tests/format/js/chain-expression/issue-15785-2.js
6 changes: 6 additions & 0 deletions tests/format/js/chain-expression/issue-15785-3.js
4 changes: 4 additions & 0 deletions tests/format/js/chain-expression/test-2.js
6 changes: 6 additions & 0 deletions tests/format/js/chain-expression/test-3.js
22 changes: 22 additions & 0 deletions tests/format/js/chain-expression/test-4.js
117 changes: 117 additions & 0 deletions tests/format/js/cursor/__snapshots__/jsfmt.spec.js.snap
17 changes: 17 additions & 0 deletions tests/format/js/cursor/cursor-11.js
17 changes: 17 additions & 0 deletions tests/format/js/cursor/cursor-12.js
3 changes: 3 additions & 0 deletions tests/format/js/cursor/cursor-13.js
1 change: 1 addition & 0 deletions tests/format/js/cursor/jsfmt.spec.js
93 changes: 80 additions & 13 deletions tests/format/js/if/__snapshots__/jsfmt.spec.js.snap
5 changes: 2 additions & 3 deletions tests/format/js/if/expr_and_same_line_comments.js
9 changes: 9 additions & 0 deletions tests/format/js/if/issue-15168.js
5 changes: 5 additions & 0 deletions tests/format/js/if/non-block.js
20 changes: 20 additions & 0 deletions tests/format/js/method-chain/__snapshots__/jsfmt.spec.js.snap
3 changes: 3 additions & 0 deletions tests/format/js/method-chain/assignment-lhs.js
16 changes: 16 additions & 0 deletions tests/format/js/preserve-line/__snapshots__/jsfmt.spec.js.snap
8 changes: 8 additions & 0 deletions tests/format/js/preserve-line/member-chain.js
56 changes: 44 additions & 12 deletions tests/format/js/strings/__snapshots__/jsfmt.spec.js.snap
10 changes: 10 additions & 0 deletions tests/format/js/strings/template-literals.js
34 changes: 10 additions & 24 deletions tests/format/js/template-literals/__snapshots__/jsfmt.spec.js.snap
3 changes: 3 additions & 0 deletions tests/format/js/ternaries/parenthesis/await-expression.js
7 changes: 7 additions & 0 deletions tests/format/js/ternaries/parenthesis/jsfmt.spec.js
3 changes: 3 additions & 0 deletions tests/format/json/jsonc/quote-props/jsfmt.spec.js
6 changes: 6 additions & 0 deletions tests/format/json/jsonc/quote-props/test.jsonc
2 changes: 2 additions & 0 deletions tests/format/json/jsonc/single-quote/jsfmt.spec.js
6 changes: 6 additions & 0 deletions tests/format/json/jsonc/single-quote/test.jsonc
3 changes: 3 additions & 0 deletions tests/format/json/jsonc/trialing-comma/jsfmt.spec.js
6 changes: 6 additions & 0 deletions tests/format/json/jsonc/trialing-comma/test.jsonc
28 changes: 28 additions & 0 deletions tests/format/json/range/jsonc/__snapshots__/jsfmt.spec.js.snap
8 changes: 8 additions & 0 deletions tests/format/json/range/jsonc/inside-array.jsonc
1 change: 1 addition & 0 deletions tests/format/json/range/jsonc/jsfmt.spec.js
216 changes: 216 additions & 0 deletions tests/format/json/with-comment/__snapshots__/jsfmt.spec.js.snap
2 changes: 2 additions & 0 deletions tests/format/json/with-comment/jsfmt.spec.js
4 changes: 1 addition & 3 deletions tests/format/jsx/text-wrap/__snapshots__/jsfmt.spec.js.snap
8 changes: 8 additions & 0 deletions tests/format/typescript/chain-expression/test2.ts
34 changes: 34 additions & 0 deletions tests/format/typescript/type-alias/conditional.ts
24 changes: 6 additions & 18 deletions tests/format/vue/vue/__snapshots__/jsfmt.spec.js.snap
7 changes: 4 additions & 3 deletions tests/integration/__tests__/__snapshots__/early-exit.js.snap
6 changes: 6 additions & 0 deletions tests/integration/__tests__/__snapshots__/schema.js.snap
8 changes: 5 additions & 3 deletions tests/integration/__tests__/bundle.js
2 changes: 1 addition & 1 deletion tests/integration/__tests__/cache.js
1 change: 1 addition & 0 deletions tests/integration/__tests__/cli.js
2 changes: 2 additions & 0 deletions tests/integration/__tests__/config-invalid.js
1 change: 1 addition & 0 deletions tests/integration/__tests__/config-resolution.js
1 change: 1 addition & 0 deletions tests/integration/__tests__/debug-api.js
1 change: 1 addition & 0 deletions tests/integration/__tests__/doc-trim.js
6 changes: 3 additions & 3 deletions tests/integration/__tests__/doc-utils-clean-doc.js
6 changes: 4 additions & 2 deletions tests/integration/__tests__/file-info.js
1 change: 1 addition & 0 deletions tests/integration/__tests__/format.js
1 change: 1 addition & 0 deletions tests/integration/__tests__/ignore-absolute-path.js
2 changes: 2 additions & 0 deletions tests/integration/__tests__/invalid-ignore.js
1 change: 1 addition & 0 deletions tests/integration/__tests__/line-suffix-boundary.js
2 changes: 1 addition & 1 deletion tests/integration/__tests__/normalize-doc.js
4 changes: 3 additions & 1 deletion tests/integration/__tests__/patterns-dirs.js
11 changes: 11 additions & 0 deletions tests/integration/__tests__/plugin-resolution.js
1 change: 1 addition & 0 deletions tests/integration/__tests__/resolve-config-file.js
2 changes: 1 addition & 1 deletion tests/integration/__tests__/schema.js
5 changes: 3 additions & 2 deletions tests/integration/__tests__/with-parser-inference.js
5 changes: 3 additions & 2 deletions tests/integration/cli-worker.js
3 changes: 2 additions & 1 deletion tests/integration/env.js
6 changes: 6 additions & 0 deletions tests/unit/__snapshots__/visitor-keys.js.snap
1 change: 1 addition & 0 deletions tests/unit/builtin-plugins.js
16 changes: 8 additions & 8 deletions tests/unit/doc-builders.js
2 changes: 1 addition & 1 deletion tests/unit/editorconfig-to-prettier.js
2 changes: 1 addition & 1 deletion tests/unit/errors.js
3 changes: 2 additions & 1 deletion tests/unit/html-element-display-values.js
2 changes: 1 addition & 1 deletion tests/unit/strip-trailing-hardline.js
23 changes: 21 additions & 2 deletions tests/unit/syntax-transform.js
2 changes: 1 addition & 1 deletion tests/unit/traverse-doc.js
4 changes: 2 additions & 2 deletions tests/unit/visitor-keys.js
2 changes: 1 addition & 1 deletion website/blog/2017-12-05-1.9.0.md
2 changes: 1 addition & 1 deletion website/blog/2021-05-09-2.3.0.md
6 changes: 3 additions & 3 deletions website/package.json
5 changes: 2 additions & 3 deletions website/pages/en/index.js
2 changes: 1 addition & 1 deletion website/playground/EditorState.js
17 changes: 8 additions & 9 deletions website/playground/Playground.js
2 changes: 1 addition & 1 deletion website/playground/buttons.js
1 change: 1 addition & 0 deletions website/playground/codeSamples.mjs
2 changes: 1 addition & 1 deletion website/playground/index.js
5 changes: 4 additions & 1 deletion website/playground/markdown.js
1 change: 1 addition & 0 deletions website/playground/sidebar/SidebarOptions.js
2 changes: 1 addition & 1 deletion website/playground/sidebar/options.js
32 changes: 16 additions & 16 deletions website/versioned_docs/version-stable/browser.md
2 changes: 1 addition & 1 deletion website/versioned_docs/version-stable/install.md
3 changes: 1 addition & 2 deletions website/versioned_docs/version-stable/options.md
23 changes: 19 additions & 4 deletions website/versioned_docs/version-stable/rationale.md
5,943 changes: 2,972 additions & 2,971 deletions website/yarn.lock
5,991 changes: 3,028 additions & 2,963 deletions yarn.lock