Skip to content

Commit

Permalink
Merge pull request #555 from source-knights/master
Browse files Browse the repository at this point in the history
Add Prettier to Maven plugin
  • Loading branch information
nedtwigg authored Apr 10, 2020
2 parents 17ad8af + ef591ef commit 3e3c969
Show file tree
Hide file tree
Showing 13 changed files with 368 additions and 3 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ lib('java.RemoveUnusedImportsStep') +'{{yes}} | {{yes}}
extra('java.EclipseFormatterStep') +'{{yes}} | {{yes}} | {{no}} |',
lib('kotlin.KtLintStep') +'{{yes}} | {{yes}} | {{no}} |',
lib('markdown.FreshMarkStep') +'{{yes}} | {{no}} | {{no}} |',
lib('npm.PrettierFormatterStep') +'{{yes}} | {{no}} | {{no}} |',
lib('npm.PrettierFormatterStep') +'{{yes}} | {{yes}} | {{no}} |',
lib('npm.TsFmtFormatterStep') +'{{yes}} | {{yes}} | {{no}} |',
lib('scala.ScalaFmtStep') +'{{yes}} | {{yes}} | {{no}} |',
lib('sql.DBeaverSQLFormatterStep') +'{{yes}} | {{no}} | {{no}} |',
Expand All @@ -73,7 +73,7 @@ extra('wtp.EclipseWtpFormatterStep') +'{{yes}} | {{yes}}
| [`java.EclipseFormatterStep`](lib-extra/src/main/java/com/diffplug/spotless/extra/java/EclipseFormatterStep.java) | :+1: | :+1: | :white_large_square: |
| [`kotlin.KtLintStep`](lib/src/main/java/com/diffplug/spotless/kotlin/KtLintStep.java) | :+1: | :+1: | :white_large_square: |
| [`markdown.FreshMarkStep`](lib/src/main/java/com/diffplug/spotless/markdown/FreshMarkStep.java) | :+1: | :white_large_square: | :white_large_square: |
| [`npm.PrettierFormatterStep`](lib/src/main/java/com/diffplug/spotless/npm/PrettierFormatterStep.java) | :+1: | :white_large_square: | :white_large_square: |
| [`npm.PrettierFormatterStep`](lib/src/main/java/com/diffplug/spotless/npm/PrettierFormatterStep.java) | :+1: | :+1: | :white_large_square: |
| [`npm.TsFmtFormatterStep`](lib/src/main/java/com/diffplug/spotless/npm/TsFmtFormatterStep.java) | :+1: | :+1: | :white_large_square: |
| [`scala.ScalaFmtStep`](lib/src/main/java/com/diffplug/spotless/scala/ScalaFmtStep.java) | :+1: | :+1: | :white_large_square: |
| [`sql.DBeaverSQLFormatterStep`](lib/src/main/java/com/diffplug/spotless/sql/DBeaverSQLFormatterStep.java) | :+1: | :white_large_square: | :white_large_square: |
Expand Down
2 changes: 2 additions & 0 deletions plugin-maven/CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (starting after version `1.27.0`).

