130 lines
2.8 KiB
JavaScript
130 lines
2.8 KiB
JavaScript
import { glob } from "tinyglobby";
|
|
import { TemplatePath } from "@11ty/eleventy-utils";
|
|
import debugUtil from "debug";
|
|
|
|
import FileSystemRemap from "./Util/GlobRemap.js";
|
|
import { isGlobMatch } from "./Util/GlobMatcher.js";
|
|
|
|
const debug = debugUtil("Eleventy:FileSystemSearch");
|
|
|
|
class FileSystemSearch {
|
|
constructor() {
|
|
this.inputs = {};
|
|
this.outputs = {};
|
|
this.promises = {};
|
|
this.count = 0;
|
|
}
|
|
|
|
getCacheKey(key, globs, options) {
|
|
if (Array.isArray(globs)) {
|
|
globs = globs.sort();
|
|
}
|
|
return key + JSON.stringify(globs) + JSON.stringify(options);
|
|
}
|
|
|
|
// returns a promise
|
|
search(key, globs, options = {}) {
|
|
debug("Glob search (%o) searching for: %o", key, globs);
|
|
|
|
if (!Array.isArray(globs)) {
|
|
globs = [globs];
|
|
}
|
|
|
|
// Strip leading slashes from everything!
|
|
globs = globs.map((entry) => TemplatePath.stripLeadingDotSlash(entry));
|
|
|
|
let cwd = FileSystemRemap.getCwd(globs);
|
|
if (cwd) {
|
|
options.cwd = cwd;
|
|
}
|
|
|
|
if (options.ignore && Array.isArray(options.ignore)) {
|
|
options.ignore = options.ignore.map((entry) => {
|
|
entry = TemplatePath.stripLeadingDotSlash(entry);
|
|
|
|
return FileSystemRemap.remapInput(entry, cwd);
|
|
});
|
|
debug("Glob search (%o) ignoring: %o", key, options.ignore);
|
|
}
|
|
|
|
let cacheKey = this.getCacheKey(key, globs, options);
|
|
|
|
// Only after the promise has resolved
|
|
if (this.outputs[cacheKey]) {
|
|
return Array.from(this.outputs[cacheKey]);
|
|
}
|
|
|
|
if (!this.promises[cacheKey]) {
|
|
this.inputs[cacheKey] = {
|
|
input: globs,
|
|
options,
|
|
};
|
|
|
|
this.count++;
|
|
|
|
globs = globs.map((entry) => {
|
|
if (cwd && entry.startsWith(cwd)) {
|
|
return FileSystemRemap.remapInput(entry, cwd);
|
|
}
|
|
|
|
return entry;
|
|
});
|
|
|
|
this.promises[cacheKey] = glob(
|
|
globs,
|
|
Object.assign(
|
|
{
|
|
caseSensitiveMatch: false, // insensitive
|
|
dot: true,
|
|
},
|
|
options,
|
|
),
|
|
).then((results) => {
|
|
this.outputs[cacheKey] = new Set(
|
|
results.map((entry) => {
|
|
let remapped = FileSystemRemap.remapOutput(entry, options.cwd);
|
|
return TemplatePath.standardizeFilePath(remapped);
|
|
}),
|
|
);
|
|
|
|
return Array.from(this.outputs[cacheKey]);
|
|
});
|
|
}
|
|
|
|
// may be an unresolved promise
|
|
return this.promises[cacheKey];
|
|
}
|
|
|
|
_modify(path, setOperation) {
|
|
path = TemplatePath.stripLeadingDotSlash(path);
|
|
|
|
let normalized = TemplatePath.standardizeFilePath(path);
|
|
|
|
for (let key in this.inputs) {
|
|
let { input, options } = this.inputs[key];
|
|
if (
|
|
isGlobMatch(path, input, {
|
|
ignore: options.ignore,
|
|
})
|
|
) {
|
|
this.outputs[key][setOperation](normalized);
|
|
}
|
|
}
|
|
}
|
|
|
|
add(path) {
|
|
this._modify(path, "add");
|
|
}
|
|
|
|
delete(path) {
|
|
this._modify(path, "delete");
|
|
}
|
|
|
|
// Issue #3859 get rid of chokidar globs
|
|
// getAllOutputFiles() {
|
|
// return Object.values(this.outputs).map(set => Array.from(set)).flat();
|
|
// }
|
|
}
|
|
|
|
export default FileSystemSearch;
|