From a6f42fa4d7bc88a52c459b6837d156ccb5bd9d62 Mon Sep 17 00:00:00 2001 From: Matthew Phillips Date: Thu, 5 Oct 2023 10:54:40 -0400 Subject: [PATCH] Fragment support --- packages/astro/src/@types/astro.ts | 2 + packages/astro/src/core/render/core.ts | 1 + packages/astro/src/core/render/result.ts | 2 + .../src/runtime/server/render/astro/render.ts | 4 +- .../astro/src/runtime/server/render/common.ts | 4 +- .../test/fixtures/fragments/astro.config.mjs | 5 +++ .../test/fixtures/fragments/package.json | 8 ++++ .../fragments/src/pages/fragments/item.astro | 4 ++ packages/astro/test/fragments.test.js | 44 +++++++++++++++++++ pnpm-lock.yaml | 6 +++ 10 files changed, 76 insertions(+), 4 deletions(-) create mode 100644 packages/astro/test/fixtures/fragments/astro.config.mjs create mode 100644 packages/astro/test/fixtures/fragments/package.json create mode 100644 packages/astro/test/fixtures/fragments/src/pages/fragments/item.astro create mode 100644 packages/astro/test/fragments.test.js diff --git a/packages/astro/src/@types/astro.ts b/packages/astro/src/@types/astro.ts index 2217e76f2..20df3c26e 100644 --- a/packages/astro/src/@types/astro.ts +++ b/packages/astro/src/@types/astro.ts @@ -1520,6 +1520,7 @@ export type AsyncRendererComponentFn = ( export interface ComponentInstance { default: AstroComponentFactory; css?: string[]; + fragment?: boolean; prerender?: boolean; /** * Only used for logging if deprecated drafts feature is used @@ -2191,6 +2192,7 @@ export interface SSRResult { */ clientDirectives: Map; compressHTML: boolean; + fragment: boolean; /** * Only used for logging */ diff --git a/packages/astro/src/core/render/core.ts b/packages/astro/src/core/render/core.ts index d8c39ec1a..c470fa896 100644 --- a/packages/astro/src/core/render/core.ts +++ b/packages/astro/src/core/render/core.ts @@ -49,6 +49,7 @@ export async function renderPage({ mod, renderContext, env, cookies }: RenderPag clientDirectives: env.clientDirectives, compressHTML: env.compressHTML, request: renderContext.request, + fragment: !!mod.fragment, site: env.site, scripts: renderContext.scripts, ssr: env.ssr, diff --git a/packages/astro/src/core/render/result.ts b/packages/astro/src/core/render/result.ts index 6f8ca9303..0b210a43e 100644 --- a/packages/astro/src/core/render/result.ts +++ b/packages/astro/src/core/render/result.ts @@ -31,6 +31,7 @@ export interface CreateResultArgs { renderers: SSRLoadedRenderer[]; clientDirectives: Map; compressHTML: boolean; + fragment: boolean; resolve: (s: string) => Promise; /** * Used for `Astro.site` @@ -155,6 +156,7 @@ export function createResult(args: CreateResultArgs): SSRResult { renderers: args.renderers, clientDirectives: args.clientDirectives, compressHTML: args.compressHTML, + fragment: args.fragment, pathname: args.pathname, cookies, /** This function returns the `Astro` faux-global */ diff --git a/packages/astro/src/runtime/server/render/astro/render.ts b/packages/astro/src/runtime/server/render/astro/render.ts index 7091513c7..1794c8222 100644 --- a/packages/astro/src/runtime/server/render/astro/render.ts +++ b/packages/astro/src/runtime/server/render/astro/render.ts @@ -33,7 +33,7 @@ export async function renderToString( // Automatic doctype insertion for pages if (isPage && !renderedFirstPageChunk) { renderedFirstPageChunk = true; - if (!/' : '\n'; str += doctype; } @@ -84,7 +84,7 @@ export async function renderToReadableStream( // Automatic doctype insertion for pages if (isPage && !renderedFirstPageChunk) { renderedFirstPageChunk = true; - if (!/' : '\n'; controller.enqueue(encoder.encode(doctype)); } diff --git a/packages/astro/src/runtime/server/render/common.ts b/packages/astro/src/runtime/server/render/common.ts index 03e9c8308..d057ae8c5 100644 --- a/packages/astro/src/runtime/server/render/common.ts +++ b/packages/astro/src/runtime/server/render/common.ts @@ -77,13 +77,13 @@ function stringifyChunk( } } case 'head': { - if (result._metadata.hasRenderedHead) { + if (result._metadata.hasRenderedHead || result.fragment) { return ''; } return renderAllHeadContent(result); } case 'maybe-head': { - if (result._metadata.hasRenderedHead || result._metadata.headInTree) { + if (result._metadata.hasRenderedHead || result._metadata.headInTree || result.fragment) { return ''; } return renderAllHeadContent(result); diff --git a/packages/astro/test/fixtures/fragments/astro.config.mjs b/packages/astro/test/fixtures/fragments/astro.config.mjs new file mode 100644 index 000000000..8659ce894 --- /dev/null +++ b/packages/astro/test/fixtures/fragments/astro.config.mjs @@ -0,0 +1,5 @@ +import { defineConfig } from 'astro/config'; + +// https://astro.build/config +export default defineConfig({ +}); diff --git a/packages/astro/test/fixtures/fragments/package.json b/packages/astro/test/fixtures/fragments/package.json new file mode 100644 index 000000000..ff16efb0b --- /dev/null +++ b/packages/astro/test/fixtures/fragments/package.json @@ -0,0 +1,8 @@ +{ + "name": "@test/fragments", + "version": "0.0.0", + "private": true, + "dependencies": { + "astro": "workspace:*" + } +} diff --git a/packages/astro/test/fixtures/fragments/src/pages/fragments/item.astro b/packages/astro/test/fixtures/fragments/src/pages/fragments/item.astro new file mode 100644 index 000000000..413abda22 --- /dev/null +++ b/packages/astro/test/fixtures/fragments/src/pages/fragments/item.astro @@ -0,0 +1,4 @@ +--- +export const fragment = true; +--- +
  • This is a single line item
  • diff --git a/packages/astro/test/fragments.test.js b/packages/astro/test/fragments.test.js new file mode 100644 index 000000000..4ac0a09f3 --- /dev/null +++ b/packages/astro/test/fragments.test.js @@ -0,0 +1,44 @@ +import { expect } from 'chai'; +import * as cheerio from 'cheerio'; +import { loadFixture } from './test-utils.js'; + +describe('Fragments', () => { + /** @type {import('./test-utils.js').Fixture} */ + let fixture; + + before(async () => { + fixture = await loadFixture({ + root: './fixtures/fragments/', + }); + }); + + describe('dev', () => { + /** @type {import('./test-utils.js').DevServer} */ + let devServer; + + before(async () => { + devServer = await fixture.startDevServer(); + }); + + after(async () => { + await devServer.stop(); + }); + + it('is only the written HTML', async () => { + const html = await fixture.fetch('/fragments/item/').then((res) => res.text()); + expect(html.startsWith('
  • ')).to.equal(true); + }); + }); + + describe('build', () => { + before(async () => { + await fixture.build(); + }); + + it('is only the written HTML', async () => { + const html = await fixture.readFile('/fragments/item/index.html'); + expect(html.startsWith('
  • ')).to.equal(true); + }); + }); + +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d70075993..6b3124bc9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -2689,6 +2689,12 @@ importers: specifier: workspace:* version: link:../../.. + packages/astro/test/fixtures/fragments: + dependencies: + astro: + specifier: workspace:* + version: link:../../.. + packages/astro/test/fixtures/get-static-paths-pages: dependencies: astro: