diff --git a/.changeset/ten-cougars-knock.md b/.changeset/ten-cougars-knock.md new file mode 100644 index 000000000..613616304 --- /dev/null +++ b/.changeset/ten-cougars-knock.md @@ -0,0 +1,15 @@ +--- +'astro': patch +--- + +Support markdown draft pages. +Markdown draft pages are markdown pages which have `draft` set in their frontmatter. By default, these will not be built by Astro while running `astro build`. To disable this behavior, you need to set `buildOptions.drafts` to `true` or pass the `--drafts` flag while running `astro build`. An exaple of a markdown draft page is: +```markdown +--- +# src/pages/blog-post.md +title: My Blog Post +draft: true +--- + +This is my blog post which is currently incomplete. +``` diff --git a/docs/src/pages/en/guides/markdown-content.md b/docs/src/pages/en/guides/markdown-content.md index da4e38985..85d9b9ed8 100644 --- a/docs/src/pages/en/guides/markdown-content.md +++ b/docs/src/pages/en/guides/markdown-content.md @@ -98,6 +98,7 @@ Markdown pages have a special frontmatter property for `layout`. This defines th # src/pages/index.md layout: ../../layouts/BaseLayout.astro title: My cool page +draft: false --- # Hello World! @@ -128,6 +129,7 @@ For Markdown files, the `content` prop also has an `astro` property which holds "date": "Tuesday, July 27 2021", "author": "Matthew Phillips", "description": "Astro 0.18 is our biggest release since Astro launch.", + "draft": false, **/ "astro": { "headers": [ @@ -159,6 +161,34 @@ Using images or videos follows Astro's normal import rules: - Example: Image is located at `/public/assets/img/astonaut.png` → Markdown: `![Astronaut](assets/img/astronaut.png)` - Or use `import` as explained on the [imports page](/en/guides/imports#other-assets) (when using Astro's Markdown Component) +### Markdown draft pages + +Markdown pages which have the property `draft` set in their frontmatter are referred to as "draft pages". By default, Astro excludes these pages from the build when building the static version of your page (i.e `astro build`), which means that you can exclude draft/incomplete pages from the production build by setting `draft` to `true`. To enable building of draft pages, you can set `buildOptions.drafts` to `true` in the configuration file, or pass the `--drafts` flag when running `astro build`. Markdown pages which do not have the `draft` property set are not affected. An example of a markdown draft page can be: + +```markdown +--- +# src/pages/blog-post.md +title: My Blog Post +draft: true +--- + +This is my blog post which is currently incomplete. +``` + +An example of a markdown post which is not a draft: + +```markdown +--- +# src/pages/blog-post.md +title: My Blog Post +draft: false +--- + +This is my blog post... +``` + +> This feature only applies to local markdown pages, not the `` component, or remote markdown. + ## Astro's Markdown Component Astro has a dedicated component used to let you render your markdown as HTML components. This is a special component that is only exposed to `.astro` files. To use the `` component, within your frontmatter block use the following import statement: diff --git a/docs/src/pages/en/reference/configuration-reference.md b/docs/src/pages/en/reference/configuration-reference.md index 7d6cb37e9..82c535a65 100644 --- a/docs/src/pages/en/reference/configuration-reference.md +++ b/docs/src/pages/en/reference/configuration-reference.md @@ -61,7 +61,7 @@ The `renderers` option defines the framework renderers to be used by Astro. #### buildOptions -The `buildOptions` option configures how a site is built, including its base URL (`buildOptions.site`), whether it includes a sitemap (`buildOptions.sitemap`), and whether its pages should be files (`path.html`) or directories (`path/index.html`) (`buildOptions.pageUrlFormat`). +The `buildOptions` option configures how a site is built, including its base URL (`buildOptions.site`), whether it includes a sitemap (`buildOptions.sitemap`), whether markdown draft pages should be included in the build (`buildOptions.drafts`), and whether its pages should be files (`path.html`) or directories (`path/index.html`) (`buildOptions.pageUrlFormat`). #### devOptions diff --git a/packages/astro/src/@types/astro.ts b/packages/astro/src/@types/astro.ts index 4185b25b8..a96bb10e9 100644 --- a/packages/astro/src/@types/astro.ts +++ b/packages/astro/src/@types/astro.ts @@ -108,6 +108,13 @@ export interface AstroUserConfig { * Default: 'directory' */ pageUrlFormat?: 'file' | 'directory'; + /** + * Control if markdown draft pages should be included in the build. + * `true`: Include draft pages + * `false`: Exclude draft pages + * Default: false + */ + drafts?: boolean; }; /** Options for the development server run with `astro dev`. */ devOptions?: { diff --git a/packages/astro/src/cli/index.ts b/packages/astro/src/cli/index.ts index 60fe945a2..0031a08ae 100644 --- a/packages/astro/src/cli/index.ts +++ b/packages/astro/src/cli/index.ts @@ -26,6 +26,7 @@ interface CLIState { port?: number; config?: string; experimentalStaticBuild?: boolean; + drafts?: boolean; }; } @@ -39,6 +40,7 @@ function resolveArgs(flags: Arguments): CLIState { config: typeof flags.config === 'string' ? flags.config : undefined, hostname: typeof flags.hostname === 'string' ? flags.hostname : undefined, experimentalStaticBuild: typeof flags.experimentalStaticBuild === 'boolean' ? flags.experimentalStaticBuild : false, + drafts: typeof flags.drafts === 'boolean' ? flags.drafts : false, }; if (flags.version) { @@ -72,14 +74,15 @@ function printHelp() { astro check Check your project for errors. ${colors.bold('Flags:')} - --config Specify the path to the Astro config file. - --project-root Specify the path to the project root folder. - --no-sitemap Disable sitemap generation (build only). - --experimental-static-build A more performant build that expects assets to be define statically. - --verbose Enable verbose logging - --silent Disable logging - --version Show the version number and exit. - --help Show this help message. + --config Specify the path to the Astro config file. + --project-root Specify the path to the project root folder. + --no-sitemap Disable sitemap generation (build only). + --experimental-static-build A more performant build that expects assets to be define statically. + --drafts Include markdown draft pages in the build. + --verbose Enable verbose logging + --silent Disable logging + --version Show the version number and exit. + --help Show this help message. `); } @@ -99,6 +102,7 @@ function mergeCLIFlags(astroConfig: AstroConfig, flags: CLIState['options']) { if (typeof flags.port === 'number') astroConfig.devOptions.port = flags.port; if (typeof flags.hostname === 'string') astroConfig.devOptions.hostname = flags.hostname; if (typeof flags.experimentalStaticBuild === 'boolean') astroConfig.buildOptions.experimentalStaticBuild = flags.experimentalStaticBuild; + if (typeof flags.drafts === 'boolean') astroConfig.buildOptions.drafts = flags.drafts; } /** The primary CLI action */ diff --git a/packages/astro/src/core/build/index.ts b/packages/astro/src/core/build/index.ts index 3c08f4f61..f6b379942 100644 --- a/packages/astro/src/core/build/index.ts +++ b/packages/astro/src/core/build/index.ts @@ -85,6 +85,19 @@ class AstroBuilder { routeCache: this.routeCache, viteServer: this.viteServer, }); + + // Filter pages by using conditions based on their frontmatter. + Object.entries(allPages).forEach(([page, data]) => { + if ('frontmatter' in data.preload[1]) { + // TODO: add better type inference to data.preload[1] + const frontmatter = (data.preload[1] as any).frontmatter; + if (Boolean(frontmatter.draft) && !this.config.buildOptions.drafts) { + debug(logging, 'build', timerMessage(`Skipping draft page ${page}`, timer.loadStart)); + delete allPages[page]; + } + } + }); + debug(logging, 'build', timerMessage('All pages loaded', timer.loadStart)); // The names of each pages diff --git a/packages/astro/src/core/config.ts b/packages/astro/src/core/config.ts index 1f8827023..6d5fd9a72 100644 --- a/packages/astro/src/core/config.ts +++ b/packages/astro/src/core/config.ts @@ -59,6 +59,7 @@ export const AstroConfigSchema = z.object({ .optional() .default('directory'), experimentalStaticBuild: z.boolean().optional().default(false), + drafts: z.boolean().optional().default(false), }) .optional() .default({}), diff --git a/packages/astro/test/astro-markdown-drafts.test.js b/packages/astro/test/astro-markdown-drafts.test.js new file mode 100644 index 000000000..beee3fd7f --- /dev/null +++ b/packages/astro/test/astro-markdown-drafts.test.js @@ -0,0 +1,47 @@ +import { expect } from 'chai'; +import cheerio from 'cheerio'; +import { loadFixture } from './test-utils.js'; + +describe('Astro Markdown with draft posts disabled', () => { + let fixture; + + before(async () => { + fixture = await loadFixture({ + projectRoot: './fixtures/astro-markdown-drafts/', + buildOptions: { + // drafts is false by default but added here for clarity + drafts: false, + sitemap: false, + }, + }); + await fixture.build(); + }); + it('Does not render the draft post', async () => { + try { + await fixture.readFile('/wip/index.html'); + } catch (err) { + expect(err.code).to.equal('ENOENT'); + } + }); +}); + +describe('Astro Markdown with draft posts enabled', () => { + let fixture; + + before(async () => { + fixture = await loadFixture({ + projectRoot: './fixtures/astro-markdown-drafts/', + buildOptions: { + drafts: true, + sitemap: false, + }, + }); + 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'); + }); +}); diff --git a/packages/astro/test/fixtures/astro-markdown-drafts/src/pages/index.md b/packages/astro/test/fixtures/astro-markdown-drafts/src/pages/index.md new file mode 100644 index 000000000..0e06444da --- /dev/null +++ b/packages/astro/test/fixtures/astro-markdown-drafts/src/pages/index.md @@ -0,0 +1,7 @@ +--- +foo: bar +--- + +# Hello world + +This should be visible. \ No newline at end of file diff --git a/packages/astro/test/fixtures/astro-markdown-drafts/src/pages/wip.md b/packages/astro/test/fixtures/astro-markdown-drafts/src/pages/wip.md new file mode 100644 index 000000000..27b829614 --- /dev/null +++ b/packages/astro/test/fixtures/astro-markdown-drafts/src/pages/wip.md @@ -0,0 +1,8 @@ +--- +foo: bar +draft: true +--- + +# WIP + +This is a draft. Don't build me! \ No newline at end of file