Skip to content

A metadata generator that fetches and parses the Google Fonts API.

License

Notifications You must be signed in to change notification settings

fontsource/google-font-metadata

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Google Font Metadata

npm version License GitHub stars

A metadata generator that fetches and parses the Google Fonts API to be primarily used for the Fontsource monorepo.

Installation

Install the package from npm:

npm install google-font-metadata

Usage

The project exports the following data:

import {
    APIv1,
    APIv2,
    APIVariable,
    APIIconStatic,
    APIIconVariable,
    APILicense,
    APIRegistry,
} from "google-font-metadata";
const {
    APIv1,
    APIv2,
    APIVariable,
    APIIconStatic,
    APIIconVariable,
    APILicense,
    APIRegistry,
} = require("google-font-metadata");

console.dir(APIv2);

APIv1

Uses the Google Fonts CSS APIv1 that includes different font files for each subset, but does NOT include unicode-range values. This isn't usually recommended.

It exports data/google-fonts-v1.json.

{
...
"abel": {
    "family": "Abel",
    "id": "abel",
    "subsets": ["latin"],
    "weights": [400],
    "styles": ["normal"],
    "variants": {
      "400": {
        "normal": {
          "latin": {
            "url": {
              "woff2": "https://fonts.gstatic.com/s/abel/v18/MwQ5bhbm2POE2V9BPQ.woff2",
              "woff": "https://fonts.gstatic.com/s/abel/v18/MwQ5bhbm2POE2V9BOw.woff",
              "truetype": "https://fonts.gstatic.com/s/abel/v18/MwQ5bhbm2POE2V9BOA.ttf"
            }
          }
        }
      }
    },
    "defSubset": "latin",
    "lastModified": "2022-04-20",
    "version": "v18",
    "category": "sans-serif"
  },
...
}

APIv2

Uses the Google Fonts CSS APIv2 and includes the unicode-range values for every subset. However, the API serves ttf files with ALL subsets included in one file and therefore all links for those file types in the same subset lead to the same link for each weight and style. woff2 and woff files are individually split per subset.

Exports data/google-fonts-v2.json.

{
...
"abel": {
    "family": "Abel",
    "id": "abel",
    "subsets": ["latin"],
    "weights": [400],
    "styles": ["normal"],
    "unicodeRange": {
      "latin": "U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD"
    },
    "variants": {
      "400": {
        "normal": {
          "latin": {
            "url": {
              "woff2": "https://fonts.gstatic.com/s/abel/v18/MwQ5bhbm2POE2V9BPQ.woff2",
              "woff": "https://fonts.gstatic.com/s/abel/v18/MwQ5bhbm2POE6Vs.woff",
              "truetype": "https://fonts.gstatic.com/s/abel/v18/MwQ5bhbm2POE6Vg.ttf"
            }
          }
        }
      }
    },
    "defSubset": "latin",
    "lastModified": "2022-04-20",
    "version": "v18",
    "category": "sans-serif"
  },
...
}

Note that fonts with large glyphsets such as the Japanese, Korean or Chinese language, are divided into many smaller numbered subsets that utilize the unicode-range @fontface selector. An example is Noto Sans JP which returns the following:

{
...
 "noto-sans-jp": {
    "family": "Noto Sans JP",
    "id": "noto-sans-jp",
    "subsets": ["japanese", "latin"],
    "weights": [100, 300, 400, 500, 700, 900],
    "styles": ["normal"],
    "unicodeRange": {
      "[0]": "U+25ee8,...,U+2f9f4",
      "[1]": "U+1f235-1f23b,...,U+25ed8",
      ...
      "[119]": "U+20,...,U+ff0e"
      },
    "variants": {
      "100": {
        "normal": {
          "[0]": {
            "url": {
              "woff2": "https://fonts.gstatic.com/s/notosansjp/v42/-F6ofjtqLzI2JPCgQBnw7HFQoggPkENvl4B0ZLgOquiXidBa3qHiDcp2RQ.0.woff2",
              "woff": "https://fonts.gstatic.com/s/notosansjp/v42/-F62fjtqLzI2JPCgQBnw7HFoxQII2lcnk-AFfrgQrvWXpdFg3KXxAMsKMbdN.0.woff",
              "opentype": "https://fonts.gstatic.com/s/notosansjp/v42/-F6ofjtqLzI2JPCgQBnw7HFQoggM.otf"
            }
          },
          ...,
        },
        ...,
      }
    }
  }
...
}

APIVariable

Scrapes the Google Fonts directory and uses the Google Fonts API to generate all the relevant axis definitions and download variant metadata. You can learn more variable font axis' here.

There are 3 default variants:

  • wght - Only links to font files that only have the wght axis.
  • standard - A default set of fonts that includes wght, wdth, slnt, opsz axis' if available.
  • full - Links to font files that have all the axis' included within them.

