diff --git a/packages/docusaurus-mdx-loader/src/index.ts b/packages/docusaurus-mdx-loader/src/index.ts
index 1695d81b19..2ffb0e415d 100644
--- a/packages/docusaurus-mdx-loader/src/index.ts
+++ b/packages/docusaurus-mdx-loader/src/index.ts
@@ -36,7 +36,8 @@ const DEFAULT_OPTIONS: RemarkAndRehypePluginOptions = {
};
type Options = RemarkAndRehypePluginOptions & {
- staticDir?: string;
+ staticDirs: string[];
+ siteDir: string;
isMDXPartial?: (filePath: string) => boolean;
isMDXPartialFrontMatterWarningDisabled?: boolean;
removeContentTitle?: boolean;
@@ -123,8 +124,15 @@ export default async function mdxLoader(
remarkPlugins: [
...(reqOptions.beforeDefaultRemarkPlugins || []),
...DEFAULT_OPTIONS.remarkPlugins,
- [transformImage, {staticDir: reqOptions.staticDir, filePath}],
- [transformLinks, {staticDir: reqOptions.staticDir, filePath}],
+ [transformImage, {staticDirs: reqOptions.staticDirs, filePath}],
+ [
+ transformLinks,
+ {
+ staticDirs: reqOptions.staticDirs,
+ filePath,
+ siteDir: reqOptions.siteDir,
+ },
+ ],
...(reqOptions.remarkPlugins || []),
],
rehypePlugins: [
diff --git a/packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/fixtures/fail.md b/packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/fail.md
similarity index 100%
rename from packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/fixtures/fail.md
rename to packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/fail.md
diff --git a/packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/img.md b/packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/img.md
new file mode 100644
index 0000000000..38e15cd04f
--- /dev/null
+++ b/packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/img.md
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+ 
+
+
+
+## Heading
+
+```md
+
+```
diff --git a/packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/fixtures/noUrl.md b/packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/noUrl.md
similarity index 100%
rename from packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/fixtures/noUrl.md
rename to packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/noUrl.md
diff --git a/packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/fixtures/pathname.md b/packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/pathname.md
similarity index 100%
rename from packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/fixtures/pathname.md
rename to packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/pathname.md
diff --git a/packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/fixtures/img.png b/packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/static/img.png
similarity index 100%
rename from packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/fixtures/img.png
rename to packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/static/img.png
diff --git a/packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/fixtures/asset.pdf b/packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/static2/img2.png
similarity index 100%
rename from packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/fixtures/asset.pdf
rename to packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/static2/img2.png
diff --git a/packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__snapshots__/index.test.ts.snap b/packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__snapshots__/index.test.ts.snap
index 571131fa51..dd2e80abfc 100644
--- a/packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__snapshots__/index.test.ts.snap
+++ b/packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__snapshots__/index.test.ts.snap
@@ -1,8 +1,8 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`transformImage plugin fail if image does not exist 1`] = `"Image packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/fixtures/img/doesNotExist.png used in packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/fixtures/fail.md not found."`;
+exports[`transformImage plugin fail if image does not exist 1`] = `"Image packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/static/img/doesNotExist.png or packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/static2/img/doesNotExist.png used in packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/fail.md not found."`;
-exports[`transformImage plugin fail if image url is absent 1`] = `"Markdown image URL is mandatory in \\"packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/fixtures/noUrl.md\\" file"`;
+exports[`transformImage plugin fail if image url is absent 1`] = `"Markdown image URL is mandatory in \\"packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/noUrl.md\\" file"`;
exports[`transformImage plugin pathname protocol 1`] = `
"
@@ -12,20 +12,22 @@ exports[`transformImage plugin pathname protocol 1`] = `
exports[`transformImage plugin transform md images to
1`] = `
"
-
+
-
+
-
+
-
+
+
+
+
+
## Heading
\`\`\`md
-
+
\`\`\`
-
-
"
`;
diff --git a/packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/fixtures/img.md b/packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/fixtures/img.md
deleted file mode 100644
index 0ef7fc0535..0000000000
--- a/packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/fixtures/img.md
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
-
-
-
- 
-
-
-
-## Heading
-
-```md
-
-```
-
-
diff --git a/packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/index.test.ts b/packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/index.test.ts
index 5a9492a41a..2e2c06aba3 100644
--- a/packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/index.test.ts
+++ b/packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/index.test.ts
@@ -5,7 +5,7 @@
* LICENSE file in the root directory of this source tree.
*/
-import {join, relative} from 'path';
+import path from 'path';
import remark from 'remark';
import mdx from 'remark-mdx';
import vfile from 'to-vfile';
@@ -13,47 +13,48 @@ import plugin from '../index';
import headings from '../../headings/index';
const processFixture = async (name, options) => {
- const path = join(__dirname, 'fixtures', `${name}.md`);
- const file = await vfile.read(path);
+ const filePath = path.join(__dirname, `__fixtures__/${name}.md`);
+ const file = await vfile.read(filePath);
const result = await remark()
.use(headings)
.use(mdx)
- .use(plugin, {...options, filePath: path})
+ .use(plugin, {...options, filePath})
.process(file);
return result.toString();
};
-// avoid hardcoding absolute
-const staticDir = `./${relative(process.cwd(), join(__dirname, 'fixtures'))}`;
+const staticDirs = [
+ // avoid hardcoding absolute in the snapshot
+ `./${path.relative(
+ process.cwd(),
+ path.join(__dirname, '__fixtures__/static'),
+ )}`,
+ `./${path.relative(
+ process.cwd(),
+ path.join(__dirname, '__fixtures__/static2'),
+ )}`,
+];
describe('transformImage plugin', () => {
test('fail if image does not exist', async () => {
await expect(
- processFixture('fail', {
- staticDir,
- }),
+ processFixture('fail', {staticDirs}),
).rejects.toThrowErrorMatchingSnapshot();
});
test('fail if image url is absent', async () => {
await expect(
- processFixture('noUrl', {
- staticDir,
- }),
+ processFixture('noUrl', {staticDirs}),
).rejects.toThrowErrorMatchingSnapshot();
});
test('transform md images to
', async () => {
- const result = await processFixture('img', {
- staticDir,
- });
+ const result = await processFixture('img', {staticDirs});
expect(result).toMatchSnapshot();
});
test('pathname protocol', async () => {
- const result = await processFixture('pathname', {
- staticDir,
- });
+ const result = await processFixture('pathname', {staticDirs});
expect(result).toMatchSnapshot();
});
});
diff --git a/packages/docusaurus-mdx-loader/src/remark/transformImage/index.ts b/packages/docusaurus-mdx-loader/src/remark/transformImage/index.ts
index f46fc32a5b..5eb1260039 100644
--- a/packages/docusaurus-mdx-loader/src/remark/transformImage/index.ts
+++ b/packages/docusaurus-mdx-loader/src/remark/transformImage/index.ts
@@ -25,7 +25,7 @@ const {
interface PluginOptions {
filePath: string;
- staticDir: string;
+ staticDirs: string[];
}
const createJSX = (node: Image, pathUrl: string) => {
@@ -63,9 +63,25 @@ async function ensureImageFileExist(imagePath: string, sourceFilePath: string) {
}
}
+async function findImage(possiblePaths: string[], sourceFilePath: string) {
+ // eslint-disable-next-line no-restricted-syntax
+ for (const possiblePath of possiblePaths) {
+ if (await fs.pathExists(possiblePath)) {
+ return possiblePath;
+ }
+ }
+ throw new Error(
+ `Image ${possiblePaths
+ .map((p) => toMessageRelativeFilePath(p))
+ .join(' or ')} used in ${toMessageRelativeFilePath(
+ sourceFilePath,
+ )} not found.`,
+ );
+}
+
async function processImageNode(
node: Image,
- {filePath, staticDir}: PluginOptions,
+ {filePath, staticDirs}: PluginOptions,
) {
if (!node.url) {
throw new Error(
@@ -88,9 +104,11 @@ async function processImageNode(
// images without protocol
else if (path.isAbsolute(node.url)) {
// absolute paths are expected to exist in the static folder
- const expectedImagePath = path.join(staticDir, node.url);
- await ensureImageFileExist(expectedImagePath, filePath);
- createJSX(node, posixPath(expectedImagePath));
+ const possibleImagePaths = staticDirs.map((dir) =>
+ path.join(dir, node.url),
+ );
+ const imagePath = await findImage(possibleImagePaths, filePath);
+ createJSX(node, posixPath(imagePath));
}
// We try to convert image urls without protocol to images with require calls
// going through webpack ensures that image assets exist at build time
diff --git a/packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/fixtures/asset.md b/packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/__fixtures__/asset.md
similarity index 97%
rename from packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/fixtures/asset.md
rename to packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/__fixtures__/asset.md
index ac15b648da..ad1ac5e881 100644
--- a/packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/fixtures/asset.md
+++ b/packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/__fixtures__/asset.md
@@ -20,6 +20,8 @@
[asset](asset.pdf)
+[asset2](/asset2.pdf)
+
[staticAsset.pdf](/staticAsset.pdf)
[@site/static/staticAsset.pdf](@site/static/staticAsset.pdf)
diff --git a/packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/fixtures/static/staticAsset.pdf b/packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/__fixtures__/asset.pdf
similarity index 100%
rename from packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/fixtures/static/staticAsset.pdf
rename to packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/__fixtures__/asset.pdf
diff --git a/packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/fixtures/noUrl.md b/packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/__fixtures__/noUrl.md
similarity index 100%
rename from packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/fixtures/noUrl.md
rename to packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/__fixtures__/noUrl.md
diff --git a/packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/fixtures/pathname.md b/packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/__fixtures__/pathname.md
similarity index 100%
rename from packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/fixtures/pathname.md
rename to packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/__fixtures__/pathname.md
diff --git a/packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/__fixtures__/static/staticAsset.pdf b/packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/__fixtures__/static/staticAsset.pdf
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/fixtures/static/staticAssetImage.png b/packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/__fixtures__/static/staticAssetImage.png
similarity index 100%
rename from packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/fixtures/static/staticAssetImage.png
rename to packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/__fixtures__/static/staticAssetImage.png
diff --git a/packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/__fixtures__/static2/asset2.pdf b/packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/__fixtures__/static2/asset2.pdf
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/__snapshots__/index.test.ts.snap b/packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/__snapshots__/index.test.ts.snap
index 9bfd2f2c63..4b6b4d89a5 100644
--- a/packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/__snapshots__/index.test.ts.snap
+++ b/packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/__snapshots__/index.test.ts.snap
@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`transformAsset plugin fail if asset url is absent 1`] = `"Markdown link URL is mandatory in \\"packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/fixtures/noUrl.md\\" file (title: asset, line: 1)."`;
+exports[`transformAsset plugin fail if asset url is absent 1`] = `"Markdown link URL is mandatory in \\"packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/__fixtures__/noUrl.md\\" file (title: asset, line: 1)."`;
exports[`transformAsset plugin pathname protocol 1`] = `
"[asset](pathname:///asset/unchecked.pdf)
@@ -30,6 +30,8 @@ exports[`transformAsset plugin transform md links to 1`] = `
asset
+asset2
+
staticAsset.pdf
@site/static/staticAsset.pdf
diff --git a/packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/index.test.ts b/packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/index.test.ts
index 836f887b8d..b9eaa062c5 100644
--- a/packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/index.test.ts
+++ b/packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/index.test.ts
@@ -5,21 +5,29 @@
* LICENSE file in the root directory of this source tree.
*/
-import {join} from 'path';
+import path from 'path';
import remark from 'remark';
import mdx from 'remark-mdx';
import vfile from 'to-vfile';
import plugin from '..';
import transformImage from '../../transformImage';
-const processFixture = async (name, options) => {
- const path = join(__dirname, 'fixtures', `${name}.md`);
- const staticDir = join(__dirname, 'fixtures', 'static');
- const file = await vfile.read(path);
+const processFixture = async (name: string, options?) => {
+ const filePath = path.join(__dirname, `__fixtures__/${name}.md`);
+ const staticDirs = [
+ path.join(__dirname, '__fixtures__/static'),
+ path.join(__dirname, '__fixtures__/static2'),
+ ];
+ const file = await vfile.read(filePath);
const result = await remark()
.use(mdx)
- .use(transformImage, {...options, filePath: path, staticDir})
- .use(plugin, {...options, filePath: path, staticDir})
+ .use(transformImage, {...options, filePath, staticDirs})
+ .use(plugin, {
+ ...options,
+ filePath,
+ staticDirs,
+ siteDir: path.join(__dirname, '__fixtures__'),
+ })
.process(file);
return result.toString();
diff --git a/packages/docusaurus-mdx-loader/src/remark/transformLinks/index.ts b/packages/docusaurus-mdx-loader/src/remark/transformLinks/index.ts
index b45907738c..4b2939a159 100644
--- a/packages/docusaurus-mdx-loader/src/remark/transformLinks/index.ts
+++ b/packages/docusaurus-mdx-loader/src/remark/transformLinks/index.ts
@@ -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[] = [];
visit(root, 'link', (node: Link) => {
- promises.push(processLinkNode({node, ...options}));
+ promises.push(processLinkNode(node, options));
});
await Promise.all(promises);
};
diff --git a/packages/docusaurus-plugin-content-blog/src/index.ts b/packages/docusaurus-plugin-content-blog/src/index.ts
index 69617d46d0..c06d4bfadc 100644
--- a/packages/docusaurus-plugin-content-blog/src/index.ts
+++ b/packages/docusaurus-plugin-content-blog/src/index.ts
@@ -17,10 +17,7 @@ import {
addTrailingPathSeparator,
createAbsoluteFilePathMatcher,
} from '@docusaurus/utils';
-import {
- STATIC_DIR_NAME,
- DEFAULT_PLUGIN_ID,
-} from '@docusaurus/core/lib/constants';
+import {DEFAULT_PLUGIN_ID} from '@docusaurus/core/lib/constants';
import {translateContent, getTranslationFiles} from './translations';
import {
@@ -465,7 +462,10 @@ export default function pluginContentBlog(
rehypePlugins,
beforeDefaultRemarkPlugins,
beforeDefaultRehypePlugins,
- staticDir: path.join(siteDir, STATIC_DIR_NAME),
+ staticDirs: siteConfig.staticDirectories.map((dir) =>
+ path.resolve(siteDir, dir),
+ ),
+ siteDir,
isMDXPartial: createAbsoluteFilePathMatcher(
options.exclude,
contentDirs,
diff --git a/packages/docusaurus-plugin-content-docs/src/index.ts b/packages/docusaurus-plugin-content-docs/src/index.ts
index c0bc7bf97c..b239e3d991 100644
--- a/packages/docusaurus-plugin-content-docs/src/index.ts
+++ b/packages/docusaurus-plugin-content-docs/src/index.ts
@@ -7,10 +7,7 @@
import path from 'path';
-import {
- STATIC_DIR_NAME,
- DEFAULT_PLUGIN_ID,
-} from '@docusaurus/core/lib/constants';
+import {DEFAULT_PLUGIN_ID} from '@docusaurus/core/lib/constants';
import {
normalizeUrl,
docuHash,
@@ -397,7 +394,10 @@ export default function pluginContentDocs(
rehypePlugins,
beforeDefaultRehypePlugins,
beforeDefaultRemarkPlugins,
- staticDir: path.join(siteDir, STATIC_DIR_NAME),
+ staticDirs: siteConfig.staticDirectories.map((dir) =>
+ path.resolve(siteDir, dir),
+ ),
+ siteDir,
isMDXPartial: createAbsoluteFilePathMatcher(
options.exclude,
contentDirs,
diff --git a/packages/docusaurus-plugin-content-pages/src/index.ts b/packages/docusaurus-plugin-content-pages/src/index.ts
index c26208d1c1..4cc5626d24 100644
--- a/packages/docusaurus-plugin-content-pages/src/index.ts
+++ b/packages/docusaurus-plugin-content-pages/src/index.ts
@@ -29,10 +29,7 @@ import {
import {Configuration} from 'webpack';
import admonitions from 'remark-admonitions';
import {PluginOptionSchema} from './pluginOptionSchema';
-import {
- DEFAULT_PLUGIN_ID,
- STATIC_DIR_NAME,
-} from '@docusaurus/core/lib/constants';
+import {DEFAULT_PLUGIN_ID} from '@docusaurus/core/lib/constants';
import {
PluginOptions,
@@ -209,7 +206,10 @@ export default function pluginContentPages(
rehypePlugins,
beforeDefaultRehypePlugins,
beforeDefaultRemarkPlugins,
- staticDir: path.join(siteDir, STATIC_DIR_NAME),
+ staticDirs: siteConfig.staticDirectories.map((dir) =>
+ path.resolve(siteDir, dir),
+ ),
+ siteDir,
isMDXPartial: createAbsoluteFilePathMatcher(
options.exclude,
contentDirs,
diff --git a/packages/docusaurus-remark-plugin-npm2yarn/src/__tests__/index.test.ts b/packages/docusaurus-remark-plugin-npm2yarn/src/__tests__/index.test.ts
index 3cab9ab431..eea0d0fe01 100644
--- a/packages/docusaurus-remark-plugin-npm2yarn/src/__tests__/index.test.ts
+++ b/packages/docusaurus-remark-plugin-npm2yarn/src/__tests__/index.test.ts
@@ -10,20 +10,15 @@ import remark from 'remark';
// TODO change to `../index` after migrating to ESM
import npm2yarn from '../../lib/index';
import vfile from 'to-vfile';
-import {join, relative} from 'path';
+import path from 'path';
import mdx from 'remark-mdx';
-const staticDir = `./${relative(process.cwd(), join(__dirname, 'fixtures'))}`;
-
-const processFixture = async (
- name: string,
- options: {sync?: boolean; staticDir: string},
-) => {
- const path = join(__dirname, 'fixtures', `${name}.md`);
- const file = await vfile.read(path);
+const processFixture = async (name: string, options?: {sync?: boolean}) => {
+ const filePath = path.join(__dirname, 'fixtures', `${name}.md`);
+ const file = await vfile.read(filePath);
const result = await remark()
.use(mdx)
- .use(npm2yarn, {...options, filePath: path})
+ .use(npm2yarn, {...options, filePath})
.process(file);
return result.toString();
@@ -31,41 +26,31 @@ const processFixture = async (
describe('npm2yarn plugin', () => {
test('test: installation file', async () => {
- const result = await processFixture('installation', {
- staticDir,
- });
+ const result = await processFixture('installation');
expect(result).toMatchSnapshot();
});
test('test: plugin file', async () => {
- const result = await processFixture('plugin', {
- staticDir,
- });
+ const result = await processFixture('plugin');
expect(result).toMatchSnapshot();
});
test('test: language was not setted', async () => {
- const result = await processFixture('syntax-not-properly-set', {
- staticDir,
- });
+ const result = await processFixture('syntax-not-properly-set');
expect(result).toMatchSnapshot();
});
test('test: already imported tabs components above are not re-imported', async () => {
- const result = await processFixture('import-tabs-above', {
- staticDir,
- });
+ const result = await processFixture('import-tabs-above');
expect(result).toMatchSnapshot();
});
test('test: already imported tabs components below are not re-imported', async () => {
- const result = await processFixture('import-tabs-below', {
- staticDir,
- });
+ const result = await processFixture('import-tabs-below');
expect(result).toMatchSnapshot();
});
diff --git a/packages/docusaurus-types/src/index.d.ts b/packages/docusaurus-types/src/index.d.ts
index 1e58a46114..36101f75b2 100644
--- a/packages/docusaurus-types/src/index.d.ts
+++ b/packages/docusaurus-types/src/index.d.ts
@@ -58,6 +58,7 @@ export interface DocusaurusConfig {
)[];
clientModules?: string[];
ssrTemplate?: string;
+ staticDirectories: string[];
stylesheets?: (
| string
| {
diff --git a/packages/docusaurus/src/commands/build.ts b/packages/docusaurus/src/commands/build.ts
index 5ca4da6405..cd5830dc46 100644
--- a/packages/docusaurus/src/commands/build.ts
+++ b/packages/docusaurus/src/commands/build.ts
@@ -13,7 +13,6 @@ import ReactLoadableSSRAddon from 'react-loadable-ssr-addon-v5-slorber';
import {Configuration} from 'webpack';
import {BundleAnalyzerPlugin} from 'webpack-bundle-analyzer';
import merge from 'webpack-merge';
-import {STATIC_DIR_NAME} from '../constants';
import {load, loadContext} from '../server';
import {handleBrokenLinks} from '../server/brokenLinks';
@@ -129,7 +128,7 @@ async function buildLocale({
outDir,
generatedFilesDir,
plugins,
- siteConfig: {baseUrl, onBrokenLinks},
+ siteConfig: {baseUrl, onBrokenLinks, staticDirectories},
routes,
} = props;
@@ -162,21 +161,16 @@ async function buildLocale({
},
});
- const staticDir = path.resolve(siteDir, STATIC_DIR_NAME);
- if (await fs.pathExists(staticDir)) {
- serverConfig = merge(serverConfig, {
- plugins: [
- new CopyWebpackPlugin({
- patterns: [
- {
- from: staticDir,
- to: outDir,
- },
- ],
- }),
- ],
- });
- }
+ serverConfig = merge(serverConfig, {
+ plugins: [
+ new CopyWebpackPlugin({
+ patterns: staticDirectories
+ .map((dir) => path.resolve(siteDir, dir))
+ .filter(fs.existsSync)
+ .map((dir) => ({from: dir, to: outDir})),
+ }),
+ ],
+ });
// Plugin Lifecycle - configureWebpack and configurePostCss.
plugins.forEach((plugin) => {
diff --git a/packages/docusaurus/src/commands/start.ts b/packages/docusaurus/src/commands/start.ts
index 01137ad211..a8ac0ed6d1 100644
--- a/packages/docusaurus/src/commands/start.ts
+++ b/packages/docusaurus/src/commands/start.ts
@@ -20,7 +20,6 @@ import WebpackDevServer from 'webpack-dev-server';
import merge from 'webpack-merge';
import {load} from '../server';
import {StartCLIOptions} from '@docusaurus/types';
-import {STATIC_DIR_NAME} from '../constants';
import createClientConfig from '../webpack/client';
import {
applyConfigureWebpack,
@@ -187,9 +186,9 @@ export default async function start(
// Reduce log verbosity, see https://github.com/facebook/docusaurus/pull/5420#issuecomment-906613105
stats: 'summary',
},
- static: {
+ static: siteConfig.staticDirectories.map((dir) => ({
publicPath: baseUrl,
- directory: path.resolve(siteDir, STATIC_DIR_NAME),
+ directory: path.resolve(siteDir, dir),
watch: {
// Useful options for our own monorepo using symlinks!
// See https://github.com/webpack/webpack/issues/11612#issuecomment-879259806
@@ -197,7 +196,7 @@ export default async function start(
ignored: /node_modules\/(?!@docusaurus)/,
...{pollingOptions},
},
- },
+ })),
historyApiFallback: {
rewrites: [{from: /\/*/, to: baseUrl}],
},
diff --git a/packages/docusaurus/src/server/__tests__/__snapshots__/config.test.ts.snap b/packages/docusaurus/src/server/__tests__/__snapshots__/config.test.ts.snap
index af70e49573..21b070a9b4 100644
--- a/packages/docusaurus/src/server/__tests__/__snapshots__/config.test.ts.snap
+++ b/packages/docusaurus/src/server/__tests__/__snapshots__/config.test.ts.snap
@@ -40,6 +40,9 @@ Object {
],
"presets": Array [],
"projectName": "hello",
+ "staticDirectories": Array [
+ "static",
+ ],
"tagline": "Hello World",
"themeConfig": Object {},
"themes": Array [],
diff --git a/packages/docusaurus/src/server/configValidation.ts b/packages/docusaurus/src/server/configValidation.ts
index 519161bd91..d873c49777 100644
--- a/packages/docusaurus/src/server/configValidation.ts
+++ b/packages/docusaurus/src/server/configValidation.ts
@@ -6,7 +6,7 @@
*/
import {DocusaurusConfig, I18nConfig} from '@docusaurus/types';
-import {DEFAULT_CONFIG_FILE_NAME} from '../constants';
+import {DEFAULT_CONFIG_FILE_NAME, STATIC_DIR_NAME} from '../constants';
import {
Joi,
logValidationBugReportHint,
@@ -37,6 +37,7 @@ export const DEFAULT_CONFIG: Pick<
| 'titleDelimiter'
| 'noIndex'
| 'baseUrlIssueBanner'
+ | 'staticDirectories'
> = {
i18n: DEFAULT_I18N_CONFIG,
onBrokenLinks: 'throw',
@@ -50,6 +51,7 @@ export const DEFAULT_CONFIG: Pick<
titleDelimiter: '|',
noIndex: false,
baseUrlIssueBanner: true,
+ staticDirectories: [STATIC_DIR_NAME],
};
const PluginSchema = Joi.alternatives()
@@ -142,6 +144,9 @@ export const ConfigSchema = Joi.object({
.equal('ignore', 'log', 'warn', 'error', 'throw')
.default(DEFAULT_CONFIG.onDuplicateRoutes),
organizationName: Joi.string().allow(''),
+ staticDirectories: Joi.array()
+ .items(Joi.string())
+ .default(DEFAULT_CONFIG.staticDirectories),
projectName: Joi.string().allow(''),
deploymentBranch: Joi.string().optional(),
customFields: Joi.object().unknown().default(DEFAULT_CONFIG.customFields),
diff --git a/packages/docusaurus/src/server/index.ts b/packages/docusaurus/src/server/index.ts
index f26b974e71..f48c3b89d8 100644
--- a/packages/docusaurus/src/server/index.ts
+++ b/packages/docusaurus/src/server/index.ts
@@ -13,7 +13,6 @@ import {
DEFAULT_BUILD_DIR_NAME,
DEFAULT_CONFIG_FILE_NAME,
GENERATED_FILES_DIR_NAME,
- STATIC_DIR_NAME,
} from '../constants';
import loadClientModules from './client-modules';
import loadConfig from './config';
@@ -193,7 +192,13 @@ function createBootstrapPlugin({
// Adds a "fallback" mdx loader for mdx files that are not processed by content plugins
// This allows to do things such as importing repo/README.md as a partial from another doc
// Not ideal solution though, but good enough for now
-function createMDXFallbackPlugin({siteDir}: {siteDir: string}): LoadedPlugin {
+function createMDXFallbackPlugin({
+ siteDir,
+ siteConfig,
+}: {
+ siteDir: string;
+ siteConfig: DocusaurusConfig;
+}): LoadedPlugin {
return {
name: 'docusaurus-mdx-fallback-plugin',
content: null,
@@ -223,7 +228,10 @@ function createMDXFallbackPlugin({siteDir}: {siteDir: string}): LoadedPlugin {
{
loader: require.resolve('@docusaurus/mdx-loader'),
options: {
- staticDir: path.join(siteDir, STATIC_DIR_NAME),
+ staticDirs: siteConfig.staticDirectories.map((dir) =>
+ path.resolve(siteDir, dir),
+ ),
+ siteDir,
isMDXPartial: (_filename: string) => true, // External mdx files are always meant to be imported as partials
isMDXPartialFrontMatterWarningDisabled: true, // External mdx files might have frontmatter, let's just disable the warning
remarkPlugins: [admonitions],
@@ -273,7 +281,7 @@ export async function load(
);
plugins.push(createBootstrapPlugin({siteConfig}));
- plugins.push(createMDXFallbackPlugin({siteDir}));
+ plugins.push(createMDXFallbackPlugin({siteDir, siteConfig}));
// Load client modules.
const clientModules = loadClientModules(plugins);
diff --git a/website/static/dogfooding/4/docu.png b/website/_dogfooding/_asset-tests/4/docu.png
similarity index 100%
rename from website/static/dogfooding/4/docu.png
rename to website/_dogfooding/_asset-tests/4/docu.png
diff --git a/website/static/dogfooding/4/图片.png b/website/_dogfooding/_asset-tests/4/图片.png
similarity index 100%
rename from website/static/dogfooding/4/图片.png
rename to website/_dogfooding/_asset-tests/4/图片.png
diff --git a/website/static/dogfooding/javadoc/index.html b/website/_dogfooding/_asset-tests/dogfooding/javadoc/index.html
similarity index 100%
rename from website/static/dogfooding/javadoc/index.html
rename to website/_dogfooding/_asset-tests/dogfooding/javadoc/index.html
diff --git a/website/static/dogfooding/someFile.pdf b/website/_dogfooding/_asset-tests/someFile.pdf
similarity index 100%
rename from website/static/dogfooding/someFile.pdf
rename to website/_dogfooding/_asset-tests/someFile.pdf
diff --git a/website/static/dogfooding/someFile.xyz b/website/_dogfooding/_asset-tests/someFile.xyz
similarity index 100%
rename from website/static/dogfooding/someFile.xyz
rename to website/_dogfooding/_asset-tests/someFile.xyz
diff --git a/website/static/dogfooding/新控制器空间/图片.png b/website/_dogfooding/_asset-tests/新控制器空间/图片.png
similarity index 100%
rename from website/static/dogfooding/新控制器空间/图片.png
rename to website/_dogfooding/_asset-tests/新控制器空间/图片.png
diff --git a/website/_dogfooding/_pages tests/markdown-tests.md b/website/_dogfooding/_pages tests/markdown-tests.md
index 0f3d0807a9..f1a417b9c3 100644
--- a/website/_dogfooding/_pages tests/markdown-tests.md
+++ b/website/_dogfooding/_pages tests/markdown-tests.md
@@ -6,13 +6,13 @@ This is a test page to see if Docusaurus markdown features are working properly
See [#3337](https://github.com/facebook/docusaurus/issues/3337)
-- [/dogfooding/someFile.pdf](/dogfooding/someFile.pdf)
+- [/someFile.pdf](/someFile.pdf)
-- [/dogfooding/someFile.xyz](/dogfooding/someFile.xyz)
+- [/someFile.xyz](/someFile.xyz)
-- [@site/static/dogfooding/someFile.pdf](@site/static/dogfooding/someFile.pdf)
+- [@site/\_dogfooding/\_asset-tests/someFile.pdf](@site/_dogfooding/_asset-tests/someFile.pdf)
-- [@site/static/dogfooding/someFile.xyz](@site/static/dogfooding/someFile.xyz)
+- [@site/\_dogfooding/\_asset-tests/someFile.xyz](@site/_dogfooding/_asset-tests/someFile.xyz)
## Linking to non-SPA page hosted within website
diff --git a/website/_dogfooding/_pages tests/markdownPageTests.md b/website/_dogfooding/_pages tests/markdownPageTests.md
index 79059cfeca..6b1e256edf 100644
--- a/website/_dogfooding/_pages tests/markdownPageTests.md
+++ b/website/_dogfooding/_pages tests/markdownPageTests.md
@@ -203,8 +203,8 @@ Code tag + double pipe: ||
## Images edge cases
-
+
-
+
-
+
diff --git a/website/docs/api/docusaurus.config.js.md b/website/docs/api/docusaurus.config.js.md
index 13df482c5d..3365619a44 100644
--- a/website/docs/api/docusaurus.config.js.md
+++ b/website/docs/api/docusaurus.config.js.md
@@ -361,6 +361,20 @@ Attempting to add unknown field in the config will lead to error in build time:
Error: The field(s) 'foo', 'bar' are not recognized in docusaurus.config.js
```
+### `staticDirectories` {#staticdirectories}
+
+An array of paths, relative to the site's directory or absolute. Files under these paths will be copied to the build output as-is.
+
+- Type: `string[]`
+
+Example:
+
+```js title="docusaurus.config.js"
+module.exports = {
+ staticDirectories: ['static'],
+};
+```
+
### `scripts` {#scripts}
An array of scripts to load. The values can be either strings or plain objects of attribute-value maps. The `