Formats your JavaScript using prettier followed by eslint --fix
npx @tessl/cli install tessl/npm-prettier-eslint@16.4.0prettier-eslint is a code formatting tool that combines the power of Prettier's opinionated formatting with ESLint's configurable rule system. It formats JavaScript, TypeScript, Vue, and Svelte code by first applying Prettier formatting, then running ESLint with the --fix flag to apply project-specific linting rules and coding standards.
npm install prettier-eslintconst format = require('prettier-eslint');
const { format, analyze } = require('prettier-eslint');ES Modules (for TypeScript projects):
import prettierEslint from 'prettier-eslint';
import { format, analyze, getOptionsForFormatting, requireModule, getESLint } from 'prettier-eslint';
import type { FormatOptions, ESLintConfig, LogLevel, PrettierOptions } from 'prettier-eslint';Type imports for advanced usage:
import type { Linter } from 'eslint';
import type { ESLint } from 'eslint';const format = require('prettier-eslint');
const sourceCode = 'const {foo} = bar';
const options = {
text: sourceCode,
eslintConfig: {
parserOptions: {
ecmaVersion: 2017,
},
rules: {
semi: ['error', 'never'],
},
},
prettierOptions: {
bracketSpacing: true,
},
};
const formatted = await format(options);
console.log(formatted); // "const { foo } = bar"Alternative usage with file path:
const format = require('prettier-eslint');
// Format a file directly - ESLint config will be auto-resolved
const formatted = await format({
filePath: './src/component.js',
prettierOptions: {
printWidth: 100
}
});Note: The module exports format as the default export, so require('prettier-eslint') returns the format function directly. Named exports are also available for format and analyze.
The primary function that formats code using Prettier followed by ESLint --fix.
/**
* Formats the text with Prettier and then ESLint while obeying the user's configuration
* @param options - Configuration options for formatting
* @returns Promise resolving to the formatted string
*/
function format(options: FormatOptions): Promise<string>;Usage Example:
import { format } from 'prettier-eslint';
const result = await format({
text: 'function hello(){console.log("world")}',
eslintConfig: {
rules: {
semi: ['error', 'always'],
quotes: ['error', 'single']
}
},
prettierOptions: {
singleQuote: true,
semi: true
}
});Analyzes and formats code, returning both the formatted output and ESLint linting messages.
/**
* Analyzes and formats text with prettier and eslint, returning both output and messages
* @param options - Configuration options identical to format function
* @returns Promise resolving to object with formatted output and ESLint messages
*/
function analyze(options: FormatOptions): Promise<{
output: string;
messages: Linter.LintMessage[];
}>;Usage Example:
import { analyze } from 'prettier-eslint';
const result = await analyze({
text: 'const unused = 42; console.log("hello");',
eslintConfig: {
rules: {
'no-unused-vars': ['error'],
'no-console': ['warn']
}
}
});
console.log(result.output); // Formatted code
console.log(result.messages); // ESLint messages arrayAll formatting functions accept a comprehensive options object for fine-grained control.
interface FormatOptions {
/** The source code to format */
text?: string;
/** The path of the file being formatted (can be used in lieu of text) */
filePath?: string;
/** ESLint configuration object */
eslintConfig?: ESLintConfig;
/** Path to the eslint module to use */
eslintPath?: string;
/** Prettier formatting options */
prettierOptions?: PrettierOptions;
/** Path to the prettier module to use */
prettierPath?: string;
/** Fallback Prettier options when values cannot be inferred from ESLint config */
fallbackPrettierOptions?: PrettierOptions;
/** Run Prettier after ESLint instead of before */
prettierLast?: boolean;
/** Logging level for debug output */
logLevel?: LogLevel;
}File Path Usage:
// Format a file directly
const result = await format({
filePath: './src/component.tsx',
// ESLint config will be automatically resolved for the file
prettierOptions: {
printWidth: 100
}
});Custom Module Paths:
const result = await format({
text: sourceCode,
eslintPath: './node_modules/eslint',
prettierPath: './node_modules/prettier',
eslintConfig: { /* config */ }
});Extended ESLint configuration interface supporting both object and string array formats for globals.
type ESLintOptions = Omit<
ESLint.Options,
'plugins' | 'reportUnusedDisableDirectives'
>;
interface ESLintConfig extends Omit<Linter.Config, 'globals'>, ESLintOptions {
/** ESLint globals configuration, supporting both object format and string tuple format */
globals?: ESLintConfigGlobals | [`${string}:${ESLintConfigGlobalValue}`];
/** Ignore patterns for files */
ignorePattern?: string[] | string;
/** File extensions to process with ESLint */
extensions?: string[];
}
type ESLintConfigGlobals = Linter.Config['globals'];
type ESLintConfigGlobalValue = 'readonly' | 'writable' | 'off';Globals Configuration:
// Object format
const config = {
globals: {
window: 'readonly',
document: 'readonly',
myGlobal: 'writable'
}
};
// String array format
const config = {
globals: ['window:readonly', 'document:readonly', 'myGlobal:writable']
};Re-exported Prettier options interface for type safety.
type PrettierOptions = import('prettier').Options;Common Prettier options used with prettier-eslint:
const prettierOptions = {
printWidth: 80,
tabWidth: 2,
useTabs: false,
semi: true,
singleQuote: true,
quoteProps: 'as-needed',
trailingComma: 'es5',
bracketSpacing: true,
bracketSameLine: false,
arrowParens: 'avoid',
parser: 'typescript'
};Control the verbosity of debugging output during the formatting process.
type LogLevel = 'debug' | 'error' | 'info' | 'silent' | 'trace' | 'warn';Logging Usage:
const result = await format({
text: sourceCode,
logLevel: 'debug', // Enable detailed logging
eslintConfig: { /* config */ }
});Core utility functions for advanced integration scenarios.
/**
* Extracts and prepares formatting options for ESLint and Prettier
* @param eslintConfig - ESLint configuration
* @param prettierOptions - Prettier options (optional)
* @param fallbackPrettierOptions - Fallback Prettier options (optional)
* @returns Object containing processed eslint and prettier options
*/
function getOptionsForFormatting(
eslintConfig: ESLintConfig,
prettierOptions?: PrettierOptions,
fallbackPrettierOptions?: PrettierOptions
): {
eslint: ESLintConfig;
prettier: PrettierOptions;
};
/**
* Safely requires a module with error handling
* @param modulePath - Path to the module
* @param name - Name of the module for error messages
* @returns The required module
*/
function requireModule<T>(modulePath: string, name: string): T;
/**
* Creates ESLint instance with given path and options
* @param eslintPath - Path to ESLint module
* @param eslintOptions - ESLint configuration options
* @returns ESLint instance
*/
function getESLint(eslintPath: string, eslintOptions: ESLintOptions): ESLint;Additional type definitions used by the library.
/** Input structure for internal prettify function */
interface PrettifyInput {
output: string;
messages: Linter.LintMessage[];
}
/** Utility type for string literals with fallback */
type StringLiteral<T> = T | (string & { _?: never });
/** Option getter structure for mapping ESLint rules to Prettier options */
interface OptionGetter {
ruleValue: (rules?: Partial<Linter.RulesRecord>) => StringLiteral<Linter.RuleEntry> | undefined;
ruleValueToPrettierOption: (...args: any[]) => unknown;
}
/** Value type for ESLint config globals */
type ESLintConfigGlobalValue = 'readonly' | 'writable' | 'off';
/** Helper type for extracting values from objects */
type ValueOf<T> = T[keyof T];prettier-eslint automatically handles the following file extensions:
.js, .jsx, .mjs, .cjs.ts, .tsx, .mts, .cts.vue (requires vue-eslint-parser).svelte (requires svelte-eslint-parser and prettier-plugin-svelte)For unsupported file extensions, only Prettier formatting is applied (ESLint is skipped).
prettier-eslint automatically configures appropriate parsers based on file extensions:
// Automatic parser selection
'.ts', '.tsx' → '@typescript-eslint/parser'
'.vue' → 'vue-eslint-parser'
'.svelte' → 'svelte-eslint-parser'Both format and analyze functions can throw errors in the following scenarios:
filePath is specified but file doesn't existAlways wrap calls in try-catch blocks:
try {
const result = await format({
filePath: './src/component.js',
eslintConfig: { /* config */ }
});
} catch (error) {
console.error('Formatting failed:', error.message);
}const through = require('through2');
const prettierEslint = require('prettier-eslint');
function createFormatterStream(options = {}) {
return through.obj(async function(file, enc, callback) {
if (file.isNull()) {
return callback(null, file);
}
try {
const formatted = await prettierEslint({
text: file.contents.toString(),
filePath: file.path,
...options
});
file.contents = Buffer.from(formatted);
callback(null, file);
} catch (error) {
callback(error);
}
});
}
gulp.task('format', () =>
gulp.src('src/**/*.js')
.pipe(createFormatterStream({
eslintConfig: {
extends: ['eslint:recommended']
}
}))
.pipe(gulp.dest('src/'))
);const fs = require('fs');
const path = require('path');
const { format } = require('prettier-eslint');
async function formatFile(filePath) {
const text = fs.readFileSync(filePath, 'utf8');
const formatted = await format({
text,
filePath,
// Let ESLint find the config automatically
logLevel: 'warn'
});
fs.writeFileSync(filePath, formatted);
console.log(`Formatted: ${filePath}`);
}
// Usage
formatFile('./src/index.js');