diff --git a/packages/docusaurus-mdx-loader/src/remark/transformImage/index.js b/packages/docusaurus-mdx-loader/src/remark/transformImage/index.js
index 1a017033a7..42122ab4a3 100644
--- a/packages/docusaurus-mdx-loader/src/remark/transformImage/index.js
+++ b/packages/docusaurus-mdx-loader/src/remark/transformImage/index.js
@@ -11,7 +11,11 @@ const url = require('url');
const fs = require('fs-extra');
const escapeHtml = require('escape-html');
const {getFileLoaderUtils} = require('@docusaurus/core/lib/webpack/utils');
-const {posixPath, toMessageRelativeFilePath} = require('@docusaurus/utils');
+const {
+ posixPath,
+ escapePath,
+ toMessageRelativeFilePath,
+} = require('@docusaurus/utils');
const {
loaders: {inlineMarkdownImageFileLoader},
@@ -22,7 +26,9 @@ const createJSX = (node, pathUrl) => {
jsxNode.type = 'jsx';
jsxNode.value = `
`;
diff --git a/packages/docusaurus-mdx-loader/src/remark/transformLinks/index.js b/packages/docusaurus-mdx-loader/src/remark/transformLinks/index.js
index 1ac3a08900..50bc4d7f71 100644
--- a/packages/docusaurus-mdx-loader/src/remark/transformLinks/index.js
+++ b/packages/docusaurus-mdx-loader/src/remark/transformLinks/index.js
@@ -5,7 +5,11 @@
* LICENSE file in the root directory of this source tree.
*/
-const {toMessageRelativeFilePath, posixPath} = require('@docusaurus/utils');
+const {
+ toMessageRelativeFilePath,
+ posixPath,
+ escapePath,
+} = require('@docusaurus/utils');
const visit = require('unist-util-visit');
const path = require('path');
@@ -43,7 +47,9 @@ function toAssetRequireNode({node, filePath, requireAssetPath}) {
? relativeRequireAssetPath
: `./${relativeRequireAssetPath}`;
- const href = `require('${inlineMarkdownLinkFileLoader}${relativeRequireAssetPath}').default`;
+ const href = `require('${inlineMarkdownLinkFileLoader}${escapePath(
+ relativeRequireAssetPath,
+ )}').default`;
const children = (node.children || []).map((n) => toValue(n)).join('');
const title = node.title ? `title="${escapeHtml(node.title)}"` : '';
diff --git a/packages/docusaurus-utils/src/__tests__/escapePath.test.ts b/packages/docusaurus-utils/src/__tests__/escapePath.test.ts
new file mode 100644
index 0000000000..4a9e467875
--- /dev/null
+++ b/packages/docusaurus-utils/src/__tests__/escapePath.test.ts
@@ -0,0 +1,25 @@
+/**
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+import {escapePath} from '../escapePath';
+
+describe('escapePath', () => {
+ test('escapePath works', () => {
+ const asserts: Record = {
+ 'c:/aaaa\\bbbb': 'c:/aaaa\\\\bbbb',
+ 'c:\\aaaa\\bbbb\\★': 'c:\\\\aaaa\\\\bbbb\\\\★',
+ '\\\\?\\c:\\aaaa\\bbbb': '\\\\\\\\?\\\\c:\\\\aaaa\\\\bbbb',
+ 'c:\\aaaa\\bbbb': 'c:\\\\aaaa\\\\bbbb',
+ 'foo\\bar': 'foo\\\\bar',
+ 'foo\\bar/lol': 'foo\\\\bar/lol',
+ 'website\\docs/**/*.{md,mdx}': 'website\\\\docs/**/*.{md,mdx}',
+ };
+ Object.keys(asserts).forEach((file) => {
+ expect(escapePath(file)).toBe(asserts[file]);
+ });
+ });
+});
diff --git a/packages/docusaurus-utils/src/__tests__/index.test.ts b/packages/docusaurus-utils/src/__tests__/index.test.ts
index f83e9f6117..9d34cc01ef 100644
--- a/packages/docusaurus-utils/src/__tests__/index.test.ts
+++ b/packages/docusaurus-utils/src/__tests__/index.test.ts
@@ -38,7 +38,7 @@ import {sum} from 'lodash';
describe('load utils', () => {
test('aliasedSitePath', () => {
- const asserts = {
+ const asserts: Record = {
'user/website/docs/asd.md': '@site/docs/asd.md',
'user/website/versioned_docs/foo/bar.md':
'@site/versioned_docs/foo/bar.md',
@@ -51,23 +51,8 @@ describe('load utils', () => {
});
});
- test('posixPath', () => {
- const asserts = {
- 'c:/aaaa\\bbbb': 'c:/aaaa/bbbb',
- 'c:\\aaaa\\bbbb\\★': 'c:\\aaaa\\bbbb\\★',
- '\\\\?\\c:\\aaaa\\bbbb': '\\\\?\\c:\\aaaa\\bbbb',
- 'c:\\aaaa\\bbbb': 'c:/aaaa/bbbb',
- 'foo\\bar': 'foo/bar',
- 'foo\\bar/lol': 'foo/bar/lol',
- 'website\\docs/**/*.{md,mdx}': 'website/docs/**/*.{md,mdx}',
- };
- Object.keys(asserts).forEach((file) => {
- expect(posixPath(file)).toBe(asserts[file]);
- });
- });
-
test('genComponentName', () => {
- const asserts = {
+ const asserts: Record = {
'/': 'index',
'/foo-bar': 'FooBar096',
'/foo/bar': 'FooBar1Df',
@@ -99,7 +84,7 @@ describe('load utils', () => {
});
test('docuHash', () => {
- const asserts = {
+ const asserts: Record = {
'': '-d41',
'/': 'index',
'/foo-bar': 'foo-bar-096',
@@ -115,7 +100,7 @@ describe('load utils', () => {
});
test('fileToPath', () => {
- const asserts = {
+ const asserts: Record = {
'index.md': '/',
'hello/index.md': '/hello/',
'foo.md': '/foo',
@@ -166,7 +151,7 @@ describe('load utils', () => {
});
test('genChunkName', () => {
- const firstAssert = {
+ const firstAssert: Record = {
'/docs/adding-blog': 'docs-adding-blog-062',
'/docs/versioning': 'docs-versioning-8a8',
'/': 'index',
@@ -186,7 +171,7 @@ describe('load utils', () => {
);
// Even with same preferred name, still different chunk name for different path
- const secondAssert = {
+ const secondAssert: Record = {
'/blog/1': 'blog-85-f-089',
'/blog/2': 'blog-353-489',
};
@@ -195,7 +180,7 @@ describe('load utils', () => {
});
// Only generate short unique id
- const thirdAssert = {
+ const thirdAssert: Record = {
a: '0cc175b9',
b: '92eb5ffe',
c: '4a8a08f0',
diff --git a/packages/docusaurus-utils/src/__tests__/posixPath.test.ts b/packages/docusaurus-utils/src/__tests__/posixPath.test.ts
new file mode 100644
index 0000000000..866ad0e21c
--- /dev/null
+++ b/packages/docusaurus-utils/src/__tests__/posixPath.test.ts
@@ -0,0 +1,25 @@
+/**
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+import {posixPath} from '../posixPath';
+
+describe('posixPath', () => {
+ test('posixPath works', () => {
+ const asserts: Record = {
+ 'c:/aaaa\\bbbb': 'c:/aaaa/bbbb',
+ 'c:\\aaaa\\bbbb\\★': 'c:\\aaaa\\bbbb\\★',
+ '\\\\?\\c:\\aaaa\\bbbb': '\\\\?\\c:\\aaaa\\bbbb',
+ 'c:\\aaaa\\bbbb': 'c:/aaaa/bbbb',
+ 'foo\\bar': 'foo/bar',
+ 'foo\\bar/lol': 'foo/bar/lol',
+ 'website\\docs/**/*.{md,mdx}': 'website/docs/**/*.{md,mdx}',
+ };
+ Object.keys(asserts).forEach((file) => {
+ expect(posixPath(file)).toBe(asserts[file]);
+ });
+ });
+});
diff --git a/packages/docusaurus-utils/src/escapePath.ts b/packages/docusaurus-utils/src/escapePath.ts
new file mode 100644
index 0000000000..d53a52a7b3
--- /dev/null
+++ b/packages/docusaurus-utils/src/escapePath.ts
@@ -0,0 +1,23 @@
+/**
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+/**
+ * When you have a path like C:\X\Y
+ * It is not safe to use directly when generating code
+ * For example, this would fail due to unescaped \: `
`
+ * But this would work: `
`
+ *
+ * Workaround for issue in posixPath, maybe we won't need it anymore soon?
+ * https://github.com/facebook/docusaurus/issues/4730#issuecomment-833530370
+ * https://github.com/sindresorhus/slash/pull/16#issuecomment-833528479
+ */
+export function escapePath(str: string): string {
+ const escaped = JSON.stringify(str);
+
+ // Remove the " around the json string;
+ return escaped.substring(1, escaped.length - 1);
+}
diff --git a/packages/docusaurus-utils/src/index.ts b/packages/docusaurus-utils/src/index.ts
index e5aae3bcae..f9193b85e8 100644
--- a/packages/docusaurus-utils/src/index.ts
+++ b/packages/docusaurus-utils/src/index.ts
@@ -21,9 +21,14 @@ import {
// @ts-expect-error: no typedefs :s
import resolvePathnameUnsafe from 'resolve-pathname';
+import {posixPath as posixPathImport} from './posixPath';
+
+export const posixPath = posixPathImport;
+
export * from './codeTranslationsUtils';
export * from './markdownParser';
export * from './markdownLinks';
+export * from './escapePath';
const fileHash = new Map();
export async function generate(
@@ -129,20 +134,6 @@ export function genComponentName(pagePath: string): string {
return upperFirst(camelCase(pageHash));
}
-/**
- * Convert Windows backslash paths to posix style paths.
- * E.g: endi\\lie -> endi/lie
- */
-export function posixPath(str: string): string {
- const isExtendedLengthPath = /^\\\\\?\\/.test(str);
- const hasNonAscii = /[^\u0000-\u0080]+/.test(str); // eslint-disable-line
-
- if (isExtendedLengthPath || hasNonAscii) {
- return str;
- }
- return str.replace(/\\/g, '/');
-}
-
// When you want to display a path in a message/warning/error,
// it's more convenient to:
// - make it relative to cwd()
diff --git a/packages/docusaurus-utils/src/posixPath.ts b/packages/docusaurus-utils/src/posixPath.ts
new file mode 100644
index 0000000000..792356376e
--- /dev/null
+++ b/packages/docusaurus-utils/src/posixPath.ts
@@ -0,0 +1,27 @@
+/**
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+/**
+ * Convert Windows backslash paths to posix style paths.
+ * E.g: endi\\lie -> endi/lie
+ *
+ * Looks like this code was originally copied from https://github.com/sindresorhus/slash/blob/main/index.js
+ *
+ */
+export function posixPath(str: string): string {
+ const isExtendedLengthPath = /^\\\\\?\\/.test(str);
+
+ // TODO not sure why we need this
+ // See https://github.com/sindresorhus/slash/pull/16#issuecomment-833528479
+ // See https://github.com/facebook/docusaurus/issues/4730#issuecomment-833530370
+ const hasNonAscii = /[^\u0000-\u0080]+/.test(str); // eslint-disable-line
+
+ if (isExtendedLengthPath || hasNonAscii) {
+ return str;
+ }
+ return str.replace(/\\/g, '/');
+}
diff --git a/website/src/pages/examples/markdownPageExample.md b/website/src/pages/examples/markdownPageExample.md
index eefa182e1a..579d08e2f5 100644
--- a/website/src/pages/examples/markdownPageExample.md
+++ b/website/src/pages/examples/markdownPageExample.md
@@ -222,3 +222,23 @@ See https://github.com/facebook/docusaurus/pull/1584
Code tag + double pipe: ||
Code tag + double pipe: ||
+
+## Images edge cases
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/website/static/dogfooding/4/docu.png b/website/static/dogfooding/4/docu.png
new file mode 100644
index 0000000000..f458149e3c
Binary files /dev/null and b/website/static/dogfooding/4/docu.png differ
diff --git a/website/static/dogfooding/4/图片.png b/website/static/dogfooding/4/图片.png
new file mode 100644
index 0000000000..2e4d675f90
Binary files /dev/null and b/website/static/dogfooding/4/图片.png differ
diff --git a/website/static/dogfooding/新控制器空间/图片.png b/website/static/dogfooding/新控制器空间/图片.png
new file mode 100644
index 0000000000..f458149e3c
Binary files /dev/null and b/website/static/dogfooding/新控制器空间/图片.png differ