Merge branch 'main' into next
# Conflicts: # CONTRIBUTING.md # cspell.json # docs/options.md # package.json # scripts/build/bundler.mjs # src/language-css/loc.js # src/language-css/parser-postcss.js # src/language-css/utils/index.js # tests/format/js/arrows-bind/jsfmt.spec.js # tests/format/js/async-do-expressions/jsfmt.spec.js # tests/format/js/bind-expressions/jsfmt.spec.js # tests/format/js/classes/top-level-super/jsfmt.spec.js # tests/format/js/comments-pipeline-own-line/jsfmt.spec.js # tests/format/js/decorator-comments/jsfmt.spec.js # tests/format/js/decorators-export/jsfmt.spec.js # tests/format/js/decorators/jsfmt.spec.js # tests/format/js/do/jsfmt.spec.js # tests/format/js/export-default/escaped/jsfmt.spec.js # tests/format/js/export-extension/jsfmt.spec.js # tests/format/js/export-star/jsfmt.spec.js # tests/format/js/exports/jsfmt.spec.js # tests/format/js/invalid-code/jsfmt.spec.js # tests/format/js/logical-assignment/jsfmt.spec.js # tests/format/js/multiparser-invalid/jsfmt.spec.js # tests/format/js/no-semi-babylon-extensions/jsfmt.spec.js # tests/format/js/object-property-comment/jsfmt.spec.js # tests/format/js/partial-application/jsfmt.spec.js # tests/format/js/pipeline-operator/jsfmt.spec.js # tests/format/js/private-in/jsfmt.spec.js # tests/format/js/record/jsfmt.spec.js # tests/format/js/reserved-word/jsfmt.spec.js # tests/format/js/strings/jsfmt.spec.js # tests/format/js/throw_expressions/jsfmt.spec.js # tests/format/js/trailing-whitespace/jsfmt.spec.js # tests/format/js/v8_intrinsic/jsfmt.spec.js # tests/format/misc/errors/js/literal/jsfmt.spec.js # tests/format/misc/errors/js/object/jsfmt.spec.js # tests/format/misc/errors/js/variable-declarator/jsfmt.spec.js # tests/integration/__tests__/bundle.js # tsconfig.json # yarn.lock
This commit is contained in:
commit
f0b63f3dff
324 files changed
+9187
-2692
No files matched your search
@@ -12,3 +12,4 @@
|
||||
/website/build/
|
||||
/website/static/playground.js
|
||||
/website/static/lib/
|
||||
/vendors/
|
||||
+2
-1
@@ -270,7 +270,7 @@ module.exports = {
|
||||
"prettier-internal-rules/no-node-comments": [
|
||||
"error",
|
||||
{
|
||||
file: "src/language-js/utils.js",
|
||||
file: "src/language-js/utils/index.js",
|
||||
functions: ["hasComment", "getComments"],
|
||||
},
|
||||
"src/language-js/pragma.js",
|
||||
@@ -278,6 +278,7 @@ module.exports = {
|
||||
"src/language-js/parse/babel.js",
|
||||
"src/language-js/parse/meriyah.js",
|
||||
"src/language-js/parse/json.js",
|
||||
"src/language-js/parse/acorn.js",
|
||||
],
|
||||
},
|
||||
},
|
||||
|
||||
@@ -40,6 +40,7 @@ jobs:
|
||||
uses: preactjs/compressed-size-action@2.3.0
|
||||
with:
|
||||
repo-token: "${{ secrets.GITHUB_TOKEN }}"
|
||||
pattern: "./dist/**/*"
|
||||
compression: none
|
||||
|
||||
lint:
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
name: Validate_Vendor_Versions
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- patch-release
|
||||
paths:
|
||||
- "package.json"
|
||||
pull_request:
|
||||
paths:
|
||||
- "package.json"
|
||||
|
||||
jobs:
|
||||
validate-vendor-versions:
|
||||
name: Validate Vendor Versions
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2.4.0
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v2.5.1
|
||||
with:
|
||||
version: "14"
|
||||
cache: "yarn"
|
||||
|
||||
- name: Install Dependencies
|
||||
run: yarn install --frozen-lockfile
|
||||
|
||||
- name: Validate Vendor Versions
|
||||
run: yarn run vendors:validate
|
||||
@@ -11,3 +11,4 @@ coverage/
|
||||
/website/static/lib/
|
||||
/website/static/playground.js
|
||||
.nyc_output
|
||||
/vendors/
|
||||
+1
-1
@@ -48,7 +48,7 @@ function run_spec(
|
||||
Parameters:
|
||||
|
||||
- **`fixtures`**: Must be set to `import.meta` or to an object of the shape `{ importMeta: import.meta, ... }`. The object may have the `snippets` property to specify an array of extra input entries in addition to the files in the current directory. For each input entry (a file or a snippet), `run_spec` configures and runs a number of tests. The main check is that for a given input the output should match the snapshot (for snippets, the expected output can also be specified directly). [Additional checks](#deeper-testing) are controlled by options and environment variables.
|
||||
- **`parsers`**: A list of parser names. The tests verify that the parsers in this list produce the same output. If the list includes `typescript`, then `babel-ts` is included implicitly. If the list includes `babel`, and the current directory is inside `tests/format/js`, then `espree` and `meriyah` are included implicitly.
|
||||
- **`parsers`**: A list of parser names. The tests verify that the parsers in this list produce the same output. If the list includes `typescript`, then `babel-ts` is included implicitly. If the list includes `babel`, and the current directory is inside `tests/format/js`, then `acorn`, `espree`, and `meriyah` are included implicitly.
|
||||
- **`options`**: In addition to Prettier's formatting options, can contain the `errors` property to specify that it's expected that the formatting shouldn't be successful and an error should be thrown for all (`errors: true`) or some combinations of input entries and parsers.
|
||||
|
||||
The implementation of `run_spec` can be found in [`tests/config/format-test.js`](tests/config/format-test.js).
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||

|
||||

|
||||
|
||||
<h2 align="center">Opinionated Code Formatter</h2>
|
||||
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
#### Preserve empty line in CSS paren groups (#12210 by @duailibe)
|
||||
|
||||
<!-- Optional description if it makes sense. -->
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
```css
|
||||
/* Input */
|
||||
$colours: (
|
||||
"text": $light-100,
|
||||
|
||||
"background-primary": $dark-300,
|
||||
"background-secondary": $dark-200,
|
||||
"background-tertiary": $dark-100
|
||||
);
|
||||
|
||||
/* Prettier stable */
|
||||
$colours: (
|
||||
"text": $light-100,
|
||||
"background-primary": $dark-300,
|
||||
"background-secondary": $dark-200,
|
||||
"background-tertiary": $dark-100
|
||||
);
|
||||
|
||||
/* Prettier main */
|
||||
$colours: (
|
||||
"text": $light-100,
|
||||
|
||||
"background-primary": $dark-300,
|
||||
"background-secondary": $dark-200,
|
||||
"background-tertiary": $dark-100
|
||||
);
|
||||
```
|
||||
@@ -0,0 +1,18 @@
|
||||
#### Print end-of-line comment for `continue`/`break` statements (#12075 by @sosukesuzuki)
|
||||
|
||||
<!-- Optional description if it makes sense. -->
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
```jsx
|
||||
// Input
|
||||
for (;;) continue // comment
|
||||
;
|
||||
|
||||
// Prettier stable
|
||||
Error: Comment "comment" was not printed. Please report this error!
|
||||
|
||||
// Prettier main
|
||||
for (;;)
|
||||
continue; // comment
|
||||
|
||||
```
|
||||
@@ -0,0 +1,40 @@
|
||||
#### Inline `await` expressions in JSX (#12088 & #12109 by @j-f1)
|
||||
|
||||
`await` expressions in JSX are now inlined if their argument would be inlined.
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
```jsx
|
||||
// Input
|
||||
{await Promise.all(
|
||||
someVeryLongExpression
|
||||
)}
|
||||
|
||||
{await (
|
||||
<div>Lorem ipsum ...</div>
|
||||
)}
|
||||
|
||||
|
||||
// Prettier stable
|
||||
{
|
||||
await Promise.all(
|
||||
someVeryLongExpression
|
||||
)
|
||||
}
|
||||
|
||||
{
|
||||
await (
|
||||
<div>Lorem ipsum ...</div>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
// Prettier main
|
||||
{await Promise.all(
|
||||
someVeryLongExpression
|
||||
)}
|
||||
|
||||
{await (
|
||||
<div>Lorem ipsum ...</div>
|
||||
)}
|
||||
|
||||
```
|
||||
@@ -0,0 +1,3 @@
|
||||
#### Add `acorn` parser (#12172 by @fisker)
|
||||
|
||||
A new value for the `parser` option has been added: [`acorn`](https://github.com/acornjs/acorn) - A small, fast, JavaScript-based JavaScript parser.
|
||||
@@ -0,0 +1,40 @@
|
||||
#### Keep comments after `default` cases in the same line (#12177 by @duailibe)
|
||||
|
||||
Keep comments right after `default` cases (in switch statements) in the same line, when possible.
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
```jsx
|
||||
// Input
|
||||
function read_statement() {
|
||||
switch (peek_keyword()) {
|
||||
case Keyword.impl: // impl<T> Growling<T> for Wolf {}
|
||||
return ImplDeclaration.read();
|
||||
|
||||
default: // expression;
|
||||
return ExpressionStatement.read();
|
||||
}
|
||||
}
|
||||
|
||||
// Prettier stable
|
||||
function read_statement() {
|
||||
switch (peek_keyword()) {
|
||||
case Keyword.impl: // impl<T> Growling<T> for Wolf {}
|
||||
return ImplDeclaration.read();
|
||||
|
||||
default:
|
||||
// expression;
|
||||
return ExpressionStatement.read();
|
||||
}
|
||||
}
|
||||
|
||||
// Prettier main
|
||||
function read_statement() {
|
||||
switch (peek_keyword()) {
|
||||
case Keyword.impl: // impl<T> Growling<T> for Wolf {}
|
||||
return ImplDeclaration.read();
|
||||
|
||||
default: // expression;
|
||||
return ExpressionStatement.read();
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,26 @@
|
||||
#### Fix misplaced argument comment in abstract methods (#12185 by @duailibe)
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
```ts
|
||||
// Input
|
||||
abstract class Foo {
|
||||
abstract bar(
|
||||
/** comment explaining userId param */
|
||||
userId
|
||||
)
|
||||
}
|
||||
|
||||
// Prettier stable
|
||||
abstract class Foo {
|
||||
abstract bar(userId);
|
||||
/** comment explaining userId param */
|
||||
}
|
||||
|
||||
// Prettier main
|
||||
abstract class Foo {
|
||||
abstract bar(
|
||||
/** comment explaining userId param */
|
||||
userId
|
||||
);
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,15 @@
|
||||
#### Fix typecast of superclass in class declarations (#12222 & #12226 by @duailibe)
|
||||
|
||||
This was a combination of two separate bugs: moving the comments before the superclass and adding multiple parenthesis around the superclass.
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
```js
|
||||
// Input
|
||||
class Foo extends /** @type {Type} */ (Bar) {}
|
||||
|
||||
// Prettier stable
|
||||
class Foo /** @type {Type} */ extends ((Bar)) {}
|
||||
|
||||
// Prettier main
|
||||
class Foo extends /** @type {Type} */ (Bar) {}
|
||||
```
|
||||
@@ -0,0 +1,24 @@
|
||||
#### Add parens to `ClassExpression` with decorators (#12260 by @fisker)
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
```js
|
||||
// Input
|
||||
(@f() class {});
|
||||
|
||||
// Prettier stable
|
||||
@f()
|
||||
class {};
|
||||
|
||||
// Prettier stable (Second format)
|
||||
SyntaxError: A class name is required. (2:7)
|
||||
1 | @f()
|
||||
> 2 | class {};
|
||||
| ^
|
||||
3 |
|
||||
|
||||
// Prettier main
|
||||
(
|
||||
@f()
|
||||
class {}
|
||||
);
|
||||
```
|
||||
@@ -0,0 +1,16 @@
|
||||
#### Fixes printing parameters of a mixin named `selector()` (#12213 by @duailibe)
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
```css
|
||||
/* Input */
|
||||
@mixin selector($param: 'value') {
|
||||
}
|
||||
|
||||
/* Prettier stable */
|
||||
@mixin selector($param: 'value) {
|
||||
}
|
||||
|
||||
/* Prettier main */
|
||||
@mixin selector($param: 'value') {
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,21 @@
|
||||
#### Fix hangs on invalid `v-for` (#12113 by @fisker)
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
```jsx
|
||||
// Input
|
||||
<template>
|
||||
<div>
|
||||
<div v-for=" a in ">aaaaa</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
// Prettier stable
|
||||
// Hangs
|
||||
|
||||
// Prettier main
|
||||
<template>
|
||||
<div>
|
||||
<div v-for=" a in ">aaaaa</div>
|
||||
</div>
|
||||
</template>;
|
||||
```
|
||||
+5
-7
@@ -213,6 +213,7 @@
|
||||
"neoclide",
|
||||
"neoformat",
|
||||
"neovim",
|
||||
"nocheck",
|
||||
"nnoremap",
|
||||
"nonenumerable",
|
||||
"Nonspacing",
|
||||
@@ -369,8 +370,6 @@
|
||||
],
|
||||
"files": [
|
||||
"*",
|
||||
".*",
|
||||
".github/**/*",
|
||||
"bin/**/*",
|
||||
"changelog_unreleased/**/*",
|
||||
"docs/**/*",
|
||||
@@ -380,20 +379,19 @@
|
||||
"website/**/*",
|
||||
"tests/config/**/*",
|
||||
"tests/integration/**/*",
|
||||
"tests/**/jsfmt.spec.js"
|
||||
"tests/format/**/jsfmt.spec.js"
|
||||
],
|
||||
"ignorePaths": [
|
||||
".git",
|
||||
"cspell.json",
|
||||
"**/node_modules/**",
|
||||
"**/yarn.lock",
|
||||
"*.{log,svg,snap,png}",
|
||||
"test*.*",
|
||||
"tests/config/jest-light-runner/**/*",
|
||||
"website/data/users.yml",
|
||||
"website/build/**",
|
||||
"website/playground/codeSamples.mjs",
|
||||
"website/pages/googlefe164a33bda4034b.html",
|
||||
"website/static/lib/**",
|
||||
"website/static/playground.js"
|
||||
"website/static/playground.js",
|
||||
"scripts/vendors/vendor-meta.json"
|
||||
]
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 58 KiB |
+4
-3
@@ -265,6 +265,7 @@ Valid options:
|
||||
- `"typescript"` (via [@typescript-eslint/typescript-estree](https://github.com/typescript-eslint/typescript-eslint)) _First available in v1.4.0_
|
||||
- `"espree"` (via [espree](https://github.com/eslint/espree)) _First available in v2.2.0_
|
||||
- `"meriyah"` (via [meriyah](https://github.com/meriyah/meriyah)) _First available in v2.2.0_
|
||||
- `"acorn"` (via [acorn](https://github.com/acornjs/acorn)) _First available in v2.6.0_
|
||||
- `"css"` (via [postcss](https://github.com/postcss/postcss)) _First available in v1.7.1_
|
||||
- `"scss"` (via [postcss-scss](https://github.com/postcss/postcss-scss)) _First available in v1.7.1_
|
||||
- `"less"` (via [postcss-less](https://github.com/shellscape/postcss-less) _First available in v1.7.1_
|
||||
@@ -350,13 +351,13 @@ Note that “in tandem” doesn’t mean “at the same time”. When the two op
|
||||
|
||||
_First available in v1.8.2_
|
||||
|
||||
By default, Prettier will wrap markdown text as-is since some services use a linebreak-sensitive renderer, e.g. GitHub comment and BitBucket. In some cases you may want to rely on editor/viewer soft wrapping instead, so this option allows you to opt out with `"never"`.
|
||||
By default, Prettier will not change wrapping in markdown text since some services use a linebreak-sensitive renderer, e.g. GitHub comments and BitBucket. To have Prettier wrap prose to the print width, change this option to "always". If you want Prettier to force all prose blocks to be on a single line and rely on editor/viewer soft wrapping instead, you can use `"never"`.
|
||||
|
||||
Valid options:
|
||||
|
||||
- `"always"` - Wrap prose if it exceeds the print width.
|
||||
- `"never"` - Do not wrap prose.
|
||||
- `"preserve"` - Wrap prose as-is. _First available in v1.9.0_
|
||||
- `"never"` - Un-wrap each block of prose into one line.
|
||||
- `"preserve"` - Do nothing, leave prose as-is. _First available in v1.9.0_
|
||||
|
||||
| Default | CLI Override | API Override |
|
||||
| ------------ | ----------------------------------------------------------- | ----------------------------------------------------------- |
|
||||
|
||||
+20
-7
@@ -3,7 +3,7 @@ id: plugins
|
||||
title: Plugins
|
||||
---
|
||||
|
||||
Plugins are ways of adding new languages to Prettier. Prettier’s own implementations of all languages are expressed using the plugin API. The core `prettier` package contains JavaScript and other web-focused languages built in. For additional languages you’ll need to install a plugin.
|
||||
Plugins are ways of adding new languages or formatting rules to Prettier. Prettier’s own implementations of all languages are expressed using the plugin API. The core `prettier` package contains JavaScript and other web-focused languages built in. For additional languages you’ll need to install a plugin.
|
||||
|
||||
## Using Plugins
|
||||
|
||||
@@ -13,25 +13,38 @@ Plugins are automatically loaded if you have them installed in the same `node_mo
|
||||
|
||||
When plugins cannot be found automatically, you can load them with:
|
||||
|
||||
- The [CLI](cli.md), via the `--plugin` and `--plugin-search-dir`:
|
||||
- The [CLI](cli.md), via `--plugin-search-dir` and `--plugin`:
|
||||
|
||||
```bash
|
||||
prettier --write main.foo --plugin-search-dir=./dir-with-plugins --plugin=./foo-plugin
|
||||
prettier --write main.foo --plugin-search-dir=./dir-with-plugins --plugin=prettier-plugin-foo
|
||||
```
|
||||
|
||||
> Tip: You can set `--plugin` or `--plugin-search-dir` options multiple times.
|
||||
> Tip: You can set `--plugin-search-dir` or `--plugin` options multiple times.
|
||||
|
||||
- Or the [API](api.md), via the `plugins` and `pluginSearchDirs` options:
|
||||
- The [API](api.md), via the `pluginSearchDirs` and `plugins` options:
|
||||
|
||||
```js
|
||||
prettier.format("code", {
|
||||
parser: "foo",
|
||||
pluginSearchDirs: ["./dir-with-plugins"],
|
||||
plugins: ["./foo-plugin"],
|
||||
plugins: ["prettier-plugin-foo"],
|
||||
});
|
||||
```
|
||||
|
||||
Prettier expects each of `pluginSearchDirs` to contain `node_modules` subdirectory, where `@prettier/plugin-*`, `@*/prettier-plugin-*` and `prettier-plugin-*` will be searched. For instance, this can be your project directory or the location of global npm modules.
|
||||
- The [Configuration File](configuration.md):
|
||||
|
||||
```json
|
||||
{
|
||||
"pluginSearchDirs": ["./dir-with-plugins"],
|
||||
"plugins": ["prettier-plugin-foo"]
|
||||
}
|
||||
```
|
||||
|
||||
`pluginSearchDirs` and `plugins` are independent and one does not require the other.
|
||||
|
||||
The paths that are provided to `pluginSearchDirs` will be searched for `@prettier/plugin-*`, `prettier-plugin-*`, and `@*/prettier-plugin-*`. For instance, these can be your project directory, a `node_modules` directory, the location of global npm modules, or any arbitrary directory that contains plugins.
|
||||
|
||||
Strings provided to `plugins` are ultimately passed to `require()`, so you can provide a module/package name, a path, or anything else `require()` takes. (`pluginSearchDirs` works the same way. That is, valid plugin paths that it finds are passed to `require()`.)
|
||||
|
||||
Providing at least one path to `--plugin-search-dir`/`pluginSearchDirs` turns off plugin autoloading in the default directory (i.e. `node_modules` above `prettier` binary).
|
||||
|
||||
|
||||
+38
-30
@@ -18,15 +18,18 @@
|
||||
"index.js",
|
||||
"standalone.js",
|
||||
"src",
|
||||
"bin"
|
||||
"bin",
|
||||
"vendors"
|
||||
],
|
||||
"dependencies": {
|
||||
"@angular/compiler": "12.2.15",
|
||||
"@angular/compiler": "12.2.16",
|
||||
"@babel/code-frame": "7.16.7",
|
||||
"@babel/parser": "7.16.7",
|
||||
"@babel/parser": "7.17.0",
|
||||
"@glimmer/syntax": "0.83.1",
|
||||
"@iarna/toml": "2.2.5",
|
||||
"@typescript-eslint/typescript-estree": "5.9.0",
|
||||
"@typescript-eslint/typescript-estree": "5.10.2",
|
||||
"acorn": "8.7.0",
|
||||
"acorn-jsx": "5.3.2",
|
||||
"angular-estree-parser": "2.5.0",
|
||||
"angular-html-parser": "1.8.0",
|
||||
"c8": "7.10.0",
|
||||
@@ -42,25 +45,24 @@
|
||||
"escape-string-regexp": "4.0.0",
|
||||
"espree": "9.3.0",
|
||||
"esutils": "2.0.3",
|
||||
"fast-glob": "3.2.9",
|
||||
"fast-glob": "3.2.11",
|
||||
"fast-json-stable-stringify": "2.1.0",
|
||||
"find-parent-dir": "0.3.1",
|
||||
"flow-parser": "0.169.0",
|
||||
"flow-parser": "0.171.0",
|
||||
"get-stdin": "8.0.0",
|
||||
"globby": "11.0.4",
|
||||
"graphql": "15.6.1",
|
||||
"html-element-attributes": "2.3.0",
|
||||
"html-styles": "1.0.0",
|
||||
"html-tag-names": "1.1.5",
|
||||
"html-void-elements": "1.0.5",
|
||||
"ignore": "5.2.0",
|
||||
"jest-docblock": "27.4.0",
|
||||
"jest-docblock": "27.5.0",
|
||||
"json5": "2.2.0",
|
||||
"leven": "3.1.0",
|
||||
"lines-and-columns": "2.0.3",
|
||||
"linguist-languages": "7.15.0",
|
||||
"lodash": "4.17.21",
|
||||
"mem": "8.1.1",
|
||||
"mem": "9.0.2",
|
||||
"meriyah": "4.2.0",
|
||||
"minimatch": "3.0.4",
|
||||
"minimist": "1.2.5",
|
||||
@@ -78,11 +80,11 @@
|
||||
"remark-footnotes": "2.0.0",
|
||||
"remark-math": "3.0.1",
|
||||
"remark-parse": "8.0.3",
|
||||
"resolve": "1.21.0",
|
||||
"resolve": "1.22.0",
|
||||
"semver": "7.3.5",
|
||||
"string-width": "4.2.3",
|
||||
"string-width": "5.0.1",
|
||||
"strip-ansi": "6.0.0",
|
||||
"typescript": "4.5.4",
|
||||
"typescript": "4.5.5",
|
||||
"unicode-regex": "3.0.0",
|
||||
"unified": "9.2.1",
|
||||
"vnopts": "1.0.2",
|
||||
@@ -90,47 +92,51 @@
|
||||
"yaml-unist-parser": "1.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@esbuild-plugins/node-globals-polyfill": "0.1.1",
|
||||
"@babel/core": "7.17.0",
|
||||
"@babel/preset-env": "7.16.11",
|
||||
"@babel/types": "7.17.0",
|
||||
"@esbuild-plugins/node-modules-polyfill": "0.1.4",
|
||||
"@glimmer/reference": "0.83.1",
|
||||
"@jest/globals": "27.4.2",
|
||||
"@prettier/jest-light-runner": "file:./tests/config/jest-light-runner",
|
||||
"@types/estree": "0.0.50",
|
||||
"@types/jest": "27.4.0",
|
||||
"@typescript-eslint/eslint-plugin": "5.9.0",
|
||||
"@typescript-eslint/eslint-plugin": "5.10.2",
|
||||
"babel-jest": "27.5.0",
|
||||
"benchmark": "2.1.4",
|
||||
"browserslist": "4.19.1",
|
||||
"browserslist-to-esbuild": "1.1.1",
|
||||
"builtin-modules": "3.2.0",
|
||||
"cross-env": "7.0.3",
|
||||
"cspell": "5.15.1",
|
||||
"core-js": "3.21.0",
|
||||
"cspell": "5.18.3",
|
||||
"enquirer": "2.3.6",
|
||||
"esbuild": "0.14.10",
|
||||
"esbuild-plugin-browserslist": "0.4.1",
|
||||
"esbuild-plugin-text-replace": "1.1.3",
|
||||
"eslint": "8.6.0",
|
||||
"esbuild": "0.14.18",
|
||||
"esbuild-plugin-text-replace": "1.2.0",
|
||||
"esbuild-visualizer": "0.3.1",
|
||||
"eslint": "8.8.0",
|
||||
"eslint-config-prettier": "8.3.0",
|
||||
"eslint-formatter-friendly": "7.0.0",
|
||||
"eslint-plugin-compat": "4.0.1",
|
||||
"eslint-plugin-compat": "4.0.2",
|
||||
"eslint-plugin-import": "2.25.4",
|
||||
"eslint-plugin-jest": "25.3.4",
|
||||
"eslint-plugin-jest": "26.0.0",
|
||||
"eslint-plugin-prettier-internal-rules": "2.0.1",
|
||||
"eslint-plugin-react": "7.28.0",
|
||||
"eslint-plugin-regexp": "1.5.1",
|
||||
"eslint-plugin-unicorn": "40.0.0",
|
||||
"eslint-plugin-unicorn": "40.1.0",
|
||||
"esm-utils": "2.0.1",
|
||||
"execa": "6.0.0",
|
||||
"jest": "27.4.7",
|
||||
"jest": "27.5.0",
|
||||
"jest-snapshot-serializer-ansi": "1.0.0",
|
||||
"jest-snapshot-serializer-raw": "1.2.0",
|
||||
"jest-watch-typeahead": "1.0.0",
|
||||
"node-actionlint": "1.2.2",
|
||||
"node-fetch": "3.1.0",
|
||||
"node-fetch": "3.1.1",
|
||||
"npm-run-all": "4.1.5",
|
||||
"path-browserify": "1.0.1",
|
||||
"prettier": "2.5.1",
|
||||
"pretty-bytes": "5.6.0",
|
||||
"read-pkg-up": "9.0.0",
|
||||
"rimraf": "3.0.2",
|
||||
"rollup-plugin-license": "2.2.0",
|
||||
"rollup-plugin-license": "2.6.1",
|
||||
"snapshot-diff": "0.9.0",
|
||||
"tempy": "2.0.0"
|
||||
},
|
||||
@@ -142,7 +148,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.js \"dist/!(bin-prettier|index|third-party).js\"",
|
||||
"test:dist-lint": "eslint --no-eslintrc --no-ignore --no-inline-config --config=./scripts/bundle-eslint-config.cjs \"dist/**/*.{js,mjs}\"",
|
||||
"perf:repeat": "yarn && yarn build && cross-env NODE_ENV=production node ./dist/bin-prettier.js --debug-repeat ${PERF_REPEAT:-1000} --loglevel debug ${PERF_FILE:-./index.js} > /dev/null",
|
||||
"perf:repeat-inspect": "yarn && yarn build && cross-env NODE_ENV=production node --inspect-brk ./dist/bin-prettier.js --debug-repeat ${PERF_REPEAT:-1000} --loglevel debug ${PERF_FILE:-./index.js} > /dev/null",
|
||||
"perf:benchmark": "yarn && yarn build && cross-env NODE_ENV=production node ./dist/bin-prettier.js --debug-benchmark --loglevel debug ${PERF_FILE:-./index.js} > /dev/null",
|
||||
@@ -151,14 +157,16 @@
|
||||
"lint:eslint": "cross-env EFF_NO_LINK_RULES=true eslint . --format friendly",
|
||||
"lint:changelog": "node ./scripts/lint-changelog.mjs",
|
||||
"lint:prettier": "prettier . \"!test*\" --check",
|
||||
"lint:spellcheck": "cspell --no-progress --relative",
|
||||
"lint:spellcheck": "cspell --no-progress --relative --dot --gitignore",
|
||||
"lint:deps": "node ./scripts/check-deps.mjs",
|
||||
"lint:actionlint": "node-actionlint",
|
||||
"fix": "run-s fix:eslint fix:prettier",
|
||||
"fix:eslint": "yarn lint:eslint --fix",
|
||||
"fix:prettier": "yarn lint:prettier --write",
|
||||
"build": "node ./scripts/build/build.mjs",
|
||||
"build:website": "node ./scripts/build-website.mjs"
|
||||
"build:website": "node ./scripts/build-website.mjs",
|
||||
"vendors:bundle": "node ./scripts/vendors/bundle-vendors.mjs",
|
||||
"vendors:validate": "node ./scripts/vendors/validate-vendor-versions.mjs"
|
||||
},
|
||||
"c8": {
|
||||
"reporter": [
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import path from "node:path";
|
||||
import fs from "node:fs/promises";
|
||||
import globby from "globby";
|
||||
import fastGlob from "fast-glob";
|
||||
import prettier from "prettier";
|
||||
import createEsmUtils from "esm-utils";
|
||||
import { execa } from "execa";
|
||||
@@ -10,7 +10,6 @@ import {
|
||||
PROJECT_ROOT,
|
||||
DIST_DIR,
|
||||
WEBSITE_DIR,
|
||||
readJson,
|
||||
writeJson,
|
||||
copyFile,
|
||||
writeFile,
|
||||
@@ -32,23 +31,25 @@ const PLAYGROUND_PRETTIER_DIR = path.join(WEBSITE_DIR, "static/lib");
|
||||
async function buildPrettier() {
|
||||
// --- Build prettier for PR ---
|
||||
const packageJsonFile = path.join(PROJECT_ROOT, "package.json");
|
||||
const content = await fs.readFile(packageJsonFile);
|
||||
const packageJson = await readJson(packageJsonFile);
|
||||
const packageJsonContent = await fs.readFile(packageJsonFile);
|
||||
const packageJson = JSON.parse(packageJsonContent);
|
||||
await writeJson(packageJsonFile, {
|
||||
...packageJson,
|
||||
version: `999.999.999-pr.${process.env.REVIEW_ID}`,
|
||||
});
|
||||
|
||||
try {
|
||||
await runYarn("build", ["--playground"], { cwd: PROJECT_ROOT });
|
||||
await runYarn("build", ["--playground", "--no-babel", "--clean"], {
|
||||
cwd: PROJECT_ROOT,
|
||||
});
|
||||
} finally {
|
||||
// restore
|
||||
await writeFile(packageJsonFile, content);
|
||||
await writeFile(packageJsonFile, packageJsonContent);
|
||||
}
|
||||
}
|
||||
|
||||
async function buildPlaygroundFiles() {
|
||||
const files = await globby(["standalone.js", "parser-*.js"], {
|
||||
const files = await fastGlob(["standalone.js", "parser-*.js"], {
|
||||
cwd: PRETTIER_DIR,
|
||||
});
|
||||
const parsers = {};
|
||||
|
||||
+48
-3
@@ -12,6 +12,14 @@ yarn build
|
||||
|
||||
## Flags
|
||||
|
||||
### `--clean`
|
||||
|
||||
Remove `dist` directory before bundle files.
|
||||
|
||||
```sh
|
||||
yarn build --clean
|
||||
```
|
||||
|
||||
### `--playground`
|
||||
|
||||
Run script with `--playground` flag will only build files needed for the website.
|
||||
@@ -28,14 +36,51 @@ To print the bundled file sizes:
|
||||
yarn build --print-size
|
||||
```
|
||||
|
||||
### `--file`
|
||||
### `--compare-size`
|
||||
|
||||
To build a single file:
|
||||
Print the file size changes compare to the last released version:
|
||||
|
||||
```sh
|
||||
yarn build --file=parser-babel.js
|
||||
yarn build --compare-size
|
||||
```
|
||||
|
||||
### `--file`
|
||||
|
||||
To build specific file(s):
|
||||
|
||||
```sh
|
||||
yarn build --file=esm/parser-babel.mjs
|
||||
```
|
||||
|
||||
```sh
|
||||
yarn build --file=standalone.js --file=parser-meriyah.js
|
||||
```
|
||||
|
||||
### `--save-as`
|
||||
|
||||
To save bundled file to a different location, this flag can only use together with ONE `--file` flag
|
||||
|
||||
```sh
|
||||
yarn build --file=parser-babel.js --save-as=babel-for-test.js
|
||||
```
|
||||
|
||||
### `--report`
|
||||
|
||||
Visualize and analyze your esbuild bundle to see which modules are taking up space.
|
||||
|
||||
Available reporter formats:
|
||||
|
||||
- `html` Generate a HTML report file, saved next to the bundled file with `.report.html` suffix.
|
||||
- `text` Generate a plain text report file, saved next to the bundled file with `.report.txt` suffix.
|
||||
- `stdout` Log report information in console.
|
||||
|
||||
```sh
|
||||
yarn build --report
|
||||
yarn build --report=stdout --report=text --report=html
|
||||
```
|
||||
|
||||
**`--report` equals to `--report=html`**
|
||||
|
||||
### `--minify` and `--no-minify`
|
||||
|
||||
By default, the file minification is controlled by `config.mjs` and `bundler.mjs`, these flags are added to override that behavior.
|
||||
|
||||
+166
-55
@@ -6,7 +6,7 @@ import readline from "node:readline";
|
||||
import chalk from "chalk";
|
||||
import minimist from "minimist";
|
||||
import prettyBytes from "pretty-bytes";
|
||||
import rimraf from "rimraf";
|
||||
import createEsmUtils from "esm-utils";
|
||||
import {
|
||||
PROJECT_ROOT,
|
||||
DIST_DIR,
|
||||
@@ -18,6 +18,8 @@ import bundler from "./bundler.mjs";
|
||||
import bundleConfigs from "./config.mjs";
|
||||
import saveLicenses from "./save-licenses.mjs";
|
||||
|
||||
const { require } = createEsmUtils(import.meta);
|
||||
|
||||
// Errors in promises should be fatal.
|
||||
const loggedErrors = new Set();
|
||||
process.on("unhandledRejection", (err) => {
|
||||
@@ -49,60 +51,100 @@ function fitTerminal(input, suffix = "") {
|
||||
const columns = Math.min(process.stdout.columns || 40, 80);
|
||||
const WIDTH = columns - maxLength + 1;
|
||||
if (input.length < WIDTH) {
|
||||
const repeatCount = WIDTH - input.length - 1 - suffix.length;
|
||||
const repeatCount = Math.max(WIDTH - input.length - 1 - suffix.length, 0);
|
||||
input += chalk.dim(".").repeat(repeatCount) + suffix;
|
||||
}
|
||||
return input;
|
||||
}
|
||||
|
||||
const clear = () => {
|
||||
readline.clearLine(process.stdout, 0);
|
||||
readline.cursorTo(process.stdout, 0, null);
|
||||
};
|
||||
|
||||
async function createBundle(bundleConfig, options) {
|
||||
const { output, target, format, type } = bundleConfig;
|
||||
process.stdout.write(fitTerminal(output));
|
||||
const { target } = bundleConfig;
|
||||
|
||||
try {
|
||||
const { skipped } = await bundler(bundleConfig, options);
|
||||
for await (const {
|
||||
name,
|
||||
started,
|
||||
skipped,
|
||||
relativePath,
|
||||
absolutePath,
|
||||
} of bundler(bundleConfig, options)) {
|
||||
const displayName = name.startsWith("esm/") ? ` ${name}` : name;
|
||||
|
||||
if (skipped) {
|
||||
console.log(status.SKIPPED);
|
||||
return;
|
||||
}
|
||||
|
||||
const file = path.join(DIST_DIR, output);
|
||||
|
||||
// Files including U+FFEE can't load in Chrome Extension
|
||||
// `prettier-chrome-extension` https://github.com/prettier/prettier-chrome-extension
|
||||
// details https://github.com/prettier/prettier/pull/8534
|
||||
if (target === "universal") {
|
||||
const content = await fs.readFile(file, "utf8");
|
||||
if (content.includes("\ufffe")) {
|
||||
throw new Error("Bundled umd file should not have U+FFFE character.");
|
||||
if (started) {
|
||||
process.stdout.write(fitTerminal(displayName));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (options["print-size"]) {
|
||||
// Clear previous line
|
||||
readline.clearLine(process.stdout, 0);
|
||||
readline.cursorTo(process.stdout, 0, null);
|
||||
if (skipped) {
|
||||
if (!options.files) {
|
||||
process.stdout.write(fitTerminal(displayName));
|
||||
console.log(status.SKIPPED);
|
||||
}
|
||||
|
||||
const getSizeText = async (file) =>
|
||||
prettyBytes((await fs.stat(file)).size);
|
||||
const sizeTexts = [await getSizeText(file)];
|
||||
if (
|
||||
type !== "core" &&
|
||||
format !== "esm" &&
|
||||
bundleConfig.bundler !== "webpack" &&
|
||||
target === "universal"
|
||||
) {
|
||||
const esmFile = path.join(
|
||||
DIST_DIR,
|
||||
"esm",
|
||||
output.replace(".js", ".mjs")
|
||||
continue;
|
||||
}
|
||||
|
||||
// Files including U+FFEE can't load in Chrome Extension
|
||||
// `prettier-chrome-extension` https://github.com/prettier/prettier-chrome-extension
|
||||
// details https://github.com/prettier/prettier/pull/8534
|
||||
if (target === "universal") {
|
||||
const content = await fs.readFile(absolutePath, "utf8");
|
||||
if (content.includes("\ufffe")) {
|
||||
throw new Error("Bundled umd file should not have U+FFFE character.");
|
||||
}
|
||||
}
|
||||
|
||||
const sizeMessages = [];
|
||||
|
||||
if (options.printSize) {
|
||||
const { size } = await fs.stat(absolutePath);
|
||||
sizeMessages.push(prettyBytes(size));
|
||||
}
|
||||
|
||||
if (options.compareSize) {
|
||||
// TODO: Use `import.meta.resolve` when Node.js support
|
||||
const stablePrettierDirectory = path.dirname(
|
||||
require.resolve("prettier")
|
||||
);
|
||||
sizeTexts.push(`esm ${await getSizeText(esmFile)}`);
|
||||
}
|
||||
process.stdout.write(fitTerminal(output, `${sizeTexts.join(", ")} `));
|
||||
}
|
||||
const stableVersionFile = path.join(
|
||||
stablePrettierDirectory,
|
||||
relativePath
|
||||
);
|
||||
let stableSize;
|
||||
try {
|
||||
({ size: stableSize } = await fs.stat(stableVersionFile));
|
||||
} catch {
|
||||
// No op
|
||||
}
|
||||
|
||||
console.log(status.DONE);
|
||||
if (stableSize) {
|
||||
const { size } = await fs.stat(absolutePath);
|
||||
const sizeDiff = size - stableSize;
|
||||
const message = chalk[sizeDiff > 0 ? "yellow" : "green"](
|
||||
prettyBytes(sizeDiff)
|
||||
);
|
||||
|
||||
sizeMessages.push(`${message}`);
|
||||
} else {
|
||||
sizeMessages.push(chalk.blue("[NEW FILE]"));
|
||||
}
|
||||
}
|
||||
|
||||
if (sizeMessages.length > 0) {
|
||||
// Clear previous line
|
||||
clear();
|
||||
process.stdout.write(
|
||||
fitTerminal(displayName, `${sizeMessages.join(", ")} `)
|
||||
);
|
||||
}
|
||||
|
||||
console.log(status.DONE);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(status.FAIL + "\n");
|
||||
handleError(error);
|
||||
@@ -135,16 +177,65 @@ async function preparePackage() {
|
||||
}
|
||||
|
||||
async function run(params) {
|
||||
const shouldPreparePackage =
|
||||
!params.playground && !params.file && params.minify === null;
|
||||
const shouldSaveBundledPackagesLicenses = shouldPreparePackage;
|
||||
params.files = params.file ? new Set([params.file].flat()) : params.file;
|
||||
params.saveAs = params["save-as"];
|
||||
params.printSize = params["print-size"];
|
||||
|
||||
let configs = bundleConfigs;
|
||||
if (params.file) {
|
||||
configs = configs.filter(({ output }) => output === params.file);
|
||||
} else {
|
||||
rimraf.sync(DIST_DIR);
|
||||
if (params.report === "") {
|
||||
params.report = ["html"];
|
||||
}
|
||||
params.reports = params.report ? [params.report].flat() : params.report;
|
||||
|
||||
delete params.file;
|
||||
delete params.report;
|
||||
delete params["save-as"];
|
||||
delete params["print-size"];
|
||||
|
||||
if (params.saveAs && !(params.files && params.files.size === 1)) {
|
||||
throw new Error("'--save-as' can only use together with one '--file' flag");
|
||||
}
|
||||
|
||||
if (
|
||||
params.saveAs &&
|
||||
!path.join(DIST_DIR, params.saveAs).startsWith(DIST_DIR)
|
||||
) {
|
||||
throw new Error("'--save-as' can only relative path");
|
||||
}
|
||||
|
||||
if (params.clean) {
|
||||
let stat;
|
||||
try {
|
||||
stat = await fs.stat(DIST_DIR);
|
||||
} catch {
|
||||
// No op
|
||||
}
|
||||
|
||||
if (stat) {
|
||||
if (stat.isDirectory()) {
|
||||
await fs.rm(DIST_DIR, { recursive: true, force: true });
|
||||
} else {
|
||||
throw new Error(`"${DIST_DIR}" is not a directory`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (params.compareSize) {
|
||||
if (params.minify === false) {
|
||||
throw new Error(
|
||||
"'--compare-size' can not use together with '--no-minify' flag"
|
||||
);
|
||||
}
|
||||
|
||||
if (params.saveAs) {
|
||||
throw new Error(
|
||||
"'--compare-size' can not use together with '--save-as' flag"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const shouldPreparePackage =
|
||||
!params.playground && !params.files && params.minify === null;
|
||||
const shouldSaveBundledPackagesLicenses = shouldPreparePackage;
|
||||
|
||||
const licenses = [];
|
||||
if (shouldSaveBundledPackagesLicenses) {
|
||||
@@ -153,7 +244,7 @@ async function run(params) {
|
||||
|
||||
console.log(chalk.inverse(" Building packages "));
|
||||
|
||||
for (const bundleConfig of configs) {
|
||||
for (const bundleConfig of bundleConfigs) {
|
||||
await createBundle(bundleConfig, params);
|
||||
}
|
||||
|
||||
@@ -162,7 +253,12 @@ async function run(params) {
|
||||
}
|
||||
|
||||
if (shouldSaveBundledPackagesLicenses) {
|
||||
await saveLicenses(licenses);
|
||||
const vendorMeta = await readJson(
|
||||
new URL("../vendors/vendor-meta.json", import.meta.url)
|
||||
);
|
||||
licenses.push(...vendorMeta.licenses);
|
||||
|
||||
await saveLicenses(licenses.filter(({ name }) => name !== "prettier"));
|
||||
} else {
|
||||
console.warn(
|
||||
chalk.red("Bundled packages licenses not included in `dist/LICENSE`.")
|
||||
@@ -172,8 +268,23 @@ async function run(params) {
|
||||
|
||||
run(
|
||||
minimist(process.argv.slice(2), {
|
||||
boolean: ["playground", "print-size", "minify"],
|
||||
string: ["file"],
|
||||
default: { playground: false, printSize: false, minify: null },
|
||||
boolean: [
|
||||
"playground",
|
||||
"print-size",
|
||||
"compare-size",
|
||||
"minify",
|
||||
"clean",
|
||||
],
|
||||
string: ["file", "save-as", "report"],
|
||||
default: {
|
||||
clean: false,
|
||||
playground: false,
|
||||
printSize: false,
|
||||
compareSize: false,
|
||||
minify: null,
|
||||
},
|
||||
unknown(flag) {
|
||||
throw new Error(`Unknown flag ${chalk.red(flag)}`);
|
||||
},
|
||||
})
|
||||
);
|
||||
+61
-49
@@ -1,54 +1,59 @@
|
||||
import path from "node:path";
|
||||
import createEsmUtils from "esm-utils";
|
||||
import builtinModules from "builtin-modules";
|
||||
import browserslist from "browserslist";
|
||||
import esbuild from "esbuild";
|
||||
import { NodeModulesPolyfillPlugin as esbuildPluginNodeModulePolyfills } from "@esbuild-plugins/node-modules-polyfill";
|
||||
import { NodeGlobalsPolyfillPlugin as esbuildPluginNodeGlobalsPolyfills } from "@esbuild-plugins/node-globals-polyfill";
|
||||
import esbuildPluginTextReplace from "esbuild-plugin-text-replace";
|
||||
import { resolveToEsbuildTarget } from "esbuild-plugin-browserslist";
|
||||
import browserslistToEsbuild from "browserslist-to-esbuild";
|
||||
import { PROJECT_ROOT, DIST_DIR } from "../utils/index.mjs";
|
||||
import esbuildPluginEvaluate from "./esbuild-plugins/evaluate.mjs";
|
||||
import esbuildPluginReplaceModule from "./esbuild-plugins/replace-module.mjs";
|
||||
import esbuildPluginLicense from "./esbuild-plugins/license.mjs";
|
||||
import esbuildPluginUmd from "./esbuild-plugins/umd.mjs";
|
||||
import esbuildPluginVisualizer from "./esbuild-plugins/visualizer.mjs";
|
||||
import bundles from "./config.mjs";
|
||||
|
||||
const { json, __dirname } = createEsmUtils(import.meta);
|
||||
const { __dirname, json, require } = createEsmUtils(import.meta);
|
||||
const packageJson = json.loadSync("../../package.json");
|
||||
|
||||
const umdTarget = resolveToEsbuildTarget(
|
||||
browserslist(packageJson.browserslist),
|
||||
{ printUnknownTargets: false }
|
||||
);
|
||||
const umdTarget = browserslistToEsbuild(packageJson.browserslist);
|
||||
const EMPTY_MODULE_REPLACEMENT = { contents: "" };
|
||||
|
||||
function* getEsbuildOptions(bundle, options) {
|
||||
function* getEsbuildOptions(bundle, buildOptions) {
|
||||
const replaceStrings = {
|
||||
"process.env.PRETTIER_TARGET": JSON.stringify(bundle.target),
|
||||
"process.env.NODE_ENV": JSON.stringify("production"),
|
||||
// `tslib` exports global variables
|
||||
"createExporter(root": "createExporter({}",
|
||||
};
|
||||
|
||||
const define = {
|
||||
"process.env.PRETTIER_TARGET": JSON.stringify(bundle.target),
|
||||
"process.env.NODE_ENV": JSON.stringify("production"),
|
||||
};
|
||||
|
||||
if (bundle.target === "universal") {
|
||||
// We can't reference `process` in UMD bundles and this is
|
||||
// an undocumented "feature"
|
||||
replaceStrings["process.env.PRETTIER_DEBUG"] = "global.PRETTIER_DEBUG";
|
||||
// `rollup-plugin-node-globals` replace `__dirname` with the real dirname
|
||||
// `parser-typescript.js` will contain a path of working directory
|
||||
replaceStrings["process.env.PRETTIER_DEBUG"] = "globalThis.PRETTIER_DEBUG";
|
||||
|
||||
define.process = JSON.stringify({ env: {}, argv: [] });
|
||||
|
||||
// Replace `__dirname` and `__filename` with a fake value
|
||||
// So `parser-typescript.js` won't contain a path of working directory
|
||||
// See #8268
|
||||
replaceStrings.__filename = JSON.stringify(
|
||||
define.__filename = JSON.stringify(
|
||||
"/prettier-security-filename-placeholder.js"
|
||||
);
|
||||
replaceStrings.__dirname = JSON.stringify(
|
||||
"/prettier-security-dirname-placeholder"
|
||||
);
|
||||
define.__dirname = JSON.stringify("/prettier-security-dirname-placeholder");
|
||||
}
|
||||
|
||||
const replaceModule = {};
|
||||
// Replace other bundled files
|
||||
if (bundle.target === "node") {
|
||||
// Replace package.json with dynamic `require("./package.json")`
|
||||
replaceModule[path.join(PROJECT_ROOT, "package.json")] = "./package.json";
|
||||
replaceModule[path.join(PROJECT_ROOT, "package.json")] = {
|
||||
path: "./package.json",
|
||||
external: true,
|
||||
};
|
||||
|
||||
// Dynamic require bundled files
|
||||
for (const item of bundles) {
|
||||
@@ -60,9 +65,8 @@ function* getEsbuildOptions(bundle, options) {
|
||||
// Universal bundle only use version info from package.json
|
||||
// Replace package.json with `{version: "{VERSION}"}`
|
||||
replaceModule[path.join(PROJECT_ROOT, "package.json")] = {
|
||||
code: `module.exports = ${JSON.stringify({
|
||||
version: packageJson.version,
|
||||
})};`,
|
||||
contents: JSON.stringify({ version: packageJson.version }),
|
||||
loader: "json",
|
||||
};
|
||||
|
||||
// Replace parser getters with `undefined`
|
||||
@@ -75,37 +79,42 @@ function* getEsbuildOptions(bundle, options) {
|
||||
"src/language-markdown/parsers.js",
|
||||
"src/language-yaml/parsers.js",
|
||||
]) {
|
||||
replaceModule[path.join(PROJECT_ROOT, file)] = { code: "" };
|
||||
replaceModule[path.join(PROJECT_ROOT, file)] = EMPTY_MODULE_REPLACEMENT;
|
||||
}
|
||||
|
||||
// Prevent `esbuildPluginNodeModulePolyfills` include shim for this module
|
||||
replaceModule.assert = require.resolve("./shims/assert.cjs");
|
||||
}
|
||||
|
||||
let shouldMinify = options.minify;
|
||||
let shouldMinify = buildOptions.minify;
|
||||
if (typeof shouldMinify !== "boolean") {
|
||||
shouldMinify = bundle.minify !== false && bundle.target === "universal";
|
||||
}
|
||||
|
||||
const esbuildOptions = {
|
||||
entryPoints: [path.join(PROJECT_ROOT, bundle.input)],
|
||||
define,
|
||||
bundle: true,
|
||||
metafile: true,
|
||||
plugins: [
|
||||
bundle.target === "universal" && esbuildPluginNodeGlobalsPolyfills(),
|
||||
bundle.target === "universal" && esbuildPluginNodeModulePolyfills(),
|
||||
esbuildPluginEvaluate(),
|
||||
esbuildPluginReplaceModule({ ...replaceModule, ...bundle.replaceModule }),
|
||||
bundle.target === "universal" && esbuildPluginNodeModulePolyfills(),
|
||||
esbuildPluginTextReplace({
|
||||
include: /\.[cm]?js$/,
|
||||
// TODO[@fisker]: Use RegExp when possible
|
||||
pattern: Object.entries({ ...replaceStrings, ...bundle.replace }),
|
||||
}),
|
||||
options.onLicenseFound &&
|
||||
buildOptions.onLicenseFound &&
|
||||
esbuildPluginLicense({
|
||||
cwd: PROJECT_ROOT,
|
||||
thirdParty: {
|
||||
includePrivate: true,
|
||||
output: options.onLicenseFound,
|
||||
output: buildOptions.onLicenseFound,
|
||||
},
|
||||
}),
|
||||
buildOptions.reports &&
|
||||
esbuildPluginVisualizer({ formats: buildOptions.reports }),
|
||||
].filter(Boolean),
|
||||
minify: shouldMinify,
|
||||
legalComments: "none",
|
||||
@@ -122,7 +131,7 @@ function* getEsbuildOptions(bundle, options) {
|
||||
|
||||
yield {
|
||||
...esbuildOptions,
|
||||
outfile: path.join(DIST_DIR, bundle.output),
|
||||
outfile: bundle.output,
|
||||
plugins: [
|
||||
esbuildPluginUmd({ name: bundle.name }),
|
||||
...esbuildOptions.plugins,
|
||||
@@ -130,28 +139,24 @@ function* getEsbuildOptions(bundle, options) {
|
||||
format: "umd",
|
||||
};
|
||||
|
||||
if (!bundle.format && !options.playground) {
|
||||
if (/^(?:standalone|parser-.*)\.js$/.test(bundle.output)) {
|
||||
yield {
|
||||
...esbuildOptions,
|
||||
outfile: path.join(
|
||||
DIST_DIR,
|
||||
`esm/${bundle.output.replace(".js", ".mjs")}`
|
||||
),
|
||||
outfile: `esm/${bundle.output.replace(".js", ".mjs")}`,
|
||||
format: "esm",
|
||||
};
|
||||
}
|
||||
} else {
|
||||
esbuildOptions.external.push(
|
||||
...builtinModules,
|
||||
"./package.json*",
|
||||
...bundles
|
||||
.filter((item) => item.input !== bundle.input)
|
||||
.map((item) => `./${item.output}*`)
|
||||
.map((item) => `./${item.output}`)
|
||||
);
|
||||
|
||||
yield {
|
||||
...esbuildOptions,
|
||||
outfile: path.join(DIST_DIR, bundle.output),
|
||||
outfile: bundle.output,
|
||||
format: "cjs",
|
||||
};
|
||||
}
|
||||
@@ -161,20 +166,27 @@ async function runBuild(bundle, esbuildOptions) {
|
||||
await esbuild.build(esbuildOptions);
|
||||
}
|
||||
|
||||
async function createBundle(bundle, options) {
|
||||
if (
|
||||
options.playground &&
|
||||
(bundle.target !== "universal" || bundle.output === "doc.js")
|
||||
) {
|
||||
return { skipped: true };
|
||||
}
|
||||
async function* createBundle(bundle, buildOptions) {
|
||||
for (const esbuildOptions of getEsbuildOptions(bundle, buildOptions)) {
|
||||
const { outfile: file } = esbuildOptions;
|
||||
|
||||
const esbuildOptions = getEsbuildOptions(bundle, options);
|
||||
for (const options of esbuildOptions) {
|
||||
await runBuild(bundle, options);
|
||||
}
|
||||
if (
|
||||
(buildOptions.files && !buildOptions.files.has(file)) ||
|
||||
(buildOptions.playground && esbuildOptions.format !== "umd")
|
||||
) {
|
||||
yield { name: file, skipped: true };
|
||||
continue;
|
||||
}
|
||||
|
||||
return { bundled: true };
|
||||
const relativePath = buildOptions.saveAs || file;
|
||||
const absolutePath = path.join(DIST_DIR, relativePath);
|
||||
|
||||
esbuildOptions.outfile = absolutePath;
|
||||
|
||||
yield { name: file, started: true };
|
||||
await runBuild(bundle, esbuildOptions, buildOptions);
|
||||
yield { name: file, relativePath, absolutePath };
|
||||
}
|
||||
}
|
||||
|
||||
export default createBundle;
|
||||
@@ -1,4 +1,5 @@
|
||||
import path from "node:path";
|
||||
import { createRequire } from "node:module";
|
||||
import createEsmUtils from "esm-utils";
|
||||
|
||||
const { require } = createEsmUtils(import.meta);
|
||||
@@ -43,11 +44,41 @@ const parsers = [
|
||||
'require("globby")': "{}",
|
||||
"extra.projects = prepareAndTransformProjects(":
|
||||
"extra.projects = [] || prepareAndTransformProjects(",
|
||||
"process.versions.node": "'999.999.999'",
|
||||
"process.versions.node": JSON.stringify("999.999.999"),
|
||||
"process.cwd()": JSON.stringify("/prettier-security-dirname-placeholder"),
|
||||
// `rollup-plugin-polyfill-node` don't have polyfill for these modules
|
||||
'require("perf_hooks")': "{}",
|
||||
'require("inspector")': "{}",
|
||||
"_fs.realpathSync.native": "_fs.realpathSync && _fs.realpathSync.native",
|
||||
// Remove useless `ts.sys`
|
||||
"ts.sys = ": "ts.sys = undefined && ",
|
||||
|
||||
// Remove useless language service
|
||||
"ts.realizeDiagnostics = ": "ts.realizeDiagnostics = undefined && ",
|
||||
"ts.TypeScriptServicesFactory = ":
|
||||
"ts.TypeScriptServicesFactory = undefined && ",
|
||||
"var ShimBase = ": "var ShimBase = undefined && ",
|
||||
"var TypeScriptServicesFactory = ":
|
||||
"var TypeScriptServicesFactory = undefined && ",
|
||||
"var LanguageServiceShimObject = ":
|
||||
"var LanguageServiceShimObject = undefined && ",
|
||||
"var CoreServicesShimHostAdapter = ":
|
||||
"var CoreServicesShimHostAdapter = undefined && ",
|
||||
"var LanguageServiceShimHostAdapter = ":
|
||||
"var LanguageServiceShimHostAdapter = undefined && ",
|
||||
"var ScriptSnapshotShimAdapter = ":
|
||||
"var ScriptSnapshotShimAdapter = undefined && ",
|
||||
"var ClassifierShimObject = ": "var ClassifierShimObject = undefined && ",
|
||||
"var CoreServicesShimObject = ":
|
||||
"var CoreServicesShimObject = undefined && ",
|
||||
"function simpleForwardCall(": "0 && function simpleForwardCall(",
|
||||
"function forwardJSONCall(": "0 && function forwardJSONCall(",
|
||||
"function forwardCall(": "0 && function forwardCall(",
|
||||
"function realizeDiagnostics(": "0 && function realizeDiagnostics(",
|
||||
"function realizeDiagnostic(": "0 && function realizeDiagnostic(",
|
||||
"function convertClassifications(":
|
||||
"0 && function convertClassifications(",
|
||||
|
||||
// Dynamic `require()`s
|
||||
"ts.sys && ts.sys.require": "false",
|
||||
"require(etwModulePath)": "undefined",
|
||||
@@ -59,9 +90,19 @@ const parsers = [
|
||||
"typescriptVersionIsAtLeast[version] = semverCheck(version);":
|
||||
"typescriptVersionIsAtLeast[version] = true;",
|
||||
},
|
||||
replaceModule: {
|
||||
[require.resolve("debug")]: require.resolve("./shims/debug.cjs"),
|
||||
},
|
||||
},
|
||||
{
|
||||
input: "src/language-js/parse/espree.js",
|
||||
input: "src/language-js/parse/acorn-and-espree.js",
|
||||
name: "prettierPlugins.espree",
|
||||
// TODO: Rename this file to `parser-acorn-and-espree.js` or find a better way
|
||||
output: "parser-espree.js",
|
||||
replace: {
|
||||
"const Syntax = ": "const Syntax = undefined && ",
|
||||
"var visitorKeys = ": "var visitorKeys = undefined && ",
|
||||
},
|
||||
},
|
||||
{
|
||||
input: "src/language-js/parse/meriyah.js",
|
||||
@@ -88,6 +129,10 @@ const parsers = [
|
||||
replaceModule: {
|
||||
[require.resolve("parse-entities/decode-entity.browser.js")]:
|
||||
require.resolve("parse-entities/decode-entity.js"),
|
||||
// Avoid `node:util` shim
|
||||
[require.resolve("inherits")]: require.resolve(
|
||||
"inherits/inherits_browser.js"
|
||||
),
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -98,6 +143,12 @@ const parsers = [
|
||||
},
|
||||
{
|
||||
input: "src/language-yaml/parser-yaml.js",
|
||||
replaceModule: {
|
||||
// Use `tslib.es6.js`, so we can avoid `globalThis` shim
|
||||
[require.resolve("tslib")]: require
|
||||
.resolve("tslib")
|
||||
.replace(/tslib\.js$/, "tslib.es6.js"),
|
||||
},
|
||||
},
|
||||
].map((bundle) => {
|
||||
const { name } = bundle.input.match(
|
||||
@@ -134,6 +185,13 @@ const coreBundles = [
|
||||
input: "src/standalone.js",
|
||||
name: "prettier",
|
||||
target: "universal",
|
||||
replaceModule: {
|
||||
[require.resolve("@babel/highlight")]: require.resolve(
|
||||
"./shims/babel-highlight.cjs"
|
||||
),
|
||||
[createRequire(require.resolve("vnopts")).resolve("chalk")]:
|
||||
require.resolve("./shims/chalk.cjs"),
|
||||
},
|
||||
},
|
||||
{
|
||||
input: "bin/prettier.js",
|
||||
|
||||
@@ -1,33 +1,55 @@
|
||||
import fs from "node:fs";
|
||||
import { dirname } from "node:path";
|
||||
|
||||
export default function esbuildPluginReplaceModule(replacements = {}) {
|
||||
return {
|
||||
name: "replace-module",
|
||||
setup(build) {
|
||||
build.onLoad({ filter: /./ }, ({ path }) => {
|
||||
if (!Reflect.has(replacements, path)) {
|
||||
build.onLoad({ filter: /./ }, ({ path, namespace }) => {
|
||||
let options = replacements[path];
|
||||
|
||||
if (!options) {
|
||||
return;
|
||||
}
|
||||
|
||||
const replacement = replacements[path];
|
||||
options =
|
||||
typeof options === "string" ? { path: options } : { ...options };
|
||||
|
||||
if (typeof replacement === "string") {
|
||||
return {
|
||||
contents: `module.exports = require(${JSON.stringify(
|
||||
replacement
|
||||
)});`,
|
||||
};
|
||||
let {
|
||||
path: file,
|
||||
resolveDir,
|
||||
contents,
|
||||
loader = "js",
|
||||
external: isExternal,
|
||||
} = options;
|
||||
|
||||
// Make this work with `@esbuild-plugins/node-modules-polyfill` plugin
|
||||
if (
|
||||
!resolveDir &&
|
||||
namespace === "node-modules-polyfills-commonjs" &&
|
||||
file
|
||||
) {
|
||||
resolveDir = dirname(file);
|
||||
}
|
||||
|
||||
if (replacement.file) {
|
||||
return {
|
||||
contents: fs.readFileSync(replacement.file, "utf8"),
|
||||
};
|
||||
if (isExternal) {
|
||||
if (!file) {
|
||||
throw new Error("Missing external module path.");
|
||||
}
|
||||
|
||||
// Prevent `esbuild` to resolve
|
||||
contents = `
|
||||
const entry = ${JSON.stringify(`${file}`)};
|
||||
module.exports = require(entry);
|
||||
`;
|
||||
} else {
|
||||
if (file) {
|
||||
contents = `
|
||||
module.exports = require(${JSON.stringify(`${file}`)});
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
contents: replacement.code,
|
||||
};
|
||||
return { contents, loader, resolveDir };
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
@@ -46,8 +46,8 @@ function getUmdWrapper(name, build) {
|
||||
|
||||
if (minify) {
|
||||
wrapper = build.esbuild
|
||||
.buildSync({ stdin: { contents: wrapper }, minify, write: false })
|
||||
.outputFiles[0].text.trim();
|
||||
.transformSync(wrapper, { loader: "js", minify })
|
||||
.code.trim();
|
||||
}
|
||||
|
||||
const [intro, outro] = wrapper.split(placeholder);
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
import fs from "node:fs/promises";
|
||||
import { visualizer as esbuildVisualizer } from "esbuild-visualizer/dist/plugin/index.js";
|
||||
|
||||
export default function esbuildPluginVisualizer({ formats }) {
|
||||
formats = Object.fromEntries(formats.map((format) => [format, true]));
|
||||
|
||||
return {
|
||||
name: "visualizer",
|
||||
setup(build) {
|
||||
const { initialOptions: esbuildConfig, esbuild } = build;
|
||||
esbuildConfig.metafile = true;
|
||||
|
||||
build.onEnd(async ({ metafile }) => {
|
||||
const files = Object.keys(metafile.outputs);
|
||||
|
||||
if (files.length !== 1) {
|
||||
throw new Error("Unexpected `outputs`.");
|
||||
}
|
||||
|
||||
if (formats.text || formats.stdout) {
|
||||
const report = await esbuild.analyzeMetafile(metafile, {
|
||||
verbose: true,
|
||||
});
|
||||
|
||||
if (formats.stdout) {
|
||||
console.log(report);
|
||||
}
|
||||
|
||||
if (formats.text) {
|
||||
await fs.writeFile(`${esbuildConfig.outfile}.report.txt`, report);
|
||||
}
|
||||
}
|
||||
|
||||
if (formats.html) {
|
||||
const report = await esbuildVisualizer(metafile, {
|
||||
title: files[0],
|
||||
});
|
||||
|
||||
await fs.writeFile(`${esbuildConfig.outfile}.report.html`, report);
|
||||
}
|
||||
});
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
"use strict";
|
||||
|
||||
const assert = () => {};
|
||||
assert.ok = assert;
|
||||
assert.strictEqual = assert;
|
||||
module.exports = assert;
|
||||
@@ -0,0 +1,6 @@
|
||||
"use strict";
|
||||
|
||||
const chalk = require("./chalk.cjs");
|
||||
const highlight = { shouldHighlight: () => false, getChalk: () => chalk };
|
||||
|
||||
module.exports = highlight;
|
||||
@@ -0,0 +1,11 @@
|
||||
"use strict";
|
||||
|
||||
const chalk = (x) => x;
|
||||
chalk.grey = chalk;
|
||||
chalk.red = chalk;
|
||||
chalk.bold = chalk;
|
||||
chalk.yellow = chalk;
|
||||
chalk.blue = chalk;
|
||||
chalk.default = chalk;
|
||||
|
||||
module.exports = chalk;
|
||||
@@ -0,0 +1,3 @@
|
||||
"use strict";
|
||||
|
||||
module.exports = () => () => {};
|
||||
@@ -0,0 +1,70 @@
|
||||
"use strict";
|
||||
|
||||
const targets = require("../package.json").browserslist;
|
||||
|
||||
module.exports = {
|
||||
root: true,
|
||||
parserOptions: {
|
||||
ecmaVersion: "latest",
|
||||
},
|
||||
settings: {
|
||||
targets,
|
||||
lintAllEsApis: true,
|
||||
polyfills: [
|
||||
// These are not really polyfilled, but seems safe to use in target browsers
|
||||
"BigInt",
|
||||
"Symbol.asyncIterator",
|
||||
],
|
||||
},
|
||||
plugins: ["compat"],
|
||||
overrides: [
|
||||
{
|
||||
files: ["**/*.mjs"],
|
||||
parserOptions: {
|
||||
sourceType: "module",
|
||||
},
|
||||
},
|
||||
{
|
||||
files: [
|
||||
"doc.js",
|
||||
"parser-*.js",
|
||||
"standalone.js",
|
||||
"parser-*.mjs",
|
||||
"standalone.mjs",
|
||||
],
|
||||
env: {
|
||||
browser: true,
|
||||
},
|
||||
rules: {
|
||||
"compat/compat": "error",
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ["index.js", "bin-prettier.js", "third-party.js"],
|
||||
rules: {
|
||||
"no-restricted-syntax": [
|
||||
"error",
|
||||
// Forbid top level `require()` parsers
|
||||
{
|
||||
selector:
|
||||
'CallExpression:not(:function *)[callee.name="require"][arguments.0.value=/parser-/]',
|
||||
message: "Parsers should be inline `require()`d.",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ["doc.js", "parser-*.js", "standalone.js"],
|
||||
rules: {
|
||||
"no-restricted-syntax": [
|
||||
"error",
|
||||
// Forbid `require()`
|
||||
{
|
||||
selector: 'CallExpression[callee.name="require"]',
|
||||
message: "UMD bundles should not include any `require()` call.",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -1,26 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
const targets = require("../package.json").browserslist;
|
||||
|
||||
module.exports = {
|
||||
root: true,
|
||||
env: {
|
||||
browser: true,
|
||||
},
|
||||
parserOptions: {
|
||||
ecmaVersion: "latest",
|
||||
},
|
||||
settings: {
|
||||
targets,
|
||||
lintAllEsApis: true,
|
||||
polyfills: [
|
||||
// These are not really polyfilled, but seems safe to use in target browsers
|
||||
"BigInt",
|
||||
"Symbol.asyncIterator",
|
||||
],
|
||||
},
|
||||
plugins: ["compat"],
|
||||
rules: {
|
||||
"compat/compat": "error",
|
||||
},
|
||||
};
|
||||
@@ -2,13 +2,13 @@
|
||||
|
||||
import fs from "node:fs";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import globby from "globby";
|
||||
import fastGlob from "fast-glob";
|
||||
|
||||
const changelogUnreleasedDir = fileURLToPath(
|
||||
new URL("../changelog_unreleased", import.meta.url)
|
||||
);
|
||||
|
||||
const files = globby.sync(["blog-post-intro.md", "*/*.md"], {
|
||||
const files = fastGlob.sync(["blog-post-intro.md", "*/*.md"], {
|
||||
cwd: changelogUnreleasedDir,
|
||||
absolute: true,
|
||||
});
|
||||
|
||||
@@ -8,13 +8,13 @@
|
||||
"chalk": "4.1.2",
|
||||
"execa": "6.0.0",
|
||||
"minimist": "1.2.5",
|
||||
"node-fetch": "3.1.0",
|
||||
"node-fetch": "3.2.0",
|
||||
"outdent": "0.8.0",
|
||||
"semver": "7.3.5",
|
||||
"string-width": "5.0.1"
|
||||
"string-width": "5.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@jest/globals": "27.4.6",
|
||||
"jest": "27.4.7"
|
||||
"@jest/globals": "27.5.0",
|
||||
"jest": "27.5.0"
|
||||
}
|
||||
}
|
||||
@@ -33,7 +33,7 @@ async function bump({
|
||||
} else {
|
||||
pkg.version = semver.inc(version, "minor") + "-dev";
|
||||
}
|
||||
await writeJson("package.json", pkg, { spaces: 2 });
|
||||
await writeJson("package.json", pkg);
|
||||
}
|
||||
|
||||
export default async function bumpPrettier(params) {
|
||||
|
||||
@@ -2,7 +2,10 @@ import chalk from "chalk";
|
||||
import { runYarn, logPromise, readJson } from "../utils.js";
|
||||
|
||||
export default async function generateBundles({ version }) {
|
||||
await logPromise("Generating bundles", runYarn(["build"]));
|
||||
await logPromise(
|
||||
"Generating bundles",
|
||||
runYarn(["build", "--clean", "--print-size", "--compare-size"])
|
||||
);
|
||||
|
||||
const builtPkg = await readJson("dist/package.json");
|
||||
if (builtPkg.version !== version) {
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
async function bump({ version }) {
|
||||
const pkg = await readJson("package.json");
|
||||
pkg.version = version;
|
||||
await writeJson("package.json", pkg, { spaces: 2 });
|
||||
await writeJson("package.json", pkg);
|
||||
|
||||
// Update github issue templates
|
||||
processFile(".github/ISSUE_TEMPLATE/formatting.md", (content) =>
|
||||
|
||||
+410
-405
File diff suppressed because it is too large.
Load diff
@@ -3,7 +3,7 @@
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const flowParser = require("flow-parser");
|
||||
const globby = require("globby");
|
||||
const fastGlob = require("fast-glob");
|
||||
const rimraf = require("rimraf");
|
||||
|
||||
const DEFAULT_SPEC_CONTENT = "run_spec(__dirname);\n";
|
||||
@@ -11,9 +11,11 @@ const SPEC_FILE_NAME = "jsfmt.spec.js";
|
||||
const FLOW_TESTS_DIR = path.join(__dirname, "..", "tests", "flow-repo");
|
||||
|
||||
function tryParse(file, content) {
|
||||
// Keep this sync with `/src/language-js/parse/flow.js`
|
||||
const ast = flowParser.parse(content, {
|
||||
esproposal_class_instance_fields: true,
|
||||
esproposal_class_static_fields: true,
|
||||
comments: false,
|
||||
enums: true,
|
||||
esproposal_decorators: true,
|
||||
esproposal_export_star_as: true,
|
||||
});
|
||||
|
||||
@@ -27,10 +29,10 @@ function tryParse(file, content) {
|
||||
}
|
||||
|
||||
function syncTests(syncDir) {
|
||||
const specFiles = globby.sync(
|
||||
const specFiles = fastGlob.sync(
|
||||
path.join(FLOW_TESTS_DIR, "**", SPEC_FILE_NAME)
|
||||
);
|
||||
const filesToCopy = globby.sync(path.join(syncDir, "**/*.js"));
|
||||
const filesToCopy = fastGlob.sync(path.join(syncDir, "**/*.js"));
|
||||
|
||||
if (filesToCopy.length === 0) {
|
||||
throw new Error(
|
||||
|
||||
@@ -272,8 +272,8 @@ test("no-identifier-n", {
|
||||
valid: ["const a = {n: 1}", "const m = 1", "a.n = 1"],
|
||||
invalid: [
|
||||
{
|
||||
code: "const n = 1; alet(n)",
|
||||
output: "const node = 1; alet(node)",
|
||||
code: "const n = 1; alert(n)",
|
||||
output: "const node = 1; alert(node)",
|
||||
errors: 1,
|
||||
},
|
||||
{
|
||||
|
||||
@@ -2,13 +2,15 @@ import fs from "node:fs/promises";
|
||||
import url from "node:url";
|
||||
import path from "node:path";
|
||||
|
||||
const toPath = (path) => (path instanceof URL ? url.fileURLToPath(path) : path);
|
||||
|
||||
async function readJson(file) {
|
||||
const data = await fs.readFile(file);
|
||||
return JSON.parse(data);
|
||||
}
|
||||
|
||||
function writeJson(file, content) {
|
||||
content = JSON.stringify(content, null, 2);
|
||||
content = JSON.stringify(content, null, 2) + "\n";
|
||||
return writeFile(file, content);
|
||||
}
|
||||
|
||||
@@ -18,7 +20,7 @@ async function copyFile(from, to) {
|
||||
}
|
||||
|
||||
async function writeFile(file, content) {
|
||||
const directory = path.dirname(file);
|
||||
const directory = path.dirname(toPath(file));
|
||||
try {
|
||||
await fs.mkdir(directory, { recursive: true });
|
||||
} catch {
|
||||
|
||||
Vendored
+55
@@ -0,0 +1,55 @@
|
||||
# `./scripts/vendors`
|
||||
|
||||
Scripts for bundling Pure ESM Packages to CommonJS so that Prettier can use them.
|
||||
|
||||
## Context
|
||||
|
||||
https://github.com/prettier/prettier/issues/12209#issuecomment-1028212785
|
||||
|
||||
Currently, Prettier is developed using CommonJS Modules. This is for historical reasons, and we are considering [migrating to ECMAScript Modules](https://github.com/prettier/prettier/issues/10157) in the future.
|
||||
|
||||
However, migrating to ECMAScript Modules is not an easy task.
|
||||
|
||||
While we are working on it, several important packages are being migrated to Pure ESM. Please see https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c from [@sindresorhus](https://github.com/sindresorhus) about Pure ESM Packages.
|
||||
|
||||
It would be a problem if Prettier could not use the new Pure ESM Package until we have completed that work.
|
||||
|
||||
So we will put the files bundled with Pure ESM Packages as CommonJS Modules under `/vendors`, and Prettier will use them.
|
||||
|
||||
**This will be removed during the migration to ESM.**
|
||||
|
||||
## Usage
|
||||
|
||||
### `/scripts/vendors/bundle-vendors.mjs`
|
||||
|
||||
```
|
||||
node ./scripts/vendors/bundle-vendors.mjs
|
||||
```
|
||||
|
||||
This script do the following 4 things:
|
||||
|
||||
**1. Bundle ESM Packages to CommonJS**
|
||||
|
||||
This bundles listed packages in `vendors.mjs` into `/vendors/*.js` as CommonJS.
|
||||
|
||||
**2. Update `package.json`**
|
||||
|
||||
This updates [`"imports"` in `package.json`](https://nodejs.org/api/packages.html#imports) to enables aliases to resolve packages put in `/vendors/*.js`.
|
||||
|
||||
**3. Lock ESM Packages version to `vendor-versions.json`**
|
||||
|
||||
This locks versions of packages that is bundled to `vendor-versions.json`. It is used to validate by `validate-vendor-versions.mjs`.
|
||||
|
||||
**4. Generate `/vendors/types.d.ts`**
|
||||
|
||||
This Generates a minimal type definition file that satisfies `lint:typecheck`.
|
||||
|
||||
### `/scripts/vendors/validate-vendor-versions.mjs`
|
||||
|
||||
```
|
||||
node ./scripts/vendors/validate-vendor-versions.mjs
|
||||
```
|
||||
|
||||
This script compares the version of packages locked in `vendor-versions.json` with the version of packages actually installed, and fails if they are different.
|
||||
|
||||
This is mainly run on CI to keep consistency between bundled and installed packages.
|
||||
Vendored
+109
@@ -0,0 +1,109 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import fs from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import createEsmUtils from "esm-utils";
|
||||
import esbuild from "esbuild";
|
||||
import { readPackageUp } from "read-pkg-up";
|
||||
import { PROJECT_ROOT } from "../utils/index.mjs";
|
||||
import esbuildPluginLicense from "../build/esbuild-plugins/license.mjs";
|
||||
import vendors from "./vendors.mjs";
|
||||
import { saveVendorVersions, saveVendorLicenses } from "./utils.mjs";
|
||||
import esbuildPluginTsNocheck from "./esbuild-plugin-ts-nocheck.mjs";
|
||||
|
||||
const { __dirname, require } = createEsmUtils(import.meta);
|
||||
const rootDir = path.join(__dirname, "..", "..");
|
||||
// prettier/vendors
|
||||
const vendorsDir = path.join(rootDir, "vendors");
|
||||
// prettier/vendors/*.js
|
||||
const getVendorFilePath = (vendorName) =>
|
||||
path.join(vendorsDir, `${vendorName}.js`);
|
||||
|
||||
async function lockVersions(vendors) {
|
||||
const vendorVersions = {};
|
||||
for (const vendor of vendors) {
|
||||
const { packageJson: vendorPackage } = await readPackageUp({
|
||||
cwd: path.dirname(require.resolve(vendor)),
|
||||
});
|
||||
const vendorVersion = vendorPackage.version;
|
||||
vendorVersions[vendor] = vendorVersion;
|
||||
}
|
||||
await saveVendorVersions(vendorVersions);
|
||||
}
|
||||
|
||||
async function fileExists(filePath) {
|
||||
try {
|
||||
return (await fs.stat(filePath)).isFile();
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
async function cleanExistsBundledJS() {
|
||||
for (const file of await fs.readdir(vendorsDir)) {
|
||||
const filePath = path.join(vendorsDir, file);
|
||||
if (path.extname(file) === ".js" && (await fileExists(filePath))) {
|
||||
await fs.rm(filePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function bundle(vendor, options) {
|
||||
const outfile = getVendorFilePath(vendor);
|
||||
if (await fileExists(outfile)) {
|
||||
await fs.rm(outfile);
|
||||
}
|
||||
|
||||
/** @type {import("esbuild").CommonOptions} */
|
||||
const esbuildOption = {
|
||||
entryPoints: [require.resolve(vendor)],
|
||||
bundle: true,
|
||||
target: ["node12.17.0"],
|
||||
platform: "node",
|
||||
plugins: [
|
||||
esbuildPluginTsNocheck(),
|
||||
esbuildPluginLicense({
|
||||
cwd: PROJECT_ROOT,
|
||||
thirdParty: {
|
||||
includePrivate: true,
|
||||
output: options.onLicenseFound,
|
||||
},
|
||||
}),
|
||||
],
|
||||
outfile,
|
||||
};
|
||||
await esbuild.build(esbuildOption);
|
||||
|
||||
await fs.writeFile(
|
||||
path.join(vendorsDir, `${vendor}.d.ts`),
|
||||
[
|
||||
"// This file is generated automatically.",
|
||||
`export {default} from "${vendor}";`,
|
||||
`export * from "${vendor}";`,
|
||||
"",
|
||||
].join("\n"),
|
||||
"utf-8"
|
||||
);
|
||||
}
|
||||
|
||||
async function main() {
|
||||
await cleanExistsBundledJS();
|
||||
|
||||
const licenses = [];
|
||||
for (const vendor of vendors) {
|
||||
await bundle(vendor, {
|
||||
onLicenseFound(dependencies) {
|
||||
licenses.push(...dependencies);
|
||||
},
|
||||
});
|
||||
console.log(`Bundled: ${vendor}`);
|
||||
}
|
||||
|
||||
await lockVersions(vendors);
|
||||
console.log("Vendor versions saved");
|
||||
|
||||
await saveVendorLicenses(licenses);
|
||||
console.log("Vendor licenses saved");
|
||||
}
|
||||
|
||||
main();
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
import fs from "node:fs";
|
||||
|
||||
const tsNoCheck = "// @ts-nocheck\n// This file is generated automatically\n";
|
||||
|
||||
export default function esbuildPluginTsNocheck() {
|
||||
return {
|
||||
name: "ts-no-check",
|
||||
setup(build) {
|
||||
const options = build.initialOptions;
|
||||
const { outfile } = options;
|
||||
build.onEnd(() => {
|
||||
if (!fs.existsSync(outfile)) {
|
||||
throw new Error(`${outfile} not exists`);
|
||||
}
|
||||
const text = fs.readFileSync(outfile, "utf8");
|
||||
fs.writeFileSync(outfile, tsNoCheck + text);
|
||||
});
|
||||
},
|
||||
};
|
||||
}
|
||||
Vendored
+23
@@ -0,0 +1,23 @@
|
||||
import fs from "node:fs";
|
||||
import { readJson, writeJson } from "../utils/index.mjs";
|
||||
|
||||
const vendorMetaFile = new URL("./vendor-meta.json", import.meta.url);
|
||||
const getMeta = () =>
|
||||
fs.existsSync(vendorMetaFile) ? readJson(vendorMetaFile) : {};
|
||||
|
||||
export async function getVendorVersions() {
|
||||
const meta = await getMeta();
|
||||
return meta.versions;
|
||||
}
|
||||
|
||||
export async function saveVendorVersions(versions) {
|
||||
const meta = await getMeta();
|
||||
meta.versions = versions;
|
||||
await writeJson(vendorMetaFile, meta);
|
||||
}
|
||||
|
||||
export async function saveVendorLicenses(licenses) {
|
||||
const meta = await getMeta();
|
||||
meta.licenses = licenses;
|
||||
await writeJson(vendorMetaFile, meta);
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import createEsmUtils from "esm-utils";
|
||||
import { readPackageUp } from "read-pkg-up";
|
||||
import { getVendorVersions } from "./utils.mjs";
|
||||
import vendors from "./vendors.mjs";
|
||||
|
||||
const { require } = createEsmUtils(import.meta);
|
||||
|
||||
async function main() {
|
||||
const errors = [];
|
||||
const vendorVersions = await getVendorVersions();
|
||||
for (const vendor of vendors) {
|
||||
const { packageJson: vendorPackage } = await readPackageUp({
|
||||
cwd: require.resolve(vendor),
|
||||
});
|
||||
const vendorPackageVersion = vendorPackage.version;
|
||||
const lockedVersion = vendorVersions[vendor];
|
||||
if (vendorPackageVersion !== lockedVersion) {
|
||||
errors.push({
|
||||
oldVersion: lockedVersion,
|
||||
newVersion: vendorPackageVersion,
|
||||
packageName: vendor,
|
||||
});
|
||||
}
|
||||
}
|
||||
if (errors.length > 0) {
|
||||
for (const { packageName, oldVersion, newVersion } of errors) {
|
||||
console.error(
|
||||
`The version of \`${packageName}\` is "${newVersion}", expected locked "${oldVersion}"`
|
||||
);
|
||||
}
|
||||
console.error(
|
||||
"Did you forget running `./scripts/vendors/bundle-vendors.mjs`?"
|
||||
);
|
||||
process.exitCode = 1;
|
||||
} else {
|
||||
console.log("Done");
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
Vendored
+164
@@ -0,0 +1,164 @@
|
||||
{
|
||||
"licenses": [
|
||||
{
|
||||
"name": "ansi-regex",
|
||||
"maintainers": [],
|
||||
"version": "6.0.1",
|
||||
"description": "Regular expression for matching ANSI escape codes",
|
||||
"repository": "chalk/ansi-regex",
|
||||
"homepage": null,
|
||||
"private": false,
|
||||
"license": "MIT",
|
||||
"licenseText": "MIT License\n\nCopyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n",
|
||||
"author": {
|
||||
"name": "Sindre Sorhus",
|
||||
"email": "sindresorhus@gmail.com",
|
||||
"url": "https://sindresorhus.com"
|
||||
},
|
||||
"contributors": []
|
||||
},
|
||||
{
|
||||
"name": "strip-ansi",
|
||||
"maintainers": [],
|
||||
"version": "7.0.1",
|
||||
"description": "Strip ANSI escape codes from a string",
|
||||
"repository": "chalk/strip-ansi",
|
||||
"homepage": null,
|
||||
"private": false,
|
||||
"license": "MIT",
|
||||
"licenseText": "MIT License\n\nCopyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n",
|
||||
"author": {
|
||||
"name": "Sindre Sorhus",
|
||||
"email": "sindresorhus@gmail.com",
|
||||
"url": "https://sindresorhus.com"
|
||||
},
|
||||
"contributors": []
|
||||
},
|
||||
{
|
||||
"name": "is-fullwidth-code-point",
|
||||
"maintainers": [],
|
||||
"version": "4.0.0",
|
||||
"description": "Check if the character represented by a given Unicode code point is fullwidth",
|
||||
"repository": "sindresorhus/is-fullwidth-code-point",
|
||||
"homepage": null,
|
||||
"private": false,
|
||||
"license": "MIT",
|
||||
"licenseText": "MIT License\n\nCopyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n",
|
||||
"author": {
|
||||
"name": "Sindre Sorhus",
|
||||
"email": "sindresorhus@gmail.com",
|
||||
"url": "https://sindresorhus.com"
|
||||
},
|
||||
"contributors": []
|
||||
},
|
||||
{
|
||||
"name": "emoji-regex",
|
||||
"maintainers": [],
|
||||
"version": "9.2.2",
|
||||
"description": "A regular expression to match all Emoji-only symbols as per the Unicode Standard.",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/mathiasbynens/emoji-regex.git"
|
||||
},
|
||||
"homepage": "https://mths.be/emoji-regex",
|
||||
"private": false,
|
||||
"license": "MIT",
|
||||
"licenseText": "Copyright Mathias Bynens <https://mathiasbynens.be/>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n",
|
||||
"author": {
|
||||
"name": "Mathias Bynens",
|
||||
"email": null,
|
||||
"url": "https://mathiasbynens.be/"
|
||||
},
|
||||
"contributors": []
|
||||
},
|
||||
{
|
||||
"name": "string-width",
|
||||
"maintainers": [],
|
||||
"version": "5.0.1",
|
||||
"description": "Get the visual width of a string - the number of columns required to display it",
|
||||
"repository": "sindresorhus/string-width",
|
||||
"homepage": null,
|
||||
"private": false,
|
||||
"license": "MIT",
|
||||
"licenseText": "MIT License\n\nCopyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n",
|
||||
"author": {
|
||||
"name": "Sindre Sorhus",
|
||||
"email": "sindresorhus@gmail.com",
|
||||
"url": "https://sindresorhus.com"
|
||||
},
|
||||
"contributors": []
|
||||
},
|
||||
{
|
||||
"name": "mimic-fn",
|
||||
"maintainers": [],
|
||||
"version": "4.0.0",
|
||||
"description": "Make a function mimic another one",
|
||||
"repository": "sindresorhus/mimic-fn",
|
||||
"homepage": null,
|
||||
"private": false,
|
||||
"license": "MIT",
|
||||
"licenseText": "MIT License\n\nCopyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n",
|
||||
"author": {
|
||||
"name": "Sindre Sorhus",
|
||||
"email": "sindresorhus@gmail.com",
|
||||
"url": "https://sindresorhus.com"
|
||||
},
|
||||
"contributors": []
|
||||
},
|
||||
{
|
||||
"name": "p-defer",
|
||||
"maintainers": [],
|
||||
"version": "1.0.0",
|
||||
"description": "Create a deferred promise",
|
||||
"repository": "sindresorhus/p-defer",
|
||||
"homepage": null,
|
||||
"private": false,
|
||||
"license": "MIT",
|
||||
"licenseText": "The MIT License (MIT)\n\nCopyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n",
|
||||
"author": {
|
||||
"name": "Sindre Sorhus",
|
||||
"email": "sindresorhus@gmail.com",
|
||||
"url": "sindresorhus.com"
|
||||
},
|
||||
"contributors": []
|
||||
},
|
||||
{
|
||||
"name": "map-age-cleaner",
|
||||
"maintainers": [],
|
||||
"version": "0.1.3",
|
||||
"description": "Automatically cleanup expired items in a Map",
|
||||
"repository": "SamVerschueren/map-age-cleaner",
|
||||
"homepage": null,
|
||||
"private": false,
|
||||
"license": "MIT",
|
||||
"licenseText": "MIT License\n\nCopyright (c) Sam Verschueren <sam.verschueren@gmail.com> (github.com/SamVerschueren)\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n",
|
||||
"author": {
|
||||
"name": "Sam Verschueren",
|
||||
"email": "sam.verschueren@gmail.com",
|
||||
"url": "github.com/SamVerschueren"
|
||||
},
|
||||
"contributors": []
|
||||
},
|
||||
{
|
||||
"name": "mem",
|
||||
"maintainers": [],
|
||||
"version": "9.0.2",
|
||||
"description": "Memoize functions - An optimization used to speed up consecutive function calls by caching the result of calls with identical input",
|
||||
"repository": "sindresorhus/mem",
|
||||
"homepage": null,
|
||||
"private": false,
|
||||
"license": "MIT",
|
||||
"licenseText": "MIT License\n\nCopyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n",
|
||||
"author": {
|
||||
"name": "Sindre Sorhus",
|
||||
"email": "sindresorhus@gmail.com",
|
||||
"url": "https://sindresorhus.com"
|
||||
},
|
||||
"contributors": []
|
||||
}
|
||||
],
|
||||
"versions": {
|
||||
"string-width": "5.0.1",
|
||||
"mem": "9.0.2"
|
||||
}
|
||||
}
|
||||
Vendored
+3
@@ -0,0 +1,3 @@
|
||||
const vendors = ["string-width", "mem"];
|
||||
|
||||
export default vendors;
|
||||
+12
-3
@@ -16,9 +16,18 @@ const getOptionsForFile = require("./options/get-options-for-file.js");
|
||||
const isTTY = require("./is-tty.js");
|
||||
|
||||
function diff(a, b) {
|
||||
return require("diff").createTwoFilesPatch("", "", a, b, "", "", {
|
||||
context: 2,
|
||||
});
|
||||
// Use `diff/lib/patch/create.js` instead of `diff` to reduce bundle size
|
||||
return require("diff/lib/patch/create.js").createTwoFilesPatch(
|
||||
"",
|
||||
"",
|
||||
a,
|
||||
b,
|
||||
"",
|
||||
"",
|
||||
{
|
||||
context: 2,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function handleError(context, filename, error, printedFilename) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
"use strict";
|
||||
|
||||
const dashify = require("dashify");
|
||||
const chalk = require("chalk");
|
||||
// eslint-disable-next-line no-restricted-modules
|
||||
const prettier = require("../../index.js");
|
||||
const { optionsNormalizer } = require("../prettier-internal.js");
|
||||
@@ -49,7 +50,7 @@ function parseArgsToOptions(context, overrideDefaults) {
|
||||
default: cliifyOptions(overrideDefaults, apiDetailedOptionMap),
|
||||
}),
|
||||
context.detailedOptions,
|
||||
{ logger: false }
|
||||
{ logger: false, colorsModule: chalk }
|
||||
),
|
||||
context.detailedOptions
|
||||
);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
"use strict";
|
||||
const pick = require("lodash/pick");
|
||||
const camelCase = require("camelcase");
|
||||
const chalk = require("chalk");
|
||||
const {
|
||||
optionsNormalizer: { normalizeCliOptions },
|
||||
} = require("../prettier-internal.js");
|
||||
@@ -19,7 +20,10 @@ function parseArgv(rawArguments, detailedOptions, logger, keys) {
|
||||
argv = pick(argv, keys);
|
||||
}
|
||||
|
||||
const normalized = normalizeCliOptions(argv, detailedOptions, { logger });
|
||||
const normalized = normalizeCliOptions(argv, detailedOptions, {
|
||||
logger,
|
||||
colorsModule: chalk,
|
||||
});
|
||||
|
||||
return Object.fromEntries(
|
||||
Object.entries(normalized).map(([key, value]) => {
|
||||
|
||||
@@ -4,17 +4,17 @@ const fs = require("fs");
|
||||
const path = require("path");
|
||||
const uniqBy = require("lodash/uniqBy");
|
||||
const partition = require("lodash/partition");
|
||||
const globby = require("globby");
|
||||
const mem = require("mem");
|
||||
const fastGlob = require("fast-glob");
|
||||
const internalPlugins = require("../languages.js");
|
||||
const { default: mem, memClear } = require("../../vendors/mem.js");
|
||||
const thirdParty = require("./third-party.js");
|
||||
const resolve = require("./resolve.js");
|
||||
|
||||
const memoizedLoad = mem(load, { cacheKey: JSON.stringify });
|
||||
const memoizedSearch = mem(findPluginsInNodeModules);
|
||||
const clearCache = () => {
|
||||
mem.clear(memoizedLoad);
|
||||
mem.clear(memoizedSearch);
|
||||
memClear(memoizedLoad);
|
||||
memClear(memoizedSearch);
|
||||
};
|
||||
|
||||
function load(plugins, pluginSearchDirs) {
|
||||
@@ -102,7 +102,7 @@ function load(plugins, pluginSearchDirs) {
|
||||
}
|
||||
|
||||
function findPluginsInNodeModules(nodeModulesDir) {
|
||||
const pluginPackageJsonPaths = globby.sync(
|
||||
const pluginPackageJsonPaths = fastGlob.sync(
|
||||
[
|
||||
"prettier-plugin-*/package.json",
|
||||
"@*/prettier-plugin-*/package.json",
|
||||
@@ -110,7 +110,6 @@ function findPluginsInNodeModules(nodeModulesDir) {
|
||||
],
|
||||
{
|
||||
cwd: nodeModulesDir,
|
||||
expandDirectories: false,
|
||||
}
|
||||
);
|
||||
return pluginPackageJsonPaths.map(path.dirname);
|
||||
|
||||
+12
-164
@@ -1,11 +1,20 @@
|
||||
"use strict";
|
||||
|
||||
const stringWidth = require("string-width");
|
||||
const escapeStringRegexp = require("escape-string-regexp");
|
||||
const getLast = require("../utils/get-last.js");
|
||||
const { getSupportInfo } = require("../main/support.js");
|
||||
|
||||
const notAsciiRegex = /[^\x20-\x7F]/;
|
||||
const isNonEmptyArray = require("../utils/is-non-empty-array.js");
|
||||
const getStringWidth = require("../utils/get-string-width.js");
|
||||
const {
|
||||
skipWhitespace,
|
||||
skipSpaces,
|
||||
skipToLineEnd,
|
||||
skipEverythingButNewLine,
|
||||
} = require("../utils/text/skip.js");
|
||||
const skipInlineComment = require("../utils/text/skip-inline-comment.js");
|
||||
const skipTrailingComment = require("../utils/text/skip-trailing-comment.js");
|
||||
const skipNewline = require("../utils/text/skip-newline.js");
|
||||
const getNextNonSpaceNonCommentCharacterIndexWithStartIndex = require("../utils/text/get-next-non-space-non-comment-character-index-with-start-index.js");
|
||||
|
||||
const getPenultimate = (arr) => arr[arr.length - 2];
|
||||
|
||||
@@ -54,110 +63,6 @@ function skip(chars) {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {(text: string, index: number | false, opts?: SkipOptions) => number | false}
|
||||
*/
|
||||
const skipWhitespace = skip(/\s/);
|
||||
/**
|
||||
* @type {(text: string, index: number | false, opts?: SkipOptions) => number | false}
|
||||
*/
|
||||
const skipSpaces = skip(" \t");
|
||||
/**
|
||||
* @type {(text: string, index: number | false, opts?: SkipOptions) => number | false}
|
||||
*/
|
||||
const skipToLineEnd = skip(",; \t");
|
||||
/**
|
||||
* @type {(text: string, index: number | false, opts?: SkipOptions) => number | false}
|
||||
*/
|
||||
const skipEverythingButNewLine = skip(/[^\n\r]/);
|
||||
|
||||
/**
|
||||
* @param {string} text
|
||||
* @param {number | false} index
|
||||
* @returns {number | false}
|
||||
*/
|
||||
function skipInlineComment(text, index) {
|
||||
/* istanbul ignore next */
|
||||
if (index === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (text.charAt(index) === "/" && text.charAt(index + 1) === "*") {
|
||||
for (let i = index + 2; i < text.length; ++i) {
|
||||
if (text.charAt(i) === "*" && text.charAt(i + 1) === "/") {
|
||||
return i + 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} text
|
||||
* @param {number | false} index
|
||||
* @returns {number | false}
|
||||
*/
|
||||
function skipTrailingComment(text, index) {
|
||||
/* istanbul ignore next */
|
||||
if (index === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (text.charAt(index) === "/" && text.charAt(index + 1) === "/") {
|
||||
return skipEverythingButNewLine(text, index);
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
// This one doesn't use the above helper function because it wants to
|
||||
// test \r\n in order and `skip` doesn't support ordering and we only
|
||||
// want to skip one newline. It's simple to implement.
|
||||
/**
|
||||
* @param {string} text
|
||||
* @param {number | false} index
|
||||
* @param {SkipOptions=} opts
|
||||
* @returns {number | false}
|
||||
*/
|
||||
function skipNewline(text, index, opts) {
|
||||
const backwards = opts && opts.backwards;
|
||||
if (index === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const atIndex = text.charAt(index);
|
||||
if (backwards) {
|
||||
// We already replace `\r\n` with `\n` before parsing
|
||||
/* istanbul ignore next */
|
||||
if (text.charAt(index - 1) === "\r" && atIndex === "\n") {
|
||||
return index - 2;
|
||||
}
|
||||
if (
|
||||
atIndex === "\n" ||
|
||||
atIndex === "\r" ||
|
||||
atIndex === "\u2028" ||
|
||||
atIndex === "\u2029"
|
||||
) {
|
||||
return index - 1;
|
||||
}
|
||||
} else {
|
||||
// We already replace `\r\n` with `\n` before parsing
|
||||
/* istanbul ignore next */
|
||||
if (atIndex === "\r" && text.charAt(index + 1) === "\n") {
|
||||
return index + 2;
|
||||
}
|
||||
if (
|
||||
atIndex === "\n" ||
|
||||
atIndex === "\r" ||
|
||||
atIndex === "\u2028" ||
|
||||
atIndex === "\u2029"
|
||||
) {
|
||||
return index + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} text
|
||||
* @param {number} index
|
||||
@@ -235,26 +140,6 @@ function isNextLineEmpty(text, node, locEnd) {
|
||||
return isNextLineEmptyAfterIndex(text, locEnd(node));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} text
|
||||
* @param {number} idx
|
||||
* @returns {number | false}
|
||||
*/
|
||||
function getNextNonSpaceNonCommentCharacterIndexWithStartIndex(text, idx) {
|
||||
/** @type {number | false} */
|
||||
let oldIdx = null;
|
||||
/** @type {number | false} */
|
||||
let nextIdx = idx;
|
||||
while (nextIdx !== oldIdx) {
|
||||
oldIdx = nextIdx;
|
||||
nextIdx = skipSpaces(text, nextIdx);
|
||||
nextIdx = skipInlineComment(text, nextIdx);
|
||||
nextIdx = skipTrailingComment(text, nextIdx);
|
||||
nextIdx = skipNewline(text, nextIdx);
|
||||
}
|
||||
return nextIdx;
|
||||
}
|
||||
|
||||
/**
|
||||
* @template N
|
||||
* @param {string} text
|
||||
@@ -517,23 +402,6 @@ function getMinNotPresentContinuousCount(str, target) {
|
||||
return max + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} text
|
||||
* @returns {number}
|
||||
*/
|
||||
function getStringWidth(text) {
|
||||
if (!text) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// shortcut to avoid needless string `RegExp`s, replacements, and allocations within `string-width`
|
||||
if (!notAsciiRegex.test(text)) {
|
||||
return text.length;
|
||||
}
|
||||
|
||||
return stringWidth(text);
|
||||
}
|
||||
|
||||
function addCommentHelper(node, comment) {
|
||||
const comments = node.comments || (node.comments = []);
|
||||
comments.push(comment);
|
||||
@@ -580,25 +448,6 @@ function isFrontMatterNode(node) {
|
||||
return node && node.type === "front-matter";
|
||||
}
|
||||
|
||||
function getShebang(text) {
|
||||
if (!text.startsWith("#!")) {
|
||||
return "";
|
||||
}
|
||||
const index = text.indexOf("\n");
|
||||
if (index === -1) {
|
||||
return text;
|
||||
}
|
||||
return text.slice(0, index);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {any} object
|
||||
* @returns {object is Array<any>}
|
||||
*/
|
||||
function isNonEmptyArray(object) {
|
||||
return Array.isArray(object) && object.length > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} description
|
||||
* @returns {(node: any) => symbol}
|
||||
@@ -664,7 +513,6 @@ module.exports = {
|
||||
addDanglingComment,
|
||||
addTrailingComment,
|
||||
isFrontMatterNode,
|
||||
getShebang,
|
||||
isNonEmptyArray,
|
||||
createGroupIdMapper,
|
||||
};
|
||||
@@ -3,8 +3,8 @@
|
||||
const path = require("path");
|
||||
|
||||
const editorconfig = require("editorconfig");
|
||||
const mem = require("mem");
|
||||
const editorConfigToPrettier = require("editorconfig-to-prettier");
|
||||
const { default: mem, memClear } = require("../../vendors/mem.js");
|
||||
const findProjectRoot = require("./find-project-root.js");
|
||||
|
||||
const jsonStringifyMem = (fn) => mem(fn, { cacheKey: JSON.stringify });
|
||||
@@ -36,8 +36,8 @@ function getLoadFunction(opts) {
|
||||
}
|
||||
|
||||
function clearCache() {
|
||||
mem.clear(editorconfigSyncWithCache);
|
||||
mem.clear(editorconfigAsyncWithCache);
|
||||
memClear(editorconfigSyncWithCache);
|
||||
memClear(editorconfigAsyncWithCache);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
|
||||
const path = require("path");
|
||||
const minimatch = require("minimatch");
|
||||
const mem = require("mem");
|
||||
const thirdParty = require("../common/third-party.js");
|
||||
|
||||
const loadToml = require("../utils/load-toml.js");
|
||||
const loadJson5 = require("../utils/load-json5.js");
|
||||
const resolve = require("../common/resolve.js");
|
||||
const { default: mem, memClear } = require("../../vendors/mem.js");
|
||||
const resolveEditorConfig = require("./resolve-config-editorconfig.js");
|
||||
|
||||
/**
|
||||
@@ -127,7 +127,7 @@ const resolveConfig = (filePath, opts) => _resolveConfig(filePath, opts, false);
|
||||
resolveConfig.sync = (filePath, opts) => _resolveConfig(filePath, opts, true);
|
||||
|
||||
function clearCache() {
|
||||
mem.clear(getExplorerMemoized);
|
||||
memClear(getExplorerMemoized);
|
||||
resolveEditorConfig.clearCache();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
"use strict";
|
||||
|
||||
const { getStringWidth, getLast } = require("../common/util.js");
|
||||
const { convertEndOfLineToChars } = require("../common/end-of-line.js");
|
||||
const getLast = require("../utils/get-last.js");
|
||||
const getStringWidth = require("../utils/get-string-width.js");
|
||||
const { fill, cursor, indent } = require("./doc-builders.js");
|
||||
const { isConcat, getDocParts } = require("./doc-utils.js");
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
"use strict";
|
||||
|
||||
const getLast = require("../utils/get-last.js");
|
||||
const { literalline, join } = require("./doc-builders.js");
|
||||
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
"use strict";
|
||||
|
||||
const { skipEverythingButNewLine } = require("../utils/text/skip.js");
|
||||
const getLast = require("../utils/get-last.js");
|
||||
const isNonEmptyArray = require("../utils/is-non-empty-array.js");
|
||||
const lineColumnToIndex = require("../utils/line-column-to-index.js");
|
||||
const {
|
||||
getLast,
|
||||
skipEverythingButNewLine,
|
||||
isNonEmptyArray,
|
||||
} = require("../common/util.js");
|
||||
|
||||
function calculateLocStart(node, text) {
|
||||
// `postcss>=8`
|
||||
|
||||
@@ -4,16 +4,14 @@ const createError = require("../common/parser-create-error.js");
|
||||
const getLast = require("../utils/get-last.js");
|
||||
const parseFrontMatter = require("../utils/front-matter/parse.js");
|
||||
const { hasPragma } = require("./pragma.js");
|
||||
const {
|
||||
hasSCSSInterpolation,
|
||||
hasStringOrFunction,
|
||||
isSCSSNestedPropertyNode,
|
||||
isSCSSVariable,
|
||||
stringifyNode,
|
||||
isModuleRuleName,
|
||||
} = require("./utils.js");
|
||||
const { locStart, locEnd } = require("./loc.js");
|
||||
const { calculateLoc, replaceQuotesInInlineComments } = require("./loc.js");
|
||||
const hasSCSSInterpolation = require("./utils/has-SCSS-interpolation.js");
|
||||
const hasStringOrFunction = require("./utils/has-string-or-function.js");
|
||||
const isSCSSNestedPropertyNode = require("./utils/is-SCSS-nested-property-node.js");
|
||||
const isSCSSVariable = require("./utils/is-SCSS-variable.js");
|
||||
const stringifyNode = require("./utils/stringify-node.js");
|
||||
const isModuleRuleName = require("./utils/is-module-rule-name.js");
|
||||
|
||||
const getHighestAncestor = (node) => {
|
||||
while (node.parent) {
|
||||
|
||||
@@ -74,8 +74,10 @@ const {
|
||||
isAtWordPlaceholderNode,
|
||||
isConfigurationNode,
|
||||
isParenGroupNode,
|
||||
} = require("./utils.js");
|
||||
} = require("./utils/index.js");
|
||||
const { locStart, locEnd } = require("./loc.js");
|
||||
const isLessParser = require("./utils/is-less-parser.js");
|
||||
const isSCSS = require("./utils/is-scss.js");
|
||||
|
||||
function shouldPrintComma(options) {
|
||||
return options.trailingComma === "es5" || options.trailingComma === "all";
|
||||
@@ -501,8 +503,8 @@ function genericPrint(path, options, print) {
|
||||
grandParent.type === "value-func" &&
|
||||
grandParent.value === "selector"
|
||||
) {
|
||||
const start = locStart(parentNode.open) + 1;
|
||||
const end = locEnd(parentNode.close) - 1;
|
||||
const start = locEnd(parentNode.open) + 1;
|
||||
const end = locStart(parentNode.close);
|
||||
const selector = options.originalText.slice(start, end).trim();
|
||||
|
||||
return lastLineHasInlineComment(selector)
|
||||
@@ -909,26 +911,40 @@ function genericPrint(path, options, print) {
|
||||
indent([
|
||||
softline,
|
||||
join(
|
||||
[",", line],
|
||||
path.map((childPath) => {
|
||||
const node = childPath.getValue();
|
||||
const printed = print();
|
||||
[line],
|
||||
path.map((childPath, index) => {
|
||||
const child = childPath.getValue();
|
||||
const isLast = index === node.groups.length - 1;
|
||||
const printed = [print(), isLast ? "" : ","];
|
||||
|
||||
// Key/Value pair in open paren already indented
|
||||
if (
|
||||
isKeyValuePairNode(node) &&
|
||||
node.type === "value-comma_group" &&
|
||||
node.groups &&
|
||||
node.groups[0].type !== "value-paren_group" &&
|
||||
node.groups[2] &&
|
||||
node.groups[2].type === "value-paren_group"
|
||||
isKeyValuePairNode(child) &&
|
||||
child.type === "value-comma_group" &&
|
||||
child.groups &&
|
||||
child.groups[0].type !== "value-paren_group" &&
|
||||
child.groups[2] &&
|
||||
child.groups[2].type === "value-paren_group"
|
||||
) {
|
||||
const parts = getDocParts(printed.contents.contents);
|
||||
const parts = getDocParts(printed[0].contents.contents);
|
||||
parts[1] = group(parts[1]);
|
||||
|
||||
return group(dedent(printed));
|
||||
}
|
||||
|
||||
if (
|
||||
!isLast &&
|
||||
child.type === "value-comma_group" &&
|
||||
child.groups &&
|
||||
child.groups[0].type !== "value-paren_group" &&
|
||||
isNextLineEmpty(
|
||||
options.originalText,
|
||||
getLast(child.groups),
|
||||
locEnd
|
||||
)
|
||||
) {
|
||||
printed.push(hardline);
|
||||
}
|
||||
|
||||
return printed;
|
||||
}, "groups")
|
||||
),
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
"use strict";
|
||||
|
||||
const isNonEmptyArray = require("../../utils/is-non-empty-array.js");
|
||||
|
||||
function hasSCSSInterpolation(groupList) {
|
||||
if (isNonEmptyArray(groupList)) {
|
||||
for (let i = groupList.length - 1; i > 0; i--) {
|
||||
// If we find `#{`, return true.
|
||||
if (
|
||||
groupList[i].type === "word" &&
|
||||
groupList[i].value === "{" &&
|
||||
groupList[i - 1].type === "word" &&
|
||||
groupList[i - 1].value.endsWith("#")
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
module.exports = hasSCSSInterpolation;
|
||||
@@ -0,0 +1,16 @@
|
||||
"use strict";
|
||||
|
||||
const isNonEmptyArray = require("../../utils/is-non-empty-array.js");
|
||||
|
||||
function hasStringOrFunction(groupList) {
|
||||
if (isNonEmptyArray(groupList)) {
|
||||
for (let i = 0; i < groupList.length; i++) {
|
||||
if (groupList[i].type === "string" || groupList[i].type === "func") {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
module.exports = hasStringOrFunction;
|
||||
@@ -1,6 +1,5 @@
|
||||
"use strict";
|
||||
|
||||
const { isNonEmptyArray } = require("../common/util.js");
|
||||
const colorAdjusterFunctions = new Set([
|
||||
"red",
|
||||
"green",
|
||||
@@ -28,7 +27,6 @@ const colorAdjusterFunctions = new Set([
|
||||
"hwb",
|
||||
"hwba",
|
||||
]);
|
||||
const moduleRuleNames = new Set(["import", "use", "forward"]);
|
||||
|
||||
function getAncestorCounter(path, typeOrTypes) {
|
||||
const types = Array.isArray(typeOrTypes) ? typeOrTypes : [typeOrTypes];
|
||||
@@ -60,43 +58,6 @@ function getPropOfDeclNode(path) {
|
||||
);
|
||||
}
|
||||
|
||||
function hasSCSSInterpolation(groupList) {
|
||||
if (isNonEmptyArray(groupList)) {
|
||||
for (let i = groupList.length - 1; i > 0; i--) {
|
||||
// If we find `#{`, return true.
|
||||
if (
|
||||
groupList[i].type === "word" &&
|
||||
groupList[i].value === "{" &&
|
||||
groupList[i - 1].type === "word" &&
|
||||
groupList[i - 1].value.endsWith("#")
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function hasStringOrFunction(groupList) {
|
||||
if (isNonEmptyArray(groupList)) {
|
||||
for (let i = 0; i < groupList.length; i++) {
|
||||
if (groupList[i].type === "string" || groupList[i].type === "func") {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function isSCSSVariable(node, options) {
|
||||
return (
|
||||
options.parser === "scss" &&
|
||||
node &&
|
||||
node.type === "word" &&
|
||||
node.value.startsWith("$")
|
||||
);
|
||||
}
|
||||
|
||||
function isWideKeywords(value) {
|
||||
return ["initial", "inherit", "unset", "revert"].includes(
|
||||
value.toLowerCase()
|
||||
@@ -265,6 +226,7 @@ function isSCSSControlDirectiveNode(node, options) {
|
||||
);
|
||||
}
|
||||
|
||||
<<<<<<< HEAD:src/language-css/utils.js
|
||||
function isSCSSNestedPropertyNode(node, options) {
|
||||
if (options.parser !== "scss") {
|
||||
return false;
|
||||
@@ -282,6 +244,8 @@ function isSCSSNestedPropertyNode(node, options) {
|
||||
.endsWith(":");
|
||||
}
|
||||
|
||||
=======
|
||||
>>>>>>> main:src/language-css/utils/index.js
|
||||
function isDetachedRulesetCallNode(node) {
|
||||
return node.raws && node.raws.params && /^\(\s*\)$/.test(node.raws.params);
|
||||
}
|
||||
@@ -444,35 +408,6 @@ function lastLineHasInlineComment(text) {
|
||||
return /\/\//.test(text.split(/[\n\r]/).pop());
|
||||
}
|
||||
|
||||
function stringifyNode(node) {
|
||||
if (node.groups) {
|
||||
const open = node.open && node.open.value ? node.open.value : "";
|
||||
const groups = node.groups.reduce(
|
||||
(previousValue, currentValue, index) =>
|
||||
previousValue +
|
||||
stringifyNode(currentValue) +
|
||||
(node.groups[0].type === "comma_group" &&
|
||||
index !== node.groups.length - 1
|
||||
? ","
|
||||
: ""),
|
||||
""
|
||||
);
|
||||
const close = node.close && node.close.value ? node.close.value : "";
|
||||
|
||||
return open + groups + close;
|
||||
}
|
||||
|
||||
const before = node.raws && node.raws.before ? node.raws.before : "";
|
||||
const quote = node.raws && node.raws.quote ? node.raws.quote : "";
|
||||
const atword = node.type === "atword" ? "@" : "";
|
||||
const value = node.value ? node.value : "";
|
||||
const unit = node.unit ? node.unit : "";
|
||||
const group = node.group ? stringifyNode(node.group) : "";
|
||||
const after = node.raws && node.raws.after ? node.raws.after : "";
|
||||
|
||||
return before + quote + atword + value + quote + unit + group + after;
|
||||
}
|
||||
|
||||
function isAtWordPlaceholderNode(node) {
|
||||
return (
|
||||
node &&
|
||||
@@ -481,10 +416,6 @@ function isAtWordPlaceholderNode(node) {
|
||||
);
|
||||
}
|
||||
|
||||
function isModuleRuleName(name) {
|
||||
return moduleRuleNames.has(name);
|
||||
}
|
||||
|
||||
function isConfigurationNode(node, parentNode) {
|
||||
if (
|
||||
!node.open ||
|
||||
@@ -523,8 +454,6 @@ module.exports = {
|
||||
getAncestorCounter,
|
||||
getAncestorNode,
|
||||
getPropOfDeclNode,
|
||||
hasSCSSInterpolation,
|
||||
hasStringOrFunction,
|
||||
maybeToLowerCase,
|
||||
insideValueFunctionNode,
|
||||
insideICSSRuleNode,
|
||||
@@ -532,7 +461,6 @@ module.exports = {
|
||||
insideURLFunctionInImportAtRuleNode,
|
||||
isKeyframeAtRuleKeywords,
|
||||
isWideKeywords,
|
||||
isSCSSVariable,
|
||||
isLastNode,
|
||||
isSCSSControlDirectiveNode,
|
||||
isDetachedRulesetDeclarationNode,
|
||||
@@ -551,7 +479,6 @@ module.exports = {
|
||||
hasComposesNode,
|
||||
hasParensAroundNode,
|
||||
hasEmptyRawBefore,
|
||||
isSCSSNestedPropertyNode,
|
||||
isDetachedRulesetCallNode,
|
||||
isTemplatePlaceholderNode,
|
||||
isTemplatePropNode,
|
||||
@@ -569,9 +496,7 @@ module.exports = {
|
||||
isMediaAndSupportsKeywords,
|
||||
isColorAdjusterFuncNode,
|
||||
lastLineHasInlineComment,
|
||||
stringifyNode,
|
||||
isAtWordPlaceholderNode,
|
||||
isModuleRuleName,
|
||||
isConfigurationNode,
|
||||
isParenGroupNode,
|
||||
};
|
||||
@@ -0,0 +1,16 @@
|
||||
"use strict";
|
||||
|
||||
function isSCSSNestedPropertyNode(node) {
|
||||
/* istanbul ignore next */
|
||||
if (!node.selector) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return node.selector
|
||||
.replace(/\/\*.*?\*\//, "")
|
||||
.replace(/\/\/.*\n/, "")
|
||||
.trim()
|
||||
.endsWith(":");
|
||||
}
|
||||
|
||||
module.exports = isSCSSNestedPropertyNode;
|
||||
@@ -0,0 +1,7 @@
|
||||
"use strict";
|
||||
|
||||
function isSCSSVariable(node) {
|
||||
return Boolean(node && node.type === "word" && node.value.startsWith("$"));
|
||||
}
|
||||
|
||||
module.exports = isSCSSVariable;
|
||||
@@ -0,0 +1,9 @@
|
||||
"use strict";
|
||||
|
||||
const moduleRuleNames = new Set(["import", "use", "forward"]);
|
||||
|
||||
function isModuleRuleName(name) {
|
||||
return moduleRuleNames.has(name);
|
||||
}
|
||||
|
||||
module.exports = isModuleRuleName;
|
||||
@@ -0,0 +1,32 @@
|
||||
"use strict";
|
||||
|
||||
function stringifyNode(node) {
|
||||
if (node.groups) {
|
||||
const open = node.open && node.open.value ? node.open.value : "";
|
||||
const groups = node.groups.reduce(
|
||||
(previousValue, currentValue, index) =>
|
||||
previousValue +
|
||||
stringifyNode(currentValue) +
|
||||
(node.groups[0].type === "comma_group" &&
|
||||
index !== node.groups.length - 1
|
||||
? ","
|
||||
: ""),
|
||||
""
|
||||
);
|
||||
const close = node.close && node.close.value ? node.close.value : "";
|
||||
|
||||
return open + groups + close;
|
||||
}
|
||||
|
||||
const before = node.raws && node.raws.before ? node.raws.before : "";
|
||||
const quote = node.raws && node.raws.quote ? node.raws.quote : "";
|
||||
const atword = node.type === "atword" ? "@" : "";
|
||||
const value = node.value ? node.value : "";
|
||||
const unit = node.unit ? node.unit : "";
|
||||
const group = node.group ? stringifyNode(node.group) : "";
|
||||
const after = node.raws && node.raws.after ? node.raws.after : "";
|
||||
|
||||
return before + quote + atword + value + quote + unit + group + after;
|
||||
}
|
||||
|
||||
module.exports = stringifyNode;
|
||||
@@ -28,10 +28,10 @@ const {
|
||||
isVueSlotAttribute,
|
||||
isVueSfcBindingsAttribute,
|
||||
getTextValueParts,
|
||||
} = require("./utils.js");
|
||||
} = require("./utils/index.js");
|
||||
const getNodeContent = require("./get-node-content.js");
|
||||
|
||||
function printEmbeddedAttributeValue(node, originalTextToDoc, options) {
|
||||
function printEmbeddedAttributeValue(node, htmlTextToDoc, options) {
|
||||
const isKeyMatched = (patterns) =>
|
||||
new RegExp(patterns.join("|")).test(node.fullName);
|
||||
const getValue = () => unescapeQuoteEntities(node.value);
|
||||
@@ -67,11 +67,11 @@ function printEmbeddedAttributeValue(node, originalTextToDoc, options) {
|
||||
const printMaybeHug = (doc) => (shouldHug ? printHug(doc) : printExpand(doc));
|
||||
|
||||
const attributeTextToDoc = (code, opts) =>
|
||||
originalTextToDoc(
|
||||
code,
|
||||
{ __onHtmlBindingRoot, __embeddedInHtml: true, ...opts },
|
||||
{ stripTrailingHardline: true }
|
||||
);
|
||||
htmlTextToDoc(code, {
|
||||
__onHtmlBindingRoot,
|
||||
__embeddedInHtml: true,
|
||||
...opts,
|
||||
});
|
||||
|
||||
if (
|
||||
node.fullName === "srcset" &&
|
||||
|
||||
@@ -9,11 +9,9 @@ const parseFrontMatter = require("../utils/front-matter/parse.js");
|
||||
const getLast = require("../utils/get-last.js");
|
||||
const createError = require("../common/parser-create-error.js");
|
||||
const { inferParserByLanguage } = require("../common/util.js");
|
||||
const {
|
||||
HTML_ELEMENT_ATTRIBUTES,
|
||||
HTML_TAGS,
|
||||
isUnknownNamespace,
|
||||
} = require("./utils.js");
|
||||
const HTML_TAGS = require("./utils/html-tag-names.js");
|
||||
const HTML_ELEMENT_ATTRIBUTES = require("./utils/html-elements-attributes.js");
|
||||
const isUnknownNamespace = require("./utils/is-unknown-namespace.js");
|
||||
const { hasPragma } = require("./pragma.js");
|
||||
const { Node } = require("./ast.js");
|
||||
const { parseIeConditionalComment } = require("./conditional-comment.js");
|
||||
|
||||
@@ -14,7 +14,7 @@ const {
|
||||
isLeadingSpaceSensitiveNode,
|
||||
isTrailingSpaceSensitiveNode,
|
||||
isWhitespaceSensitiveNode,
|
||||
} = require("./utils.js");
|
||||
} = require("./utils/index.js");
|
||||
|
||||
const PREPROCESS_PIPELINE = [
|
||||
removeIgnorableFirstLf,
|
||||
|
||||
@@ -11,7 +11,7 @@ const {
|
||||
isTextLikeNode,
|
||||
hasPrettierIgnore,
|
||||
preferHardlineAsLeadingSpaces,
|
||||
} = require("../utils.js");
|
||||
} = require("../utils/index.js");
|
||||
const {
|
||||
printOpeningTagPrefix,
|
||||
needsToBorrowNextOpeningTagStartMarker,
|
||||
|
||||
@@ -20,7 +20,7 @@ const {
|
||||
isVueCustomBlock,
|
||||
countParents,
|
||||
forceBreakContent,
|
||||
} = require("../utils.js");
|
||||
} = require("../utils/index.js");
|
||||
const {
|
||||
printOpeningTagPrefix,
|
||||
printOpeningTag,
|
||||
|
||||
@@ -17,7 +17,7 @@ const {
|
||||
isPreLikeNode,
|
||||
hasPrettierIgnore,
|
||||
shouldPreserveContent,
|
||||
} = require("../utils.js");
|
||||
} = require("../utils/index.js");
|
||||
|
||||
function printClosingTag(node, options) {
|
||||
return [
|
||||
|
||||
@@ -13,7 +13,7 @@ const {
|
||||
countChars,
|
||||
unescapeQuoteEntities,
|
||||
getTextValueParts,
|
||||
} = require("./utils.js");
|
||||
} = require("./utils/index.js");
|
||||
const preprocess = require("./print-preprocess.js");
|
||||
const { insertPragma } = require("./pragma.js");
|
||||
const { locStart, locEnd } = require("./loc.js");
|
||||
|
||||
@@ -40,8 +40,13 @@ function parseVueFor(value) {
|
||||
if (!inMatch) {
|
||||
return;
|
||||
}
|
||||
|
||||
const res = {};
|
||||
res.for = inMatch[3].trim();
|
||||
if (!res.for) {
|
||||
return;
|
||||
}
|
||||
|
||||
const alias = inMatch[1].trim().replace(stripParensRE, "");
|
||||
const iteratorMatch = alias.match(forIteratorRE);
|
||||
if (iteratorMatch) {
|
||||
@@ -54,10 +59,18 @@ function parseVueFor(value) {
|
||||
res.alias = alias;
|
||||
}
|
||||
|
||||
const left = [res.alias, res.iterator1, res.iterator2];
|
||||
if (
|
||||
left.some(
|
||||
(part, index) =>
|
||||
!part && (index === 0 || left.slice(index + 1).some(Boolean))
|
||||
)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
return {
|
||||
left: `${[res.alias, res.iterator1, res.iterator2]
|
||||
.filter(Boolean)
|
||||
.join(",")}`,
|
||||
left: left.filter(Boolean).join(","),
|
||||
operator: inMatch[2],
|
||||
right: res.for,
|
||||
};
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
"use strict";
|
||||
|
||||
function arrayToMap(array) {
|
||||
const map = Object.create(null);
|
||||
for (const value of array) {
|
||||
map[value] = true;
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
module.exports = arrayToMap;
|
||||
@@ -0,0 +1,9 @@
|
||||
"use strict";
|
||||
|
||||
const htmlElementAttributes = require("html-element-attributes");
|
||||
const mapObject = require("./map-object.js");
|
||||
const arrayToMap = require("./array-to-map.js");
|
||||
|
||||
const HTML_ELEMENT_ATTRIBUTES = mapObject(htmlElementAttributes, arrayToMap);
|
||||
|
||||
module.exports = HTML_ELEMENT_ATTRIBUTES;
|
||||
@@ -0,0 +1,8 @@
|
||||
"use strict";
|
||||
|
||||
const htmlTagNames = require("html-tag-names");
|
||||
const arrayToMap = require("./array-to-map.js");
|
||||
|
||||
const HTML_TAGS = arrayToMap(htmlTagNames);
|
||||
|
||||
module.exports = HTML_TAGS;
|
||||
@@ -1,28 +1,24 @@
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* @typedef {import("../common/ast-path")} AstPath
|
||||
* @typedef {import("../../common/ast-path")} AstPath
|
||||
*/
|
||||
|
||||
const htmlTagNames = require("html-tag-names");
|
||||
const htmlElementAttributes = require("html-element-attributes");
|
||||
const {
|
||||
inferParserByLanguage,
|
||||
isFrontMatterNode,
|
||||
} = require("../common/util.js");
|
||||
} = require("../../common/util.js");
|
||||
const {
|
||||
builders: { line, hardline, join },
|
||||
utils: { getDocParts, replaceTextEndOfLine },
|
||||
} = require("../document/index.js");
|
||||
} = require("../../document/index.js");
|
||||
const {
|
||||
CSS_DISPLAY_TAGS,
|
||||
CSS_DISPLAY_DEFAULT,
|
||||
CSS_WHITE_SPACE_TAGS,
|
||||
CSS_WHITE_SPACE_DEFAULT,
|
||||
} = require("./constants.evaluate.js");
|
||||
|
||||
const HTML_TAGS = arrayToMap(htmlTagNames);
|
||||
const HTML_ELEMENT_ATTRIBUTES = mapObject(htmlElementAttributes, arrayToMap);
|
||||
} = require("../constants.evaluate.js");
|
||||
const isUnknownNamespace = require("./is-unknown-namespace.js");
|
||||
|
||||
// https://infra.spec.whatwg.org/#ascii-whitespace
|
||||
const HTML_WHITESPACE = new Set(["\t", "\n", "\f", "\r", " "]);
|
||||
@@ -47,22 +43,6 @@ const getLeadingAndTrailingHtmlWhitespace = (string) => {
|
||||
};
|
||||
const hasHtmlWhitespace = (string) => /[\t\n\f\r ]/.test(string);
|
||||
|
||||
function arrayToMap(array) {
|
||||
const map = Object.create(null);
|
||||
for (const value of array) {
|
||||
map[value] = true;
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
function mapObject(object, fn) {
|
||||
const newObject = Object.create(null);
|
||||
for (const [key, value] of Object.entries(object)) {
|
||||
newObject[key] = fn(value, key);
|
||||
}
|
||||
return newObject;
|
||||
}
|
||||
|
||||
function shouldPreserveContent(node, options) {
|
||||
// unterminated node in ie conditional comment
|
||||
// e.g. <!--[if lt IE 9]><html><![endif]-->
|
||||
@@ -539,14 +519,6 @@ function getNodeCssStyleDisplay(node, options) {
|
||||
}
|
||||
}
|
||||
|
||||
function isUnknownNamespace(node) {
|
||||
return (
|
||||
node.type === "element" &&
|
||||
!node.hasExplicitNamespace &&
|
||||
!["html", "svg"].includes(node.namespace)
|
||||
);
|
||||
}
|
||||
|
||||
function getNodeCssStyleWhiteSpace(node) {
|
||||
return (
|
||||
(node.type === "element" &&
|
||||
@@ -667,8 +639,6 @@ function getTextValueParts(node, value = node.value) {
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
HTML_ELEMENT_ATTRIBUTES,
|
||||
HTML_TAGS,
|
||||
htmlTrim,
|
||||
htmlTrimPreserveIndentation,
|
||||
hasHtmlWhitespace,
|
||||
@@ -0,0 +1,11 @@
|
||||
"use strict";
|
||||
|
||||
function isUnknownNamespace(node) {
|
||||
return (
|
||||
node.type === "element" &&
|
||||
!node.hasExplicitNamespace &&
|
||||
!["html", "svg"].includes(node.namespace)
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = isUnknownNamespace;
|
||||
@@ -0,0 +1,11 @@
|
||||
"use strict";
|
||||
|
||||
function mapObject(object, fn) {
|
||||
const newObject = Object.create(null);
|
||||
for (const [key, value] of Object.entries(object)) {
|
||||
newObject[key] = fn(value, key);
|
||||
}
|
||||
return newObject;
|
||||
}
|
||||
|
||||
module.exports = mapObject;
|
||||
@@ -1,6 +1,6 @@
|
||||
"use strict";
|
||||
|
||||
const { isBlockComment } = require("./utils.js");
|
||||
const isBlockComment = require("./utils/is-block-comment.js");
|
||||
|
||||
const ignoredProperties = new Set([
|
||||
"range",
|
||||
|
||||
@@ -13,7 +13,6 @@ const {
|
||||
isNonEmptyArray,
|
||||
} = require("../common/util.js");
|
||||
const {
|
||||
isBlockComment,
|
||||
getFunctionParameters,
|
||||
isPrettierIgnoreComment,
|
||||
isJsxNode,
|
||||
@@ -25,11 +24,13 @@ const {
|
||||
isCallExpression,
|
||||
isMemberExpression,
|
||||
isObjectProperty,
|
||||
isLineComment,
|
||||
getComments,
|
||||
CommentCheckFlags,
|
||||
markerForIfWithoutBlockAndSameLineComment,
|
||||
} = require("./utils.js");
|
||||
} = require("./utils/index.js");
|
||||
const { locStart, locEnd } = require("./loc.js");
|
||||
const isBlockComment = require("./utils/is-block-comment.js");
|
||||
|
||||
/**
|
||||
* @typedef {import("./types/estree").Node} Node
|
||||
@@ -68,6 +69,7 @@ function handleOwnLineComment(context) {
|
||||
handleAssignmentPatternComments,
|
||||
handleMethodNameComments,
|
||||
handleLabeledStatementComments,
|
||||
handleBreakAndContinueStatementComments,
|
||||
].some((fn) => fn(context));
|
||||
}
|
||||
|
||||
@@ -91,6 +93,8 @@ function handleEndOfLineComment(context) {
|
||||
handleOnlyComments,
|
||||
handleTypeAliasComments,
|
||||
handleVariableDeclaratorComments,
|
||||
handleBreakAndContinueStatementComments,
|
||||
handleSwitchDefaultCaseComments,
|
||||
].some((fn) => fn(context));
|
||||
}
|
||||
|
||||
@@ -423,6 +427,17 @@ function handleClassComments({
|
||||
// Don't add leading comments to `implements`, `extends`, `mixins` to
|
||||
// avoid printing the comment after the keyword.
|
||||
if (followingNode) {
|
||||
if (
|
||||
enclosingNode.superClass &&
|
||||
followingNode === enclosingNode.superClass &&
|
||||
precedingNode &&
|
||||
(precedingNode === enclosingNode.id ||
|
||||
precedingNode === enclosingNode.typeParameters)
|
||||
) {
|
||||
addTrailingComment(precedingNode, comment);
|
||||
return true;
|
||||
}
|
||||
|
||||
for (const prop of ["implements", "extends", "mixins"]) {
|
||||
if (enclosingNode[prop] && followingNode === enclosingNode[prop][0]) {
|
||||
if (
|
||||
@@ -455,6 +470,7 @@ function handleMethodNameComments({
|
||||
if (
|
||||
enclosingNode &&
|
||||
precedingNode &&
|
||||
getNextNonSpaceNonCommentCharacter(text, comment, locEnd) === "(" &&
|
||||
// "MethodDefinition" is handled in getCommentChildNodes
|
||||
(enclosingNode.type === "Property" ||
|
||||
enclosingNode.type === "TSDeclareMethod" ||
|
||||
@@ -895,6 +911,28 @@ function handleTSMappedTypeComments({
|
||||
return false;
|
||||
}
|
||||
|
||||
function handleSwitchDefaultCaseComments({
|
||||
comment,
|
||||
enclosingNode,
|
||||
followingNode,
|
||||
}) {
|
||||
if (
|
||||
!enclosingNode ||
|
||||
enclosingNode.type !== "SwitchCase" ||
|
||||
enclosingNode.test
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (followingNode.type === "BlockStatement" && isLineComment(comment)) {
|
||||
addBlockStatementFirstComment(followingNode, comment);
|
||||
} else {
|
||||
addDanglingComment(enclosingNode, comment);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Node} node
|
||||
* @returns {boolean}
|
||||
@@ -931,6 +969,7 @@ function getCommentChildNodes(node, options) {
|
||||
if (
|
||||
(options.parser === "typescript" ||
|
||||
options.parser === "flow" ||
|
||||
options.parser === "acorn" ||
|
||||
options.parser === "espree" ||
|
||||
options.parser === "meriyah" ||
|
||||
options.parser === "__babel_estree") &&
|
||||
|
||||
@@ -4,7 +4,7 @@ const {
|
||||
hasComment,
|
||||
CommentCheckFlags,
|
||||
isObjectProperty,
|
||||
} = require("./utils.js");
|
||||
} = require("./utils/index.js");
|
||||
const formatMarkdown = require("./embed/markdown.js");
|
||||
const formatCss = require("./embed/css.js");
|
||||
const formatGraphql = require("./embed/graphql.js");
|
||||
|
||||
@@ -13,6 +13,7 @@ const languages = [
|
||||
since: "0.0.0",
|
||||
parsers: [
|
||||
"babel",
|
||||
"acorn",
|
||||
"espree",
|
||||
"meriyah",
|
||||
"babel-flow",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"use strict";
|
||||
|
||||
const { isNonEmptyArray } = require("../common/util.js");
|
||||
const isNonEmptyArray = require("../utils/is-non-empty-array.js");
|
||||
|
||||
/**
|
||||
* @typedef {import("./types/estree").Node} Node
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
"use strict";
|
||||
|
||||
const getLast = require("../utils/get-last.js");
|
||||
const isNonEmptyArray = require("../utils/is-non-empty-array.js");
|
||||
const {
|
||||
getFunctionParameters,
|
||||
getLeftSidePathName,
|
||||
@@ -14,7 +15,7 @@ const {
|
||||
isCallExpression,
|
||||
isMemberExpression,
|
||||
isObjectProperty,
|
||||
} = require("./utils.js");
|
||||
} = require("./utils/index.js");
|
||||
|
||||
function needsParens(path, options) {
|
||||
const parent = path.getParentNode();
|
||||
@@ -95,7 +96,6 @@ function needsParens(path, options) {
|
||||
node.type === "LogicalExpression" ||
|
||||
node.type === "NewExpression" ||
|
||||
node.type === "ObjectExpression" ||
|
||||
node.type === "ParenthesizedExpression" ||
|
||||
node.type === "SequenceExpression" ||
|
||||
node.type === "TaggedTemplateExpression" ||
|
||||
node.type === "UnaryExpression" ||
|
||||
@@ -668,6 +668,10 @@ function needsParens(path, options) {
|
||||
}
|
||||
|
||||
case "ClassExpression":
|
||||
if (isNonEmptyArray(node.decorators)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (parent.type) {
|
||||
case "NewExpression":
|
||||
return name === "callee";
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
"use strict";
|
||||
|
||||
const acorn = require("./acorn.js");
|
||||
const espree = require("./espree.js");
|
||||
|
||||
module.exports = {
|
||||
parsers: {
|
||||
acorn,
|
||||
espree,
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,81 @@
|
||||
"use strict";
|
||||
|
||||
const createError = require("../../common/parser-create-error.js");
|
||||
const tryCombinations = require("../../utils/try-combinations.js");
|
||||
const createParser = require("./utils/create-parser.js");
|
||||
const postprocess = require("./postprocess/index.js");
|
||||
|
||||
/** @type {import("acorn").Options} */
|
||||
const parseOptions = {
|
||||
ecmaVersion: "latest",
|
||||
sourceType: "module",
|
||||
allowReserved: true,
|
||||
allowReturnOutsideFunction: true,
|
||||
allowImportExportEverywhere: true,
|
||||
allowAwaitOutsideFunction: true,
|
||||
allowSuperOutsideMethod: true,
|
||||
allowHashBang: true,
|
||||
locations: true,
|
||||
ranges: true,
|
||||
};
|
||||
|
||||
function createParseError(error) {
|
||||
const { message, loc } = error;
|
||||
|
||||
/* istanbul ignore next */
|
||||
if (!loc) {
|
||||
return error;
|
||||
}
|
||||
|
||||
const { line, column } = loc;
|
||||
|
||||
return createError(message.replace(/ \(\d+:\d+\)$/, ""), {
|
||||
start: { line, column: column + 1 },
|
||||
});
|
||||
}
|
||||
|
||||
let parser;
|
||||
const getParser = () => {
|
||||
if (!parser) {
|
||||
const { Parser: AcornParser } = require("acorn");
|
||||
const acornJsx = require("acorn-jsx");
|
||||
parser = AcornParser.extend(acornJsx());
|
||||
}
|
||||
return parser;
|
||||
};
|
||||
|
||||
function parseWithOptions(text, sourceType) {
|
||||
const parser = getParser();
|
||||
|
||||
const comments = [];
|
||||
const tokens = [];
|
||||
|
||||
/** @type {any} */
|
||||
const ast = parser.parse(text, {
|
||||
...parseOptions,
|
||||
sourceType,
|
||||
onComment: comments,
|
||||
onToken: tokens,
|
||||
});
|
||||
ast.comments = comments;
|
||||
ast.tokens = tokens;
|
||||
|
||||
return ast;
|
||||
}
|
||||
|
||||
function parse(text, parsers, options = {}) {
|
||||
const { result: ast, error: moduleParseError } = tryCombinations(
|
||||
() => parseWithOptions(text, /* sourceType */ "module"),
|
||||
() => parseWithOptions(text, /* sourceType */ "script")
|
||||
);
|
||||
|
||||
if (!ast) {
|
||||
// throw the error for `module` parsing
|
||||
throw createParseError(moduleParseError);
|
||||
}
|
||||
|
||||
options.originalText = text;
|
||||
return postprocess(ast, options);
|
||||
}
|
||||
|
||||
module.exports = createParser(parse);
|
||||
@@ -1,10 +1,8 @@
|
||||
"use strict";
|
||||
|
||||
const tryCombinations = require("../../utils/try-combinations.js");
|
||||
const {
|
||||
getNextNonSpaceNonCommentCharacterIndexWithStartIndex,
|
||||
getShebang,
|
||||
} = require("../../common/util.js");
|
||||
const getShebang = require("../utils/get-shebang.js");
|
||||
const getNextNonSpaceNonCommentCharacterIndexWithStartIndex = require("../../utils/text/get-next-non-space-non-comment-character-index-with-start-index.js");
|
||||
const createParser = require("./utils/create-parser.js");
|
||||
const createBabelParseError = require("./utils/create-babel-parse-error.js");
|
||||
const postprocess = require("./postprocess/index.js");
|
||||
@@ -39,6 +37,7 @@ const parseOptions = {
|
||||
"decimal",
|
||||
"moduleBlocks",
|
||||
"asyncDoExpressions",
|
||||
"regexpUnicodeSets",
|
||||
],
|
||||
tokens: true,
|
||||
ranges: true,
|
||||
|
||||
@@ -50,8 +50,4 @@ function parse(originalText, parsers, options = {}) {
|
||||
return postprocess(ast, options);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
parsers: {
|
||||
espree: createParser(parse),
|
||||
},
|
||||
};
|
||||
module.exports = createParser(parse);
|
||||
@@ -5,7 +5,8 @@ const createParser = require("./utils/create-parser.js");
|
||||
const replaceHashbang = require("./utils/replace-hashbang.js");
|
||||
const postprocess = require("./postprocess/index.js");
|
||||
|
||||
// https://github.com/facebook/flow/tree/master/packages/flow-parser#options
|
||||
// https://github.com/facebook/flow/tree/main/packages/flow-parser#options
|
||||
// Keep this sync with `/scripts/sync-flow-test.js`
|
||||
const parseOptions = {
|
||||
// `all_comments` (boolean, default `true`) - include a list of all comments from the whole program
|
||||
// all_comments: true,
|
||||
@@ -13,23 +14,15 @@ const parseOptions = {
|
||||
comments: false,
|
||||
// `enums` (boolean, default `false`) - enable parsing of Flow enums
|
||||
enums: true,
|
||||
// `esproposal_class_instance_fields` (boolean, default `false`) - enable parsing of class instance fields
|
||||
esproposal_class_instance_fields: true,
|
||||
// `esproposal_class_static_fields` (boolean, default `false`) - enable parsing of class static fields
|
||||
esproposal_class_static_fields: true,
|
||||
// `esproposal_decorators` (boolean, default `false`) - enable parsing of decorators
|
||||
esproposal_decorators: true,
|
||||
// `esproposal_export_star_as` (boolean, default `false`) - enable parsing of `export * as` syntax
|
||||
esproposal_export_star_as: true,
|
||||
// `esproposal_nullish_coalescing` (boolean, default `false`) - enable parsing of nullish coalescing (`??`)
|
||||
esproposal_nullish_coalescing: true,
|
||||
// `esproposal_optional_chaining` (boolean, default `false`) - enable parsing of optional chaining (`?.`)
|
||||
esproposal_optional_chaining: true,
|
||||
// `types` (boolean, default `true`) - enable parsing of Flow types
|
||||
// types: true,
|
||||
// `use_strict` (boolean, default `false`) - treat the file as strict, without needing a "use strict" directive
|
||||
// use_strict: false,
|
||||
// Not documented
|
||||
// `tokens` (boolean, default `false`) - include a list of all parsed tokens in a top-level `tokens` property
|
||||
tokens: true,
|
||||
};
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"use strict";
|
||||
|
||||
const { isNonEmptyArray } = require("../../common/util.js");
|
||||
const isNonEmptyArray = require("../../utils/is-non-empty-array.js");
|
||||
const createError = require("../../common/parser-create-error.js");
|
||||
const createParser = require("./utils/create-parser.js");
|
||||
const createBabelParseError = require("./utils/create-babel-parse-error.js");
|
||||
|
||||
@@ -53,9 +53,13 @@ module.exports = {
|
||||
get __ng_directive() {
|
||||
return require("./angular.js").parsers.__ng_directive;
|
||||
},
|
||||
// JS - acorn
|
||||
get acorn() {
|
||||
return require("./acorn-and-espree.js").parsers.acorn;
|
||||
},
|
||||
// JS - espree
|
||||
get espree() {
|
||||
return require("./espree.js").parsers.espree;
|
||||
return require("./acorn-and-espree.js").parsers.espree;
|
||||
},
|
||||
// JS - meriyah
|
||||
get meriyah() {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
"use strict";
|
||||
|
||||
const { getLast } = require("../../../common/util.js");
|
||||
const { locStart, locEnd } = require("../../loc.js");
|
||||
const { isTypeCastComment } = require("../../comments.js");
|
||||
const { isTsKeywordType } = require("../../utils.js");
|
||||
const isTsKeywordType = require("../../utils/is-ts-keyword-type.js");
|
||||
const isTypeCastComment = require("../../utils/is-type-cast-comment.js");
|
||||
const getLast = require("../../../utils/get-last.js");
|
||||
const visitNode = require("./visitNode.js");
|
||||
const { throwErrorForInvalidNodes } = require("./typescript.js");
|
||||
|
||||
@@ -20,6 +20,7 @@ function postprocess(ast, options) {
|
||||
if (
|
||||
options.parser !== "typescript" &&
|
||||
options.parser !== "flow" &&
|
||||
options.parser !== "acorn" &&
|
||||
options.parser !== "espree" &&
|
||||
options.parser !== "meriyah"
|
||||
) {
|
||||
@@ -114,6 +115,29 @@ function postprocess(ast, options) {
|
||||
case "TopicReference":
|
||||
options.__isUsingHackPipeline = true;
|
||||
break;
|
||||
// TODO: Remove this when https://github.com/meriyah/meriyah/issues/200 get fixed
|
||||
case "ExportAllDeclaration": {
|
||||
const { exported } = node;
|
||||
if (
|
||||
options.parser === "meriyah" &&
|
||||
exported &&
|
||||
exported.type === "Identifier"
|
||||
) {
|
||||
const raw = options.originalText.slice(
|
||||
locStart(exported),
|
||||
locEnd(exported)
|
||||
);
|
||||
if (raw.startsWith('"') || raw.startsWith("'")) {
|
||||
node.exported = {
|
||||
...node.exported,
|
||||
type: "Literal",
|
||||
value: node.exported.name,
|
||||
raw,
|
||||
};
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -134,8 +158,8 @@ function postprocess(ast, options) {
|
||||
}
|
||||
}
|
||||
|
||||
// This is a workaround to transform `ChainExpression` from `espree`, `meriyah`,
|
||||
// and `typescript` into `babel` shape AST, we should do the opposite,
|
||||
// This is a workaround to transform `ChainExpression` from `acorn`, `espree`,
|
||||
// `meriyah`, and `typescript` into `babel` shape AST, we should do the opposite,
|
||||
// since `ChainExpression` is the standard `estree` AST for `optional chaining`
|
||||
// https://github.com/estree/estree/blob/master/es2020.md
|
||||
function transformChainExpression(node) {
|
||||
|
||||
@@ -63,7 +63,8 @@ function throwErrorForInvalidAbstractProperty(tsNode, esTreeNode) {
|
||||
function throwErrorForInvalidNodes(ast, options) {
|
||||
const { esTreeNodeToTSNodeMap, tsNodeToESTreeNodeMap } =
|
||||
options.tsParseResult;
|
||||
ast = visitNode(ast, (node) => {
|
||||
|
||||
visitNode(ast, (node) => {
|
||||
const tsNode = esTreeNodeToTSNodeMap.get(node);
|
||||
if (!tsNode) {
|
||||
return;
|
||||
|
||||
Loaded 100 of 324 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user