Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow user defined tags for js injection #1234

Closed
wants to merge 6 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 30 additions & 10 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -233,14 +233,18 @@ class HtmlWebpackPlugin {
plugin: self
}))
.then(({ assetTags }) => {
// Inject scripts to body unless it set explictly to head
const scriptTarget = self.options.inject === 'head' ? 'head' : 'body';
// Inject scripts to body unless it set explictly to a user defined tag
let scriptTarget = 'body';
if (typeof (self.options.inject) === 'string') {
scriptTarget = self.options.inject;
}
// Group assets to `head` and `body` tag arrays
const assetGroups = this.generateAssetGroups(assetTags, scriptTarget);
// Allow third-party-plugin authors to reorder and change the assetTags once they are grouped
return getHtmlWebpackPluginHooks(compilation).alterAssetTagGroups.promise({
headTags: assetGroups.headTags,
bodyTags: assetGroups.bodyTags,
userDefinedTags: assetGroups.userDefinedTags,
outputName: childCompilationOutputName,
plugin: self
});
Expand All @@ -262,16 +266,16 @@ class HtmlWebpackPlugin {
// Execute the template
.then(([assetsHookResult, assetTags, compilationResult]) => typeof compilationResult !== 'function'
? compilationResult
: self.executeTemplate(compilationResult, assetsHookResult.assets, { headTags: assetTags.headTags, bodyTags: assetTags.bodyTags }, compilation));
: self.executeTemplate(compilationResult, assetsHookResult.assets, { headTags: assetTags.headTags, bodyTags: assetTags.bodyTags, userDefinedTags: assetTags.userDefinedTags }, compilation));

const injectedHtmlPromise = Promise.all([assetTagGroupsPromise, templateExectutionPromise])
// Allow plugins to change the html before assets are injected
.then(([assetTags, html]) => {
const pluginArgs = { html, headTags: assetTags.headTags, bodyTags: assetTags.bodyTags, plugin: self, outputName: childCompilationOutputName };
const pluginArgs = { html, headTags: assetTags.headTags, bodyTags: assetTags.bodyTags, userDefinedTags: assetTags.userDefinedTags, plugin: self, outputName: childCompilationOutputName };
return getHtmlWebpackPluginHooks(compilation).afterTemplateExecution.promise(pluginArgs);
})
.then(({ html, headTags, bodyTags }) => {
return self.postProcessHtml(html, assets, { headTags, bodyTags });
.then(({ html, headTags, bodyTags, userDefinedTags }) => {
return self.postProcessHtml(html, assets, { headTags, bodyTags, userDefinedTags });
});

const emitHtmlPromise = injectedHtmlPromise
Expand Down Expand Up @@ -817,14 +821,17 @@ class HtmlWebpackPlugin {
...assetTags.meta,
...assetTags.styles
],
bodyTags: []
bodyTags: [],
userDefinedTags: []
};
// Add script tags to head or body depending on
// the htmlPluginOptions
// Add script tags to head, body, or user defined tag depending
// on the htmlPluginOptions
if (scriptTarget === 'body') {
result.bodyTags.push(...assetTags.scripts);
} else {
} else if (scriptTarget === 'head') {
result.headTags.push(...assetTags.scripts);
} else {
result.userDefinedTags.push(...assetTags.scripts);
}
return result;
}
Expand All @@ -847,8 +854,11 @@ class HtmlWebpackPlugin {
const htmlRegExp = /(<html[^>]*>)/i;
const headRegExp = /(<\/head\s*>)/i;
const bodyRegExp = /(<\/body\s*>)/i;
const otherTagRegExp = new RegExp(`(</${this.options.inject}\\s*>)`, 'i');

const body = assetTags.bodyTags.map((assetTagObject) => htmlTagObjectToString(assetTagObject, this.options.xhtml));
const head = assetTags.headTags.map((assetTagObject) => htmlTagObjectToString(assetTagObject, this.options.xhtml));
const userDefinedTag = assetTags.userDefinedTags.map((assetTagObject) => htmlTagObjectToString(assetTagObject, this.options.xhtml));

if (body.length) {
if (bodyRegExp.test(html)) {
Expand All @@ -874,6 +884,16 @@ class HtmlWebpackPlugin {
html = html.replace(headRegExp, match => head.join('') + match);
}

if (userDefinedTag.length) {
if (otherTagRegExp.test(html)) {
// Append assets to body element
html = html.replace(otherTagRegExp, match => userDefinedTag.join('') + match);
} else {
// Append scripts to the end of the file if no <other> element exists:
html += userDefinedTag.join('');
}
}

// Inject manifest into the opening html tag
if (assets.manifest) {
html = html.replace(/(<html[^>]*)(>)/i, (match, start, end) => {
Expand Down