@arco-plugins/utils
Version:
utils for arco design plugins
123 lines (122 loc) • 4.05 kB
JavaScript
;
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;