Skip to content

Commit

Permalink
Updated for HTMLWebpackPlugin >= 4.0.0
Browse files Browse the repository at this point in the history
Updated license from MIT to GPL-3.0
  • Loading branch information
BTOdell committed May 21, 2020
1 parent 18f7809 commit c3aa2e3
Show file tree
Hide file tree
Showing 7 changed files with 1,536 additions and 1,227 deletions.
9 changes: 0 additions & 9 deletions .npmignore

This file was deleted.

7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Changelog

## v2.0.0 (2020-05-21)

**Major release! Breaking changes!**

* Updated for HTMLWebpackPlugin >= 4.0.0
* Updated license from MIT to GPL-3.0

## v1.0.8 (2020-04-03)

Updated NPM dependencies to fix security vulnerabilities.
Expand Down
695 changes: 674 additions & 21 deletions LICENSE

Large diffs are not rendered by default.

122 changes: 48 additions & 74 deletions index.ts
Original file line number Diff line number Diff line change
@@ -1,53 +1,19 @@
import * as path from "path";
import { ParsedPath } from "path";
import { AsyncSeriesWaterfallHook } from "tapable";
import webpack = require("webpack");

// Added by the HtmlWebpackPlugin
declare module "webpack" {
namespace compilation {
interface CompilationHooks {
htmlWebpackPluginBeforeHtmlProcessing: AsyncSeriesWaterfallHook;
}
}
}

interface HTMLPluginDataAssetChunk {

size: number;
entry: string;
hash: string;
css: string[];

}

interface HTMLPluginDataAssets {

publicPath: string;
chunks: { [key: string]: HTMLPluginDataAssetChunk };
js: string[];
css: string[];

}

interface HTMLPluginData {

html: string;
assets: HTMLPluginDataAssets;
// plugin: HtmlWebpackPlugin;
outputName: string;
import * as webpack from "webpack";
import * as HtmlWebpackPlugin from "html-webpack-plugin";
import {HtmlTagObject} from "html-webpack-plugin";

function replaceJS(html: string, publicPath: string, assetTags: HtmlTagObject[], compilerOptions: webpack.Configuration): string {
return replace(html, publicPath, assetTags, "script", "src", compilerOptions, /(<script[\S\s]*?src=['"])(.+?)(['"][^>]*?>)/gi);
}

function replaceJS(html: string, jsFiles: string[], compilerOptions: webpack.Configuration): string {
return replace(html, jsFiles, compilerOptions, /(<script[\S\s]*?src=['"])(.+?)(['"][^>]*?>)/gi);
function replaceCSS(html: string, publicPath: string, assetTags: HtmlTagObject[], compilerOptions: webpack.Configuration): string {
return replace(html, publicPath, assetTags, "link", "href", compilerOptions, /(<link[\S\s]*?href=['"])(.+?)(['"][^>]*?>)/gi);
}

function replaceCSS(html: string, cssFiles: string[], compilerOptions: webpack.Configuration): string {
return replace(html, cssFiles, compilerOptions, /(<link[\S\s]*?href=['"])(.+?)(['"][^>]*?>)/gi);
}

function replace(html: string, files: string[], compilerOptions: webpack.Configuration, regex: RegExp): string {
function replace(html: string, publicPath: string, assetTags: HtmlTagObject[], filterAssetTagName: string, filterAssetTagAttribute: string,
compilerOptions: webpack.Configuration, regex: RegExp): string {
const basePath: string = getBasePath(compilerOptions);
let output: string = "";
let lastIndex: number = 0;
Expand All @@ -61,20 +27,34 @@ function replace(html: string, files: string[], compilerOptions: webpack.Configu
output += scriptPrefix;

// Resolve script source path
const resolvedScriptSource: string = path.resolve(basePath, scriptSource);
const resolvedScriptSource: string = path.join(basePath, scriptSource);
const scriptSourceName: string = getPathName(resolvedScriptSource);

// Determine if source should be replaced
let replaceFile: string|undefined;
for (let i = files.length - 1; i >= 0; i--) {
const file: string = files[i];
const resolvedFile: string = path.resolve(basePath, file);
const fileName: string = getPathName(resolvedFile);
if (scriptSourceName === fileName) {
for (let i = assetTags.length - 1; i >= 0; i--) {
const assetTag: HtmlTagObject = assetTags[i];
if (assetTag.tagName !== filterAssetTagName) {
continue;
}
if (!(filterAssetTagAttribute in assetTag.attributes)) {
continue;
}
const assetPath: string | boolean = assetTag.attributes[filterAssetTagAttribute];
if (typeof assetPath !== "string") {
continue;
}
let assetFileName: string;
if (publicPath && assetPath.startsWith(publicPath)) {
assetFileName = assetPath.slice(publicPath.length);
} else {
assetFileName = assetPath;
}
if (scriptSourceName === getPathName(path.join(basePath, assetFileName))) {
// Replace!
replaceFile = path.relative(basePath, resolvedFile);
replaceFile = assetPath;
// Remove file from files array
files.splice(i, 1);
assetTags.splice(i, 1);
}
}
if (replaceFile != null) {
Expand Down Expand Up @@ -118,40 +98,34 @@ const pluginName = "ReplaceUrlHtmlWebpackPlugin";
/**
*
*/
class ReplaceUrlHtmlWebpackPlugin {
export class ReplaceUrlHtmlWebpackPlugin {

/**
* @override
*/
public apply(compiler: webpack.Compiler): void {
const compilerOptions: webpack.Configuration = compiler.options;
compiler.hooks.compilation.tap(pluginName, (compilation: webpack.compilation.Compilation) => {
compilation.hooks.htmlWebpackPluginBeforeHtmlProcessing.tap(pluginName, (data: HTMLPluginData) => {
// Replace asset elements in HTML
const assets: HTMLPluginDataAssets = data.assets;
const jsFiles: string[] = assets.js;
const cssFiles: string[] = assets.css;
let html: string = data.html;
html = replaceJS(html, jsFiles, compilerOptions);
html = replaceCSS(html, cssFiles, compilerOptions);
// Remove chunks that were removed
const chunks = assets.chunks;
for (const chunkName in chunks) {
if (chunks.hasOwnProperty(chunkName)) {
const chunk: HTMLPluginDataAssetChunk = chunks[chunkName];
if (jsFiles.indexOf(chunk.entry) < 0) {
delete chunks[chunkName];
}
let publicPath: string | undefined;
HtmlWebpackPlugin.getHooks(compilation).beforeAssetTagGeneration.tapAsync(pluginName, (data, cb) => {
publicPath = data.assets.publicPath;
cb(null, data);
});
HtmlWebpackPlugin.getHooks(compilation).afterTemplateExecution.tapAsync(pluginName, (data, cb) => {
if (publicPath != null) {
// Process both head and body tags
for (const assetTags of [data.headTags, data.bodyTags]) {
// Replace asset tags in HTML
let html: string = data.html;
html = replaceJS(html, publicPath, assetTags, compilerOptions);
html = replaceCSS(html, publicPath, assetTags, compilerOptions);
// Assign HTML back to data object
data.html = html;
}
}
// Assign HTML back to data object
data.html = html;
// Return data object
return data;
cb(null, data);
});
});
}

}

export = ReplaceUrlHtmlWebpackPlugin;
Loading

0 comments on commit c3aa2e3

Please sign in to comment.