@herb-tools/linter 0.8.0 → 0.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +42 -2
- package/dist/herb-lint.js +88 -17
- package/dist/herb-lint.js.map +1 -1
- package/dist/index.cjs +58 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +59 -1
- package/dist/index.js.map +1 -1
- package/dist/loader.cjs +70 -8
- package/dist/loader.cjs.map +1 -1
- package/dist/loader.js +70 -8
- package/dist/loader.js.map +1 -1
- package/dist/package.json +7 -7
- package/dist/src/herb-disable-comment-utils.js.map +1 -1
- package/dist/src/linter-ignore.js +42 -0
- package/dist/src/linter-ignore.js.map +1 -0
- package/dist/src/linter.js +12 -0
- package/dist/src/linter.js.map +1 -1
- package/dist/src/rules/html-head-only-elements.js +6 -1
- package/dist/src/rules/html-head-only-elements.js.map +1 -1
- package/dist/src/rules/rule-utils.js +2 -0
- package/dist/src/rules/rule-utils.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/linter-ignore.d.ts +12 -0
- package/dist/types/rules/rule-utils.d.ts +1 -1
- package/dist/types/src/linter-ignore.d.ts +12 -0
- package/dist/types/src/rules/rule-utils.d.ts +1 -1
- package/docs/rules/html-head-only-elements.md +24 -2
- package/package.json +7 -7
- package/src/herb-disable-comment-utils.ts +3 -0
- package/src/linter-ignore.ts +50 -0
- package/src/linter.ts +14 -0
- package/src/rules/html-head-only-elements.ts +6 -1
- package/src/rules/rule-utils.ts +3 -1
package/dist/index.cjs
CHANGED
|
@@ -3055,6 +3055,8 @@ function findAttributeByName(attributes, attributeName) {
|
|
|
3055
3055
|
* Checks if a tag has a specific attribute
|
|
3056
3056
|
*/
|
|
3057
3057
|
function hasAttribute(node, attributeName) {
|
|
3058
|
+
if (!node)
|
|
3059
|
+
return false;
|
|
3058
3060
|
return getAttribute(node, attributeName) !== null;
|
|
3059
3061
|
}
|
|
3060
3062
|
/**
|
|
@@ -5154,8 +5156,13 @@ class HeadOnlyElementsVisitor extends BaseRuleVisitor {
|
|
|
5154
5156
|
return;
|
|
5155
5157
|
if (tagName === "title" && this.insideSVG)
|
|
5156
5158
|
return;
|
|
5159
|
+
if (tagName === "meta" && this.hasItempropAttribute(node))
|
|
5160
|
+
return;
|
|
5157
5161
|
this.addOffense(`Element \`<${tagName}>\` must be placed inside the \`<head>\` tag.`, node.location);
|
|
5158
5162
|
}
|
|
5163
|
+
hasItempropAttribute(node) {
|
|
5164
|
+
return hasAttribute(node.open_tag, "itemprop");
|
|
5165
|
+
}
|
|
5159
5166
|
get insideHead() {
|
|
5160
5167
|
return this.elementStack.includes("head");
|
|
5161
5168
|
}
|
|
@@ -6665,6 +6672,46 @@ const rules = [
|
|
|
6665
6672
|
ParserNoErrorsRule,
|
|
6666
6673
|
];
|
|
6667
6674
|
|
|
6675
|
+
const HERB_LINTER_PREFIX = "herb:linter";
|
|
6676
|
+
const HERB_LINTER_IGNORE_PREFIX = `${HERB_LINTER_PREFIX} ignore`;
|
|
6677
|
+
/**
|
|
6678
|
+
* Check if an ERB content node is a herb:linter ignore comment.
|
|
6679
|
+
*
|
|
6680
|
+
* @param node - The ERB content node to check
|
|
6681
|
+
* @returns true if this is a linter ignore directive
|
|
6682
|
+
*/
|
|
6683
|
+
function isHerbLinterIgnoreComment(node) {
|
|
6684
|
+
if (!core.isERBCommentNode(node))
|
|
6685
|
+
return false;
|
|
6686
|
+
const content = node?.content?.value || "";
|
|
6687
|
+
return content.trim() === HERB_LINTER_IGNORE_PREFIX;
|
|
6688
|
+
}
|
|
6689
|
+
/**
|
|
6690
|
+
* Check if the document contains a herb:linter ignore directive anywhere.
|
|
6691
|
+
*/
|
|
6692
|
+
function hasLinterIgnoreDirective(parseResult) {
|
|
6693
|
+
if (parseResult.failed)
|
|
6694
|
+
return false;
|
|
6695
|
+
const detector = new LinterIgnoreDetector();
|
|
6696
|
+
detector.visit(parseResult.value);
|
|
6697
|
+
return detector.hasIgnoreDirective;
|
|
6698
|
+
}
|
|
6699
|
+
/**
|
|
6700
|
+
* Visitor that detects if the AST contains a herb:linter ignore directive.
|
|
6701
|
+
*/
|
|
6702
|
+
class LinterIgnoreDetector extends core.Visitor {
|
|
6703
|
+
hasIgnoreDirective = false;
|
|
6704
|
+
visitERBContentNode(node) {
|
|
6705
|
+
if (isHerbLinterIgnoreComment(node)) {
|
|
6706
|
+
this.hasIgnoreDirective = true;
|
|
6707
|
+
return;
|
|
6708
|
+
}
|
|
6709
|
+
if (this.hasIgnoreDirective)
|
|
6710
|
+
return;
|
|
6711
|
+
this.visitChildNodes(node);
|
|
6712
|
+
}
|
|
6713
|
+
}
|
|
6714
|
+
|
|
6668
6715
|
class Linter {
|
|
6669
6716
|
rules;
|
|
6670
6717
|
allAvailableRules;
|
|
@@ -6875,6 +6922,17 @@ class Linter {
|
|
|
6875
6922
|
let ignoredCount = 0;
|
|
6876
6923
|
let wouldBeIgnoredCount = 0;
|
|
6877
6924
|
const parseResult = this.herb.parse(source, { track_whitespace: true });
|
|
6925
|
+
// Check for file-level ignore directive using visitor
|
|
6926
|
+
if (hasLinterIgnoreDirective(parseResult)) {
|
|
6927
|
+
return {
|
|
6928
|
+
offenses: [],
|
|
6929
|
+
errors: 0,
|
|
6930
|
+
warnings: 0,
|
|
6931
|
+
info: 0,
|
|
6932
|
+
hints: 0,
|
|
6933
|
+
ignored: 0
|
|
6934
|
+
};
|
|
6935
|
+
}
|
|
6878
6936
|
const lexResult = this.herb.lex(source);
|
|
6879
6937
|
const hasParserErrors = parseResult.recursiveErrors().length > 0;
|
|
6880
6938
|
const sourceLines = source.split("\n");
|