mirror of
https://github.com/withastro/astro.git
synced 2025-01-22 10:31:53 -05:00
feat(fonts): config (#12777)
This commit is contained in:
parent
21b6f35c32
commit
95673fcd21
15 changed files with 466 additions and 33 deletions
|
@ -113,7 +113,7 @@
|
||||||
"test:e2e:match": "playwright test -g",
|
"test:e2e:match": "playwright test -g",
|
||||||
"test:e2e:chrome": "playwright test",
|
"test:e2e:chrome": "playwright test",
|
||||||
"test:e2e:firefox": "playwright test --config playwright.firefox.config.js",
|
"test:e2e:firefox": "playwright test --config playwright.firefox.config.js",
|
||||||
"test:types": "tsc --project tsconfig.tests.json",
|
"test:types": "tsc --project test/types/tsconfig.json",
|
||||||
"test:unit": "astro-scripts test \"test/units/**/*.test.js\" --teardown ./test/units/teardown.js",
|
"test:unit": "astro-scripts test \"test/units/**/*.test.js\" --teardown ./test/units/teardown.js",
|
||||||
"test:integration": "astro-scripts test \"test/*.test.js\""
|
"test:integration": "astro-scripts test \"test/*.test.js\""
|
||||||
},
|
},
|
||||||
|
|
4
packages/astro/src/assets/fonts/constants.ts
Normal file
4
packages/astro/src/assets/fonts/constants.ts
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
import { GOOGLE_PROVIDER_NAME } from "./providers/google.js";
|
||||||
|
import { LOCAL_PROVIDER_NAME } from "./providers/local.js";
|
||||||
|
|
||||||
|
export const BUILTIN_PROVIDERS = [GOOGLE_PROVIDER_NAME, LOCAL_PROVIDER_NAME] as const;
|
5
packages/astro/src/assets/fonts/helpers.ts
Normal file
5
packages/astro/src/assets/fonts/helpers.ts
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
import type { FontProvider } from './types.js';
|
||||||
|
|
||||||
|
export function defineFontProvider<TName extends string>(provider: FontProvider<TName>) {
|
||||||
|
return provider;
|
||||||
|
}
|
6
packages/astro/src/assets/fonts/providers.ts
Normal file
6
packages/astro/src/assets/fonts/providers.ts
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
import { adobe } from './providers/adobe.js';
|
||||||
|
|
||||||
|
/** TODO: */
|
||||||
|
export const fontProviders = {
|
||||||
|
adobe,
|
||||||
|
};
|
9
packages/astro/src/assets/fonts/providers/adobe.ts
Normal file
9
packages/astro/src/assets/fonts/providers/adobe.ts
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
import { defineFontProvider } from '../helpers.js';
|
||||||
|
|
||||||
|
export function adobe(config: { apiKey: string }) {
|
||||||
|
return defineFontProvider({
|
||||||
|
name: 'adobe',
|
||||||
|
entrypoint: 'astro/assets/fonts/providers/adobe',
|
||||||
|
config,
|
||||||
|
});
|
||||||
|
}
|
10
packages/astro/src/assets/fonts/providers/google.ts
Normal file
10
packages/astro/src/assets/fonts/providers/google.ts
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
import { defineFontProvider } from '../helpers.js';
|
||||||
|
|
||||||
|
export const GOOGLE_PROVIDER_NAME = 'google';
|
||||||
|
|
||||||
|
export function google() {
|
||||||
|
return defineFontProvider({
|
||||||
|
name: GOOGLE_PROVIDER_NAME,
|
||||||
|
entrypoint: 'astro/assets/fonts/providers/google',
|
||||||
|
});
|
||||||
|
}
|
10
packages/astro/src/assets/fonts/providers/local.ts
Normal file
10
packages/astro/src/assets/fonts/providers/local.ts
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
import { defineFontProvider } from '../helpers.js';
|
||||||
|
|
||||||
|
export const LOCAL_PROVIDER_NAME = 'local';
|
||||||
|
|
||||||
|
export function local() {
|
||||||
|
return defineFontProvider({
|
||||||
|
name: LOCAL_PROVIDER_NAME,
|
||||||
|
entrypoint: 'astro/assets/fonts/providers/google',
|
||||||
|
});
|
||||||
|
}
|
27
packages/astro/src/assets/fonts/types.ts
Normal file
27
packages/astro/src/assets/fonts/types.ts
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
import type { BUILTIN_PROVIDERS } from './constants.js';
|
||||||
|
import type { GOOGLE_PROVIDER_NAME } from './providers/google.js';
|
||||||
|
import type { LOCAL_PROVIDER_NAME } from './providers/local.js';
|
||||||
|
|
||||||
|
export interface FontProvider<TName extends string> {
|
||||||
|
name: TName;
|
||||||
|
entrypoint: string;
|
||||||
|
config?: Record<string, any>;
|
||||||
|
}
|
||||||
|
|
||||||
|
type LocalFontFamily = {
|
||||||
|
provider: LocalProviderName;
|
||||||
|
// TODO: refine type
|
||||||
|
src: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type StandardFontFamily<TProvider extends string> = {
|
||||||
|
provider: TProvider;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type FontFamily<TProvider extends string> = TProvider extends LocalProviderName
|
||||||
|
? LocalFontFamily
|
||||||
|
: StandardFontFamily<TProvider>;
|
||||||
|
|
||||||
|
export type LocalProviderName = typeof LOCAL_PROVIDER_NAME;
|
||||||
|
export type GoogleProviderName = typeof GOOGLE_PROVIDER_NAME;
|
||||||
|
export type BuiltInProvider = (typeof BUILTIN_PROVIDERS)[number];
|
|
@ -5,6 +5,7 @@ import type { ImageServiceConfig } from '../types/public/index.js';
|
||||||
|
|
||||||
export { defineConfig, getViteConfig } from './index.js';
|
export { defineConfig, getViteConfig } from './index.js';
|
||||||
export { envField } from '../env/config.js';
|
export { envField } from '../env/config.js';
|
||||||
|
export { fontProviders } from '../assets/fonts/providers.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the configuration needed to use the Sharp-based image service
|
* Return the configuration needed to use the Sharp-based image service
|
||||||
|
|
|
@ -7,6 +7,7 @@ import type {
|
||||||
SessionDriverName,
|
SessionDriverName,
|
||||||
} from '../types/public/config.js';
|
} from '../types/public/config.js';
|
||||||
import { createDevelopmentManifest } from '../vite-plugin-astro-server/plugin.js';
|
import { createDevelopmentManifest } from '../vite-plugin-astro-server/plugin.js';
|
||||||
|
import type { BuiltInProvider, FontFamily, FontProvider } from '../assets/fonts/types.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See the full Astro Configuration API Documentation
|
* See the full Astro Configuration API Documentation
|
||||||
|
@ -15,7 +16,11 @@ import { createDevelopmentManifest } from '../vite-plugin-astro-server/plugin.js
|
||||||
export function defineConfig<
|
export function defineConfig<
|
||||||
const TLocales extends Locales = never,
|
const TLocales extends Locales = never,
|
||||||
const TDriver extends SessionDriverName = never,
|
const TDriver extends SessionDriverName = never,
|
||||||
>(config: AstroUserConfig<TLocales, TDriver>) {
|
const TFontProviders extends FontProvider<string>[] = never,
|
||||||
|
const TFontFamilies extends FontFamily<
|
||||||
|
(TFontProviders extends never ? [] : TFontProviders)[number]['name'] | BuiltInProvider
|
||||||
|
>[] = never,
|
||||||
|
>(config: AstroUserConfig<TLocales, TDriver, TFontProviders, TFontFamilies>) {
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ import type { SvgRenderMode } from '../../assets/utils/svg.js';
|
||||||
import { EnvSchema } from '../../env/schema.js';
|
import { EnvSchema } from '../../env/schema.js';
|
||||||
import type { AstroUserConfig, ViteUserConfig } from '../../types/public/config.js';
|
import type { AstroUserConfig, ViteUserConfig } from '../../types/public/config.js';
|
||||||
import { appendForwardSlash, prependForwardSlash, removeTrailingForwardSlash } from '../path.js';
|
import { appendForwardSlash, prependForwardSlash, removeTrailingForwardSlash } from '../path.js';
|
||||||
|
import { BUILTIN_PROVIDERS } from '../../assets/fonts/constants.js';
|
||||||
|
|
||||||
// The below types are required boilerplate to workaround a Zod issue since v3.21.2. Since that version,
|
// The below types are required boilerplate to workaround a Zod issue since v3.21.2. Since that version,
|
||||||
// Zod's compiled TypeScript would "simplify" certain values to their base representation, causing references
|
// Zod's compiled TypeScript would "simplify" certain values to their base representation, causing references
|
||||||
|
@ -589,6 +590,53 @@ export const AstroConfigSchema = z.object({
|
||||||
}
|
}
|
||||||
return svgConfig;
|
return svgConfig;
|
||||||
}),
|
}),
|
||||||
|
fonts: z
|
||||||
|
.object({
|
||||||
|
providers: z
|
||||||
|
.array(
|
||||||
|
z
|
||||||
|
.object({
|
||||||
|
name: z.string().superRefine((name, ctx) => {
|
||||||
|
if (BUILTIN_PROVIDERS.includes(name as any)) {
|
||||||
|
ctx.addIssue({
|
||||||
|
code: z.ZodIssueCode.custom,
|
||||||
|
message: `"${name}" is a reserved provider name`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
entrypoint: z.string(),
|
||||||
|
config: z.record(z.string(), z.any()).optional(),
|
||||||
|
})
|
||||||
|
.strict(),
|
||||||
|
)
|
||||||
|
.optional(),
|
||||||
|
families: z.array(
|
||||||
|
z
|
||||||
|
.object({
|
||||||
|
provider: z.string(),
|
||||||
|
})
|
||||||
|
.strict(),
|
||||||
|
),
|
||||||
|
})
|
||||||
|
.strict()
|
||||||
|
.optional()
|
||||||
|
.superRefine((fonts, ctx) => {
|
||||||
|
if (!fonts) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const providersNames = [
|
||||||
|
...BUILTIN_PROVIDERS,
|
||||||
|
...(fonts.providers ?? []).map((provider) => provider.name),
|
||||||
|
];
|
||||||
|
for (const family of fonts.families) {
|
||||||
|
if (!providersNames.includes(family.provider)) {
|
||||||
|
ctx.addIssue({
|
||||||
|
code: z.ZodIssueCode.custom,
|
||||||
|
message: `Invalid provider "${family.provider}". Please use of the following: ${providersNames.map((name) => `"${name}"`).join(', ')}`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}),
|
||||||
})
|
})
|
||||||
.strict(
|
.strict(
|
||||||
`Invalid or outdated experimental feature.\nCheck for incorrect spelling or outdated Astro version.\nSee https://docs.astro.build/en/reference/experimental-flags/ for a list of all current experiments.`,
|
`Invalid or outdated experimental feature.\nCheck for incorrect spelling or outdated Astro version.\nSee https://docs.astro.build/en/reference/experimental-flags/ for a list of all current experiments.`,
|
||||||
|
|
|
@ -17,8 +17,11 @@ import type { AstroCookieSetOptions } from '../../core/cookies/cookies.js';
|
||||||
import type { Logger, LoggerLevel } from '../../core/logger/core.js';
|
import type { Logger, LoggerLevel } from '../../core/logger/core.js';
|
||||||
import type { EnvSchema } from '../../env/schema.js';
|
import type { EnvSchema } from '../../env/schema.js';
|
||||||
import type { AstroIntegration } from './integrations.js';
|
import type { AstroIntegration } from './integrations.js';
|
||||||
|
import type { BuiltInProvider, FontFamily, FontProvider } from '../../assets/fonts/types.js';
|
||||||
export type Locales = (string | { codes: string[]; path: string })[];
|
export type Locales = (string | { codes: string[]; path: string })[];
|
||||||
|
|
||||||
|
export type { FontProvider };
|
||||||
|
|
||||||
type NormalizeLocales<T extends Locales> = {
|
type NormalizeLocales<T extends Locales> = {
|
||||||
[K in keyof T]: T[K] extends string
|
[K in keyof T]: T[K] extends string
|
||||||
? T[K]
|
? T[K]
|
||||||
|
@ -164,6 +167,10 @@ export interface ViteUserConfig extends OriginalViteUserConfig {
|
||||||
*/ export interface AstroUserConfig<
|
*/ export interface AstroUserConfig<
|
||||||
TLocales extends Locales = never,
|
TLocales extends Locales = never,
|
||||||
TSession extends SessionDriverName = never,
|
TSession extends SessionDriverName = never,
|
||||||
|
TFontProviders extends FontProvider<string>[] = never,
|
||||||
|
TFontFamilies extends FontFamily<
|
||||||
|
(TFontProviders extends never ? [] : TFontProviders)[number]['name'] | BuiltInProvider
|
||||||
|
>[] = never,
|
||||||
> {
|
> {
|
||||||
/**
|
/**
|
||||||
* @docs
|
* @docs
|
||||||
|
@ -2059,6 +2066,45 @@ export interface ViteUserConfig extends OriginalViteUserConfig {
|
||||||
*/
|
*/
|
||||||
mode: SvgRenderMode;
|
mode: SvgRenderMode;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @name experimental.fonts
|
||||||
|
* @type {object}
|
||||||
|
* @default `undefined`
|
||||||
|
* @version 5.x
|
||||||
|
* @description
|
||||||
|
*
|
||||||
|
* TODO:
|
||||||
|
*/
|
||||||
|
fonts?: {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @name experimental.fonts.providers
|
||||||
|
* @type {FontProvider[]}
|
||||||
|
* @version 5.x
|
||||||
|
* @description
|
||||||
|
*
|
||||||
|
* TODO:
|
||||||
|
*/
|
||||||
|
providers?: [TFontProviders] extends [never] ? FontProvider<string>[] : TFontProviders;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @name experimental.fonts.families
|
||||||
|
* @type {FontFamily[]}
|
||||||
|
* @version 5.x
|
||||||
|
* @description
|
||||||
|
*
|
||||||
|
* TODO:
|
||||||
|
*/
|
||||||
|
families: [TFontFamilies] extends [never]
|
||||||
|
? FontFamily<
|
||||||
|
| ([TFontProviders] extends [never] ? [] : TFontProviders)[number]['name']
|
||||||
|
| BuiltInProvider
|
||||||
|
>[]
|
||||||
|
: TFontFamilies;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,40 +2,234 @@ import { describe, it } from 'node:test';
|
||||||
import { expectTypeOf } from 'expect-type';
|
import { expectTypeOf } from 'expect-type';
|
||||||
import { defineConfig } from '../../dist/config/index.js';
|
import { defineConfig } from '../../dist/config/index.js';
|
||||||
import type { AstroUserConfig } from '../../dist/types/public/index.js';
|
import type { AstroUserConfig } from '../../dist/types/public/index.js';
|
||||||
|
import type { FontFamily, FontProvider } from '../../dist/assets/fonts/types.js';
|
||||||
|
|
||||||
|
function assertType<T>(data: T, cb: (data: NoInfer<T>) => void) {
|
||||||
|
cb(data);
|
||||||
|
}
|
||||||
|
|
||||||
describe('defineConfig()', () => {
|
describe('defineConfig()', () => {
|
||||||
it('Infers generics correctly', () => {
|
it('Infers i18n generics correctly', () => {
|
||||||
const config_0 = defineConfig({});
|
assertType(defineConfig({}), (config) => {
|
||||||
expectTypeOf(config_0).toEqualTypeOf<AstroUserConfig<never>>();
|
expectTypeOf(config).toEqualTypeOf<AstroUserConfig<never, never, never, never>>();
|
||||||
expectTypeOf(config_0.i18n!.defaultLocale).toEqualTypeOf<string>();
|
expectTypeOf(config.i18n!.defaultLocale).toEqualTypeOf<string>();
|
||||||
|
|
||||||
const config_1 = defineConfig({
|
|
||||||
i18n: {
|
|
||||||
locales: ['en'],
|
|
||||||
defaultLocale: 'en',
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
expectTypeOf(config_1).toEqualTypeOf<AstroUserConfig<['en']>>();
|
|
||||||
expectTypeOf(config_1.i18n!.defaultLocale).toEqualTypeOf<'en'>();
|
|
||||||
|
|
||||||
const config_2 = defineConfig({
|
assertType(
|
||||||
i18n: {
|
defineConfig({
|
||||||
locales: ['en', 'fr'],
|
i18n: {
|
||||||
defaultLocale: 'fr',
|
locales: ['en'],
|
||||||
|
defaultLocale: 'en',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
(config) => {
|
||||||
|
expectTypeOf(config).toEqualTypeOf<AstroUserConfig<['en'], never, never, never>>();
|
||||||
|
expectTypeOf(config.i18n!.defaultLocale).toEqualTypeOf<'en'>();
|
||||||
},
|
},
|
||||||
});
|
);
|
||||||
expectTypeOf(config_2).toEqualTypeOf<AstroUserConfig<['en', 'fr']>>();
|
|
||||||
expectTypeOf(config_2.i18n!.defaultLocale).toEqualTypeOf<'en' | 'fr'>();
|
|
||||||
|
|
||||||
const config_3 = defineConfig({
|
assertType(
|
||||||
i18n: {
|
defineConfig({
|
||||||
locales: ['en', { path: 'french', codes: ['fr', 'fr-FR'] }],
|
i18n: {
|
||||||
defaultLocale: 'en',
|
locales: ['en', 'fr'],
|
||||||
|
defaultLocale: 'fr',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
(config) => {
|
||||||
|
expectTypeOf(config).toEqualTypeOf<AstroUserConfig<['en', 'fr'], never, never, never>>();
|
||||||
|
expectTypeOf(config.i18n!.defaultLocale).toEqualTypeOf<'en' | 'fr'>();
|
||||||
},
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
assertType(
|
||||||
|
defineConfig({
|
||||||
|
i18n: {
|
||||||
|
locales: ['en', { path: 'french', codes: ['fr', 'fr-FR'] }],
|
||||||
|
defaultLocale: 'en',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
(config) => {
|
||||||
|
expectTypeOf(config).toEqualTypeOf<
|
||||||
|
AstroUserConfig<
|
||||||
|
['en', { readonly path: 'french'; readonly codes: ['fr', 'fr-FR'] }],
|
||||||
|
never,
|
||||||
|
never,
|
||||||
|
never
|
||||||
|
>
|
||||||
|
>();
|
||||||
|
expectTypeOf(config.i18n!.defaultLocale).toEqualTypeOf<'en' | 'fr' | 'fr-FR'>();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Infers fonts generics correctly', () => {
|
||||||
|
assertType(defineConfig({}), (config) => {
|
||||||
|
expectTypeOf(config).toEqualTypeOf<AstroUserConfig<never, never, never, never>>();
|
||||||
|
expectTypeOf(config.experimental!.fonts!.providers!).toEqualTypeOf<FontProvider<string>[]>();
|
||||||
|
expectTypeOf(config.experimental!.fonts!.families).toEqualTypeOf<
|
||||||
|
FontFamily<'google' | 'local'>[]
|
||||||
|
>();
|
||||||
});
|
});
|
||||||
expectTypeOf(config_3).toEqualTypeOf<
|
|
||||||
AstroUserConfig<['en', { readonly path: 'french'; readonly codes: ['fr', 'fr-FR'] }]>
|
assertType(
|
||||||
>();
|
defineConfig({
|
||||||
expectTypeOf(config_3.i18n!.defaultLocale).toEqualTypeOf<'en' | 'fr' | 'fr-FR'>();
|
experimental: {
|
||||||
|
fonts: {
|
||||||
|
families: [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
(config) => {
|
||||||
|
expectTypeOf(config).toEqualTypeOf<AstroUserConfig<never, never, never, []>>();
|
||||||
|
expectTypeOf(config.experimental!.fonts!.providers!).toEqualTypeOf<
|
||||||
|
FontProvider<string>[]
|
||||||
|
>();
|
||||||
|
expectTypeOf(config.experimental!.fonts!.families).toEqualTypeOf<[]>();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
assertType(
|
||||||
|
defineConfig({
|
||||||
|
experimental: {
|
||||||
|
fonts: {
|
||||||
|
families: [{ provider: 'google' }, { provider: 'local', src: 'test' }],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
(config) => {
|
||||||
|
expectTypeOf(config).toEqualTypeOf<
|
||||||
|
AstroUserConfig<
|
||||||
|
never,
|
||||||
|
never,
|
||||||
|
never,
|
||||||
|
[
|
||||||
|
{ readonly provider: 'google' },
|
||||||
|
{
|
||||||
|
readonly provider: 'local';
|
||||||
|
readonly src: 'test';
|
||||||
|
},
|
||||||
|
]
|
||||||
|
>
|
||||||
|
>();
|
||||||
|
expectTypeOf(config.experimental!.fonts!.providers!).toEqualTypeOf<
|
||||||
|
FontProvider<string>[]
|
||||||
|
>();
|
||||||
|
expectTypeOf(config.experimental!.fonts!.families).toEqualTypeOf<
|
||||||
|
[
|
||||||
|
{ readonly provider: 'google' },
|
||||||
|
{
|
||||||
|
readonly provider: 'local';
|
||||||
|
readonly src: 'test';
|
||||||
|
},
|
||||||
|
]
|
||||||
|
>();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
assertType(
|
||||||
|
defineConfig({
|
||||||
|
experimental: {
|
||||||
|
fonts: {
|
||||||
|
providers: [],
|
||||||
|
families: [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
(config) => {
|
||||||
|
expectTypeOf(config).toEqualTypeOf<AstroUserConfig<never, never, [], []>>();
|
||||||
|
expectTypeOf(config.experimental!.fonts!.providers!).toEqualTypeOf<[]>();
|
||||||
|
expectTypeOf(config.experimental!.fonts!.families).toEqualTypeOf<[]>();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
assertType(
|
||||||
|
defineConfig({
|
||||||
|
experimental: {
|
||||||
|
fonts: {
|
||||||
|
providers: [{ name: 'adobe', entrypoint: '' }],
|
||||||
|
families: [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
(config) => {
|
||||||
|
expectTypeOf(config).toEqualTypeOf<
|
||||||
|
AstroUserConfig<
|
||||||
|
never,
|
||||||
|
never,
|
||||||
|
[
|
||||||
|
{
|
||||||
|
readonly name: 'adobe';
|
||||||
|
readonly entrypoint: '';
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[]
|
||||||
|
>
|
||||||
|
>();
|
||||||
|
expectTypeOf(config.experimental!.fonts!.providers!).toEqualTypeOf<
|
||||||
|
[
|
||||||
|
{
|
||||||
|
readonly name: 'adobe';
|
||||||
|
readonly entrypoint: '';
|
||||||
|
},
|
||||||
|
]
|
||||||
|
>();
|
||||||
|
expectTypeOf(config.experimental!.fonts!.families).toEqualTypeOf<[]>();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
assertType(
|
||||||
|
defineConfig({
|
||||||
|
experimental: {
|
||||||
|
fonts: {
|
||||||
|
providers: [{ name: 'adobe', entrypoint: '' }],
|
||||||
|
families: [
|
||||||
|
{ provider: 'google' },
|
||||||
|
{ provider: 'local', src: 'test' },
|
||||||
|
{ provider: 'adobe' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
(config) => {
|
||||||
|
expectTypeOf(config).toEqualTypeOf<
|
||||||
|
AstroUserConfig<
|
||||||
|
never,
|
||||||
|
never,
|
||||||
|
[
|
||||||
|
{
|
||||||
|
readonly name: 'adobe';
|
||||||
|
readonly entrypoint: '';
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{ readonly provider: 'google' },
|
||||||
|
{
|
||||||
|
readonly provider: 'local';
|
||||||
|
readonly src: 'test';
|
||||||
|
},
|
||||||
|
{ readonly provider: 'adobe' },
|
||||||
|
]
|
||||||
|
>
|
||||||
|
>();
|
||||||
|
expectTypeOf(config.experimental!.fonts!.providers!).toEqualTypeOf<
|
||||||
|
[
|
||||||
|
{
|
||||||
|
readonly name: 'adobe';
|
||||||
|
readonly entrypoint: '';
|
||||||
|
},
|
||||||
|
]
|
||||||
|
>();
|
||||||
|
expectTypeOf(config.experimental!.fonts!.families).toEqualTypeOf<
|
||||||
|
[
|
||||||
|
{ readonly provider: 'google' },
|
||||||
|
{
|
||||||
|
readonly provider: 'local';
|
||||||
|
readonly src: 'test';
|
||||||
|
},
|
||||||
|
{ readonly provider: 'adobe' },
|
||||||
|
]
|
||||||
|
>();
|
||||||
|
},
|
||||||
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
{
|
{
|
||||||
"extends": "../../tsconfig.base.json",
|
"extends": "../../../../tsconfig.base.json",
|
||||||
"include": ["test/types"],
|
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
"emitDeclarationOnly": false,
|
"emitDeclarationOnly": false,
|
|
@ -370,7 +370,7 @@ describe('Config Validation', () => {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
process.cwd(),
|
process.cwd(),
|
||||||
).catch((err) => err),
|
),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -385,7 +385,7 @@ describe('Config Validation', () => {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
process.cwd(),
|
process.cwd(),
|
||||||
).catch((err) => err),
|
),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -427,4 +427,73 @@ describe('Config Validation', () => {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('fonts', () => {
|
||||||
|
it('Should allow empty providers and families', () => {
|
||||||
|
assert.doesNotThrow(() =>
|
||||||
|
validateConfig(
|
||||||
|
{
|
||||||
|
experimental: {
|
||||||
|
fonts: {
|
||||||
|
providers: [],
|
||||||
|
families: [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
process.cwd(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should not allow providers with reserved names', async () => {
|
||||||
|
let configError = await validateConfig(
|
||||||
|
{
|
||||||
|
experimental: {
|
||||||
|
fonts: {
|
||||||
|
providers: [{ name: 'google', entrypoint: '' }],
|
||||||
|
families: [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
process.cwd(),
|
||||||
|
).catch((err) => err);
|
||||||
|
assert.equal(configError instanceof z.ZodError, true);
|
||||||
|
assert.equal(
|
||||||
|
configError.errors[0].message.includes('"google" is a reserved provider name'),
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
|
||||||
|
configError = await validateConfig(
|
||||||
|
{
|
||||||
|
experimental: {
|
||||||
|
fonts: {
|
||||||
|
providers: [{ name: 'local', entrypoint: '' }],
|
||||||
|
families: [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
process.cwd(),
|
||||||
|
).catch((err) => err);
|
||||||
|
assert.equal(configError instanceof z.ZodError, true);
|
||||||
|
assert.equal(
|
||||||
|
configError.errors[0].message.includes('"local" is a reserved provider name'),
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should not allow using non registed providers', async () => {
|
||||||
|
const configError = await validateConfig(
|
||||||
|
{
|
||||||
|
experimental: {
|
||||||
|
fonts: {
|
||||||
|
families: [{ provider: 'custom' }],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
process.cwd(),
|
||||||
|
).catch((err) => err);
|
||||||
|
assert.equal(configError instanceof z.ZodError, true);
|
||||||
|
assert.equal(configError.errors[0].message.includes('Invalid provider "custom"'), true);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue