All files / mixins fontFace.js

100% Statements 22/22
100% Branches 17/17
100% Functions 6/6
100% Lines 14/14
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95                                22x 5x       5x 3x       6x 6x 6x 6x                                                                                     10x 9x 8x 7x   6x                         6x        
// @flow
 
/** */
type FontFaceConfiguration = {
  fontFamily: string;
  fontFilePath?: string;
  fontStretch?: string;
  fontStyle?: string;
  fontVariant?: string;
  fontWeight?: string;
  fileFormats?: Array<string>;
  localFonts?: Array<string>;
  unicodeRange?: string
}
 
function generateFileReferences(fontFilePath: string, fileFormats: Array<string>) {
  const fileFontReferences = fileFormats.map((format) => `url("${fontFilePath}.${format}")`)
  return fileFontReferences.join(', ')
}
 
function generateLocalReferences(localFonts: Array<string>) {
  const localFontReferences = localFonts.map((font) => `local("${font}")`)
  return localFontReferences.join(', ')
}
 
function generateSources(fontFilePath?: string, localFonts?: Array<string>, fileFormats: Array<string>) {
  const fontReferences = []
  if (localFonts) fontReferences.push(generateLocalReferences(localFonts))
  if (fontFilePath) fontReferences.push(generateFileReferences(fontFilePath, fileFormats))
  return fontReferences.join(', ')
}
 
/**
 * CSS for a @font-face declaration.
 *
 * @example
 * // Styles as object basic usage
 * const styles = {
 *    ...fontFace({
 *      'fontFamily': 'Sans-Pro'
 *      'fontFilePath': 'path/to/file'
 *    })
 * }
 *
 * // styled-components basic usage
 * injectGlobals`${
 *   fontFace({
 *     'fontFamily': 'Sans-Pro'
 *     'fontFilePath': 'path/to/file'
 *   }
 * )}`
 *
 * // CSS as JS Output
 *
 * '@font-face': {
 *   'font-family': '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")',
 * }
 */
 
function fontFace({
    fontFamily,
    fontFilePath,
    fontStretch,
    fontStyle,
    fontVariant,
    fontWeight,
    fileFormats = ['eot', 'woff2', 'woff', 'ttf', 'svg'],
    localFonts,
    unicodeRange,
  }: FontFaceConfiguration) {
  // Error Handling
  if (!fontFamily) throw new Error('fontFace expects a name of a font-family.')
  if (!fontFilePath && !localFonts) throw new Error('fontFace expects either the path to the font file(s) or a name of a local copy.')
  if (localFonts && !Array.isArray(localFonts)) throw new Error('fontFace expects localFonts to be an array.')
  if (!Array.isArray(fileFormats)) throw new Error('fontFace expects fileFormats to be an array.')
 
  const fontFaceDeclaration = {
    '@font-face': {
      'font-family': fontFamily,
      'src': generateSources(fontFilePath, localFonts, fileFormats),
      'unicode-range': unicodeRange,
      'font-stretch': fontStretch,
      'font-style': fontStyle,
      'font-variant': fontVariant,
      'font-weight': fontWeight,
    },
  }
 
  // Removes undefined fields for cleaner css object.
  return JSON.parse(JSON.stringify(fontFaceDeclaration))
}
 
export default fontFace