New: Command-line tool for Glyphs

Or add a callback from the plugin.

glyphs-cli 0.2.1 is out now with fixes for variable font export. You can install the updated version as always with

python3 -m pip install glyphs-cli --upgrade
2 Likes

glyphs --format tt --format cff ... would be cool to compile both in one go.

Also --plugins ā€œā€ could be the default, at least when you provide --app with a specific version. I was confused why using a specific version would fail with some plugin failures in my local GlyphsApp installed plugins.

glyphs-cli 0.3.0 is out now with support for multiple outline formats (CFF and TrueType at once), and multiple container formats (OTF/TTF, WOFF, and WOFF 2). There is now also a --config option to provide a custom export configuration for advanced control.

You can install the updated version as always with

pip install glyphs-cli --upgrade

glyphs export --format

You can now provide a comma-separated list of outline formats to glyphs export --format:

glyphs export --format cff,tt ...

The command above export both CFF/PostScript- and TrueType-flavor OpenType fonts.

glyphs export --container

Use the new --container option to choose which font container formats to export:

  • standard (OTF/TTF)
  • woff (WOFF)
  • woff2 (WOFF 2)

By default, standard is used. You can provide a comma-separated list of container formats:

glyphs export --container standard,woff2 ...

glyphs export --config <file>

A configuration file that can change export settings and specify specific instances.

The file format is JSON5, a superset of JSON with support for comments, unquoted keys, and trailing commas.

The file is an object with the following values:

  • "settings": (optional) Export settings.
  • "sourceFiles": (optional) List of file paths to source files to export. These source files are used in addition to the files specified as <source> arguments.

Each source file in "sourceFiles" is an object with the following values:

  • "filePath": File path to the source file.
  • "instances": (optional) Array of instance configurations. If unset, uses all instances of the source file.
  • "settings": (optional) Export settings overriding the config-file-level settings.

Each instance configuration in "instances" is an object with the following values:

  • "selector": Selects an instance from the source file. An integer selects the instance at that index; a string selects the instance with that name.
  • "fileName": (optional) Specifies a custom file name for the exported font file.
  • "settings": (optional) Export settings overriding the source-file-level settings.

Export settings can be specified using command-line arguments (e.g., --output, --format, …), in the config file, per source file, and per instance. The settings use inheritance such that a more specific scope overwrites the settings of a less specific scope. For example, setting the outline format for an instance uses it over the value set for the source file, in the config file, and from the arguments. The settings offer the following optional values:

  • "outputPath": File path to the directory into which to export the font files.
  • "outlineFormats": Array of strings; "cff" (CFF/PostScript) or "tt" (TrueType).
  • "containerFormats": Array of strings; "standard" (OTF/TTF), "woff" (WOFF), or "woff2" (WOFF 2).
  • "autohint", "removeOverlap", "useSubroutines", "useProductionNames", "optimizeDeltas": Explicitly enabled or disabled these options. If unset, the default choice of the selected Glyphs app version is used.

For example, the following config file defines that both CFF and TrueType versions of all instances should be exported:

{
  settings: {
    outlineFormats: ["cff", "tt"],
  },
}

The config above is equivalent to passing the --format cff,tt argument.
Settings can also be scoped to source files:

{
  settings: {
    outlineFormats: ["cff", "tt"],
  },
  sourceFiles: [
    {
      filePath: "SomeFont.glyphspackage",
    },
    {
      filePath: "OtherFont.glyphspackage",
      settings: {
        outlineFormats: ["tt"],
      },
    },
  ],
}

Here, SomeFont.glyphspackage and any other source files provided as <source> arguments are exported using both CFF and TrueType outlines, but OtherFont.glyphspackage is exported just using TrueType outlines.

Settings can also be specifically scoped to instances:

{
  sourceFiles: [
    {
      filePath: "SomeFont.glyphspackage",
      instances: [
        {
          selector: "Regular",
        },
        {
          selector: "Regular",
          fileName: "SomeFont-Regular-SourceGlyphNames",
          settings: {
            useProductionNames: false,
          },
        },
      ],
    },
  ],
}

Here, the same instance is exported twice, each time with different settings. A separate fileName is specified for the second instance so the two instances don’t use the same export file name and thus don’t overwrite each other.

glyphs export --json

The glyphs export --plain option is now renamed to --json and provides more details about the exported font files.

When the --json flag is set, the tool writes a JSON report for each processed instance on a separate line. Each report is an object with the following values:

  • "sourceFilePath": Absolute file path to the source file.
  • "instanceName": Name of the instance.
  • "exportConfiguration": Configuration settings used for the export.
  • "exportFilePath": Absolute file path to the exported font file. May be null.
  • "warnings", "errors": Array of objects with string values for the keys title, instancePath, and description.

"exportConfiguration" is an object with the following values:

  • "outlineFormat": "cff" (CFF/PostScript) or "tt" (TrueType).
  • "containerFormat": "standard" (OTF/TTF), "woff" (WOFF), or "woff2" (WOFF 2).
  • "autohint", "removeOverlap", "useSubroutines", "useProductionNames", "optimizeDeltas": (optional, Boolean) Whether these options were explicitly enabled or disabled. If unset, the default choice of the selected Glyphs app version was used.
2 Likes

Could you elaborate on why using --app with a specific version should handle plug-ins differently? I mostly use the glyphs tool with --app 3 to use the latest version of Glyphs 3.

Like I said, I found it confusing running glyphs export --app 3523 ... and seeing errors caused by my local GlyphsApp installed plugins. I was under the impression using the --app argument would use a ā€œstandaloneā€ compiler, always, so why would that concern itself with anything user-installed.

Or if you think about it the other way around. I want to spec --app so that a compile is repeatable on different machines. I explicitly do not want any user-installed plugins from their environment mess with the compile.

Generally speaking, I would almost always feel it more intuitive if --plugins was unset. I mean, almost all the plugins a regular user will have installed would be for drawing and not relevant for compiles, or am I under some misconception here? For those cases where it would be relevant, using ā€œappā€ or explicit lists seems a much more understandable action than defaulting to always pull any installed (or not installed) plugins into a command line compile.

Great job adding the format and container options :raising_hands:

That was mostly my impression as well launching the CLI tool, but the requests for plug-in support were immediate and numerous. I think most of this are filter plug-ins and other export-time modifications. I am keeping an eye on how this develops.

1 Like

A couple of observations:

  • The ā€œinstancesā€ is kind of clumsy to use; the ā€œselectorā€ property should take maybe more than just the style name into account, e.g. full family + stylename (e.g. one source with 2 VFs, 2x8 instances, each with different filters: You have ā€œRegularā€ 4 times, so style name as selector is unusable), and defining 16 instances by index is error-prone
  • It would be cool if ā€œinstancesā€ ā€œselectorā€ could be a regex; easily include/exclude e.g. ā€œVariableā€ instances
  • ā€œRemoveOverlapā€ defined as filter on an instance in the source file as Custom Parameter results in a error with filter not found, I suppose it conflicts with the ā€œsettingā€ somehow
  • Maybe output which is used when instances in the source file define ā€œfileNameā€, to clarify which is used

I agree that instance selection can be clumsy. I will add the option to use static/variable as part of the selection as well as other name components. Remove Overlap should work as a filter regardless of the settings, I will have a look at that.

I am not sure I understand. Could you give an example?

Is there something specific to do with a GitHub Action to ensure that a custom GlyphData.xml is properly referenced? I’m seeing different results from a straight export from Glyphs vs. what the same file exported through a GitHub Action is doing and it mostly seems related to things I’ve defined in my custom glyph data.