const fs = require('fs');
const path = require('path');
const escapeStringRegExp = require('escape-string-regexp');

// We need html-webpack-plugin to work, so do a check
try {
    require('html-webpack-plugin');
}
catch (err) {
    throw new Error(`This plugin requires 'html-webpack-plugin' to work. Please install it using: npm i -D html-webpack-plugin`);
}

// We need webpack-manifest-plugin to work, so do a check
try {
    require('webpack-manifest-plugin');
}
catch (err) {
    throw new Error(`This plugin requires 'webpack-manifest-plugin' to work. Please install it using: npm i -D webpack-manifest-plugin`);
}

class HtmlInjectManifestPlugin {
    constructor(options) {
        options = options || {};
        options.files = options.files || [];
        
        this.options = options;
    }
    
    apply(compiler) {
        compiler.hooks.compilation.tap(this.constructor.name, (compilation) => {
            compilation.hooks.htmlWebpackPluginAfterEmit.tap(this.constructor.name, (htmlPluginData) => {
                const emittedHtmlFilePath = path.join(compiler.outputPath, htmlPluginData.outputName);
                
                compiler.hooks.webpackManifestPluginAfterEmit.tap(this.constructor.name, (manifest) => {
                    const mergedManifest = this.mergeManifest(manifest);
                    
                    compiler.hooks.afterEmit.tap(this.constructor.name, () => {
                        this.processHtmlFile(emittedHtmlFilePath, mergedManifest);
                    });
                });
            });
        });
        
        compiler.hooks.emit.tap('HtmlInjectManifestPlugin', (compilation) => {
            for (let file of this.options.files) {
                compilation.fileDependencies.add(file);
            }
        });
    }
    
    mergeManifest(manifest) {
        let mergedManifest = {};
        
        // If files were provided, watch em
        if (this.options.files.length) {
            const manifests = this.options.files
                .map(file => JSON.parse(fs.readFileSync(file)));
            
            mergedManifest = Object.assign(mergedManifest, ...manifests);
        }
        
        return Object.assign(mergedManifest, manifest);
    }
    
    processHtmlFile(filePath, manifest) {
        if (!fs.existsSync(filePath))
            return;
        
        let processedHtml = fs.readFileSync(filePath, 'utf8');
        
        for (let key of Object.keys(manifest)) {
            const replace = escapeStringRegExp(`[${key}]`);
            const replaceWith = manifest[key];
            
            processedHtml = processedHtml.replace(new RegExp(replace, 'g'), replaceWith);
        }
        
        fs.writeFileSync(filePath, processedHtml);
    }
}

module.exports = HtmlInjectManifestPlugin;
@@ -23,38 +23,8 @@
 ');%0A
-const path = require('path');%0A
 cons
@@ -922,33 +922,44 @@
 ebpackPlugin
-AfterEmit
+BeforeHtmlProcessing
 .tap(this.co
@@ -1022,60 +1022,25 @@
 nst 
-emittedHtmlFilePath = path.join(compiler.outputPath,
+unprocessedHtml =
  htm
@@ -1055,19 +1055,12 @@
 ata.
-outputName)
+html
 ;%0A  
@@ -1248,32 +1248,33 @@
 (manifest);%0A    
+%0A
                 
@@ -1277,194 +1277,470 @@
     
-%0A                    compiler.hooks.afterEmit.tap(this.constructor.name, () =%3E %7B%0A                        this.processHtmlFile(emittedHtmlFilePath, mergedManifest);%0A                    %7D)
+    const processedHtml = this.processHtmlFile(unprocessedHtml, mergedManifest);%0A    %0A                    // Emit the file%0A                    compilation.assets%5B%60index.html%60%5D = %7B%0A                        source() %7B%0A                            return Buffer.from(processedHtml);%0A                        %7D,%0A                        size() %7B%0A                            return Buffer.byteLength(this.source(), 'utf8');%0A                        %7D%0A                    %7D
 ;%0A  
@@ -2283,16 +2283,25 @@
 ync(file
+, 'utf-8'
 )));%0A   
@@ -2490,24 +2490,31 @@
 tmlFile(
-filePath
+unprocessedHtml
 , manife
@@ -2531,128 +2531,43 @@
     
-if (!fs.existsSync(filePath))%0A            return;%0A        %0A        let processedHtml = fs.readFileSync(filePath, 'utf8')
+let processedHtml = unprocessedHtml
 ;%0A  
@@ -2863,34 +2863,14 @@
     
-fs.writeFileSync(filePath,
+return
  pro
@@ -2875,25 +2875,24 @@
 rocessedHtml
-)
 ;%0A    %7D%0A%7D%0A%0Am

fix manifest files.