Skip to content
This repository was archived by the owner on May 17, 2019. It is now read-only.

Commit e50ea98

Browse files
authored
Push initial commit (#1)
* initial commit * address feedback * rename to fusion-plugin-font-loader-react * use familar custom font name in tests
1 parent 0253c2f commit e50ea98

26 files changed

+5890
-0
lines changed

.buildkite/browserTests

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#!/usr/bin/env bash
2+
export DISPLAY=:99.0
3+
/etc/init.d/xvfb start
4+
5+
./node_modules/.bin/nyc --instrument=false --exclude-after-remap=false --reporter=text --reporter=json ./node_modules/.bin/unitest --browser=dist-tests/browser.js
6+
bash <(curl -s https://codecov.io/bash) -f coverage/coverage-final.json -n browser

.buildkite/nodeTests

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/usr/bin/env bash
2+
./node_modules/.bin/nyc --instrument=false --exclude-after-remap=false --reporter=text --reporter=json node dist-tests/node.js
3+
bash <(curl -s https://codecov.io/bash) -f coverage/coverage-final.json -n node

.buildkite/pipeline.yml

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
steps:
2+
- name: ':docker: :package:'
3+
plugins:
4+
'docker-compose#v1.7.0':
5+
build: fusion-plugin-font-loader-react
6+
image-repository: 296822479253.dkr.ecr.us-east-2.amazonaws.com/fusionjs
7+
- wait
8+
- command: yarn flow
9+
name: ':flowtype:'
10+
plugins:
11+
'docker-compose#v1.7.0':
12+
run: fusion-plugin-font-loader-react
13+
- name: ':eslint:'
14+
command: yarn lint
15+
plugins:
16+
'docker-compose#v1.7.0':
17+
run: fusion-plugin-font-loader-react
18+
- name: ':chrome: :white_check_mark:'
19+
command: .buildkite/browserTests
20+
plugins:
21+
'docker-compose#v1.7.0':
22+
run: fusion-plugin-font-loader-react
23+
- name: ':node: :white_check_mark:'
24+
command: .buildkite/nodeTests
25+
plugins:
26+
'docker-compose#v1.7.0':
27+
run: fusion-plugin-font-loader-react

.buildkite/xvfb_daemon_run

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#!/bin/bash
2+
export DISPLAY=:99
3+
/etc/init.d/xvfb start
4+
sleep 1
5+
$@
6+
exit_value=$?
7+
/etc/init.d/xvfb stop
8+
exit $exit_value

.buildkite/xvfb_init

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
XVFB=/usr/bin/Xvfb
2+
XVFBARGS="$DISPLAY -ac -screen 0 1024x768x16 +extension RANDR"
3+
PIDFILE=/var/xvfb_${DISPLAY:1}.pid
4+
case "$1" in
5+
start)
6+
echo -n "Starting virtual X frame buffer: Xvfb"
7+
/sbin/start-stop-daemon --start --quiet --pidfile $PIDFILE --make-pidfile --background --exec $XVFB -- $XVFBARGS
8+
echo "."
9+
;;
10+
stop)
11+
echo -n "Stopping virtual X frame buffer: Xvfb"
12+
/sbin/start-stop-daemon --stop --quiet --pidfile $PIDFILE
13+
echo "."
14+
;;
15+
restart)
16+
$0 stop
17+
$0 start
18+
;;
19+
*)
20+
echo "Usage: /etc/init.d/xvfb {start|stop|restart}"
21+
exit 1
22+
esac
23+
exit 0

.cuprc.js

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
module.exports = {
2+
babel: {
3+
presets: [
4+
require.resolve('@babel/preset-react'),
5+
],
6+
}
7+
};

.eslintrc.js

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module.exports = {
2+
extends: [require.resolve('eslint-config-fusion')],
3+
};

.flowconfig

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
[ignore]
2+
.*/node_modules/.*[^(package)]\.json$
3+
4+
[include]
5+
./src/
6+
7+
[libs]
8+
9+
[lints]
10+
11+
[options]
12+
suppress_comment= \\(.\\|\n\\)*\\$FlowIgnore
13+
14+
[strict]

.gitignore

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
node_modules/
2+
dist/
3+
dist-tests/
4+
coverage/
5+
.nyc_output/
6+
.vscode
7+
8+
.DS_Store
9+
npm-debug.log
10+
yarn-error.log

Dockerfile

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
FROM node:8.9.0
2+
3+
WORKDIR /fusion-plugin-font-loader-react
4+
5+
# Install electron dependencies.
6+
ENV DISPLAY :99
7+
ADD .buildkite/xvfb_init /etc/init.d/xvfb
8+
ADD .buildkite/xvfb_daemon_run /usr/bin/xvfb-daemon-run
9+
10+
RUN dpkg --add-architecture i386
11+
RUN apt-get update
12+
RUN apt-get -y install libgtk2.0-dev libx11-xcb-dev libgtkextra-dev libgconf2-dev libnss3 libasound2 libxtst-dev libxss1 xvfb && \
13+
chmod a+x /etc/init.d/xvfb /usr/bin/xvfb-daemon-run
14+
15+
COPY . .
16+
17+
RUN yarn
18+
19+
RUN yarn build-test

LICENSE

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2017 Uber Technologies, Inc.
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

+126
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
# fusion-plugin-font-loader-react
2+
3+
Provides :
4+
1. A fusion plugin that generates @font-faces and preloads fallback fonts based on app-level font configuration.
5+
2. A Higher Order Component for loading custom web fonts (and associated utils). During font loading, this HOC temporarily swaps the element to a well-matched fallback font, avoiding FOIT and FOUT. See https://www.zachleat.com/web/comprehensive-webfonts/#critical-foft-preload for more on this.
6+
7+
## Installation
8+
9+
```
10+
yarn add fusion-plugin-font-loading
11+
```
12+
13+
## Usage
14+
15+
### Configuration
16+
Consuming apps should define a `font-config.js` which a) provides data for @font-face generation, b) is used to derive the fallback font and styles that will be used by the `with-font-loading.js` HOC.
17+
18+
_Sample \<app\>/src/font-config.js file_
19+
```js
20+
import {assetUrl} from 'fusion-core';
21+
export const preloadDepth = 1;
22+
export const fonts = {
23+
'Lato-Regular': {
24+
urls: {
25+
woff2: assetUrl('../static/Lato-Regular.woff2'),
26+
},
27+
fallback: {
28+
name: 'Helvetica',
29+
},
30+
},
31+
'Lato-Bold': {
32+
urls: {
33+
woff2: assetUrl('../static/Lato-Bold.woff2'),
34+
},
35+
fallback: {
36+
name: 'Lato-Regular',
37+
styles: {
38+
'font-weight': 'bold',
39+
},
40+
},
41+
},
42+
'Lato-Thin': {
43+
urls: {
44+
woff2: assetUrl('./static/Lato-Thin.woff2'),
45+
},
46+
fallback: {
47+
name: 'Lato-Regular',
48+
styles: {
49+
'font-weight': '100',
50+
},
51+
},
52+
},
53+
};
54+
```
55+
56+
#### @font-face generation
57+
58+
Based on the example configuration file above the following @font-face would be generated in <head>
59+
60+
```css
61+
@font-face {font-family: "Lato-Regular"; src: url("/_static/ca614426b50ca7d007056aa00954764b.woff2") format("woff2");}
62+
@font-face {font-family: "Lato-Bold"; src: url("/_static/ca104da8af9a2e0771e8fe2b31f8ec1e.woff2") format("woff2");}
63+
@font-face {font-family: "Lato-Thin"; src: url("/_static/03b64805a8cd2d53fadc5814445c2fb5.woff2") format("woff2");}
64+
```
65+
66+
#### font loading
67+
68+
1. An in-memory font fallback tree is generated at runtime based on the defintitions provided in `font-config.js`
69+
2. Fallbacks at and above the specified `preloadDepth` will be preloaded/prefetched on page load
70+
3. Remaining fonts will lazily loaded.
71+
72+
Based on the sample config above (`preloadDepth` is set to 1), the HOC example above would yield the following values for `prop.fontStyles`:
73+
74+
while loading font:
75+
```js
76+
{
77+
fontFamily: 'Lato-Regular'
78+
fontWeight: 'bold'
79+
}
80+
```
81+
82+
when font is loaded:
83+
```js
84+
{
85+
fontFamily: 'Lato-Bold'
86+
}
87+
```
88+
89+
If `preloadDepth` were 0 then every font would be preloaded, and there would be no fallback fonts
90+
91+
If `preloadDepth` were 2 then the only fallback font would be Helvetica, and since Helvetica is a system font, no custom fonts would be preloaded.
92+
93+
### Higher Order Component
94+
95+
This repo also supplies a `with-font-loading.js` Higher Order Component which is used to:
96+
1. Load a specified font
97+
2. Temporarily assign a fallback font and styles to the wrapped component via `props.fontStyles`
98+
3. When the font is loaded assign the true font to child component via `props.fontStyles`
99+
100+
```js
101+
const FancyLink1 = withFontLoading('Lato-Bold'.(
102+
styled('a', props => ({
103+
':hover': {fontSize: `${props.answer}px`}.
104+
...props.fontStyles,
105+
}))
106+
);
107+
```
108+
109+
This will lazy-load `Lato-Bold` and meanwhile assign a fallback font and styling to the element via `props.fontStyles`.
110+
111+
## Utils
112+
113+
### font-loader.js
114+
115+
Promise used by `with-font-loading.js` HOC to dynamically load specified font; calls `resolve` when load is complete.
116+
117+
Uses `document.fonts.load` where available (chrome and firefox as of 10/17), otherwise uses a polyfill.
118+
119+
120+
121+
122+
123+
124+
125+
126+

