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:
Sébastien Lorber 2021-05-06 16:48:20 +02:00 committed by GitHub
parent 39105f03d4
commit a79c70c954
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 148 additions and 40 deletions

View 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]);
});
});
});

View 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',

View 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]);
});
});
});

View 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);
}

View file

@ -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()

View 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, '/');
}