Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
Stephen Lam committed Apr 6, 2018
0 parents commit f01103f
Show file tree
Hide file tree
Showing 17 changed files with 9,908 additions and 0 deletions.
7 changes: 7 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module.exports = {
root: true,
env: {
es6: true,
},
extends: ['@ascendancyy/eslint-config-eva'],
};
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules
1 change: 1 addition & 0 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
__tests__/
47 changes: 47 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# @ascendancyy/vue-cli-plugin-stylelint

> stylelint plugin for vue-cli
## Injected commands

- **`vue-cli-service lint:style`**

```
Usage: vue-cli-service lint:style [options] [...files]
Options:
--no-fix do not auto-fix errors
--options list additional stylelint cli options
```

Lints and fixes files. If no specific files are given, it lints all vue files, html files, and stylesheets in `src`.

## Configuration (stylelint.config.js, .stylelintrc[.*])

Lint on (re)build with `stylelint-webpack-plugin` can be enabled with the `lintStyleOnBuild` option in `vue.config.js`:

``` js
module.exports = {
// ...
pluginOptions: {
lintStyleOnBuild: true
}
}
```

## Installing in an already created project

```
npm install -D @ascendancyy/vue-cli-plugin-stylelint
vue invoke @ascendancyy/vue-cli-plugin-stylelint
```

> There is also a shorthand to invoke the plugin
> `vue invoke @ascendancyy/stylelint`
## webpack-chain Injections

- `config.plugin('stylelint')`
- `config.plugin('stylelint').use('stylelint-webpack-plugin')`
- `config.plugin('friendly-errors').tap(/* Adds additional transformer and formatter */)`
11 changes: 11 additions & 0 deletions __tests__/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module.exports = {
env: {
jest: true,
},
parserOptions: {
ecmaVersion: 2018,
},
rules: {
'global-require': 'off',
},
};
94 changes: 94 additions & 0 deletions __tests__/generator.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
const generateWithPlugin = require('@vue/cli-test-utils/generateWithPlugin');

test('default', async () => {
const { pkg } = await generateWithPlugin({
id: '@ascendancyy/vue-cli-plugin-stylelint',
apply: require('../generator'),
options: {},
});

expect(pkg.scripts['lint:style']).toBeTruthy();
expect(pkg.devDependencies).toHaveProperty('stylelint-config-standard');
});

test('standard', async () => {
const { pkg } = await generateWithPlugin({
id: '@ascendancyy/vue-cli-plugin-stylelint',
apply: require('../generator'),
options: {
config: 'stylelint-config-standard',
},
});

expect(pkg.scripts['lint:style']).toBeTruthy();
expect(pkg.devDependencies).toHaveProperty('stylelint-config-standard');
});

test('primer', async () => {
const { pkg } = await generateWithPlugin({
id: '@ascendancyy/vue-cli-plugin-stylelint',
apply: require('../generator'),
options: {
config: 'stylelint-config-primer',
},
});

expect(pkg.scripts['lint:style']).toBeTruthy();
expect(pkg.devDependencies).toHaveProperty('stylelint-config-primer');
});

test('kanbaru', async () => {
const { pkg } = await generateWithPlugin({
id: '@ascendancyy/vue-cli-plugin-stylelint',
apply: require('../generator'),
options: {
config: '@ascendancyy/stylelint-config-kanbaru',
},
});

expect(pkg.scripts['lint:style']).toBeTruthy();
expect(pkg.devDependencies).toHaveProperty('@ascendancyy/stylelint-config-kanbaru');
});

test('lint on save', async () => {
const { pkg } = await generateWithPlugin({
id: '@ascendancyy/vue-cli-plugin-stylelint',
apply: require('../generator'),
options: {
lintStyleOn: 'build',
},
});
expect(pkg.vue.pluginOptions).toEqual({ lintStyleOnBuild: true });
});

test('lint on commit', async () => {
const { pkg } = await generateWithPlugin({
id: '@ascendancyy/vue-cli-plugin-stylelint',
apply: require('../generator'),
options: {
lintStyleOn: 'commit',
},
});
expect(pkg.gitHooks['pre-commit']).toBe('lint-staged');
expect(pkg.devDependencies).toHaveProperty('lint-staged');
expect(pkg['lint-staged']).toEqual({
'*.{vue,htm,html,css,sss,less,scss}': ['vue-cli-service lint:style', 'git add'],
});
expect(pkg.vue.pluginOptions).toEqual({ lintStyleOnBuild: false });
});

