diff --git a/dist/index.d.ts b/dist/index.d.ts deleted file mode 100644 index 305449e1..00000000 --- a/dist/index.d.ts +++ /dev/null @@ -1,333 +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. - */ - -import type {Plugin} from 'rollup'; - -type FilePath = string; -type FileEncoding = string; -type FactoryFn = () => T; -type Factory = T | FactoryFn; - -/** - * A person, as described in NPM documentation. - * - * @see https://docs.npmjs.com/cli/v7/configuring-npm/package-json#people-fields-author-contributors - */ -export interface Person { - /** - * Person Name. - */ - readonly name: string; - - /** - * Person Email. - */ - readonly email: string | null; - - /** - * Person URL. - */ - readonly url: string | null; - - /** - * Turns the person into a formatted string - * @returns formatted person info - */ - text: () => string; -} - -/** - * @see {@link https://github.com/mjeanroy/rollup-plugin-license#comment-style} - */ -export type CommentStyle = 'regular' | 'ignored' | 'slash'; - -/** - * Banner content descriptor. - */ -interface BannerContentOptions { - /** - * File to get banner content from. - */ - file: FilePath; - - /** - * File encoding. - * @default utf-8 - */ - encoding?: FileEncoding; -} - -/** - * Banner content, can be: - * - A raw string, evaluated as a (lodash) template. - * - A file description, the content being read and evaluated as a (lodash) template. - */ -type BannerContent = string | BannerContentOptions; - -/** - * Data injected during banner "rendering" (i.e evaluated as template - * model). - */ -interface BannerContentData { - [key: string]: any; -} - -/** - * Banner Options. - */ -interface BannerOptions { - content: Factory; - commentStyle?: CommentStyle; - data?: Factory; -} - -export type Banner = string | BannerOptions; - -/** - * Dependency Repository Description. - */ -interface DependencyRepository { - /** - * Repository URL. - */ - readonly url: string; - - /** - * Repository Type (git, svn, etc.). - */ - readonly type: string; -} - -/** - * Dependency information is derived from the package.json file - */ -export interface Dependency { - /** - * Dependency Name. - */ - readonly name: string | null; - - /** - * Dependency Maintainers list. - */ - readonly maintainers: string[]; - - /** - * Dependency Version. - */ - readonly version: string | null; - - /** - * Dependency Description. - */ - readonly description: string | null; - - /** - * Dependency Repository Location. - */ - readonly repository: string | DependencyRepository | null; - - /** - * Repository Public Homepage. - */ - readonly homepage: string | null; - - /** - * If dependency is private. - */ - readonly private: boolean; - - /** - * SPDX License short ID. - */ - readonly license: string | null; - - /** - * Full License file text. - */ - readonly licenseText: string | null; - - /** - * Author information. - */ - readonly author: Person | null; - - /** - * Dependency Contributes list. - */ - readonly contributors: Person[]; - - /** - * Turns the dependency into a formatted string - * @returns formatted dependency license info - */ - text: () => string; -} - -/** - * SPDX Licence Identifier. - */ -type SpdxId = string; - -/** - * Function checking dependency license validity. - */ -type ThirdPartyDependencyValidatorFn = (Dependency: Dependency) => boolean; - -type ThirdPartyValidator = SpdxId | ThirdPartyDependencyValidatorFn; - -interface ThirdPartyAllowOptions { - /** - * Testing if the license if valid - */ - test: ThirdPartyValidator; - - /** - * Fail if a dependency does not specify any licenses - * @default false - */ - failOnUnlicensed?: boolean; - - /** - * Fail if a dependency specify a license that does not match given requirement - * @default false - */ - failOnViolation?: boolean; -} - -/** - * Output generator: may write a file to disk, or something else as long as it is a - * synchronous operation. - */ -type ThirdPartyOutputGeneratorFn = (dependencies: Dependency[]) => void; - -/** - * Template as a raw string. - */ -type ThirdPartyOutputTemplate = string; - -/** - * Template function. - */ -type ThirdPartyOutputTemplateFn = (dependencies: Dependency[]) => void; - -/** - * Third Party output options object. - */ -interface ThirdPartyOutputOptions { - /** - * Name of file to write licenses to - */ - file: FilePath; - - /** - * @default utf-8 - */ - encoding?: FileEncoding; - - /** - * Template function that can be defined to customize report output. - * - * @example - * template(dependencies) { - * return dependencies.map((dependency) => ( - * `${dependency.name}:${dependency.version} -- ${dependency.license}`).join('\n') - * ); - * }, - * - * // Lodash template that can be defined to customize report output - * template: ` - * <% _.forEach(dependencies, function (dependency) { %> - * <%= dependency.name %>:<%= dependency.version%> -- <%= dependency.license %> - * <% }) %> - * ` - */ - template?: ThirdPartyOutputTemplate | ThirdPartyOutputTemplateFn; -} - -type ThirdPartyOutput = FilePath | ThirdPartyOutputGeneratorFn | ThirdPartyOutputOptions; - -interface ThirdPartyOptions { - /** - * Output for third party report. - */ - output: ThirdPartyOutput | ThirdPartyOutput[]; - - /** - * If private dependencies should be checked (`private: true` in package.json) - * @default false - */ - includePrivate?: boolean; - - /** - * Ensures that dependencies does not violate any license restriction. - * - * For example, suppose you want to limit dependencies with MIT or Apache-2.0 - * licenses, simply define the restriction: - * - * @example - * { - * allow: '(MIT OR Apache-2.0)' - * } - * - * allow(dependency) { - * return dependency.license === 'MIT'; - * } - */ - allow?: ThirdPartyValidator | ThirdPartyAllowOptions; -} - -export type ThirdParty = ThirdPartyOutputGeneratorFn | ThirdPartyOptions; - -export interface Options { - sourcemap?: boolean | string; - - /** - * Debug mode - * @default false - */ - debug?: boolean; - - /** - * Current Working Directory - * @default process.cwd() - */ - cwd?: string; - - /** - * License banner to place at the top of your bundle - */ - banner?: Factory; - - /** - * For third party dependencies. - * Creates a file containing a summary of all dependencies can be generated - * automatically - */ - thirdParty?: ThirdParty; -} - -declare function rollupPluginLicense(options: Options): Plugin; - -export default rollupPluginLicense; diff --git a/dist/index.js b/dist/index.js deleted file mode 100644 index ed178554..00000000 --- a/dist/index.js +++ /dev/null @@ -1,1393 +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"; - -var _ = require("lodash"); -var fs = require("fs"); -var path = require("path"); -var mkdirp = require("mkdirp"); -var moment = require("moment"); -var MagicString = require("magic-string"); -var glob = require("glob"); -var packageNameRegex = require("package-name-regex"); -var commenting = require("commenting"); -var spdxExpressionValidate = require("spdx-expression-validate"); -var spdxSatisfies = require("spdx-satisfies"); - -function _interopDefaultLegacy(e) { - return e && typeof e === "object" && "default" in e ? e : { default: e }; -} - -var ___default = /*#__PURE__*/ _interopDefaultLegacy(_); -var fs__default = /*#__PURE__*/ _interopDefaultLegacy(fs); -var path__default = /*#__PURE__*/ _interopDefaultLegacy(path); -var mkdirp__default = /*#__PURE__*/ _interopDefaultLegacy(mkdirp); -var moment__default = /*#__PURE__*/ _interopDefaultLegacy(moment); -var MagicString__default = /*#__PURE__*/ _interopDefaultLegacy(MagicString); -var glob__default = /*#__PURE__*/ _interopDefaultLegacy(glob); -var packageNameRegex__default = - /*#__PURE__*/ _interopDefaultLegacy(packageNameRegex); -var commenting__default = /*#__PURE__*/ _interopDefaultLegacy(commenting); -var spdxExpressionValidate__default = /*#__PURE__*/ _interopDefaultLegacy( - spdxExpressionValidate -); -var spdxSatisfies__default = /*#__PURE__*/ _interopDefaultLegacy(spdxSatisfies); - -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 (___default["default"].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; - } - } - - ___default["default"].forEach(["name", "email", "url"], (prop) => { - if (___default["default"].has(o, prop)) { - o[prop] = ___default["default"].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) - * - * @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 = ___default["default"].map( - ___default["default"].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 = `(${___default["default"] - .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 (!___default["default"].isEmpty(this.contributors)) { - lines.push(`Contributors:`); - - const allContributors = ___default["default"] - .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__default["default"].Style( - commentStyle.body, - commentStyle.start, - commentStyle.end - ); - } - - return commenting__default["default"](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 ___default["default"].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 ___default["default"].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 ___default["default"].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 ___default["default"].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 ___default["default"].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 ___default["default"].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 ( - ___default["default"].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 = ""; - - ___default["default"].forEach(paths, (p) => { - if (___default["default"].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 = ___default["default"].castArray(schema); - - const matchedValidators = ___default["default"].filter( - validators, - (validator) => validator.test(value) - ); // No one matched, we can stop here and return an error with a proper message. - - if (___default["default"].isEmpty(matchedValidators)) { - return [ - { - path, - message: ___default["default"] - .map( - validators, - (validator) => `"${formatPath(path)}" ${validator.message}` - ) - .join(" OR "), - }, - ]; - } // Run "sub-validators" - - return ___default["default"] - .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 = []; - - ___default["default"].forEach(obj, (value, k) => { - if (___default["default"].isNil(value)) { - return; - } - - const path = [...current, k]; - - if (!___default["default"].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 (___default["default"].isUndefined(item)) { - return [ - { - path, - message: `"${formatPath(path)}" is undefined.`, - }, - ]; - } - - if (___default["default"].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 ___default["default"] - .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 ___default["default"].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 (___default["default"].isEmpty(errors)) { - return; - } - - const messages = []; - - ___default["default"].forEach(errors, (e) => { - if (e.type === "object.allowUnknown") { - warn( - `Unknown property: "${formatPath( - e.path - )}", allowed options are: ${___default["default"] - .keys(SCHEMA) - .join(", ")}.` - ); - } else { - messages.push(e.message); - } - }); - - if (!___default["default"].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__default["default"](license) && - spdxSatisfies__default["default"](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__default["default"].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__default["default"].parse(id).dir; - let pkg = null; - const scannedDirs = []; - - while (dir && dir !== this._cwd && !scannedDirs.includes(dir)) { - // Try the cache. - if (___default["default"].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__default["default"].join(dir, "package.json"); - const exists = fs__default["default"].existsSync(pkgPath); - - if (exists) { - this.debug(`found package.json at: ${pkgPath}, read it`); // Read `package.json` file - - const pkgJson = JSON.parse( - fs__default["default"].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__default["default"].test(name); - - if (isValidPackageName || hasLicense) { - // We found it! - pkg = pkgJson; // Read license file, if it exists. - - const cwd = this._cwd || process.cwd(); - const absolutePath = path__default["default"].join( - dir, - "[lL][iI][cC][eE][nN][cCsS][eE]*" - ); - const relativeToCwd = path__default["default"].relative( - cwd, - absolutePath - ); - - const licenseFile = this._findGlob(relativeToCwd, cwd)[0]; - - if (licenseFile) { - pkg.licenseText = fs__default["default"].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__default["default"].normalize( - path__default["default"].join(dir, "..") - ); - } // Update the cache - - ___default["default"].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}`); - - ___default["default"].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__default["default"](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 (!___default["default"].has(this._dependencies, name)) { - this._dependencies[name] = new Dependency(pkg); - } - } - /** - * Scan third-party dependencies, and: - * - Warn for license violations. - * - Generate summary. - * - * @return {void} - */ - - scanThirdParties() { - const thirdParty = this._options.thirdParty; - - if (!thirdParty) { - return; - } - - const includePrivate = thirdParty.includePrivate || false; - - const outputDependencies = ___default["default"] - .chain(this._dependencies) - .values() - .filter((dependency) => includePrivate || !dependency.private) - .value(); - - if (___default["default"].isFunction(thirdParty)) { - thirdParty(outputDependencies); - return; - } - - 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}`); - } - /** - * Find given file, matching given pattern. - * - * @param {string} pattern Pattern to look for. - * @param {string} cwd Working directory. - * @returns {*} All match. - * @private - */ - - _findGlob(pattern, cwd) { - return glob__default["default"].sync(pattern, { - cwd, - }); - } - /** - * 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 (___default["default"].isNil(banner)) { - return null; - } // Banner can be defined as a simple inline string. - - if (___default["default"].isString(banner)) { - this.debug("prepend banner from raw string"); - return banner; - } // Extract banner content. - - const content = ___default["default"].result(banner, "content"); // Content can be an inline string. - - if (___default["default"].isString(content)) { - this.debug("prepend banner from content raw string"); - return content; - } // Otherwise, file must be defined (if not, that's an error). - - if (!___default["default"].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__default["default"].resolve(file); - const exists = fs__default["default"].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__default["default"].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 = ___default["default"].template(content); // Generate the banner. - - const pkg = this._pkg; - - const dependencies = ___default["default"].values(this._dependencies); - - const data = banner.data - ? ___default["default"].result(banner, "data") - : {}; - const text = tmpl({ - _: ___default["default"], - moment: moment__default["default"], - pkg, - dependencies, - data, - }); // Compute comment style to use. - - const style = ___default["default"].has(banner, "commentStyle") - ? banner.commentStyle - : computeDefaultCommentStyle(text); // Ensure given style name is valid. - - if (!___default["default"].has(COMMENT_STYLES, style)) { - throw new Error( - `Unknown comment style ${style}, please use one of: ${___default[ - "default" - ].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) { - ___default["default"].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 = - ___default["default"].isString(allow) || - ___default["default"].isFunction(allow) - ? allow - : allow.test; - const isValid = ___default["default"].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) { - ___default["default"].forEach( - ___default["default"].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 (___default["default"].isFunction(output)) { - output(outputDependencies); - return; - } // Default is to export to given file. - // Allow custom formatting of output using given template option. - - const template = ___default["default"].isString(output.template) - ? (dependencies) => - ___default["default"].template(output.template)({ - dependencies, - _: ___default["default"], - moment: moment__default["default"], - }) - : output.template; - - const defaultTemplate = (dependencies) => - ___default["default"].isEmpty(dependencies) - ? "No third parties dependencies" - : ___default["default"] - .map(dependencies, (d) => d.text()) - .join(`${EOL}${EOL}---${EOL}${EOL}`); - - const text = ___default["default"].isFunction(template) - ? template(outputDependencies) - : defaultTemplate(outputDependencies); - - const isOutputFile = ___default["default"].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__default["default"].sync(path__default["default"].parse(file).dir); - fs__default["default"].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( - ___default["default"] - .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;