mirror of
https://github.com/withastro/astro.git
synced 2024-12-16 21:46:22 -05:00
feat(astro): add Built-in SVG component support (#12067)
Co-authored-by: Sarah Rainsberger <sarah@rainsberger.ca> Co-authored-by: Emanuele Stoppa <my.burning@gmail.com>
This commit is contained in:
parent
e246dc5232
commit
c48916cc4e
35 changed files with 2144 additions and 701 deletions
30
.changeset/blue-socks-doubt.md
Normal file
30
.changeset/blue-socks-doubt.md
Normal file
|
@ -0,0 +1,30 @@
|
|||
---
|
||||
'astro': minor
|
||||
---
|
||||
|
||||
Adds experimental support for built-in SVG components.
|
||||
|
||||
|
||||
This feature allows you to import SVG files directly into your Astro project as components. By default, Astro will inline the SVG content into your HTML output.
|
||||
|
||||
To enable this feature, set `experimental.svg` to `true` in your Astro config:
|
||||
|
||||
```js
|
||||
{
|
||||
experimental: {
|
||||
svg: true,
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
To use this feature, import an SVG file in your Astro project, passing any common SVG attributes to the imported component. Astro also provides a `size` attribute to set equal `height` and `width` properties:
|
||||
|
||||
```astro
|
||||
---
|
||||
import Logo from './path/to/svg/file.svg';
|
||||
---
|
||||
|
||||
<Logo size={24} />
|
||||
```
|
||||
|
||||
For a complete overview, and to give feedback on this experimental API, see the [Feature RFC](https://github.com/withastro/roadmap/pull/1035).
|
25
packages/astro/client.d.ts
vendored
25
packages/astro/client.d.ts
vendored
|
@ -103,14 +103,31 @@ declare module '*.webp' {
|
|||
const metadata: ImageMetadata;
|
||||
export default metadata;
|
||||
}
|
||||
declare module '*.svg' {
|
||||
const metadata: ImageMetadata;
|
||||
export default metadata;
|
||||
}
|
||||
declare module '*.avif' {
|
||||
const metadata: ImageMetadata;
|
||||
export default metadata;
|
||||
}
|
||||
declare module '*.svg' {
|
||||
type Props = {
|
||||
/**
|
||||
* Accesible, short-text description
|
||||
*
|
||||
* {@link https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title|MDN Reference}
|
||||
*/
|
||||
title?: string;
|
||||
/**
|
||||
* Shorthand for setting the `height` and `width` properties
|
||||
*/
|
||||
size?: number | string;
|
||||
/**
|
||||
* Override the default rendering mode for SVGs
|
||||
*/
|
||||
mode?: import('./dist/assets/utils/svg.js').SvgRenderMode
|
||||
} & astroHTML.JSX.SVGAttributes
|
||||
|
||||
const Component: ((_props: Props) => any) & ImageMetadata;
|
||||
export default Component;
|
||||
}
|
||||
|
||||
declare module 'astro:transitions' {
|
||||
type TransitionModule = typeof import('./dist/virtual-modules/transitions.js');
|
||||
|
|
|
@ -59,6 +59,7 @@
|
|||
"./toolbar": "./dist/toolbar/index.js",
|
||||
"./actions/runtime/*": "./dist/actions/runtime/*",
|
||||
"./assets": "./dist/assets/index.js",
|
||||
"./assets/runtime": "./dist/assets/runtime.js",
|
||||
"./assets/utils": "./dist/assets/utils/index.js",
|
||||
"./assets/utils/inferRemoteSize.js": "./dist/assets/utils/remoteProbe.js",
|
||||
"./assets/endpoint/*": "./dist/assets/endpoint/*.js",
|
||||
|
@ -163,6 +164,7 @@
|
|||
"shiki": "^1.22.2",
|
||||
"tinyexec": "^0.3.1",
|
||||
"tsconfck": "^3.1.4",
|
||||
"ultrahtml": "^1.5.3",
|
||||
"unist-util-visit": "^5.0.0",
|
||||
"vfile": "^6.0.3",
|
||||
"vite": "6.0.0-beta.6",
|
||||
|
|
102
packages/astro/src/assets/runtime.ts
Normal file
102
packages/astro/src/assets/runtime.ts
Normal file
|
@ -0,0 +1,102 @@
|
|||
import {
|
||||
createComponent,
|
||||
render,
|
||||
spreadAttributes,
|
||||
unescapeHTML,
|
||||
} from '../runtime/server/index.js';
|
||||
import type { SSRResult } from '../types/public/index.js';
|
||||
import type { ImageMetadata } from './types.js';
|
||||
|
||||
export interface SvgComponentProps {
|
||||
meta: ImageMetadata;
|
||||
attributes: Record<string, string>;
|
||||
children: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure these IDs are kept on the module-level so they're incremented on a per-page basis
|
||||
*/
|
||||
const ids = new WeakMap<SSRResult, number>();
|
||||
let counter = 0;
|
||||
|
||||
export function createSvgComponent({ meta, attributes, children }: SvgComponentProps) {
|
||||
const rendered = new WeakSet<Response>();
|
||||
const Component = createComponent((result, props) => {
|
||||
let id;
|
||||
if (ids.has(result)) {
|
||||
id = ids.get(result)!;
|
||||
} else {
|
||||
counter += 1;
|
||||
ids.set(result, counter);
|
||||
id = counter;
|
||||
}
|
||||
id = `a:${id}`;
|
||||
|
||||
const {
|
||||
title: titleProp,
|
||||
viewBox,
|
||||
mode,
|
||||
...normalizedProps
|
||||
} = normalizeProps(attributes, props);
|
||||
const title = titleProp ? unescapeHTML(`<title>${titleProp}</title>`) : '';
|
||||
|
||||
if (mode === 'sprite') {
|
||||
// On the first render, include the symbol definition
|
||||
let symbol: any = '';
|
||||
if (!rendered.has(result.response)) {
|
||||
// We only need the viewBox on the symbol definition, we can drop it everywhere else
|
||||
symbol = unescapeHTML(`<symbol${spreadAttributes({ viewBox, id })}>${children}</symbol>`);
|
||||
rendered.add(result.response);
|
||||
}
|
||||
|
||||
return render`<svg${spreadAttributes(normalizedProps)}>${title}${symbol}<use href="#${id}" /></svg>`;
|
||||
}
|
||||
|
||||
// Default to inline mode
|
||||
return render`<svg${spreadAttributes({ viewBox, ...normalizedProps })}>${title}${unescapeHTML(children)}</svg>`;
|
||||
});
|
||||
|
||||
if (import.meta.env.DEV) {
|
||||
// Prevent revealing that this is a component
|
||||
makeNonEnumerable(Component);
|
||||
|
||||
// Maintaining the current `console.log` output for SVG imports
|
||||
Object.defineProperty(Component, Symbol.for('nodejs.util.inspect.custom'), {
|
||||
value: (_: any, opts: any, inspect: any) => inspect(meta, opts),
|
||||
});
|
||||
}
|
||||
|
||||
// Attaching the metadata to the component to maintain current functionality
|
||||
return Object.assign(Component, meta);
|
||||
}
|
||||
|
||||
type SvgAttributes = Record<string, any>;
|
||||
|
||||
/**
|
||||
* Some attributes required for `image/svg+xml` are irrelevant when inlined in a `text/html` document. We can save a few bytes by dropping them.
|
||||
*/
|
||||
const ATTRS_TO_DROP = ['xmlns', 'xmlns:xlink', 'version'];
|
||||
const DEFAULT_ATTRS: SvgAttributes = { role: 'img' };
|
||||
|
||||
export function dropAttributes(attributes: SvgAttributes) {
|
||||
for (const attr of ATTRS_TO_DROP) {
|
||||
delete attributes[attr];
|
||||
}
|
||||
|
||||
return attributes;
|
||||
}
|
||||
|
||||
function normalizeProps(attributes: SvgAttributes, { size, ...props }: SvgAttributes) {
|
||||
if (size !== undefined && props.width === undefined && props.height === undefined) {
|
||||
props.height = size;
|
||||
props.width = size;
|
||||
}
|
||||
|
||||
return dropAttributes({ ...DEFAULT_ATTRS, ...attributes, ...props });
|
||||
}
|
||||
|
||||
function makeNonEnumerable(object: Record<string, any>) {
|
||||
for (const property in object) {
|
||||
Object.defineProperty(object, property, { enumerable: false });
|
||||
}
|
||||
}
|
|
@ -8,7 +8,7 @@ import type {
|
|||
ImageTransform,
|
||||
UnresolvedSrcSetValue,
|
||||
} from '../types.js';
|
||||
import { isESMImportedImage } from '../utils/imageKind.js';
|
||||
import { isESMImportedImage, isRemoteImage } from '../utils/imageKind.js';
|
||||
import { isRemoteAllowed } from '../utils/remotePattern.js';
|
||||
|
||||
export type ImageService = LocalImageService | ExternalImageService;
|
||||
|
@ -151,7 +151,7 @@ export const baseService: Omit<LocalImageService, 'transform'> = {
|
|||
propertiesToHash: DEFAULT_HASH_PROPS,
|
||||
validateOptions(options) {
|
||||
// `src` is missing or is `undefined`.
|
||||
if (!options.src || (typeof options.src !== 'string' && typeof options.src !== 'object')) {
|
||||
if (!options.src || (!isRemoteImage(options.src) && !isESMImportedImage(options.src))) {
|
||||
throw new AstroError({
|
||||
...AstroErrorData.ExpectedImage,
|
||||
message: AstroErrorData.ExpectedImage.message(
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import type { ImageMetadata, UnresolvedImageTransform } from '../types.js';
|
||||
|
||||
export function isESMImportedImage(src: ImageMetadata | string): src is ImageMetadata {
|
||||
return typeof src === 'object';
|
||||
return typeof src === 'object' || (typeof src === 'function' && 'src' in src);
|
||||
}
|
||||
|
||||
export function isRemoteImage(src: ImageMetadata | string): src is string {
|
||||
|
|
|
@ -13,3 +13,4 @@ export {
|
|||
} from './remotePattern.js';
|
||||
export { hashTransform, propsToFilename } from './transformToPath.js';
|
||||
export { inferRemoteSize } from './remoteProbe.js';
|
||||
export { makeSvgComponent } from './svg.js'
|
||||
|
|
|
@ -7,6 +7,7 @@ import type { ImageMetadata } from '../../types.js';
|
|||
import { imageMetadata } from '../metadata.js';
|
||||
|
||||
type FileEmitter = vite.Rollup.EmitFile;
|
||||
type ImageMetadataWithContents = ImageMetadata & { contents?: Buffer };
|
||||
|
||||
export async function emitESMImage(
|
||||
id: string | undefined,
|
||||
|
@ -15,7 +16,7 @@ export async function emitESMImage(
|
|||
// FIX: in Astro 6, this function should not be passed in dev mode at all.
|
||||
// Or rethink the API so that a function that throws isn't passed through.
|
||||
fileEmitter?: FileEmitter,
|
||||
): Promise<ImageMetadata | undefined> {
|
||||
): Promise<ImageMetadataWithContents | undefined> {
|
||||
if (!id) {
|
||||
return undefined;
|
||||
}
|
||||
|
@ -30,7 +31,7 @@ export async function emitESMImage(
|
|||
|
||||
const fileMetadata = await imageMetadata(fileData, id);
|
||||
|
||||
const emittedImage: Omit<ImageMetadata, 'fsPath'> = {
|
||||
const emittedImage: Omit<ImageMetadataWithContents, 'fsPath'> = {
|
||||
src: '',
|
||||
...fileMetadata,
|
||||
};
|
||||
|
@ -42,6 +43,11 @@ export async function emitESMImage(
|
|||
value: id,
|
||||
});
|
||||
|
||||
// Attach file data for SVGs
|
||||
if (fileMetadata.format === 'svg') {
|
||||
emittedImage.contents = fileData;
|
||||
}
|
||||
|
||||
// Build
|
||||
let isBuild = typeof fileEmitter === 'function';
|
||||
if (isBuild) {
|
||||
|
@ -71,7 +77,7 @@ export async function emitESMImage(
|
|||
emittedImage.src = `/@fs` + prependForwardSlash(fileURLToNormalizedPath(url));
|
||||
}
|
||||
|
||||
return emittedImage as ImageMetadata;
|
||||
return emittedImage as ImageMetadataWithContents;
|
||||
}
|
||||
|
||||
function fileURLToNormalizedPath(filePath: URL): string {
|
||||
|
|
27
packages/astro/src/assets/utils/svg.ts
Normal file
27
packages/astro/src/assets/utils/svg.ts
Normal file
|
@ -0,0 +1,27 @@
|
|||
import { parse, renderSync } from 'ultrahtml';
|
||||
import type { ImageMetadata } from '../types.js';
|
||||
import type { SvgComponentProps } from '../runtime.js';
|
||||
import { dropAttributes } from '../runtime.js';
|
||||
|
||||
function parseSvg(contents: string) {
|
||||
const root = parse(contents);
|
||||
const [{ attributes, children }] = root.children;
|
||||
const body = renderSync({ ...root, children });
|
||||
|
||||
return { attributes, body };
|
||||
}
|
||||
|
||||
export type SvgRenderMode = 'inline' | 'sprite';
|
||||
|
||||
export function makeSvgComponent(meta: ImageMetadata, contents: Buffer | string, options?: { mode?: SvgRenderMode }) {
|
||||
const file = typeof contents === 'string' ? contents : contents.toString('utf-8');
|
||||
const { attributes, body: children } = parseSvg(file);
|
||||
const props: SvgComponentProps = {
|
||||
meta,
|
||||
attributes: dropAttributes({ mode: options?.mode, ...attributes }),
|
||||
children,
|
||||
};
|
||||
|
||||
return `import { createSvgComponent } from 'astro/assets/runtime';
|
||||
export default createSvgComponent(${JSON.stringify(props)})`;
|
||||
}
|
|
@ -18,6 +18,7 @@ import { isESMImportedImage } from './utils/imageKind.js';
|
|||
import { emitESMImage } from './utils/node/emitAsset.js';
|
||||
import { getProxyCode } from './utils/proxy.js';
|
||||
import { hashTransform, propsToFilename } from './utils/transformToPath.js';
|
||||
import { makeSvgComponent } from './utils/svg.js';
|
||||
|
||||
const resolvedVirtualModuleId = '\0' + VIRTUAL_MODULE_ID;
|
||||
|
||||
|
@ -52,7 +53,7 @@ const addStaticImageFactory = (
|
|||
|
||||
let finalFilePath: string;
|
||||
let transformsForPath = globalThis.astroAsset.staticImages.get(finalOriginalPath);
|
||||
let transformForHash = transformsForPath?.transforms.get(hash);
|
||||
const transformForHash = transformsForPath?.transforms.get(hash);
|
||||
|
||||
// If the same image has already been transformed with the same options, we'll reuse the final path
|
||||
if (transformsForPath && transformForHash) {
|
||||
|
@ -213,6 +214,12 @@ export default function assets({ settings }: { settings: AstroSettings }): vite.
|
|||
});
|
||||
}
|
||||
|
||||
if (settings.config.experimental.svg && /\.svg$/.test(id)) {
|
||||
const { contents, ...metadata } = imageMetadata;
|
||||
// We know that the contents are present, as we only emit this property for SVG files
|
||||
return makeSvgComponent(metadata, contents!, { mode: settings.config.experimental.svg.mode });
|
||||
}
|
||||
|
||||
// We can only reliably determine if an image is used on the server, as we need to track its usage throughout the entire build.
|
||||
// Since you cannot use image optimization on the client anyway, it's safe to assume that if the user imported
|
||||
// an image on the client, it should be present in the final build.
|
||||
|
|
|
@ -96,6 +96,9 @@ export const ASTRO_CONFIG_DEFAULTS = {
|
|||
clientPrerender: false,
|
||||
contentIntellisense: false,
|
||||
responsiveImages: false,
|
||||
svg: {
|
||||
mode: 'inline',
|
||||
},
|
||||
},
|
||||
} satisfies AstroUserConfig & { server: { open: boolean } };
|
||||
|
||||
|
@ -534,6 +537,24 @@ export const AstroConfigSchema = z.object({
|
|||
.boolean()
|
||||
.optional()
|
||||
.default(ASTRO_CONFIG_DEFAULTS.experimental.responsiveImages),
|
||||
svg: z.union([
|
||||
z.boolean(),
|
||||
z
|
||||
.object({
|
||||
mode: z
|
||||
.union([z.literal('inline'), z.literal('sprite')])
|
||||
.optional()
|
||||
.default(ASTRO_CONFIG_DEFAULTS.experimental.svg.mode),
|
||||
})
|
||||
])
|
||||
.optional()
|
||||
.transform((svgConfig) => {
|
||||
// Handle normalization of `experimental.svg` config boolean values
|
||||
if (typeof svgConfig === 'boolean') {
|
||||
return svgConfig ? ASTRO_CONFIG_DEFAULTS.experimental.svg : undefined;
|
||||
}
|
||||
return svgConfig;
|
||||
}),
|
||||
})
|
||||
.strict(
|
||||
`Invalid or outdated experimental feature.\nCheck for incorrect spelling or outdated Astro version.\nSee https://docs.astro.build/en/reference/configuration-reference/#experimental-flags for a list of all current experiments.`,
|
||||
|
|
|
@ -8,6 +8,7 @@ import type {
|
|||
import type { UserConfig as OriginalViteUserConfig, SSROptions as ViteSSROptions } from 'vite';
|
||||
import type { ImageFit, ImageLayout } from '../../assets/types.js';
|
||||
import type { RemotePattern } from '../../assets/utils/remotePattern.js';
|
||||
import type { SvgRenderMode } from '../../assets/utils/svg.js';
|
||||
import type { AssetsPrefix } from '../../core/app/types.js';
|
||||
import type { AstroConfigType } from '../../core/config/schema.js';
|
||||
import type { REDIRECT_STATUS_CODES } from '../../core/constants.js';
|
||||
|
@ -1769,7 +1770,7 @@ export interface ViteUserConfig extends OriginalViteUserConfig {
|
|||
* @name experimental.contentIntellisense
|
||||
* @type {boolean}
|
||||
* @default `false`
|
||||
* @version 4.14.0
|
||||
* @version 5.x
|
||||
* @description
|
||||
*
|
||||
* Enables Intellisense features (e.g. code completion, quick hints) for your content collection entries in compatible editors.
|
||||
|
@ -1906,6 +1907,63 @@ export interface ViteUserConfig extends OriginalViteUserConfig {
|
|||
*/
|
||||
|
||||
responsiveImages?: boolean;
|
||||
|
||||
/**
|
||||
* @docs
|
||||
* @name experimental.svg
|
||||
* @type {boolean|object}
|
||||
* @default `undefined`
|
||||
* @version 5.x
|
||||
* @description
|
||||
*
|
||||
* This feature allows you to import SVG files directly into your Astro project. By default, Astro will inline the SVG content into your HTML output.
|
||||
*
|
||||
* To enable this feature, set `experimental.svg` to `true` in your Astro config:
|
||||
*
|
||||
* ```js
|
||||
* {
|
||||
* experimental: {
|
||||
* svg: true,
|
||||
* },
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* To use this feature, import an SVG file in your Astro project, passing any common SVG attributes to the imported component.
|
||||
* Astro also provides a `size` attribute to set equal `height` and `width` properties:
|
||||
*
|
||||
* ```astro
|
||||
* ---
|
||||
* import Logo from './path/to/svg/file.svg';
|
||||
* ---
|
||||
*
|
||||
* <Logo size={24} />
|
||||
* ```
|
||||
*
|
||||
* For a complete overview, and to give feedback on this experimental API,
|
||||
* see the [Feature RFC](https://github.com/withastro/roadmap/pull/1035).
|
||||
*/
|
||||
svg?: {
|
||||
/**
|
||||
* @docs
|
||||
* @name experimental.svg.mode
|
||||
* @type {string}
|
||||
* @default 'inline'
|
||||
*
|
||||
* The default technique for handling imported SVG files. Astro will inline the SVG content into your HTML output if not specified.
|
||||
*
|
||||
* - `inline`: Astro will inline the SVG content into your HTML output.
|
||||
* - `sprite`: Astro will generate a sprite sheet with all imported SVG files.
|
||||
*
|
||||
* ```astro
|
||||
* ---
|
||||
* import Logo from './path/to/svg/file.svg';
|
||||
* ---
|
||||
*
|
||||
* <Logo size={24} mode="sprite" />
|
||||
* ```
|
||||
*/
|
||||
mode?: SvgRenderMode;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
|
|
406
packages/astro/test/core-image-svg.test.js
Normal file
406
packages/astro/test/core-image-svg.test.js
Normal file
|
@ -0,0 +1,406 @@
|
|||
import assert from 'node:assert/strict';
|
||||
import { Writable } from 'node:stream';
|
||||
import { after, before, describe, it } from 'node:test';
|
||||
import * as cheerio from 'cheerio';
|
||||
import { Logger } from '../dist/core/logger/core.js';
|
||||
import { loadFixture } from './test-utils.js';
|
||||
|
||||
describe('astro:assets - SVG Components', () => {
|
||||
/** @type {import('./test-utils').Fixture} */
|
||||
let fixture;
|
||||
|
||||
describe('dev', () => {
|
||||
/** @type {import('./test-utils').DevServer} */
|
||||
let devServer;
|
||||
/** @type {Array<{ type: any, level: 'error', message: string; }>} */
|
||||
let logs = [];
|
||||
|
||||
before(async () => {
|
||||
fixture = await loadFixture({
|
||||
root: './fixtures/core-image-svg/',
|
||||
});
|
||||
|
||||
devServer = await fixture.startDevServer({
|
||||
logger: new Logger({
|
||||
level: 'error',
|
||||
dest: new Writable({
|
||||
objectMode: true,
|
||||
write(event, _, callback) {
|
||||
logs.push(event);
|
||||
callback();
|
||||
},
|
||||
}),
|
||||
}),
|
||||
});
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await devServer.stop();
|
||||
});
|
||||
|
||||
describe('basics', () => {
|
||||
let $;
|
||||
before(async () => {
|
||||
let res = await fixture.fetch('/');
|
||||
let html = await res.text();
|
||||
$ = cheerio.load(html, { xml: true });
|
||||
});
|
||||
it('Inlines the SVG by default', () => {
|
||||
const $svgs = $('.inline svg');
|
||||
assert.equal($svgs.length, 2);
|
||||
$svgs.each(function () {
|
||||
assert.equal($(this).attr('role'), 'img');
|
||||
assert.equal(!!$(this).attr('mode'), false);
|
||||
const $use = $(this).children('use');
|
||||
assert.equal($use.length, 0);
|
||||
})
|
||||
});
|
||||
|
||||
it('Adds the <svg> tag with the definition', () => {
|
||||
const $svg = $('.sprite #definition svg');
|
||||
assert.equal($svg.length, 1);
|
||||
assert.equal($svg.attr('role'), 'img');
|
||||
|
||||
const $symbol = $svg.children('symbol');
|
||||
assert.equal($symbol.length, 1);
|
||||
assert.equal($symbol.attr('id').startsWith('a:'), true);
|
||||
|
||||
const $use = $svg.children('use');
|
||||
assert.equal($use.length, 1);
|
||||
assert.equal($use.attr('href').startsWith('#a:'), true);
|
||||
assert.equal($use.attr('href').slice(1), $symbol.attr('id'));
|
||||
});
|
||||
it('Adds the <svg> tag that uses the definition', () => {
|
||||
let $svg = $('.sprite #reused svg');
|
||||
assert.equal($svg.length, 1);
|
||||
assert.equal($svg.attr('role'), 'img');
|
||||
|
||||
const $symbol = $svg.children('symbol');
|
||||
assert.equal($symbol.length, 0);
|
||||
|
||||
const definitionId = $('#definition svg symbol').attr('id')
|
||||
const $use = $svg.children('use');
|
||||
assert.equal($use.length, 1);
|
||||
assert.equal($use.attr('href').startsWith('#a:'), true);
|
||||
assert.equal($use.attr('href').slice(1), definitionId);
|
||||
});
|
||||
});
|
||||
|
||||
describe('props', () => {
|
||||
describe('size', () => {
|
||||
let $;
|
||||
before(async () => {
|
||||
let res = await fixture.fetch('/size');
|
||||
let html = await res.text();
|
||||
$ = cheerio.load(html, { xml: true });
|
||||
});
|
||||
|
||||
it('has no height and width - no dimensions set', () => {
|
||||
let $svg = $('#base svg');
|
||||
assert.equal($svg.length, 1);
|
||||
assert.equal(!!$svg.attr('height'), false);
|
||||
assert.equal(!!$svg.attr('width'), false);
|
||||
});
|
||||
it('has height and width - no dimensions set', () => {
|
||||
let $svg = $('#base-with-defaults svg');
|
||||
assert.equal($svg.length, 1);
|
||||
assert.equal($svg.attr('height'), '1em');
|
||||
assert.equal($svg.attr('width'), '1em');
|
||||
});
|
||||
it('has height and width - string size set', () => {
|
||||
let $svg = $('#size-string svg');
|
||||
assert.equal($svg.length, 1);
|
||||
assert.equal($svg.attr('height'), '32');
|
||||
assert.equal($svg.attr('width'), '32');
|
||||
assert.equal(!!$svg.attr('size'), false);
|
||||
});
|
||||
it('has height and width - number size set', () => {
|
||||
let $svg = $('#size-number svg');
|
||||
assert.equal($svg.length, 1);
|
||||
assert.equal($svg.attr('height'), '48');
|
||||
assert.equal($svg.attr('width'), '48');
|
||||
assert.equal(!!$svg.attr('size'), false);
|
||||
});
|
||||
it('has height and width overridden - size set', () => {
|
||||
let $svg = $('#override-attrs svg');
|
||||
assert.equal($svg.length, 1);
|
||||
assert.equal($svg.attr('height'), '16');
|
||||
assert.equal($svg.attr('width'), '16');
|
||||
assert.equal(!!$svg.attr('size'), false);
|
||||
});
|
||||
it('has unchanged width - size set', () => {
|
||||
let $svg = $('#ignore-size-for-width svg');
|
||||
assert.equal($svg.length, 1);
|
||||
assert.equal($svg.attr('height'), '1em');
|
||||
assert.equal($svg.attr('width'), '24');
|
||||
assert.equal(!!$svg.attr('size'), false);
|
||||
});
|
||||
it('has unchanged height - size set', () => {
|
||||
let $svg = $('#ignore-size-for-height svg');
|
||||
assert.equal($svg.length, 1);
|
||||
assert.equal($svg.attr('height'), '24');
|
||||
assert.equal($svg.attr('width'), '1em');
|
||||
assert.equal(!!$svg.attr('size'), false);
|
||||
});
|
||||
it('has unchanged height and with - size set', () => {
|
||||
let $svg = $('#ignore-size svg');
|
||||
assert.equal($svg.length, 1);
|
||||
assert.equal($svg.attr('height'), '24');
|
||||
assert.equal($svg.attr('width'), '24');
|
||||
assert.equal(!!$svg.attr('size'), false);
|
||||
});
|
||||
});
|
||||
describe('mode', () => {
|
||||
let $;
|
||||
before(async () => {
|
||||
let res = await fixture.fetch('/inline');
|
||||
let html = await res.text();
|
||||
$ = cheerio.load(html, { xml: true });
|
||||
});
|
||||
|
||||
it('adds the svg into the document directly by default', () => {
|
||||
let $svg = $('#default svg');
|
||||
assert.equal($svg.length, 1);
|
||||
assert.equal(!!$svg.attr('viewBox'), true);
|
||||
assert.equal($svg.attr('height'), '1em');
|
||||
assert.equal($svg.attr('width'), '1em');
|
||||
assert.equal($svg.attr('role'), 'img');
|
||||
assert.equal(!!$svg.attr('mode'), false);
|
||||
|
||||
const $symbol = $svg.children('symbol')
|
||||
assert.equal($symbol.length, 0);
|
||||
const $use = $svg.children('use')
|
||||
assert.equal($use.length, 0);
|
||||
const $path = $svg.children('path');
|
||||
assert.equal($path.length, 1);
|
||||
})
|
||||
it('adds the svg into the document directly', () => {
|
||||
let $svg = $('#inline svg');
|
||||
assert.equal($svg.length, 1);
|
||||
assert.equal(!!$svg.attr('viewBox'), true);
|
||||
assert.equal($svg.attr('height'), '1em');
|
||||
assert.equal($svg.attr('width'), '1em');
|
||||
assert.equal($svg.attr('role'), 'img');
|
||||
assert.equal(!!$svg.attr('mode'), false);
|
||||
|
||||
const $symbol = $svg.children('symbol')
|
||||
assert.equal($symbol.length, 0);
|
||||
const $use = $svg.children('use')
|
||||
assert.equal($use.length, 0);
|
||||
const $path = $svg.children('path');
|
||||
assert.equal($path.length, 1);
|
||||
});
|
||||
it('adds the svg into the document and overrides the dimensions', () => {
|
||||
let $svg = $('#inline-with-size svg');
|
||||
assert.equal($svg.length, 1);
|
||||
assert.equal(!!$svg.attr('viewBox'), true);
|
||||
assert.equal($svg.attr('height'), '24');
|
||||
assert.equal($svg.attr('width'), '24');
|
||||
assert.equal($svg.attr('role'), 'img');
|
||||
assert.equal(!!$svg.attr('mode'), false);
|
||||
|
||||
const $symbol = $svg.children('symbol')
|
||||
assert.equal($symbol.length, 0);
|
||||
const $use = $svg.children('use')
|
||||
assert.equal($use.length, 0);
|
||||
const $path = $svg.children('path');
|
||||
assert.equal($path.length, 1);
|
||||
})
|
||||
it('adds the svg into the document as a sprite, overridding the default', () => {
|
||||
let $svg = $('#definition svg');
|
||||
assert.equal($svg.length, 1);
|
||||
assert.equal(!!$svg.attr('viewBox'), false);
|
||||
assert.equal($svg.attr('height'), '1em');
|
||||
assert.equal($svg.attr('width'), '1em');
|
||||
assert.equal($svg.attr('role'), 'img');
|
||||
assert.equal(!!$svg.attr('mode'), false);
|
||||
|
||||
let $symbol = $svg.children('symbol')
|
||||
assert.equal($symbol.length, 1);
|
||||
assert.equal(!!$symbol.attr('viewBox'), true);
|
||||
let $use = $svg.children('use')
|
||||
assert.equal($use.length, 1);
|
||||
let $path = $svg.children('path');
|
||||
assert.equal($path.length, 0);
|
||||
|
||||
$svg = $('#reused svg');
|
||||
assert.equal($svg.length, 1);
|
||||
assert.equal(!!$svg.attr('viewBox'), false);
|
||||
assert.equal($svg.attr('height'), '1em');
|
||||
assert.equal($svg.attr('width'), '1em');
|
||||
assert.equal($svg.attr('role'), 'img');
|
||||
assert.equal(!!$svg.attr('mode'), false);
|
||||
|
||||
$symbol = $svg.children('symbol')
|
||||
assert.equal($symbol.length, 0);
|
||||
assert.equal(!!$symbol.attr('viewBox'), false);
|
||||
$use = $svg.children('use')
|
||||
assert.equal($use.length, 1);
|
||||
$path = $svg.children('path');
|
||||
assert.equal($path.length, 0);
|
||||
})
|
||||
});
|
||||
describe('title', () => {
|
||||
let $;
|
||||
before(async () => {
|
||||
let res = await fixture.fetch('/title');
|
||||
let html = await res.text();
|
||||
$ = cheerio.load(html, { xml: true });
|
||||
});
|
||||
|
||||
it('adds a title into the SVG', () => {
|
||||
let $svg = $('#base svg');
|
||||
assert.equal($svg.length, 1);
|
||||
assert.equal(!!$svg.attr('title'), false);
|
||||
|
||||
const $title = $('#base svg > title');
|
||||
assert.equal($title.length, 1);
|
||||
assert.equal($title.text(), 'GitHub Logo')
|
||||
});
|
||||
});
|
||||
describe('strip', () => {
|
||||
let $;
|
||||
before(async () => {
|
||||
let res = await fixture.fetch('/strip');
|
||||
let html = await res.text();
|
||||
$ = cheerio.load(html, { xml: true });
|
||||
});
|
||||
|
||||
it('removes unnecessary attributes', () => {
|
||||
let $svg = $('#base svg');
|
||||
assert.equal($svg.length, 1);
|
||||
assert.equal(!!$svg.attr('xmlns'), false);
|
||||
assert.equal(!!$svg.attr('xmlns:xlink'), false);
|
||||
assert.equal(!!$svg.attr('version'), false);
|
||||
});
|
||||
});
|
||||
describe('additional props', () => {
|
||||
let $;
|
||||
before(async () => {
|
||||
let res = await fixture.fetch('/props');
|
||||
let html = await res.text();
|
||||
$ = cheerio.load(html, { xml: true });
|
||||
});
|
||||
|
||||
it('adds the props to the svg', () => {
|
||||
let $svg = $('#base svg');
|
||||
assert.equal($svg.length, 1);
|
||||
assert.equal($svg.attr('aria-hidden'), 'true');
|
||||
assert.equal($svg.attr('id'), 'plus');
|
||||
assert.equal($svg.attr('style'), `color:red;font-size:32px`);
|
||||
assert.equal($svg.attr('class'), 'foobar');
|
||||
assert.equal($svg.attr('data-state'), 'open');
|
||||
|
||||
const $symbol = $svg.children('symbol')
|
||||
assert.equal($symbol.length, 0);
|
||||
const $use = $svg.children('use')
|
||||
assert.equal($use.length, 0);
|
||||
const $path = $svg.children('path')
|
||||
assert.equal($path.length, 1);
|
||||
});
|
||||
it('allows overriding the role attribute', () => {
|
||||
let $svg = $('#role svg');
|
||||
assert.equal($svg.length, 1);
|
||||
assert.equal($svg.attr('role'), 'presentation');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('multiple', () => {
|
||||
let $;
|
||||
before(async () => {
|
||||
let res = await fixture.fetch('/multiple');
|
||||
let html = await res.text();
|
||||
$ = cheerio.load(html, { xml: true });
|
||||
});
|
||||
|
||||
it('adds only one definition for each svg', () => {
|
||||
// First SVG
|
||||
let $svg = $('.one svg');
|
||||
assert.equal($svg.length, 2);
|
||||
let $symbol = $('.one svg > symbol');
|
||||
assert.equal($symbol.length, 1);
|
||||
let $use = $('.one svg > use');
|
||||
assert.equal($use.length, 2);
|
||||
let defId = $('.one.def svg > use').attr('id');
|
||||
let useId = $('.one.use svg > use').attr('id');
|
||||
assert.equal(defId, useId);
|
||||
|
||||
// Second SVG
|
||||
$svg = $('.two svg');
|
||||
assert.equal($svg.length, 2);
|
||||
$symbol = $('.two svg > symbol');
|
||||
assert.equal($symbol.length, 1);
|
||||
$use = $('.two svg > use');
|
||||
assert.equal($use.length, 2);
|
||||
defId = $('.two.def svg > use').attr('id');
|
||||
useId = $('.two.use svg > use').attr('id');
|
||||
assert.equal(defId, useId);
|
||||
|
||||
|
||||
// Third SVG
|
||||
$svg = $('.three svg');
|
||||
assert.equal($svg.length, 1);
|
||||
$symbol = $('.three svg > symbol');
|
||||
assert.equal($symbol.length, 1);
|
||||
$use = $('.three svg > use');
|
||||
assert.equal($use.length, 1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('markdown', () => {
|
||||
it('Adds the <svg> tag with the definition', async () => {
|
||||
let res = await fixture.fetch('/blog/basic');
|
||||
let html = await res.text();
|
||||
const $ = cheerio.load(html, { xml: true });
|
||||
|
||||
const $svg = $('svg');
|
||||
assert.equal($svg.length, 1);
|
||||
assert.equal($svg.attr('role'), 'img');
|
||||
|
||||
const $symbol = $svg.children('symbol');
|
||||
assert.equal($symbol.length, 0);
|
||||
const $use = $svg.children('use');
|
||||
assert.equal($use.length, 0);
|
||||
const $path = $svg.children('path');
|
||||
assert.equal($path.length > 0, true);
|
||||
});
|
||||
it('Adds the <svg> tag that uses the definition', async () => {
|
||||
let res = await fixture.fetch('/blog/sprite');
|
||||
let html = await res.text();
|
||||
const $ = cheerio.load(html, { xml: true });
|
||||
|
||||
const $svg = $('svg');
|
||||
assert.equal($svg.length, 2);
|
||||
$svg.each(function() { assert.equal($(this).attr('role'), 'img') });
|
||||
|
||||
const definitionId = $($svg[0]).children('symbol').attr('id')
|
||||
|
||||
const $reuse = $($svg[1]);
|
||||
const $symbol = $reuse.children('symbol');
|
||||
assert.equal($symbol.length, 0);
|
||||
|
||||
const $use = $reuse.children('use');
|
||||
assert.equal($use.length, 1);
|
||||
assert.equal($use.attr('href').startsWith('#a:'), true);
|
||||
assert.equal($use.attr('href').slice(1), definitionId);
|
||||
});
|
||||
it('Adds the <svg> tag that applies props', async () => {
|
||||
let res = await fixture.fetch('/blog/props');
|
||||
let html = await res.text();
|
||||
const $ = cheerio.load(html, { xml: true });
|
||||
|
||||
const $svg = $('svg');
|
||||
assert.equal($svg.length, 1);
|
||||
assert.equal($svg.attr('role'), 'img');
|
||||
assert.equal($svg.attr('height'), '48');
|
||||
assert.equal($svg.attr('width'), '48');
|
||||
assert.equal(!!$svg.attr('size'), false);
|
||||
assert.equal($svg.attr('class'), 'icon');
|
||||
assert.equal($svg.attr('data-icon'), 'github');
|
||||
assert.equal($svg.attr('aria-description'), 'Some description');
|
||||
assert.equal($svg.children('title').text(), 'Find out more on GitHub!');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
9
packages/astro/test/fixtures/core-image-svg/astro.config.mjs
vendored
Normal file
9
packages/astro/test/fixtures/core-image-svg/astro.config.mjs
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
import mdx from '@astrojs/mdx';
|
||||
import { defineConfig } from 'astro/config';
|
||||
|
||||
export default defineConfig({
|
||||
integrations: [mdx()],
|
||||
experimental: {
|
||||
svg: {}
|
||||
}
|
||||
});
|
12
packages/astro/test/fixtures/core-image-svg/package.json
vendored
Normal file
12
packages/astro/test/fixtures/core-image-svg/package.json
vendored
Normal file
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"name": "@test/core-image-svg",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"astro": "workspace:*",
|
||||
"@astrojs/mdx": "workspace:*"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "astro dev"
|
||||
}
|
||||
}
|
10
packages/astro/test/fixtures/core-image-svg/src/assets/alpine-multi-color.svg
vendored
Normal file
10
packages/astro/test/fixtures/core-image-svg/src/assets/alpine-multi-color.svg
vendored
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 7.9 KiB |
4
packages/astro/test/fixtures/core-image-svg/src/assets/astro.svg
vendored
Normal file
4
packages/astro/test/fixtures/core-image-svg/src/assets/astro.svg
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
<svg viewBox="0 0 85 107" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M27.5893 91.1365C22.7555 86.7178 21.3443 77.4335 23.3583 70.7072C26.8503 74.948 31.6888 76.2914 36.7005 77.0497C44.4374 78.2199 52.0358 77.7822 59.2231 74.2459C60.0453 73.841 60.8052 73.3027 61.7036 72.7574C62.378 74.714 62.5535 76.6892 62.3179 78.6996C61.7452 83.5957 59.3086 87.3778 55.4332 90.2448C53.8835 91.3916 52.2437 92.4167 50.6432 93.4979C45.7262 96.8213 44.3959 100.718 46.2435 106.386C46.2874 106.525 46.3267 106.663 46.426 107C43.9155 105.876 42.0817 104.24 40.6844 102.089C39.2086 99.8193 38.5065 97.3081 38.4696 94.5909C38.4511 93.2686 38.4511 91.9345 38.2733 90.6309C37.8391 87.4527 36.3471 86.0297 33.5364 85.9478C30.6518 85.8636 28.37 87.6469 27.7649 90.4554C27.7187 90.6707 27.6517 90.8837 27.5847 91.1341L27.5893 91.1365Z" fill="#17191E"/>
|
||||
<path d="M0 69.5866C0 69.5866 14.3139 62.6137 28.6678 62.6137L39.4901 29.1204C39.8953 27.5007 41.0783 26.3999 42.4139 26.3999C43.7495 26.3999 44.9325 27.5007 45.3377 29.1204L56.1601 62.6137C73.1601 62.6137 84.8278 69.5866 84.8278 69.5866C84.8278 69.5866 60.5145 3.35233 60.467 3.21944C59.7692 1.2612 58.5911 0 57.0029 0H27.8274C26.2392 0 25.1087 1.2612 24.3634 3.21944C24.3108 3.34983 0 69.5866 0 69.5866Z" fill="#17191E"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.2 KiB |
3
packages/astro/test/fixtures/core-image-svg/src/assets/chevron-right.svg
vendored
Normal file
3
packages/astro/test/fixtures/core-image-svg/src/assets/chevron-right.svg
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24">
|
||||
<path fill="currentColor" d="M8.59 16.58L13.17 12L8.59 7.41L10 6l6 6l-6 6z" />
|
||||
</svg>
|
After Width: | Height: | Size: 173 B |
6
packages/astro/test/fixtures/core-image-svg/src/assets/github.svg
vendored
Normal file
6
packages/astro/test/fixtures/core-image-svg/src/assets/github.svg
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
<svg viewBox="0 0 16 16">
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.012 8.012 0 0 0 16 8c0-4.42-3.58-8-8-8z"
|
||||
></path>
|
||||
</svg>
|
After Width: | Height: | Size: 649 B |
1
packages/astro/test/fixtures/core-image-svg/src/assets/penguin.svg
vendored
Normal file
1
packages/astro/test/fixtures/core-image-svg/src/assets/penguin.svg
vendored
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 12 KiB |
3
packages/astro/test/fixtures/core-image-svg/src/assets/plus.svg
vendored
Normal file
3
packages/astro/test/fixtures/core-image-svg/src/assets/plus.svg
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24">
|
||||
<path fill="currentColor" fill-rule="evenodd" d="M12 3.75a.75.75 0 0 1 .75.75v6.75h6.75a.75.75 0 0 1 0 1.5h-6.75v6.75a.75.75 0 0 1-1.5 0v-6.75H4.5a.75.75 0 0 1 0-1.5h6.75V4.5a.75.75 0 0 1 .75-.75" clip-rule="evenodd" />
|
||||
</svg>
|
After Width: | Height: | Size: 314 B |
7
packages/astro/test/fixtures/core-image-svg/src/content/blog/basic.mdx
vendored
Normal file
7
packages/astro/test/fixtures/core-image-svg/src/content/blog/basic.mdx
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
title: Basic Test
|
||||
description: Check that SVG Components work
|
||||
---
|
||||
import Astro from '~/assets/astro.svg';
|
||||
|
||||
<Astro />
|
14
packages/astro/test/fixtures/core-image-svg/src/content/blog/props.mdx
vendored
Normal file
14
packages/astro/test/fixtures/core-image-svg/src/content/blog/props.mdx
vendored
Normal file
|
@ -0,0 +1,14 @@
|
|||
---
|
||||
title: Props Test
|
||||
description: Check that SVG Components work
|
||||
---
|
||||
import Github from '~/assets/github.svg';
|
||||
|
||||
<Github
|
||||
size="48"
|
||||
title="Find out more on GitHub!"
|
||||
style={{color: 'red'}}
|
||||
class="icon"
|
||||
data-icon="github"
|
||||
aria-description="Some description"
|
||||
/>
|
8
packages/astro/test/fixtures/core-image-svg/src/content/blog/sprite.mdx
vendored
Normal file
8
packages/astro/test/fixtures/core-image-svg/src/content/blog/sprite.mdx
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
title: Kitchen Sink Test
|
||||
description: Check that SVG Components work
|
||||
---
|
||||
import Astro from '~/assets/astro.svg';
|
||||
|
||||
<Astro mode="sprite" />
|
||||
<Astro mode="sprite" />
|
10
packages/astro/test/fixtures/core-image-svg/src/content/config.ts
vendored
Normal file
10
packages/astro/test/fixtures/core-image-svg/src/content/config.ts
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
import { defineCollection, z } from 'astro:content';
|
||||
|
||||
const blog = defineCollection({
|
||||
schema: z.object({
|
||||
title: z.string(),
|
||||
description: z.string().max(60, 'For SEO purposes, keep descriptions short!'),
|
||||
}),
|
||||
});
|
||||
|
||||
export const collections = { blog };
|
22
packages/astro/test/fixtures/core-image-svg/src/pages/blog/[...slug].astro
vendored
Normal file
22
packages/astro/test/fixtures/core-image-svg/src/pages/blog/[...slug].astro
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
---
|
||||
import { getCollection } from 'astro:content';
|
||||
|
||||
export async function getStaticPaths() {
|
||||
const blogEntries = await getCollection('blog');
|
||||
return blogEntries.map(entry => ({
|
||||
params: { slug: entry.slug }, props: { entry },
|
||||
}));
|
||||
}
|
||||
|
||||
const { entry } = Astro.props;
|
||||
const { Content } = await entry.render();
|
||||
---
|
||||
<html>
|
||||
<head>
|
||||
<title>{entry.data.title}</title>
|
||||
<meta name="description" content={entry.data.description} />
|
||||
</head>
|
||||
<body>
|
||||
<Content />
|
||||
</body>
|
||||
</html>
|
27
packages/astro/test/fixtures/core-image-svg/src/pages/index.astro
vendored
Normal file
27
packages/astro/test/fixtures/core-image-svg/src/pages/index.astro
vendored
Normal file
|
@ -0,0 +1,27 @@
|
|||
---
|
||||
import AstroLogo from "~/assets/astro.svg";
|
||||
---
|
||||
|
||||
<html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div class="inline">
|
||||
<div id="initial">
|
||||
<AstroLogo />
|
||||
</div>
|
||||
<div id="reused">
|
||||
<AstroLogo />
|
||||
</div>
|
||||
</div>
|
||||
<div class="sprite">
|
||||
<div id="definition">
|
||||
<AstroLogo mode="sprite"/>
|
||||
</div>
|
||||
<div id="reused">
|
||||
<AstroLogo mode="sprite" />
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
25
packages/astro/test/fixtures/core-image-svg/src/pages/inline.astro
vendored
Normal file
25
packages/astro/test/fixtures/core-image-svg/src/pages/inline.astro
vendored
Normal file
|
@ -0,0 +1,25 @@
|
|||
---
|
||||
import ChrevronRight from '~/assets/chevron-right.svg'
|
||||
---
|
||||
<html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="default">
|
||||
<ChrevronRight />
|
||||
</div>
|
||||
<div id="definition">
|
||||
<ChrevronRight mode="sprite"/>
|
||||
</div>
|
||||
<div id="inline">
|
||||
<ChrevronRight mode="inline" />
|
||||
</div>
|
||||
<div id="reused">
|
||||
<ChrevronRight mode="sprite" />
|
||||
</div>
|
||||
<div id="inline-with-size">
|
||||
<ChrevronRight mode="inline" size="24"/>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
27
packages/astro/test/fixtures/core-image-svg/src/pages/multiple.astro
vendored
Normal file
27
packages/astro/test/fixtures/core-image-svg/src/pages/multiple.astro
vendored
Normal file
|
@ -0,0 +1,27 @@
|
|||
---
|
||||
import AstroLogo from '~/assets/astro.svg';
|
||||
import GithubLogo from '~/assets/github.svg';
|
||||
import AlpineLogo from '~/assets/alpine-multi-color.svg';
|
||||
---
|
||||
<html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div class="one def">
|
||||
<AstroLogo mode='sprite' />
|
||||
</div>
|
||||
<div class="two def">
|
||||
<GithubLogo mode='sprite' />
|
||||
</div>
|
||||
<div class="three def">
|
||||
<AlpineLogo mode='sprite' width="64" />
|
||||
</div>
|
||||
<div class="one use">
|
||||
<AstroLogo mode='sprite' size="48"/>
|
||||
</div>
|
||||
<div class="two use">
|
||||
<GithubLogo mode='sprite' size="32" />
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
16
packages/astro/test/fixtures/core-image-svg/src/pages/props.astro
vendored
Normal file
16
packages/astro/test/fixtures/core-image-svg/src/pages/props.astro
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
---
|
||||
import Plus from '~/assets/plus.svg'
|
||||
---
|
||||
<html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="base">
|
||||
<Plus aria-hidden="true" id="plus" style={{ color: 'red', fontSize: '32px' }} class="foobar" data-state="open" />
|
||||
</div>
|
||||
<div id="role">
|
||||
<Plus role="presentation" />
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
35
packages/astro/test/fixtures/core-image-svg/src/pages/size.astro
vendored
Normal file
35
packages/astro/test/fixtures/core-image-svg/src/pages/size.astro
vendored
Normal file
|
@ -0,0 +1,35 @@
|
|||
---
|
||||
import AstroLogo from '~/assets/astro.svg';
|
||||
import Plus from '~/assets/plus.svg';
|
||||
---
|
||||
<html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="base">
|
||||
<AstroLogo />
|
||||
</div>
|
||||
<div id="base-with-defaults">
|
||||
<Plus />
|
||||
</div>
|
||||
<div id="size-string">
|
||||
<AstroLogo size="32" />
|
||||
</div>
|
||||
<div id="size-number">
|
||||
<AstroLogo size={48} />
|
||||
</div>
|
||||
<div id="override-attrs">
|
||||
<Plus size="16" />
|
||||
</div>
|
||||
<div id="ignore-size-for-width">
|
||||
<Plus width="24" size="16" />
|
||||
</div>
|
||||
<div id="ignore-size-for-height">
|
||||
<Plus height="24" size="16" />
|
||||
</div>
|
||||
<div id="ignore-size">
|
||||
<Plus width="24" height="24" size="16" />
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
13
packages/astro/test/fixtures/core-image-svg/src/pages/strip.astro
vendored
Normal file
13
packages/astro/test/fixtures/core-image-svg/src/pages/strip.astro
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
---
|
||||
import Alpine from '~/assets/alpine-multi-color.svg'
|
||||
---
|
||||
<html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="base">
|
||||
<Alpine />
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
13
packages/astro/test/fixtures/core-image-svg/src/pages/title.astro
vendored
Normal file
13
packages/astro/test/fixtures/core-image-svg/src/pages/title.astro
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
---
|
||||
import GitHub from '~/assets/github.svg'
|
||||
---
|
||||
<html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="base">
|
||||
<GitHub title="GitHub Logo" />
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
11
packages/astro/test/fixtures/core-image-svg/tsconfig.json
vendored
Normal file
11
packages/astro/test/fixtures/core-image-svg/tsconfig.json
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"extends": "astro/tsconfigs/strict",
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"~/assets/*": [
|
||||
"src/assets/*"
|
||||
]
|
||||
},
|
||||
}
|
||||
}
|
1868
pnpm-lock.yaml
1868
pnpm-lock.yaml
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue