From c7f8eede0117229eaa530df8929dde2734ca8584 Mon Sep 17 00:00:00 2001 From: Mickael Jeanroy Date: Fri, 7 Aug 2020 14:19:36 +0200 Subject: [PATCH] release: prepare next release --- dist/index.js | 1324 ------------------------------------------------- 1 file changed, 1324 deletions(-) delete mode 100644 dist/index.js diff --git a/dist/index.js b/dist/index.js deleted file mode 100644 index 77aa32f7..00000000 --- a/dist/index.js +++ /dev/null @@ -1,1324 +0,0 @@ -/** - * The MIT License (MIT) - * - * Copyright (c) 2016-2020 Mickael Jeanroy - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - */ - -"use strict"; - -function _interopDefault(ex) { - return ex && typeof ex === "object" && "default" in ex ? ex["default"] : ex; -} - -var _ = _interopDefault(require("lodash")); -var fs = _interopDefault(require("fs")); -var path = _interopDefault(require("path")); -var mkdirp = _interopDefault(require("mkdirp")); -var moment = _interopDefault(require("moment")); -var MagicString = _interopDefault(require("magic-string")); -var glob = _interopDefault(require("glob")); -var packageNameRegex = _interopDefault(require("package-name-regex")); -var commenting = _interopDefault(require("commenting")); -var spdxExpressionValidate = _interopDefault( - require("spdx-expression-validate") -); -var spdxSatisfies = _interopDefault(require("spdx-satisfies")); - -const EOL = "\n"; - -/** - * Person, defined by: - * - A name. - * - An email (optional). - * - An URL (optional). - */ - -class Person { - /** - * Create the person. - * - * If parameter is a string, it will be automatically parsed according to - * this format: NAME (URL) (where email and url are optional). - * - * @param {string|object} person The person identity. - * @constructor - */ - constructor(person) { - if (_.isString(person)) { - const o = {}; - let current = "name"; - - for (let i = 0, size = person.length; i < size; ++i) { - const character = person.charAt(i); - - if (character === "<") { - current = "email"; - } else if (character === "(") { - current = "url"; - } else if (character !== ")" && character !== ">") { - o[current] = (o[current] || "") + character; - } - } - - _.forEach(["name", "email", "url"], (prop) => { - if (_.has(o, prop)) { - o[prop] = _.trim(o[prop]); - } - }); - - person = o; - } - - this.name = person.name || null; - this.email = person.email || null; - this.url = person.url || null; - } - /** - * Serialize the person to a string with the following format: - * NAME (URL) - * - * @param {string} prefix Optional prefix prepended to the output string. - * @param {string} suffix Optional suffix appended to the output string. - * @return {string} The person as a string. - */ - - text() { - let text = `${this.name}`; - - if (this.email) { - text += ` <${this.email}>`; - } - - if (this.url) { - text += ` (${this.url})`; - } - - return text; - } -} - -/** - * Dependency structure. - */ - -class Dependency { - /** - * Create new dependency from package description. - * - * @param {Object} pkg Package description. - * @constructor - */ - constructor(pkg) { - this.name = pkg.name || null; - this.maintainers = pkg.maintainers || []; - this.version = pkg.version || null; - this.description = pkg.description || null; - this.repository = pkg.repository || null; - this.homepage = pkg.homepage || null; - this.private = pkg.private || false; - this.license = pkg.license || null; - this.licenseText = pkg.licenseText || null; // Parse the author field to get an object. - - this.author = pkg.author ? new Person(pkg.author) : null; // Parse the contributor array. - - this.contributors = _.map( - _.castArray(pkg.contributors || []), - (contributor) => new Person(contributor) - ); // The `licenses` field is deprecated but may be used in some packages. - // Map it to a standard license field. - - if (!this.license && pkg.licenses) { - // Map it to a valid license field. - // See: https://docs.npmjs.com/files/package.json#license - this.license = `(${_.chain(pkg.licenses) - .map((license) => license.type || license) - .join(" OR ") - .value()})`; - } - } - /** - * Serialize dependency as a string. - * - * @return {string} The dependency correctly formatted. - */ - - text() { - const lines = []; - lines.push(`Name: ${this.name}`); - lines.push(`Version: ${this.version}`); - lines.push(`License: ${this.license}`); - lines.push(`Private: ${this.private}`); - - if (this.description) { - lines.push(`Description: ${this.description || false}`); - } - - if (this.repository) { - lines.push(`Repository: ${this.repository.url}`); - } - - if (this.homepage) { - lines.push(`Homepage: ${this.homepage}`); - } - - if (this.author) { - lines.push(`Author: ${this.author.text()}`); - } - - if (!_.isEmpty(this.contributors)) { - lines.push(`Contributors:`); - - const allContributors = _.chain(this.contributors) - .map((contributor) => contributor.text()) - .map((line) => ` ${line}`) - .value(); - - lines.push(...allContributors); - } - - if (this.licenseText) { - lines.push("License Copyright:"); - lines.push("==="); - lines.push(""); - lines.push(this.licenseText); - } - - return lines.join(EOL); - } -} - -/** - * Generate block comment from given text content. - * - * @param {string} text Text content. - * @param {Object} commentStyle The comment style setting. - * @return {string} Block comment. - */ - -function generateBlockComment(text, commentStyle) { - const options = { - extension: ".js", - }; - - if (commentStyle) { - options.style = new commenting.Style( - commentStyle.body, - commentStyle.start, - commentStyle.end - ); - } - - return commenting(text.trim(), options); -} - -/** - * The plugin name. - * @type {string} - */ -const PLUGIN_NAME = "rollup-plugin-license"; - -/** - * Check if given value is a `string`. - * - * @param {*} value The value to check. - * @return {boolean} `true` if `value` is a string, `false` otherwise. - */ - -function isString(value) { - return _.isString(value); -} -/** - * Check if given value is a `boolean`. - * - * @param {*} value The value to check. - * @return {boolean} `true` if `value` is a boolean, `false` otherwise. - */ - -function isBoolean(value) { - return _.isBoolean(value); -} -/** - * Check if given value is a `function`. - * - * @param {*} value The value to check. - * @return {boolean} `true` if `value` is a function, `false` otherwise. - */ - -function isFunction(value) { - return _.isFunction(value); -} -/** - * Check if given value is a `number`. - * - * @param {*} value The value to check. - * @return {boolean} `true` if `value` is a number, `false` otherwise. - */ - -function isNumber(value) { - return _.isNumber(value); -} -/** - * Check if given value is `null` or `undefined`. - * - * @param {*} value The value to check. - * @return {boolean} `true` if `value` is `null` or `undefined`, `false` otherwise. - */ - -function isNil(value) { - return _.isNil(value); -} -/** - * Check if given value is an `array`. - * - * @param {*} value The value to check. - * @return {boolean} `true` if `value` is an array, `false` otherwise. - */ - -function isArray(value) { - return _.isArray(value); -} -/** - * Check if given value is an plain object. - * - * @param {*} value The value to check. - * @return {boolean} `true` if `value` is a plain object, `false` otherwise. - */ - -function isObject(value) { - return ( - _.isObject(value) && - !isArray(value) && - !isFunction(value) && - !isNil(value) && - !isString(value) && - !isNumber(value) - ); -} - -const validators = { - string() { - return { - type: "object.type.string", - message: "must be a string", - schema: null, - test: isString, - }; - }, - - boolean() { - return { - type: "object.type.boolean", - message: "must be a boolean", - schema: null, - test: isBoolean, - }; - }, - - func() { - return { - type: "object.type.func", - message: "must be a function", - schema: null, - test: isFunction, - }; - }, - - object(schema) { - return { - type: "object.type.object", - message: "must be an object", - schema, - test: isObject, - }; - }, - - array(schema) { - return { - type: "object.type.array", - message: "must be an array", - schema, - test: isArray, - }; - }, - - any() { - return { - type: "object.any", - message: null, - schema: null, - test: () => true, - }; - }, -}; - -/** - * Format given array of path to a human readable path. - * - * @param {Array} paths List of paths. - * @return {string} The full path. - */ - -function formatPath(paths) { - let str = ""; - - _.forEach(paths, (p) => { - if (_.isNumber(p)) { - str += `[${p}]`; - } else if (!str) { - str += p; - } else { - str += `.${p}`; - } - }); - - return str; -} - -/** - * Validate value against given schema. - * It is assumed that `value` will not be `null` or `undefined`. - * - * @param {*} value The value being validated. - * @param {Array|Object} schema The validation schema. - * @param {Array} path The path being validated. - * @returns {Array} Found errors. - */ - -function doItemValidation(value, schema, path) { - const validators = _.castArray(schema); - - const matchedValidators = _.filter(validators, (validator) => - validator.test(value) - ); // No one matched, we can stop here and return an error with a proper message. - - if (_.isEmpty(matchedValidators)) { - return [ - { - path, - message: _.map( - validators, - (validator) => `"${formatPath(path)}" ${validator.message}` - ).join(" OR "), - }, - ]; - } // Run "sub-validators" - - return _.chain(matchedValidators) - .filter((validator) => validator.schema) - .map((validator) => validate(value, validator.schema, path)) - .flatten() - .value(); -} -/** - * Validate object against given schema. - * Note that `null` or `undefined` is allowed and do not produce an error. - * - * @param {Object} obj The object to validate. - * @param {Array|Object} schema The validation schema. - * @param {Array} current The current path being validated. - * @returns {Array} Found errors. - */ - -function validateObject(obj, schema, current) { - const errors = []; - - _.forEach(obj, (value, k) => { - if (_.isNil(value)) { - return; - } - - const path = [...current, k]; - - if (!_.has(schema, k)) { - errors.push({ - type: "object.allowUnknown", - path, - }); - } else { - errors.push(...doItemValidation(value, schema[k], path)); - } - }); - - return errors; -} -/** - * Validate element of an array. - * - * Instead of "classic" object validation, `null` and `undefined` will produce - * an error here. - * - * @param {*} item The item to validate. - * @param {number} idx The index of item in original array. - * @param {Array|Object} schema The validation schema. - * @param {Array} current The path being validated. - * @return {Array} Found errors. - */ - -function validateArrayItem(item, idx, schema, current) { - const path = [...current, idx]; - - if (_.isUndefined(item)) { - return [ - { - path, - message: `"${formatPath(path)}" is undefined.`, - }, - ]; - } - - if (_.isNull(item)) { - return [ - { - path, - message: `"${formatPath(path)}" is null.`, - }, - ]; - } - - return doItemValidation(item, schema, path); -} -/** - * Validate all elements of given array against given schema (or array of schemas). - * - * @param {Array<*>} array Array of elements to validate. - * @param {Array|Object} schema The schema to use for validation. - * @param {string} current The path being validated. - * @return {Array} Found errors. - */ - -function validateArray(array, schema, current) { - return _.chain(array) - .map((item, idx) => validateArrayItem(item, idx, schema, current)) - .flatten() - .value(); -} -/** - * Validate given object against given schema. - * - * Note that the very first version used `@hapi/joi` but this package does not support node < 8 in its latest version. - * Since I don't want to depends on deprecated and non maintained packages, and I want to keep compatibility with - * Node 6, I re-implemented the small part I needed here. - * - * Once node 6 will not be supported (probably with rollup >= 2), it will be time to drop this in favor of `@hapi/joi` - * for example. - * - * @param {Object} obj Object to validate. - * @param {Object} schema The schema against the given object will be validated. - * @param {Array} current The current path context of given object, useful to validate against subobject. - * @return {Array} Found errors. - */ - -function validate(obj, schema, current = []) { - return _.isArray(obj) - ? validateArray(obj, schema, current) - : validateObject(obj, schema, current); -} -/** - * Validate given object against given schema. - * - * @param {Object} obj Object to validate. - * @param {Object} schema The schema against the given object will be validated. - * @param {Array} current The current path context of given object, useful to validate against subobject. - * @return {Array} Found errors. - */ - -function validateSchema(obj, schema, current) { - return validate(obj, schema, current); -} - -/** - * The option object schema. - * @type {Object} - */ - -const SCHEMA = { - sourcemap: [validators.string(), validators.boolean()], - debug: validators.boolean(), - cwd: validators.string(), - banner: [ - validators.func(), - validators.string(), - validators.object({ - commentStyle: validators.string(), - data: validators.any(), - content: [ - validators.func(), - validators.string(), - validators.object({ - file: validators.string(), - encoding: validators.string(), - }), - ], - }), - ], - thirdParty: [ - validators.func(), - validators.object({ - includePrivate: validators.boolean(), - allow: [ - validators.string(), - validators.func(), - validators.object({ - test: [validators.string(), validators.func()], - failOnUnlicensed: validators.boolean(), - failOnViolation: validators.boolean(), - }), - ], - output: [ - validators.func(), - validators.string(), - validators.object({ - file: validators.string(), - encoding: validators.string(), - template: [validators.string(), validators.func()], - }), - validators.array([ - validators.func(), - validators.string(), - validators.object({ - file: validators.string(), - encoding: validators.string(), - template: [validators.string(), validators.func()], - }), - ]), - ], - }), - ], -}; -/** - * Print warning message to the console. - * - * @param {string} msg Message to log. - * @return {void} - */ - -function warn(msg) { - console.warn(`[${PLUGIN_NAME}] -- ${msg}`); -} -/** - * Validate given option object. - * - * @param {Object} options Option object. - * @return {Array} An array of all errors. - */ - -function doValidation(options) { - return validateSchema(options, SCHEMA); -} -/** - * Validate option object according to pre-defined schema. - * - * @param {Object} options Option object. - * @return {void} - */ - -function validateOptions(options) { - const errors = doValidation(options); - - if (_.isEmpty(errors)) { - return; - } - - const messages = []; - - _.forEach(errors, (e) => { - if (e.type === "object.allowUnknown") { - warn( - `Unknown property: "${formatPath( - e.path - )}", allowed options are: ${_.keys(SCHEMA).join(", ")}.` - ); - } else { - messages.push(e.message); - } - }); - - if (!_.isEmpty(messages)) { - throw new Error( - `[${PLUGIN_NAME}] -- Error during validation of option object: ${messages.join( - " ; " - )}` - ); - } -} -/** - * Normalize and validate option object. - * - * @param {Object} options Option object to validate. - * @return {Object} New normalized options. - */ - -function licensePluginOptions(options) { - validateOptions(options); - return options; -} - -/** - * Normalize license name: - * - Returns `UNLICENSED` for nil parameter. - * - Trim license value. - * - * @param {string} license The license name. - * @return {string} The normalized license name. - */ - -function normalizeLicense(license) { - if (!license) { - return "UNLICENSED"; - } - - return license.trim(); -} -/** - * Check if given license name is the `UNLICENSED` value. - * - * @param {string} license The license to check. - * @return {boolean} `true` if `license` is the UNLICENSED one, `false` otherwise. - */ - -function checkUnlicensed(license) { - return license.toUpperCase() === "UNLICENSED"; -} -/** - * Check if dependency is unlicensed, or not. - * - * @param {Object} dependency The dependency. - * @return {boolean} `true` if dependency does not have any license, `false` otherwise. - */ - -function isUnlicensed(dependency) { - const license = normalizeLicense(dependency.license); - return checkUnlicensed(license); -} -/** - * Check if license dependency is valid according to given SPDX validator pattern. - * - * @param {Object} dependency The dependency. - * @param {string} allow The validator as a SPDX pattern. - * @return {boolean} `true` if dependency license is valid, `false` otherwise. - */ - -function isValid(dependency, allow) { - const license = normalizeLicense(dependency.license); - - if (checkUnlicensed(license)) { - return false; - } - - return spdxExpressionValidate(license) && spdxSatisfies(license, allow); -} - -const licenseValidator = { - isUnlicensed, - isValid, -}; - -/** - * Pre-Defined comment style: - * - * - `regular` stands for "classic" block comment. - * - `ignored` stands for block comment starting with standard prefix ignored by minifier. - * - `slash` stands for "inline" style (i.e `//`). - * - `none` stands for no comment style at all. - * - * @type {Object} - */ - -const COMMENT_STYLES = { - regular: { - start: "/**", - body: " *", - end: " */", - }, - ignored: { - start: "/*!", - body: " *", - end: " */", - }, - slash: { - start: "//", - body: "//", - end: "//", - }, - none: null, -}; -/** - * Compute the comment style to use for given text: - * - If text starts with a block comment, nothing is done (i.e use `none`). - * - Otherwise, use the `regular` style. - * - * @param {string} text The text to comment. - * @return {string} The comment style name. - */ - -function computeDefaultCommentStyle(text) { - const trimmedText = text.trim(); - const start = trimmedText.slice(0, 3); - const startWithComment = start === "/**" || start === "/*!"; - return startWithComment ? "none" : "regular"; -} -/** - * Rollup Plugin. - * @class - */ - -class LicensePlugin { - /** - * Initialize plugin. - * - * @param {Object} options Plugin options. - */ - constructor(options = {}) { - // Plugin name, used by rollup. - this.name = PLUGIN_NAME; // Initialize main options. - - this._options = options; - this._cwd = this._options.cwd || process.cwd(); - this._dependencies = {}; - this._pkg = require(path.join(this._cwd, "package.json")); - this._debug = this._options.debug || false; // SourceMap can now be disable/enable on the plugin. - - this._sourcemap = this._options.sourcemap !== false; // This is a cache storing a directory path to associated package. - // This is an improvement to avoid looking for package information for - // already scanned directory. - - this._cache = {}; - } - /** - * Enable source map. - * - * @return {void} - */ - - disableSourceMap() { - this._sourcemap = false; - } - /** - * Hook triggered by `rollup` to load code from given path file. - * - * This hook is used here to analyze a JavaScript file to extract - * associated `package.json` file and store the main information about - * it (license, author, etc.). - * - * This method is used to analyse all the files added to the final bundle - * to extract license informations. - * - * @param {string} id Module identifier. - * @return {void} - */ - - scanDependency(id) { - if (id.startsWith("\0")) { - id = id.replace(/^\0/, ""); - this.debug(`scanning internal module ${id}`); - } - - this.debug(`scanning ${id}`); // Look for the `package.json` file - - let dir = path.parse(id).dir; - let pkg = null; - const scannedDirs = []; - - while (dir && dir !== this._cwd) { - // Try the cache. - if (_.has(this._cache, dir)) { - pkg = this._cache[dir]; - - if (pkg) { - this.debug(`found package.json in cache (package: ${pkg.name})`); - this.addDependency(pkg); - } - - break; - } - - scannedDirs.push(dir); - const pkgPath = path.join(dir, "package.json"); - const exists = fs.existsSync(pkgPath); - - if (exists) { - this.debug(`found package.json at: ${pkgPath}, read it`); // Read `package.json` file - - const pkgJson = JSON.parse(fs.readFileSync(pkgPath, "utf-8")); // We are probably in a package.json specifying the type of package (module, cjs). - // Nevertheless, if the package name is not defined, we must not use this `package.json` descriptor. - - const license = pkgJson.license || pkgJson.licenses; - const hasLicense = license && license.length > 0; - const name = pkgJson.name; - const isValidPackageName = name && packageNameRegex.test(name); - - if (isValidPackageName || hasLicense) { - // We found it! - pkg = pkgJson; // Read license file, if it exists. - - const licenseFile = glob.sync(path.join(dir, "LICENSE*"))[0]; - - if (licenseFile) { - pkg.licenseText = fs.readFileSync(licenseFile, "utf-8"); - } // Add the new dependency to the set of third-party dependencies. - - this.addDependency(pkg); // We can stop now. - - break; - } - } // Go up in the directory tree. - - dir = path.normalize(path.join(dir, "..")); - } // Update the cache - - _.forEach(scannedDirs, (scannedDir) => { - this._cache[scannedDir] = pkg; - }); - } - /** - * Hook triggered by `rollup` to load code from given path file. - * - * @param {Object} dependencies List of modules included in the final bundle. - * @return {void} - */ - - scanDependencies(dependencies) { - this.debug(`Scanning: ${dependencies}`); - - _.forEach(dependencies, (dependency) => { - this.scanDependency(dependency); - }); - } - /** - * Hook triggered by `rollup` to transform the final generated bundle. - * This hook is used here to prepend the license banner to the final bundle. - * - * @param {string} code The bundle content. - * @param {boolean} sourcemap If sourcemap must be generated. - * @return {Object} The result containing the code and, optionnally, the source map - * if it has been enabled (using `enableSourceMap` method). - */ - - prependBanner(code, sourcemap) { - // Create a magicString: do not manipulate the string directly since it - // will be used to generate the sourcemap. - const magicString = new MagicString(code); - const banner = this._options.banner; - - const content = this._readBanner(banner); - - if (content) { - magicString.prepend(EOL); - magicString.prepend(this._generateBanner(content, banner)); - } - - const result = { - code: magicString.toString(), - }; - - if (this._sourcemap !== false && sourcemap !== false) { - result.map = magicString.generateMap({ - hires: true, - }); - } - - return result; - } - /** - * Add new dependency to the bundle descriptor. - * - * @param {Object} pkg Dependency package information. - * @return {void} - */ - - addDependency(pkg) { - const name = pkg.name; - - if (!name) { - this.warn("Trying to add dependency without any name, skipping it."); - } else if (!_.has(this._dependencies, name)) { - this._dependencies[name] = new Dependency(pkg); - } - } - /** - * Scan third-party dependencies, and: - * - Warn for license violations. - * - Generate summary. - * - * @param {boolean} includePrivate Flag that can be used to include / exclude private dependencies. - * @return {void} - */ - - scanThirdParties() { - const thirdParty = this._options.thirdParty; - - if (!thirdParty) { - return; - } - - const includePrivate = thirdParty.includePrivate || false; - - const outputDependencies = _.chain(this._dependencies) - .values() - .filter((dependency) => includePrivate || !dependency.private) - .value(); - - if (_.isFunction(thirdParty)) { - return thirdParty(outputDependencies); - } - - const allow = thirdParty.allow; - - if (allow) { - this._scanLicenseViolations(outputDependencies, allow); - } - - const output = thirdParty.output; - - if (output) { - this._exportThirdParties(outputDependencies, output); - } - } - /** - * Log debug message if debug mode is enabled. - * - * @param {string} msg Log message. - * @return {void} - */ - - debug(msg) { - if (this._debug) { - console.debug(`[${this.name}] -- ${msg}`); - } - } - /** - * Log warn message. - * - * @param {string} msg Log message. - * @return {void} - */ - - warn(msg) { - console.warn(`[${this.name}] -- ${msg}`); - } - /** - * Read banner from given options and returns it. - * - * @param {Object|string} banner Banner as a raw string, or banner options. - * @return {string|null} The banner template. - * @private - */ - - _readBanner(banner) { - if (_.isNil(banner)) { - return null; - } // Banner can be defined as a simple inline string. - - if (_.isString(banner)) { - this.debug("prepend banner from raw string"); - return banner; - } // Extract banner content. - - const content = _.result(banner, "content"); // Content can be an inline string. - - if (_.isString(content)) { - this.debug("prepend banner from content raw string"); - return content; - } // Otherwise, file must be defined (if not, that's an error). - - if (!_.has(content, "file")) { - throw new Error( - `[${this.name}] -- Cannot find banner content, please specify an inline content, or a path to a file` - ); - } - - const file = content.file; - const encoding = content.encoding || "utf-8"; - this.debug(`prepend banner from file: ${file}`); - this.debug(`use encoding: ${encoding}`); - const filePath = path.resolve(file); - const exists = fs.existsSync(filePath); // Fail fast if file does not exist. - - if (!exists) { - throw new Error( - `[${this.name}] -- Template file ${filePath} does not exist, or cannot be read` - ); - } - - return fs.readFileSync(filePath, encoding); - } - /** - * Generate banner output from given raw string and given options. - * - * Banner output will be a JavaScript comment block, comment style may be customized using - * the `commentStyle` option. - * - * @param {string} content Banner content, as a raw string. - * @param {Object} banner Banner options. - * @return {string} The banner output. - * @private - */ - - _generateBanner(content, banner) { - // Create the template function with lodash. - const tmpl = _.template(content); // Generate the banner. - - const pkg = this._pkg; - - const dependencies = _.values(this._dependencies); - - const data = banner.data ? _.result(banner, "data") : {}; - const text = tmpl({ - _, - moment, - pkg, - dependencies, - data, - }); // Compute comment style to use. - - const style = _.has(banner, "commentStyle") - ? banner.commentStyle - : computeDefaultCommentStyle(text); // Ensure given style name is valid. - - if (!_.has(COMMENT_STYLES, style)) { - throw new Error( - `Unknown comment style ${style}, please use one of: ${_.keys( - COMMENT_STYLES - )}` - ); - } - - this.debug(`generate banner using comment style: ${style}`); - return COMMENT_STYLES[style] - ? generateBlockComment(text, COMMENT_STYLES[style]) - : text; - } - /** - * Scan for dependency violations and print a warning if some violations are found. - * - * @param {Array} outputDependencies The dependencies to scan. - * @param {string} allow The allowed licenses as a SPDX pattern. - * @return {void} - */ - - _scanLicenseViolations(outputDependencies, allow) { - _.forEach(outputDependencies, (dependency) => { - this._scanLicenseViolation(dependency, allow); - }); - } - /** - * Scan dependency for a dependency violation. - * - * @param {Object} dependency The dependency to scan. - * @param {string|function|object} allow The allowed licenses as a SPDX pattern, or a validator function. - * @return {void} - */ - - _scanLicenseViolation(dependency, allow) { - const testFn = - _.isString(allow) || _.isFunction(allow) ? allow : allow.test; - const isValid = _.isFunction(testFn) - ? testFn(dependency) - : licenseValidator.isValid(dependency, testFn); - - if (!isValid) { - const failOnUnlicensed = allow.failOnUnlicensed === true; - const failOnViolation = allow.failOnViolation === true; - - this._handleInvalidLicense(dependency, failOnUnlicensed, failOnViolation); - } - } - /** - * Handle invalid dependency: - * - Print a warning for unlicensed dependency. - * - Print a warning for dependency violation. - * - * @param {Object} dependency The dependency to scan. - * @param {boolean} failOnUnlicensed `true` to fail on unlicensed dependency, `false` otherwise. - * @param {boolean} failOnViolation `true` to fail on license violation, `false` otherwise. - * @return {void} - */ - - _handleInvalidLicense(dependency, failOnUnlicensed, failOnViolation) { - if (licenseValidator.isUnlicensed(dependency)) { - this._handleUnlicensedDependency(dependency, failOnUnlicensed); - } else { - this._handleLicenseViolation(dependency, failOnViolation); - } - } - /** - * Handle unlicensed dependency: print a warning to the console to alert for the dependency - * that should be fixed. - * - * @param {Object} dependency The dependency. - * @param {boolean} fail `true` to fail instead of emitting a simple warning. - * @return {void} - */ - - _handleUnlicensedDependency(dependency, fail) { - const message = `Dependency "${dependency.name}" does not specify any license.`; - - if (!fail) { - this.warn(message); - } else { - throw new Error(message); - } - } - /** - * Handle license violation: print a warning to the console to alert about the violation. - * - * @param {Object} dependency The dependency. - * @param {boolean} fail `true` to fail instead of emitting a simple warning. - * @return {void} - */ - - _handleLicenseViolation(dependency, fail) { - const message = - `Dependency "${dependency.name}" has a license (${dependency.license}) which is not compatible with ` + - `requirement, looks like a license violation to fix.`; - - if (!fail) { - this.warn(message); - } else { - throw new Error(message); - } - } - /** - * Export scanned third party dependencies to a destination output (a function, a - * file written to disk, etc.). - * - * @param {Array} outputDependencies The dependencies to include in the output. - * @param {Object|function|string|Array} outputs The output (or the array of output) destination. - * @return {void} - */ - - _exportThirdParties(outputDependencies, outputs) { - _.forEach(_.castArray(outputs), (output) => { - this._exportThirdPartiesToOutput(outputDependencies, output); - }); - } - /** - * Export scanned third party dependencies to a destination output (a function, a - * file written to disk, etc.). - * - * @param {Array} outputDependencies The dependencies to include in the output. - * @param {Array} output The output destination. - * @return {void} - */ - - _exportThirdPartiesToOutput(outputDependencies, output) { - if (_.isFunction(output)) { - return output(outputDependencies); - } // Default is to export to given file. - // Allow custom formatting of output using given template option. - - const template = _.isString(output.template) - ? (dependencies) => - _.template(output.template)({ - dependencies, - _, - moment, - }) - : output.template; - - const defaultTemplate = (dependencies) => - _.isEmpty(dependencies) - ? "No third parties dependencies" - : _.map(dependencies, (d) => d.text()).join( - `${EOL}${EOL}---${EOL}${EOL}` - ); - - const text = _.isFunction(template) - ? template(outputDependencies) - : defaultTemplate(outputDependencies); - - const isOutputFile = _.isString(output); - - const file = isOutputFile ? output : output.file; - const encoding = isOutputFile ? "utf-8" : output.encoding || "utf-8"; - this.debug(`exporting third-party summary to ${file}`); - this.debug(`use encoding: ${encoding}`); // Create directory if it does not already exist. - - mkdirp.sync(path.parse(file).dir); - fs.writeFileSync(file, (text || "").trim(), { - encoding, - }); - } -} -/** - * Create new `rollup-plugin-license` instance with given - * options. - * - * @param {Object} options Option object. - * @return {LicensePlugin} The new instance. - */ - -function licensePlugin(options) { - return new LicensePlugin(licensePluginOptions(options)); -} - -/** - * Create rollup plugin compatible with rollup >= 1.0.0 - * - * @param {Object} options Plugin options. - * @return {Object} Plugin instance. - */ - -function rollupPluginLicense(options = {}) { - const plugin = licensePlugin(options); - return { - /** - * Name of the plugin, used automatically by rollup. - * @type {string} - */ - name: plugin.name, - - /** - * Function called by rollup when the final bundle is generated: it is used - * to prepend the banner file on the generated bundle. - * - * @param {string} code Bundle content. - * @param {Object} chunk The chunk being generated. - * @param {Object} outputOptions The options for the generated output. - * @return {void} - */ - renderChunk(code, chunk, outputOptions = {}) { - plugin.scanDependencies( - _.chain(chunk.modules) - .toPairs() - .reject((mod) => mod[1].isAsset) - .filter((mod) => mod[1].renderedLength > 0) - .map((mod) => mod[0]) - .value() - ); - return plugin.prependBanner(code, outputOptions.sourcemap !== false); - }, - - /** - * Function called by rollup when the final bundle will be written on disk: it - * is used to generate a file containing a summary of all third-party dependencies - * with license information. - * - * @return {void} - */ - generateBundle() { - plugin.scanThirdParties(); - }, - }; -} - -module.exports = rollupPluginLicense;