diff --git a/README.md b/README.md index 937fdcdc..3d6d8531 100644 --- a/README.md +++ b/README.md @@ -274,6 +274,17 @@ you can pass `--no-config` instead. Path to a file containing patterns that describe files to ignore. By default, prettier looks for `./.prettierignore`. +#### `--require-pragma` + +Require a special comment, called a pragma, to be present in the file's first docblock comment in order for prettier to format it. +```js +/** + * @prettier + */ +``` + +Valid pragmas are `@prettier` and `@format`. + #### `--list-different` Another useful flag is `--list-different` (or `-l`) which prints the filenames of files that are different from Prettier formatting. If there are differences the script errors out, which is useful in a CI scenario. @@ -288,7 +299,7 @@ Do not look for a configuration file. The default settings will be used. #### `--config-precedence` -Defines how config file should be evaluated in combination of CLI options. +Defines how config file should be evaluated in combination of CLI options. **cli-override (default)** diff --git a/docs/options.md b/docs/options.md index 06406013..67c339da 100644 --- a/docs/options.md +++ b/docs/options.md @@ -133,3 +133,26 @@ Default | CLI Override | API Override --------|--------------|------------- None | `--stdin-filepath ` | `filepath: ""` +## Require pragma +Prettier can restrict itself to only format files that contain a special comment, called a pragma, at the top of the file. This is very useful +when gradually transitioning large, unformatted codebases to prettier. + +For example, a file with the following as its first comment will be formatted when `--require-pragma` is supplied: + +```js +/** + * @prettier + */ +``` + +or + +```js +/** + * @format + */ +``` + +Default | CLI Override | API Override +--------|--------------|------------- +None | `--require-pragma` | `requirePragma` diff --git a/index.js b/index.js index cb351acc..25452ce7 100644 --- a/index.js +++ b/index.js @@ -10,6 +10,7 @@ const normalizeOptions = require("./src/options").normalize; const parser = require("./src/parser"); const printDocToDebug = require("./src/doc-debug").printDocToDebug; const config = require("./src/resolve-config"); +const docblock = require("jest-docblock"); function guessLineEnding(text) { const index = text.indexOf("\n"); @@ -30,6 +31,11 @@ function attachComments(text, ast, opts) { return astComments; } +function hasPragma(text) { + const pragmas = Object.keys(docblock.parse(docblock.extract(text))); + return pragmas.indexOf("prettier") !== -1 || pragmas.indexOf("format") !== -1; +} + function ensureAllCommentsPrinted(astComments) { if (!astComments) { return; @@ -56,6 +62,10 @@ function ensureAllCommentsPrinted(astComments) { } function formatWithCursor(text, opts, addAlignmentSize) { + if (opts.requirePragma && !hasPragma(text)) { + return { formatted: text }; + } + text = stripBom(text); addAlignmentSize = addAlignmentSize || 0; diff --git a/package.json b/package.json index 305b4f87..49db81f5 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,7 @@ "globby": "^6.1.0", "graphql": "0.10.1", "ignore": "^3.3.3", + "jest-docblock": "^21.0.2", "jest-validate": "20.0.3", "minimatch": "3.0.4", "minimist": "1.2.0", diff --git a/src/cli-constant.js b/src/cli-constant.js index 516475bd..05de15a9 100644 --- a/src/cli-constant.js +++ b/src/cli-constant.js @@ -7,7 +7,8 @@ const booleanOptionNames = [ "bracket-spacing", "jsx-bracket-same-line", // Deprecated in 0.0.10 - "flow-parser" + "flow-parser", + "require-pragma" ]; const stringOptionNames = [ @@ -86,6 +87,8 @@ Available options: Finds and prints the path to a configuration file for a given input file. --ignore-path Path to a file containing patterns that describe files to ignore. Defaults to ./.prettierignore. + --require-pragma + Require either '@prettier' or '@format' to be present in the file's first docblock comment in order for it to be formatted. --stdin Read input from stdin. --stdin-filepath Path to the file used to read from stdin. --print-width Specify the length of line that the printer will wrap on. Defaults to 80. diff --git a/src/cli-util.js b/src/cli-util.js index 3fd50001..c6b6952e 100644 --- a/src/cli-util.js +++ b/src/cli-util.js @@ -25,6 +25,7 @@ function getOptions(argv) { printWidth: getIntOption(argv, "print-width"), tabWidth: getIntOption(argv, "tab-width"), bracketSpacing: argv["bracket-spacing"], + requirePragma: argv["require-pragma"], singleQuote: argv["single-quote"], jsxBracketSameLine: argv["jsx-bracket-same-line"], filepath: argv["stdin-filepath"], diff --git a/src/options.js b/src/options.js index 25ad8c86..fb824ae5 100644 --- a/src/options.js +++ b/src/options.js @@ -15,6 +15,7 @@ const defaults = { bracketSpacing: true, jsxBracketSameLine: false, parser: "babylon", + requirePragma: false, semi: true }; diff --git a/tests/require-pragma/__snapshots__/jsfmt.spec.js.snap b/tests/require-pragma/__snapshots__/jsfmt.spec.js.snap new file mode 100644 index 00000000..66392b09 --- /dev/null +++ b/tests/require-pragma/__snapshots__/jsfmt.spec.js.snap @@ -0,0 +1,59 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`module-with-pragma.js 1`] = ` +/** + * @flow + * @format + */ + +function foo(bar) + + +{ + + return bar + + 3 + + 4; +} +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +/** + * @flow + * @format + */ + +function foo(bar) { + return bar + 3 + 4; +} + +`; + +exports[`module-without-pragma.js 1`] = ` +/** + * @flow + */ + +function foo(bar) + + +{ + + return bar + + 3 + + 4; +} +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +/** + * @flow + */ + +function foo(bar) + + +{ + + return bar + + 3 + + 4; +} + +`; diff --git a/tests/require-pragma/jsfmt.spec.js b/tests/require-pragma/jsfmt.spec.js new file mode 100644 index 00000000..61c7d29f --- /dev/null +++ b/tests/require-pragma/jsfmt.spec.js @@ -0,0 +1 @@ +run_spec(__dirname, { requirePragma: true }); diff --git a/tests/require-pragma/module-with-pragma.js b/tests/require-pragma/module-with-pragma.js new file mode 100644 index 00000000..79499ba9 --- /dev/null +++ b/tests/require-pragma/module-with-pragma.js @@ -0,0 +1,14 @@ +/** + * @flow + * @format + */ + +function foo(bar) + + +{ + + return bar + + 3 + + 4; +} diff --git a/tests/require-pragma/module-without-pragma.js b/tests/require-pragma/module-without-pragma.js new file mode 100644 index 00000000..8ece3791 --- /dev/null +++ b/tests/require-pragma/module-without-pragma.js @@ -0,0 +1,13 @@ +/** + * @flow + */ + +function foo(bar) + + +{ + + return bar + + 3 + + 4; +} diff --git a/tests_integration/__tests__/__snapshots__/early-exit.js.snap b/tests_integration/__tests__/__snapshots__/early-exit.js.snap index 00097955..c41392de 100644 --- a/tests_integration/__tests__/__snapshots__/early-exit.js.snap +++ b/tests_integration/__tests__/__snapshots__/early-exit.js.snap @@ -19,6 +19,8 @@ Available options: Finds and prints the path to a configuration file for a given input file. --ignore-path Path to a file containing patterns that describe files to ignore. Defaults to ./.prettierignore. + --require-pragma + Require either '@prettier' or '@format' to be present in the file's first docblock comment in order for it to be formatted. --stdin Read input from stdin. --stdin-filepath Path to the file used to read from stdin. --print-width Specify the length of line that the printer will wrap on. Defaults to 80. diff --git a/yarn.lock b/yarn.lock index fbdccb6d..da7e212c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2258,6 +2258,10 @@ jest-docblock@^20.0.1, jest-docblock@^20.0.3: version "20.0.3" resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-20.0.3.tgz#17bea984342cc33d83c50fbe1545ea0efaa44712" +jest-docblock@^21.0.2: + version "21.0.2" + resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-21.0.2.tgz#66f69ddb440799fc32f91d0ac3d8d35e99e2032f" + jest-environment-jsdom@^20.0.3: version "20.0.3" resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-20.0.3.tgz#048a8ac12ee225f7190417713834bb999787de99"