mirror of
https://github.com/facebook/docusaurus.git
synced 2025-05-11 16:17:25 +02:00
fix(v2): fix encoding of markdown image/file inline file-loaders (#4736)
* try to reproduce windows edge case due to file encoding * mdx loader => required file paths should be escaped * revert bad change * try to fix posix path issues * try to fix posix path issues * attempt to fix the file-loader edge cases with non-ascii chars * Add more example image edge-cases
This commit is contained in:
parent
39105f03d4
commit
a79c70c954
12 changed files with 148 additions and 40 deletions
25
packages/docusaurus-utils/src/__tests__/escapePath.test.ts
Normal file
25
packages/docusaurus-utils/src/__tests__/escapePath.test.ts
Normal file
|
@ -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<string, string> = {
|
||||
'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]);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -38,7 +38,7 @@ import {sum} from 'lodash';
|
|||
|
||||
describe('load utils', () => {
|
||||
test('aliasedSitePath', () => {
|
||||
const asserts = {
|
||||
const asserts: Record<string, string> = {
|
||||
'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<string, string> = {
|
||||
'/': 'index',
|
||||
'/foo-bar': 'FooBar096',
|
||||
'/foo/bar': 'FooBar1Df',
|
||||
|
@ -99,7 +84,7 @@ describe('load utils', () => {
|
|||
});
|
||||
|
||||
test('docuHash', () => {
|
||||
const asserts = {
|
||||
const asserts: Record<string, string> = {
|
||||
'': '-d41',
|
||||
'/': 'index',
|
||||
'/foo-bar': 'foo-bar-096',
|
||||
|
@ -115,7 +100,7 @@ describe('load utils', () => {
|
|||
});
|
||||
|
||||
test('fileToPath', () => {
|
||||
const asserts = {
|
||||
const asserts: Record<string, string> = {
|
||||
'index.md': '/',
|
||||
'hello/index.md': '/hello/',
|
||||
'foo.md': '/foo',
|
||||
|
@ -166,7 +151,7 @@ describe('load utils', () => {
|
|||
});
|
||||
|
||||
test('genChunkName', () => {
|
||||
const firstAssert = {
|
||||
const firstAssert: Record<string, string> = {
|
||||
'/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<string, string> = {
|
||||
'/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<string, string> = {
|
||||
a: '0cc175b9',
|
||||
b: '92eb5ffe',
|
||||
c: '4a8a08f0',
|
||||
|
|
25
packages/docusaurus-utils/src/__tests__/posixPath.test.ts
Normal file
25
packages/docusaurus-utils/src/__tests__/posixPath.test.ts
Normal file
|
@ -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<string, string> = {
|
||||
'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]);
|
||||
});
|
||||
});
|
||||
});
|
23
packages/docusaurus-utils/src/escapePath.ts
Normal file
23
packages/docusaurus-utils/src/escapePath.ts
Normal file
|
@ -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 \: `<img src={require('${filePath}')} />`
|
||||
* But this would work: `<img src={require('${escapePath(filePath)}')} />`
|
||||
*
|
||||
* 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);
|
||||
}
|
|
@ -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()
|
||||
|
|
27
packages/docusaurus-utils/src/posixPath.ts
Normal file
27
packages/docusaurus-utils/src/posixPath.ts
Normal file
|
@ -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, '/');
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue