diff --git a/packages/grafana-toolkit/README.md b/packages/grafana-toolkit/README.md index dbe2f1eaa0d..51be02f21b4 100644 --- a/packages/grafana-toolkit/README.md +++ b/packages/grafana-toolkit/README.md @@ -123,7 +123,15 @@ Using themes: TODO, for now please refer to [internal guide](../../style_guides/ > NOTE: We do not support Emotion's `css` prop. Use className instead! -## Prettier [todo] +## Prettier +When `plugin:build` task is performed we run Prettier check. In order for your IDE to pickup our Prettier config we suggest creating `.prettierrc.js` file in the root directory of your plugin with following contents: + +```js +module.exports = { + ...require("./node_modules/@grafana/toolkit/src/config/prettier.plugin.config.json"), +}; +``` + ## Development mode [todo] `grafana-toolkit plugin:dev [--watch]` diff --git a/packages/grafana-toolkit/package.json b/packages/grafana-toolkit/package.json index 10242927e11..0b3bf0917ee 100644 --- a/packages/grafana-toolkit/package.json +++ b/packages/grafana-toolkit/package.json @@ -26,7 +26,6 @@ "@types/jest": "24.0.13", "@types/jest-cli": "^23.6.0", "@types/node": "^12.0.4", - "@types/prettier": "^1.16.4", "@types/react-dev-utils": "^9.0.1", "@types/semver": "^6.0.0", "@types/webpack": "4.4.34", @@ -53,7 +52,7 @@ "postcss-flexbugs-fixes": "4.1.0", "postcss-loader": "3.0.0", "postcss-preset-env": "6.6.0", - "prettier": "^1.17.1", + "prettier": "^1.18.2", "react-dev-utils": "^9.0.1", "replace-in-file": "^4.1.0", "replace-in-file-webpack-plugin": "^1.0.6", @@ -76,6 +75,7 @@ "@types/lodash": "4.14.119" }, "devDependencies": { - "@types/glob": "^7.1.1" + "@types/glob": "^7.1.1", + "@types/prettier": "^1.16.4" } } diff --git a/packages/grafana-toolkit/src/cli/tasks/plugin.build.ts b/packages/grafana-toolkit/src/cli/tasks/plugin.build.ts index e603140240c..e0dd49b4de2 100644 --- a/packages/grafana-toolkit/src/cli/tasks/plugin.build.ts +++ b/packages/grafana-toolkit/src/cli/tasks/plugin.build.ts @@ -4,15 +4,19 @@ import execa = require('execa'); import path = require('path'); import fs = require('fs'); import glob = require('glob'); +import util = require('util'); +import { Linter, Configuration, RuleFailure } from 'tslint'; +import * as prettier from 'prettier'; import { useSpinner } from '../utils/useSpinner'; -import { Linter, Configuration, RuleFailure } from 'tslint'; import { testPlugin } from './plugin/tests'; import { bundlePlugin as bundleFn, PluginBundleOptions } from './plugin/bundle'; + interface PrecommitOptions {} export const bundlePlugin = useSpinner('Compiling...', async options => await bundleFn(options)); +const readFileAsync = util.promisify(fs.readFile); // @ts-ignore export const clean = useSpinner('Cleaning', async () => await execa('rimraf', [`${process.cwd()}/dist`])); @@ -36,20 +40,67 @@ const typecheckPlugin = useSpinner('Typechecking', async () => { await execa('tsc', ['--noEmit']); }); +const getTypescriptSources = () => { + const globPattern = path.resolve(process.cwd(), 'src/**/*.+(ts|tsx)'); + return glob.sync(globPattern); +}; + +const getStylesSources = () => { + const globPattern = path.resolve(process.cwd(), 'src/**/*.+(scss|css)'); + return glob.sync(globPattern); +}; + +const prettierCheckPlugin = useSpinner('Prettier check', async () => { + const prettierConfig = require(path.resolve(__dirname, '../../config/prettier.plugin.config.json')); + const sources = [...getStylesSources(), ...getTypescriptSources()]; + + const promises = sources.map((s, i) => { + return new Promise<{ path: string; failed: boolean }>((resolve, reject) => { + fs.readFile(s, (err, data) => { + let failed = false; + if (err) { + throw new Error(err.message); + } + + if ( + !prettier.check(data.toString(), { + ...prettierConfig, + filepath: s, + }) + ) { + failed = true; + } + + resolve({ + path: s, + failed, + }); + }); + }); + }); + + const results = await Promise.all(promises); + const failures = results.filter(r => r.failed); + if (failures.length) { + console.log('\nFix Prettier issues in following files:'); + failures.forEach(f => console.log(f.path)); + throw new Error('Prettier failed'); + } +}); + // @ts-ignore const lintPlugin = useSpinner('Linting', async () => { let tsLintConfigPath = path.resolve(process.cwd(), 'tslint.json'); if (!fs.existsSync(tsLintConfigPath)) { tsLintConfigPath = path.resolve(__dirname, '../../config/tslint.plugin.json'); } - const globPattern = path.resolve(process.cwd(), 'src/**/*.+(ts|tsx)'); - const sourcesToLint = glob.sync(globPattern); const options = { fix: true, // or fail formatter: 'json', }; const configuration = Configuration.findConfiguration(tsLintConfigPath).results; + const sourcesToLint = getTypescriptSources(); const lintResults = sourcesToLint .map(fileName => { @@ -81,9 +132,9 @@ const lintPlugin = useSpinner('Linting', async () => { }); const pluginBuildRunner: TaskRunner = async () => { - // console.log('asasas') await clean(); await prepare(); + await prettierCheckPlugin(); // @ts-ignore await lintPlugin(); await testPlugin({ updateSnapshot: false, coverage: false }); diff --git a/packages/grafana-toolkit/src/config/prettier.plugin.config.json b/packages/grafana-toolkit/src/config/prettier.plugin.config.json new file mode 100644 index 00000000000..ae16c29eb8e --- /dev/null +++ b/packages/grafana-toolkit/src/config/prettier.plugin.config.json @@ -0,0 +1,5 @@ +{ + "trailingComma": "es5", + "singleQuote": true, + "printWidth": 150 +} diff --git a/packages/grafana-toolkit/src/config/tslint.plugin.json b/packages/grafana-toolkit/src/config/tslint.plugin.json index 3f0a5b6dc52..8c2d6608f52 100644 --- a/packages/grafana-toolkit/src/config/tslint.plugin.json +++ b/packages/grafana-toolkit/src/config/tslint.plugin.json @@ -1,4 +1,5 @@ { + "extends": ["tslint-config-prettier"], "rules": { "array-type": [true, "array-simple"], "arrow-return-shorthand": true, diff --git a/yarn.lock b/yarn.lock index acf914cf65d..6f5bb08215d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12726,7 +12726,7 @@ prettier@1.16.4: version "1.16.4" resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.16.4.tgz#73e37e73e018ad2db9c76742e2647e21790c9717" -prettier@^1.17.1: +prettier@^1.18.2: version "1.18.2" resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.18.2.tgz#6823e7c5900017b4bd3acf46fe9ac4b4d7bda9ea" integrity sha512-OeHeMc0JhFE9idD4ZdtNibzY0+TPHSpSSb9h8FqtP+YnoZZ1sl8Vc9b1sasjfymH3SonAF4QcA2+mzHPhMvIiw==