eslint-plugin-vue: Wrong detect of `Parsing error: invalid-first-character-of-tag-name` in expression.
Tell us about your environment
- ESLint Version:
4.16.0
- eslint-plugin-vue Version:
4.2.2
- Node Version:
v8.1.3
Please show your full configuration:
const isDev = process.env.NODE_ENV === 'development';
// http://eslint.org/docs/user-guide/configuring
module.exports = {
root: true,
parserOptions: {
parser: 'babel-eslint',
sourceType: 'module'
},
env: {
browser: true,
},
extends: [
'eslint:recommended',
'plugin:vue/recommended', // or 'plugin:vue/base'
'airbnb-base',
],
// required to lint *.vue files
plugins: [
'vue',
],
// check if imports actually resolve
'settings': {
'import/resolver': {
'webpack': {
'config': 'build/webpack.base.conf.js'
}
},
},
// add your custom rules here
'rules': {
// eslint rules
'camelcase': ['error', {
'properties': 'always'
}],
'function-paren-newline': ['error', 'consistent'],
'id-match': ['error', '^(\\${0,1}[a-z]+[a-zA-Z_]*||[A-Z_0-9]+||[pk][12])$', {
'onlyDeclarations': true,
}],
'max-len': ['error', {
'code': 140,
'ignoreTrailingComments': true,
'ignoreStrings': true,
'ignoreTemplateLiterals': true,
'ignoreUrls': true,
'ignoreComments': true
}],
'no-underscore-dangle': 0,
'no-return-assign': 0,
'object-curly-newline': ['error', {
'consistent': true
}],
'one-var': ['error', {
'initialized': 'never',
}],
'one-var-declaration-per-line': ['error', 'initializations'],
'prefer-destructuring': 0,
// allow debugger during development
'no-debugger': isDev ? 0 : 2,
'no-console': isDev ? 0 : 1,
'no-unused-vars': isDev ? 0 : 1,
// don't require .vue extension when importing
'import/extensions': ['error', 'always', {
'js': 'never',
'vue': 'never'
}],
// allow optionalDependencies
'import/no-extraneous-dependencies': ['error', {
'optionalDependencies': ['test/unit/index.js']
}],
// allow single export
'import/prefer-default-export': 'off',
// vue lint configs
'vue/attribute-hyphenation': ['error', 'always'],
'vue/html-end-tags': 'error',
'vue/html-indent': ['error', 2, {
'attribute': 1,
'closeBracket': 0,
'ignores': []
}],
'vue/html-quotes': ['error', 'double'],
'vue/html-self-closing': ['error', {
'html': {
'normal': 'never',
'void': 'never',
'component': 'never'
},
'svg': 'always',
'math': 'always',
}],
'vue/max-attributes-per-line': [2, {
'singleline': 10,
'multiline': {
'max': 2,
'allowFirstLine': false
},
}],
'vue/mustache-interpolation-spacing': ['error', 'always'],
'vue/name-property-casing': ['error', 'kebab-case'],
'vue/no-async-in-computed-properties': 'error',
'vue/no-confusing-v-for-v-if': 'error',
'vue/no-dupe-keys': 'error',
'vue/no-duplicate-attributes': ['error', {
allowCoexistClass: true,
allowCoexistStyle: true,
}],
'vue/no-multi-spaces': 'error',
'vue/no-parsing-error': 'error',
'vue/no-reserved-keys': ['error', {
'reserved': ['$el', '$nextTick', '$route', '$router', 'asyncData'],
'groups': [],
}],
'vue/no-shared-component-data': 'error',
'vue/no-side-effects-in-computed-properties': 'error',
'vue/no-template-key': 'error',
'vue/no-textarea-mustache': 'error',
// 'vue/order-in-components': ['error', {
// 'order': [
// ['name', 'delimiters', 'functional', 'model'],
// ['components', 'directives', 'filters'],
// ['parent', 'mixins', 'extends', 'provide', 'inject'],
// 'el',
// 'template',
// 'props',
// 'propsData',
// 'data',
// 'computed',
// 'watch',
// 'asyncData',
// 'onWechatReady',
// 'LIFECYCLE_HOOKS',
// 'methods',
// 'render',
// 'renderError'
// ],
// }],
'vue/require-component-is': 'error',
'vue/require-default-prop': 'error',
'vue/require-prop-types': 'error',
'vue/require-render-return': 'error',
'vue/require-v-for-key': 'error',
'vue/require-valid-default-prop': 'error',
'vue/return-in-computed-property': 'error',
'vue/this-in-template': ['error', 'never'],
'vue/v-bind-style': ['error', 'shorthand'],
'vue/v-on-style': ['error', 'shorthand'],
'vue/valid-template-root': 'error',
'vue/valid-v-bind': 'error',
'vue/valid-v-cloak': 'error',
'vue/valid-v-else-if': 'error',
'vue/valid-v-else': 'error',
'vue/valid-v-for': 'error',
'vue/valid-v-html': 'error',
'vue/valid-v-if': 'error',
'vue/valid-v-model': 'error',
'vue/valid-v-on': 'error',
'vue/valid-v-once': 'error',
'vue/valid-v-pre': 'error',
'vue/valid-v-show': 'error',
'vue/valid-v-text': 'error',
}
}
What did you do? Please include the actual source code causing the issue.
<div class="pull-down-touching-tip__text">
{{ scope.distance < fireDistance ? '继续下拉刷新' : '松手刷新' }}
</div>
What did you expect to happen?
No error.
What actually happened? Please include the actual, raw output from ESLint.
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Reactions: 8
- Comments: 45 (18 by maintainers)
This is still a thing, and it is absurd.
The contents of {{ }} is executed as a JavaScript expression. It isn’t HTML by any stretch of the imagination. Having to escape html reserved characters is very unnatural in what is essentially a script.
Let JavaScript expressions be expressions. Fix this bug.
By that logic, anything inside of a
<script>
tag is HTML.Interpolated JS should absolutely not be treated as HTML. Being able to use
>
but having to use<
instead of<
is absolutely ridiculous, I can’t believe that’s an acceptable solution.Oh?
{{ scope.distance < fireDistance ? 'Pull to refresh' : 'Release to refresh' }}
works fine in my environment.No this is NOT html, it’s in
{{}}
, which means it is a inline JavaScript expression.I re-thought about this, I decided that I don’t add that option.
It messes the code easily by removing a space. Inside of mustaches is still HTML.
I’d like to recommend to use
<
(note it requires semicolon) for<
.Thank you.
Thank you for the report.
This is a correct error as according to HTML spec:
Anything else
step.To make valid HTML, you should use
<
instead of the<
. Or you can ignore the error by the option ofvue/no-parsing-error
rule: https://github.com/vuejs/eslint-plugin-vue/blob/master/docs/rules/no-parsing-error.md#wrench-optionsI completely agree with @Smilebags - Vue template is something more than a pure HTML and the linter should obey this fact. Everything inside a mustache and the mustache itself is and should be practically and theoretically invisible for the HTML parser.
It’s still in HTML.
I think we can all agree there are no HTML tags in
{{ a < b ? 1 : 2 }}
. So it follows that seeing an “invalid-first-character-of-tag-name” is a mistake.Either the warning is valid or it isn’t. And seeing how there aren’t any tags in that statement, the warning is not valid.
I think we all understand the situation that leads to the warning being generated today, but the why doesn’t really change the should.
Exactly. So the following code is syntax error since the script ends at the first
</script>
. HTML spec allows<
in script elements.As same,
{{ a<b ? 1 : 2}}
is syntax error because<b>
tag exists there. This is just a fact. I cannot change it.@mysticatea Please disable as default, its really annoying 😦
For reference, add this to your eslintrc.js (eslint config) file to remove notice:
No. the inside of
{{ }}
is HTML in Vue.js 2.x. That’s the reason that I rewrote HTML parser for Vue.js 3 from scratch.This is just a fact. I don’t think the reopen makes sense.
In Vue.js 3 support, this behavior will change, I think. Because the inside of
{{ }}
in Vue.js 3 is not HTML.Quick hotfix to this with error: no error:
the rule
invalid-first-character-of-tag-name
should not be parsed inside mustache tags, inside it is javascript not html, dont matter what is your justification for this, its a compiler warning mustache tags are not suposed to be rendered in browser, so it doesnt make senseSame problem, use
>
instead of<
Not quite what I’m talking about.
https://jsfiddle.net/krvftv74/2/
It’s kind of funny that my example is throwing HTML linter errors, but my point is the Vue linter should know better.
The expression
{{ scope.distance < fireDistance ? 'Pull to refresh' : 'Release to refresh' }}
in template, will be rendered intoPull to refresh
orRelease to refresh
due toscope.distance
andfireDistance
. There is no spec in the result. I can’t understand why lint report an error here. 😕You need to set
parserOptions.vueFeatures.interpolationAsNonHTML
to true.https://github.com/vuejs/vue-eslint-parser#parseroptionsvuefeaturesinterpolationasnonhtml https://github.com/vuejs/vue-eslint-parser/pull/88
All other arguments about syntax aside, if JavaScript expressions (be them ternary or otherwise) are supported and encouraged by VueJS, it should probably not throw an error in a VueJS linter.
alt;
is not a JavaScript operator and anyone’s opinion to the contrary is diverging standard.LOL, still a problem
still have this issue with Vue3 in 2021. I think this issue should be open.
check v-text documentation
use
v-text
( orv-html
)Go in packages.json and add this code
rules: { "vue/no-parsing-error": [2, { "invalid-first-character-of-tag-name": false }] }
still a problem
I know that HTML syntax is very tolerant. Browsers/Parsers work fine even if HTML parse error. But HTML parse errors still exist, so the rule reports it and has the options which are to ignore HTML parse errors.
OK, I opened an issue to add option which ignores HTML syntax errors in mustaches in
vue-eslint-parser
repo.