feat(core): allow sourcing from multiple static directories (#4095)

* [WIP] Implementaion of multiple directory static sourcing

* Move default to validation

* Update test

* Refactor

* Port to MDX loader

* Fix

* Move dogfooding assets

* Doc writeup

* Restore assets

* Support absolute paths

* Dogfood absolute path

* Fix

* More tests

* Fix snapshots

Co-authored-by: Joshua Chen <sidachen2003@gmail.com>
This commit is contained in:
Oliver Ullman 2021-11-18 11:26:26 -03:00 committed by GitHub
parent 3f18c928bb
commit 1366c31201
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
43 changed files with 238 additions and 181 deletions

View file

@ -27,7 +27,8 @@ const hashRegex = /#.*$/;
interface PluginOptions {
filePath: string;
staticDir: string;
staticDirs: string[];
siteDir: string;
}
async function ensureAssetFileExist(
@ -81,11 +82,10 @@ function toAssetRequireNode({
// If the link looks like an asset link, we'll link to the asset,
// and use a require("assetUrl") (using webpack url-loader/file-loader)
// instead of navigating to such link
async function convertToAssetLinkIfNeeded({
node,
staticDir,
filePath,
}: {node: Link} & PluginOptions) {
async function convertToAssetLinkIfNeeded(
node: Link,
{filePath, siteDir, staticDirs}: PluginOptions,
) {
const assetPath = node.url.replace(hashRegex, '');
const hasSiteAlias = assetPath.startsWith('@site/');
@ -107,7 +107,6 @@ async function convertToAssetLinkIfNeeded({
}
if (assetPath.startsWith('@site/')) {
const siteDir = path.join(staticDir, '..');
const fileSystemAssetPath = path.join(
siteDir,
assetPath.replace('@site/', ''),
@ -115,9 +114,13 @@ async function convertToAssetLinkIfNeeded({
await ensureAssetFileExist(fileSystemAssetPath, filePath);
toAssetLinkNode(fileSystemAssetPath);
} else if (path.isAbsolute(assetPath)) {
const fileSystemAssetPath = path.join(staticDir, assetPath);
if (await fs.pathExists(fileSystemAssetPath)) {
toAssetLinkNode(fileSystemAssetPath);
// eslint-disable-next-line no-restricted-syntax
for (const staticDir of staticDirs) {
const fileSystemAssetPath = path.join(staticDir, assetPath);
if (await fs.pathExists(fileSystemAssetPath)) {
toAssetLinkNode(fileSystemAssetPath);
return;
}
}
} else {
const fileSystemAssetPath = path.join(path.dirname(filePath), assetPath);
@ -127,11 +130,7 @@ async function convertToAssetLinkIfNeeded({
}
}
async function processLinkNode({
node,
filePath,
staticDir,
}: {node: Link} & PluginOptions) {
async function processLinkNode(node: Link, options: PluginOptions) {
if (!node.url) {
// try to improve error feedback
// see https://github.com/facebook/docusaurus/issues/3309#issuecomment-690371675
@ -139,7 +138,7 @@ async function processLinkNode({
const line = node?.position?.start?.line || '?';
throw new Error(
`Markdown link URL is mandatory in "${toMessageRelativeFilePath(
filePath,
options.filePath,
)}" file (title: ${title}, line: ${line}).`,
);
}
@ -149,14 +148,14 @@ async function processLinkNode({
return;
}
await convertToAssetLinkIfNeeded({node, staticDir, filePath});
await convertToAssetLinkIfNeeded(node, options);
}
const plugin: Plugin<[PluginOptions]> = (options) => {
const transformer: Transformer = async (root) => {
const promises: Promise<void>[] = [];
visit(root, 'link', (node: Link) => {
promises.push(processLinkNode({node, ...options}));
promises.push(processLinkNode(node, options));
});
await Promise.all(promises);
};