Merge branch 'main' into feat/csr

This commit is contained in:
Nate Moore 2023-05-22 10:55:02 -05:00 committed by GitHub
commit 7fa79b3761
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
37 changed files with 425 additions and 216 deletions

View file

@ -1,6 +0,0 @@
---
'@astrojs/prefetch': patch
---
Fix the inclusion of `@types/network-information`.

View file

@ -1,5 +0,0 @@
---
'@astrojs/markdoc': patch
---
Fix inconsistent Markdoc heading IDs for documents with the same headings.

View file

@ -1,5 +0,0 @@
---
'astro': patch
---
Fix routes created by `injectRoute` for SSR

View file

@ -1,5 +0,0 @@
---
'astro': patch
---
Emit middleware as an entrypoint during build

View file

@ -1,5 +0,0 @@
---
'astro': patch
---
Emit pages as dynamic import chunks during the build

View file

@ -1,5 +0,0 @@
---
'astro': patch
---
Add route information when warning of `getStaticPaths()` ignored

View file

@ -1,5 +0,0 @@
---
'astro': patch
---
Fix unnecessary warning showing on start when a collection folder was empty. The warning was also enhanced to add more information about possible causes.

View file

@ -1,5 +1,11 @@
# @astrojs/rss # @astrojs/rss
## 2.4.3
### Patch Changes
- [#7153](https://github.com/withastro/astro/pull/7153) [`e17ed0727`](https://github.com/withastro/astro/commit/e17ed0727ef1acb512c77723a1b641326de8ca84) Thanks [@AkashRajpurohit](https://github.com/AkashRajpurohit)! - exposes RSSFeedItem type
## 2.4.2 ## 2.4.2
### Patch Changes ### Patch Changes

View file

@ -1,7 +1,7 @@
{ {
"name": "@astrojs/rss", "name": "@astrojs/rss",
"description": "Add RSS feeds to your Astro projects", "description": "Add RSS feeds to your Astro projects",
"version": "2.4.2", "version": "2.4.3",
"type": "module", "type": "module",
"types": "./dist/index.d.ts", "types": "./dist/index.d.ts",
"author": "withastro", "author": "withastro",

View file

@ -32,7 +32,7 @@ export type RSSOptions = {
trailingSlash?: z.infer<typeof rssOptionsValidator>['trailingSlash']; trailingSlash?: z.infer<typeof rssOptionsValidator>['trailingSlash'];
}; };
type RSSFeedItem = { export type RSSFeedItem = {
/** Link to item */ /** Link to item */
link: string; link: string;
/** Full content of the item. Should be valid HTML */ /** Full content of the item. Should be valid HTML */

View file

@ -1,5 +1,27 @@
# astro # astro
## 2.5.2
### Patch Changes
- [#7144](https://github.com/withastro/astro/pull/7144) [`ba0636240`](https://github.com/withastro/astro/commit/ba0636240996f9f082d122a8414240196881cb96) Thanks [@lilnasy](https://github.com/lilnasy)! - Fixed an issue where scripts that weren't safe to inline were inlined.
- [#7150](https://github.com/withastro/astro/pull/7150) [`8f418d13c`](https://github.com/withastro/astro/commit/8f418d13c5d5c9c40f05020205f24380b718654b) Thanks [@MoustaphaDev](https://github.com/MoustaphaDev)! - fix no matched path when using `getStaticPaths` without `prerender` export.
## 2.5.1
### Patch Changes
- [#7128](https://github.com/withastro/astro/pull/7128) [`72f686a68`](https://github.com/withastro/astro/commit/72f686a68930de52f9a274c13c98acad59925b31) Thanks [@johannesspohr](https://github.com/johannesspohr)! - Fix routes created by `injectRoute` for SSR
- [#7132](https://github.com/withastro/astro/pull/7132) [`319a0a7a0`](https://github.com/withastro/astro/commit/319a0a7a0a6a950387c942b467746d590bb32fda) Thanks [@ematipico](https://github.com/ematipico)! - Emit middleware as an entrypoint during build
- [#7036](https://github.com/withastro/astro/pull/7036) [`852d59a8d`](https://github.com/withastro/astro/commit/852d59a8d68e124f10852609e0f1619d5838ac76) Thanks [@ematipico](https://github.com/ematipico)! - Emit pages as dynamic import chunks during the build
- [#7126](https://github.com/withastro/astro/pull/7126) [`530fb9ebe`](https://github.com/withastro/astro/commit/530fb9ebee77646921ec29d45d9b66484bdfb521) Thanks [@bluwy](https://github.com/bluwy)! - Add route information when warning of `getStaticPaths()` ignored
- [#7118](https://github.com/withastro/astro/pull/7118) [`3257dd289`](https://github.com/withastro/astro/commit/3257dd28901c785a6a661211b98c5ef2cb3b9aa4) Thanks [@Princesseuh](https://github.com/Princesseuh)! - Fix unnecessary warning showing on start when a collection folder was empty. The warning was also enhanced to add more information about possible causes.
## 2.5.0 ## 2.5.0
### Minor Changes ### Minor Changes

View file

@ -1,6 +1,6 @@
{ {
"name": "astro", "name": "astro",
"version": "2.5.0", "version": "2.5.2",
"description": "Astro is a modern site builder with web best practices, performance, and DX front-of-mind.", "description": "Astro is a modern site builder with web best practices, performance, and DX front-of-mind.",
"type": "module", "type": "module",
"author": "withastro", "author": "withastro",

View file

@ -4,7 +4,7 @@ import { viteID } from '../../util.js';
import type { BuildInternals } from '../internal.js'; import type { BuildInternals } from '../internal.js';
import { getPageDataByViteID } from '../internal.js'; import { getPageDataByViteID } from '../internal.js';
import type { AstroBuildPlugin } from '../plugin'; import type { AstroBuildPlugin } from '../plugin';
import type { StaticBuildOptions } from '../types'; import type { OutputChunk, StaticBuildOptions } from '../types';
function virtualHoistedEntry(id: string) { function virtualHoistedEntry(id: string) {
return id.startsWith('/astro/hoisted.js?q='); return id.startsWith('/astro/hoisted.js?q=');
@ -50,15 +50,25 @@ export function vitePluginHoistedScripts(
assetInlineLimit = settings.config.vite?.build.assetsInlineLimit; assetInlineLimit = settings.config.vite?.build.assetsInlineLimit;
} }
const considerInlining = new Map<string, OutputChunk>();
const importedByOtherScripts = new Set<string>();
// Find all page entry points and create a map of the entry point to the hashed hoisted script. // Find all page entry points and create a map of the entry point to the hashed hoisted script.
// This is used when we render so that we can add the script to the head. // This is used when we render so that we can add the script to the head.
for (const [id, output] of Object.entries(bundle)) { Object.entries(bundle).forEach(([id, output]) => {
if ( if (
output.type === 'chunk' && output.type === 'chunk' &&
output.facadeModuleId && output.facadeModuleId &&
virtualHoistedEntry(output.facadeModuleId) virtualHoistedEntry(output.facadeModuleId)
) { ) {
considerInlining.set(id, output);
output.imports.forEach((imported) => importedByOtherScripts.add(imported));
}
});
for (const [id, output] of considerInlining.entries()) {
const canBeInlined = const canBeInlined =
importedByOtherScripts.has(output.fileName) === false &&
output.imports.length === 0 && output.imports.length === 0 &&
output.dynamicImports.length === 0 && output.dynamicImports.length === 0 &&
Buffer.byteLength(output.code) <= assetInlineLimit; Buffer.byteLength(output.code) <= assetInlineLimit;
@ -89,7 +99,6 @@ export function vitePluginHoistedScripts(
delete bundle[id]; delete bundle[id];
} }
} }
}
}, },
}; };
} }

View file

@ -1,5 +1,6 @@
import path from 'node:path'; import path from 'node:path';
import type { Plugin as VitePlugin } from 'vite'; import type { Plugin as VitePlugin } from 'vite';
import { getPrerenderMetadata } from '../../../prerender/metadata.js';
import type { BuildInternals } from '../internal.js'; import type { BuildInternals } from '../internal.js';
import type { AstroBuildPlugin } from '../plugin.js'; import type { AstroBuildPlugin } from '../plugin.js';
import type { StaticBuildOptions } from '../types'; import type { StaticBuildOptions } from '../types';
@ -20,7 +21,7 @@ function vitePluginPrerender(opts: StaticBuildOptions, internals: BuildInternals
if (pageInfo) { if (pageInfo) {
// prerendered pages should be split into their own chunk // prerendered pages should be split into their own chunk
// Important: this can't be in the `pages/` directory! // Important: this can't be in the `pages/` directory!
if (meta.getModuleInfo(id)?.meta.astro?.pageOptions?.prerender) { if (getPrerenderMetadata(meta.getModuleInfo(id))) {
pageInfo.route.prerender = true; pageInfo.route.prerender = true;
return 'prerender'; return 'prerender';
} }

View file

@ -138,7 +138,7 @@ export async function callEndpoint<MiddlewareResult = Response | EndpointOutput>
}; };
} }
if (env.ssr && !mod.prerender) { if (env.ssr && !ctx.route?.prerender) {
if (response.hasOwnProperty('headers')) { if (response.hasOwnProperty('headers')) {
warn( warn(
logging, logging,

View file

@ -89,7 +89,7 @@ export async function getParamsAndProps(
routeCache.set(route, routeCacheEntry); routeCache.set(route, routeCacheEntry);
} }
const matchedStaticPath = findPathItemByKey(routeCacheEntry.staticPaths, params, route); const matchedStaticPath = findPathItemByKey(routeCacheEntry.staticPaths, params, route);
if (!matchedStaticPath && (ssr ? mod.prerender : true)) { if (!matchedStaticPath && (ssr ? route.prerender : true)) {
return GetParamsAndPropsError.NoMatchingStaticPath; return GetParamsAndPropsError.NoMatchingStaticPath;
} }
// Note: considered using Object.create(...) for performance // Note: considered using Object.create(...) for performance

View file

@ -66,6 +66,7 @@ export async function preload({
try { try {
// Load the module from the Vite SSR Runtime. // Load the module from the Vite SSR Runtime.
const mod = (await env.loader.import(fileURLToPath(filePath))) as ComponentInstance; const mod = (await env.loader.import(fileURLToPath(filePath))) as ComponentInstance;
return [renderers, mod]; return [renderers, mod];
} catch (error) { } catch (error) {
// If the error came from Markdown or CSS, we already handled it and there's no need to enhance it // If the error came from Markdown or CSS, we already handled it and there's no need to enhance it

View file

@ -31,7 +31,7 @@ export async function callGetStaticPaths({
}: CallGetStaticPathsOptions): Promise<RouteCacheEntry> { }: CallGetStaticPathsOptions): Promise<RouteCacheEntry> {
validateDynamicRouteModule(mod, { ssr, logging, route }); validateDynamicRouteModule(mod, { ssr, logging, route });
// No static paths in SSR mode. Return an empty RouteCacheEntry. // No static paths in SSR mode. Return an empty RouteCacheEntry.
if (ssr && !mod.prerender) { if (ssr && !route.prerender) {
return { staticPaths: Object.assign([], { keyed: new Map() }) }; return { staticPaths: Object.assign([], { keyed: new Map() }) };
} }
// Add a check here to make TypeScript happy. // Add a check here to make TypeScript happy.

View file

@ -227,7 +227,7 @@ export function createRouteManifest(
]); ]);
const validEndpointExtensions: Set<string> = new Set(['.js', '.ts']); const validEndpointExtensions: Set<string> = new Set(['.js', '.ts']);
const localFs = fsMod ?? nodeFs; const localFs = fsMod ?? nodeFs;
const isPrenderDefault = isHybridOutput(settings.config); const isPrerenderDefault = isHybridOutput(settings.config);
const foundInvalidFileExtensions: Set<string> = new Set(); const foundInvalidFileExtensions: Set<string> = new Set();
@ -340,7 +340,7 @@ export function createRouteManifest(
component, component,
generate, generate,
pathname: pathname || undefined, pathname: pathname || undefined,
prerender: isPrenderDefault, prerender: isPrerenderDefault,
}); });
} }
}); });
@ -416,7 +416,7 @@ export function createRouteManifest(
component, component,
generate, generate,
pathname: pathname || void 0, pathname: pathname || void 0,
prerender: isPrenderDefault, prerender: isPrerenderDefault,
}); });
}); });

