UNPKG

@arco-plugins/utils

Version:
123 lines (122 loc) 4.05 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.isMatch = exports.matcher = void 0; const path_1 = require("path"); const lodash_1 = require("lodash"); const micromatch_1 = __importDefault(require("micromatch")); const arrify_1 = require("./arrify"); const UNESCAPED_GLOB_SYMBOLS_RE = /(\\?)([()*?[\]{|}]|^!|[!+@](?=\())/g; const NODE_MODULES_REGEXP = /(\/node_modules\/)/; /** * 替换反斜杠 * @param {string} str * @returns {string} */ function replaceBackslashes(str) { return str.replace(/\\/g, '/'); } /** * 将后缀转为 glob 格式 * @param {string|string[]} patterns * @param {string|string[]} extensions * @returns {string[]} */ function getExtensionsGlob(extensions) { const extensionsGlob = arrify_1.arrify(extensions).map((extension) => extension.replace(/^\./u, '')); const ext = extensionsGlob.length === 1 ? extensionsGlob[0] : `{${extensionsGlob.join(',')}}`; return `**/*.${ext}`; } /** * 将路径转为绝对路径 * @param {string|string[]} paths * @param {string} context * @returns {string[]} */ function absoluteGlobPatterns(patterns, context) { const validContext = `${replaceBackslashes(context).replace(UNESCAPED_GLOB_SYMBOLS_RE, '\\$2')}`; return arrify_1.arrify(patterns).map((p) => path_1.resolve(validContext, replaceBackslashes(p))); } /** * 转为 glob 格式 * @param {string|string[]} patterns * @returns {string[]} */ function parseToGlobPatterns(patterns, context) { return absoluteGlobPatterns(patterns, context).reduce((result, p) => { const isFolder = !path_1.extname(p); const g = isFolder ? p.replace(/[/\\]?$/u, `/**`) : p; result.push(g); if (NODE_MODULES_REGEXP.test(g)) { result.push(g.replace(NODE_MODULES_REGEXP, (_, $1) => `${$1}.pnpm/**${$1}`)); } return result; }, []); } function splitStrAndRegExp(pattern) { const patterns = arrify_1.arrify(pattern); const strings = []; const regExps = []; patterns.forEach((p) => { if (lodash_1.isRegExp(p)) { regExps.push(p); } else if (p && lodash_1.isString(p)) { strings.push(p); } }); return { strings, regExps, }; } /** * 生成文件匹配函数 * @param {string | RegExp | (string | RegExp)[]} pattern * @returns (resource: string) => boolean */ function matcher(pattern, options = {}) { const { extensions = [], cwd, extraGlobPattern = [] } = options; const { strings, regExps } = splitStrAndRegExp(pattern); const patternsForGlob = [ ...arrify_1.arrify(extraGlobPattern), ...(cwd ? strings.reduce((res, p) => { res.push(...parseToGlobPatterns(p, cwd)); return res; }, []) : strings), ]; // 因为 resource中含有 . 符号时候默认会忽略匹配,所以设置 dot: true const globMatchOptions = { dot: true, }; const isMatchGlob = patternsForGlob.length ? (resource) => micromatch_1.default.isMatch(resource, patternsForGlob, globMatchOptions) : () => false; const isMatchRegExp = regExps.length ? (resource) => regExps.some((r) => r.test(resource)) : () => false; const isMatchExt = extensions.length ? micromatch_1.default.matcher(getExtensionsGlob(extensions), globMatchOptions) : () => true; return (resource) => { if (!isMatchExt(resource)) { return false; } return isMatchGlob(resource) || isMatchRegExp(resource); }; } exports.matcher = matcher; /** * 返回是否文件路径匹配 * @param {string} resource * @param {string | RegExp | (string | RegExp)[]} pattern * @returns boolean */ function isMatch(resource, pattern, options = {}) { return matcher(pattern, options)(resource); } exports.isMatch = isMatch;