# 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
     * injectGlobal`${
     *   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