expo-font
Version:
Load fonts at runtime and use them in React Native components.
64 lines (55 loc) • 2.01 kB
text/typescript
import type { ExpoConfig } from 'expo/config';
import {
type ConfigPlugin,
IOSConfig,
type InfoPlist,
type XcodeProject,
withInfoPlist,
withXcodeProject,
} from 'expo/config-plugins';
import path from 'path';
import { resolveFontPaths } from './utils';
export const withFontsIos: ConfigPlugin<string[]> = (config, fonts) => {
config = addFontsToTarget(config, fonts);
config = addFontsToPlist(config, fonts);
return config;
};
function addFontsToTarget(config: ExpoConfig, fonts: string[]) {
return withXcodeProject(config, async (config) => {
const resolvedFonts = await resolveFontPaths(fonts, config.modRequest.projectRoot);
const project = config.modResults;
const platformProjectRoot = config.modRequest.platformProjectRoot;
IOSConfig.XcodeUtils.ensureGroupRecursively(project, 'Resources');
addResourceFile(project, platformProjectRoot, resolvedFonts);
return config;
});
}
function addFontsToPlist(config: ExpoConfig, fonts: string[]) {
return withInfoPlist(config, async (config) => {
const resolvedFonts = await resolveFontPaths(fonts, config.modRequest.projectRoot);
const existingFonts = getUIAppFonts(config.modResults);
const fontList = resolvedFonts.map((font) => path.basename(font)) ?? [];
const allFonts = [...existingFonts, ...fontList];
config.modResults.UIAppFonts = Array.from(new Set(allFonts));
return config;
});
}
function addResourceFile(project: XcodeProject, platformRoot: string, f: string[]) {
for (const font of f) {
const fontPath = path.relative(platformRoot, font);
IOSConfig.XcodeUtils.addResourceFileToGroup({
filepath: fontPath,
groupName: 'Resources',
project,
isBuildFile: true,
verbose: true,
});
}
}
function getUIAppFonts(infoPlist: InfoPlist): string[] {
const fonts = infoPlist['UIAppFonts'];
if (fonts != null && Array.isArray(fonts) && fonts.every((font) => typeof font === 'string')) {
return fonts as string[];
}
return [];
}