Tell us about your environment
Please show your full configuration:
const fs = require('fs');
// Import AirBNB base rules to wrap them onto framework specific configs.
const airbnbRulesStyle = require('eslint-config-airbnb-base/rules/style').rules;
const airbnbRulesES6 = require('eslint-config-airbnb-base/rules/es6').rules;
const airbnbRulesBestPractices = require('eslint-config-airbnb-base/rules/best-practices').rules;
const maxLenBaseRule = {
code: 120,
ignoreUrls: true,
};
const rules = {
'object-property-newline': ['error', {
allowAllPropertiesOnSameLine: false,
}],
'array-element-newline': ['error', 'consistent'],
'array-bracket-newline': ['error', 'consistent'],
'max-len': ['error', maxLenBaseRule],
'no-param-reassign': ['error', {
props: false,
}],
'no-plusplus': ['error', {
allowForLoopAfterthoughts: true,
}],
'no-underscore-dangle': ['error', {
allow: ['_id'],
}],
'import/extensions': ['error', 'always', {
js: 'never',
ts: 'never',
}],
'import/no-extraneous-dependencies': 'off',
};
const tsRules = {
'@typescript-eslint/explicit-function-return-type': ['error', {
allowExpressions: true,
}],
'@typescript-eslint/no-unused-vars': ['error', {
args: 'none',
}],
'@typescript-eslint/no-explicit-any': 'off',
};
if (!fs.existsSync('node_modules')) {
rules['import/no-unresolved'] = 'off';
}
const vueRules = {
indent: 'off', // @see https://eslint.vuejs.org/rules/script-indent.html#options
'vue/array-bracket-spacing': airbnbRulesStyle['array-bracket-spacing'],
'vue/arrow-spacing': airbnbRulesES6['arrow-spacing'],
'vue/block-spacing': airbnbRulesStyle['block-spacing'],
'vue/brace-style': airbnbRulesStyle['brace-style'],
'vue/camelcase': airbnbRulesStyle.camelcase,
'vue/comma-dangle': airbnbRulesStyle['comma-dangle'],
'vue/component-definition-name-casing': 'error',
'vue/component-name-in-template-casing': 'error',
'vue/component-tags-order': ['error', {
order: ['script', 'style', 'template'],
}],
'vue/dot-location': airbnbRulesBestPractices['dot-location'],
'vue/eqeqeq': airbnbRulesBestPractices.eqeqeq,
'vue/key-spacing': airbnbRulesStyle['key-spacing'],
'vue/keyword-spacing': airbnbRulesStyle['keyword-spacing'],
'vue/match-component-file-name': ['error', {
extensions: ['vue'],
shouldMatchCase: true,
}],
'vue/max-len': ['error', maxLenBaseRule],
'vue/no-empty-pattern': airbnbRulesBestPractices['no-empty-pattern'],
'vue/no-irregular-whitespace': 'error',
'vue/no-reserved-component-names': 'error',
'vue/no-restricted-syntax': airbnbRulesStyle['no-restricted-syntax'],
'vue/object-curly-spacing': airbnbRulesStyle['object-curly-spacing'],
'vue/padding-line-between-blocks': 'error',
'vue/script-indent': ['error', 2, {
baseIndent: 1,
}],
'vue/space-infix-ops': airbnbRulesStyle['space-infix-ops'],
'vue/space-unary-ops': airbnbRulesStyle['space-unary-ops'],
'vue/v-on-function-call': 'error',
'vue/v-slot-style': 'error',
'vue/valid-v-slot': 'error',
};
module.exports = {
env: {
browser: true,
commonjs: true,
es6: true,
node: true,
jquery: true,
'cypress/globals': true,
},
plugins: [
'cypress',
'@typescript-eslint',
],
extends: [
'eslint:recommended',
'airbnb',
],
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaVersion: 2018,
sourceType: 'module',
},
rules,
overrides: [
{
files: ['*.ts'],
extends: [
'plugin:@typescript-eslint/eslint-recommended',
'plugin:@typescript-eslint/recommended',
],
rules: tsRules,
},
{
files: ['*.vue'],
extends: [
'plugin:vue/recommended',
],
rules: vueRules,
},
],
settings: {
'import/resolver': {
node: {
extensions: [
'.js',
'.jsx',
'.ts',
'.d.ts',
'.tsx',
],
},
},
},
};
What did you do?
<script>
const testObject = {};
const test = testObject?.foo;
console.log(test);
export default {
name: 'MyComponent',
props: {
title: {
default: null,
type: String,
},
},
};
</script>
<template>
<div class="panel panel-default">
<div
v-if="this.$slots.header || this.$slots.title || title"
class="panel-heading"
>
<slot name="header">
<h4 class="panel-title">
<slot name="title">
{{ title }}
</slot>
</h4>
</slot>
</div>
<div class="panel-body">
<slot />
</div>
<div
v-if="this.$slots.footer"
class="panel-footer"
>
<slot name="footer" />
</div>
<ul id="example-1">
<li
v-for="item in [1,2,3]"
:key="item"
>
{{ item }}
</li>
</ul>
</div>
</template>
What did you expect to happen?
Successful lint
What actually happened?
/code/fixtures/MyComponent.vue
3:26 error Parsing error: Unexpected token .
See also: https://gitlab.com/nexylan/pretty/-/merge_requests/89
Note: Optional chaining parsing works on eslint core, only the plugin parser crashes.
Hi.
You may need to use babel-eslint or @typescript-eslint/parser for .vue to solve the problem.
{
files: ['*.vue'],
extends: [
'plugin:vue/recommended',
],
+ parserOptions: {
+ parser: '@typescript-eslint/parser',
+ },
rules: vueRules,
},
https://eslint.vuejs.org/user-guide/#how-to-use-a-custom-parser
The parser that eslint uses by default does not yet support Optional Chaining.
If the problem persists, please reopen this issue.
@ota-meshi Thanks for the answer, but that didn't help.
Using the parser now give me this error (with the same vue file):
/code/fixtures/MyComponent.vue
7:8 error Parsing error: '}' expected
But the file seems correct.
Also, this parser is already set globally and works with my *.ts override. Why not with the *.vue override? :thinking:
Most helpful comment
Hi.
You may need to use
babel-eslintor@typescript-eslint/parserfor.vueto solve the problem.https://eslint.vuejs.org/user-guide/#how-to-use-a-custom-parser
The parser that eslint uses by default does not yet support Optional Chaining.
https://github.com/eslint/eslint/issues/12642