From 29a5fdc1535fc389035d8107025f7490bfa976ed Mon Sep 17 00:00:00 2001 From: Bjorn Lu Date: Sun, 4 Sep 2022 16:43:47 +0800 Subject: [PATCH] Correctly escape paths in file names (#4584) --- .changeset/slimy-fireants-carry.md | 5 +++++ .../astro/src/core/build/vite-plugin-analyzer.ts | 5 ++--- packages/astro/src/jsx/babel.ts | 11 +++-------- packages/astro/src/runtime/server/hydration.ts | 4 ++-- .../src/pages/index.astro | 8 ++++++-- .../src/pages/mdx.mdx | 5 +++-- .../test/special-chars-in-component-imports.test.js | 12 ++++++++++-- 7 files changed, 31 insertions(+), 19 deletions(-) create mode 100644 .changeset/slimy-fireants-carry.md diff --git a/.changeset/slimy-fireants-carry.md b/.changeset/slimy-fireants-carry.md new file mode 100644 index 000000000000..7f972759a223 --- /dev/null +++ b/.changeset/slimy-fireants-carry.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Correctly escape paths in file names diff --git a/packages/astro/src/core/build/vite-plugin-analyzer.ts b/packages/astro/src/core/build/vite-plugin-analyzer.ts index e4f64b18126c..e25ee42aa90d 100644 --- a/packages/astro/src/core/build/vite-plugin-analyzer.ts +++ b/packages/astro/src/core/build/vite-plugin-analyzer.ts @@ -4,7 +4,6 @@ import type { BuildInternals } from '../../core/build/internal.js'; import type { PluginMetadata as AstroPluginMetadata } from '../../vite-plugin-astro/types'; import { prependForwardSlash } from '../../core/path.js'; -import { resolveClientDevPath } from '../../core/render/dev/resolve.js'; import { getTopLevelPages } from './graph.js'; import { getPageDataByViteID, trackClientOnlyPageDatas } from './internal.js'; @@ -82,7 +81,7 @@ export function vitePluginAnalyzer(internals: BuildInternals): VitePlugin { const astro = info.meta.astro as AstroPluginMetadata['astro']; for (const c of astro.hydratedComponents) { - const rid = c.resolvedPath ? resolveClientDevPath(c.resolvedPath) : c.specifier; + const rid = c.resolvedPath ? decodeURI(c.resolvedPath) : c.specifier; internals.discoveredHydratedComponents.add(rid); } @@ -93,7 +92,7 @@ export function vitePluginAnalyzer(internals: BuildInternals): VitePlugin { const clientOnlys: string[] = []; for (const c of astro.clientOnlyComponents) { - const cid = c.resolvedPath ? resolveClientDevPath(c.resolvedPath) : c.specifier; + const cid = c.resolvedPath ? decodeURI(c.resolvedPath) : c.specifier; internals.discoveredClientOnlyComponents.add(cid); clientOnlys.push(cid); } diff --git a/packages/astro/src/jsx/babel.ts b/packages/astro/src/jsx/babel.ts index 338464b269d6..1a5a7664e7da 100644 --- a/packages/astro/src/jsx/babel.ts +++ b/packages/astro/src/jsx/babel.ts @@ -1,6 +1,7 @@ import type { PluginObj } from '@babel/core'; import * as t from '@babel/types'; import { pathToFileURL } from 'node:url'; +import { resolveClientDevPath } from '../core/render/dev/resolve.js'; import { HydrationDirectiveProps } from '../runtime/server/hydration.js'; import type { PluginMetadata } from '../vite-plugin-astro/types'; @@ -217,10 +218,7 @@ export default function astroJSX(): PluginObj { let resolvedPath: string; if (meta.path.startsWith('.')) { const fileURL = pathToFileURL(state.filename!); - resolvedPath = `/@fs${new URL(meta.path, fileURL).pathname}`; - if (resolvedPath.endsWith('.jsx')) { - resolvedPath = resolvedPath.slice(0, -4); - } + resolvedPath = resolveClientDevPath(`/@fs${new URL(meta.path, fileURL).pathname}`); } else { resolvedPath = meta.path; } @@ -300,10 +298,7 @@ export default function astroJSX(): PluginObj { let resolvedPath: string; if (meta.path.startsWith('.')) { const fileURL = pathToFileURL(state.filename!); - resolvedPath = `/@fs${new URL(meta.path, fileURL).pathname}`; - if (resolvedPath.endsWith('.jsx')) { - resolvedPath = resolvedPath.slice(0, -4); - } + resolvedPath = resolveClientDevPath(`/@fs${new URL(meta.path, fileURL).pathname}`); } else { resolvedPath = meta.path; } diff --git a/packages/astro/src/runtime/server/hydration.ts b/packages/astro/src/runtime/server/hydration.ts index d58dc406ebe7..fea251b79272 100644 --- a/packages/astro/src/runtime/server/hydration.ts +++ b/packages/astro/src/runtime/server/hydration.ts @@ -140,12 +140,12 @@ export async function generateHydrateScript( } // Add component url - island.props['component-url'] = await result.resolve(componentUrl); + island.props['component-url'] = await result.resolve(decodeURI(componentUrl)); // Add renderer url if (renderer.clientEntrypoint) { island.props['component-export'] = componentExport.value; - island.props['renderer-url'] = await result.resolve(renderer.clientEntrypoint); + island.props['renderer-url'] = await result.resolve(decodeURI(renderer.clientEntrypoint)); island.props['props'] = escapeHTML(serializeProps(props)); } diff --git a/packages/astro/test/fixtures/special-chars-in-component-imports/src/pages/index.astro b/packages/astro/test/fixtures/special-chars-in-component-imports/src/pages/index.astro index 5e7ff90cfc41..9f44b97c5fe8 100644 --- a/packages/astro/test/fixtures/special-chars-in-component-imports/src/pages/index.astro +++ b/packages/astro/test/fixtures/special-chars-in-component-imports/src/pages/index.astro @@ -1,17 +1,21 @@ --- import CaretCounter from '../components/^--with-carets/Counter'; import RocketCounter from '../components/and-rockets-🚀/Counter'; -import PercentCounter from '../components/now-100%-better/Counter'; +// Not supported in Vite +// import PercentCounter from '../components/now-100%-better/Counter'; import SpaceCounter from '../components/with some spaces/Counter'; import RoundBracketCounter from '../components/with-(round-brackets)/Counter'; import SquareBracketCounter from '../components/with-[square-brackets]/Counter'; --- + + +

Special chars in component import paths from an .astro file

- + diff --git a/packages/astro/test/fixtures/special-chars-in-component-imports/src/pages/mdx.mdx b/packages/astro/test/fixtures/special-chars-in-component-imports/src/pages/mdx.mdx index f9ccc9e2ba88..79c1ba1807ec 100644 --- a/packages/astro/test/fixtures/special-chars-in-component-imports/src/pages/mdx.mdx +++ b/packages/astro/test/fixtures/special-chars-in-component-imports/src/pages/mdx.mdx @@ -1,6 +1,7 @@ import CaretCounter from '../components/^--with-carets/Counter' import RocketCounter from '../components/and-rockets-🚀/Counter' -import PercentCounter from '../components/now-100%-better/Counter' +// Not supported in Vite +// import PercentCounter from '../components/now-100%-better/Counter' import SpaceCounter from '../components/with some spaces/Counter' import RoundBracketCounter from '../components/with-(round-brackets)/Counter' import SquareBracketCounter from '../components/with-[square-brackets]/Counter' @@ -9,7 +10,7 @@ import SquareBracketCounter from '../components/with-[square-brackets]/Counter' - +{/* */} diff --git a/packages/astro/test/special-chars-in-component-imports.test.js b/packages/astro/test/special-chars-in-component-imports.test.js index 8cd9b2563341..21081a15655b 100644 --- a/packages/astro/test/special-chars-in-component-imports.test.js +++ b/packages/astro/test/special-chars-in-component-imports.test.js @@ -2,11 +2,19 @@ import { expect } from 'chai'; import { load as cheerioLoad } from 'cheerio'; import { isWindows, loadFixture } from './test-utils.js'; -describe.skip('Special chars in component import paths', () => { +describe('Special chars in component import paths', () => { /** @type {import('./test-utils').Fixture} */ let fixture; - const componentIds = ['caret', 'rocket', 'percent', 'space', 'round-bracket', 'square-bracket']; + const componentIds = [ + 'caret', + 'rocket', + // Not supported as import identifier in Vite + // 'percent', + 'space', + 'round-bracket', + 'square-bracket', + ]; before(async () => { fixture = await loadFixture({