0
Fork 0
mirror of https://github.com/withastro/astro.git synced 2024-12-30 22:03:56 -05:00

Remove deprecated features from Astro 3.0 (#9168)

This commit is contained in:
Bjorn Lu 2023-11-28 00:44:20 +08:00 committed by GitHub
parent c7953645ee
commit 153a5abb90
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
47 changed files with 95 additions and 398 deletions

View file

@ -0,0 +1,5 @@
---
'@astrojs/rss': major
---
Removes the `drafts` option as the feature is deprecated in Astro 3.0

View file

@ -0,0 +1,11 @@
---
'astro': major
---
Removes deprecated features from Astro 3.0
- Adapters are now required to pass `supportedAstroFeatures` to specify a list of features they support.
- The `build.split` and `build.excludeMiddleware` options are removed. Use `functionPerRoute` and `edgeMiddleware` from adapters instead.
- The `markdown.drafts` option and draft feature is removed. Use content collections instead.
- Lowercase endpoint names are no longer supported. Use uppercase endpoint names instead.
- `getHeaders()` exported from markdown files is removed. Use `getHeadings()` instead.

View file

@ -6,6 +6,7 @@ export function getAdapter(): AstroAdapter {
serverEntrypoint: '@benchmark/timer/server.js',
previewEntrypoint: '@benchmark/timer/preview.js',
exports: ['handler'],
supportedAstroFeatures: {},
};
}

View file

