kjelsrud.dev/node_modules/astro/dist/content/vite-plugin-content-virtual-mod.js

179 lines
6 KiB
JavaScript
Raw Normal View History

2023-07-19 21:31:30 +02:00
import glob from "fast-glob";
import fsMod from "node:fs";
import { extname } from "node:path";
import { fileURLToPath, pathToFileURL } from "node:url";
import pLimit from "p-limit";
import { AstroError, AstroErrorData } from "../core/errors/index.js";
import { appendForwardSlash } from "../core/path.js";
import { rootRelativePath } from "../core/util.js";
import { VIRTUAL_MODULE_ID } from "./consts.js";
import {
getContentEntryIdAndSlug,
getContentPaths,
getDataEntryExts,
getDataEntryId,
getEntryCollectionName,
getEntryConfigByExtMap,
getEntrySlug,
getEntryType,
getExtGlob
} from "./utils.js";
function astroContentVirtualModPlugin({
settings
}) {
const contentPaths = getContentPaths(settings.config);
const relContentDir = rootRelativePath(settings.config.root, contentPaths.contentDir);
const contentEntryConfigByExt = getEntryConfigByExtMap(settings.contentEntryTypes);
const contentEntryExts = [...contentEntryConfigByExt.keys()];
const dataEntryExts = getDataEntryExts(settings);
const virtualModContents = fsMod.readFileSync(contentPaths.virtualModTemplate, "utf-8").replace(
"@@COLLECTION_NAME_BY_REFERENCE_KEY@@",
new URL("reference-map.json", contentPaths.cacheDir).pathname
).replace("@@CONTENT_DIR@@", relContentDir).replace(
"'@@CONTENT_ENTRY_GLOB_PATH@@'",
JSON.stringify(globWithUnderscoresIgnored(relContentDir, contentEntryExts))
).replace(
"'@@DATA_ENTRY_GLOB_PATH@@'",
JSON.stringify(globWithUnderscoresIgnored(relContentDir, dataEntryExts))
).replace(
"'@@RENDER_ENTRY_GLOB_PATH@@'",
JSON.stringify(
globWithUnderscoresIgnored(
relContentDir,
/** Note: data collections excluded */
contentEntryExts
)
)
);
const astroContentVirtualModuleId = "\0" + VIRTUAL_MODULE_ID;
return {
name: "astro-content-virtual-mod-plugin",
resolveId(id) {
if (id === VIRTUAL_MODULE_ID) {
return astroContentVirtualModuleId;
}
},
async load(id) {
if (id === astroContentVirtualModuleId) {
const stringifiedLookupMap = await getStringifiedLookupMap({
fs: fsMod,
contentPaths,
contentEntryConfigByExt,
dataEntryExts,
root: settings.config.root
});
return {
code: virtualModContents.replace(
"/* @@LOOKUP_MAP_ASSIGNMENT@@ */",
`lookupMap = ${stringifiedLookupMap};`
)
};
}
}
};
}
async function getStringifiedLookupMap({
contentPaths,
contentEntryConfigByExt,
dataEntryExts,
root,
fs
}) {
const { contentDir } = contentPaths;
const relContentDir = rootRelativePath(root, contentDir, false);
const contentEntryExts = [...contentEntryConfigByExt.keys()];
let lookupMap = {};
const contentGlob = await glob(
`${relContentDir}**/*${getExtGlob([...dataEntryExts, ...contentEntryExts])}`,
{
absolute: true,
cwd: fileURLToPath(root),
fs: {
readdir: fs.readdir.bind(fs),
readdirSync: fs.readdirSync.bind(fs)
}
}
);
const limit = pLimit(10);
const promises = [];
for (const filePath of contentGlob) {
promises.push(
limit(async () => {
var _a, _b, _c, _d, _e;
const entryType = getEntryType(filePath, contentPaths, contentEntryExts, dataEntryExts);
if (entryType !== "content" && entryType !== "data")
return;
const collection = getEntryCollectionName({ contentDir, entry: pathToFileURL(filePath) });
if (!collection)
throw UnexpectedLookupMapError;
if (((_a = lookupMap[collection]) == null ? void 0 : _a.type) && lookupMap[collection].type !== entryType) {
throw new AstroError({
...AstroErrorData.MixedContentDataCollectionError,
message: AstroErrorData.MixedContentDataCollectionError.message(collection)
});
}
if (entryType === "content") {
const contentEntryType = contentEntryConfigByExt.get(extname(filePath));
if (!contentEntryType)
throw UnexpectedLookupMapError;
const { id, slug: generatedSlug } = await getContentEntryIdAndSlug({
entry: pathToFileURL(filePath),
contentDir,
collection
});
const slug = await getEntrySlug({
id,
collection,
generatedSlug,
fs,
fileUrl: pathToFileURL(filePath),
contentEntryType
});
if ((_c = (_b = lookupMap[collection]) == null ? void 0 : _b.entries) == null ? void 0 : _c[slug]) {
throw new AstroError({
...AstroErrorData.DuplicateContentEntrySlugError,
message: AstroErrorData.DuplicateContentEntrySlugError.message(collection, slug),
hint: slug !== generatedSlug ? `Check the \`slug\` frontmatter property in **${id}**.` : void 0
});
}
lookupMap[collection] = {
type: "content",
entries: {
...(_d = lookupMap[collection]) == null ? void 0 : _d.entries,
[slug]: rootRelativePath(root, filePath)
}
};
} else {
const id = getDataEntryId({ entry: pathToFileURL(filePath), contentDir, collection });
lookupMap[collection] = {
type: "data",
entries: {
...(_e = lookupMap[collection]) == null ? void 0 : _e.entries,
[id]: rootRelativePath(root, filePath)
}
};
}
})
);
}
await Promise.all(promises);
return JSON.stringify(lookupMap);
}
const UnexpectedLookupMapError = new AstroError({
...AstroErrorData.UnknownContentCollectionError,
message: `Unexpected error while parsing content entry IDs and slugs.`
});
function globWithUnderscoresIgnored(relContentDir, exts) {
const extGlob = getExtGlob(exts);
const contentDir = appendForwardSlash(relContentDir);
return [
`${contentDir}**/*${extGlob}`,
`!${contentDir}**/_*/**${extGlob}`,
`!${contentDir}**/_*${extGlob}`
];
}
export {
astroContentVirtualModPlugin,
getStringifiedLookupMap
};