Skip to content

Commit

Permalink
fix: conditionally import image style (#12925)
Browse files Browse the repository at this point in the history
* fix: conditionally import image style

* Use wrapper component for conditional style import

* changeset

* Add tests

* Fix tests

* Update markdoc tests

* Lint
  • Loading branch information
ascorbic authored Jan 8, 2025
1 parent 21aa25c commit 44841fc
Show file tree
Hide file tree
Showing 15 changed files with 76 additions and 25 deletions.
5 changes: 5 additions & 0 deletions .changeset/green-buses-add.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'astro': patch
---

Ensures image styles are not imported unless experimental responsive images are enabled
1 change: 0 additions & 1 deletion packages/astro/components/Image.astro
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import type { UnresolvedImageTransform } from '../dist/assets/types';
import { applyResponsiveAttributes } from '../dist/assets/utils/imageAttributes.js';
import { AstroError, AstroErrorData } from '../dist/core/errors/index.js';
import type { HTMLAttributes } from '../types';
import './image.css';
// The TypeScript diagnostic for JSX props uses the last member of the union to suggest props, so it would be better for
// LocalImageProps to be last. Unfortunately, when we do this the error messages that remote images get are complete nonsense
Expand Down
3 changes: 1 addition & 2 deletions packages/astro/components/Picture.astro
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,8 @@ import type {
UnresolvedImageTransform,
} from '../dist/types/public/index.js';
import type { HTMLAttributes } from '../types';
import './image.css';
type Props = (LocalImageProps | RemoteImageProps) & {
export type Props = (LocalImageProps | RemoteImageProps) & {
formats?: ImageOutputFormat[];
fallbackFormat?: ImageOutputFormat;
pictureAttributes?: HTMLAttributes<'picture'>;
Expand Down
13 changes: 13 additions & 0 deletions packages/astro/components/ResponsiveImage.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
import type { LocalImageProps, RemoteImageProps } from 'astro:assets';
import Image from './Image.astro';
type Props = LocalImageProps | RemoteImageProps;
const { class: className, ...props } = Astro.props;
import './image.css';
---

{/* Applying class outside of the spread prevents it from applying unnecessary astro-* classes */}
<Image {...props} class={className} />
11 changes: 11 additions & 0 deletions packages/astro/components/ResponsivePicture.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
import { default as Picture, type Props as PictureProps } from './Picture.astro';
type Props = PictureProps;
const { class: className, ...props } = Astro.props;
---

{/* Applying class outside of the spread prevents it from applying unnecessary astro-* classes */}

<Picture {...props} class={className} />
5 changes: 3 additions & 2 deletions packages/astro/src/assets/vite-plugin-assets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ export default function assets({ settings }: { settings: AstroSettings }): vite.
referencedImages: new Set(),
};

const imageComponentPrefix = settings.config.experimental.responsiveImages ? 'Responsive' : '';
return [
// Expose the components and different utilities from `astro:assets`
{
Expand All @@ -119,8 +120,8 @@ export default function assets({ settings }: { settings: AstroSettings }): vite.
return /* ts */ `
export { getConfiguredImageService, isLocalService } from "astro/assets";
import { getImage as getImageInternal } from "astro/assets";
export { default as Image } from "astro/components/Image.astro";
export { default as Picture } from "astro/components/Picture.astro";
export { default as Image } from "astro/components/${imageComponentPrefix}Image.astro";
export { default as Picture } from "astro/components/${imageComponentPrefix}Picture.astro";
export { inferRemoteSize } from "astro/assets/utils/inferRemoteSize.js";
export const imageConfig = ${JSON.stringify({ ...settings.config.image, experimentalResponsiveImages: settings.config.experimental.responsiveImages })};
Expand Down
8 changes: 4 additions & 4 deletions packages/astro/test/content-collections-render.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,15 @@ describe('Content Collections - render()', () => {
assert.equal($('ul li').length, 3);

// Includes styles
assert.equal($('link[rel=stylesheet]').length, 2);
assert.equal($('link[rel=stylesheet]').length, 1);
});

it('Excludes CSS for non-rendered entries', async () => {
const html = await fixture.readFile('/index.html');
const $ = cheerio.load(html);

// Excludes styles
assert.equal($('link[rel=stylesheet]').length, 1);
assert.equal($('link[rel=stylesheet]').length, 0);
});

it('De-duplicates CSS used both in layout and directly in target page', async () => {
Expand Down Expand Up @@ -110,7 +110,7 @@ describe('Content Collections - render()', () => {
assert.equal($('ul li').length, 3);

// Includes styles
assert.equal($('link[rel=stylesheet]').length, 2);
assert.equal($('link[rel=stylesheet]').length, 1);
});

it('Exclude CSS for non-rendered entries', async () => {
Expand All @@ -121,7 +121,7 @@ describe('Content Collections - render()', () => {
const $ = cheerio.load(html);

// Includes styles
assert.equal($('link[rel=stylesheet]').length, 1);
assert.equal($('link[rel=stylesheet]').length, 0);
});

it('De-duplicates CSS used both in layout and directly in target page', async () => {
Expand Down
8 changes: 6 additions & 2 deletions packages/astro/test/core-image.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,11 @@ describe('astro:image', () => {

describe('basics', () => {
let $;
let body;
before(async () => {
let res = await fixture.fetch('/');
let html = await res.text();
$ = cheerio.load(html);
body = await res.text();
$ = cheerio.load(body);
});

it('Adds the <img> tag', () => {
Expand All @@ -61,6 +62,9 @@ describe('astro:image', () => {
assert.equal($img.attr('src').startsWith('/_image'), true);
});

it('does not inject responsive image styles when not enabled', () => {
assert.ok(!body.includes('[data-astro-image]'));
});
it('includes loading and decoding attributes', () => {
let $img = $('#local img');
assert.equal(!!$img.attr('loading'), true);
Expand Down
2 changes: 1 addition & 1 deletion packages/astro/test/ssr-assets.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ describe('SSR Assets', () => {
const app = await fixture.loadTestAdapterApp();
/** @type {Set<string>} */
const assets = app.manifest.assets;
assert.equal(assets.size, 2);
assert.equal(assets.size, 1);
assert.equal(Array.from(assets)[0].endsWith('.css'), true);
});
});
12 changes: 6 additions & 6 deletions packages/integrations/markdoc/test/propagated-assets.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,23 +45,23 @@ describe('Markdoc - propagated assets', () => {
let styleContents;
if (mode === 'dev') {
const styles = stylesDocument.querySelectorAll('style');
assert.equal(styles.length, 2);
styleContents = styles[1].textContent;
assert.equal(styles.length, 1);
styleContents = styles[0].textContent;
} else {
const links = stylesDocument.querySelectorAll('link[rel="stylesheet"]');
assert.equal(links.length, 2);
styleContents = await fixture.readFile(links[1].href);
assert.equal(links.length, 1);
styleContents = await fixture.readFile(links[0].href);
}
assert.equal(styleContents.includes('--color-base-purple: 269, 79%;'), true);
});

it('[fails] Does not bleed styles to other page', async () => {
if (mode === 'dev') {
const styles = scriptsDocument.querySelectorAll('style');
assert.equal(styles.length, 1);
assert.equal(styles.length, 0);
} else {
const links = scriptsDocument.querySelectorAll('link[rel="stylesheet"]');
assert.equal(links.length, 1);
assert.equal(links.length, 0);
}
});
});
Expand Down
6 changes: 3 additions & 3 deletions packages/integrations/mdx/test/css-head-mdx.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,15 @@ describe('Head injection w/ MDX', () => {
const { document } = parseHTML(html);

const links = document.querySelectorAll('head link[rel=stylesheet]');
assert.equal(links.length, 2);
assert.equal(links.length, 1);
});

it('injects content from a component using Content#render()', async () => {
const html = await fixture.readFile('/DirectContentUsage/index.html');
const { document } = parseHTML(html);

const links = document.querySelectorAll('head link[rel=stylesheet]');
assert.equal(links.length, 2);
assert.equal(links.length, 1);

const scripts = document.querySelectorAll('script[type=module]');
assert.equal(scripts.length, 1);
Expand Down Expand Up @@ -79,7 +79,7 @@ describe('Head injection w/ MDX', () => {
const $ = cheerio.load(html);

const headLinks = $('head link[rel=stylesheet]');
assert.equal(headLinks.length, 2);
assert.equal(headLinks.length, 1);

const bodyLinks = $('body link[rel=stylesheet]');
assert.equal(bodyLinks.length, 0);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import mdx from '@astrojs/mdx';
import { testImageService } from '../../../../../astro/test/test-image-service.js';
import { defineConfig } from 'astro/config';

export default {
export default defineConfig({
integrations: [mdx()],
image: {
service: testImageService(),
},
}
experimental: {
responsiveImages: true,
}
})
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
---
import { getEntry } from 'astro:content';
import { getEntry, render } from 'astro:content';
import MyImage from 'src/components/MyImage.astro';
const entry = await getEntry('blog', 'entry');
const { Content } = await entry.render();
const { Content } = await render(entry)
---

<!DOCTYPE html>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Nothing to see here.
14 changes: 14 additions & 0 deletions packages/integrations/mdx/test/mdx-images.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,4 +65,18 @@ describe('MDX Page', () => {
});
}
});

describe('build', () => {
before(async () => {
await fixture.build();
});
it('includes responsive styles', async () => {
const code = await fixture.readFile('/index.html');
assert.ok(code.includes('[data-astro-image]'));
});
it("doesn't include styles on pages without images", async () => {
const code = await fixture.readFile('/no-image/index.html');
assert.ok(!code.includes('[data-astro-image]'));
});
});
});

0 comments on commit 44841fc

Please sign in to comment.