Custom ESLint processors for analyzing Vue Single File Components and handling Vue-specific comment directives. These processors enable ESLint to understand the structure of .vue files and properly lint template, script, and style blocks.
Primary processor for handling Vue Single File Component files with template, script, and style blocks.
/**
* Main processor for .vue files
* Handles preprocessing and postprocessing of Vue Single File Components
*/
const vueProcessor: ESLintProcessor;
// Accessible as both ".vue" and "vue" keys
const processors = {
".vue": vueProcessor,
"vue": vueProcessor, // Alias for the same processor
};Usage Examples:
// Using processor in flat config
export default [
{
files: ["*.vue"],
processor: "vue/vue", // or "vue/.vue"
plugins: {
vue: eslintPluginVue,
},
rules: {
"vue/multi-word-component-names": "error",
},
},
];
// Using processor in legacy config
module.exports = {
plugins: ["vue"],
overrides: [
{
files: ["*.vue"],
processor: "vue/.vue",
},
],
};Transforms Vue file content before ESLint analysis, extracting script content for linting.
/**
* Preprocesses Vue file content for ESLint analysis
* Extracts script content and handles special Vue syntax
* @param code - The raw Vue file content
* @param filename - The file path being processed
* @returns Array of code blocks to be linted (typically single script block)
*/
function preprocess(code: string, filename: string): string[];Processing Behavior:
// Input: Vue SFC file
const vueFile = `
<template>
<div>{{ message }}</div>
</template>
<script>
export default {
data() {
return { message: 'Hello' };
}
};
</script>
<style>
.container { padding: 20px; }
</style>
`;
// Output: Array with script content
const processed = preprocess(vueFile, "Component.vue");
// Result: [`export default {\n data() {\n return { message: 'Hello' };\n }\n};`]Processes linting messages after ESLint analysis, handling Vue comment directives and filtering messages.
/**
* Postprocesses lint messages from ESLint analysis
* Handles Vue comment directives and filters messages appropriately
* @param messages - Array of message arrays from each processed block
* @returns Filtered and processed lint messages
*/
function postprocess(messages: LintMessage[][]): LintMessage[];Processing Features:
eslint-disable, eslint-enable commentseslint-disable comments// Vue comment directives in templates and scripts
const vueWithDirectives = `
<template>
<!-- eslint-disable-next-line vue/multi-word-component-names -->
<div></div>
</template>
<script>
/* eslint-disable vue/no-unused-vars */
export default {
name: 'App', // This would normally trigger unused-vars
data() {
return { unused: true }; // But it's disabled
}
};
/* eslint-enable vue/no-unused-vars */
</script>
`;The processor supports ESLint's autofix functionality for Vue files.
/**
* Processor autofix support
* Enables ESLint to automatically fix issues in Vue files
*/
const supportsAutofix: boolean = true;Autofix Capabilities:
// Autofix examples in Vue files
// Before:
const beforeFix = `
<template>
<div class="container" >Content</div>
</template>
<script>
export default{
name:'MyComponent',
data(){
return{message:'Hello'}
}
}
</script>
`;
// After running ESLint with --fix:
const afterFix = `
<template>
<div class="container">Content</div>
</template>
<script>
export default {
name: 'MyComponent',
data() {
return { message: 'Hello' };
}
};
</script>
`;Metadata information about the processor capabilities and version.
/**
* Processor metadata
* Provides information about processor capabilities
* References the same meta object as the main plugin
*/
const meta: PluginMeta;The processor implements a sophisticated comment directive system for controlling linting in Vue files.
/**
* Comment directive types supported by the processor
* These directives control which rules are active in different parts of the file
*/
interface CommentDirectives {
/** Disable all rules for a block */
disableBlock: string;
/** Disable all rules for a line */
disableLine: string;
/** Enable all rules for a block */
enableBlock: string;
/** Enable all rules for a line */
enableLine: string;
/** Disable specific rules for a block */
disableBlockRule: string;
/** Disable specific rules for a line */
disableLineRule: string;
/** Enable specific rules for a block */
enableBlockRule: string;
/** Enable specific rules for a line */
enableLineRule: string;
/** Clear all disable states */
clear: string;
}Comment Directive Examples:
// Various comment directive patterns
const directiveExamples = `
<template>
<!-- eslint-disable -->
<div>All rules disabled here</div>
<!-- eslint-enable -->
<!-- eslint-disable vue/html-self-closing -->
<input type="text"></input>
<!-- eslint-enable vue/html-self-closing -->
<!-- eslint-disable-next-line vue/multi-word-component-names -->
<App />
</template>
<script>
/* eslint-disable vue/no-unused-vars */
export default {
name: 'Component',
/* eslint-enable vue/no-unused-vars */
data() {
// eslint-disable-next-line vue/no-side-effects-in-computed-properties
const computed = this.computedValue;
return {};
}
};
</script>
`;The processor maintains accurate error location mapping between processed and original Vue file content.
/**
* Location mapping for error reporting
* Maps positions in processed content back to original Vue file locations
*/
interface LocationMapping {
/** Original line number in Vue file */
originalLine: number;
/** Original column number in Vue file */
originalColumn: number;
/** Processed line number */
processedLine: number;
/** Processed column number */
processedColumn: number;
}Location Mapping Example:
// Original Vue file with line numbers
const originalVue = `
1: <template>
2: <div>{{ message }}</div>
3: </template>
4:
5: <script>
6: export default {
7: data() {
8: return { message: 'Hello' };
9: }
10:};
11:</script>
`;
// Error in processed script content at line 3, column 5
// Maps back to original line 8, column 5 in the Vue fileinterface ESLintProcessor {
/** Transform file content before linting */
preprocess: (code: string, filename: string) => string[];
/** Process lint messages after linting */
postprocess: (messages: LintMessage[][]) => LintMessage[];
/** Whether processor supports auto-fixing */
supportsAutofix: boolean;
/** Processor metadata */
meta: ProcessorMeta;
}
interface ProcessorMeta {
name: string;
version: string;
}
interface LintMessage {
/** Rule that generated this message */
ruleId: string | null;
/** Message severity (1 = warning, 2 = error) */
severity: 1 | 2;
/** Human-readable message */
message: string;
/** Line number (1-based) */
line: number;
/** Column number (1-based) */
column: number;
/** AST node type that caused the issue */
nodeType?: string;
/** Message template ID */
messageId?: string;
/** End line number for multi-line issues */
endLine?: number;
/** End column number for multi-line issues */
endColumn?: number;
/** Auto-fix information */
fix?: FixInfo;
/** Suggested fixes */
suggestions?: SuggestionInfo[];
}
interface FixInfo {
/** Range to replace [start, end] */
range: [number, number];
/** Text to insert */
text: string;
}
interface SuggestionInfo {
/** Description of the suggestion */
desc: string;
/** Fix information */
fix: FixInfo;
/** Message template ID */
messageId?: string;
/** Data for message template */
data?: Record<string, any>;
}
interface GroupState {
/** Keys for disabled-all directives */
disableAllKeys: Set<string>;
/** Keys for rule-specific disable directives */
disableRuleKeys: Map<string, string[]>;
}
interface ProcessorState {
/** Block-level disable state */
block: GroupState;
/** Line-level disable state */
line: GroupState;
}