first commit

This commit is contained in:
monjack
2025-06-20 18:01:48 +08:00
commit 6daa6d65c1
24611 changed files with 2512443 additions and 0 deletions

View File

@ -0,0 +1,482 @@
// @ts-check
/**
* @file
* Helper plugin manages the cached state of the child compilation
*
* To optimize performance the child compilation is running asynchronously.
* Therefore it needs to be started in the compiler.make phase and ends after
* the compilation.afterCompile phase.
*
* To prevent bugs from blocked hooks there is no promise or event based api
* for this plugin.
*
* Example usage:
*
* ```js
const childCompilerPlugin = new PersistentChildCompilerPlugin();
childCompilerPlugin.addEntry('./src/index.js');
compiler.hooks.afterCompile.tapAsync('MyPlugin', (compilation, callback) => {
console.log(childCompilerPlugin.getCompilationResult()['./src/index.js']));
return true;
});
* ```
*/
"use strict";
// Import types
/** @typedef {import("webpack").Compiler} Compiler */
/** @typedef {import("webpack").Compilation} Compilation */
/** @typedef {import("webpack/lib/FileSystemInfo").Snapshot} Snapshot */
/** @typedef {import("./child-compiler").ChildCompilationTemplateResult} ChildCompilationTemplateResult */
/** @typedef {{fileDependencies: string[], contextDependencies: string[], missingDependencies: string[]}} FileDependencies */
/** @typedef {{
dependencies: FileDependencies,
compiledEntries: {[entryName: string]: ChildCompilationTemplateResult}
} | {
dependencies: FileDependencies,
error: Error
}} ChildCompilationResult */
const { HtmlWebpackChildCompiler } = require("./child-compiler");
/**
* This plugin is a singleton for performance reasons.
* To keep track if a plugin does already exist for the compiler they are cached
* in this map
* @type {WeakMap<Compiler, PersistentChildCompilerSingletonPlugin>}}
*/
const compilerMap = new WeakMap();
class CachedChildCompilation {
/**
* @param {Compiler} compiler
*/
constructor(compiler) {
/**
* @private
* @type {Compiler}
*/
this.compiler = compiler;
// Create a singleton instance for the compiler
// if there is none
if (compilerMap.has(compiler)) {
return;
}
const persistentChildCompilerSingletonPlugin =
new PersistentChildCompilerSingletonPlugin();
compilerMap.set(compiler, persistentChildCompilerSingletonPlugin);
persistentChildCompilerSingletonPlugin.apply(compiler);
}
/**
* apply is called by the webpack main compiler during the start phase
* @param {string} entry
*/
addEntry(entry) {
const persistentChildCompilerSingletonPlugin = compilerMap.get(
this.compiler,
);
if (!persistentChildCompilerSingletonPlugin) {
throw new Error(
"PersistentChildCompilerSingletonPlugin instance not found.",
);
}
persistentChildCompilerSingletonPlugin.addEntry(entry);
}
getCompilationResult() {
const persistentChildCompilerSingletonPlugin = compilerMap.get(
this.compiler,
);
if (!persistentChildCompilerSingletonPlugin) {
throw new Error(
"PersistentChildCompilerSingletonPlugin instance not found.",
);
}
return persistentChildCompilerSingletonPlugin.getLatestResult();
}
/**
* Returns the result for the given entry
* @param {string} entry
* @returns {
| { mainCompilationHash: string, error: Error }
| { mainCompilationHash: string, compiledEntry: ChildCompilationTemplateResult }
}
*/
getCompilationEntryResult(entry) {
const latestResult = this.getCompilationResult();
const compilationResult = latestResult.compilationResult;
return "error" in compilationResult
? {
mainCompilationHash: latestResult.mainCompilationHash,
error: compilationResult.error,
}
: {
mainCompilationHash: latestResult.mainCompilationHash,
compiledEntry: compilationResult.compiledEntries[entry],
};
}
}
class PersistentChildCompilerSingletonPlugin {
/**
*
* @param {{fileDependencies: string[], contextDependencies: string[], missingDependencies: string[]}} fileDependencies
* @param {Compilation} mainCompilation
* @param {number} startTime
*/
static createSnapshot(fileDependencies, mainCompilation, startTime) {
return new Promise((resolve, reject) => {
mainCompilation.fileSystemInfo.createSnapshot(
startTime,
fileDependencies.fileDependencies,
fileDependencies.contextDependencies,
fileDependencies.missingDependencies,
// @ts-ignore
null,
(err, snapshot) => {
if (err) {
return reject(err);
}
resolve(snapshot);
},
);
});
}
/**
* Returns true if the files inside this snapshot
* have not been changed
*
* @param {Snapshot} snapshot
* @param {Compilation} mainCompilation
* @returns {Promise<boolean | undefined>}
*/
static isSnapshotValid(snapshot, mainCompilation) {
return new Promise((resolve, reject) => {
mainCompilation.fileSystemInfo.checkSnapshotValid(
snapshot,
(err, isValid) => {
if (err) {
reject(err);
}
resolve(isValid);
},
);
});
}
static watchFiles(mainCompilation, fileDependencies) {
Object.keys(fileDependencies).forEach((dependencyType) => {
fileDependencies[dependencyType].forEach((fileDependency) => {
mainCompilation[dependencyType].add(fileDependency);
});
});
}
constructor() {
/**
* @private
* @type {
| {
isCompiling: false,
isVerifyingCache: false,
entries: string[],
compiledEntries: string[],
mainCompilationHash: string,
compilationResult: ChildCompilationResult
}
| Readonly<{
isCompiling: false,
isVerifyingCache: true,
entries: string[],
previousEntries: string[],
previousResult: ChildCompilationResult
}>
| Readonly <{
isVerifyingCache: false,
isCompiling: true,
entries: string[],
}>
} the internal compilation state */
this.compilationState = {
isCompiling: false,
isVerifyingCache: false,
entries: [],
compiledEntries: [],
mainCompilationHash: "initial",
compilationResult: {
dependencies: {
fileDependencies: [],
contextDependencies: [],
missingDependencies: [],
},
compiledEntries: {},
},
};
}
/**
* apply is called by the webpack main compiler during the start phase
* @param {Compiler} compiler
*/
apply(compiler) {
/** @type Promise<ChildCompilationResult> */
let childCompilationResultPromise = Promise.resolve({
dependencies: {
fileDependencies: [],
contextDependencies: [],
missingDependencies: [],
},
compiledEntries: {},
});
/**
* The main compilation hash which will only be updated
* if the childCompiler changes
*/
/** @type {string} */
let mainCompilationHashOfLastChildRecompile = "";
/** @type {Snapshot | undefined} */
let previousFileSystemSnapshot;
let compilationStartTime = new Date().getTime();
compiler.hooks.make.tapAsync(
"PersistentChildCompilerSingletonPlugin",
(mainCompilation, callback) => {
if (
this.compilationState.isCompiling ||
this.compilationState.isVerifyingCache
) {
return callback(new Error("Child compilation has already started"));
}
// Update the time to the current compile start time
compilationStartTime = new Date().getTime();
// The compilation starts - adding new templates is now not possible anymore
this.compilationState = {
isCompiling: false,
isVerifyingCache: true,
previousEntries: this.compilationState.compiledEntries,
previousResult: this.compilationState.compilationResult,
entries: this.compilationState.entries,
};
// Validate cache:
const isCacheValidPromise = this.isCacheValid(
previousFileSystemSnapshot,
mainCompilation,
);
let cachedResult = childCompilationResultPromise;
childCompilationResultPromise = isCacheValidPromise.then(
(isCacheValid) => {
// Reuse cache
if (isCacheValid) {
return cachedResult;
}
// Start the compilation
const compiledEntriesPromise = this.compileEntries(
mainCompilation,
this.compilationState.entries,
);
// Update snapshot as soon as we know the fileDependencies
// this might possibly cause bugs if files were changed between
// compilation start and snapshot creation
compiledEntriesPromise
.then((childCompilationResult) => {
return PersistentChildCompilerSingletonPlugin.createSnapshot(
childCompilationResult.dependencies,
mainCompilation,
compilationStartTime,
);
})
.then((snapshot) => {
previousFileSystemSnapshot = snapshot;
});
return compiledEntriesPromise;
},
);
// Add files to compilation which needs to be watched:
mainCompilation.hooks.optimizeTree.tapAsync(
"PersistentChildCompilerSingletonPlugin",
(chunks, modules, callback) => {
const handleCompilationDonePromise =
childCompilationResultPromise.then((childCompilationResult) => {
this.watchFiles(
mainCompilation,
childCompilationResult.dependencies,
);
});
handleCompilationDonePromise.then(
// @ts-ignore
() => callback(null, chunks, modules),
callback,
);
},
);
// Store the final compilation once the main compilation hash is known
mainCompilation.hooks.additionalAssets.tapAsync(
"PersistentChildCompilerSingletonPlugin",
(callback) => {
const didRecompilePromise = Promise.all([
childCompilationResultPromise,
cachedResult,
]).then(([childCompilationResult, cachedResult]) => {
// Update if childCompilation changed
return cachedResult !== childCompilationResult;
});
const handleCompilationDonePromise = Promise.all([
childCompilationResultPromise,
didRecompilePromise,
]).then(([childCompilationResult, didRecompile]) => {
// Update hash and snapshot if childCompilation changed
if (didRecompile) {
mainCompilationHashOfLastChildRecompile =
/** @type {string} */ (mainCompilation.hash);
}
this.compilationState = {
isCompiling: false,
isVerifyingCache: false,
entries: this.compilationState.entries,
compiledEntries: this.compilationState.entries,
compilationResult: childCompilationResult,
mainCompilationHash: mainCompilationHashOfLastChildRecompile,
};
});
handleCompilationDonePromise.then(() => callback(null), callback);
},
);
// Continue compilation:
callback(null);
},
);
}
/**
* Add a new entry to the next compile run
* @param {string} entry
*/
addEntry(entry) {
if (
this.compilationState.isCompiling ||
this.compilationState.isVerifyingCache
) {
throw new Error(
"The child compiler has already started to compile. " +
"Please add entries before the main compiler 'make' phase has started or " +
"after the compilation is done.",
);
}
if (this.compilationState.entries.indexOf(entry) === -1) {
this.compilationState.entries = [...this.compilationState.entries, entry];
}
}
getLatestResult() {
if (
this.compilationState.isCompiling ||
this.compilationState.isVerifyingCache
) {
throw new Error(
"The child compiler is not done compiling. " +
"Please access the result after the compiler 'make' phase has started or " +
"after the compilation is done.",
);
}
return {
mainCompilationHash: this.compilationState.mainCompilationHash,
compilationResult: this.compilationState.compilationResult,
};
}
/**
* Verify that the cache is still valid
* @private
* @param {Snapshot | undefined} snapshot
* @param {Compilation} mainCompilation
* @returns {Promise<boolean | undefined>}
*/
isCacheValid(snapshot, mainCompilation) {
if (!this.compilationState.isVerifyingCache) {
return Promise.reject(
new Error(
"Cache validation can only be done right before the compilation starts",
),
);
}
// If there are no entries we don't need a new child compilation
if (this.compilationState.entries.length === 0) {
return Promise.resolve(true);
}
// If there are new entries the cache is invalid
if (
this.compilationState.entries !== this.compilationState.previousEntries
) {
return Promise.resolve(false);
}
// Mark the cache as invalid if there is no snapshot
if (!snapshot) {
return Promise.resolve(false);
}
return PersistentChildCompilerSingletonPlugin.isSnapshotValid(
snapshot,
mainCompilation,
);
}
/**
* Start to compile all templates
*
* @private
* @param {Compilation} mainCompilation
* @param {string[]} entries
* @returns {Promise<ChildCompilationResult>}
*/
compileEntries(mainCompilation, entries) {
const compiler = new HtmlWebpackChildCompiler(entries);
return compiler.compileTemplates(mainCompilation).then(
(result) => {
return {
// The compiled sources to render the content
compiledEntries: result,
// The file dependencies to find out if a
// recompilation is required
dependencies: compiler.fileDependencies,
// The main compilation hash can be used to find out
// if this compilation was done during the current compilation
mainCompilationHash: mainCompilation.hash,
};
},
(error) => ({
// The compiled sources to render the content
error,
// The file dependencies to find out if a
// recompilation is required
dependencies: compiler.fileDependencies,
// The main compilation hash can be used to find out
// if this compilation was done during the current compilation
mainCompilationHash: mainCompilation.hash,
}),
);
}
/**
* @private
* @param {Compilation} mainCompilation
* @param {FileDependencies} files
*/
watchFiles(mainCompilation, files) {
PersistentChildCompilerSingletonPlugin.watchFiles(mainCompilation, files);
}
}
module.exports = {
CachedChildCompilation,
};