Furthermore, a variant is generated for each unique axis in the font, e.g. if wdth exists, variants.wdth.normal.latin will exist. Note that the wght axis is also included in each unique custom variant.

Note that standard or full variants may not exist if there are no relevant axes in the font for that classification. This is to prevent duplicate variants with different names.

Exports data/variable.json.

{
...
"akshar": {
    "family": "Akshar",
    "id": "akshar",
    "axes": {
      "wght": { "default": "400", "min": "300", "max": "700", "step": "1" }
    },
    "variants": {
      "wght": {
        "normal": {
          "devanagari": "https://fonts.gstatic.com/s/akshar/v5/Yq6V-LyHWTfz9rGCpR5lhOc.woff2",
          "latin-ext": "https://fonts.gstatic.com/s/akshar/v5/Yq6V-LyHWTfz9rGCqh5lhOc.woff2",
          "latin": "https://fonts.gstatic.com/s/akshar/v5/Yq6V-LyHWTfz9rGCpB5l.woff2"
        }
      },
      "full": {
        "normal": {
          "devanagari": "https://fonts.gstatic.com/s/akshar/v5/Yq6V-LyHWTfz9rGCpR5lhOc.woff2",
          "latin-ext": "https://fonts.gstatic.com/s/akshar/v5/Yq6V-LyHWTfz9rGCqh5lhOc.woff2",
          "latin": "https://fonts.gstatic.com/s/akshar/v5/Yq6V-LyHWTfz9rGCpB5l.woff2"
        }
      },
      "standard": {
        "normal": {
          "devanagari": "https://fonts.gstatic.com/s/akshar/v5/Yq6V-LyHWTfz9rGCpR5lhOc.woff2",
          "latin-ext": "https://fonts.gstatic.com/s/akshar/v5/Yq6V-LyHWTfz9rGCqh5lhOc.woff2",
          "latin": "https://fonts.gstatic.com/s/akshar/v5/Yq6V-LyHWTfz9rGCpB5l.woff2"
        }
      }
    }
  },
...
}

Note that certain fonts such as Inter or Recursive have the SLNT axis, meaning their font-style in CSS won't be normal or italic on property full but oblique x deg x deg. Refer to the CSS test fixture for Recursive. While still showing as normal in metadata, it is up to the developer to include the oblique style if they are generating CSS using the min and max values from recursive.axes.slnt property.

APIDirect and APIVariableDirect

These are arrays of generated objects from the npx gfm generate [key] command. It is unlikely you will use this.

import { APIDirect, APIVariableDirect } from "google-font-metadata";
const { APIDirect, APIVariableDirect } = require("google-font-metadata");

Exports data/api-response.json and data/variable-response.json respectively.

APILicense

Scrapes the Google Fonts Attribution page and returns a readable object.

{
...
  "abel": {
    "id": "abel",
    "authors": {
      "copyright": "Copyright 2011, Matthew Desmond with Reserved Font Name Abel.",
      "website": "http://www.madtype.com",
      "email": "[email protected]"
    },
    "license": {
      "type": "SIL Open Font License, 1.1",
      "url": "http://scripts.sil.org/OFL"
    },
    "original": "Copyright (c) 2011, Matthew Desmond (http://www.madtype.com | [email protected]), with Reserved Font Name Abel."
  },
...
}

Exports data/licenses.json

APIRegistry

{
...
  {
    "name": "Thick Stroke",
    "tag": "XOPQ",
    "min": -1000,
    "max": 2000,
    "default": 88,
    "precision": 0
  },
...
}

Exports data/axis-registry.json

You can refer to src/index.ts and src/data.ts to see all exports.

Updating API Files

You can use the gfm CLI tool to update the metadata with fresh results from the Google APIs.

npx gfm generate [key] - Fetches the default Google Fonts API which can be used for parsing later. This has to be called before npx gfm parse.

Flags:

  • -n, --normal - Only fetch the normal Google Developer API for APIv1 and APIv2.
  • -v, --variable - Only scrape the variable axis page for APIVariable. Note key does not need to be given if this option is passed.

You are able to get a Google Fonts API key value from here. Alternatively, you can use a .env file with API_KEY=keyvalue instead of providing a key argument in the command.

npx gfm parse - Parses through the Google Fonts CSS API and generate full metadata using the generate command data.

Flags:

  • -1, --v1 - Only parse and update APIv1.
  • -2, --v2 - Only parse and update APIv2.
  • -v, --variable - Only parse and update APIVariable.
  • -l, --license - Only parse and update APILicense.
  • -f, --force - This skips the cache and force parses every font.
  • --no-validate - This skips invoking npx gfm validate after finishing parsing.

npx gfm validate - Helper command to validate your existing metadata with a schema. This is automatically invoked with npx gfm parse.

Flags:

  • -1, --v1 - Only validate APIv1.
  • -2, --v2 - Only validate APIv2.
  • -v, --variable - Only validate APIVariable.