84 lines
3.3 KiB
JavaScript
84 lines
3.3 KiB
JavaScript
/**
|
|
* @fileoverview Rule to enforce correct placement of at-rules.
|
|
* @author thecalamiity
|
|
*/
|
|
//-----------------------------------------------------------------------------
|
|
// Type Definitions
|
|
//-----------------------------------------------------------------------------
|
|
/**
|
|
* @import { CSSRuleDefinition } from "../types.js"
|
|
* @typedef {"invalidCharsetPlacement" | "invalidImportPlacement" | "invalidNamespacePlacement"} NoInvalidAtRulePlacementMessageIds
|
|
* @typedef {CSSRuleDefinition<{ RuleOptions: [], MessageIds: NoInvalidAtRulePlacementMessageIds }>} NoInvalidAtRulePlacementRuleDefinition
|
|
*/
|
|
//-----------------------------------------------------------------------------
|
|
// Rule Definition
|
|
//-----------------------------------------------------------------------------
|
|
export default /** @satisfies {NoInvalidAtRulePlacementRuleDefinition} */ ({
|
|
meta: {
|
|
type: "problem",
|
|
docs: {
|
|
description: "Disallow invalid placement of at-rules",
|
|
recommended: true,
|
|
url: "https://github.com/eslint/css/blob/main/docs/rules/no-invalid-at-rule-placement.md",
|
|
},
|
|
messages: {
|
|
invalidCharsetPlacement: "@charset must be placed at the very beginning of the stylesheet, before any rules, comments, or whitespace.",
|
|
invalidImportPlacement: "@import must be placed before all other rules, except @charset and @layer statements.",
|
|
invalidNamespacePlacement: "@namespace must be placed before all other rules, except @charset and @import.",
|
|
},
|
|
},
|
|
create(context) {
|
|
let hasSeenNonImportRule = false;
|
|
let hasSeenLayerBlock = false;
|
|
let hasSeenLayer = false;
|
|
let hasSeenNamespace = false;
|
|
return {
|
|
Atrule(node) {
|
|
const name = node.name.toLowerCase();
|
|
if (name === "charset") {
|
|
if (node.loc.start.line !== 1 ||
|
|
node.loc.start.column !== 1) {
|
|
context.report({
|
|
node,
|
|
messageId: "invalidCharsetPlacement",
|
|
});
|
|
}
|
|
return;
|
|
}
|
|
if (name === "layer") {
|
|
if (node.block) {
|
|
hasSeenLayerBlock = true;
|
|
}
|
|
hasSeenLayer = true;
|
|
return;
|
|
}
|
|
if (name === "namespace") {
|
|
if (hasSeenNonImportRule || hasSeenLayer) {
|
|
context.report({
|
|
node,
|
|
messageId: "invalidNamespacePlacement",
|
|
});
|
|
}
|
|
hasSeenNamespace = true;
|
|
return;
|
|
}
|
|
if (name === "import") {
|
|
if (hasSeenNonImportRule ||
|
|
hasSeenNamespace ||
|
|
hasSeenLayerBlock) {
|
|
context.report({
|
|
node,
|
|
messageId: "invalidImportPlacement",
|
|
});
|
|
}
|
|
return;
|
|
}
|
|
hasSeenNonImportRule = true;
|
|
},
|
|
Rule() {
|
|
hasSeenNonImportRule = true;
|
|
},
|
|
};
|
|
},
|
|
});
|