| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109 | /** * @author Toru Nagashima * See LICENSE file in root directory for full license. */"use strict"const path = require("path")const { Minimatch } = require("minimatch")/** @typedef {import("../util/import-target")} ImportTarget *//** * @typedef {Object} DefinitionData * @property {string | string[]} name The name to disallow. * @property {string} [message] The custom message to show. *//** * Check if matched or not. * @param {InstanceType<Minimatch>} matcher The matcher. * @param {boolean} absolute The flag that the matcher is for absolute paths. * @param {ImportTarget} importee The importee information. */function match(matcher, absolute, { filePath, name }) {    if (absolute) {        return filePath != null && matcher.match(filePath)    }    return matcher.match(name)}/** Restriction. */class Restriction {    /**     * Initialize this restriction.     * @param {DefinitionData} def The definition of a restriction.     */    constructor({ name, message }) {        const names = Array.isArray(name) ? name : [name]        const matchers = names.map(raw => {            const negate = raw[0] === "!" && raw[1] !== "("            const pattern = negate ? raw.slice(1) : raw            const absolute = path.isAbsolute(pattern)            const matcher = new Minimatch(pattern, { dot: true })            return { absolute, matcher, negate }        })        this.matchers = matchers        this.message = message ? ` ${message}` : ""    }    /**     * Check if a given importee is disallowed.     * @param {ImportTarget} importee The importee to check.     * @returns {boolean} `true` if the importee is disallowed.     */    match(importee) {        return this.matchers.reduce(            (ret, { absolute, matcher, negate }) =>                negate                    ? ret && !match(matcher, absolute, importee)                    : ret || match(matcher, absolute, importee),            false        )    }}/** * Create a restriction. * @param {string | DefinitionData} def A definition. * @returns {Restriction} Created restriction. */function createRestriction(def) {    if (typeof def === "string") {        return new Restriction({ name: def })    }    return new Restriction(def)}/** * Create restrictions. * @param {(string | DefinitionData | GlobDefinition)[]} defs Definitions. * @returns {(Restriction | GlobRestriction)[]} Created restrictions. */function createRestrictions(defs) {    return (defs || []).map(createRestriction)}/** * Checks if given importees are disallowed or not. * @param {RuleContext} context - A context to report. * @param {ImportTarget[]} targets - A list of target information to check. * @returns {void} */module.exports = function checkForRestriction(context, targets) {    const restrictions = createRestrictions(context.options[0])    for (const target of targets) {        const restriction = restrictions.find(r => r.match(target))        if (restriction) {            context.report({                node: target.node,                messageId: "restricted",                data: {                    name: target.name,                    customMessage: restriction.message,                },            })        }    }}
 |