docker-compose.yml

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
version: '2'
2+
services:
3+
fusion-plugin-font-loader-react:
4+
build: .
5+
volumes:
6+
- '.:/fusion-plugin-font-loader-react'
7+
- /fusion-plugin-font-loader-react/node_modules/
8+
- /fusion-plugin-font-loader-react/dist/
9+
- /fusion-plugin-font-loader-react/dist-tests/
10+
environment:
11+
- CODECOV_TOKEN
12+
- CI=true
13+
- BUILDKITE
14+
- BUILDKITE_BRANCH
15+
- BUILDKITE_BUILD_NUMBER
16+
- BUILDKITE_JOB_ID
17+
- BUILDKITE_BUILD_URL
18+
- BUILDKITE_PROJECT_SLUG
19+
- BUILDKITE_COMMIT

package.json

+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
{
2+
"name": "fusion-plugin-font-loader-react",
3+
"version": "0.1.0",
4+
"description": "The Fusion plugin for declaring and optimizing the loading of cutsom fonts",
5+
"license": "MIT",
6+
"repository": "fusionjs/fusion-plugin-font-loading",
7+
"files": [
8+
"dist"
9+
],
10+
"main": "./dist/node.cjs.js",
11+
"module": "./dist/node.es.js",
12+
"browser": {
13+
"./dist/node.cjs.js": "./dist/browser.es5.cjs.js",
14+
"./dist/node.es.js": "./dist/browser.es5.es.js"
15+
},
16+
"es2015": {
17+
"./dist/browser.es5.cjs.js": "./dist/browser.es2015.cjs.js",
18+
"./dist/browser.es5.es.js": "./dist/browser.es2015.es.js"
19+
},
20+
"es2017": {
21+
"./dist/browser.es5.cjs.js": "./dist/browser.es2017.cjs.js",
22+
"./dist/browser.es5.es.js": "./dist/browser.es2017.es.js",
23+
"./dist/browser.es2015.cjs.js": "./dist/browser.es2017.cjs.js",
24+
"./dist/browser.es2015.es.js": "./dist/browser.es2017.es.js"
25+
},
26+
"dependencies": {},
27+
"devDependencies": {
28+
"@babel/preset-react": "^7.0.0-beta.32",
29+
"babel-eslint": "^8.0.2",
30+
"create-universal-package": "^2.1.1",
31+
"enzyme": "^3.1.1",
32+
"enzyme-adapter-react-16": "^1.0.4",
33+
"eslint": "^4.11.0",
34+
"eslint-config-fusion": "^0.1.2",
35+
"eslint-plugin-cup": "^1.0.0",
36+
"eslint-plugin-flowtype": "^2.39.1",
37+
"eslint-plugin-prettier": "^2.3.1",
38+
"eslint-plugin-react": "^7.4.0",
39+
"flow-bin": "^0.59.0",
40+
"fusion-core": "^0.2.3",
41+
"nyc": "^11.3.0",
42+
"prettier": "1.8.2",
43+
"react": "^16.1.1",
44+
"react-dom": "^16.1.1",
45+
"tape-cup": "^4.7.1",
46+
"unitest": "^1.1.0"
47+
},
48+
"peerDependencies": {
49+
"fusion-core": "^0.2.3",
50+
"react": "14.x - 16.x"
51+
},
52+
"scripts": {
53+
"clean": "rm -rf dist",
54+
"lint": "eslint . --ignore-path .gitignore",
55+
"transpile": "npm run clean && cup build",
56+
"build-test": "rm -rf dist-tests && cup build-tests",
57+
"just-test": "node_modules/.bin/unitest --browser=dist-tests/browser.js && node dist-tests/node.js",
58+
"test": "npm run build-test && npm run just-test",
59+
"prepublish": "npm run transpile"
60+
},
61+
"engines": {
62+
"node": ">= 8.9.0"
63+
}
64+
}

src/__tests__/fixtures/expected.js

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
export const fallbackLookup = {
2+
depth0: {},
3+
depth1: {
4+
'Lato-Bold': {
5+
name: 'Lato-Regular',
6+
styles: {'font-weight': 'bold'},
7+
},
8+
'Lato-Thin': {
9+
name: 'Lato-Regular',
10+
styles: {'font-weight': '100'},
11+
},
12+
},
13+
depth2: {
14+
'Lato-Regular': {
15+
name: 'Helvetica',
16+
},
17+
'Lato-Bold': {
18+
name: 'Helvetica',
19+
},
20+
'Lato-Thin': {
21+
name: 'Helvetica',
22+
},
23+
},
24+
};
25+
26+
export const fontFaces =
27+
'\n@font-face {font-family: "Lato-Regular"; src: url("/_static/Lato-Regular.woff") format("woff")\n,url("/_static/Lato-Regular.woff2") format("woff2")\n;}\n@font-face {font-family: "Lato-Bold"; src: url("/_static/Lato-Bold.woff") format("woff")\n,url("/_static/Lato-Bold.woff2") format("woff2")\n;}\n@font-face {font-family: "Lato-Thin"; src: url("/_static/Lato-Thin.woff") format("woff")\n,url("/_static/Lato-Thin.woff2") format("woff2")\n;}';
28+
29+
export const preloadLinks =
30+
'\n<link rel="font" href="/_static/Lato-Regular.woff2" as="font" type="font/woff2" crossorigin>';

0 commit comments

Comments
 (0)