View file

@ -32,14 +32,14 @@ export function validateDynamicRouteModule(
route: RouteData; route: RouteData;
} }
) { ) {
if (ssr && mod.getStaticPaths && !mod.prerender) { if (ssr && mod.getStaticPaths && !route.prerender) {
warn( warn(
logging, logging,
'getStaticPaths', 'getStaticPaths',
`getStaticPaths() in ${bold(route.component)} is ignored when "output: server" is set.` `getStaticPaths() in ${bold(route.component)} is ignored when "output: server" is set.`
); );
} }
if ((!ssr || mod.prerender) && !mod.getStaticPaths) { if ((!ssr || route.prerender) && !mod.getStaticPaths) {
throw new AstroError({ throw new AstroError({
...AstroErrorData.GetStaticPathsRequired, ...AstroErrorData.GetStaticPathsRequired,
location: { file: route.component }, location: { file: route.component },

View file

@ -0,0 +1,22 @@
import type { ModuleInfo, ModuleLoader } from '../core/module-loader';
import { viteID } from '../core/util.js';
type GetPrerenderStatusParams = {
filePath: URL;
loader: ModuleLoader;
};
export function getPrerenderStatus({
filePath,
loader,
}: GetPrerenderStatusParams): boolean | undefined {
const fileID = viteID(filePath);
const moduleInfo = loader.getModuleInfo(fileID);
if (!moduleInfo) return;
const prerenderStatus = getPrerenderMetadata(moduleInfo);
return prerenderStatus;
}
export function getPrerenderMetadata(moduleInfo: ModuleInfo) {
return moduleInfo?.meta?.astro?.pageOptions?.prerender;
}

View file

@ -16,6 +16,7 @@ import { preload, renderPage } from '../core/render/dev/index.js';
import { getParamsAndProps, GetParamsAndPropsError } from '../core/render/index.js'; import { getParamsAndProps, GetParamsAndPropsError } from '../core/render/index.js';
import { createRequest } from '../core/request.js'; import { createRequest } from '../core/request.js';
import { matchAllRoutes } from '../core/routing/index.js'; import { matchAllRoutes } from '../core/routing/index.js';
import { getPrerenderStatus } from '../prerender/metadata.js';
import { isHybridOutput } from '../prerender/utils.js'; import { isHybridOutput } from '../prerender/utils.js';
import { log404 } from './common.js'; import { log404 } from './common.js';
import { handle404Response, writeSSRResult, writeWebResponse } from './response.js'; import { handle404Response, writeSSRResult, writeWebResponse } from './response.js';
@ -50,6 +51,17 @@ export async function matchRoute(
for await (const maybeRoute of matches) { for await (const maybeRoute of matches) {
const filePath = new URL(`./${maybeRoute.component}`, settings.config.root); const filePath = new URL(`./${maybeRoute.component}`, settings.config.root);
const preloadedComponent = await preload({ env, filePath }); const preloadedComponent = await preload({ env, filePath });
// gets the prerender metadata set by the `astro:scanner` vite plugin
const prerenderStatus = getPrerenderStatus({
filePath,
loader: env.loader,
});
if (prerenderStatus !== undefined) {
maybeRoute.prerender = prerenderStatus;
}
const [, mod] = preloadedComponent; const [, mod] = preloadedComponent;
// attempt to get static paths // attempt to get static paths
// if this fails, we have a bad URL match! // if this fails, we have a bad URL match!

View file

@ -1,20 +1,28 @@
import { expect } from 'chai'; import { expect } from 'chai';
import { loadFixture } from './test-utils.js'; import { loadFixture } from './test-utils.js';
import * as cheerio from 'cheerio'; import * as cheerio from 'cheerio';
import testAdapter from './test-adapter.js';
describe('prerender getStaticPaths - build calls', () => { describe('Prerender', () => {
/** @type {import('./test-utils').Fixture} */ /** @type {import('./test-utils').Fixture} */
let fixture; let fixture;
describe('output: "server"', () => {
describe('getStaticPaths - build calls', () => {
before(async () => { before(async () => {
fixture = await loadFixture({ fixture = await loadFixture({
root: './fixtures/ssr-prerender-get-static-paths/', root: './fixtures/ssr-prerender-get-static-paths/',
site: 'https://mysite.dev/', site: 'https://mysite.dev/',
adapter: testAdapter(),
base: '/blog', base: '/blog',
output: 'server',
}); });
await fixture.build(); await fixture.build();
}); });
after(async () => {
await fixture.clean();
});
afterEach(() => { afterEach(() => {
// reset the flag used by [...calledTwiceTest].astro between each test // reset the flag used by [...calledTwiceTest].astro between each test
globalThis.isCalledOnce = false; globalThis.isCalledOnce = false;
@ -26,24 +34,19 @@ describe('prerender getStaticPaths - build calls', () => {
}); });
it('Astro.url sets the current pathname', async () => { it('Astro.url sets the current pathname', async () => {
const html = await fixture.readFile('/food/tacos/index.html'); const html = await fixture.readFile('/client/food/tacos/index.html');
const $ = cheerio.load(html); const $ = cheerio.load(html);
expect($('#props').text()).to.equal('10'); expect($('#props').text()).to.equal('10');
expect($('#url').text()).to.equal('/blog/food/tacos/'); expect($('#url').text()).to.equal('/blog/food/tacos/');
}); });
}); });
describe('prerender getStaticPaths - dev calls', () => { describe('getStaticPaths - dev calls', () => {
let fixture;
let devServer; let devServer;
before(async () => { before(async () => {
globalThis.isCalledOnce = false; globalThis.isCalledOnce = false;
fixture = await loadFixture({
root: './fixtures/ssr-prerender-get-static-paths/',
site: 'https://mysite.dev/',
});
devServer = await fixture.startDevServer(); devServer = await fixture.startDevServer();
}); });
@ -57,37 +60,38 @@ describe('prerender getStaticPaths - dev calls', () => {
}); });
it('only calls prerender getStaticPaths once', async () => { it('only calls prerender getStaticPaths once', async () => {
let res = await fixture.fetch('/a'); let res = await fixture.fetch('/blog/a');
expect(res.status).to.equal(200); expect(res.status).to.equal(200);
res = await fixture.fetch('/b'); res = await fixture.fetch('/blog/b');
expect(res.status).to.equal(200); expect(res.status).to.equal(200);
res = await fixture.fetch('/c'); res = await fixture.fetch('/blog/c');
expect(res.status).to.equal(200); expect(res.status).to.equal(200);
}); });
describe('404 behavior', () => { describe('404 behavior', () => {
it('resolves 200 on matching static path - named params', async () => { it('resolves 200 on matching static path - named params', async () => {
const res = await fixture.fetch('/pizza/provolone-sausage'); const res = await fixture.fetch('/blog/pizza/provolone-sausage');
expect(res.status).to.equal(200); expect(res.status).to.equal(200);
}); });
it('resolves 404 on pattern match without static path - named params', async () => { it('resolves 404 on pattern match without static path - named params', async () => {
const res = await fixture.fetch('/pizza/provolone-pineapple'); const res = await fixture.fetch('/blog/pizza/provolone-pineapple');
const html = await res.text(); const html = await res.text();
expect(res.status).to.equal(404); expect(res.status).to.equal(404);
expect(html).to.match(/404/); expect(html).to.match(/404/);
}); });
it('resolves 200 on matching static path - rest params', async () => { it('resolves 200 on matching static path - rest params', async () => {
const res = await fixture.fetch('/pizza/grimaldis/new-york'); const res = await fixture.fetch('/blog/pizza/grimaldis/new-york');
expect(res.status).to.equal(200); expect(res.status).to.equal(200);
}); });
it('resolves 404 on pattern match without static path - rest params', async () => { it('resolves 404 on pattern match without static path - rest params', async () => {
const res = await fixture.fetch('/pizza/pizza-hut'); const res = await fixture.fetch('/blog/pizza/pizza-hut');
const html = await res.text(); const html = await res.text();
expect(res.status).to.equal(404); expect(res.status).to.equal(404);
expect(html).to.match(/404/); expect(html).to.match(/404/);
}); });
@ -95,19 +99,19 @@ describe('prerender getStaticPaths - dev calls', () => {
describe('route params type validation', () => { describe('route params type validation', () => {
it('resolves 200 on nested array parameters', async () => { it('resolves 200 on nested array parameters', async () => {
const res = await fixture.fetch('/nested-arrays/slug1'); const res = await fixture.fetch('/blog/nested-arrays/slug1');
expect(res.status).to.equal(200); expect(res.status).to.equal(200);
}); });
it('resolves 200 on matching static path - string params', async () => { it('resolves 200 on matching static path - string params', async () => {
// route provided with { params: { year: "2022", slug: "post-2" }} // route provided with { params: { year: "2022", slug: "post-2" }}
const res = await fixture.fetch('/blog/2022/post-1'); const res = await fixture.fetch('/blog/blog/2022/post-1');
expect(res.status).to.equal(200); expect(res.status).to.equal(200);
}); });
it('resolves 200 on matching static path - numeric params', async () => { it('resolves 200 on matching static path - numeric params', async () => {
// route provided with { params: { year: 2022, slug: "post-2" }} // route provided with { params: { year: 2022, slug: "post-2" }}
const res = await fixture.fetch('/blog/2022/post-2'); const res = await fixture.fetch('/blog/blog/2022/post-2');
expect(res.status).to.equal(200); expect(res.status).to.equal(200);
}); });
}); });
@ -115,7 +119,7 @@ describe('prerender getStaticPaths - dev calls', () => {
it('resolves 200 on matching static paths', async () => { it('resolves 200 on matching static paths', async () => {
// routes params provided for pages /posts/1, /posts/2, and /posts/3 // routes params provided for pages /posts/1, /posts/2, and /posts/3
for (const page of [1, 2, 3]) { for (const page of [1, 2, 3]) {
let res = await fixture.fetch(`/posts/${page}`); let res = await fixture.fetch(`/blog/posts/${page}`);
expect(res.status).to.equal(200); expect(res.status).to.equal(200);
const html = await res.text(); const html = await res.text();
@ -123,9 +127,165 @@ describe('prerender getStaticPaths - dev calls', () => {
const canonical = $('link[rel=canonical]'); const canonical = $('link[rel=canonical]');
expect(canonical.attr('href')).to.equal( expect(canonical.attr('href')).to.equal(
`https://mysite.dev/posts/${page}`, `https://mysite.dev/blog/posts/${page}`,
`doesn't trim the /${page} route param` `doesn't trim the /${page} route param`
); );
} }
}); });
});
});
describe('output: "hybrid"', () => {
describe('getStaticPaths - build calls', () => {
before(async () => {
fixture = await loadFixture({
root: './fixtures/ssr-prerender-get-static-paths/',
site: 'https://mysite.dev/',
adapter: testAdapter(),
base: '/blog',
output: 'hybrid',
experimental: {
hybridOutput: true,
},
vite: {
plugins: [vitePluginRemovePrerenderExport()],
},
});
await fixture.build();
});
after(async () => {
await fixture.clean();
});
afterEach(() => {
// reset the flag used by [...calledTwiceTest].astro between each test
globalThis.isCalledOnce = false;
});
it('is only called once during build', () => {
// useless expect; if build() throws in setup then this test fails
expect(true).to.equal(true);
});
it('Astro.url sets the current pathname', async () => {
const html = await fixture.readFile('/client/food/tacos/index.html');
const $ = cheerio.load(html);
expect($('#props').text()).to.equal('10');
expect($('#url').text()).to.equal('/blog/food/tacos/');
});
});
describe('getStaticPaths - dev calls', () => {
let devServer;
before(async () => {
globalThis.isCalledOnce = false;
devServer = await fixture.startDevServer();
});
afterEach(() => {
// reset the flag used by [...calledTwiceTest].astro between each test
globalThis.isCalledOnce = false;
});
after(async () => {
devServer.stop();
});
it('only calls hybrid getStaticPaths once', async () => {
let res = await fixture.fetch('/blog/a');
expect(res.status).to.equal(200);
res = await fixture.fetch('/blog/b');
expect(res.status).to.equal(200);
res = await fixture.fetch('/blog/c');
expect(res.status).to.equal(200);
});
describe('404 behavior', () => {
it('resolves 200 on matching static path - named params', async () => {
const res = await fixture.fetch('/blog/pizza/provolone-sausage');
expect(res.status).to.equal(200);
});
it('resolves 404 on pattern match without static path - named params', async () => {
const res = await fixture.fetch('/blog/pizza/provolone-pineapple');
const html = await res.text();
expect(res.status).to.equal(404);
expect(html).to.match(/404/);
});
it('resolves 200 on matching static path - rest params', async () => {
const res = await fixture.fetch('/blog/pizza/grimaldis/new-york');
expect(res.status).to.equal(200);
});
it('resolves 404 on pattern match without static path - rest params', async () => {
const res = await fixture.fetch('/blog/pizza/pizza-hut');
const html = await res.text();
expect(res.status).to.equal(404);
expect(html).to.match(/404/);
});
});
describe('route params type validation', () => {
it('resolves 200 on nested array parameters', async () => {
const res = await fixture.fetch('/blog/nested-arrays/slug1');
expect(res.status).to.equal(200);
});
it('resolves 200 on matching static path - string params', async () => {
// route provided with { params: { year: "2022", slug: "post-2" }}
const res = await fixture.fetch('/blog/blog/2022/post-1');
expect(res.status).to.equal(200);
});
it('resolves 200 on matching static path - numeric params', async () => {
// route provided with { params: { year: 2022, slug: "post-2" }}
const res = await fixture.fetch('/blog/blog/2022/post-2');
expect(res.status).to.equal(200);
});
});
it('resolves 200 on matching static paths', async () => {
// routes params provided for pages /posts/1, /posts/2, and /posts/3
for (const page of [1, 2, 3]) {
let res = await fixture.fetch(`/blog/posts/${page}`);
expect(res.status).to.equal(200);
const html = await res.text();
const $ = cheerio.load(html);
const canonical = $('link[rel=canonical]');
expect(canonical.attr('href')).to.equal(
`https://mysite.dev/blog/posts/${page}`,
`doesn't trim the /${page} route param`
);
}
});
});
});
}); });
/** @returns {import('vite').Plugin} */
function vitePluginRemovePrerenderExport() {
const EXTENSIONS = ['.astro', '.ts'];
/** @type {import('vite').Plugin} */
const plugin = {
name: 'remove-prerender-export',
transform(code, id) {
if (!EXTENSIONS.some((ext) => id.endsWith(ext))) return;
return code.replace(/export\s+const\s+prerender\s+=\s+true;/g, '');
},
};
return {
name: 'remove-prerender-export-injector',
configResolved(resolved) {
resolved.plugins.unshift(plugin);
},
};
}

View file

@ -42,7 +42,7 @@
"tiny-glob": "^0.2.9" "tiny-glob": "^0.2.9"
}, },
"peerDependencies": { "peerDependencies": {
"astro": "workspace:^2.5.0" "astro": "workspace:^2.5.2"
}, },
"devDependencies": { "devDependencies": {
"astro": "workspace:*", "astro": "workspace:*",

View file

@ -36,7 +36,7 @@
"esbuild": "^0.15.18" "esbuild": "^0.15.18"
}, },
"peerDependencies": { "peerDependencies": {
"astro": "workspace:^2.5.0" "astro": "workspace:^2.5.2"
}, },
"devDependencies": { "devDependencies": {
"astro": "workspace:*", "astro": "workspace:*",

View file

@ -62,7 +62,7 @@
"vite": "^4.3.1" "vite": "^4.3.1"
}, },
"peerDependencies": { "peerDependencies": {
"astro": "workspace:^2.5.0", "astro": "workspace:^2.5.2",
"sharp": ">=0.31.0" "sharp": ">=0.31.0"
}, },
"peerDependenciesMeta": { "peerDependenciesMeta": {

View file

@ -1,5 +1,14 @@
# @astrojs/markdoc # @astrojs/markdoc
## 0.2.1
### Patch Changes
- [#7141](https://github.com/withastro/astro/pull/7141) [`a9e1cd7e5`](https://github.com/withastro/astro/commit/a9e1cd7e58794fe220539c2ed935c9eb96bab55a) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Fix inconsistent Markdoc heading IDs for documents with the same headings.
- Updated dependencies [[`72f686a68`](https://github.com/withastro/astro/commit/72f686a68930de52f9a274c13c98acad59925b31), [`319a0a7a0`](https://github.com/withastro/astro/commit/319a0a7a0a6a950387c942b467746d590bb32fda), [`852d59a8d`](https://github.com/withastro/astro/commit/852d59a8d68e124f10852609e0f1619d5838ac76), [`530fb9ebe`](https://github.com/withastro/astro/commit/530fb9ebee77646921ec29d45d9b66484bdfb521), [`3257dd289`](https://github.com/withastro/astro/commit/3257dd28901c785a6a661211b98c5ef2cb3b9aa4)]:
- astro@2.5.1
## 0.2.0 ## 0.2.0
### Minor Changes ### Minor Changes

View file

@ -1,7 +1,7 @@
{ {
"name": "@astrojs/markdoc", "name": "@astrojs/markdoc",
"description": "Add support for Markdoc pages in your Astro site", "description": "Add support for Markdoc pages in your Astro site",
"version": "0.2.0", "version": "0.2.1",
"type": "module", "type": "module",
"types": "./dist/index.d.ts", "types": "./dist/index.d.ts",
"author": "withastro", "author": "withastro",
@ -47,7 +47,7 @@
"zod": "^3.17.3" "zod": "^3.17.3"
}, },
"peerDependencies": { "peerDependencies": {
"astro": "workspace:^2.5.0" "astro": "workspace:^2.5.2"
}, },
"devDependencies": { "devDependencies": {
"@astrojs/markdown-remark": "^2.2.1", "@astrojs/markdown-remark": "^2.2.1",

View file

@ -42,7 +42,7 @@
"esbuild": "^0.15.18" "esbuild": "^0.15.18"
}, },
"peerDependencies": { "peerDependencies": {
"astro": "workspace:^2.5.0" "astro": "workspace:^2.5.2"
}, },
"devDependencies": { "devDependencies": {
"@netlify/edge-functions": "^2.0.0", "@netlify/edge-functions": "^2.0.0",

View file

@ -38,7 +38,7 @@
"server-destroy": "^1.0.1" "server-destroy": "^1.0.1"
}, },
"peerDependencies": { "peerDependencies": {
"astro": "workspace:^2.5.0" "astro": "workspace:^2.5.2"
}, },
"devDependencies": { "devDependencies": {
"@types/send": "^0.17.1", "@types/send": "^0.17.1",

View file

@ -1,5 +1,11 @@
# @astrojs/prefetch # @astrojs/prefetch
## 0.2.3
### Patch Changes
- [#7123](https://github.com/withastro/astro/pull/7123) [`147373722`](https://github.com/withastro/astro/commit/147373722b37126af949bb054a1cdfb0aed6c2ff) Thanks [@connor-baer](https://github.com/connor-baer)! - Fix the inclusion of `@types/network-information`.
## 0.2.2 ## 0.2.2
### Patch Changes ### Patch Changes

View file

@ -1,7 +1,7 @@
{ {
"name": "@astrojs/prefetch", "name": "@astrojs/prefetch",
"description": "Prefetch page navigations in your Astro site", "description": "Prefetch page navigations in your Astro site",
"version": "0.2.2", "version": "0.2.3",
"type": "module", "type": "module",
"types": "./dist/index.d.ts", "types": "./dist/index.d.ts",
"author": "withastro", "author": "withastro",

View file

@ -48,7 +48,7 @@
"vite": "^4.3.1" "vite": "^4.3.1"
}, },
"peerDependencies": { "peerDependencies": {
"astro": "workspace:^2.5.0", "astro": "workspace:^2.5.2",
"svelte": "^3.54.0" "svelte": "^3.54.0"
}, },
"engines": { "engines": {

View file

@ -44,7 +44,7 @@
"vite": "^4.3.1" "vite": "^4.3.1"
}, },
"peerDependencies": { "peerDependencies": {
"astro": "workspace:^2.5.0", "astro": "workspace:^2.5.2",
"tailwindcss": "^3.0.24" "tailwindcss": "^3.0.24"
}, },
"pnpm": { "pnpm": {

View file

@ -59,7 +59,7 @@
"web-vitals": "^3.1.1" "web-vitals": "^3.1.1"
}, },
"peerDependencies": { "peerDependencies": {
"astro": "workspace:^2.5.0" "astro": "workspace:^2.5.2"
}, },
"devDependencies": { "devDependencies": {
"@types/set-cookie-parser": "^2.4.2", "@types/set-cookie-parser": "^2.4.2",

View file

@ -56,7 +56,7 @@
"vue": "^3.2.37" "vue": "^3.2.37"
}, },
"peerDependencies": { "peerDependencies": {
"astro": "workspace:^2.5.0", "astro": "workspace:^2.5.2",
"vue": "^3.2.30" "vue": "^3.2.30"
}, },
"engines": { "engines": {

View file

@ -5759,7 +5759,7 @@ packages:
resolution: {integrity: sha512-kkH7sWzKPq0xt3H1n+ghb4xEMP8k0U7XV3kkB+ZGy69kDk2ySFW1qPi06sjKzFY3t1j6XbJSqr4mF9L7CYVyhg==} resolution: {integrity: sha512-kkH7sWzKPq0xt3H1n+ghb4xEMP8k0U7XV3kkB+ZGy69kDk2ySFW1qPi06sjKzFY3t1j6XbJSqr4mF9L7CYVyhg==}
engines: {node: '>=6.9.0'} engines: {node: '>=6.9.0'}
dependencies: dependencies:
'@babel/types': 7.18.4 '@babel/types': 7.21.5
dev: false dev: false
/@babel/helper-module-imports@7.21.4: /@babel/helper-module-imports@7.21.4:
@ -5853,7 +5853,6 @@ packages:
/@babel/helper-string-parser@7.21.5: /@babel/helper-string-parser@7.21.5:
resolution: {integrity: sha512-5pTUx3hAJaZIdW99sJ6ZUUgWq/Y+Hja7TowEnLNMm1VivRgZQL3vpBY3qUACVsvw+yQU6+YgfBVmcbLaZtrA1w==} resolution: {integrity: sha512-5pTUx3hAJaZIdW99sJ6ZUUgWq/Y+Hja7TowEnLNMm1VivRgZQL3vpBY3qUACVsvw+yQU6+YgfBVmcbLaZtrA1w==}
engines: {node: '>=6.9.0'} engines: {node: '>=6.9.0'}
dev: false
/@babel/helper-validator-identifier@7.19.1: /@babel/helper-validator-identifier@7.19.1:
resolution: {integrity: sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==} resolution: {integrity: sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==}
@ -5907,8 +5906,7 @@ packages:
engines: {node: '>=6.0.0'} engines: {node: '>=6.0.0'}
hasBin: true hasBin: true
dependencies: dependencies:
'@babel/types': 7.18.4 '@babel/types': 7.21.5
dev: false
/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.18.6(@babel/core@7.18.2): /@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.18.6(@babel/core@7.18.2):
resolution: {integrity: sha512-Dgxsyg54Fx1d4Nge8UnvTrED63vrwOdPmyvPzlNN/boaliRP54pm3pGzZD1SJUwrBA+Cs/xdG8kXX6Mn/RfISQ==} resolution: {integrity: sha512-Dgxsyg54Fx1d4Nge8UnvTrED63vrwOdPmyvPzlNN/boaliRP54pm3pGzZD1SJUwrBA+Cs/xdG8kXX6Mn/RfISQ==}
@ -6996,7 +6994,7 @@ packages:
'@babel/helper-plugin-utils': 7.21.5 '@babel/helper-plugin-utils': 7.21.5
'@babel/plugin-proposal-unicode-property-regex': 7.18.6(@babel/core@7.18.2) '@babel/plugin-proposal-unicode-property-regex': 7.18.6(@babel/core@7.18.2)
'@babel/plugin-transform-dotall-regex': 7.18.6(@babel/core@7.18.2) '@babel/plugin-transform-dotall-regex': 7.18.6(@babel/core@7.18.2)
'@babel/types': 7.18.4 '@babel/types': 7.21.5
esutils: 2.0.3 esutils: 2.0.3
dev: false dev: false
@ -7069,7 +7067,6 @@ packages:
'@babel/helper-string-parser': 7.21.5 '@babel/helper-string-parser': 7.21.5
'@babel/helper-validator-identifier': 7.19.1 '@babel/helper-validator-identifier': 7.19.1
to-fast-properties: 2.0.0 to-fast-properties: 2.0.0
dev: false
/@builder.io/partytown@0.7.4: /@builder.io/partytown@0.7.4:
resolution: {integrity: sha512-dcZBPNQiHbMhvDGmdWRFNe75Z/XYmeZ2bubYmC5BeQpF09ObbPcbSqIP2NaNOFonKlWLfsE6u1790o9ZmlfpIw==} resolution: {integrity: sha512-dcZBPNQiHbMhvDGmdWRFNe75Z/XYmeZ2bubYmC5BeQpF09ObbPcbSqIP2NaNOFonKlWLfsE6u1790o9ZmlfpIw==}
@ -8720,7 +8717,7 @@ packages:
/@ts-morph/common@0.16.0: /@ts-morph/common@0.16.0:
resolution: {integrity: sha512-SgJpzkTgZKLKqQniCjLaE3c2L2sdL7UShvmTmPBejAKd2OKV/yfMpQ2IWpAuA+VY5wy7PkSUaEObIqEK6afFuw==} resolution: {integrity: sha512-SgJpzkTgZKLKqQniCjLaE3c2L2sdL7UShvmTmPBejAKd2OKV/yfMpQ2IWpAuA+VY5wy7PkSUaEObIqEK6afFuw==}
dependencies: dependencies:
fast-glob: 3.2.11 fast-glob: 3.2.12
minimatch: 5.1.6 minimatch: 5.1.6
mkdirp: 1.0.4 mkdirp: 1.0.4
path-browserify: 1.0.1 path-browserify: 1.0.1
@ -9422,7 +9419,7 @@ packages:
/@vue/compiler-core@3.2.47: /@vue/compiler-core@3.2.47:
resolution: {integrity: sha512-p4D7FDnQb7+YJmO2iPEv0SQNeNzcbHdGByJDsT4lynf63AFkOTFN07HsiRSvjGo0QrxR/o3d0hUyNCUnBU2Tig==} resolution: {integrity: sha512-p4D7FDnQb7+YJmO2iPEv0SQNeNzcbHdGByJDsT4lynf63AFkOTFN07HsiRSvjGo0QrxR/o3d0hUyNCUnBU2Tig==}
dependencies: dependencies:
'@babel/parser': 7.18.4 '@babel/parser': 7.21.8
'@vue/shared': 3.2.47 '@vue/shared': 3.2.47
estree-walker: 2.0.2 estree-walker: 2.0.2
source-map: 0.6.1 source-map: 0.6.1
@ -9495,7 +9492,7 @@ packages:
/@vue/reactivity-transform@3.2.47: /@vue/reactivity-transform@3.2.47:
resolution: {integrity: sha512-m8lGXw8rdnPVVIdIFhf0LeQ/ixyHkH5plYuS83yop5n7ggVJU+z5v0zecwEnX7fa7HNLBhh2qngJJkxpwEEmYA==} resolution: {integrity: sha512-m8lGXw8rdnPVVIdIFhf0LeQ/ixyHkH5plYuS83yop5n7ggVJU+z5v0zecwEnX7fa7HNLBhh2qngJJkxpwEEmYA==}
dependencies: dependencies:
'@babel/parser': 7.18.4 '@babel/parser': 7.21.8
'@vue/compiler-core': 3.2.47 '@vue/compiler-core': 3.2.47
'@vue/shared': 3.2.47 '@vue/shared': 3.2.47
estree-walker: 2.0.2 estree-walker: 2.0.2
@ -10127,7 +10124,7 @@ packages:
/builtins@5.0.1: /builtins@5.0.1:
resolution: {integrity: sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==} resolution: {integrity: sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==}
dependencies: dependencies:
semver: 7.3.8 semver: 7.5.1
dev: true dev: true
/bundle-name@3.0.0: /bundle-name@3.0.0:
@ -14538,7 +14535,7 @@ packages:
resolution: {integrity: sha512-zNy02qivjjRosswoYmPi8hIKJRr8MpQyeKT6qlcq/OnOgA3Rhoae+IYOqsM9V5+JnHWmxKnWOT2GxvtqdtOCXA==} resolution: {integrity: sha512-zNy02qivjjRosswoYmPi8hIKJRr8MpQyeKT6qlcq/OnOgA3Rhoae+IYOqsM9V5+JnHWmxKnWOT2GxvtqdtOCXA==}
engines: {node: '>=10'} engines: {node: '>=10'}
dependencies: dependencies:
semver: 7.3.8 semver: 7.5.1
/node-addon-api@6.1.0: /node-addon-api@6.1.0:
resolution: {integrity: sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==} resolution: {integrity: sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==}
@ -14672,7 +14669,7 @@ packages:
dependencies: dependencies:
execa: 6.1.0 execa: 6.1.0
parse-package-name: 1.0.0 parse-package-name: 1.0.0
semver: 7.3.8 semver: 7.5.1
validate-npm-package-name: 4.0.0 validate-npm-package-name: 4.0.0
dev: true dev: true