Skip to content

Latest commit

 

History

History
107 lines (81 loc) · 2.97 KB

compilers.md

File metadata and controls

107 lines (81 loc) · 2.97 KB

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, .vue and .svelte may also import dependencies and other files. So ideally, these files are included in the analysis to get a better overview of what files and dependencies are used or not. To this end, Knip v2 supports a compiler for any file extension.

Prerequisites

The Knip config needs to be in a .js or .ts file (not .json), since compilers are functions.

Interface

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

(source: string) => string;

This may also be an async function.

Examples

MDX

Here's an example using @mdx-js/mdx v1.6.22

const compile = require('@mdx-js/mdx');

module.exports = {
  entry: ['src/index.ts', '**/*.stories.mdx'],
  project: 'src/*.{ts,mdx}',
  compilers: {
    mdx: compile,
  },
};

Vue

Here's a fully configured knip.ts with a "compiler" for .vue files in Vue projects:

const compiler = /<script\b[^>]*>([\s\S]*?)<\/script>/gm;

export default {
  ignore: '*.d.ts',
  entry: ['src/main.ts', 'vite.config.ts'],
  project: '**/*.{ts,vue}',
  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 only the import statements.

Svelte

Here's another example, this one is for Svelte:

import sveltePreprocess from 'svelte-preprocess';
import { preprocess, compile } from 'svelte/compiler';

const sveltePreprocessor = sveltePreprocess();

export default {
  ignore: ['**/*.d.ts'],
  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 little bit of configuration. It's enabled automatically, so there's nothing to configure.

Just for reference, this also seems to work pretty well (but may err on certain syntax or edge cases):

export default {
  svelte: (text: string) => [...text.matchAll(/import[^;]+/g)].join('\n'),
  css: (text: string) => [...text.matchAll(/(?<=@)import[^;]+/g)].join('\n'),
};