eslint-plugin-lit
Advanced tools
Comparing version 0.2.1 to 0.3.0
@@ -6,2 +6,3 @@ "use strict"; | ||
*/ | ||
const template_analyzer_1 = require("../template-analyzer"); | ||
//------------------------------------------------------------------------------ | ||
@@ -17,2 +18,6 @@ // Rule Definition | ||
url: 'https://github.com/43081j/eslint-plugin-lit/blob/master/docs/rules/attribute-value-entities.md' | ||
}, | ||
messages: { | ||
unencoded: 'Attribute values may not contain unencoded HTML ' + | ||
'entities, e.g. use `>` instead of `>`' | ||
} | ||
@@ -22,3 +27,3 @@ }, | ||
// variables should be defined here | ||
const disallowedPattern = /[^\s=]+=('[^"']*"|("[^&<>"]*|'[^&<>']*)[&<>]+)/; | ||
const disallowedPattern = /[&<>"]/; | ||
//---------------------------------------------------------------------- | ||
@@ -35,11 +40,20 @@ // Helpers | ||
node.tag.name === 'html') { | ||
for (const quasi of node.quasi.quasis) { | ||
if (disallowedPattern.test(quasi.value.raw)) { | ||
context.report({ | ||
node: quasi, | ||
message: 'Attribute values may not contain unencoded HTML ' + | ||
'entities, e.g. use `>` instead of `>`' | ||
}); | ||
const analyzer = template_analyzer_1.TemplateAnalyzer.create(node); | ||
analyzer.traverse({ | ||
enterElement: (element) => { | ||
// eslint-disable-next-line guard-for-in | ||
for (const attr in element.attribs) { | ||
const loc = analyzer.getLocationForAttribute(element, attr); | ||
if (!loc) { | ||
continue; | ||
} | ||
if (disallowedPattern.test(element.attribs[attr])) { | ||
context.report({ | ||
loc: loc, | ||
messageId: 'unencoded' | ||
}); | ||
} | ||
} | ||
} | ||
} | ||
}); | ||
} | ||
@@ -46,0 +60,0 @@ } |
@@ -6,2 +6,3 @@ "use strict"; | ||
*/ | ||
const template_analyzer_1 = require("../template-analyzer"); | ||
//------------------------------------------------------------------------------ | ||
@@ -16,2 +17,5 @@ // Rule Definition | ||
url: 'https://github.com/43081j/eslint-plugin-lit/blob/master/docs/rules/no-duplicate-template-bindings.md' | ||
}, | ||
messages: { | ||
duplicateBinding: 'Duplicate bindings are not allowed.' | ||
} | ||
@@ -21,4 +25,2 @@ }, | ||
// variables should be defined here | ||
const propertyPattern = /\b([\.@\?])?([\w\-]+)([=\s>])/g; | ||
const tagPattern = /<[^\/][^>]*>/g; // todo: handle `foo=">"` | ||
//---------------------------------------------------------------------- | ||
@@ -35,23 +37,11 @@ // Helpers | ||
node.tag.name === 'html') { | ||
const html = node.quasi.quasis | ||
.map((q) => q.value.raw) | ||
.join('{{__lint__}}'); | ||
const tags = html.match(tagPattern); | ||
if (tags) { | ||
for (const tag of tags) { | ||
const pattern = new RegExp(propertyPattern.source, 'g'); | ||
let match; | ||
let seen = []; | ||
while ((match = pattern.exec(tag)) !== null) { | ||
if (seen.includes(match[2])) { | ||
// todo: maybe report column of this property | ||
context.report({ | ||
node: node, | ||
message: `Duplicate bindings are not allowed, "${match[2]}" was set multiple times.` | ||
}); | ||
} | ||
else { | ||
seen.push(match[2]); | ||
} | ||
} | ||
const analyzer = template_analyzer_1.TemplateAnalyzer.create(node); | ||
const dupeErrors = analyzer.errors.filter((err) => err.code === 'duplicate-attribute'); | ||
for (const err of dupeErrors) { | ||
const loc = analyzer.resolveLocation(err); | ||
if (loc) { | ||
context.report({ | ||
loc: loc, | ||
messageId: 'duplicateBinding' | ||
}); | ||
} | ||
@@ -58,0 +48,0 @@ } |
@@ -6,2 +6,3 @@ "use strict"; | ||
*/ | ||
const template_analyzer_1 = require("../template-analyzer"); | ||
//------------------------------------------------------------------------------ | ||
@@ -16,2 +17,5 @@ // Rule Definition | ||
url: 'https://github.com/43081j/eslint-plugin-lit/blob/master/docs/rules/no-legacy-template-syntax.md' | ||
}, | ||
messages: { | ||
unsupported: 'Legacy lit-extended syntax is unsupported, did you mean to use "{{replacement}}"?' | ||
} | ||
@@ -21,3 +25,3 @@ }, | ||
// variables should be defined here | ||
const legacyPropertyPattern = /\b(on\-([\w\-]+)|([\w\-]+)([\$\?]))=$/; | ||
const legacyEventPattern = /^on-./; | ||
//---------------------------------------------------------------------- | ||
@@ -34,24 +38,36 @@ // Helpers | ||
node.tag.name === 'html') { | ||
for (const quasi of node.quasi.quasis) { | ||
const val = quasi.value.raw; | ||
const match = val.match(legacyPropertyPattern); | ||
if (match) { | ||
if (match[3]) { | ||
let replacement = `${match[3]}=`; | ||
if (match[4] === '?') { | ||
replacement = `?${match[3]}=`; | ||
const analyzer = template_analyzer_1.TemplateAnalyzer.create(node); | ||
analyzer.traverse({ | ||
enterElement: (element) => { | ||
// eslint-disable-next-line guard-for-in | ||
for (const attr in element.attribs) { | ||
const loc = analyzer.getLocationForAttribute(element, attr); | ||
if (!loc) { | ||
continue; | ||
} | ||
context.report({ | ||
node: quasi, | ||
message: `Legacy lit-extended syntax is unsupported, did you mean to use "${replacement}"?` | ||
}); | ||
const lastChar = attr.slice(-1); | ||
if (legacyEventPattern.test(attr)) { | ||
const replacement = `@${attr.substr(3)}=`; | ||
context.report({ | ||
loc: loc, | ||
messageId: 'unsupported', | ||
data: { | ||
replacement: replacement | ||
} | ||
}); | ||
} | ||
else if (lastChar === '?' || lastChar === '$') { | ||
const prefix = lastChar === '?' ? '?' : ''; | ||
const replacement = `${prefix}${attr.slice(0, -1)}=`; | ||
context.report({ | ||
loc: loc, | ||
messageId: 'unsupported', | ||
data: { | ||
replacement: replacement | ||
} | ||
}); | ||
} | ||
} | ||
else { | ||
context.report({ | ||
node: quasi, | ||
message: `Legacy lit-extended syntax is unsupported, did you mean to use "@${match[2]}="?` | ||
}); | ||
} | ||
} | ||
} | ||
}); | ||
} | ||
@@ -58,0 +74,0 @@ } |
@@ -16,1 +16,17 @@ import * as ESTree from 'estree'; | ||
export declare function getPropertyMap(node: ESTree.Class): ReadonlyMap<string, ESTree.ObjectExpression>; | ||
/** | ||
* Generates a placeholder string for a given quasi | ||
* | ||
* @param {ESTree.TaggedTemplateExpression} node Root node | ||
* @param {ESTree.TemplateElement} quasi Quasi to generate placeholder | ||
* for | ||
* @return {string} | ||
*/ | ||
export declare function getExpressionPlaceholder(node: ESTree.TaggedTemplateExpression, quasi: ESTree.TemplateElement): string; | ||
/** | ||
* Converts a template expression into HTML | ||
* | ||
* @param {ESTree.TaggedTemplateExpression} node Node to convert | ||
* @return {string} | ||
*/ | ||
export declare function templateExpressionToHtml(node: ESTree.TaggedTemplateExpression): string; |
@@ -65,1 +65,36 @@ "use strict"; | ||
exports.getPropertyMap = getPropertyMap; | ||
/** | ||
* Generates a placeholder string for a given quasi | ||
* | ||
* @param {ESTree.TaggedTemplateExpression} node Root node | ||
* @param {ESTree.TemplateElement} quasi Quasi to generate placeholder | ||
* for | ||
* @return {string} | ||
*/ | ||
function getExpressionPlaceholder(node, quasi) { | ||
const i = node.quasi.quasis.indexOf(quasi); | ||
if (/=$/.test(quasi.value.raw)) { | ||
return `"{{__Q:${i}__}}"`; | ||
} | ||
return `{{__Q:${i}__}}`; | ||
} | ||
exports.getExpressionPlaceholder = getExpressionPlaceholder; | ||
/** | ||
* Converts a template expression into HTML | ||
* | ||
* @param {ESTree.TaggedTemplateExpression} node Node to convert | ||
* @return {string} | ||
*/ | ||
function templateExpressionToHtml(node) { | ||
let html = ''; | ||
for (let i = 0; i < node.quasi.quasis.length; i++) { | ||
const quasi = node.quasi.quasis[i]; | ||
const expr = node.quasi.expressions[i]; | ||
html += quasi.value.raw; | ||
if (expr) { | ||
html += getExpressionPlaceholder(node, quasi); | ||
} | ||
} | ||
return html; | ||
} | ||
exports.templateExpressionToHtml = templateExpressionToHtml; |
{ | ||
"name": "eslint-plugin-lit", | ||
"version": "0.2.1", | ||
"version": "0.3.0", | ||
"description": "lit-html support for ESLint", | ||
@@ -29,2 +29,4 @@ "main": "lib/index.js", | ||
"dependencies": { | ||
"parse5": "^5.1.0", | ||
"parse5-htmlparser2-tree-adapter": "^5.1.0", | ||
"requireindex": "^1.2.0" | ||
@@ -36,2 +38,4 @@ }, | ||
"@types/node": "^10.7.1", | ||
"@types/parse5": "^5.0.0", | ||
"@types/parse5-htmlparser2-tree-adapter": "^5.0.1", | ||
"babel-eslint": "^9.0.0", | ||
@@ -38,0 +42,0 @@ "chai": "^4.1.2", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
42878
34
948
3
13
+ Addedparse5@^5.1.0
+ Addedparse5@5.1.1(transitive)
+ Addedparse5-htmlparser2-tree-adapter@5.1.1(transitive)