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
23 changes: 15 additions & 8 deletions .agents/skills/triage/diagnose.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,11 @@ These variables are referenced throughout this skill. They may be passed as args
## Overview

1. Review the reproduction and error details from `report.md`
2. Locate the relevant source files in `packages/`
3. Add instrumentation to understand the code path
4. Identify the root cause
5. Append diagnosis findings to `report.md`
2. Load any domain-specific skills relevant to the bug category
3. Locate the relevant source files in `packages/`
4. Add instrumentation to understand the code path
5. Identify the root cause
6. Append diagnosis findings to `report.md`

## Step 1: Review the Reproduction

Expand All @@ -35,11 +36,17 @@ Re-run the reproduction if needed to see the error firsthand:
pnpm -C <triageDir> run build # or dev/preview
```

## Step 2: Locate Relevant Source Files
## Step 2: Load Domain-Specific Skills

Before diving into the source, check whether any skills in `.agents/skills/` are relevant to this bug category. Use `ls .agents/skills/` to see what's available, then read the `---` frontmatter of any that look relevant to get their description.

If a skill covers the category of bug you're investigating, load it with the `skill` tool and follow its guidance during diagnosis. Domain skills contain deep knowledge about specific subsystems that can significantly speed up root cause identification.

## Step 3: Locate Relevant Source Files

Using the error messages, stack traces, and any other reproduction details from Step 1, identify the source files in `packages/` that are likely involved.

## Step 3: Investigate with Instrumentation
## Step 4: Investigate with Instrumentation

Add `console.log` statements to understand the code path:

Expand All @@ -61,7 +68,7 @@ Iterate until you understand:
- What data is being passed
- Where the logic diverges from expected behavior

## Step 4: Identify Root Cause
## Step 5: Identify Root Cause

Once you understand the issue, document:

Expand All @@ -76,7 +83,7 @@ Consider:
- Does this affect other similar use cases?
- Are there edge cases to consider?

## Step 5: Write Output
## Step 6: Write Output

Append your diagnosis findings to the existing `report.md` (written by the reproduce skill).

Expand Down
39 changes: 23 additions & 16 deletions .agents/skills/triage/fix.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,15 @@ These variables are referenced throughout this skill. They may be passed as args
## Overview

1. Review the diagnosis from `report.md`
2. Verify fix feasibility (browser/runtime compatibility)
3. Implement a minimal fix in `packages/`
4. Rebuild the affected package(s)
5. Verify the fix resolves the reproduction
6. Ensure no regressions
7. Generate git diff
8. Append fix details to `report.md`
9. Clean up the working directory
2. Load any domain-specific skills relevant to the bug category
3. Verify fix feasibility (browser/runtime compatibility)
4. Implement a minimal fix in `packages/`
5. Rebuild the affected package(s)
6. Verify the fix resolves the reproduction
7. Ensure no regressions
8. Generate git diff
9. Append fix details to `report.md`
10. Clean up the working directory

## Step 1: Review the Diagnosis

Expand All @@ -39,14 +40,20 @@ Read `report.md` from the `triageDir` directory to understand:

**Note:** The repo may be messy from previous steps. Check `git status` and either work from the current state or `git reset --hard` to start clean.

## Step 2: Verify Fix Feasibility
## Step 2: Load Domain-Specific Skills

Before implementing, check whether any skills in `.agents/skills/` are relevant to this bug category. Use `ls .agents/skills/` to see what's available, then read the `---` frontmatter of any that look relevant to get their description.

If a skill covers the subsystem you're fixing, load it with the `skill` tool. Domain skills often contain fix approaches, key files, and caveats that aren't captured in `report.md`.

## Step 3: Verify Fix Feasibility

Consider your potential fixes and verify that any modern features you plan to use are supported:

- **Node.js:** When writing code for the runtime (server, build logic, integrations, etc.), target Node.js version `>=22.12.0`.
- **Browsers:** If your fix relies on browser support for any web platform feature, check the browser compatibility table on MDN to confirm it is supported across our browser targets. Do not treat specification compliance as proof of browser support. If the feature lacks sufficient support, choose a different approach.

## Step 3: Implement the Fix
## Step 4: Implement the Fix

Make changes in `packages/` source files. Follow these principles:

Expand Down Expand Up @@ -82,7 +89,7 @@ export function renderComponent(component: AstroComponent, props: Props) {
}
```

## Step 4: Rebuild the Package
## Step 5: Rebuild the Package

