123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134 |
- // @flow
- import PolishedError from '../internalHelpers/_errors'
- import type { FontFaceConfiguration } from '../types/fontFaceConfiguration'
- import type { Styles } from '../types/style'
- const dataURIRegex = /^\s*data:([a-z]+\/[a-z-]+(;[a-z-]+=[a-z-]+)?)?(;charset=[a-z0-9-]+)?(;base64)?,[a-z0-9!$&',()*+,;=\-._~:@/?%\s]*\s*$/i
- const formatHintMap = {
- woff: 'woff',
- woff2: 'woff2',
- ttf: 'truetype',
- otf: 'opentype',
- eot: 'embedded-opentype',
- svg: 'svg',
- svgz: 'svg',
- }
- function generateFormatHint(format: string, formatHint: boolean): string {
- if (!formatHint) return ''
- return ` format("${formatHintMap[format]}")`
- }
- function isDataURI(fontFilePath: string): boolean {
- return !!fontFilePath.replace(/\s+/g, ' ').match(dataURIRegex)
- }
- function generateFileReferences(
- fontFilePath: string,
- fileFormats: Array<string>,
- formatHint: boolean,
- ): string {
- if (isDataURI(fontFilePath)) {
- return `url("${fontFilePath}")${generateFormatHint(fileFormats[0], formatHint)}`
- }
- const fileFontReferences = fileFormats.map(
- format => `url("${fontFilePath}.${format}")${generateFormatHint(format, formatHint)}`,
- )
- return fileFontReferences.join(', ')
- }
- function generateLocalReferences(localFonts: Array<string>): string {
- const localFontReferences = localFonts.map(font => `local("${font}")`)
- return localFontReferences.join(', ')
- }
- function generateSources(
- fontFilePath?: string,
- localFonts: Array<string> | null,
- fileFormats: Array<string>,
- formatHint: boolean,
- ): string {
- const fontReferences = []
- if (localFonts) fontReferences.push(generateLocalReferences(localFonts))
- if (fontFilePath) {
- fontReferences.push(generateFileReferences(fontFilePath, fileFormats, formatHint))
- }
- return fontReferences.join(', ')
- }
- /**
- * CSS for a @font-face declaration. Defaults to check for local copies of the font on the user's machine. You can disable this by passing `null` to localFonts.
- *
- * @example
- * // Styles as object basic usage
- * const styles = {
- * ...fontFace({
- * 'fontFamily': 'Sans-Pro',
- * 'fontFilePath': 'path/to/file'
- * })
- * }
- *
- * // styled-components basic usage
- * const GlobalStyle = createGlobalStyle`${
- * fontFace({
- * 'fontFamily': 'Sans-Pro',
- * 'fontFilePath': 'path/to/file'
- * }
- * )}`
- *
- * // CSS as JS Output
- *
- * '@font-face': {
- * 'fontFamily': 'Sans-Pro',
- * 'src': 'url("path/to/file.eot"), url("path/to/file.woff2"), url("path/to/file.woff"), url("path/to/file.ttf"), url("path/to/file.svg")',
- * }
- */
- export default function fontFace({
- fontFamily,
- fontFilePath,
- fontStretch,
- fontStyle,
- fontVariant,
- fontWeight,
- fileFormats = ['eot', 'woff2', 'woff', 'ttf', 'svg'],
- formatHint = false,
- localFonts = [fontFamily],
- unicodeRange,
- fontDisplay,
- fontVariationSettings,
- fontFeatureSettings,
- }: FontFaceConfiguration): Styles {
- // Error Handling
- if (!fontFamily) throw new PolishedError(55)
- if (!fontFilePath && !localFonts) {
- throw new PolishedError(52)
- }
- if (localFonts && !Array.isArray(localFonts)) {
- throw new PolishedError(53)
- }
- if (!Array.isArray(fileFormats)) {
- throw new PolishedError(54)
- }
- const fontFaceDeclaration = {
- '@font-face': {
- fontFamily,
- src: generateSources(fontFilePath, localFonts, fileFormats, formatHint),
- unicodeRange,
- fontStretch,
- fontStyle,
- fontVariant,
- fontWeight,
- fontDisplay,
- fontVariationSettings,
- fontFeatureSettings,
- },
- }
- // Removes undefined fields for cleaner css object.
- return JSON.parse(JSON.stringify(fontFaceDeclaration))
- }
|