Skip to content

Commit 293d373

Browse files
lojjicayuhito
andauthored
feat!: v2 woff files are now split by unicode-range subset (#116)
* feat: v2 woff files are now split by unicode-range subset * test: update fixtures * docs: update changelog --------- Co-authored-by: Lotus <declininglotus@gmail.com>
1 parent 18cbea4 commit 293d373

23 files changed

+22494
-276
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22

33
Google Font Metadata will log all notable changes within this file.
44

5+
# [5.0.0](https://github.com/fontsource/google-font-metadata/releases/tag/v5.0.0)
6+
7+
## BREAKING CHANGES
8+
9+
- APIv2 woff files are now split by unicode-range subset. [#116](https://github.com/fontsource/google-font-metadata/pull/116)
10+
511
# [4.2.1](https://github.com/fontsource/google-font-metadata/releases/tag/v4.2.1)
612

713
## Fixes

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ It exports [`data/google-fonts-v1.json`](https://github.com/fontsource/google-fo
7474

7575
## APIv2
7676

77-
Uses the Google Fonts CSS APIv2 and includes the unicode-range values for every subset. However, the API serves `woff/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` files are individually split per subset.
77+
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.
7878

7979
Exports [`data/google-fonts-v2.json`](https://github.com/fontsource/google-font-metadata/tree/main/data/google-fonts-v2.json).
8080

@@ -135,7 +135,7 @@ Note that fonts with large glyphsets such as the Japanese, Korean or Chinese lan
135135
"[0]": {
136136
"url": {
137137
"woff2": "https://fonts.gstatic.com/s/notosansjp/v42/-F6ofjtqLzI2JPCgQBnw7HFQoggPkENvl4B0ZLgOquiXidBa3qHiDcp2RQ.0.woff2",
138-
"woff": "https://fonts.gstatic.com/s/notosansjp/v42/-F6ofjtqLzI2JPCgQBnw7HFQoggJ.woff",
138+
"woff": "https://fonts.gstatic.com/s/notosansjp/v42/-F62fjtqLzI2JPCgQBnw7HFoxQII2lcnk-AFfrgQrvWXpdFg3KXxAMsKMbdN.0.woff",
139139
"opentype": "https://fonts.gstatic.com/s/notosansjp/v42/-F6ofjtqLzI2JPCgQBnw7HFQoggM.otf"
140140
}
141141
},

data/user-agents.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"apiv2": {
88
"variable": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36",
99
"woff2": "Mozilla/5.0 (Windows NT 6.3; rv:39.0) Gecko/20100101 Firefox/44.0",
10-
"woff": "Mozilla/4.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1667.0 Safari/537.36",
10+
"woff": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/11.1.2 Safari/605.1.15",
1111
"ttf": "Mozilla/5.0"
1212
}
1313
}

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "google-font-metadata",
33
"description": "A metadata generator for Google Fonts.",
4-
"version": "4.2.1",
4+
"version": "5.0.0",
55
"author": "Ayuhito <hello@ayuhito.com>",
66
"main": "./dist/index.js",
77
"module": "./dist/index.mjs",

src/api-parser-v2.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -194,9 +194,9 @@ export const processCSS = (
194194
] = path;
195195
}
196196

197-
// APIv2 uses one woff to support all subsets instead of splitting them
197+
// APIv2 splits woff/woff2 files by subset, but uses one combined file for other formats
198198
// These don't have a subset
199-
if (fontStyle && type === 'url' && format !== 'woff2') {
199+
if (fontStyle && type === 'url' && !format.startsWith('woff')) {
200200
const keys = Object.keys(
201201
fontObject[id].variants[fontWeight][fontStyle]
202202
);

tests/__snapshots__/api-parser-v2.test.ts.snap

Lines changed: 10878 additions & 0 deletions
Large diffs are not rendered by default.

tests/api-parser-v2.test.ts

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import * as data from '../src/data';
99
import APIResponse from './fixtures/api-response.json';
1010
import APIv2 from './fixtures/google-fonts-v2.json';
1111
import { apiParseV2Handlers, setupAPIServer } from './mocks/index';
12-
import { cssFixture, idGen } from './utils/helpers';
12+
import { cssFixture } from './utils/helpers';
1313

1414
vi.mock('node:fs/promises');
1515
vi.mock('../src/data');
@@ -43,20 +43,16 @@ describe('API Parser v2', () => {
4343

4444
describe('Process CSS', () => {
4545
it('Returns valid font object', async () => {
46-
const newAPIv2 = APIv2 as FontObjectV2; // Need to type assert as a more generic obj else we can't pick using id var
47-
4846
for (const font of APIResponse) {
49-
const id = idGen(font.family);
50-
const validFontObj = { [id]: newAPIv2[id] };
5147

5248
const css = await fetchAllCSS(font);
53-
expect(processCSS(css, font)).toMatchObject(validFontObj);
49+
expect(processCSS(css, font)).toMatchSnapshot();
5450
}
5551
});
5652
});
5753

5854
describe('Full parse and order', () => {
59-
vi.spyOn(data, 'APIv2', 'get').mockReturnValue(APIv2);
55+
vi.spyOn(data, 'APIv2', 'get').mockReturnValue(APIv2 as FontObjectV2);
6056
vi.spyOn(data, 'APIDirect', 'get').mockReturnValue(APIResponse);
6157

6258
it('Copies APIv2 as a cache since force flag is false', async () => {
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
/* latin */
12
@font-face {
23
font-family: 'Abel';
34
font-style: normal;
45
font-weight: 400;
5-
src: url(https://fonts.gstatic.com/s/abel/v18/MwQ5bhbm2POE6Vs.woff) format('woff');
6+
src: url(https://fonts.gstatic.com/s/abel/v18/MwQ5bhbm2POE2V9BO7h5uGM.woff) format('woff');
7+
unicode-range: 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;
68
}
Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,24 @@
1+
/* vietnamese */
12
@font-face {
23
font-family: 'Ballet';
34
font-style: normal;
45
font-weight: 400;
5-
src: url(https://fonts.gstatic.com/s/ballet/v21/QGYyz_MYZA-HM4NjuGOVnUEXme1I4Xi3C4I.woff) format('woff');
6+
src: url(https://fonts.gstatic.com/s/ballet/v21/QGYyz_MYZA-HM4NjuGOVnUEXme1I4Xi3O4m0FQItq6f9IRnL.woff) format('woff');
7+
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB;
8+
}
9+
/* latin-ext */
10+
@font-face {
11+
font-family: 'Ballet';
12+
font-style: normal;
13+
font-weight: 400;
14+
src: url(https://fonts.gstatic.com/s/ballet/v21/QGYyz_MYZA-HM4NjuGOVnUEXme1I4Xi3O4i0FQItq6f9IRnL.woff) format('woff');
15+
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
16+
}
17+
/* latin */
18+
@font-face {
19+
font-family: 'Ballet';
20+
font-style: normal;
21+
font-weight: 400;
22+
src: url(https://fonts.gstatic.com/s/ballet/v21/QGYyz_MYZA-HM4NjuGOVnUEXme1I4Xi3O4a0FQItq6f9IQ.woff) format('woff');
23+
unicode-range: 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;
624
}
Lines changed: 81 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,96 @@
1+
/* greek-ext */
12
@font-face {
23
font-family: 'Cardo';
34
font-style: italic;
45
font-weight: 400;
5-
src: url(https://fonts.gstatic.com/s/cardo/v19/wlpxgwjKBV1pqhv93Ic.woff) format('woff');
6+
src: url(https://fonts.gstatic.com/s/cardo/v19/wlpxgwjKBV1pqhv97I8x2kxNYChuCg.woff) format('woff');
7+
unicode-range: U+1F00-1FFF;
68
}
9+
/* greek */
10+
@font-face {
11+
font-family: 'Cardo';
12+
font-style: italic;
13+
font-weight: 400;
14+
src: url(https://fonts.gstatic.com/s/cardo/v19/wlpxgwjKBV1pqhv97IAx2kxNYChuCg.woff) format('woff');
15+
unicode-range: U+0370-03FF;
16+
}
17+
/* latin-ext */
18+
@font-face {
19+
font-family: 'Cardo';
20+
font-style: italic;
21+
font-weight: 400;
22+
src: url(https://fonts.gstatic.com/s/cardo/v19/wlpxgwjKBV1pqhv97I0x2kxNYChuCg.woff) format('woff');
23+
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
24+
}
25+
/* latin */
26+
@font-face {
27+
font-family: 'Cardo';
28+
font-style: italic;
29+
font-weight: 400;
30+
src: url(https://fonts.gstatic.com/s/cardo/v19/wlpxgwjKBV1pqhv97IMx2kxNYCg.woff) format('woff');
31+
unicode-range: 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;
32+
}
33+
/* greek-ext */
734
@font-face {
835
font-family: 'Cardo';
936
font-style: normal;
1037
font-weight: 400;
11-
src: url(https://fonts.gstatic.com/s/cardo/v19/wlp_gwjKBV1pqiv8.woff) format('woff');
38+
src: url(https://fonts.gstatic.com/s/cardo/v19/wlp_gwjKBV1pqhv03Ic7225PUCk.woff) format('woff');
39+
unicode-range: U+1F00-1FFF;
40+
}
41+
/* greek */
42+
@font-face {
43+
font-family: 'Cardo';
44+
font-style: normal;
45+
font-weight: 400;
46+
src: url(https://fonts.gstatic.com/s/cardo/v19/wlp_gwjKBV1pqhv73Ic7225PUCk.woff) format('woff');
47+
unicode-range: U+0370-03FF;
48+
}
49+
/* latin-ext */
50+
@font-face {
51+
font-family: 'Cardo';
52+
font-style: normal;
53+
font-weight: 400;
54+
src: url(https://fonts.gstatic.com/s/cardo/v19/wlp_gwjKBV1pqhv23Ic7225PUCk.woff) format('woff');
55+
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
56+
}
57+
/* latin */
58+
@font-face {
59+
font-family: 'Cardo';
60+
font-style: normal;
61+
font-weight: 400;
62+
src: url(https://fonts.gstatic.com/s/cardo/v19/wlp_gwjKBV1pqhv43Ic7225P.woff) format('woff');
63+
unicode-range: 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;
64+
}
65+
/* greek-ext */
66+
@font-face {
67+
font-family: 'Cardo';
68+
font-style: normal;
69+
font-weight: 700;
70+
src: url(https://fonts.gstatic.com/s/cardo/v19/wlpygwjKBV1pqhND-ZQa-WVlaiBWM_I.woff) format('woff');
71+
unicode-range: U+1F00-1FFF;
72+
}
73+
/* greek */
74+
@font-face {
75+
font-family: 'Cardo';
76+
font-style: normal;
77+
font-weight: 700;
78+
src: url(https://fonts.gstatic.com/s/cardo/v19/wlpygwjKBV1pqhND-ZQV-WVlaiBWM_I.woff) format('woff');
79+
unicode-range: U+0370-03FF;
80+
}
81+
/* latin-ext */
82+
@font-face {
83+
font-family: 'Cardo';
84+
font-style: normal;
85+
font-weight: 700;
86+
src: url(https://fonts.gstatic.com/s/cardo/v19/wlpygwjKBV1pqhND-ZQY-WVlaiBWM_I.woff) format('woff');
87+
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
1288
}
89+
/* latin */
1390
@font-face {
1491
font-family: 'Cardo';
1592
font-style: normal;
1693
font-weight: 700;
17-
src: url(https://fonts.gstatic.com/s/cardo/v19/wlpygwjKBV1pqhND-aQS.woff) format('woff');
94+
src: url(https://fonts.gstatic.com/s/cardo/v19/wlpygwjKBV1pqhND-ZQW-WVlaiBW.woff) format('woff');
95+
unicode-range: 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;
1896
}

0 commit comments

Comments
 (0)