forked from DustinJackson/html-webpack-inline-source-plugin
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
147 lines (128 loc) · 5.03 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
'use strict';
var escapeRegex = require('escape-string-regexp');
var path = require('path');
var slash = require('slash');
var sourceMapUrl = require('source-map-url');
function HtmlWebpackInlineSourcePlugin(htmlWebpackPlugin, customScriptTagAttributes) {
this.htmlWebpackPlugin = htmlWebpackPlugin;
this.customScriptTagAttributes = customScriptTagAttributes;
}
HtmlWebpackInlineSourcePlugin.prototype.apply = function (compiler) {
var self = this;
// Hook into the html-webpack-plugin processing
compiler.hooks.compilation.tap('html-webpack-inline-source-plugin', compilation => {
self.htmlWebpackPlugin
.getHooks(compilation)
.alterAssetTagGroups.tapAsync('html-webpack-inline-source-plugin', (htmlPluginData, callback) => {
if (!htmlPluginData.plugin.options.inlineSource) {
return callback(null, htmlPluginData);
}
var regexStr = htmlPluginData.plugin.options.inlineSource;
var result = self.processTags(compilation, regexStr, htmlPluginData);
callback(null, result);
});
});
};
HtmlWebpackInlineSourcePlugin.prototype.processTags = function (compilation, regexStr, pluginData) {
var self = this;
var bodyTags = [];
var headTags = [];
var regex = new RegExp(regexStr);
var filename = pluginData.plugin.options.filename;
pluginData.headTags.forEach(function (tag) {
headTags.push(self.processTag(compilation, regex, tag, filename));
});
pluginData.bodyTags.forEach(function (tag) {
bodyTags.push(self.processTag(compilation, regex, tag, filename));
});
return {headTags: headTags, bodyTags: bodyTags, plugin: pluginData.plugin, outputName: pluginData.outputName};
};
HtmlWebpackInlineSourcePlugin.prototype.resolveSourceMaps = function (compilation, assetName, asset) {
var source = asset.source();
var out = compilation.outputOptions;
// Get asset file absolute path
var assetPath = path.join(out.path, assetName);
// Extract original sourcemap URL from source string
if (typeof source !== 'string') {
source = source.toString();
}
var mapUrlOriginal = sourceMapUrl.getFrom(source);
// Return unmodified source if map is unspecified, URL-encoded, or already relative to site root
if (!mapUrlOriginal || mapUrlOriginal.indexOf('data:') === 0 || mapUrlOriginal.indexOf('/') === 0) {
return source;
}
// Figure out sourcemap file path *relative to the asset file path*
var assetDir = path.dirname(assetPath);
var mapPath = path.join(assetDir, mapUrlOriginal);
var mapPathRelative = path.relative(out.path, mapPath);
// Starting with Node 6, `path` module throws on `undefined`
var publicPath = out.publicPath || '';
// Prepend Webpack public URL path to source map relative path
// Calling `slash` converts Windows backslashes to forward slashes
var mapUrlCorrected = slash(path.join(publicPath, mapPathRelative));
// Regex: exact original sourcemap URL, possibly '*/' (for CSS), then EOF, ignoring whitespace
var regex = new RegExp(escapeRegex(mapUrlOriginal) + '(\\s*(?:\\*/)?\\s*$)');
// Replace sourcemap URL and (if necessary) preserve closing '*/' and whitespace
return source.replace(regex, function (match, group) {
return mapUrlCorrected + group;
});
};
HtmlWebpackInlineSourcePlugin.prototype.processTag = function (compilation, regex, tag, filename) {
var assetUrl;
// inline js
if (tag.tagName === 'script' && tag.attributes && regex.test(tag.attributes.src)) {
assetUrl = tag.attributes.src;
if (this.customScriptTagAttributes === undefined) {
tag = {
tagName: 'script',
closeTag: true,
attributes: {
type: 'text/javascript'
}
}
} else {
tag = {
tagName: 'script',
closeTag: true,
attributes: {
type: 'text/javascript',
...this.customScriptTagAttributes
}
};
}
// inline css
} else if (tag.tagName === 'link' && regex.test(tag.attributes.href)) {
assetUrl = tag.attributes.href;
tag = {
tagName: 'style',
closeTag: true,
attributes: {
type: 'text/css'
}
};
}
if (assetUrl) {
// Strip public URL prefix from asset URL to get Webpack asset name
var publicUrlPrefix = compilation.outputOptions.publicPath || '';
// if filename is in subfolder, assetUrl should be prepended folder path
if (path.basename(filename) !== filename) {
assetUrl = path.dirname(filename) + '/' + assetUrl;
}
var assetName = path.posix.relative(publicUrlPrefix, assetUrl);
var asset = getAssetByName(compilation.assets, assetName);
var updatedSource = this.resolveSourceMaps(compilation, assetName, asset);
tag.innerHTML = (tag.tagName === 'script') ? updatedSource.replace(/(<)(\/script>)/g, '\\x3C$2') : updatedSource;
}
return tag;
};
function getAssetByName(assests, assetName) {
for (var key in assests) {
if (assests.hasOwnProperty(key)) {
var processedKey = path.posix.relative('', key);
if (processedKey === assetName) {
return assests[key];
}
}
}
}
module.exports = HtmlWebpackInlineSourcePlugin;