Skip to content

321638914/unplugin-preprocessor-directives

 
 

Repository files navigation

logo

unplugin-preprocessor-directives

npm version npm downloads bundle License JSDocs

English | 简体中文

Install

npm i unplugin-preprocessor-directives
Vite
// vite.config.ts
import PreprocessorDirectives from 'unplugin-preprocessor-directives/vite'

export default defineConfig({
  plugins: [
    PreprocessorDirectives({ /* options */ }),
  ],
})

Example: playground/


Rollup
// rollup.config.js
import PreprocessorDirectives from 'unplugin-preprocessor-directives/rollup'

export default {
  plugins: [
    PreprocessorDirectives({ /* options */ }),
  ],
}


Webpack
// webpack.config.js
module.exports = {
  /* ... */
  plugins: [
    require('unplugin-preprocessor-directives/webpack')({ /* options */ })
  ]
}


Nuxt
// nuxt.config.js
export default defineNuxtConfig({
  modules: [
    ['unplugin-preprocessor-directives/nuxt', { /* options */ }],
  ],
})

This module works for both Nuxt 2 and Nuxt Vite


Vue CLI
// vue.config.js
module.exports = {
  configureWebpack: {
    plugins: [
      require('unplugin-preprocessor-directives/webpack')({ /* options */ }),
    ],
  },
}


esbuild
// esbuild.config.js
import { build } from 'esbuild'
import PreprocessorDirectives from 'unplugin-preprocessor-directives/esbuild'

build({
  plugins: [PreprocessorDirectives()],
})


Rspack (⚠️ experimental)
// rspack.config.js
module.exports = {
  plugins: [
    require('unplugin-preprocessor-directives/rspack')({ /* options */ }),
  ],
}


Usage

Defining symbols

You use the following two preprocessor directives to define or undefine symbols for conditional compilation:

  • #define: Define a symbol.
  • #undef: Undefine a symbol.

You use #define to define a symbol. When you use the symbol as the expression that's passed to the #if directive, the expression will evaluate to true, as the following example shows:

// #define VERBOSE

// #if VERBOSE
console.log('Verbose output version')
// #endif

Warning

#define and #undef are Hoisting, like var in JavaScript.

Conditional compilation

  • #if: Opens a conditional compilation, where code is compiled only if the specified symbol is defined and evaluated to true.
  • #elif: Closes the preceding conditional compilation and opens a new conditional compilation based on if the specified symbol is defined and evaluated to true.
  • #else: Closes the preceding conditional compilation and opens a new conditional compilation if the previous specified symbol isn't defined or evaluated to false.
  • #endif: Closes the preceding conditional compilation.

Note

By default, use vite's loadEnv function to load environment variables based on process.env.NODE_ENV and compile symbols as conditions.

// src/index.ts

// #if DEV
console.log('Debug version')
// #endif

// #if !MYTEST
console.log('MYTEST is not defined or false')
// #endif

You can use the operators == (equality) and != (inequality) to test for the bool values true or false. true means the symbol is defined. The statement #if DEBUG has the same meaning as #if (DEBUG == true). You can use the && (and), || (or), and ! (not) operators to evaluate whether multiple symbols have been defined. You can also group symbols and operators with parentheses.

class MyClass {
  constructor() {
    // #if (DEBUG && MYTEST)
    console.log('DEBUG and MYTEST are defined')
    // #elif (DEBUG==false && !MYTEST)
    console.log('DEBUG and MYTEST are not defined')
    // #endif
  }
}

Error and warning and info messages

You instruct the compiler to generate user-defined compiler errors and warnings and informational messages.

  • #error: Generates an error.
  • #warning: Generates a warning.
  • #info: Generates an informational message.
// #error this is an error message
// #warning this is a warning message
// #info this is an info message

Custom directive

You can used defineDirective to define your own directive.

Taking the built-in directive as an example:

/** @see https://xregexp.com/ */
import type { NamedGroupsArray } from 'xregexp'
import { defineDirective } from '../directive'

export default defineDirective<undefined>(() => ({
  nested: false,
  name: '#define',
  pattern: /.*?#(?<directive>(?:un)?def(?:ine)?)\s*(?<key>[\w]*)\s/gm,
  processor({ ctx }) {
    return (...args) => {
      const group = args[args.length - 1] as NamedGroupsArray
      if (group.directive === 'define')
        // @ts-expect-error ignore
        ctx.env[group.key] = true

      else if (group.directive === 'undef')
        delete ctx.env[group.key]

      return ''
    }
  },
}))

name: string

directive name, used to identify the directive in warning and error messages

enforce: 'pre' | 'post'

Execution priority of directives

  • pre: Execute as early as possible
  • post: Execute as late as possible

nested: boolean

Is it a nested instruction, The default is false. If it is true, matchRecursive will be used internally for replace and recursive calls. Otherwise, replace will be used`

pattern

The regular expression of the directive, if it is a nested instruction, needs to specify the start and end regular expressions

processor

The processing function of the directive.

About

preprocessor directives for jsx,tsx,js,ts,html,css,vue and more

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • TypeScript 97.7%
  • HTML 2.3%