## [Unreleased]
###
* Support for prettier ([#555](https://github.com/diffplug/spotless/pull/555)).

## [1.29.0] - 2020-04-02
### Added
Expand Down
67 changes: 66 additions & 1 deletion plugin-maven/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ Spotless supports the following powerful formatters:
* Eclipse's [CDT](https://www.eclipse.org/cdt/) C/C++ code formatter
* Eclipse's [WTP](https://www.eclipse.org/webtools/) Web-Tools code formatters
* Google's [google-java-format](https://github.com/google/google-java-format)
* [Typescript Tsfmt formatter](https://github.com/vvakame/typescript-formatter)
* [Prettier formatter](https://prettier.io)
* User-defined license enforcement, regex replacement, etc.

Contributions are welcome, see [the contributing guide](../CONTRIBUTING.md) for development info.
Expand Down Expand Up @@ -200,11 +202,13 @@ Use the Eclipse to define the *Code Style preferences* (see [Eclipse documentati
```xml
<configuration>
<typescript>
<tsfmt>

<!-- optionally define which files will be formatted. -->
<includes>
<include>src/**/*.ts</include> <!-- default value if nothing is specified -->
</includes>

<tsfmt>
<!-- must specify exactly one of the following "{foo}File" or "config" elements -->
<tslintFile>${basedir}/path/to/repo/tslint.json</tslintFile>
<tsfmtFile>${basedir}/path/to/repo/tsfmt.json</tsfmtFile>
Expand Down Expand Up @@ -243,6 +247,67 @@ Spotless will try to auto-discover an npm installation. If that is not working f

Spotless uses npm to install necessary packages locally. It runs tsfmt using [J2V8](https://github.com/eclipsesource/J2V8) internally after that.

<a name="prettier"></a>

## Applying [Prettier](https://prettier.io) to javascript | flow | typeScript | css | scss | less | jsx | graphQL | yaml | etc.

Prettier is a formatter that can format [multiple file types](https://prettier.io/docs/en/language-support.html).

To use prettier, you first have to specify the files that you want it to apply to. Then you specify prettier, and how you want to apply it.

```xml
<configuration>
<formats>

<format>
<includes>
<include>src/**/typescript/**/*.ts</include>
</includes>

<prettier>
<!-- Specify either simple prettier version (1.19.0 is max supported,
which is also default) or whole devDependencies -->
<prettierVersion>1.19.0</prettierVersion>
<devDependencies>
<prettier>1.19.0</prettier>
</devDependencies>

<!-- Specify config file and/or inline config -->
<configFile>${basedir}/path/to/configfile</configFile>
<config>
<useTabs>true</useTabs>
</config>
</prettier>
</format>

</formats>
</configuration>
```

Supported config options are documented on [prettier.io](https://prettier.io/docs/en/options.html).
Supported config file variants are documented on [prettier.io](https://prettier.io/docs/en/configuration.html).

*Please note:*
- The auto-discovery of config files (up the file tree) will not work when using prettier within spotless.
- Prettier's override syntax is not supported when using prettier within spotless.

To apply prettier to more kinds of files, just add more formats.

### Prerequisite: prettier requires a working NodeJS version

Prettier, like tsfmt, is based on NodeJS, so to use it, a working NodeJS installation (especially npm) is required on the host running spotless.
Spotless will try to auto-discover an npm installation. If that is not working for you, it is possible to directly configure the npm binary to use.

```xml
<formats><format><prettier>
<npmExecutable>/usr/bin/npm</npmExecutable>
...
```

Spotless uses npm to install necessary packages locally. It runs prettier using [J2V8](https://github.com/eclipsesource/J2V8) internally after that.
Development for J2V8 for non android envs is stopped (for Windows since J2V8 4.6.0 and Unix 4.8.0), therefore Prettier is limited to <= v1.19.0 as newer versions
use ES6 feature and that needs a newer J2V8 version.

<a name="format"></a>

## Applying to custom sources
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,10 @@ public final void addEclipseWtp(EclipseWtp eclipseWtp) {
addStepFactory(eclipseWtp);
}

public final void addPrettier(Prettier prettier) {
addStepFactory(prettier);
}

protected final void addStepFactory(FormatterStepFactory stepFactory) {
Objects.requireNonNull(stepFactory);
stepFactories.add(stepFactory);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/*
* Copyright 2016 DiffPlug
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.diffplug.spotless.maven.generic;

import java.io.File;
import java.util.LinkedHashMap;
import java.util.Map;

import org.apache.maven.plugins.annotations.Parameter;

import com.diffplug.spotless.FormatterStep;
import com.diffplug.spotless.maven.FormatterStepConfig;
import com.diffplug.spotless.maven.FormatterStepFactory;
import com.diffplug.spotless.npm.PrettierConfig;
import com.diffplug.spotless.npm.PrettierFormatterStep;

public class Prettier implements FormatterStepFactory {

@Parameter
private String prettierVersion;

@Parameter
private Map<String, String> devDependencies;

@Parameter
private Map<String, String> config;

@Parameter
private String configFile;

@Parameter
private String npmExecutable;

@Override
public FormatterStep newFormatterStep(FormatterStepConfig stepConfig) {

// check if config is only setup in one way
if (this.prettierVersion != null && this.devDependencies != null) {
throw onlyOneConfig();
}

// set dev dependencies
if (devDependencies == null) {
if (prettierVersion == null || prettierVersion.isEmpty()) {
devDependencies = PrettierFormatterStep.defaultDevDependencies();
} else {
devDependencies = PrettierFormatterStep.defaultDevDependenciesWithPrettier(prettierVersion);
}
}

File npm = npmExecutable != null ? stepConfig.getFileLocator().locateLocal(npmExecutable) : null;

// process config file or inline config
File configFileHandler;
if (this.configFile != null) {
configFileHandler = stepConfig.getFileLocator().locateLocal(this.configFile);
} else {
configFileHandler = null;
}

Map<String, Object> configInline;
if (config != null) {
configInline = new LinkedHashMap<>();
// try to parse string values as integers or booleans
for (Map.Entry<String, String> e : config.entrySet()) {
try {
configInline.put(e.getKey(), Integer.parseInt(e.getValue()));
} catch (NumberFormatException ignore) {
try {
configInline.put(e.getKey(), Boolean.parseBoolean(e.getValue()));
} catch (IllegalArgumentException ignore2) {
configInline.put(e.getKey(), e.getValue());
}
}
}
} else {
configInline = null;
}

// create the format step
PrettierConfig prettierConfig = new PrettierConfig(configFileHandler, configInline);
File buildDir = stepConfig.getFileLocator().getBuildDir();
return PrettierFormatterStep.create(devDependencies, stepConfig.getProvisioner(), buildDir, npm, prettierConfig);
}

private static IllegalArgumentException onlyOneConfig() {
return new IllegalArgumentException("must specify exactly one configFile or config");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,10 @@ protected void writePomWithTypescriptSteps(String... steps) throws IOException {
writePom(groupWithSteps("typescript", steps));
}

protected void writePomWithPrettierSteps(String includes, String... steps) throws IOException {
writePom(formats(groupWithSteps("format", including(includes), steps)));
}

protected void writePom(String... configuration) throws IOException {
writePom(null, configuration);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
* Copyright 2016 DiffPlug
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.diffplug.spotless.maven.prettier;

import static org.assertj.core.api.Assertions.assertThat;

import java.io.IOException;

import org.junit.Test;

import com.diffplug.spotless.maven.MavenIntegrationTest;
import com.diffplug.spotless.maven.MavenRunner;

public class PrettierFormatStepTest extends MavenIntegrationTest {

private void run(String kind, String suffix) throws IOException, InterruptedException {
String configPath = ".prettierrc.yml";
setFile(configPath).toResource("npm/prettier/filetypes/" + kind + "/" + ".prettierrc.yml");
String path = "src/main/" + kind + "/test." + suffix;
setFile(path).toResource("npm/prettier/filetypes/" + kind + "/" + kind + ".dirty");
mavenRunner().withArguments("spotless:apply").runNoError();
assertFile(path).sameAsResource("npm/prettier/filetypes/" + kind + "/" + kind + ".clean");
}

@Test
public void prettier_typescript() throws Exception {
String suffix = "ts";
writePomWithPrettierSteps("**/*." + suffix,
"<prettier>",
" <prettierVersion>1.16.4</prettierVersion>",
" <configFile>.prettierrc.yml</configFile>",
"</prettier>");
run("typescript", suffix);
}

@Test
public void prettier_html() throws Exception {
String suffix = "html";
writePomWithPrettierSteps("**/*." + suffix,
"<prettier>",
" <prettierVersion>1.16.4</prettierVersion>",
" <configFile>.prettierrc.yml</configFile>",
"</prettier>");
run("html", suffix);
}

@Test
public void prettier_tsx() throws Exception {
String suffix = "tsx";
writePomWithPrettierSteps("src/main/**/*." + suffix,
"<includes><include>src/**/*.tsx</include></includes>",
"<prettier>",
" <prettierVersion>1.16.4</prettierVersion>",
" <configFile>.prettierrc.yml</configFile>",
"</prettier>");
run("tsx", suffix);
}

@Test
public void prettier_tsx_inline_config() throws Exception {
String suffix = "tsx";
writePomWithPrettierSteps("src/main/**/*." + suffix,
"<prettier>",
" <prettierVersion>1.16.4</prettierVersion>",
" <config><parser>typescript</parser></config>",
"</prettier>");
run("tsx", suffix);
}

@Test
public void unique_dependency_config() throws Exception {
writePomWithFormatSteps(
"<includes><include>**/*.ts</include></includes>",
"<prettier>",
" <prettierVersion>1.16.4</prettierVersion>",
" <devDependencies><prettier>1.16.4</prettier></devDependencies>",
"</prettier>");

MavenRunner.Result result = mavenRunner().withArguments("spotless:apply").runHasError();
assertThat(result.output()).contains("must specify exactly one configFile or config");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
parser: html
13 changes: 13 additions & 0 deletions testlib/src/main/resources/npm/prettier/filetypes/html/html.clean
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html dir="ltr" lang="en">
<head>
<meta charset="viewport" content="with=device-width" />
<title>Test</title>
<script type="module" src="module.js"></script>
<script type="module2" src="module2.js"></script>

<link rel="stylesheet" type="text/css" href="style.css" />
</head>

<body></body>
</html>
17 changes: 17 additions & 0 deletions testlib/src/main/resources/npm/prettier/filetypes/html/html.dirty
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<!DOCTYPE html>
<html dir="ltr" lang="en">

<head>
<meta
charset="viewport"
content="with=device-width">
<title>Test</title><script type="module" src="module.js"></script>
<script type="module2" src="module2.js"></script>

<link rel="stylesheet" type ="text/css" href="style.css">
</head>

<body>

</body></html>

Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
parser: typescript
files: "scr/**/*.tsx"
excludeFiles: "target/**"
Loading

0 comments on commit 3e3c969

Please sign in to comment.