UNPKG

eslint-plugin-ember

Version:
83 lines (75 loc) 2.64 kB
/** @type {import('eslint').Rule.RuleModule} */ module.exports = { meta: { type: 'problem', docs: { description: 'disallow tagName attribute on {{input}} helper', category: 'Best Practices', url: 'https://github.com/ember-cli/eslint-plugin-ember/tree/master/docs/rules/template-no-input-tagname.md', templateMode: 'both', }, schema: [], messages: { unexpected: 'Unexpected tagName usage on input helper.' }, originallyFrom: { name: 'ember-template-lint', rule: 'lib/rules/no-input-tagname.js', docs: 'docs/rule/no-input-tagname.md', tests: 'test/unit/rules/no-input-tagname-test.js', }, }, create(context) { const isStrictMode = context.filename.endsWith('.gjs') || context.filename.endsWith('.gts'); // local name → 'Input'. Only populated in GJS/GTS via ImportDeclaration. const importedComponents = new Map(); function checkCurly(node) { if (!node.path) { return; } const attrs = node.hash?.pairs || []; const hasTagName = attrs.some((a) => a.key === 'tagName'); if (node.path.original === 'input' && hasTagName) { context.report({ node, messageId: 'unexpected' }); } else if ( node.path.original === 'component' && node.params?.[0]?.original === 'input' && hasTagName ) { context.report({ node, messageId: 'unexpected' }); } } const visitors = { GlimmerElementNode(node) { const hasTagName = node.attributes?.some((a) => a.name === '@tagName'); if (!hasTagName) { return; } if (isStrictMode) { // In GJS/GTS: only flag if explicitly imported from @ember/component if (importedComponents.has(node.tag)) { context.report({ node, messageId: 'unexpected' }); } } else { // In HBS: <Input ...> always resolves to the framework Input if (node.tag === 'Input') { context.report({ node, messageId: 'unexpected' }); } } }, }; if (isStrictMode) { visitors.ImportDeclaration = function (node) { if (node.source.value === '@ember/component') { for (const specifier of node.specifiers) { if (specifier.type === 'ImportSpecifier' && specifier.imported.name === 'Input') { importedComponents.set(specifier.local.name, 'Input'); } } } }; } else { visitors.GlimmerMustacheStatement = checkCurly; visitors.GlimmerSubExpression = checkCurly; } return visitors; }, };