test('cancel', async () => {
const { pkg } = await generateWithPlugin({
id: '@ascendancyy/vue-cli-plugin-stylelint',
apply: require('../generator'),
options: {
overwriteConfig: 'abort',
},
});

expect(pkg).toEqual({
scripts: undefined,
devDependencies: undefined,
vue: undefined,
});
});
59 changes: 59 additions & 0 deletions generator/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
const chalk = require('chalk');
const lint = require('../lint');

module.exports = (api, options) => {
const { overwriteConfig } = options;
if (overwriteConfig === 'abort') {
api.exitLog(chalk`{yellow Plugin setup successfully cancelled}`, 'warn');
return;
}

let { lintStyleOn = [] } = options;
if (typeof lintStyleOn === 'string') {
lintStyleOn = lintStyleOn.split(',');
}

const pkg = {
scripts: {
'lint:style': 'vue-cli-service lint:style',
},
devDependencies: {},
vue: {
pluginOptions: {
lintStyleOnBuild: lintStyleOn.includes('build'),
},
},
};

const { config = 'stylelint-config-standard' } = options;
if (config === 'stylelint-config-standard') {
Object.assign(pkg.devDependencies, {
'stylelint-config-standard': '^18.2.0',
});
} else if (config === 'stylelint-config-primer') {
Object.assign(pkg.devDependencies, {
'stylelint-config-primer': '^2.2.5',
});
} else if (config === '@ascendancyy/stylelint-config-kanbaru') {
Object.assign(pkg.devDependencies, {
'@ascendancyy/stylelint-config-kanbaru': '^1.0.1',
});
}

if (lintStyleOn.includes('commit')) {
Object.assign(pkg.devDependencies, {
'lint-staged': '^6.0.0',
});
pkg.gitHooks = {
'pre-commit': 'lint-staged',
};
pkg['lint-staged'] = {
'*.{vue,htm,html,css,sss,less,scss}': ['vue-cli-service lint:style', 'git add'],
};
}

api.render('./template', { config: options.config });
api.extendPackage(pkg);

api.onCreateComplete(() => { lint(api, { silent: true }); });
};
1 change: 1 addition & 0 deletions generator/template/_stylelintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# .gitignore syntax (uses node-ignore behind the scenes)
6 changes: 6 additions & 0 deletions generator/template/stylelint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module.exports = {
root: true,
extends: [
<% if (config) { _%>'<%- config %>',<%_ } %>
],
};
57 changes: 57 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
const StyleLintPlugin = require('stylelint-webpack-plugin');
const CodeframeFormatter = require('stylelint-codeframe-formatter');

const lint = require('./lint');

module.exports = (api, projectOptions) => {
const { pluginOptions: { lintStyleOnBuild } } = projectOptions;
if (lintStyleOnBuild) {
api.chainWebpack((webpackConfig) => {
/* eslint-disable indent */
webpackConfig
.plugin('stylelint')
.use(StyleLintPlugin, [{
failOnError: lintStyleOnBuild === 'error',
files: ['src/**/*.{vue,htm,html,css,sss,less,scss}'],
formatter: CodeframeFormatter,
}])
.end()
.plugin('friendly-errors')
.tap(([options]) => {
['Transformers', 'Formatters'].forEach((name) => {
const optKey = `additional${name}`;
let plugins;
if (Array.isArray(options[optKey])) {
plugins = options[optKey];
} else {
plugins = [];
Object.assign(options, { [optKey]: plugins });
}

let plugin;
try {
const pluginName = name.toLowerCase().slice(0, -1);
// eslint-disable-next-line global-require
plugin = require('./stylelintError')[pluginName];
} catch (e) {
return;
}

plugin && plugins.push(plugin);
});
return [options];
});
/* eslint-enable indent */
});
}

api.registerCommand('lint:style', {
description: 'lint and fix source files',
usage: 'vue-cli-service lint [options] [...files]',
options: {
'--no-fix': 'do not fix errors',
'--options': 'display stylelint options',
},
details: 'Autofixing is an experimental feature, see https://stylelint.io/user-guide/cli/#autofixing-errors',
}, (args) => { lint(api, args); });
};
5 changes: 5 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module.exports = {
testMatch: [
'**/__tests__/?(*.)(spec|test).js?(x)',
],
};
Loading

0 comments on commit f01103f

Please sign in to comment.