View File

@ -0,0 +1,264 @@
// @ts-check
"use strict";
/**
* @file
* This file uses webpack to compile a template with a child compiler.
*
* [TEMPLATE] -> [JAVASCRIPT]
*
*/
/** @typedef {import("webpack").Chunk} Chunk */
/** @typedef {import("webpack").sources.Source} Source */
/** @typedef {{hash: string, entry: Chunk, content: string, assets: {[name: string]: { source: Source, info: import("webpack").AssetInfo }}}} ChildCompilationTemplateResult */
/**
* The HtmlWebpackChildCompiler is a helper to allow reusing one childCompiler
* for multiple HtmlWebpackPlugin instances to improve the compilation performance.
*/
class HtmlWebpackChildCompiler {
/**
*
* @param {string[]} templates
*/
constructor(templates) {
/**
* @type {string[]} templateIds
* The template array will allow us to keep track which input generated which output
*/
this.templates = templates;
/** @type {Promise<{[templatePath: string]: ChildCompilationTemplateResult}>} */
this.compilationPromise; // eslint-disable-line
/** @type {number | undefined} */
this.compilationStartedTimestamp; // eslint-disable-line
/** @type {number | undefined} */
this.compilationEndedTimestamp; // eslint-disable-line
/**
* All file dependencies of the child compiler
* @type {{fileDependencies: string[], contextDependencies: string[], missingDependencies: string[]}}
*/
this.fileDependencies = {
fileDependencies: [],
contextDependencies: [],
missingDependencies: [],
};
}
/**
* Returns true if the childCompiler is currently compiling
*
* @returns {boolean}
*/
isCompiling() {
return !this.didCompile() && this.compilationStartedTimestamp !== undefined;
}
/**
* Returns true if the childCompiler is done compiling
*
* @returns {boolean}
*/
didCompile() {
return this.compilationEndedTimestamp !== undefined;
}
/**
* This function will start the template compilation
* once it is started no more templates can be added
*
* @param {import('webpack').Compilation} mainCompilation
* @returns {Promise<{[templatePath: string]: ChildCompilationTemplateResult}>}
*/
compileTemplates(mainCompilation) {
const webpack = mainCompilation.compiler.webpack;
const Compilation = webpack.Compilation;
const NodeTemplatePlugin = webpack.node.NodeTemplatePlugin;
const NodeTargetPlugin = webpack.node.NodeTargetPlugin;
const LoaderTargetPlugin = webpack.LoaderTargetPlugin;
const EntryPlugin = webpack.EntryPlugin;
// To prevent multiple compilations for the same template
// the compilation is cached in a promise.
// If it already exists return
if (this.compilationPromise) {
return this.compilationPromise;
}
const outputOptions = {
filename: "__child-[name]",
publicPath: "",
library: {
type: "var",
name: "HTML_WEBPACK_PLUGIN_RESULT",
},
scriptType: /** @type {'text/javascript'} */ ("text/javascript"),
iife: true,
};
const compilerName = "HtmlWebpackCompiler";
// Create an additional child compiler which takes the template
// and turns it into an Node.JS html factory.
// This allows us to use loaders during the compilation
const childCompiler = mainCompilation.createChildCompiler(
compilerName,
outputOptions,
[
// Compile the template to nodejs javascript
new NodeTargetPlugin(),
new NodeTemplatePlugin(),
new LoaderTargetPlugin("node"),
new webpack.library.EnableLibraryPlugin("var"),
],
);
// The file path context which webpack uses to resolve all relative files to
childCompiler.context = mainCompilation.compiler.context;
// Generate output file names
const temporaryTemplateNames = this.templates.map(
(template, index) => `__child-HtmlWebpackPlugin_${index}-${template}`,
);
// Add all templates
this.templates.forEach((template, index) => {
new EntryPlugin(
childCompiler.context,
"data:text/javascript,__webpack_public_path__ = __webpack_base_uri__ = htmlWebpackPluginPublicPath;",
`HtmlWebpackPlugin_${index}-${template}`,
).apply(childCompiler);
new EntryPlugin(
childCompiler.context,
template,
`HtmlWebpackPlugin_${index}-${template}`,
).apply(childCompiler);
});
// The templates are compiled and executed by NodeJS - similar to server side rendering
// Unfortunately this causes issues as some loaders require an absolute URL to support ES Modules
// The following config enables relative URL support for the child compiler
childCompiler.options.module = { ...childCompiler.options.module };
childCompiler.options.module.parser = {
...childCompiler.options.module.parser,
};
childCompiler.options.module.parser.javascript = {
...childCompiler.options.module.parser.javascript,
url: "relative",
};
this.compilationStartedTimestamp = new Date().getTime();
/** @type {Promise<{[templatePath: string]: ChildCompilationTemplateResult}>} */
this.compilationPromise = new Promise((resolve, reject) => {
/** @type {Source[]} */
const extractedAssets = [];
childCompiler.hooks.thisCompilation.tap(
"HtmlWebpackPlugin",
(compilation) => {
compilation.hooks.processAssets.tap(
{
name: "HtmlWebpackPlugin",
stage: Compilation.PROCESS_ASSETS_STAGE_ADDITIONS,
},
(assets) => {
temporaryTemplateNames.forEach((temporaryTemplateName) => {
if (assets[temporaryTemplateName]) {
extractedAssets.push(assets[temporaryTemplateName]);
compilation.deleteAsset(temporaryTemplateName);
}
});
},
);
},
);
childCompiler.runAsChild((err, entries, childCompilation) => {
// Extract templates
// TODO fine a better way to store entries and results, to avoid duplicate chunks and assets
const compiledTemplates = entries
? extractedAssets.map((asset) => asset.source())
: [];
// Extract file dependencies
if (entries && childCompilation) {
this.fileDependencies = {
fileDependencies: Array.from(childCompilation.fileDependencies),
contextDependencies: Array.from(
childCompilation.contextDependencies,
),
missingDependencies: Array.from(
childCompilation.missingDependencies,
),
};
}
// Reject the promise if the childCompilation contains error
if (
childCompilation &&
childCompilation.errors &&
childCompilation.errors.length
) {
const errorDetailsArray = [];
for (const error of childCompilation.errors) {
let message = error.message;
if (error.stack) {
message += "\n" + error.stack;
}
errorDetailsArray.push(message);
}
const errorDetails = errorDetailsArray.join("\n");
reject(new Error("Child compilation failed:\n" + errorDetails));
return;
}
// Reject if the error object contains errors
if (err) {
reject(err);
return;
}
if (!childCompilation || !entries) {
reject(new Error("Empty child compilation"));
return;
}
/**
* @type {{[templatePath: string]: ChildCompilationTemplateResult}}
*/
const result = {};
/** @type {{[name: string]: { source: Source, info: import("webpack").AssetInfo }}} */
const assets = {};
for (const asset of childCompilation.getAssets()) {
assets[asset.name] = { source: asset.source, info: asset.info };
}
compiledTemplates.forEach((templateSource, entryIndex) => {
// The compiledTemplates are generated from the entries added in
// the addTemplate function.
// Therefore, the array index of this.templates should be the as entryIndex.
result[this.templates[entryIndex]] = {
// TODO, can we have Buffer here?
content: /** @type {string} */ (templateSource),
hash: childCompilation.hash || "XXXX",
entry: entries[entryIndex],
assets,
};
});
this.compilationEndedTimestamp = new Date().getTime();
resolve(result);
});
});
return this.compilationPromise;
}
}
module.exports = {
HtmlWebpackChildCompiler,
};

