diff --git a/.changeset/gorgeous-clocks-leave.md b/.changeset/gorgeous-clocks-leave.md new file mode 100644 index 000000000..de81c9106 --- /dev/null +++ b/.changeset/gorgeous-clocks-leave.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Updates Astro.resolve to return project-relative paths diff --git a/packages/astro/src/runtime/server/index.ts b/packages/astro/src/runtime/server/index.ts index 07acb0ba0..010474b2b 100644 --- a/packages/astro/src/runtime/server/index.ts +++ b/packages/astro/src/runtime/server/index.ts @@ -2,6 +2,7 @@ import type { AstroComponentMetadata, Renderer } from '../../@types/astro'; import type { AstroGlobalPartial, SSRResult, SSRElement } from '../../@types/astro'; import shorthash from 'shorthash'; +import { pathToFileURL } from 'url'; import { extractDirectives, generateHydrateScript } from './hydration.js'; import { serializeListValue } from './util.js'; export { createMetadata } from './metadata.js'; @@ -286,15 +287,22 @@ function createFetchContentFn(url: URL) { // This is used to create the top-level Astro global; the one that you can use // Inside of getStaticPaths. -export function createAstro(fileURLStr: string, site: string): AstroGlobalPartial { +export function createAstro(fileURLStr: string, site: string, projectRootStr: string): AstroGlobalPartial { const url = new URL(fileURLStr); + const projectRoot = projectRootStr === '.' ? pathToFileURL(process.cwd()) : new URL(projectRootStr); const fetchContent = createFetchContentFn(url); return { site: new URL(site), fetchContent, // INVESTIGATE is there a use-case for multi args? resolve(...segments: string[]) { - return segments.reduce((u, segment) => new URL(segment, u), url).pathname; + let resolved = segments.reduce((u, segment) => new URL(segment, u), url).pathname; + // When inside of project root, remove the leading path so you are + // left with only `/src/images/tower.png` + if (resolved.startsWith(projectRoot.pathname)) { + resolved = '/' + resolved.substr(projectRoot.pathname.length); + } + return resolved; }, }; } diff --git a/packages/astro/src/vite-plugin-astro/index.ts b/packages/astro/src/vite-plugin-astro/index.ts index 6f6ebef78..6ec16db2f 100644 --- a/packages/astro/src/vite-plugin-astro/index.ts +++ b/packages/astro/src/vite-plugin-astro/index.ts @@ -57,6 +57,7 @@ export default function astro({ config, devServer }: AstroPluginOptions): vite.P // result passed to esbuild, but also available in the catch handler. tsResult = await transform(source, { as: isPage ? 'document' : 'fragment', + projectRoot: config.projectRoot.toString(), site: config.buildOptions.site, sourcefile: id, sourcemap: 'both', diff --git a/packages/astro/src/vite-plugin-build-html/index.ts b/packages/astro/src/vite-plugin-build-html/index.ts index cabc5e0bd..7650c0224 100644 --- a/packages/astro/src/vite-plugin-build-html/index.ts +++ b/packages/astro/src/vite-plugin-build-html/index.ts @@ -69,6 +69,7 @@ export function rollupPluginAstroBuildHTML(options: PluginOptions): VitePlugin { for (const [component, pageData] of Object.entries(allPages)) { const [renderers, mod] = pageData.preload; + // Hydrated components are statically identified. for (const path of mod.$$metadata.getAllHydratedComponentPaths()) { jsInput.add(path); } @@ -138,6 +139,9 @@ export function rollupPluginAstroBuildHTML(options: PluginOptions): VitePlugin { const src = getAttribute(node, 'src'); if (src?.startsWith(srcRoot) && !astroAssetMap.has(src)) { astroAssetMap.set(src, fs.readFile(new URL(`file://${src}`))); + } else if (src?.startsWith(srcRootWeb) && !astroAssetMap.has(src)) { + const resolved = new URL('.' + src, astroConfig.projectRoot); + astroAssetMap.set(src, fs.readFile(resolved)); } } @@ -146,6 +150,9 @@ export function rollupPluginAstroBuildHTML(options: PluginOptions): VitePlugin { for (const { url } of candidates) { if (url.startsWith(srcRoot) && !astroAssetMap.has(url)) { astroAssetMap.set(url, fs.readFile(new URL(`file://${url}`))); + } else if (url.startsWith(srcRootWeb) && !astroAssetMap.has(url)) { + const resolved = new URL('.' + url, astroConfig.projectRoot); + astroAssetMap.set(url, fs.readFile(resolved)); } } } @@ -347,7 +354,11 @@ export function rollupPluginAstroBuildHTML(options: PluginOptions): VitePlugin { } remove(script); } else if (isInSrcDirectory(script, 'src', srcRoot, srcRootWeb)) { - const src = getAttribute(script, 'src'); + let src = getAttribute(script, 'src'); + // If this is projectRoot relative, get the fullpath to match the facadeId. + if (src?.startsWith(srcRootWeb)) { + src = new URL('.' + src, astroConfig.projectRoot).pathname; + } // On windows the facadeId doesn't start with / but does not Unix :/ if (src && (facadeIdMap.has(src) || facadeIdMap.has(src.substr(1)))) { const assetRootPath = '/' + (facadeIdMap.get(src) || facadeIdMap.get(src.substr(1))); diff --git a/packages/astro/src/vite-plugin-markdown/index.ts b/packages/astro/src/vite-plugin-markdown/index.ts index b3494e126..0d868a7cd 100644 --- a/packages/astro/src/vite-plugin-markdown/index.ts +++ b/packages/astro/src/vite-plugin-markdown/index.ts @@ -52,7 +52,13 @@ ${setup}`.trim(); } // Transform from `.astro` to valid `.ts` - let { code: tsResult } = await transform(astroResult, { sourcefile: id, sourcemap: 'inline', internalURL: 'astro/internal' }); + let { code: tsResult } = await transform(astroResult, { + projectRoot: config.projectRoot.toString(), + site: config.buildOptions.site, + sourcefile: id, + sourcemap: 'inline', + internalURL: 'astro/internal', + }); tsResult = `\nexport const metadata = ${JSON.stringify(metadata)}; export const frontmatter = ${JSON.stringify(content)};