npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@zilero/gulp-conditional

v2.1.0

Published

Route each file of a gulp stream through a different plugin chain depending on a condition, like an if / else if / else for streams.

Readme

@zilero/gulp-conditional

Route each file of a gulp stream through a different plugin chain depending on a condition, like an if / else if / else for streams.

npm install size node license docs

Each file goes to the first branch whose condition holds for it; files no condition matches go to a default branch or pass through untouched. A branch is any plugin, or a chain of plugins. Replaces gulp-if (and ternary-stream).

  • As many branches as you need, checked in order: if / else if / else, not only if / else.
  • Conditions are booleans, globs, RegExps, arrays of them, or functions of the file (sync or async).
  • A branch can be a chain (() => [scssCompiler(), cssSqueezer()]), with errors from every link reported.
  • Branches are created on their first file and ended with the stream, so concat-like plugins in a branch work.
  • No branch outlives the stream: when it ends, fails or is destroyed, every branch is destroyed too.

Install

npm install --save-dev @zilero/gulp-conditional
# pnpm add -D @zilero/gulp-conditional · bun add -d @zilero/gulp-conditional

gulp is not a dependency: the plugin works with the gulp your project already has.

Usage

// gulpfile.ts
import { conditional } from '@zilero/gulp-conditional';
import { cssSqueezer } from '@zilero/gulp-css-squeezer';
import { jsSqueezer } from '@zilero/gulp-js-squeezer';
import { scssCompiler } from '@zilero/gulp-scss-compiler';
import { dest, src } from 'gulp';
import { pipeline } from 'node:stream/promises';

export const build = (): Promise<void> =>
  pipeline(
    src('src/**', { sourcemaps: true }),
    conditional({
      handlers: [
        { condition: '*.js', handler: () => jsSqueezer() },
        { condition: '*.scss', handler: () => [scssCompiler(), cssSqueezer()] }
      ]
    }),
    dest('dist', { sourcemaps: '.' })
  );

In CommonJS: const { conditional } = require('@zilero/gulp-conditional'). The default export is the same function.

Options

| Option | Type | Default | Description | | ---------------- | --------------------------------------------------------------- | ------- | -------------------------------------------------------------------------------------------------------------- | | handlers | { condition: Condition, handler: () => Duplex \| Duplex[] }[] | — | Required, at least one. Checked in order for every file; the first branch whose condition holds gets the file. | | defaultHandler | () => Duplex \| Duplex[] | — | Creates the branch for the files no condition matched. Without it they pass through untouched. |

A Condition is one of:

| Form | The file goes to the branch when | | ------------------------------------------- | -------------------------------------------------------------------------------------------- | | boolean | it is true (every file) — false sends none. | | string (a glob) | it matches file.relative. A glob without a slash matches the name in any folder: '*.js'. | | RegExp | it matches file.relative, with / separators. | | (string \| RegExp)[] | any of them matches. | | ({ file }) => boolean \| Promise<boolean> | it returns true. |

A handler returns a plugin stream, or a non-empty array of them that the files go through in order. Return an array, not a().pipe(b()): .pipe() returns b, so the files would skip a.

Options are validated when the plugin is created: unknown keys, an empty handlers array (Add at least one handler) and a condition of another type are errors.

Conditions and handlers

  • Conditions are checked for every file, in the order of handlers; later conditions are not called once one holds. Globs and RegExps are compiled once, when the plugin is created; dotfiles match.
  • Each handler is called once, for the first file that goes to its branch. A branch that gets no files is never created.
  • The stream ends after every branch has finished, so a branch that emits files when it ends (a concat, an archive) works.
  • Branches run side by side: files from different branches can come out in a different order than they went in.
  • A slow branch slows the stream down: files wait until the branch can take more. A branch's output is pushed on at once, without waiting for a slow downstream.

Source maps

Maps travel with the files: a branch plugin that updates file.sourceMap does so as it would outside conditional.

Files and errors

  • Every file goes through the conditions, including files without contents and directories.
  • A condition that throws fails the stream with a PluginError from @zilero/gulp-conditional.
  • A handler that returns something other than a stream fails with handlers[0].handler must return a stream or an array of streams, got undefined (or defaultHandler …); an empty array with … returned an empty array; return at least one stream.
  • An error from a branch is reported on the next file written to the stream, or when it ends. A PluginError keeps the name of the plugin that threw it; any other error is wrapped in a PluginError from this plugin.

Recipes

Minify only in production:

conditional({ handlers: [{ condition: process.env.NODE_ENV === 'production', handler: () => jsSqueezer() }] });

Images one way, everything else another:

conditional({
  handlers: [{ condition: /\.(png|jpe?g|webp)$/i, handler: () => imageSqueezer() }],
  defaultHandler: () => textReplace({ rules: { search: '__VERSION__', replace: version } })
});

Decide with an async function of the file:

import { stat } from 'node:fs/promises';

conditional({
  handlers: [{ condition: async ({ file }) => (await stat(file.path)).size > 50_000, handler: () => jsSqueezer() }]
});

Migrating from gulp-if

| gulp-if | conditional | | ------------------------------------- | ------------------------------------------------------------------------- | | gulpIf(condition, uglify()) | conditional({ handlers: [{ condition, handler: () => jsSqueezer() }] }) | | gulpIf(condition, a(), b()) (else) | handlers: [{ condition, handler: a }], defaultHandler: b | | nested gulpIf for else-if | more entries in handlers, checked in order | | a lazy pipe of plugins for a chain | return an array: handler: () => [a(), b()] | | a glob string, a function of the file | the same; globs match file.relative, RegExps and arrays work too |

The stream is created by a function (handler: () => plugin()), not passed in, so it exists only when a file needs it.

From 1.x

  • Conditions are checked for every file; in 1.x a condition was evaluated once, for the whole stream.
  • A condition can be a function of the file (sync or async), a glob, a RegExp or an array of them, as well as a boolean.
  • A handler may return an array of streams to chain.
  • Branches are created only when a file goes to them, and files that match nothing pass through when there is no defaultHandler.

Requirements

  • Node.js 22.13+
  • gulp 5 (gulp 4 works too)
  • ESM with TypeScript types; require() works through Node's require(esm)
  • No engine: Node streams, globs through picomatch (via @zilero/gulp-plugin-factory)

Documentation · Changelog · All plugins · Issues

MIT © Artemev Alexandr