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 + +![](/dogfooding/新控制器空间/图片.png) + +![](../../../static/dogfooding/新控制器空间/图片.png) + +![](./../../../static/dogfooding/新控制器空间/图片.png) + +![](/dogfooding/4/图片.png) + +![](../../../static/dogfooding/4/图片.png) + +![](./../../../static/dogfooding/4/图片.png) + +![](/dogfooding/4/docu.png) + +![](../../../static/dogfooding/4/docu.png) + +![](./../../../static/dogfooding/4/docu.png) 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