A set of utility functions commonly used by Rollup plugins
—
Pattern matching utilities for creating precise RegExp patterns, commonly used in plugin hook filters and string matching operations. These functions automatically escape special characters and provide consistent anchoring behavior.
Creates a RegExp that matches strings exactly by anchoring at both the beginning and end of the string.
/**
* Constructs a RegExp that matches the exact string specified
* Automatically escapes special regex characters and anchors with ^ and $
* @param str - The string(s) to match exactly
* @param flags - Optional RegExp flags (e.g., 'i', 'g', 'm')
* @returns RegExp with exact matching (^pattern$)
*/
function exactRegex(str: string | string[], flags?: string): RegExp;Parameters:
str (string | string[]): The string or array of strings to match exactly. Special regex characters are automatically escaped.flags (string, optional): Standard RegExp flags like 'i' (case-insensitive), 'g' (global), 'm' (multiline)Returns: RegExp with ^ and $ anchors for exact matching
Usage Examples:
import { exactRegex } from "@rollup/pluginutils";
// Basic exact matching
exactRegex('foobar'); // /^foobar$/
exactRegex('hello world'); // /^hello world$/
// Multiple alternatives
exactRegex(['foo', 'bar']); // /^(?:foo|bar)$/
exactRegex(['index.js', 'main.js']); // /^(?:index\.js|main\.js)$/
// With flags
exactRegex('FooBar', 'i'); // /^FooBar$/i (case-insensitive)
// Automatic escaping of special characters
exactRegex('foo(bar)'); // /^foo\(bar\)$/
exactRegex('app.config.js'); // /^app\.config\.js$/
exactRegex('$special^chars'); // /^\$special\^chars$/
// Use in plugin hooks
export default function myPlugin() {
const entryPattern = exactRegex(['index.js', 'main.js', 'app.js']);
return {
buildStart() {
// Filter entry files
const entries = this.getModuleIds().filter(id =>
entryPattern.test(id.split('/').pop())
);
console.log('Entry files:', entries);
}
};
}
// Virtual module matching
export default function virtualPlugin() {
const virtualPattern = exactRegex(['virtual:config', 'virtual:env']);
return {
resolveId(id) {
if (virtualPattern.test(id)) {
return id;
}
}
};
}Creates a RegExp that matches strings with a specific prefix by anchoring only at the beginning of the string.
/**
* Constructs a RegExp that matches a value that has the specified prefix
* Automatically escapes special regex characters and anchors with ^
* @param str - The string(s) to match as prefix
* @param flags - Optional RegExp flags (e.g., 'i', 'g', 'm')
* @returns RegExp with prefix matching (^pattern)
*/
function prefixRegex(str: string | string[], flags?: string): RegExp;Parameters:
str (string | string[]): The string or array of strings to match as prefixflags (string, optional): Standard RegExp flagsReturns: RegExp with ^ anchor for prefix matching
Usage Examples:
import { prefixRegex } from "@rollup/pluginutils";
// Basic prefix matching
prefixRegex('foo'); // /^foo/
prefixRegex('src/'); // /^src\//
// Multiple prefixes
prefixRegex(['src/', 'lib/']); // /^(?:src\/|lib\/)/
prefixRegex(['@scope/', 'my-']); // /^(?:@scope\/|my-)/
// With flags
prefixRegex('HTTP', 'i'); // /^HTTP/i
// Automatic escaping
prefixRegex('src/components/'); // /^src\/components\//
prefixRegex('@rollup/'); // /^@rollup\//
// Use for module filtering
export default function myPlugin() {
const srcPattern = prefixRegex(['src/', 'lib/', 'components/']);
return {
transform(code, id) {
// Only transform files in source directories
if (srcPattern.test(id)) {
return { code: transformCode(code) };
}
}
};
}
// Package scope filtering
export default function scopePlugin(options = {}) {
const { allowedScopes = ['@mycompany/', '@utils/'] } = options;
const scopePattern = prefixRegex(allowedScopes);
return {
resolveId(id) {
if (scopePattern.test(id)) {
// Allow imports from specified scopes
return null; // Continue with normal resolution
} else {
// Block other scoped packages
return false;
}
}
};
}
// Environment-based file matching
const devPattern = prefixRegex(['dev/', 'development/']);
const prodPattern = prefixRegex(['prod/', 'production/']);
export default function envPlugin(options = {}) {
const { environment = 'production' } = options;
const pattern = environment === 'development' ? devPattern : prodPattern;
return {
load(id) {
if (pattern.test(id)) {
// Load environment-specific files
return fs.readFileSync(id, 'utf-8');
}
}
};
}Creates a RegExp that matches strings with a specific suffix by anchoring only at the end of the string.
/**
* Constructs a RegExp that matches a value that has the specified suffix
* Automatically escapes special regex characters and anchors with $
* @param str - The string(s) to match as suffix
* @param flags - Optional RegExp flags (e.g., 'i', 'g', 'm')
* @returns RegExp with suffix matching (pattern$)
*/
function suffixRegex(str: string | string[], flags?: string): RegExp;Parameters:
str (string | string[]): The string or array of strings to match as suffixflags (string, optional): Standard RegExp flagsReturns: RegExp with $ anchor for suffix matching
Usage Examples:
import { suffixRegex } from "@rollup/pluginutils";
// Basic suffix matching
suffixRegex('.js'); // /\.js$/
suffixRegex('.test.js'); // /\.test\.js$/
// Multiple suffixes
suffixRegex(['.js', '.ts']); // /(?:\.js|\.ts)$/
suffixRegex(['.worker.js', '.worker.ts']); // /(?:\.worker\.js|\.worker\.ts)$/
// With flags
suffixRegex('.JS', 'i'); // /\.JS$/i
// Automatic escaping
suffixRegex('.d.ts'); // /\.d\.ts$/
suffixRegex('.(test|spec).js'); // /\.\(test\|spec\)\.js$/
// File extension filtering
export default function myPlugin() {
const jsPattern = suffixRegex(['.js', '.jsx', '.ts', '.tsx']);
const testPattern = suffixRegex(['.test.js', '.spec.js', '.test.ts', '.spec.ts']);
return {
transform(code, id) {
// Only transform JavaScript files
if (jsPattern.test(id) && !testPattern.test(id)) {
return { code: transformCode(code) };
}
}
};
}
// Worker file detection
export default function workerPlugin() {
const workerPattern = suffixRegex(['.worker.js', '.worker.ts']);
return {
load(id) {
if (workerPattern.test(id)) {
// Special handling for worker files
return `
const workerCode = ${JSON.stringify(fs.readFileSync(id, 'utf-8'))};
export default () => new Worker(URL.createObjectURL(
new Blob([workerCode], { type: 'application/javascript' })
));
`;
}
}
};
}
// Asset file handling
export default function assetPlugin() {
const imagePattern = suffixRegex(['.png', '.jpg', '.jpeg', '.gif', '.svg']);
const fontPattern = suffixRegex(['.woff', '.woff2', '.ttf', '.eot']);
return {
load(id) {
if (imagePattern.test(id)) {
// Emit image as asset
const referenceId = this.emitFile({
type: 'asset',
name: path.basename(id),
source: fs.readFileSync(id)
});
return `export default import.meta.ROLLUP_FILE_URL_${referenceId};`;
}
if (fontPattern.test(id)) {
// Handle font files
return handleFontFile(id);
}
}
};
}import { exactRegex, prefixRegex, suffixRegex } from "@rollup/pluginutils";
export default function comprehensivePlugin(options = {}) {
const {
entryFiles = ['index.js', 'main.js'],
sourceDirectories = ['src/', 'lib/'],
fileExtensions = ['.js', '.ts', '.jsx', '.tsx'],
excludePatterns = ['.test.', '.spec.', '.stories.']
} = options;
// Create patterns
const entryPattern = exactRegex(entryFiles);
const sourcePattern = prefixRegex(sourceDirectories);
const extensionPattern = suffixRegex(fileExtensions);
const excludePattern = new RegExp(excludePatterns.map(p =>
p.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
).join('|'));
return {
buildStart() {
console.log('Entry pattern:', entryPattern);
console.log('Source pattern:', sourcePattern);
console.log('Extension pattern:', extensionPattern);
},
transform(code, id) {
const fileName = path.basename(id);
const isEntry = entryPattern.test(fileName);
const isSource = sourcePattern.test(id);
const hasValidExtension = extensionPattern.test(id);
const isExcluded = excludePattern.test(id);
if (hasValidExtension && (isEntry || isSource) && !isExcluded) {
return { code: transformCode(code, { isEntry }) };
}
}
};
}import { exactRegex, prefixRegex } from "@rollup/pluginutils";
export default function virtualModulePlugin() {
const exactVirtualPattern = exactRegex([
'virtual:config',
'virtual:env',
'virtual:version'
]);
const prefixVirtualPattern = prefixRegex(['virtual:generated-']);
return {
resolveId(id) {
if (exactVirtualPattern.test(id) || prefixVirtualPattern.test(id)) {
return id;
}
},
load(id) {
// Handle exact virtual modules
if (exactVirtualPattern.test(id)) {
switch (id) {
case 'virtual:config':
return 'export default { apiUrl: "https://api.example.com" };';
case 'virtual:env':
return `export const NODE_ENV = "${process.env.NODE_ENV}";`;
case 'virtual:version':
return `export const version = "${packageJson.version}";`;
}
}
// Handle prefixed virtual modules
if (prefixVirtualPattern.test(id)) {
const type = id.replace('virtual:generated-', '');
return generateVirtualModule(type);
}
}
};
}import { suffixRegex } from "@rollup/pluginutils";
export default function fileTypePlugin() {
const patterns = {
scripts: suffixRegex(['.js', '.ts', '.jsx', '.tsx']),
styles: suffixRegex(['.css', '.scss', '.sass', '.less']),
images: suffixRegex(['.png', '.jpg', '.jpeg', '.gif', '.svg']),
fonts: suffixRegex(['.woff', '.woff2', '.ttf', '.eot']),
data: suffixRegex(['.json', '.yaml', '.yml', '.xml'])
};
return {
load(id) {
if (patterns.scripts.test(id)) {
return handleScriptFile(id);
}
if (patterns.styles.test(id)) {
return handleStyleFile(id);
}
if (patterns.images.test(id)) {
return handleImageFile(id);
}
if (patterns.fonts.test(id)) {
return handleFontFile(id);
}
if (patterns.data.test(id)) {
return handleDataFile(id);
}
}
};
}Install with Tessl CLI
npx tessl i tessl/npm-rollup--pluginutils