-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlicense-banner-plugin.js
105 lines (92 loc) · 3.9 KB
/
license-banner-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
const ConcatSource = require('webpack-sources').ConcatSource
const ModuleFilenameHelpers = require('webpack/lib/ModuleFilenameHelpers')
const Mustache = require('mustache')
const path = require('path')
const fs = require('fs')
function wrapComment (str) {
if (str.indexOf('\n') < 0) {
return '/*! ' + str + ' */'
}
return '/*!\n * ' + str.split('\n').join('\n * ') + '\n */'
}
module.exports = class LicenseBannerPlugin {
constructor (options) {
if (arguments.length > 1) {
throw new Error('LicenseBannerPlugin only takes one argument (pass an options object)')
}
if (typeof options === 'string') {
options = {
bannerTemplate: options
}
}
this.options = options || {}
this.bannerTemplate = this.options.raw ? options.bannerTemplate : wrapComment(options.bannerTemplate)
this.recursiveInclude = options.recursiveInclude
this.basePath = options.basePath || path.normalize('../../')
this.parsePeerDependencies = options.parsePeerDependencies
this.templateData = this.adjustPackageInfo(require(path.join(this.basePath, 'package.json')))
this.dependencies = [this.adjustPackageInfo(require('webpack/package.json'))]
this.parsePackageInfo(this.templateData, this.basePath)
if (this.options.additionalData) {
Object.assign(this.templateData, this.options.additionalData)
}
}
adjustPackageInfo (packageInfo) {
packageInfo.license = packageInfo.license || false
packageInfo.author = packageInfo.author || false
if (packageInfo.author && !(typeof packageInfo.author === 'string')) {
packageInfo.author = packageInfo.author.name +
(packageInfo.author.email ? (' <' + packageInfo.author.email + '>') : '') +
(packageInfo.author.url ? (' (' + packageInfo.author.url + ')') : '')
}
return packageInfo
}
findPackageJson (packagePath, packageName) {
let possiblePath = path.join(packagePath, 'node_modules', packageName, 'package.json')
if (fs.existsSync(path.join(possiblePath))) {
return require(possiblePath)
} else if (packagePath !== this.basePath) {
return this.findPackageJson(path.join(packagePath, '../../'), packageName)
} else {
throw new Error(`Package not found. Path: ${packagePath}. Name: ${packageName}.`)
}
}
parsePackageInfo (packageInfo, packagePath) {
let packageDependencies = packageInfo.dependencies ? packageInfo.dependencies : {}
if (this.parsePeerDependencies && packageInfo.peerDependencies) {
Object.assign(packageDependencies, packageInfo.peerDependencies)
}
for (let dependency of Object.keys(packageDependencies)) {
if (!this.dependencies.some(d => d.name === dependency)) {
let childPackageInfo = this.adjustPackageInfo(this.findPackageJson(packagePath, dependency))
this.dependencies.push(childPackageInfo)
if (this.recursiveInclude && dependency.match(this.recursiveInclude)) {
this.parsePackageInfo(childPackageInfo, path.join(packagePath, 'node_modules', dependency))
}
}
}
}
apply (compiler) {
let options = this.options
let bannerTemplate = this.bannerTemplate
this.templateData.dependencies = this.dependencies
.filter(dep => !compiler.options.externals.hasOwnProperty(dep.name))
.sort((a, b) => (a.name.toLowerCase() > b.name.toLowerCase()) ? 1 : -1)
let banner = Mustache.render(bannerTemplate, this.templateData)
compiler.plugin('compilation', compilation => {
compilation.plugin('optimize-chunk-assets', (chunks, callback) => {
chunks.forEach(chunk => {
if (options.entryOnly && !chunk.initial) {
return
}
chunk.files
.filter(ModuleFilenameHelpers.matchObject.bind(undefined, options))
.forEach(file => {
compilation.assets[file] = new ConcatSource(banner, '\n', compilation.assets[file])
})
})
callback()
})
})
}
}