-
Notifications
You must be signed in to change notification settings - Fork 1
/
bookmarklet-webpack-plugin.js
106 lines (89 loc) · 2.85 KB
/
bookmarklet-webpack-plugin.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
const fs = require('fs');
const validateOptions = require('schema-utils');
const { RawSource } = require('webpack-sources');
const Handlebars = require('handlebars');
// TODO: Setup schema file
// > include default values
// > Add more error handling
// schema for options object
const schema = {
type: 'object',
properties: {
test: {
type: 'string',
},
},
};
module.exports = class BookmarkletWebpackPlugin {
constructor(options = {}) {
validateOptions(schema, options, 'BookmarkletWebpackPlugin');
this.options = options;
}
apply(compiler) {
const {
input,
output = 'index.html',
repo,
linkName = 'Bookmarklet',
pageTitle = 'Bookmarklet',
author,
templatePath = require.resolve('./default.html.hbs'),
} = this.options;
compiler.hooks.emit.tapAsync(
'BookmarkletWebpackPlugin',
(compilation, cb) => {
const asset = Object.entries(compilation.assets).filter(([key, _]) =>
key.includes(input)
);
if (asset.length > 1)
throw Error(
`
BookmarkletWebpackPlugin:
input: ${input}, returned no matching assets
*Make sure you provide the options object to the plugin with a valid 'input' property
Example
plugins: [new BookmarkletWebpackPlugin({input: 'main', output: 'bookmarkletPage.html'})],
input should match the javascript bundle name -- Output:{filename: [[name]].js
currently does not support [contentHash] but will return partial matches
`
);
if (asset.length > 1)
throw Error(
`
BookmarkletWebpackPlugin:
input: ${input}
Matched multiple assets: ${asset.map(([key, _]) => key).join(', ')}
*Must rename assets or use a better match bundle name.
`
);
const assetName = asset[0][0];
const code = encodeURIComponent(asset[0][1]._value);
const bookmarkletCode = `javascript:(function(){${code}})()`;
// Remove the javascript asset output
delete compilation.assets[assetName];
try {
const templateSource = fs.readFileSync(templatePath, 'utf8');
const generateOutput = Handlebars.compile(templateSource);
compilation.assets[output] = new RawSource(
generateOutput({
bookmarkletCode,
repo,
linkName,
pageTitle,
author,
})
);
} catch (error) {
throw Error(
`
BookmarkletWebpackPlugin:
input: ${input}
Failed to generate output from template: ${error.message}
`
);
}
cb();
}
);
}
};