[Content collections] Remove experimental flag (#5825)

* refactor: remove experimental.cc from core

* chore: remove experimental flag from tests

* fix: mock contentDir in remark tests

* fix: check vfile.path in rel-image-error plugin

* fix: move .astro/ excludes to all test/fixtures

* fix: include test/**/fixtures in ignore

* chore: changeset
This commit is contained in:
Ben Holmes 2023-01-11 12:51:31 -05:00 committed by GitHub
parent 665a2c2225
commit 52209ca2ad
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
27 changed files with 58 additions and 103 deletions

View file

@ -0,0 +1,14 @@
---
'astro': major
'@astrojs/mdx': major
'@astrojs/markdown-remark': major
---
Baseline the experimental `contentCollections` flag. You're free to remove this from your astro config!
```diff
import { defineConfig } from 'astro/config';
export default defineConfig({
- experimental: { contentCollections: true }
})

4
.gitignore vendored
View file

@ -24,3 +24,7 @@ packages/integrations/**/.netlify/
# exclude IntelliJ/WebStorm stuff
.idea
# ignore content collection generated files
packages/**/test/**/fixtures/**/.astro/
packages/**/test/**/fixtures/**/env.d.ts

View file

@ -7,7 +7,4 @@ import sitemap from '@astrojs/sitemap';
export default defineConfig({
site: 'https://example.com',
integrations: [mdx(), sitemap()],
experimental: {
contentCollections: true,
},
});

View file

@ -83,7 +83,6 @@ export interface CLIFlags {
port?: number;
config?: string;
drafts?: boolean;
experimentalContentCollections?: boolean;
}
export interface BuildConfig {
@ -911,34 +910,13 @@ export interface AstroUserConfig {
legacy?: object;
/**
* @docs
* @kind heading
* @name Experimental Flags
* @description
* Astro offers experimental flags to give users early access to new features.
* These flags are not guaranteed to be stable.
*/
experimental?: {
/**
* @docs
* @name experimental.contentCollections
* @type {boolean}
* @default `false`
* @version 1.7.0
* @description
* Enable experimental support for [Content Collections](https://docs.astro.build/en/guides/content-collections/). This makes the `src/content/` directory a reserved directory for Astro to manage, and introduces the `astro:content` module for querying this content.
*
* To enable this feature, set `experimental.contentCollections` to `true` in your Astro config:
*
* ```js
* {
* experimental: {
* contentCollections: true,
* },
* }
*/
contentCollections?: boolean;
};
experimental?: object;
// Legacy options to be removed

View file

@ -349,7 +349,6 @@ async function generatePath(
logging,
markdown: {
...settings.config.markdown,
isExperimentalContentCollections: settings.config.experimental.contentCollections,
contentDir: getContentPaths(settings.config).contentDir,
},
mode: opts.mode,

View file

@ -157,8 +157,7 @@ async function ssrBuild(opts: StaticBuildOptions, internals: BuildInternals, inp
}),
vitePluginPrerender(opts, internals),
...(viteConfig.plugins || []),
settings.config.experimental.contentCollections &&
astroBundleDelayedAssetPlugin({ internals }),
astroBundleDelayedAssetPlugin({ internals }),
// SSR needs to be last
ssr && vitePluginSSR(internals, settings.adapter!),
],

View file

