Skip to content

Compilers

Projects may have source files that are not JavaScript or TypeScript, and thus require compilation (or transpilation, or pre-processing, you name it). Files like .mdx, .astro, .vue and .svelte may also import other sources files and external dependencies. So ideally, these files are also included when linting the project. That’s why Knip supports compilers.

Prerequisites

Since compilers are functions, the Knip config must to be in a dynamic .js or .ts file.

Interface

The compiler function interface is straightforward. Text in, text out:

(source: string) => string;

This may also be an async function.

Examples

Astro

Use a configuration like this to compile non-standard files in Astro projects:

import compile from '@mdx-js/mdx'; // Use v1
export default {
compilers: {
astro: (text: string) => [...text.matchAll(/import[^;]+/g)].join('\n'),
css: (text: string) => [...text.matchAll(/(?<=@)import[^;]+/g)].join('\n'),
mdx: (text: string) => compile(text),
},
};

Depending on your project you may not need the css and/or mdx “compilers”.

Knip has an Astro plugin to save you some configuration. It’s enabled automatically.

MDX

Here’s an example using an actual compiler (@mdx-js/mdx):

knip.ts
import compile from '@mdx-js/mdx'; // Use v1
module.exports = {
entry: ['src/index.ts', '**/*.stories.mdx'],
compilers: {
mdx: (text: string) => compile(text),
},
};

Vue

Here’s an example “compiler” for .vue files in Vue projects:

knip.ts
const compiler = /<script\b[^>]*>([\s\S]*?)<\/script>/gm;
export default {
compilers: {
vue: text => {
const scripts = [];
let match;
while ((match = compiler.exec(text))) scripts.push(match[1]);
return scripts.join(';');
},
},
};

This is tested on a project generated using npm init vue@latest. Note that this is not a real compiler, but in many cases it’s enough to extract and return the contents of the <script> elements as a TypeScript module.

Knip does not have a Vue plugin, mainly because the entry file src/main.ts is already covered by the default entry patterns. You may need to add e.g. src/App.vue as an entry file.

Svelte

Use a configuration like this to compile non-standard files in Svelte projects:

knip.ts
import sveltePreprocess from 'svelte-preprocess';
import { preprocess, compile } from 'svelte/compiler';
const sveltePreprocessor = sveltePreprocess();
export default {
paths: {
// This ain't pretty, but Svelte basically does the same
'$app/*': ['node_modules/@sveltejs/kit/src/runtime/app/*'],
'$env/*': ['.svelte-kit/ambient.d.ts'],
},
compilers: {
svelte: async (text: string) => {
const processed = await preprocess(text, sveltePreprocessor, {
filename: 'dummy.ts',
});
const compiled = compile(processed.code);
return compiled.js.code;
},
css: (text: string) => [...text.matchAll(/(?<=@)import[^;]+/g)].join('\n'),
},
};

The compiler for .svelte files in this example is the actual Svelte compiler, this is the recommended way whenever available. Knip has a Svelte plugin to save you some configuration. It’s enabled automatically.

ISC License © 2024 Lars Kappert