| /** |
| * @fileoverview Detects usages of the `value` attribute |
| * @author James Garbutt <https://github.com/43081j> |
| */ |
| import { TemplateAnalyzer } from '../template-analyzer.js'; |
| import { isExpressionPlaceholder } from '../util.js'; |
| //------------------------------------------------------------------------------ |
| // Rule Definition |
| //------------------------------------------------------------------------------ |
| export const rule = { |
| meta: { |
| docs: { |
| description: 'Detects usages of the `value` attribute where the ' + |
| 'equivalent property should be used instead', |
| recommended: false, |
| url: 'https://github.com/43081j/eslint-plugin-lit/blob/master/docs/rules/no-value-attribute.md' |
| }, |
| fixable: 'code', |
| schema: [], |
| messages: { |
| preferProperty: 'The `value` attribute only defines the initial value ' + |
| 'rather than permanently binding; you should set the `value` ' + |
| 'property instead via `.value`' |
| } |
| }, |
| create(context) { |
| const source = context.getSourceCode(); |
| const warnedTags = ['input']; |
| //---------------------------------------------------------------------- |
| // Helpers |
| //---------------------------------------------------------------------- |
| //---------------------------------------------------------------------- |
| // Public |
| //---------------------------------------------------------------------- |
| return { |
| TaggedTemplateExpression: (node) => { |
| if (node.type === 'TaggedTemplateExpression' && |
| node.tag.type === 'Identifier' && |
| node.tag.name === 'html') { |
| const analyzer = TemplateAnalyzer.create(node); |
| analyzer.traverse({ |
| enterElement: (element) => { |
| if (warnedTags.includes(element.tagName) && |
| 'value' in element.attribs && |
| isExpressionPlaceholder(element.attribs['value'])) { |
| const loc = analyzer.getLocationForAttribute(element, 'value', source); |
| if (loc) { |
| const range = source.getIndexFromLoc(loc.start); |
| context.report({ |
| loc, |
| messageId: 'preferProperty', |
| fix: (fixer) => fixer.insertTextBeforeRange([range, range], '.') |
| }); |
| } |
| } |
| } |
| }); |
| } |
| } |
| }; |
| } |
| }; |