@ -28,7 +28,7 @@ Start by [adding a `site` to your project's `astro.config` for link generation](
import rss from '@astrojs/rss';
import { getCollection } from 'astro:content';
export async function get(context) {
export async function GET(context) {
const posts = await getCollection('blog');
return rss({
title: 'Buzzs Blog',
@ -55,7 +55,7 @@ Read **[Astro's RSS docs][astro-rss]** for more on using content collections, an
The `rss` default export offers a number of configuration options. Here's a quick reference:
```js
export function get(context) {
export function GET(context) {
return rss({
// `<title>` field in output xml
title: 'Buzzs Blog',
@ -98,7 +98,7 @@ The base URL to use when generating RSS item links. We recommend using the [endp
```ts
import rss from '@astrojs/rss';
export const get = (context) =>
export const GET = (context) =>
rss({
site: context.site,
// ...
@ -113,14 +113,6 @@ A list of formatted RSS feed items. See [Astro's RSS items documentation](https:
When providing a formatted RSS item list, see the [`RSSFeedItem` type reference](#rssfeeditem).
### drafts
Type: `boolean (optional)`
**Deprecated**: Manually filter `items` instead.
Set `drafts: true` to include [draft posts](https://docs.astro.build/en/guides/markdown-content/#draft-pages) in the feed output. By default, this option is `false` and draft posts are not included.
### stylesheet
Type: `string (optional)`
@ -136,7 +128,7 @@ A string of valid XML to be injected between your feed's `<description>` and `<i
```js
import rss from '@astrojs/rss';
export const get = () => rss({
export const GET = () => rss({
...
customData: '<language>en-us</language>',
});
@ -181,7 +173,7 @@ By default, the library will add trailing slashes to the emitted URLs. To preven
```js
import rss from '@astrojs/rss';
export const get = () =>
export const GET = () =>
rss({
trailingSlash: false,
});
@ -361,7 +353,7 @@ This function assumes, but does not verify, you are globbing for items inside `s
// src/pages/rss.xml.js
import rss, { pagesGlobToRssItems } from '@astrojs/rss';
export async function get(context) {
export async function GET(context) {
return rss({
title: 'Buzzs Blog',
description: 'A humble Astronauts guide to the stars',
@ -379,7 +371,7 @@ As `rss()` returns a `Response`, you can also use `getRssString()` to get the RS
// src/pages/rss.xml.js
import { getRssString } from '@astrojs/rss';
export async function get(context) {
export async function GET(context) {
const rssString = await getRssString({
title: 'Buzzs Blog',
...

View file

@ -27,11 +27,6 @@ export type RSSOptions = {
stylesheet?: z.infer<typeof rssOptionsValidator>['stylesheet'];
/** Specify custom data in opening of file */
customData?: z.infer<typeof rssOptionsValidator>['customData'];
/**
* Whether to include drafts or not
* @deprecated Deprecated since version 3.0. Use content collections instead.
*/
drafts?: z.infer<typeof rssOptionsValidator>['drafts'];
trailingSlash?: z.infer<typeof rssOptionsValidator>['trailingSlash'];
};
@ -48,11 +43,6 @@ export type RSSFeedItem = {
description?: z.infer<typeof rssSchema>['description'];
/** Append some other XML-valid data to this item */
customData?: z.infer<typeof rssSchema>['customData'];
/**
* Whether draft or not
* @deprecated Deprecated since version 3.0. Use content collections instead.
*/
draft?: z.infer<typeof rssSchema>['draft'];
/** Categories or tags related to the item */
categories?: z.infer<typeof rssSchema>['categories'];
/** The item author's email address */
@ -92,7 +82,6 @@ const rssOptionsValidator = z.object({
return items;
}),
xmlns: z.record(z.string()).optional(),
drafts: z.boolean().default(false),
stylesheet: z.union([z.string(), z.boolean()]).optional(),
customData: z.string().optional(),
trailingSlash: z.boolean().default(true),
@ -159,10 +148,7 @@ export function pagesGlobToRssItems(items: GlobResult): Promise<ValidatedRSSFeed
/** Generate RSS 2.0 feed */
async function generateRSS(rssOptions: ValidatedRSSOptions): Promise<string> {
const { site } = rssOptions;
const items = rssOptions.drafts
? rssOptions.items
: rssOptions.items.filter((item) => !item.draft);
const { items, site } = rssOptions;
const xmlOptions = {
ignoreAttributes: false,

View file

@ -8,7 +8,6 @@ export const rssSchema = z.object({
.refine((value) => !isNaN(value.getTime())),
description: z.string().optional(),
customData: z.string().optional(),
draft: z.boolean().optional(),
categories: z.array(z.string()).optional(),
author: z.string().optional(),
commentsUrl: z.string().optional(),

View file

@ -156,36 +156,12 @@ describe('getRssString', () => {
chai.expect(str).to.contain(customData);
});
it('should filter out entries marked as `draft`', async () => {
const str = await getRssString({
title,
description,
items: [phpFeedItem, { ...web1FeedItem, draft: true }],
site,
});
chai.expect(str).xml.to.equal(validXmlWithoutWeb1FeedResult);
});
it('should respect drafts option', async () => {
const str = await getRssString({
title,
description,
items: [phpFeedItem, { ...web1FeedItem, draft: true }],
site,
drafts: true,
});
chai.expect(str).xml.to.equal(validXmlResult);
});
it('should not append trailing slash to URLs with the given option', async () => {
const str = await getRssString({
title,
description,
items: [phpFeedItem, { ...web1FeedItem, draft: true }],
items: [phpFeedItem],
site,
drafts: true,
trailingSlash: false,
});

View file

@ -242,8 +242,6 @@ interface ExportedMarkdownModuleEntities {
file: MD['file'];
url: MD['url'];
getHeadings: MD['getHeadings'];
/** @deprecated Renamed to `getHeadings()` */
getHeaders: () => void;
Content: MD['Content'];
rawContent: MD['rawContent'];
compiledContent: MD['compiledContent'];

View file

@ -143,7 +143,6 @@ export interface CLIFlags {
host?: string | boolean;
port?: number;
config?: string;
drafts?: boolean;
open?: boolean;
}
@ -886,33 +885,6 @@ export interface AstroUserConfig {
* ```
*/
inlineStylesheets?: 'always' | 'auto' | 'never';
/**
* @docs
* @name build.split
* @type {boolean}
* @default `false`
* @deprecated Deprecated since version 3.0.
* @description
* The build config option `build.split` has been replaced by the adapter configuration option [`functionPerRoute`](/en/reference/adapter-reference/#functionperroute).
*
* Please see your [SSR adapter's documentation](/en/guides/integrations-guide/#official-integrations) for using `functionPerRoute` to define how your SSR code is bundled.
*
*/
split?: boolean;
/**
* @docs
* @name build.excludeMiddleware
* @type {boolean}
* @default `false`
* @deprecated Deprecated since version 3.0.
* @description
* The build config option `build.excludeMiddleware` has been replaced by the adapter configuration option [`edgeMiddleware`](/en/reference/adapter-reference/#edgemiddleware).
*
* Please see your [SSR adapter's documentation](/en/guides/integrations-guide/#official-integrations) for using `edgeMiddleware` to define whether or not any SSR middleware code will be bundled when built.
*/
excludeMiddleware?: boolean;
};
/**
@ -1183,28 +1155,6 @@ export interface AstroUserConfig {
* @name Markdown Options
*/
markdown?: {
/**
* @docs
* @name markdown.drafts
* @type {boolean}
* @default `false`
* @deprecated Deprecated since version 3.0. Use content collections instead.
* @description
* Control whether Markdown draft pages should be included in the build.
*
* A Markdown page is considered a draft if it includes `draft: true` in its frontmatter. Draft pages are always included & visible during development (`astro dev`) but by default they will not be included in your final build.
*
* ```js
* {
* markdown: {
* // Example: Include all drafts in your final build
* drafts: true,
* }
* }
* ```
*/
drafts?: boolean;
/**
* @docs
* @name markdown.shikiConfig
@ -1749,10 +1699,6 @@ export interface ComponentInstance {
css?: string[];
partial?: boolean;
prerender?: boolean;
/**
* Only used for logging if deprecated drafts feature is used
*/
frontmatter?: Record<string, any>;
getStaticPaths?: (options: GetStaticPathsOptions) => GetStaticPathsResult;
}
@ -2056,7 +2002,7 @@ export interface AstroAdapter {
*
* If the adapter is not able to handle certain configurations, Astro will throw an error.
*/
supportedAstroFeatures?: AstroFeatureMap;
supportedAstroFeatures: AstroFeatureMap;
}
type Body = string;
@ -2145,7 +2091,7 @@ export interface APIContext<
* ];
* }
*
* export async function get({ params }) {
* export async function GET({ params }) {
* return {
* body: `Hello user ${params.id}!`,
* }
@ -2168,7 +2114,7 @@ export interface APIContext<
* ];
* }
*
* export function get({ props }) {
* export function GET({ props }) {
* return {
* body: `Hello ${props.name}!`,
* }
@ -2184,7 +2130,7 @@ export interface APIContext<
* Example usage:
* ```ts
* // src/pages/secret.ts
* export function get({ redirect }) {
* export function GET({ redirect }) {
* return redirect('/login');
* }
* ```

View file

@ -14,7 +14,6 @@ export async function build({ flags }: BuildOptions) {
usage: '[...flags]',
tables: {
Flags: [
['--drafts', `Include Markdown draft pages in the build.`],
['--outDir <directory>', `Specify the output directory for the build.`],
['--help (-h)', 'See all available flags.'],
],

View file

@ -15,9 +15,6 @@ export function flagsToAstroInlineConfig(flags: Flags): AstroInlineConfig {
site: typeof flags.site === 'string' ? flags.site : undefined,
base: typeof flags.base === 'string' ? flags.base : undefined,
outDir: typeof flags.outDir === 'string' ? flags.outDir : undefined,
markdown: {
drafts: typeof flags.drafts === 'boolean' ? flags.drafts : undefined,
},
server: {
port: typeof flags.port === 'number' ? flags.port : undefined,
host:

View file

@ -111,16 +111,6 @@ async function getEntryForFallbackRoute(
return RedirectSinglePageBuiltModule;
}
function shouldSkipDraft(pageModule: ComponentInstance, settings: AstroSettings): boolean {
return (
// Drafts are disabled
!settings.config.markdown.drafts &&
// This is a draft post
'frontmatter' in pageModule &&
(pageModule as any).frontmatter?.draft === true
);
}
// Gives back a facadeId that is relative to the root.
// ie, src/pages/index.astro instead of /Users/name..../src/pages/index.astro
export function rootRelativeFacadeId(facadeId: string, settings: AstroSettings): string {
@ -185,11 +175,7 @@ export async function generatePages(opts: StaticBuildOptions, internals: BuildIn
if (pageData.route.prerender) {
const ssrEntryURLPage = createEntryURL(filePath, outFolder);
const ssrEntryPage = await import(ssrEntryURLPage.toString());
if (
// TODO: remove in Astro 4.0
opts.settings.config.build.split ||
opts.settings.adapter?.adapterFeatures?.functionPerRoute
) {
if (opts.settings.adapter?.adapterFeatures?.functionPerRoute) {
// forcing to use undefined, so we fail in an expected way if the module is not even there.
const ssrEntry = ssrEntryPage?.pageModule;
if (ssrEntry) {
@ -244,10 +230,7 @@ export async function generatePages(opts: StaticBuildOptions, internals: BuildIn
await queue.onIdle();
const assetsTimeEnd = performance.now();
logger.info(
null,
green(`✓ Completed in ${getTimeStat(assetsTimer, assetsTimeEnd)}.\n`)
);
logger.info(null, green(`✓ Completed in ${getTimeStat(assetsTimer, assetsTimeEnd)}.\n`));
delete globalThis?.astroAsset?.addStaticImage;
}
@ -302,16 +285,6 @@ async function generatePage(
);
}
const pageModule = await pageModulePromise();
// TODO: Remove in Astro 4.0
if (shouldSkipDraft(pageModule, pipeline.getSettings())) {
logger.info(null, `${magenta('⚠️')} Skipping draft ${pageData.route.component}`);
logger.warn(
null,
`The drafts feature is deprecated. You should migrate to content collections instead. See https://docs.astro.build/en/guides/content-collections/#filtering-collection-queries for more information.`
);
return;
}
const generationOptions: Readonly<GeneratePathOptions> = {
pageData,
linkIds,
@ -390,13 +363,13 @@ async function getPathsForRoute(
throw err;
});
const label = staticPaths.length === 1 ? 'page' : 'pages';
logger.debug(
'build',
`├── ${bold(green('✔'))} ${route.component}${magenta(
`[${staticPaths.length} ${label}]`
)}`
);
const label = staticPaths.length === 1 ? 'page' : 'pages';
logger.debug(
'build',
`├── ${bold(green('✔'))} ${route.component}${magenta(
`[${staticPaths.length} ${label}]`
)}`
);
paths.push(
...staticPaths

View file

@ -161,7 +161,7 @@ class AstroBuilder {
this.logger.info('build', `output: ${blue('"' + this.settings.config.output + '"')}`);
this.logger.info('build', `directory: ${blue(fileURLToPath(this.settings.config.outDir))}`);
if (this.settings.adapter) {
this.logger.info('build', `adapter: ${green(this.settings.adapter.name)}`);
this.logger.info('build', `adapter: ${green(this.settings.adapter.name)}`);
}
this.logger.info('build', 'Collecting build info...');
this.timer.loadStart = performance.now();
@ -253,32 +253,6 @@ class AstroBuilder {
`the outDir cannot be the root folder. Please build to a folder such as dist.`
);
}
// TODO: Remove in Astro 4.0
if (config.build.split === true) {
if (config.output === 'static') {
this.logger.warn(
'config',
'The option `build.split` won\'t take effect, because `output` is not `"server"` or `"hybrid"`.'
);
}
this.logger.warn(
'deprecated',
'The option `build.split` is deprecated. Use the adapter options.'
);
}
if (config.build.excludeMiddleware === true) {
if (config.output === 'static') {
this.logger.warn(
'config',
'The option `build.excludeMiddleware` won\'t take effect, because `output` is not `"server"` or `"hybrid"`.'
);
}
this.logger.warn(
'deprecated',
'The option `build.excludeMiddleware` is deprecated. Use the adapter options.'
);
}
}
/** Stats */

View file

@ -98,8 +98,6 @@ export function pluginManifest(
const manifest = await createManifest(options, internals);
const shouldPassMiddlewareEntryPoint =
// TODO: remove in Astro 4.0
options.settings.config.build.excludeMiddleware ||
options.settings.adapter?.adapterFeatures?.edgeMiddleware;
await runHookBuildSsr({
config: options.settings.config,

View file

@ -92,10 +92,6 @@ function vitePluginPages(opts: StaticBuildOptions, internals: BuildInternals): V
}
export function shouldBundleMiddleware(settings: AstroSettings) {
// TODO: Remove in Astro 4.0
if (settings.config.build.excludeMiddleware === true) {
return false;
}
if (settings.adapter?.adapterFeatures?.edgeMiddleware === true) {
return false;
}

View file

@ -102,10 +102,7 @@ export function pluginSSR(
hooks: {
'build:before': () => {
let vitePlugin =
ssr &&
// TODO: Remove in Astro 4.0
options.settings.config.build.split === false &&
functionPerRouteEnabled === false
ssr && functionPerRouteEnabled === false
? vitePluginSSR(internals, options.settings.adapter!, options)
: undefined;
@ -119,7 +116,7 @@ export function pluginSSR(
return;
}
if (options.settings.config.build.split || functionPerRouteEnabled) {
if (functionPerRouteEnabled) {
return;
}
@ -146,7 +143,7 @@ function vitePluginSSRSplit(
name: '@astrojs/vite-plugin-astro-ssr-split',
enforce: 'post',
options(opts) {
if (options.settings.config.build.split || functionPerRouteEnabled) {
if (functionPerRouteEnabled) {
const inputs = new Set<string>();
for (const [path, pageData] of eachPageFromAllPages(options.allPages)) {
@ -223,7 +220,7 @@ export function pluginSSRSplit(
hooks: {
'build:before': () => {
let vitePlugin =
ssr && (options.settings.config.build.split || functionPerRouteEnabled)
ssr && functionPerRouteEnabled
? vitePluginSSRSplit(internals, options.settings.adapter!, options)
: undefined;
@ -240,7 +237,7 @@ function generateSSRCode(config: AstroConfig, adapter: AstroAdapter) {
const imports: string[] = [];
const contents: string[] = [];
let pageMap;
if (config.build.split || isFunctionPerRouteEnabled(adapter)) {
if (isFunctionPerRouteEnabled(adapter)) {
pageMap = 'pageModule';
} else {
pageMap = 'pageMap';

View file

@ -67,7 +67,6 @@ export function resolveFlags(flags: Partial<Flags>): CLIFlags {
config: typeof flags.config === 'string' ? flags.config : undefined,
host:
typeof flags.host === 'string' || typeof flags.host === 'boolean' ? flags.host : undefined,
drafts: typeof flags.drafts === 'boolean' ? flags.drafts : undefined,
};
}

View file

@ -38,8 +38,6 @@ const ASTRO_CONFIG_DEFAULTS = {
serverEntry: 'entry.mjs',
redirects: true,
inlineStylesheets: 'auto',
split: false,
excludeMiddleware: false,
},
image: {
service: { entrypoint: 'astro/assets/services/sharp', config: {} },
@ -51,10 +49,7 @@ const ASTRO_CONFIG_DEFAULTS = {
open: false,
},
integrations: [],
markdown: {
drafts: false,
...markdownConfigDefaults,
},
markdown: markdownConfigDefaults,
vite: {},
legacy: {},
redirects: {},
@ -139,20 +134,6 @@ export const AstroConfigSchema = z.object({
.enum(['always', 'auto', 'never'])
.optional()
.default(ASTRO_CONFIG_DEFAULTS.build.inlineStylesheets),
/**
* @deprecated
* Use the adapter feature instead
*/
split: z.boolean().optional().default(ASTRO_CONFIG_DEFAULTS.build.split),
/**
* @deprecated
* Use the adapter feature instead
*/
excludeMiddleware: z
.boolean()
.optional()
.default(ASTRO_CONFIG_DEFAULTS.build.excludeMiddleware),
})
.default({}),
server: z.preprocess(
@ -245,7 +226,6 @@ export const AstroConfigSchema = z.object({
.default(ASTRO_CONFIG_DEFAULTS.image),
markdown: z
.object({
drafts: z.boolean().default(false),
syntaxHighlight: z
.union([z.literal('shiki'), z.literal('prism'), z.literal(false)])
.default(ASTRO_CONFIG_DEFAULTS.markdown.syntaxHighlight),
@ -452,12 +432,6 @@ export function createRelativeSchema(cmd: string, fileProtocolRoot: string) {
.enum(['always', 'auto', 'never'])
.optional()
.default(ASTRO_CONFIG_DEFAULTS.build.inlineStylesheets),
split: z.boolean().optional().default(ASTRO_CONFIG_DEFAULTS.build.split),
excludeMiddleware: z
.boolean()
.optional()
.default(ASTRO_CONFIG_DEFAULTS.build.excludeMiddleware),
})
.optional()
.default({}),

View file

@ -64,14 +64,6 @@ export async function renderPage({ mod, renderContext, env, cookies }: RenderPag
routingStrategy: renderContext.routingStrategy,
});
// TODO: Remove in Astro 4.0
if (mod.frontmatter && typeof mod.frontmatter === 'object' && 'draft' in mod.frontmatter) {
env.logger.warn(
null,
`The drafts feature is deprecated and used in ${renderContext.route.component}. You should migrate to content collections instead. See https://docs.astro.build/en/guides/content-collections/#filtering-collection-queries for more information.`
);
}
const response = await runtimeRenderPage(
result,
Component,

View file

@ -17,17 +17,6 @@ const UNSUPPORTED_ASSETS_FEATURE: AstroAssetsFeature = {
isSharpCompatible: false,
};
// NOTE: remove for Astro 4.0
const ALL_UNSUPPORTED: Required<AstroFeatureMap> = {
serverOutput: UNSUPPORTED,
staticOutput: UNSUPPORTED,
hybridOutput: UNSUPPORTED,
assets: UNSUPPORTED_ASSETS_FEATURE,
i18n: {
detectBrowserLanguage: UNSUPPORTED,
},
};
type ValidationResult = {
[Property in keyof AstroFeatureMap]: boolean;
};
@ -41,7 +30,7 @@ type ValidationResult = {
*/
export function validateSupportedFeatures(
adapterName: string,
featureMap: AstroFeatureMap = ALL_UNSUPPORTED,
featureMap: AstroFeatureMap,
config: AstroConfig,
logger: Logger
): ValidationResult {
@ -105,18 +94,21 @@ function validateSupportKind(
}
function featureIsUnsupported(adapterName: string, logger: Logger, featureName: string) {
logger.error(
'config',
`The feature ${featureName} is not supported (used by ${adapterName}).`
);
logger.error('config', `The feature ${featureName} is not supported (used by ${adapterName}).`);
}
function featureIsExperimental(adapterName: string, logger: Logger) {
logger.warn('config', `The feature is experimental and subject to change (used by ${adapterName}).`);
logger.warn(
'config',
`The feature is experimental and subject to change (used by ${adapterName}).`
);
}
function featureIsDeprecated(adapterName: string, logger: Logger) {
logger.warn('config', `The feature is deprecated and will be removed in the future (used by ${adapterName}).`);
logger.warn(
'config',
`The feature is deprecated and will be removed in the future (used by ${adapterName}).`
);
}
const SHARP_SERVICE = 'astro/assets/services/sharp';

View file

@ -244,10 +244,8 @@ export async function runHookConfigDone({
);
}
if (!adapter.supportedAstroFeatures) {
// NOTE: throw an error in Astro 4.0
logger.warn(
null,
`The adapter ${adapter.name} doesn't provide a feature map. From Astro 3.0, an adapter can provide a feature map. Not providing a feature map will cause an error in Astro 4.0.`
throw new Error(
`The adapter ${adapter.name} doesn't provide a feature map. It is required in Astro 4.0.`
);
} else {
const validationResult = validateSupportedFeatures(

View file

@ -2,35 +2,11 @@ import { bold } from 'kleur/colors';
import type { APIContext, EndpointHandler, Params } from '../../@types/astro.js';
import type { Logger } from '../../core/logger/core.js';
function getHandlerFromModule(mod: EndpointHandler, method: string, logger: Logger) {
const lowerCaseMethod = method.toLowerCase();
// TODO: remove in Astro 4.0
if (mod[lowerCaseMethod]) {
logger.warn(
null,
`Lower case endpoint names are deprecated and will not be supported in Astro 4.0. Rename the endpoint ${lowerCaseMethod} to ${method}.`
);
}
function getHandlerFromModule(mod: EndpointHandler, method: string) {
// If there was an exact match on `method`, return that function.
if (mod[method]) {
return mod[method];
}
// TODO: remove in Astro 4.0
if (mod[lowerCaseMethod]) {
return mod[lowerCaseMethod];
}
// TODO: remove in Astro 4.0
// Handle `del` instead of `delete`, since `delete` is a reserved word in JS.
if (method === 'delete' && mod['del']) {
return mod['del'];
}
// TODO: remove in Astro 4.0
// If a single `all` handler was used, return that function.
if (mod['all']) {
return mod['all'];
}
if (mod['ALL']) {
return mod['ALL'];
}
@ -48,9 +24,8 @@ export async function renderEndpoint(
const { request, url } = context;
const chosenMethod = request.method?.toUpperCase();
const handler = getHandlerFromModule(mod, chosenMethod, logger);
// TODO: remove the 'get' check in Astro 4.0
if (!ssr && ssr === false && chosenMethod && chosenMethod !== 'GET' && chosenMethod !== 'get') {
const handler = getHandlerFromModule(mod, chosenMethod);
if (!ssr && ssr === false && chosenMethod && chosenMethod !== 'GET') {
logger.warn(
null,
`${url.pathname} ${bold(

View file

@ -1,44 +0,0 @@
import { expect } from 'chai';
import * as cheerio from 'cheerio';
import { loadFixture } from './test-utils.js';
describe('Astro Markdown with draft posts disabled', () => {
let fixture;
before(async () => {
fixture = await loadFixture({
root: './fixtures/astro-markdown-drafts/',
});
await fixture.build();
});
it('Does not render the draft post', async () => {
let renderedDraft = false;
try {
await fixture.readFile('/wip/index.html');
renderedDraft = true;
} catch (err) {
expect(err.code).to.equal('ENOENT');
}
expect(renderedDraft).to.equal(false, 'Rendered a draft post');
});
});
describe('Astro Markdown with draft posts enabled', () => {
let fixture;
before(async () => {
fixture = await loadFixture({
root: './fixtures/astro-markdown-drafts/',
markdown: {
drafts: true,
},
});
await fixture.build();
});
it('Renders the draft post', async () => {
const html = await fixture.readFile('/wip/index.html');
const $ = cheerio.load(html);
expect($('h1').length).to.be.ok;
expect($('h1').text()).to.equal('WIP');
});
});

View file

@ -105,7 +105,6 @@ describe('Events', () => {
config: 'path/to/config.mjs',
experimentalSsr: true,
experimentalIntegrations: true,
drafts: true,
};
const [{ payload }] = events.eventCliSession(
{
@ -122,7 +121,6 @@ describe('Events', () => {
'config',
'experimentalSsr',
'experimentalIntegrations',
'drafts',
]);
});
});

View file

@ -10,14 +10,9 @@ describe('Adapter', () => {
fixture = await loadFixture({
root: './fixtures/middleware space/',
output: 'server',
build: {
excludeMiddleware: true,
},
adapter: testAdapter({
extendAdapter: {
supportsFeatures: {
edgeMiddleware: 'Unsupported',
},
supportedAstroFeatures: {},
},
}),
});
@ -34,14 +29,9 @@ describe('Adapter', () => {
fixture = await loadFixture({
root: './fixtures/middleware space/',
output: 'server',
build: {
split: true,
},
adapter: testAdapter({
extendAdapter: {
supportsFeatures: {
functionPerPage: 'Unsupported',
},
supportedAstroFeatures: {},
},
}),
});

View file

@ -1,8 +0,0 @@
{
"name": "@test/astro-markdown-drafts",
"version": "0.0.0",
"private": true,
"dependencies": {
"astro": "workspace:*"
}
}

View file

@ -1,7 +0,0 @@
---
foo: bar
---
# Hello world
This should be visible.

View file

@ -1,8 +0,0 @@
---
foo: bar
draft: true
---
# WIP
This is a draft. Don't build me!

View file

@ -21,7 +21,7 @@ This should also work outside of code blocks:
// src/pages/rss.xml.js
import rss from '@astrojs/rss';
export const get = () => rss({
export const GET = () => rss({
// Use Vite env vars with import.meta.env
site: import.meta.env.SITE,
title: import.meta.env.TITLE,

View file

@ -4,7 +4,7 @@ export function GET() {
return new Response('ok')
}
export async function post({ request }) {
export async function POST({ request }) {
const data = await request.formData();
const file = data.get('file');

View file

@ -1,4 +1,4 @@
export const get = () => {
export const GET = () => {
return new Response(
undefined,
{

View file

@ -277,6 +277,11 @@ describe('Middleware API in PROD mode, SSR', () => {
excludeMiddleware: true,
},
adapter: testAdapter({
extendAdapter: {
adapterFeatures: {
edgeMiddleware: true,
},
},
setMiddlewareEntryPoint(entryPointsOrMiddleware) {
middlewarePath = entryPointsOrMiddleware;
},
@ -317,7 +322,9 @@ describe('Middleware with tailwind', () => {
});
});
describe('Middleware, split middleware option', () => {
// `loadTestAdapterApp()` does not understand how to load the page with `functionPerRoute`
// since there's no `entry.mjs`. Skip for now.
describe.skip('Middleware supports functionPerRoute feature', () => {
/** @type {import('./test-utils').Fixture} */
let fixture;
@ -325,10 +332,13 @@ describe('Middleware, split middleware option', () => {
fixture = await loadFixture({
root: './fixtures/middleware space/',
output: 'server',
build: {
excludeMiddleware: true,
},
adapter: testAdapter({}),
adapter: testAdapter({
extendAdapter: {
adapterFeatures: {
functionPerRoute: true,
},
},
}),
});
await fixture.build();
});

View file

@ -47,6 +47,7 @@ describe('Integration buildConfig hook', () => {
name: 'my-ssr-adapter',
serverEntrypoint: '@my-ssr',
exports: ['manifest', 'createApp'],
supportedAstroFeatures: {},
});
},
},

View file

@ -77,15 +77,7 @@ export default function (
name: 'my-ssr-adapter',
serverEntrypoint: '@my-ssr',
exports: ['manifest', 'createApp'],
supportedFeatures: {
assets: {
supportKind: 'Stable',
isNodeCompatible: true,
},
serverOutput: 'Stable',
staticOutput: 'Stable',
hybridOutput: 'Stable',
},
supportedAstroFeatures: {},
...extendAdapter,
});
},

View file

@ -106,7 +106,7 @@ describe('Astro feature map', function () {
it('should not support the feature when not provided', () => {
let result = validateSupportedFeatures(
'test',
undefined,
{},
{
output: 'hybrid',
},

View file

@ -2,7 +2,7 @@ import { getCollection } from 'astro:content';
import { stringify } from 'devalue';
import { stripAllRenderFn } from '../../utils.js';
export async function get() {
export async function GET() {
const posts = await getCollection('blog');
return {
body: stringify(stripAllRenderFn(posts))

View file

@ -2,7 +2,7 @@ import { getEntryBySlug } from 'astro:content';
import { stringify } from 'devalue';
import { stripRenderFn } from '../../utils.js';
export async function get() {
export async function GET() {
const post = await getEntryBySlug('blog', 'post-1');
return {
body: stringify(stripRenderFn(post)),

View file

@ -83,11 +83,7 @@ You can configure how your MDX is rendered with the following options:
### Options inherited from Markdown config
All [`markdown` configuration options](https://docs.astro.build/en/reference/configuration-reference/#markdown-options) except `drafts` can be configured separately in the MDX integration. This includes remark and rehype plugins, syntax highlighting, and more. Options will default to those in your Markdown config ([see the `extendMarkdownConfig` option](#extendmarkdownconfig) to modify this).
:::note
There is no separate MDX configuration for [including pages marked as draft in the build](https://docs.astro.build/en/reference/configuration-reference/#markdowndrafts). This Markdown setting will be respected by both Markdown and MDX files and cannot be overridden for MDX files specifically.
:::
All [`markdown` configuration options](https://docs.astro.build/en/reference/configuration-reference/#markdown-options) can be configured separately in the MDX integration. This includes remark and rehype plugins, syntax highlighting, and more. Options will default to those in your Markdown config ([see the `extendMarkdownConfig` option](#extendmarkdownconfig) to modify this).
```js
// astro.config.mjs

View file

@ -1,4 +1,4 @@
export async function get() {
export async function GET() {
const docs = await import.meta.glob('./*.mdx', { eager: true });
return {
body: JSON.stringify(Object.values(docs).map(doc => doc.frontmatter)),

View file

@ -1,4 +1,4 @@
export async function get() {
export async function GET() {
const mdxPages = await import.meta.glob('./*.mdx', { eager: true });
return {

View file

@ -1,4 +1,4 @@
export async function get() {
export async function GET() {
const mdxPages = await import.meta.glob('./*.mdx', { eager: true });
return {

View file

@ -1,4 +1,4 @@
export async function get() {
export async function GET() {
const mdxPages = await import.meta.glob('./*.mdx', { eager: true });
return {

View file

@ -1,6 +1,6 @@
import { frontmatter } from './vite-env-vars.mdx';
export function get() {
export function GET() {
return {
body: JSON.stringify(frontmatter),
}

View file

@ -1,4 +1,4 @@
export async function get() {
export async function GET() {
let number = Math.random();
return {
body: JSON.stringify({

View file

@ -1,4 +1,4 @@
export async function get({}) {
export async function GET({}) {
return {
body: JSON.stringify({
name: 'Astro',

View file

@ -29,7 +29,7 @@ export { remarkShiki } from './remark-shiki.js';
export { createShikiHighlighter, replaceCssVariables, type ShikiHighlighter } from './shiki.js';
export * from './types.js';
export const markdownConfigDefaults: Omit<Required<AstroMarkdownOptions>, 'drafts'> = {
export const markdownConfigDefaults: Required<AstroMarkdownOptions> = {
syntaxHighlight: 'shiki',
shikiConfig: {
langs: [],

View file

@ -40,7 +40,6 @@ export interface ShikiConfig {
}
export interface AstroMarkdownOptions {
drafts?: boolean;
syntaxHighlight?: 'shiki' | 'prism' | false;
shikiConfig?: ShikiConfig;
remarkPlugins?: RemarkPlugins;