View File

@ -0,0 +1,45 @@
// @ts-check
"use strict";
/** @typedef {import("webpack").Compilation} Compilation */
/**
* @type {{[sortmode: string] : (entryPointNames: Array<string>, compilation: Compilation, htmlWebpackPluginOptions: any) => Array<string> }}
* This file contains different sort methods for the entry chunks names
*/
module.exports = {};
/**
* Performs identity mapping (no-sort).
* @param {Array<string>} chunks the chunks to sort
* @return {Array<string>} The sorted chunks
*/
module.exports.none = (chunks) => chunks;
/**
* Sort manually by the chunks
* @param {string[]} entryPointNames the chunks to sort
* @param {Compilation} compilation the webpack compilation
* @param {any} htmlWebpackPluginOptions the plugin options
* @return {string[]} The sorted chunks
*/
module.exports.manual = (
entryPointNames,
compilation,
htmlWebpackPluginOptions,
) => {
const chunks = htmlWebpackPluginOptions.chunks;
if (!Array.isArray(chunks)) {
return entryPointNames;
}
// Remove none existing entries from
// htmlWebpackPluginOptions.chunks
return chunks.filter((entryPointName) => {
return compilation.entrypoints.has(entryPointName);
});
};
/**
* Defines the default sorter.
*/
module.exports.auto = module.exports.none;

