UNPKG

content-injector-webpack-plugin

Version:

A flexible Webpack plugin for injecting dynamic content (e.g., version, timestamps) into build assets with precise file matching and position control.

80 lines (79 loc) 3.05 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const webpack_1 = require("webpack"); const crypto_1 = require("crypto"); class ContentInjectorWebpackPlugin { constructor(options) { this.options = { match: /\.js$/, position: 'head', injectHash: false, hashAlgorithm: 'md5', hashLength: 8, ...options, }; } apply(compiler) { compiler.hooks.emit.tapAsync('ContentInjectorWebpackPlugin', (compilation, callback) => { Object.keys(compilation.assets).forEach((filename) => { if (this.shouldProcessFile(filename) && this.validateFilename(filename)) { const asset = compilation.assets[filename]; const originalSource = asset.source().toString(); const fileHash = this.options.injectHash ? this.getFileHash(originalSource) : ''; let bannerContent; if (typeof this.options.content === 'function') { bannerContent = this.options.injectHash ? this.options.content(fileHash) : this.options.content(); } else { bannerContent = this.options.content; } const newSource = this.options.position === 'head' ? new webpack_1.sources.ConcatSource(bannerContent, originalSource) : new webpack_1.sources.ConcatSource(originalSource, bannerContent); compilation.assets[filename] = newSource; } }); callback(); }); } getFileHash(content) { const hash = (0, crypto_1.createHash)(this.options.hashAlgorithm) .update(content) .digest('hex'); return this.options.hashLength ? hash.substring(0, this.options.hashLength) : ''; } validateFilename(filename) { const { include, exclude } = this.options; if (exclude && this.matchCondition(filename, exclude)) { return false; } if (include) { return this.matchCondition(filename, include); } return this.matchCondition(filename, this.options.match); } matchCondition(filename, condition) { if (typeof condition === 'function') { return condition(filename); } if (typeof condition === 'string') { return filename.includes(condition); } if (condition instanceof RegExp) { return condition.test(filename); } return false; } shouldProcessFile(filename) { const isTextAsset = /\.(js|css|txt|html?|xml|json|svg)$/i.test(filename); return isTextAsset && !/\.map$/.test(filename); } } module.exports = ContentInjectorWebpackPlugin;