Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/fix-dev-quit-fonts-dist.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'astro': patch
---

Fixes an issue where stopping the dev server with `q+enter` incorrectly created a `dist` folder and copied font files when using the experimental Fonts API
5 changes: 5 additions & 0 deletions .changeset/fix-react-mdx-nested-hydration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"astro": patch
---

Fixes hydration for React components nested inside HTML elements in MDX files
2 changes: 1 addition & 1 deletion .github/renovate.json5
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"labels": ["dependencies"],
"rangeStrategy": "bump",
"postUpdateOptions": ["pnpmDedupe"],
"lockfileMaintenance": {
"lockFileMaintenance": {
"enabled": true
},
"ignorePaths": [
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
export { default } from '../components/Layout.astro';
import Counter from '../components/Counter.jsx';

export const someProps = {
count: 0,
};

# Nested React Components in MDX

This tests that React components nested inside HTML elements still hydrate correctly.

<div class="wrapper">
<Counter id="nested-counter" {...someProps} client:load>
# Hello from nested component!
</Counter>
</div>
20 changes: 20 additions & 0 deletions packages/astro/e2e/react-component.test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { expect } from '@playwright/test';
import { prepareTestFactory } from './shared-component-tests.js';
import { waitForHydrate } from './test-utils.js';

const { test, createTests } = prepareTestFactory(import.meta.url, {
root: './fixtures/react-component/',
Expand Down Expand Up @@ -37,6 +38,25 @@ test.describe('dev', () => {
});
});

test.describe('React components nested in HTML elements in MDX', () => {
test('client:load nested in div', async ({ page, astro }) => {
await page.goto(astro.resolveUrl('/nested-in-div/'));

const counter = page.locator('#nested-counter');
await expect(counter, 'component is visible').toBeVisible();

const count = counter.locator('pre');
await expect(count, 'initial count is 0').toHaveText('0');

await waitForHydrate(page, counter);

const inc = counter.locator('.increment');
await inc.click();

await expect(count, 'count incremented by 1').toHaveText('1');
});
});

test.describe('React client id generation', () => {
test('react components generate unique ids', async ({ page, astro }) => {
await page.goto(astro.resolveUrl('/'));
Expand Down
2 changes: 1 addition & 1 deletion packages/astro/src/assets/fonts/vite-plugin-fonts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ export function fontsPlugin({ settings, sync, logger }: Options): Plugin {
}
},
async buildEnd() {
if (sync || settings.config.experimental.fonts!.length === 0) {
if (sync || settings.config.experimental.fonts!.length === 0 || !isBuild) {
cleanup();
return;
}
Expand Down
37 changes: 4 additions & 33 deletions packages/astro/src/runtime/server/render/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,9 @@ import {
} from './common.js';
import { componentIsHTMLElement, renderHTMLElement } from './dom.js';
import { maybeRenderHead } from './head.js';
import {
createRenderInstruction,
isRenderInstruction,
type RenderInstruction,
} from './instruction.js';
import { createRenderInstruction } from './instruction.js';
import { containsServerDirective, ServerIslandComponent } from './server-islands.js';
import {
type ComponentSlots,
mergeSlotInstructions,
renderSlots,
renderSlotToString,
SlotString,
} from './slot.js';
import { type ComponentSlots, renderSlots, renderSlotToString } from './slot.js';
import { formatList, internalSpreadAttributes, renderElement, voidElementNames } from './util.js';

const needsHeadRenderingSymbol = Symbol.for('astro.needsHeadRendering');
Expand Down Expand Up @@ -534,7 +524,6 @@ export async function renderComponentToString(
route?: RouteData,
): Promise<string> {
let str = '';
let instructions: RenderInstruction[] | null = null;
let renderedFirstPageChunk = false;

// Handle head injection if required. Note that this needs to run early so
Expand All @@ -559,21 +548,7 @@ export async function renderComponentToString(
// `renderToString` doesn't work with emitting responses, so ignore here
if (chunk instanceof Response) return;

// For pages, stringify immediately (final output)
// For non-pages (slots/components), collect instructions for deferred processing
if (isPage) {
str += chunkToString(result, chunk);
} else {
if (chunk instanceof SlotString) {
str += chunk;
instructions = mergeSlotInstructions(instructions, chunk);
} else if (isRenderInstruction(chunk)) {
instructions ??= [];
instructions.push(chunk);
} else {
str += chunkToString(result, chunk);
}
}
str += chunkToString(result, chunk);
},
};

Expand All @@ -594,11 +569,7 @@ export async function renderComponentToString(
throw e;
}

// For pages, return plain string. For non-pages, return SlotString to preserve instructions.
if (isPage) {
return str;
}
return new SlotString(str, instructions) as unknown as string;
return str;
}

export type NonAstroPageComponent = {
Expand Down
21 changes: 21 additions & 0 deletions packages/astro/test/fonts.test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// @ts-check
import assert from 'node:assert/strict';
import { existsSync } from 'node:fs';
import { readdir } from 'node:fs/promises';
import { describe, it } from 'node:test';
import { fontProviders } from 'astro/config';
Expand All @@ -11,6 +12,7 @@ import { loadFixture } from './test-utils.js';
*/
async function createDevFixture(inlineConfig) {
const fixture = await loadFixture({ root: './fixtures/fonts/', ...inlineConfig });
await fixture.clean();
const devServer = await fixture.startDevServer();

return {
Expand Down Expand Up @@ -200,6 +202,25 @@ describe('astro fonts', () => {
assert.equal(parsed[0].src[0].url.startsWith('/_astro/fonts/'), true);
});
});

it('Does not create dist folder or copy fonts when dev server stops', async () => {
const { fixture, run } = await createDevFixture({
experimental: {
fonts: [
{
name: 'Poppins',
cssVariable: '--font-test',
provider: fontProviders.fontsource(),
weights: [400, 500],
},
],
},
});
await run(async () => {
await fixture.fetch('/');
});
assert.equal(existsSync(fixture.config.outDir), false);
});
});

describe('build', () => {
Expand Down
Loading
Loading