42
app_vue/node_modules/html-webpack-plugin/lib/errors.js generated vendored Normal file
View File

@ -0,0 +1,42 @@
// @ts-nocheck
"use strict";
let prettyError;
function getPrettyError() {
if (!prettyError) {
// lazily require to improve startup time since pretty-error is rather heavy package
const PrettyError = require("pretty-error");
prettyError = new PrettyError();
prettyError.withoutColors();
prettyError.skipPackage("html-plugin-evaluation");
prettyError.skipNodeFiles();
prettyError.skip(function (traceLine) {
return traceLine.path === "html-plugin-evaluation";
});
}
return prettyError;
}
module.exports = function (err, context) {
return {
toHtml: function () {
return "Html Webpack Plugin:\n<pre>\n" + this.toString() + "</pre>";
},
toJsonHtml: function () {
return JSON.stringify(this.toHtml());
},
toString: function () {
try {
return getPrettyError()
.render(err)
.replace(/webpack:\/\/\/\./g, context);
} catch (e) {
// This can sometimes fail. We don't know why, but returning the
// original error is better than returning the error thrown by
// pretty-error.
return err;
}
},
};
};

View File

@ -0,0 +1,7 @@
// TODO remove in the next major release
const plugin = require("../index");
module.exports = {
getHtmlWebpackPluginHooks: (compilation) =>
plugin.getCompilationHooks(compilation),
};

View File

@ -0,0 +1,127 @@
// @ts-check
/** @typedef {import("../typings").HtmlTagObject} HtmlTagObject */
/**
* @file
* This file provides to helper to create html as a object representation as
* those objects are easier to modify than pure string representations
*
* Usage:
* ```
* const element = createHtmlTagObject('h1', {class: 'demo'}, 'Hello World');
* const html = htmlTagObjectToString(element);
* console.log(html) // -> <h1 class="demo">Hello World</h1>
* ```
*/
/**
* All html tag elements which must not contain innerHTML
* @see https://www.w3.org/TR/html5/syntax.html#void-elements
*/
const voidTags = [
"area",
"base",
"br",
"col",
"embed",
"hr",
"img",
"input",
"keygen",
"link",
"meta",
"param",
"source",
"track",
"wbr",
];
/**
* Turn a tag definition into a html string
* @param {HtmlTagObject} tagDefinition
* A tag element according to the htmlWebpackPlugin object notation
*
* @param xhtml {boolean}
* Whether the generated html should add closing slashes to be xhtml compliant
*/
function htmlTagObjectToString(tagDefinition, xhtml) {
const attributes = Object.keys(tagDefinition.attributes || {})
.filter(function (attributeName) {
return (
tagDefinition.attributes[attributeName] === "" ||
tagDefinition.attributes[attributeName]
);
})
.map(function (attributeName) {
if (tagDefinition.attributes[attributeName] === true) {
return xhtml
? attributeName + '="' + attributeName + '"'
: attributeName;
}
return (
attributeName + '="' + tagDefinition.attributes[attributeName] + '"'
);
});
return (
"<" +
[tagDefinition.tagName].concat(attributes).join(" ") +
(tagDefinition.voidTag && xhtml ? "/" : "") +
">" +
(tagDefinition.innerHTML || "") +
(tagDefinition.voidTag ? "" : "</" + tagDefinition.tagName + ">")
);
}
/**
* Static helper to create a tag object to be get injected into the dom
*
* @param {string} tagName
* the name of the tag e.g. 'div'
*
* @param {{[attributeName: string]: string|boolean|null|undefined}} [attributes]
* tag attributes e.g. `{ 'class': 'example', disabled: true }`
*
* @param {string} [innerHTML]
*
* @param {{[attributeName: string]: string|boolean|null|undefined}} [meta]
* meta information about the tag e.g. `{ 'plugin': 'html-webpack-plugin' }`
*
* @returns {HtmlTagObject}
*/
function createHtmlTagObject(tagName, attributes, innerHTML, meta) {
return {
tagName: tagName,
voidTag: voidTags.indexOf(tagName) !== -1,
attributes: attributes || {},
meta: meta || {},
innerHTML: innerHTML,
};
}
/**
* The `HtmlTagArray Array with a custom `.toString()` method.
*
* This allows the following:
* ```
* const tags = HtmlTagArray.from([tag1, tag2]);
* const scriptTags = tags.filter((tag) => tag.tagName === 'script');
* const html = scriptTags.toString();
* ```
*
* Or inside a string literal:
* ```
* const tags = HtmlTagArray.from([tag1, tag2]);
* const html = `<html><body>${tags.filter((tag) => tag.tagName === 'script')}</body></html>`;
* ```
*
*/
class HtmlTagArray extends Array {
toString() {
return this.join("");
}
}
module.exports = {
HtmlTagArray: HtmlTagArray,
createHtmlTagObject: createHtmlTagObject,
htmlTagObjectToString: htmlTagObjectToString,
};