After making changes, rebuild the affected package:

Expand All @@ -92,15 +99,15 @@ pnpm -C packages/astro build # or packages/integrations/<name>

Watch for build errors — fix any TypeScript issues before proceeding.

## Step 5: Verify the Fix
## Step 6: Verify the Fix

Re-run the reproduction, often using `pnpm run build`/`astro build` or `pnpm run dev`/`astro dev`.

## Step 6: Check for Regressions
## Step 7: Check for Regressions

Test that you didn't break anything new, and that normal cases still work. If you find regressions, refine the fix to handle all cases.

## Step 7: Generate Git Diff
## Step 8: Generate Git Diff

From the repository root, generate the diff:

Expand All @@ -110,7 +117,7 @@ git diff packages/

This captures all your changes for the report.

## Step 8: Write Output
## Step 9: Write Output

Append your fix details to the existing `report.md` (written by reproduce and diagnose skills).

Expand All @@ -125,7 +132,7 @@ The report must include all information needed for a final GitHub comment to be
- Any alternative approaches considered and their tradeoffs
- If the fix failed: what was tried and why it didn't work

## Step 9: Clean Up the Working Directory
## Step 10: Clean Up the Working Directory

1. Run `git status` and review all changed files
2. Revert any changes that are NOT part of the fix:
Expand Down
9 changes: 9 additions & 0 deletions .changeset/calm-coats-approve.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
'astro': minor
---

Allows setting codec-specific defaults for Astro's built-in Sharp image service via `image.service.config`.

You can now configure encoder-level options such as `jpeg.mozjpeg`, `webp.effort`, `webp.alphaQuality`, `avif.effort`, `avif.chromaSubsampling`, and `png.compressionLevel` when using `astro/assets/services/sharp` for compile-time image generation.

These settings apply as defaults for the built-in Sharp pipeline, while per-image `quality` still takes precedence when set on `<Image />`, `<Picture />`, or `getImage()`.
5 changes: 5 additions & 0 deletions .changeset/common-cats-travel.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@astrojs/vercel': patch
---

Fix vercel ISR path rewrite
5 changes: 5 additions & 0 deletions .changeset/fix-emitfile-serve-warning.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'astro': patch
---

Fixes the `emitFile() is not supported in serve mode` warning that appears during `astro dev` when using integrations that inject before-hydration scripts (e.g. `@astrojs/react`)
24 changes: 24 additions & 0 deletions .changeset/legal-rings-rhyme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
'@astrojs/markdown-remark': minor
---

Updates `createMarkdownProcessor` to support advanced SmartyPants options.

The `smartypants` property in `AstroMarkdownOptions` now accepts `Smartypants` options, allowing fine-grained control over typography transformations (backticks, dashes, ellipses, and quotes).

```ts
import { createMarkdownProcessor } from '@astrojs/markdown-remark';

const processor = await createMarkdownProcessor({
smartypants: {
backticks: 'all',
dashes: 'oldschool',
ellipses: 'unspaced',
openingQuotes: { double: '«', single: '' },
closingQuotes: { double: '»', single: '' },
quotes: false,
}
});
```

For the up-to-date supported properties, check out [the `retext-smartypants` options](https://github.com/retextjs/retext-smartypants?tab=readme-ov-file#fields).
27 changes: 27 additions & 0 deletions .changeset/red-heads-stare.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
---
'astro': minor
---

Adds support for advanced configuration of SmartyPants in Markdown.

You can now pass an options object to `markdown.smartypants` in your Astro configuration to fine-tune how punctuation, dashes, and quotes are transformed.

This is helpful for projects that require specific typographic standards, such as "oldschool" dash handling or localized quotation marks.

```js
// astro.config.mjs
export default defineConfig({
markdown: {
smartypants: {
backticks: 'all',
dashes: 'oldschool',
ellipses: 'unspaced',
openingQuotes: { double: '«', single: '' },
closingQuotes: { double: '»', single: '' },
quotes: false,
},
},
});
```

See [the `retext-smartypants` options](https://github.com/retextjs/retext-smartypants?tab=readme-ov-file#fields) for more information.
5 changes: 5 additions & 0 deletions .changeset/warn-vite8-cloudflare-override.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'astro': patch
---

Warns on dev server startup when Vite 8 is detected at the top level of the user's project, and automatically adds a `"overrides": { "vite": "^7" }` entry to `package.json` when running `astro add cloudflare`. This prevents a `require_dist is not a function` crash caused by a Vite version split between Astro (requires Vite 7) and packages like `@tailwindcss/vite` that hoist Vite 8.
105 changes: 92 additions & 13 deletions packages/astro/src/assets/services/sharp.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
import type { FitEnum, FormatEnum, ResizeOptions, SharpOptions } from 'sharp';
import type {
AvifOptions,
FitEnum,
FormatEnum,
JpegOptions,
PngOptions,
ResizeOptions,
SharpOptions,
WebpOptions,
} from 'sharp';
import { AstroError, AstroErrorData } from '../../core/errors/index.js';
import type { ImageFit, ImageOutputFormat, ImageQualityPreset } from '../types.js';
import {
Expand All @@ -18,6 +27,26 @@ export interface SharpImageServiceConfig {
* The `kernel` option is passed to resize calls. See https://sharp.pixelplumbing.com/api-resize/ for more information
*/
kernel?: ResizeOptions['kernel'];

/**
* The default encoder options passed to `sharp().jpeg()`.
*/
jpeg?: JpegOptions;

/**
* The default encoder options passed to `sharp().png()`.
*/
png?: PngOptions;

/**
* The default encoder options passed to `sharp().webp()`.
*/
webp?: WebpOptions;

/**
* The default encoder options passed to `sharp().avif()`.
*/
avif?: AvifOptions;
}

let sharp: typeof import('sharp');
Expand All @@ -29,6 +58,56 @@ const qualityTable: Record<ImageQualityPreset, number> = {
max: 100,
};

function resolveSharpQuality(quality: BaseServiceTransform['quality']): number | undefined {
if (!quality) return undefined;

const parsedQuality = parseQuality(quality);
if (typeof parsedQuality === 'number') {
return parsedQuality;
}

return quality in qualityTable ? qualityTable[quality] : undefined;
}

export function resolveSharpEncoderOptions(
transform: Pick<BaseServiceTransform, 'format' | 'quality'>,
inputFormat: string | undefined,
serviceConfig: SharpImageServiceConfig = {},
): JpegOptions | PngOptions | WebpOptions | AvifOptions | { quality?: number } | undefined {
const quality = resolveSharpQuality(transform.quality);

switch (transform.format) {
case 'jpg':
case 'jpeg':
return {
...serviceConfig.jpeg,
...(quality === undefined ? {} : { quality }),
};
case 'png':
return {
...serviceConfig.png,
...(quality === undefined ? {} : { quality }),
};
case 'webp': {
const webpOptions: WebpOptions = {
...serviceConfig.webp,
...(quality === undefined ? {} : { quality }),
};
if (inputFormat === 'gif') {
webpOptions.loop ??= 0;
}
return webpOptions;
}
case 'avif':
return {
...serviceConfig.avif,
...(quality === undefined ? {} : { quality }),
};
default:
return quality === undefined ? undefined : { quality };
}
}

async function loadSharp() {
let sharpImport: typeof import('sharp');
try {
Expand Down Expand Up @@ -116,21 +195,21 @@ const sharpService: LocalImageService<SharpImageServiceConfig> = {
}

if (transform.format) {
let quality: number | string | undefined = undefined;
if (transform.quality) {
const parsedQuality = parseQuality(transform.quality);
if (typeof parsedQuality === 'number') {
quality = parsedQuality;
} else {
quality = transform.quality in qualityTable ? qualityTable[transform.quality] : undefined;
}
}
const encoderOptions = resolveSharpEncoderOptions(transform, format, config.service.config);

if (transform.format === 'webp' && format === 'gif') {
// Convert animated GIF to animated WebP with loop=0 (infinite)
result.webp({ quality: typeof quality === 'number' ? quality : undefined, loop: 0 });
// Convert animated GIF to animated WebP with loop=0 (infinite) unless overridden in config.
result.webp(encoderOptions as WebpOptions | undefined);
} else if (transform.format === 'webp') {
result.webp(encoderOptions as WebpOptions | undefined);
} else if (transform.format === 'png') {
result.png(encoderOptions as PngOptions | undefined);
} else if (transform.format === 'avif') {
result.avif(encoderOptions as AvifOptions | undefined);
} else if (transform.format === 'jpeg' || transform.format === 'jpg') {
result.jpeg(encoderOptions as JpegOptions | undefined);
} else {
result.toFormat(transform.format as keyof FormatEnum, { quality });
result.toFormat(transform.format as keyof FormatEnum, encoderOptions);
}
}

Expand Down
Loading
Loading