diff --git a/packages/docusaurus-utils/src/__tests__/index.test.js b/packages/docusaurus-utils/src/__tests__/index.test.js index 2aabcfedc3..ed75cf2447 100644 --- a/packages/docusaurus-utils/src/__tests__/index.test.js +++ b/packages/docusaurus-utils/src/__tests__/index.test.js @@ -13,9 +13,23 @@ import { idx, getSubFolder, normalizeUrl, + posixPath, } from '../index'; 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', + }; + Object.keys(asserts).forEach(file => { + expect(posixPath(file)).toBe(asserts[file]); + }); + }); + test('fileToComponentName', () => { const asserts = { 'index.md': 'MDIndex', diff --git a/packages/docusaurus-utils/src/index.js b/packages/docusaurus-utils/src/index.js index c632df72eb..86c6532a31 100644 --- a/packages/docusaurus-utils/src/index.js +++ b/packages/docusaurus-utils/src/index.js @@ -49,6 +49,21 @@ function fileToComponentName(file) { return ext ? ext.toUpperCase() + str : str; } +/** + * Convert Windows backslash paths to posix style paths. E.g: endi\\lie -> endi/lie + * @param {string} str windows backslash paths + * @returns {string} posix-style path + */ +function posixPath(str) { + const isExtendedLengthPath = /^\\\\\?\\/.test(str); + const hasNonAscii = /[^\u0000-\u0080]+/.test(str); // eslint-disable-line + + if (isExtendedLengthPath || hasNonAscii) { + return str; + } + return str.replace(/\\/g, '/'); +} + function generateChunkName(str, prefix) { const name = str === '/' ? 'index' : kebabHash(str); return prefix ? `${prefix}---${name}` : name; @@ -153,4 +168,5 @@ module.exports = { idx, normalizeUrl, parse, + posixPath, }; diff --git a/packages/docusaurus/lib/server/load/plugins.js b/packages/docusaurus/lib/server/load/plugins.js index d33694463d..c3b5d03a5f 100644 --- a/packages/docusaurus/lib/server/load/plugins.js +++ b/packages/docusaurus/lib/server/load/plugins.js @@ -7,7 +7,7 @@ const fs = require('fs-extra'); const path = require('path'); -const {generate} = require('@docusaurus/utils'); +const {generate, posixPath} = require('@docusaurus/utils'); module.exports = async function loadPlugins({pluginConfigs = [], context}) { // 1. Plugin Lifecycle - Initialization/Constructor @@ -48,7 +48,10 @@ module.exports = async function loadPlugins({pluginConfigs = [], context}) { metadataFileName, JSON.stringify(content, null, 2), ); - const contentPath = path.join('@generated', pluginContentPath); + // Note that we need to convert it into POSIX format because + // import XXXXX from '@generated\this-is\my\path' is incorrect + // import XXXXX from '@generated/this-is/my/path' is correct + const contentPath = posixPath(path.join('@generated', pluginContentPath)); return { metadataKey, diff --git a/packages/docusaurus/lib/server/load/routes.js b/packages/docusaurus/lib/server/load/routes.js index 2e4a695014..2c1a652485 100644 --- a/packages/docusaurus/lib/server/load/routes.js +++ b/packages/docusaurus/lib/server/load/routes.js @@ -34,7 +34,8 @@ async function loadRoutes(pluginsRouteConfigs) { const importStr = isObj ? target.path : target; const queryStr = target.query ? `?${stringify(target.query)}` : ''; const chunkName = generateChunkName(name || importStr, prefix); - return `() => import(/* webpackChunkName: '${chunkName}' */ '${importStr}${queryStr}')`; + const finalStr = JSON.stringify(importStr + queryStr); + return `() => import(/* webpackChunkName: '${chunkName}' */ ${finalStr})`; } function generateRouteCode(pluginRouteConfig) {