55
app_vue/node_modules/html-webpack-plugin/lib/loader.js generated vendored Normal file
View File

@ -0,0 +1,55 @@
/* This loader renders the template with underscore if no other loader was found */
// @ts-nocheck
"use strict";
const _template = require("lodash/template");
module.exports = function (source) {
// Get templating options
const options = this.getOptions();
const force = options.force || false;
const allLoadersButThisOne = this.loaders.filter(
(loader) => loader.normal !== module.exports,
);
// This loader shouldn't kick in if there is any other loader (unless it's explicitly enforced)
if (allLoadersButThisOne.length > 0 && !force) {
return source;
}
// Allow only one html-webpack-plugin loader to allow loader options in the webpack config
const htmlWebpackPluginLoaders = this.loaders.filter(
(loader) => loader.normal === module.exports,
);
const lastHtmlWebpackPluginLoader =
htmlWebpackPluginLoaders[htmlWebpackPluginLoaders.length - 1];
if (this.loaders[this.loaderIndex] !== lastHtmlWebpackPluginLoader) {
return source;
}
// Skip .js files (unless it's explicitly enforced)
if (/\.(c|m)?js$/.test(this.resourcePath) && !force) {
return source;
}
// The following part renders the template with lodash as a minimalistic loader
//
const template = _template(source, {
interpolate: /<%=([\s\S]+?)%>/g,
variable: "data",
...options,
});
// Use `eval("require")("lodash")` to enforce using the native nodejs require
// during template execution
return (
'var _ = eval("require")(' +
JSON.stringify(require.resolve("lodash")) +
");" +
"module.exports = function (templateParams) { with(templateParams) {" +
// Execute the lodash template
"return (" +
template.source +
")();" +
"}}"
);
};