Implement support for draft pages (#2392)
* feat: support draft pages * implemented support for draft pages * added integration test * updated relevant documentation (english only) * docs: explicitly mention "markdown draft pages" * chore: add changeset * chore: modify changeset - changed type to 'patch' - added more description
This commit is contained in:
parent
9278ecdc4c
commit
24aa3245ae
10 changed files with 141 additions and 9 deletions
15
.changeset/ten-cougars-knock.md
Normal file
15
.changeset/ten-cougars-knock.md
Normal file
|
@ -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.
|
||||||
|
```
|
|
@ -98,6 +98,7 @@ Markdown pages have a special frontmatter property for `layout`. This defines th
|
||||||
# src/pages/index.md
|
# src/pages/index.md
|
||||||
layout: ../../layouts/BaseLayout.astro
|
layout: ../../layouts/BaseLayout.astro
|
||||||
title: My cool page
|
title: My cool page
|
||||||
|
draft: false
|
||||||
---
|
---
|
||||||
|
|
||||||
# Hello World!
|
# Hello World!
|
||||||
|
@ -128,6 +129,7 @@ For Markdown files, the `content` prop also has an `astro` property which holds
|
||||||
"date": "Tuesday, July 27 2021",
|
"date": "Tuesday, July 27 2021",
|
||||||
"author": "Matthew Phillips",
|
"author": "Matthew Phillips",
|
||||||
"description": "Astro 0.18 is our biggest release since Astro launch.",
|
"description": "Astro 0.18 is our biggest release since Astro launch.",
|
||||||
|
"draft": false,
|
||||||
**/
|
**/
|
||||||
"astro": {
|
"astro": {
|
||||||
"headers": [
|
"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)`
|
- 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)
|
- 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 `<Markdown />` component, or remote markdown.
|
||||||
|
|
||||||
## Astro's Markdown Component
|
## 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 `<Markdown>` component, within your frontmatter block use the following import statement:
|
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 `<Markdown>` component, within your frontmatter block use the following import statement:
|
||||||
|
|
|
@ -61,7 +61,7 @@ The `renderers` option defines the framework renderers to be used by Astro.
|
||||||
|
|
||||||
#### buildOptions
|
#### 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
|
#### devOptions
|
||||||
|
|
||||||
|
|
|
@ -108,6 +108,13 @@ export interface AstroUserConfig {
|
||||||
* Default: 'directory'
|
* Default: 'directory'
|
||||||
*/
|
*/
|
||||||
pageUrlFormat?: 'file' | '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`. */
|
/** Options for the development server run with `astro dev`. */
|
||||||
devOptions?: {
|
devOptions?: {
|
||||||
|
|
|
@ -26,6 +26,7 @@ interface CLIState {
|
||||||
port?: number;
|
port?: number;
|
||||||
config?: string;
|
config?: string;
|
||||||
experimentalStaticBuild?: boolean;
|
experimentalStaticBuild?: boolean;
|
||||||
|
drafts?: boolean;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,6 +40,7 @@ function resolveArgs(flags: Arguments): CLIState {
|
||||||
config: typeof flags.config === 'string' ? flags.config : undefined,
|
config: typeof flags.config === 'string' ? flags.config : undefined,
|
||||||
hostname: typeof flags.hostname === 'string' ? flags.hostname : undefined,
|
hostname: typeof flags.hostname === 'string' ? flags.hostname : undefined,
|
||||||
experimentalStaticBuild: typeof flags.experimentalStaticBuild === 'boolean' ? flags.experimentalStaticBuild : false,
|
experimentalStaticBuild: typeof flags.experimentalStaticBuild === 'boolean' ? flags.experimentalStaticBuild : false,
|
||||||
|
drafts: typeof flags.drafts === 'boolean' ? flags.drafts : false,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (flags.version) {
|
if (flags.version) {
|
||||||
|
@ -76,6 +78,7 @@ function printHelp() {
|
||||||
--project-root <path> Specify the path to the project root folder.
|
--project-root <path> Specify the path to the project root folder.
|
||||||
--no-sitemap Disable sitemap generation (build only).
|
--no-sitemap Disable sitemap generation (build only).
|
||||||
--experimental-static-build A more performant build that expects assets to be define statically.
|
--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
|
--verbose Enable verbose logging
|
||||||
--silent Disable logging
|
--silent Disable logging
|
||||||
--version Show the version number and exit.
|
--version Show the version number and exit.
|
||||||
|
@ -99,6 +102,7 @@ function mergeCLIFlags(astroConfig: AstroConfig, flags: CLIState['options']) {
|
||||||
if (typeof flags.port === 'number') astroConfig.devOptions.port = flags.port;
|
if (typeof flags.port === 'number') astroConfig.devOptions.port = flags.port;
|
||||||
if (typeof flags.hostname === 'string') astroConfig.devOptions.hostname = flags.hostname;
|
if (typeof flags.hostname === 'string') astroConfig.devOptions.hostname = flags.hostname;
|
||||||
if (typeof flags.experimentalStaticBuild === 'boolean') astroConfig.buildOptions.experimentalStaticBuild = flags.experimentalStaticBuild;
|
if (typeof flags.experimentalStaticBuild === 'boolean') astroConfig.buildOptions.experimentalStaticBuild = flags.experimentalStaticBuild;
|
||||||
|
if (typeof flags.drafts === 'boolean') astroConfig.buildOptions.drafts = flags.drafts;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The primary CLI action */
|
/** The primary CLI action */
|
||||||
|
|
|
@ -85,6 +85,19 @@ class AstroBuilder {
|
||||||
routeCache: this.routeCache,
|
routeCache: this.routeCache,
|
||||||
viteServer: this.viteServer,
|
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));
|
debug(logging, 'build', timerMessage('All pages loaded', timer.loadStart));
|
||||||
|
|
||||||
// The names of each pages
|
// The names of each pages
|
||||||
|
|
|
@ -59,6 +59,7 @@ export const AstroConfigSchema = z.object({
|
||||||
.optional()
|
.optional()
|
||||||
.default('directory'),
|
.default('directory'),
|
||||||
experimentalStaticBuild: z.boolean().optional().default(false),
|
experimentalStaticBuild: z.boolean().optional().default(false),
|
||||||
|
drafts: z.boolean().optional().default(false),
|
||||||
})
|
})
|
||||||
.optional()
|
.optional()
|
||||||
.default({}),
|
.default({}),
|
||||||
|
|
47
packages/astro/test/astro-markdown-drafts.test.js
Normal file
47
packages/astro/test/astro-markdown-drafts.test.js
Normal file
|
@ -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');
|
||||||
|
});
|
||||||
|
});
|
7
packages/astro/test/fixtures/astro-markdown-drafts/src/pages/index.md
vendored
Normal file
7
packages/astro/test/fixtures/astro-markdown-drafts/src/pages/index.md
vendored
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
---
|
||||||
|
foo: bar
|
||||||
|
---
|
||||||
|
|
||||||
|
# Hello world
|
||||||
|
|
||||||
|
This should be visible.
|
8
packages/astro/test/fixtures/astro-markdown-drafts/src/pages/wip.md
vendored
Normal file
8
packages/astro/test/fixtures/astro-markdown-drafts/src/pages/wip.md
vendored
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
---
|
||||||
|
foo: bar
|
||||||
|
draft: true
|
||||||
|
---
|
||||||
|
|
||||||
|
# WIP
|
||||||
|
|
||||||
|
This is a draft. Don't build me!
|
Loading…
Reference in a new issue