Skip to content

RFC: Allow to exclude files via "file extensions" #216

@rainerhahnekamp

Description

@rainerhahnekamp

Handling Non-TypeScript File Imports in Sheriff

Sheriff relies on the TypeScript compiler to generate the dependency graph. This
design choice ensures that any file extension supported by the TypeScript
compiler—such as .vue or .tsx—works out of the box without requiring
additional configuration.

However, in modern frontend projects, it's common to import non-TypeScript
assets like SVGs, images, or stylesheets. In these cases, the bundler
(e.g., Vite, Webpack) provides a loader to handle such imports. Since Sheriff
operates exclusively on the TypeScript API, these non-code imports currently
cause failures.

This limitation has already been reported in the following issues:

Proposed Solution

We introduce a configuration property:

"ignoreFileExtensions": [
  ".svg", ".png", ".jpg", ".jpeg", ".gif", ".webp", ".ico",
  ".css", ".scss", ".sass", ".less",
  ".woff", ".woff2", ".ttf", ".eot", ".otf",
  ".mp3", ".wav", ".ogg",
  ".mp4", ".webm", ".mov",
  ".json", ".csv", ".xml", ".txt", ".md"
]

This property is an array of strings. If a file is imported and its path ends
with any of these extensions, Sheriff will:

  • Skip the file entirely (no parsing attempted)
  • Exclude it from all rule evaluation
  • Remove it from the dependency graph entirely

Internally, String.prototype.endsWith is used to match extensions.

We deliberately use a blacklist approach to ensure that extensions like
.tsx (which are TypeScript-supported) continue to work without extra config.

The list is enabled by default, even if no config is provided. Setting
ignoreFileExtensions manually gives full control and disables the default
list completely.

Regex or glob pattern matching is not supported.


Programmatic Configuration

Sheriff projects typically include a config file from the start. While the
default values are automatically applied, users can opt into full control by
defining ignoreFileExtensions directly, or extend the default list
programmatically using helper utilities.

To make this extension easier, Sheriff exports:

import {
  ignoreFileExtensions,
  defaultIgnoreFileExtensions
} from 'sheriff';

Use defaultIgnoreFileExtensions if you want to inspect or reuse the current
default list. Use ignoreFileExtensions() for ergonomic programmatic config.

Function Signatures

function ignoreFileExtensions(...extensions: string[]): {
  ignoreFileExtensions: string[];
}

function ignoreFileExtensions(
  cb: (defaults: string[]) => string[]
): { ignoreFileExtensions: string[] }

Example 1: Append to the default list

const config = {
  ...ignoreFileExtensions('.env', '.yaml')
};

Example 2: Transform or override the list

const config = {
  ...ignoreFileExtensions((defaults) =>
    defaults.filter(ext => ext !== '.json').concat('.mdx')
  )
};

Example 3: Full manual control (disables default)

const config = {
  ignoreFileExtensions: ['.custom']
};

Behavior Summary

  • ✅ TypeScript-supported files (e.g., .ts, .tsx, .vue) are parsed normally.
  • 🚫 Common asset files are excluded via a default list.
  • 🔧 Ignored files are not parsed or validated.
  • 📦 They are omitted entirely from the dependency graph.
  • 🧱 The default list is always active unless explicitly overridden.
  • 🧰 Utility functions help extend or override defaults in code.
  • ❌ Regex or glob patterns are not supported.

Future-Proofing Ideas

To allow greater flexibility and support advanced setups in the future, we will
not implement now, but could revisit those ideas later:

  • Named presets: e.g., "frontend", "node", "docs" to simplify config.
  • Project-level merging: combining global and per-project ignores in large
    workspaces.

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions