diff --git a/.changeset/cool-birds-prove.md b/.changeset/cool-birds-prove.md new file mode 100644 index 000000000000..70c190b89273 --- /dev/null +++ b/.changeset/cool-birds-prove.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Fix missing styles for Markdoc files in development diff --git a/.changeset/early-students-taste.md b/.changeset/early-students-taste.md new file mode 100644 index 000000000000..3f068a0d250c --- /dev/null +++ b/.changeset/early-students-taste.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Remove `slash` package diff --git a/.changeset/rich-pumpkins-change.md b/.changeset/rich-pumpkins-change.md new file mode 100644 index 000000000000..1637bd11c2ff --- /dev/null +++ b/.changeset/rich-pumpkins-change.md @@ -0,0 +1,5 @@ +--- +'@astrojs/internal-helpers': patch +--- + +Add `slash` path utility diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 0c348f7c9494..2aa663727425 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -20,10 +20,7 @@ jobs: if: ${{ github.repository_owner == 'withastro' }} uses: withastro/automation/.github/workflows/congratsbot.yml@main with: - GITHUB_REPO: ${{ github.repository }} - COMMIT_AUTHOR: ${{ github.event.commits[0].author.name }} - COMMIT_MESSAGE: ${{ github.event.commits[0].message }} - COMMIT_ID: ${{ github.event.commits[0].id }} + EMOJIS: '🎉,🎊,🧑‍🚀,🥳,🙌,🚀,👏,<:houston_golden:1068575433647456447>,<:astrocoin:894990669515489301>,<:astro_pride:1085944201587458169>' secrets: DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK_CONGRATS }} diff --git a/packages/astro/package.json b/packages/astro/package.json index 82fb50bf78c1..16ab32525d0e 100644 --- a/packages/astro/package.json +++ b/packages/astro/package.json @@ -158,10 +158,8 @@ "semver": "^7.5.2", "server-destroy": "^1.0.1", "shiki": "^0.14.1", - "slash": "^4.0.0", "string-width": "^5.1.2", "strip-ansi": "^7.1.0", - "supports-esm": "^1.0.0", "tsconfig-resolver": "^3.0.1", "typescript": "*", "unist-util-visit": "^4.1.2", diff --git a/packages/astro/src/assets/utils/emitAsset.ts b/packages/astro/src/assets/utils/emitAsset.ts index 9b8d6fc08b3c..b1e01b3e4e22 100644 --- a/packages/astro/src/assets/utils/emitAsset.ts +++ b/packages/astro/src/assets/utils/emitAsset.ts @@ -1,8 +1,7 @@ import fs from 'node:fs'; import path from 'node:path'; import { fileURLToPath, pathToFileURL } from 'node:url'; -import slash from 'slash'; -import { prependForwardSlash } from '../../core/path.js'; +import { prependForwardSlash, slash } from '../../core/path.js'; import { imageMetadata, type Metadata } from './metadata.js'; export async function emitESMImage( @@ -46,7 +45,6 @@ export async function emitESMImage( } function fileURLToNormalizedPath(filePath: URL): string { - // Uses `slash` package instead of Vite's `normalizePath` - // to avoid CJS bundling issues. + // Uses `slash` instead of Vite's `normalizePath` to avoid CJS bundling issues. return slash(fileURLToPath(filePath) + filePath.search).replace(/\\/g, '/'); } diff --git a/packages/astro/src/core/render/dev/vite.ts b/packages/astro/src/core/render/dev/vite.ts index b3efb34bb49d..39df7d269c93 100644 --- a/packages/astro/src/core/render/dev/vite.ts +++ b/packages/astro/src/core/render/dev/vite.ts @@ -46,44 +46,45 @@ export async function* crawlGraph( const entryIsStyle = isCSSRequest(id); for (const importedModule of entry.importedModules) { - // A propagation stopping point is a module with the ?astroPropagatedAssets flag. - // When we encounter one of these modules we don't want to continue traversing. - let isPropagationStoppingPoint = false; + if (!importedModule.id) continue; + // some dynamically imported modules are *not* server rendered in time // to only SSR modules that we can safely transform, we check against // a list of file extensions based on our built-in vite plugins - if (importedModule.id) { - // Strip special query params like "?content". - // NOTE: Cannot use `new URL()` here because not all IDs will be valid paths. - // For example, `virtual:image-loader` if you don't have the plugin installed. - const importedModulePathname = importedModule.id.replace(STRIP_QUERY_PARAMS_REGEX, ''); - // If the entry is a style, skip any modules that are not also styles. - // Tools like Tailwind might add HMR dependencies as `importedModules` - // but we should skip them--they aren't really imported. Without this, - // every hoisted script in the project is added to every page! - if (entryIsStyle && !isCSSRequest(importedModulePathname)) { - continue; - } - const isFileTypeNeedingSSR = fileExtensionsToSSR.has( - npath.extname(importedModulePathname) - ); - isPropagationStoppingPoint = ASTRO_PROPAGATED_ASSET_REGEX.test(importedModule.id); - if ( - isFileTypeNeedingSSR && - // Should not SSR a module with ?astroPropagatedAssets - !isPropagationStoppingPoint - ) { - const mod = loader.getModuleById(importedModule.id); - if (!mod?.ssrModule) { - try { - await loader.import(importedModule.id); - } catch { - /** Likely an out-of-date module entry! Silently continue. */ - } + + // Strip special query params like "?content". + // NOTE: Cannot use `new URL()` here because not all IDs will be valid paths. + // For example, `virtual:image-loader` if you don't have the plugin installed. + const importedModulePathname = importedModule.id.replace(STRIP_QUERY_PARAMS_REGEX, ''); + // If the entry is a style, skip any modules that are not also styles. + // Tools like Tailwind might add HMR dependencies as `importedModules` + // but we should skip them--they aren't really imported. Without this, + // every hoisted script in the project is added to every page! + if (entryIsStyle && !isCSSRequest(importedModulePathname)) { + continue; + } + + const isFileTypeNeedingSSR = fileExtensionsToSSR.has(npath.extname(importedModulePathname)); + // A propagation stopping point is a module with the ?astroPropagatedAssets flag. + // When we encounter one of these modules we don't want to continue traversing. + const isPropagationStoppingPoint = ASTRO_PROPAGATED_ASSET_REGEX.test(importedModule.id); + if ( + isFileTypeNeedingSSR && + // Should not SSR a module with ?astroPropagatedAssets + !isPropagationStoppingPoint + ) { + const mod = loader.getModuleById(importedModule.id); + if (!mod?.ssrModule) { + try { + await loader.import(importedModule.id); + } catch { + /** Likely an out-of-date module entry! Silently continue. */ } } } - if (urlDeps.includes(urlId(importedModule.url)) && !isPropagationStoppingPoint) { + + // Make sure the `importedModule` traversed is explicitly imported by the user, and not by HMR + if (urlDeps.includes(importedModule.url) && !isPropagationStoppingPoint) { importedModules.add(importedModule); } } @@ -102,18 +103,10 @@ export async function* crawlGraph( } } -// Virtual modules URL should start with /@id/ but do not -function urlId(url: string) { - if (url.startsWith('astro:scripts')) { - return '/@id/' + url; - } - return url; -} - function getDepsFromEntry(entry: ModuleNode) { let deps = entry.ssrTransformResult?.deps ?? []; if (entry.ssrTransformResult?.dynamicDeps) { - return deps.concat(entry.ssrTransformResult.dynamicDeps); + deps = deps.concat(entry.ssrTransformResult.dynamicDeps); } - return deps; + return deps.map((dep) => unwrapId(dep)); } diff --git a/packages/astro/src/core/render/ssr-element.ts b/packages/astro/src/core/render/ssr-element.ts index 84b0ab531293..2d9bf9ae8d59 100644 --- a/packages/astro/src/core/render/ssr-element.ts +++ b/packages/astro/src/core/render/ssr-element.ts @@ -1,13 +1,12 @@ -import slashify from 'slash'; import type { SSRElement } from '../../@types/astro'; -import { joinPaths, prependForwardSlash } from '../../core/path.js'; +import { joinPaths, prependForwardSlash, slash } from '../../core/path.js'; import type { StylesheetAsset } from '../app/types'; export function createAssetLink(href: string, base?: string, assetsPrefix?: string): string { if (assetsPrefix) { - return joinPaths(assetsPrefix, slashify(href)); + return joinPaths(assetsPrefix, slash(href)); } else if (base) { - return prependForwardSlash(joinPaths(base, slashify(href))); + return prependForwardSlash(joinPaths(base, slash(href))); } else { return href; } diff --git a/packages/astro/src/core/routing/manifest/create.ts b/packages/astro/src/core/routing/manifest/create.ts index 90c134f40145..b5a6831643a5 100644 --- a/packages/astro/src/core/routing/manifest/create.ts +++ b/packages/astro/src/core/routing/manifest/create.ts @@ -11,12 +11,11 @@ import type { LogOptions } from '../../logger/core'; import nodeFs from 'fs'; import { createRequire } from 'module'; import path from 'path'; -import slash from 'slash'; import { fileURLToPath } from 'url'; import { getPrerenderDefault } from '../../../prerender/utils.js'; import { SUPPORTED_MARKDOWN_FILE_EXTENSIONS } from '../../constants.js'; import { warn } from '../../logger/core.js'; -import { removeLeadingForwardSlash } from '../../path.js'; +import { removeLeadingForwardSlash, slash } from '../../path.js'; import { resolvePages } from '../../util.js'; import { getRouteGenerator } from './generator.js'; const require = createRequire(import.meta.url); diff --git a/packages/astro/src/core/util.ts b/packages/astro/src/core/util.ts index 403d41527626..2529e89c2439 100644 --- a/packages/astro/src/core/util.ts +++ b/packages/astro/src/core/util.ts @@ -1,13 +1,12 @@ import fs from 'fs'; import path from 'path'; -import slash from 'slash'; import { fileURLToPath } from 'url'; import { normalizePath } from 'vite'; import type { AstroConfig, AstroSettings, RouteType } from '../@types/astro'; import { isServerLikeOutput } from '../prerender/utils.js'; import { SUPPORTED_MARKDOWN_FILE_EXTENSIONS } from './constants.js'; import type { ModuleLoader } from './module-loader'; -import { prependForwardSlash, removeTrailingForwardSlash } from './path.js'; +import { prependForwardSlash, removeTrailingForwardSlash, slash } from './path.js'; /** Returns true if argument is an object of any prototype/class (but not null). */ export function isObject(value: unknown): value is Record { @@ -90,15 +89,18 @@ export function parseNpmName( * Windows: C:/Users/astro/code/my-project/src/pages/index.astro */ export function viteID(filePath: URL): string { - return slash(fileURLToPath(filePath) + filePath.search).replace(/\\/g, '/'); + return slash(fileURLToPath(filePath) + filePath.search); } export const VALID_ID_PREFIX = `/@id/`; +export const NULL_BYTE_PLACEHOLDER = `__x00__`; -// Strip valid id prefix. This is prepended to resolved Ids that are -// not valid browser import specifiers by the importAnalysis plugin. +// Strip valid id prefix and replace null byte placeholder. Both are prepended to resolved ids +// as they are not valid browser import specifiers (by the Vite's importAnalysis plugin) export function unwrapId(id: string): string { - return id.startsWith(VALID_ID_PREFIX) ? id.slice(VALID_ID_PREFIX.length) : id; + return id.startsWith(VALID_ID_PREFIX) + ? id.slice(VALID_ID_PREFIX.length).replace(NULL_BYTE_PLACEHOLDER, '\0') + : id; } export function resolvePages(config: AstroConfig) { diff --git a/packages/astro/src/vite-plugin-load-fallback/index.ts b/packages/astro/src/vite-plugin-load-fallback/index.ts index 7c853245be34..084cb885f7ef 100644 --- a/packages/astro/src/vite-plugin-load-fallback/index.ts +++ b/packages/astro/src/vite-plugin-load-fallback/index.ts @@ -1,7 +1,7 @@ import nodeFs from 'fs'; import npath from 'path'; -import slashify from 'slash'; import type * as vite from 'vite'; +import { slash } from '../core/path.js'; type NodeFileSystemModule = typeof nodeFs; @@ -47,7 +47,7 @@ export default function loadFallbackPlugin({ async resolveId(id, parent) { // See if this can be loaded from our fs if (parent) { - const candidateId = npath.posix.join(npath.posix.dirname(slashify(parent)), id); + const candidateId = npath.posix.join(npath.posix.dirname(slash(parent)), id); try { // Check to see if this file exists and is not a directory. const stats = await fs.promises.stat(candidateId); diff --git a/packages/astro/test/units/content-collections/frontmatter.test.js b/packages/astro/test/units/content-collections/frontmatter.test.js index f264f994a5cc..d35a6df33668 100644 --- a/packages/astro/test/units/content-collections/frontmatter.test.js +++ b/packages/astro/test/units/content-collections/frontmatter.test.js @@ -1,7 +1,6 @@ import { fileURLToPath } from 'node:url'; import nodeFS from 'node:fs'; import path from 'node:path'; -import slash from 'slash'; import { runInContainer } from '../../../dist/core/dev/index.js'; import { attachContentServerListeners } from '../../../dist/content/index.js'; @@ -11,7 +10,9 @@ const root = new URL('../../fixtures/alias/', import.meta.url); function getTypesDts() { const typesdtsURL = new URL('../../../content-types.template.d.ts', import.meta.url); - const relpath = slash(path.relative(fileURLToPath(root), fileURLToPath(typesdtsURL))); + const relpath = path + .relative(fileURLToPath(root), fileURLToPath(typesdtsURL)) + .replace(/\\/g, '/'); return { [relpath]: nodeFS.readFileSync(typesdtsURL, 'utf-8'), }; diff --git a/packages/integrations/cloudflare/package.json b/packages/integrations/cloudflare/package.json index b63d3a02a6ae..ca2f2ea473ac 100644 --- a/packages/integrations/cloudflare/package.json +++ b/packages/integrations/cloudflare/package.json @@ -52,7 +52,6 @@ "chai": "^4.3.7", "cheerio": "1.0.0-rc.12", "mocha": "^9.2.2", - "slash": "^4.0.0", "wrangler": "^2.0.23" } } diff --git a/packages/integrations/cloudflare/test/prerender.test.js b/packages/integrations/cloudflare/test/prerender.test.js index 526f8a4ac5e0..847bd950a0f1 100644 --- a/packages/integrations/cloudflare/test/prerender.test.js +++ b/packages/integrations/cloudflare/test/prerender.test.js @@ -1,6 +1,5 @@ import { loadFixture } from './test-utils.js'; import { expect } from 'chai'; -import slash from 'slash'; describe('Prerendering', () => { /** @type {import('./test-utils').Fixture} */ @@ -21,7 +20,7 @@ describe('Prerendering', () => { it('includes prerendered routes in the routes.json config', async () => { const foundRoutes = JSON.parse(await fixture.readFile('/_routes.json')).exclude.map((r) => - slash(r) + r.replace(/\\/g, '/') ); const expectedExcludedRoutes = ['/_worker.js', '/one/index.html', '/one/']; @@ -48,7 +47,7 @@ describe('Hybrid rendering', () => { it('includes prerendered routes in the routes.json config', async () => { const foundRoutes = JSON.parse(await fixture.readFile('/_routes.json')).exclude.map((r) => - slash(r) + r.replace(/\\/g, '/') ); const expectedExcludedRoutes = ['/_worker.js', '/index.html', '/']; diff --git a/packages/internal-helpers/src/path.ts b/packages/internal-helpers/src/path.ts index 2f2a974c43f6..50166554265f 100644 --- a/packages/internal-helpers/src/path.ts +++ b/packages/internal-helpers/src/path.ts @@ -84,3 +84,7 @@ export function removeQueryString(path: string) { export function isRemotePath(src: string) { return /^(http|ftp|https|ws):?\/\//.test(src) || src.startsWith('data:'); } + +export function slash(path: string) { + return path.replace(/\\/g, '/'); +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8f5c1f2f39d2..e16f768f2c44 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -619,18 +619,12 @@ importers: shiki: specifier: ^0.14.1 version: 0.14.1 - slash: - specifier: ^4.0.0 - version: 4.0.0 string-width: specifier: ^5.1.2 version: 5.1.2 strip-ansi: specifier: ^7.1.0 version: 7.1.0 - supports-esm: - specifier: ^1.0.0 - version: 1.0.0 tsconfig-resolver: specifier: ^3.0.1 version: 3.0.1 @@ -3638,9 +3632,6 @@ importers: mocha: specifier: ^9.2.2 version: 9.2.2 - slash: - specifier: ^4.0.0 - version: 4.0.0 wrangler: specifier: ^2.0.23 version: 2.0.23 @@ -7719,10 +7710,6 @@ packages: dependencies: '@lit-labs/ssr-dom-shim': 1.1.1 - /@ljharb/has-package-exports-patterns@0.0.2: - resolution: {integrity: sha512-4/RWEeXDO6bocPONheFe6gX/oQdP/bEpv0oL4HqjPP5DCenBSt0mHgahppY49N0CpsaqffdwPq+TlX9CYOq2Dw==} - dev: false - /@manypkg/find-root@1.1.0: resolution: {integrity: sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==} dependencies: @@ -12093,12 +12080,6 @@ packages: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} - /has-package-exports@1.3.0: - resolution: {integrity: sha512-e9OeXPQnmPhYoJ63lXC4wWe34TxEGZDZ3OQX9XRqp2VwsfLl3bQBy7VehLnd34g3ef8CmYlBLGqEMKXuz8YazQ==} - dependencies: - '@ljharb/has-package-exports-patterns': 0.0.2 - dev: false - /has-property-descriptors@1.0.0: resolution: {integrity: sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==} dependencies: @@ -16461,12 +16442,6 @@ packages: dependencies: has-flag: 4.0.0 - /supports-esm@1.0.0: - resolution: {integrity: sha512-96Am8CDqUaC0I2+C/swJ0yEvM8ZnGn4unoers/LSdE4umhX7mELzqyLzx3HnZAluq5PXIsGMKqa7NkqaeHMPcg==} - dependencies: - has-package-exports: 1.3.0 - dev: false - /supports-preserve-symlinks-flag@1.0.0: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'}