Correctly escape paths in file names (#4584)

This commit is contained in:
Bjorn Lu 2022-09-04 16:43:47 +08:00 committed by GitHub
parent 893a02a1bb
commit 29a5fdc153
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 31 additions and 19 deletions

View file

@ -0,0 +1,5 @@
---
'astro': patch
---
Correctly escape paths in file names

View file

@ -4,7 +4,6 @@ import type { BuildInternals } from '../../core/build/internal.js';
import type { PluginMetadata as AstroPluginMetadata } from '../../vite-plugin-astro/types'; import type { PluginMetadata as AstroPluginMetadata } from '../../vite-plugin-astro/types';
import { prependForwardSlash } from '../../core/path.js'; import { prependForwardSlash } from '../../core/path.js';
import { resolveClientDevPath } from '../../core/render/dev/resolve.js';
import { getTopLevelPages } from './graph.js'; import { getTopLevelPages } from './graph.js';
import { getPageDataByViteID, trackClientOnlyPageDatas } from './internal.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']; const astro = info.meta.astro as AstroPluginMetadata['astro'];
for (const c of astro.hydratedComponents) { 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); internals.discoveredHydratedComponents.add(rid);
} }
@ -93,7 +92,7 @@ export function vitePluginAnalyzer(internals: BuildInternals): VitePlugin {
const clientOnlys: string[] = []; const clientOnlys: string[] = [];
for (const c of astro.clientOnlyComponents) { 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); internals.discoveredClientOnlyComponents.add(cid);
clientOnlys.push(cid); clientOnlys.push(cid);
} }

View file

@ -1,6 +1,7 @@
import type { PluginObj } from '@babel/core'; import type { PluginObj } from '@babel/core';
import * as t from '@babel/types'; import * as t from '@babel/types';
import { pathToFileURL } from 'node:url'; import { pathToFileURL } from 'node:url';
import { resolveClientDevPath } from '../core/render/dev/resolve.js';
import { HydrationDirectiveProps } from '../runtime/server/hydration.js'; import { HydrationDirectiveProps } from '../runtime/server/hydration.js';
import type { PluginMetadata } from '../vite-plugin-astro/types'; import type { PluginMetadata } from '../vite-plugin-astro/types';
@ -217,10 +218,7 @@ export default function astroJSX(): PluginObj {
let resolvedPath: string; let resolvedPath: string;
if (meta.path.startsWith('.')) { if (meta.path.startsWith('.')) {
const fileURL = pathToFileURL(state.filename!); const fileURL = pathToFileURL(state.filename!);
resolvedPath = `/@fs${new URL(meta.path, fileURL).pathname}`; resolvedPath = resolveClientDevPath(`/@fs${new URL(meta.path, fileURL).pathname}`);
if (resolvedPath.endsWith('.jsx')) {
resolvedPath = resolvedPath.slice(0, -4);
}
} else { } else {
resolvedPath = meta.path; resolvedPath = meta.path;
} }
@ -300,10 +298,7 @@ export default function astroJSX(): PluginObj {
let resolvedPath: string; let resolvedPath: string;
if (meta.path.startsWith('.')) { if (meta.path.startsWith('.')) {
const fileURL = pathToFileURL(state.filename!); const fileURL = pathToFileURL(state.filename!);
resolvedPath = `/@fs${new URL(meta.path, fileURL).pathname}`; resolvedPath = resolveClientDevPath(`/@fs${new URL(meta.path, fileURL).pathname}`);
if (resolvedPath.endsWith('.jsx')) {
resolvedPath = resolvedPath.slice(0, -4);
}
} else { } else {
resolvedPath = meta.path; resolvedPath = meta.path;
} }

View file

@ -140,12 +140,12 @@ export async function generateHydrateScript(
} }
// Add component url // Add component url
island.props['component-url'] = await result.resolve(componentUrl); island.props['component-url'] = await result.resolve(decodeURI(componentUrl));
// Add renderer url // Add renderer url
if (renderer.clientEntrypoint) { if (renderer.clientEntrypoint) {
island.props['component-export'] = componentExport.value; 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)); island.props['props'] = escapeHTML(serializeProps(props));
} }

View file

@ -1,17 +1,21 @@
--- ---
import CaretCounter from '../components/^--with-carets/Counter'; import CaretCounter from '../components/^--with-carets/Counter';
import RocketCounter from '../components/and-rockets-🚀/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 SpaceCounter from '../components/with some spaces/Counter';
import RoundBracketCounter from '../components/with-(round-brackets)/Counter'; import RoundBracketCounter from '../components/with-(round-brackets)/Counter';
import SquareBracketCounter from '../components/with-[square-brackets]/Counter'; import SquareBracketCounter from '../components/with-[square-brackets]/Counter';
--- ---
<html> <html>
<head>
<meta charset="utf-8" />
</head>
<body> <body>
<h1>Special chars in component import paths from an .astro file</h1> <h1>Special chars in component import paths from an .astro file</h1>
<CaretCounter id="caret" client:visible /> <CaretCounter id="caret" client:visible />
<RocketCounter id="rocket" client:visible /> <RocketCounter id="rocket" client:visible />
<PercentCounter id="percent" client:visible /> <!-- <PercentCounter id="percent" client:visible /> -->
<SpaceCounter id="space" client:visible /> <SpaceCounter id="space" client:visible />
<RoundBracketCounter id="round-bracket" client:visible /> <RoundBracketCounter id="round-bracket" client:visible />
<SquareBracketCounter id="square-bracket" client:visible /> <SquareBracketCounter id="square-bracket" client:visible />

View file

@ -1,6 +1,7 @@
import CaretCounter from '../components/^--with-carets/Counter' import CaretCounter from '../components/^--with-carets/Counter'
import RocketCounter from '../components/and-rockets-🚀/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 SpaceCounter from '../components/with some spaces/Counter'
import RoundBracketCounter from '../components/with-(round-brackets)/Counter' import RoundBracketCounter from '../components/with-(round-brackets)/Counter'
import SquareBracketCounter from '../components/with-[square-brackets]/Counter' import SquareBracketCounter from '../components/with-[square-brackets]/Counter'
@ -9,7 +10,7 @@ import SquareBracketCounter from '../components/with-[square-brackets]/Counter'
<CaretCounter id="caret" client:visible /> <CaretCounter id="caret" client:visible />
<RocketCounter id="rocket" client:visible /> <RocketCounter id="rocket" client:visible />
<PercentCounter id="percent" client:visible /> {/* <PercentCounter id="percent" client:visible /> */}
<SpaceCounter id="space" client:visible /> <SpaceCounter id="space" client:visible />
<RoundBracketCounter id="round-bracket" client:visible /> <RoundBracketCounter id="round-bracket" client:visible />
<SquareBracketCounter id="square-bracket" client:visible /> <SquareBracketCounter id="square-bracket" client:visible />

View file

@ -2,11 +2,19 @@ import { expect } from 'chai';
import { load as cheerioLoad } from 'cheerio'; import { load as cheerioLoad } from 'cheerio';
import { isWindows, loadFixture } from './test-utils.js'; 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} */ /** @type {import('./test-utils').Fixture} */
let 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 () => { before(async () => {
fixture = await loadFixture({ fixture = await loadFixture({