@ -76,15 +76,13 @@ export function rollupPluginAstroBuildCSS(options: PluginOptions): VitePlugin[]
// For CSS, create a hash of all of the pages that use it.
// This causes CSS to be built into shared chunks when used by multiple pages.
if (isCSSRequest(id)) {
if (settings.config.experimental.contentCollections) {
for (const [pageInfo] of walkParentInfos(id, {
getModuleInfo: args[0].getModuleInfo,
})) {
if (new URL(pageInfo.id, 'file://').searchParams.has(DELAYED_ASSET_FLAG)) {
// Split delayed assets to separate modules
// so they can be injected where needed
return createNameHash(id, [id]);
}
for (const [pageInfo] of walkParentInfos(id, {
getModuleInfo: args[0].getModuleInfo,
})) {
if (new URL(pageInfo.id, 'file://').searchParams.has(DELAYED_ASSET_FLAG)) {
// Split delayed assets to separate modules
// so they can be injected where needed
return createNameHash(id, [id]);
}
}
return createNameForParentPages(id, args[0]);
@ -174,17 +172,10 @@ export function rollupPluginAstroBuildCSS(options: PluginOptions): VitePlugin[]
id,
this,
function until(importer) {
if (settings.config.experimental.contentCollections) {
// Short circuit when `contentCollections` is enabled.
return new URL(importer, 'file://').searchParams.has(DELAYED_ASSET_FLAG);
}
return false;
return new URL(importer, 'file://').searchParams.has(DELAYED_ASSET_FLAG);
}
)) {
if (
settings.config.experimental.contentCollections &&
new URL(pageInfo.id, 'file://').searchParams.has(DELAYED_ASSET_FLAG)
) {
if (new URL(pageInfo.id, 'file://').searchParams.has(DELAYED_ASSET_FLAG)) {
for (const parent of walkParentInfos(id, this)) {
const parentInfo = parent[0];
if (moduleIsTopLevelPage(parentInfo)) {

View file

@ -210,7 +210,6 @@ function buildManifest(
base: settings.config.base,
markdown: {
...settings.config.markdown,
isExperimentalContentCollections: settings.config.experimental.contentCollections,
contentDir: getContentPaths(settings.config).contentDir,
},
pageMap: null as any,

View file

@ -100,10 +100,6 @@ export function resolveFlags(flags: Partial<Flags>): CLIFlags {
host:
typeof flags.host === 'string' || typeof flags.host === 'boolean' ? flags.host : undefined,
drafts: typeof flags.drafts === 'boolean' ? flags.drafts : undefined,
experimentalContentCollections:
typeof flags.experimentalContentCollections === 'boolean'
? flags.experimentalContentCollections
: undefined,
};
}
@ -132,7 +128,6 @@ function mergeCLIFlags(astroConfig: AstroUserConfig, flags: CLIFlags) {
// TODO: Come back here and refactor to remove this expected error.
astroConfig.server.host = flags.host;
}
if (flags.experimentalContentCollections) astroConfig.experimental.contentCollections = true;
return astroConfig;
}

View file

@ -34,9 +34,6 @@ const ASTRO_CONFIG_DEFAULTS: AstroUserConfig & any = {
},
vite: {},
legacy: {},
experimental: {
contentCollections: false,
},
};
export const AstroConfigSchema = z.object({
@ -167,15 +164,7 @@ export const AstroConfigSchema = z.object({
vite: z
.custom<ViteUserConfig>((data) => data instanceof Object && !Array.isArray(data))
.default(ASTRO_CONFIG_DEFAULTS.vite),
experimental: z
.object({
contentCollections: z
.boolean()
.optional()
.default(ASTRO_CONFIG_DEFAULTS.experimental.contentCollections),
})
.optional()
.default({}),
experimental: z.object({}).optional().default({}),
legacy: z.object({}).optional().default({}),
});

View file

@ -104,13 +104,9 @@ export async function createVite(
astroHeadPropagationPlugin({ settings }),
astroScannerPlugin({ settings, logging }),
astroInjectEnvTsPlugin({ settings, logging, fs }),
...(settings.config.experimental.contentCollections
? [
astroContentVirtualModPlugin({ settings }),
astroContentServerPlugin({ fs, settings, logging, mode }),
astroDelayedAssetPlugin({ mode }),
]
: []),
astroContentVirtualModPlugin({ settings }),
astroContentServerPlugin({ fs, settings, logging, mode }),
astroDelayedAssetPlugin({ mode }),
],
publicDir: fileURLToPath(settings.config.publicDir),
root: fileURLToPath(settings.config.root),

View file

@ -24,7 +24,6 @@ export function createDevelopmentEnvironment(
logging,
markdown: {
...settings.config.markdown,
isExperimentalContentCollections: settings.config.experimental.contentCollections,
contentDir: getContentPaths(settings.config).contentDir,
},
mode,

View file

@ -71,7 +71,6 @@ export default function markdown({ settings, logging }: AstroPluginOptions): Plu
const renderResult = await renderMarkdown(raw.content, {
...settings.config.markdown,
fileURL: new URL(`file://${fileId}`),
isExperimentalContentCollections: settings.config.experimental.contentCollections,
contentDir: getContentPaths(settings.config).contentDir,
frontmatter: raw.data,
});

View file

@ -1,2 +0,0 @@
.astro/
env.d.ts

View file

@ -4,7 +4,4 @@ import mdx from '@astrojs/mdx';
// https://astro.build/config
export default defineConfig({
integrations: [mdx()],
experimental: {
contentCollections: true,
},
});

View file

@ -4,7 +4,4 @@ import mdx from '@astrojs/mdx';
// https://astro.build/config
export default defineConfig({
integrations: [mdx()],
experimental: {
contentCollections: true,
},
});

View file

@ -4,7 +4,4 @@ import mdx from '@astrojs/mdx';
// https://astro.build/config
export default defineConfig({
integrations: [mdx()],
experimental: {
contentCollections: true,
},
});

View file

@ -3,5 +3,4 @@ import mdx from '@astrojs/mdx';
export default defineConfig({
integrations: [mdx()],
experimental: { contentCollections: true },
});

View file

@ -47,7 +47,6 @@ describe('Content Collections - render()', () => {
userConfig: {
integrations: [mdx()],
vite: { server: { middlewareMode: true } },
experimental: { contentCollections: true },
},
},
async (container) => {
@ -121,7 +120,6 @@ describe('Content Collections - render()', () => {
userConfig: {
integrations: [mdx()],
vite: { server: { middlewareMode: true } },
experimental: { contentCollections: true },
},
},
async (container) => {
@ -193,7 +191,6 @@ describe('Content Collections - render()', () => {
userConfig: {
integrations: [mdx()],
vite: { server: { middlewareMode: true } },
experimental: { contentCollections: true },
},
},
async (container) => {
@ -259,7 +256,6 @@ describe('Content Collections - render()', () => {
userConfig: {
integrations: [mdx()],
vite: { server: { middlewareMode: true } },
experimental: { contentCollections: true },
},
},
async (container) => {

View file

@ -161,9 +161,8 @@ export async function getRemarkPlugins(
remarkPlugins = [...remarkPlugins, ...ignoreStringPlugins(mdxOptions.remarkPlugins)];
// Apply last in case user plugins resolve relative image paths
if (config.experimental.contentCollections) {
remarkPlugins.push(toRemarkContentRelImageError(config));
}
remarkPlugins.push(toRemarkContentRelImageError(config));
return remarkPlugins;
}

View file

@ -53,7 +53,6 @@ export async function renderMarkdown(
remarkRehype = markdownConfigDefaults.remarkRehype,
gfm = markdownConfigDefaults.gfm,
smartypants = markdownConfigDefaults.smartypants,
isExperimentalContentCollections = false,
contentDir,
frontmatter: userFrontmatter = {},
} = opts;
@ -91,9 +90,7 @@ export async function renderMarkdown(
}
// Apply later in case user plugins resolve relative image paths
if (isExperimentalContentCollections) {
parser.use([toRemarkContentRelImageError({ contentDir })]);
}
parser.use([toRemarkContentRelImageError({ contentDir })]);
parser.use([
[

View file

@ -10,6 +10,8 @@ import type { VFile } from 'vfile';
export default function toRemarkContentRelImageError({ contentDir }: { contentDir: URL }) {
return function remarkContentRelImageError() {
return (tree: any, vfile: VFile) => {
if (typeof vfile?.path !== 'string') return;
const isContentFile = pathToFileURL(vfile.path).href.startsWith(contentDir.href);
if (!isContentFile) return;

View file

@ -59,8 +59,6 @@ export interface MarkdownRenderingOptions extends AstroMarkdownOptions {
scopedClassName: string | null;
};
/** Used to prevent relative image imports from `src/content/` */
isExperimentalContentCollections?: boolean;
/** Used to prevent relative image imports from `src/content/` */
contentDir: URL;
/** Used for frontmatter injection plugins */
frontmatter?: Record<string, any>;

View file

@ -1,10 +1,14 @@
import { renderMarkdown } from '../dist/index.js';
import chai from 'chai';
import { mockRenderMarkdownParams } from './test-utils.js';
describe('autolinking', () => {
describe('plain md', () => {
it('autolinks URLs starting with a protocol in plain text', async () => {
const { code } = await renderMarkdown(`See https://example.com for more.`, {});
const { code } = await renderMarkdown(
`See https://example.com for more.`,
mockRenderMarkdownParams
);
chai
.expect(code.replace(/\n/g, ''))
@ -12,7 +16,10 @@ describe('autolinking', () => {
});
it('autolinks URLs starting with "www." in plain text', async () => {
const { code } = await renderMarkdown(`See www.example.com for more.`, {});
const { code } = await renderMarkdown(
`See www.example.com for more.`,
mockRenderMarkdownParams
);
chai
.expect(code.trim())
@ -22,7 +29,7 @@ describe('autolinking', () => {
it('does not autolink URLs in code blocks', async () => {
const { code } = await renderMarkdown(
'See `https://example.com` or `www.example.com` for more.',
{}
mockRenderMarkdownParams
);
chai

View file

@ -1,9 +1,13 @@
import { renderMarkdown } from '../dist/index.js';
import { expect } from 'chai';
import { mockRenderMarkdownParams } from './test-utils.js';
describe('entities', () => {
it('should not unescape entities in regular Markdown', async () => {
const { code } = await renderMarkdown(`&lt;i&gt;This should NOT be italic&lt;/i&gt;`, {});
const { code } = await renderMarkdown(
`&lt;i&gt;This should NOT be italic&lt;/i&gt;`,
mockRenderMarkdownParams
);
expect(code).to.equal(`<p>&#x3C;i>This should NOT be italic&#x3C;/i></p>`);
});

View file

@ -1,4 +1,5 @@
import { renderMarkdown } from '../dist/index.js';
import { mockRenderMarkdownParams } from './test-utils.js';
import chai from 'chai';
import { fileURLToPath } from 'node:url';
@ -8,6 +9,7 @@ describe('plugins', () => {
it('should be able to get file path when passing fileURL', async () => {
let context;
await renderMarkdown(`test`, {
...mockRenderMarkdownParams,
fileURL: new URL('virtual.md', import.meta.url),
remarkPlugins: [
function () {

View file

@ -0,0 +1,3 @@
export const mockRenderMarkdownParams = {
contentDir: new URL('file:///src/content/'),
};