Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/forwardemail/custom-fonts-in-emails

An extremely easy way to use custom fonts in emails without having to use art software.
https://github.com/forwardemail/custom-fonts-in-emails

alternative asset custom dynamic email emails engine font fonts image png render renderer responsive static svg template templates text view

Last synced: about 1 month ago
JSON representation

An extremely easy way to use custom fonts in emails without having to use art software.

Awesome Lists containing this project

README

        

# custom-fonts-in-emails

[![build status](https://github.com/ladjs/custom-fonts-in-emails/actions/workflows/ci.yml/badge.svg)](https://github.com/ladjs/custom-fonts-in-emails/actions/workflows/ci.yml)
[![code style](https://img.shields.io/badge/code_style-XO-5ed9c7.svg)](https://github.com/sindresorhus/xo)
[![styled with prettier](https://img.shields.io/badge/styled_with-prettier-ff69b4.svg)](https://github.com/prettier/prettier)
[![made with lass](https://img.shields.io/badge/made_with-lass-95CC28.svg)](https://lass.js.org)
[![license](https://img.shields.io/github/license/ladjs/custom-fonts-in-emails.svg)](LICENSE)

**An extremely easy way to use custom fonts in emails without having to use art software.**

## Table of Contents

* [Features](#features)
* [What does this do](#what-does-this-do)
* [Old Approach](#old-approach)
* [New Approach](#new-approach)
* [Examples](#examples)
* [Install](#install)
* [Usage](#usage)
* [Options](#options)
* [textToSvg](#texttosvg)
* [API](#api)
* [`customFonts.setDefaults(options)`](#customfontssetdefaultsoptions)
* [`customFonts.setOptions(options)`](#customfontssetoptionsoptions)
* [`customFonts.svg(options)`](#customfontssvgoptions)
* [`customFonts.img(options)`](#customfontsimgoptions)
* [`customFonts.png(options, scale)`](#customfontspngoptions-scale)
* [`customFonts.png2x(options)`](#customfontspng2xoptions)
* [`customFonts.png3x(options)`](#customfontspng3xoptions)
* [`customFonts.getAvailableFontPaths()`](#customfontsgetavailablefontpaths)
* [`customFonts.getAvailableFontNames()`](#customfontsgetavailablefontnames)
* [`customFonts.customFontsCache`](#customfontscustomfontscache)
* [License](#license)

## Features

* :art: Outputs optimized SVG, PNG, and Base64 inlined images with optional support for [**@2x**](https://github.com/2x) and [**@3x**](https://github.com/3x) Retina versions (uses the incredibly fast and performant [sharp][sharp]).
* :bulb: Automatic smart-detection of font names spelled incorrectly (or with the wrong extension) with 50% accuracy (uses [fast-levenshtein][fast-levenshtein] and checks for at least 50% distance match).
* :crystal\_ball: Detects user, local, network, system fonts, and `node_modules` folder fonts using [os-fonts][os-fonts] and [pkg-up][pkg-up] (e.g. you don't need to write `Arial.ttf`, you can just write `Arial`).
* :tada: Supports all WOFF, OTF, and TTF fonts (both with TrueType `glyf` and PostScript `cff` outlines).
* :sparkles: Use with recommended packages [nodemailer][nodemailer] and [nodemailer-base64-to-s3][nodemailer-base64-to-s3], or simply use [Lad][lad-url] (has this built-in).
* :pear: Pairs great with [font-awesome-assets][font-awesome-assets] and [juice][juice] (see [Lad's][lad-url] usage as an example).
* :white\_check\_mark: Supports offline and missing image support by automatically adding `alt`, `title`, and `style` attributes of `color` and `font-size` based upon the options passed.

## What does this do

* Imagine you find a really cool font on GitHub such as [GoudyBookletter1911][goudybookletter1911], or another font at sites like [DaFont][dafont] or [Font Squirrel][font-squirrel].
* You want to use this font in your emails and write the text "Make something people want" with it to use as a footer graphic. **:tada: Congratulations, because this package lets you do that with basically one line of code!**
* Let's compare the old and new way (thanks to this package) to put custom fonts in emails.

### Old Approach

Here's the old, slow, and convoluted way you'd do this:

1. Typically you'd have to open Photoshop, GIMP, or Sketch (wait for the updates to finish), and then create an image with this text, select the font, color, and then save it as an image.
2. Then upload it somewhere or have to wait until it deploys to production so you have a valid non-local URL (which is prone to caching in Gmail – in other words... if you ever need to make a slight adjustment to it then you have to completely rename the file).
3. Reference the image in your HTML and try to rememember it's dimensions, or have to open up the art software again to get dimensions. What about Retina? What if you need to change the size or color of the font? What if you need to convert points to pixels? Just forget it... It's too complicated and time consuming, and now your emails will look boring like they always did! :frowning: :rage:

### New Approach

:boom: You don't need to do that anymore! :smile: Here's how easy it is:

```js
import customFonts from 'custom-fonts-in-emails';
import path from 'path';

const options = {
text: 'Make something people want',
fontNameOrPath: 'GoudyBookletter1911',
fontColor: 'white',
backgroundColor: '#ff6600',
fontSize: 40
};

customFonts.png2x(options)
.then(console.log)
.catch(console.error);
```

```html
Make something people want
```

Make something people want

You can now use any font in your emails – without having to use art software like Photoshop or Sketch!

It supports system-wide and `node_modules` fonts out of the box, but you can pass a file path if you wish to use a custom non-standard font. You can also customize its kerning, anchor, color/fill, stroke, font size (even in points if needed), add custom attributes to the HTML tag, and more! See [Usage](#usage), [Options](#options), and the [API](#api) reference below for more info.

It even uses the [fast-levenshtein][fast-levenshtein] algorithm to detect the closest match to the spelling of a font (e.g. in case you mispellled `Arial` as `Arail`).

## Examples

Using the options defined in [New Approach](#new-approach) above, the following code provides examples of this package's [API](#api) methods.

| API Method and Preview | Image Type |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ |
| `customFonts.svg(options)` Make something people want | SVG tag `` |
| `customFonts.img(options)` Make something people want | IMG tag `` with Base64-encoded Inline SVG |
| `customFonts.png(options, scale)` Make something people want | IMG tag `` with Base64-encoded Inline PNG |
| `customFonts.png@2x(options)` Make something people want | IMG tag `` with Base64-encoded Inline PNG [**@2x**](https://github.com/2x) Resolution |
| `customFonts.png@3x(options)` Make something people want | IMG tag `` with Base64-encoded Inline PNG [**@3x**](https://github.com/3x) Resolution |

Lastly, here's what a broken image looks like that was attempted to be rendered with an API method. It makes use of the option `supportsFallback` defined below in [Options](#options). This is a really useful fallback for offline emails, invalid cached images, and more!

Make something people want

## Install

```bash
npm install -s custom-fonts-in-emails
```

## Usage

```js
import customFonts from 'custom-fonts-in-emails';
```

or

```js
import {
setDefaults,
setOptions,
svg,
img,
png,
png2x,
png3x,
getClosestFontName,
getFontPathsByName,
getFontPathByName,
getAvailableFontPaths,
getAvailableFontNames,
// optional: this is a cache of all the custom fonts loaded
customFontsCache
} from 'custom-fonts-in-emails';
```

If you plan to use this for outbound emails, then you'll want to make use of [nodemailer][nodemailer] and [nodemailer-base64-to-s3][nodemailer-base64-to-s3]. Or you can simply use [Lad][lad-url], which has this built-in already!

## Options

The `options` argument in all [API](#api) methods is an Object that accepts the following properties:

| Property | Type | Description |
| ------------------ | :--------------: | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `text` | String | Text to write using the font family specified in `fontNameOrPath` (defaults to an empty String of `''`) |
| `fontNameOrPath` | String | Name or file path of the font (defaults to `Arial` – note that by default we load user, local, network, system, and `node_modules` fonts across any operating system using [os-fonts][os-fonts], so you can use any font installed!) |
| `fontSize` | Number or String | Size of font **in pixels**, which is rounded to nearest whole Integer (this automatically sets `options.textToSvg.fontSize` – defaults to `24px`, but you don't need to specify the affix `px` as it is automatically stripped and converted to the nearest whole Integer using `Math.round(parseInt(val, 10))` – this value must be greater than 0) |
| `fontColor` | String | Valid hex color or rgba value to render the text fill color with with (defaults to `#000`) |
| `backgroundColor` | String | Valid hex color or rgba value to render the background color with (defaults to `transparent`) |
| `supportsFallback` | Boolean | Ensure that the output image has fallback attributes `title` and `alt` (both set to the value of `options.text`), and `style` which is set to or concatenated with `color` set to `options.fontColor`, `font-size` set to `options.fontSize / 2` (for vertical centering we divide by 2), `line-height` set to `options.fontSize` affixed with `px`, and finally `text-align: center` &ndash not applicable to `customFonts.svg` (defaults to `true`) |
| `resizeToFontSize` | Boolean | Ensure that the output image height is resized to `fontSize`, and its width is proportionally scaled – not applicable to `customFonts.svg` nor `customFonts.img` (defaults to `false`) |
| `trim` | Boolean | Ensure that the output image is trimmed using [sharp][sharp]'s [trim][trim] API method – it trims "boring" pixels from the edges – not applicable to `customFonts.svg` nor `customFonts.img` (defaults to `false`) |
| `trimTolerance` | Number | Must be from 1-99 inclusive, sets the trim tolerance value using [trim][trim] (defaults to `10`) |
| `attrs` | Object | Attribute key-value pairs that will be applied to the returned tag (defaults to `{}`, e.g. if you want to make the image output a fixed height scaled proportionally, then you can do `{ style: 'height: 40px; width: auto;' }`, **this is useful if you want to add custom CSS classes, style attributes, or other attributes in general to the returned tags**) |
| `textToSvg` | Object | Options defined in [textToSvg](#texttosvg) below which get passed to [text-to-svg][text-to-svg] (and subsequently [opentype.js][opentype.js]): |

### textToSvg

| Property | Type | Description |
| ------------ | :----: | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `x` | Number | Horizontal position of the beginning of the text (defaults to `0`) |
| `y` | Number | Vertical position of the baseline of the text (defaults to `0`) |
| `fontSize` | Number | Size of the text in points (defaults to `options.fontSize`) |
| `anchor` | String | Anchor of object in coordinate (defaults to `left top` – the String consists of `horizontal vertical`, where `horizontal` can be one of `left`, `center`, or `right`, and `vertical` can be one of `baseline`, `top`, `middle`, `bottom`) |
| `attributes` | Object | Attribute key-value pairs that will be applied to the returned `` element inside the `` tag (defaults to `{ fill: '#000', stroke: 'none' }` – note that if you specify `fontColor` then it will set `fill` equal to `fontColor`, but it can be overridden this attribute explicitly!) |

## API

### `customFonts.setDefaults(options)`

A function that accepts [options](#options) to set defaults for future use and returns a Promise that resolveswith the new package defaults.

### `customFonts.setOptions(options)`

A function that accepts [options](#options) and returns a Promise that resolves with refined `options`.

### `customFonts.svg(options)`

A function that accepts [options](#options) and returns a Promise that resolves with a String of the `` HTML tag for the custom font.

This function takes the argument `options` and passes it to `customFonts.setOptions`.

### `customFonts.img(options)`

Same as `customFonts.svg`, except it returns the String as Base64 inlined data.

### `customFonts.png(options, scale)`

Same as `customFonts.img`, except it returns Base64 inlined data for a PNG instead of an SVG.

It also optionally accepts a Number `scale` (defaults to `1`), which will scale the image for retina support.

For example, if the font rendered is 20px, then it will multiply 20px by `scale` (e.g. if `scale` is `2`, then the image returned will be `20px` but it will be scaled to `40px`).

### `customFonts.png2x(options)`

Same as `customFonts.png`, except it returns an image with twice as many pixels (it multiplies `fontSize * 2` and returns an image scaled to 1x for 2x retina support, it passes `2` as the `scale`).

### `customFonts.png3x(options)`

Same as `customFonts.png`, except it returns an image with three as many pixels (it multiplies `fontSize * 3` and returns an image scaled to 1x for 3x retina support, it passes `3` as the `scale`).

### `customFonts.getAvailableFontPaths()`

A function that returns an Array of file paths for all of the user, local, network, system, and `node_modules` fonts available on the current operating system.

### `customFonts.getAvailableFontNames()`

The same as `customFonts.getAvailableFontPaths`, except it returns font names instead of font paths.

### `customFonts.customFontsCache`

This is an object of all of the custom fonts cached.

## License

[MIT](LICENSE) © Nick Baugh

##

[lad-url]: https://lad.js.org

[nodemailer]: https://github.com/nodemailer/nodemailer

[nodemailer-base64-to-s3]: https://github.com/ladjs/nodemailer-base64-to-s3

[dafont]: http://www.dafont.com/

[font-squirrel]: https://www.fontsquirrel.com/

[font-awesome-assets]: https://github.com/ladjs/font-awesome-assets

[text-to-svg]: https://github.com/shrhdk/text-to-svg

[opentype.js]: https://github.com/nodebox/opentype.js

[os-fonts]: https://github.com/vutran/os-fonts

[fast-levenshtein]: https://github.com/hiddentao/fast-levenshtein

[goudybookletter1911]: https://github.com/theleagueof/goudy-bookletter-1911

[juice]: https://github.com/Automattic/juice

[sharp]: https://github.com/lovell/sharp

[trim]: http://sharp.dimens.io/en/stable/api/#trimtolerance

[pkg-up]: https://github.com/sindresorhus/pkg-up