Skip to content

Commit

Permalink
Merge pull request #562 from nextcloud/feat/support-vue-ts
Browse files Browse the repository at this point in the history
  • Loading branch information
skjnldsv committed Jun 20, 2023
2 parents 5af3baa + 05b788a commit 6cc9136
Show file tree
Hide file tree
Showing 13 changed files with 301 additions and 169 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
@@ -1,5 +1,13 @@
# Changelog

## Unreleased

[Full Changelog](https://github.com/nextcloud/eslint-config/compare/v8.2.1...master)

**Features:**
- Provide config for vue files written in Typescript, use `extends: "@nextcloud/eslint-config/typescript"`.
- Fully support vue files using the Composition API `<script setup>`.

## [v8.3.0-beta.0](https://github.com/nextcloud/eslint-config/tree/v8.3.0-beta.0) (2023-05-12)

[Full Changelog](https://github.com/nextcloud/eslint-config/compare/v8.2.1...v8.3.0-beta.0)
Expand Down
14 changes: 14 additions & 0 deletions README.md
Expand Up @@ -28,6 +28,20 @@ module.exports = {
}
```

### Usage with Typescript projects

If your projects uses Typescript for vue files, like `<script lang="ts">` then use the Typescript config instead:

Add a file `.eslintrc.js` in the root directory of your app repository with the following content:

```js
module.exports = {
extends: [
'@nextcloud/eslint-config/typescript',
],
}
```

## Release new version

1. Update CHANGELOG.md file with the latest changes
Expand Down
175 changes: 15 additions & 160 deletions index.js
@@ -1,166 +1,21 @@
const base = require('./parts/base.js')
const typescriptOverrides = require('./parts/typescript.js')
const vueOverrides = require('./parts/vue.js')

/**
* Config for Vue + Javascript projects (optionally with parts, except vue files, written in Typescript)
*/
module.exports = {
root: true,
env: {
browser: true,
commonjs: true,
es6: true,
node: true,
// Allow jest syntax in the src folder
jest: true,
},
parserOptions: {
parser: '@babel/eslint-parser',
ecmaVersion: 6,
requireConfigFile: false,
},
extends: [
'eslint:recommended',
'plugin:import/errors',
'plugin:import/warnings',
'plugin:n/recommended',
'plugin:vue/recommended',
'plugin:@nextcloud/recommended',
'plugin:jsdoc/recommended',
'standard',
],
settings: {
'import/resolver': {
node: {
paths: ['src'],
extensions: ['.js', '.vue'],
},
exports: {
conditions: ['import'],
},
},
jsdoc: {
tagNamePreference: {
returns: 'return',
},
mode: 'typescript',
},
},
plugins: ['vue', 'n', 'jsdoc'],
rules: {
// space before function ()
'space-before-function-paren': ['error', {
anonymous: 'never',
named: 'never',
asyncArrow: 'always',
}],
// stay consistent with array brackets
'array-bracket-newline': ['error', 'consistent'],
// tabs only for indentation
indent: ['error', 'tab'],
'no-tabs': ['error', { allowIndentationTabs: true }],
'vue/html-indent': ['error', 'tab'],
// allow spaces after tabs for alignment
'no-mixed-spaces-and-tabs': ['error', 'smart-tabs'],
// only debug console
'no-console': ['error', { allow: ['error', 'warn', 'info', 'debug'] }],
// classes blocks
'padded-blocks': ['error', { classes: 'always' }],
// always have the operator in front
'operator-linebreak': ['error', 'before'],
// ternary on multiline
'multiline-ternary': ['error', 'always-multiline'],
// force proper JSDocs
'jsdoc/require-returns': 0,
'jsdoc/require-returns-description': 0,
'jsdoc/tag-lines': ['off'],
// disallow use of "var"
'no-var': 'error',
// suggest using const
'prefer-const': 'error',
// es6 import/export and require
'n/no-unpublished-require': ['off'],
'n/no-unsupported-features/es-syntax': ['off'],
// PascalCase components names for vuejs
// https://vuejs.org/v2/style-guide/#Single-file-component-filename-casing-strongly-recommended
'vue/component-name-in-template-casing': ['error', 'PascalCase'],
// force name
'vue/match-component-file-name': ['error', {
extensions: ['jsx', 'vue', 'js'],
shouldMatchCase: true,
}],
// space before self-closing elements
'vue/html-closing-bracket-spacing': 'error',
// no ending html tag on a new line
'vue/html-closing-bracket-newline': ['error', { multiline: 'never' }],
// check vue files too
'n/no-missing-import': ['error', {}],
// code spacing with attributes
'vue/max-attributes-per-line': ['error', {
singleline: 3,
multiline: 1,
}],
'vue/first-attribute-linebreak': ['error', {
singleline: 'beside',
multiline: 'beside',
}],
// Allow single-word components names
'vue/multi-word-component-names': ['off'],
// custom event naming convention
'vue/custom-event-name-casing': ['error', 'kebab-case', {
// allows custom xxxx:xxx events formats
ignores: ['/^[a-z]+(?:-[a-z]+)*:[a-z]+(?:-[a-z]+)*$/u'],
}],
// always add a trailing comma (for diff readability)
'comma-dangle': ['warn', 'always-multiline'],
// Allow shallow import of @vue/test-utils and @testing-library/vue in order to be able to use it in
// the src folder
'n/no-unpublished-import': ['error', {
allowModules: ['@vue/test-utils', '@testing-library/vue'],
}],
// require object literal shorthand syntax
'object-shorthand': ['error', 'always'],
// Warn when file extensions are not used on import paths
'import/extensions': ['warn', 'always', {
ignorePackages: true,
}],
// ignore camelcase for __webpack variables
camelcase: ['error', {
allow: ['^UNSAFE_', '^__webpack_'],
properties: 'never',
ignoreGlobals: true,
}],
},
// Base rules
...base,
// basic Typescript rules
overrides: [
{
files: ['**/*.ts', '**/*.tsx'],
extends: [
'@vue/eslint-config-typescript/recommended',
'plugin:import/typescript',
],
parserOptions: {
parser: '@typescript-eslint/parser',
},
rules: {
'n/no-missing-import': 'off',
'import/extensions': 'off',
'jsdoc/check-tag-names': [
'warn', {
// for projects using typedoc
definedTags: [
'notExported',
'packageDocumentation',
],
},
],
// Does not make sense with TypeScript
'jsdoc/require-param-type': 'off',
},
settings: {
'import/resolver': {
typescript: {
alwaysTryTypes: true,
},
node: {
paths: ['src'],
extensions: ['.(m|c)?js', '.ts', '.tsx', '.vue'],
},
},
},
...typescriptOverrides,
},
// Setup different vue parser to support `<script setup>` correctly
{
...vueOverrides,
},
],
}
15 changes: 8 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Expand Up @@ -45,7 +45,8 @@
"eslint-plugin-vue": "^9.7.0",
"jest": "^29.4.1",
"ts-jest": "^29.0.5",
"typescript": "^5.0.2"
"typescript": "^5.0.2",
"vue-eslint-parser": "^9.3.1"
},
"keywords": [
"eslint",
Expand Down
96 changes: 96 additions & 0 deletions parts/base.js
@@ -0,0 +1,96 @@
/** Base rules */
module.exports = {
root: true,
env: {
browser: true,
commonjs: true,
es6: true,
node: true,
// Allow jest syntax in the src folder
jest: true,
},
parser: '@babel/eslint-parser',
parserOptions: {
requireConfigFile: false,
},
extends: [
'eslint:recommended',
'plugin:import/errors',
'plugin:import/warnings',
'plugin:n/recommended',
'plugin:@nextcloud/recommended',
'plugin:jsdoc/recommended',
'standard',
],
settings: {
'import/resolver': {
node: {
paths: ['src'],
extensions: ['.js', '.vue'],
},
exports: {
conditions: ['import'],
},
},
jsdoc: {
tagNamePreference: {
returns: 'return',
},
mode: 'typescript',
},
},
plugins: ['vue', 'n', 'jsdoc'],
rules: {
// space before function ()
'space-before-function-paren': ['error', {
anonymous: 'never',
named: 'never',
asyncArrow: 'always',
}],
// stay consistent with array brackets
'array-bracket-newline': ['error', 'consistent'],
// tabs only for indentation
indent: ['error', 'tab'],
'no-tabs': ['error', { allowIndentationTabs: true }],
// allow spaces after tabs for alignment
'no-mixed-spaces-and-tabs': ['error', 'smart-tabs'],
// only debug console
'no-console': ['error', { allow: ['error', 'warn', 'info', 'debug'] }],
// classes blocks
'padded-blocks': ['error', { classes: 'always' }],
// always have the operator in front
'operator-linebreak': ['error', 'before'],
// ternary on multiline
'multiline-ternary': ['error', 'always-multiline'],
// force proper JSDocs
'jsdoc/require-returns': 0,
'jsdoc/require-returns-description': 0,
'jsdoc/tag-lines': ['off'],
// disallow use of "var"
'no-var': 'error',
// suggest using const
'prefer-const': 'error',
// es6 import/export and require
'n/no-unpublished-require': ['off'],
'n/no-unsupported-features/es-syntax': ['off'],
// always add a trailing comma (for diff readability)
'comma-dangle': ['warn', 'always-multiline'],
// Allow shallow import of @vue/test-utils and @testing-library/vue in order to be able to use it in
// the src folder
'n/no-unpublished-import': ['error', {
allowModules: ['@vue/test-utils', '@testing-library/vue'],
}],
// require object literal shorthand syntax
'object-shorthand': ['error', 'always'],
// Warn when file extensions are not used on import paths
'import/extensions': ['warn', 'always', {
ignorePackages: true,
}],
// ignore camelcase for __webpack variables
camelcase: ['error', {
allow: ['^UNSAFE_', '^__webpack_'],
properties: 'never',
ignoreGlobals: true,
}],
},
}
36 changes: 36 additions & 0 deletions parts/typescript.js
@@ -0,0 +1,36 @@
/** Rules for typescript */
module.exports = {
files: ['**/*.ts', '**/*.tsx'],
extends: [
'@vue/eslint-config-typescript/recommended',
'plugin:import/typescript',
],
parser: '@typescript-eslint/parser',
parserOptions: {},
rules: {
'n/no-missing-import': 'off',
'import/extensions': 'off',
'jsdoc/check-tag-names': [
'warn', {
// for projects using typedoc
definedTags: [
'notExported',
'packageDocumentation',
],
},
],
// Does not make sense with TypeScript
'jsdoc/require-param-type': 'off',
},
settings: {
'import/resolver': {
typescript: {
alwaysTryTypes: true,
},
node: {
paths: ['src'],
extensions: ['.(m|c)?js', '.ts', '.tsx', '.vue'],
},
},
},
}

0 comments on commit 6cc9136

Please sign in to comment.