Skip to content

Commit 8643505

Browse files
JungzlzyyvCopilot
authored
fix(preset-web-fonts): support width axis and single axis config for google provider (#4878)
Co-authored-by: Chris <[email protected]> Co-authored-by: Copilot <[email protected]>
1 parent 4800597 commit 8643505

File tree

5 files changed

+57
-40
lines changed

5 files changed

+57
-40
lines changed

packages-presets/preset-web-fonts/src/preset.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ export function normalizedFontMeta(meta: WebFontMeta | string, defaultProvider:
2828
meta.provider = resolveProvider(meta.provider || defaultProvider)
2929
if (meta.weights)
3030
meta.weights = [...new Set(meta.weights.sort((a, b) => a.toString().localeCompare(b.toString(), 'en', { numeric: true })))]
31+
if (meta.widths)
32+
meta.widths = [...new Set(meta.widths.sort((a, b) => a.toString().localeCompare(b.toString(), 'en', { numeric: true })))]
3133
return meta as ResolvedWebFontMeta
3234
}
3335

Lines changed: 4 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,5 @@
1-
import type { Provider, WebFontsProviders } from '../types'
1+
import type { Provider } from '../types'
2+
import { createGoogleCompatibleProvider } from './google'
23

3-
export function createCoolLabsCompatibleProvider(name: WebFontsProviders, host: string): Provider {
4-
return {
5-
name,
6-
getImportUrl(fonts) {
7-
const sort = (weights: string[][]) => {
8-
const firstW = weights.map(w => w[0])
9-
const lastW = weights.map(w => w[1])
10-
return `${firstW.join(';')};${lastW.join(';')}`
11-
}
12-
13-
const strings = fonts
14-
.map((i) => {
15-
let name = i.name.replace(/\s+/g, '+')
16-
if (i.weights?.length) {
17-
name += i.italic
18-
? `:ital,wght@${sort(i.weights.map(w => [`0,${w}`, `1,${w}`]))}`
19-
: `:wght@${i.weights.join(';')}`
20-
}
21-
return `family=${name}`
22-
})
23-
.join('&')
24-
return `${host}/css2?${strings}&display=swap`
25-
},
26-
}
27-
}
28-
29-
export const CoolLabsFontsProvider: Provider = createCoolLabsCompatibleProvider('coollabs', 'https://api.fonts.coollabs.io')
4+
// https://fonts.coollabs.io/
5+
export const CoolLabsFontsProvider: Provider = createGoogleCompatibleProvider('coollabs', 'https://api.fonts.coollabs.io')

packages-presets/preset-web-fonts/src/providers/google.ts

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,54 @@
11
import type { Provider, WebFontsProviders } from '../types'
22

3+
export interface FontAxis {
4+
axis: string
5+
values: string[]
6+
}
7+
8+
export function generateFontAxes(axes: FontAxis[]): string {
9+
if (!axes || axes.length === 0)
10+
return ''
11+
12+
let combinations: string[][] = [[]]
13+
for (const { values } of axes) {
14+
const newCombinations: string[][] = []
15+
for (const combo of combinations) {
16+
for (const value of values) {
17+
newCombinations.push([...combo, value])
18+
}
19+
}
20+
combinations = newCombinations
21+
}
22+
return combinations.map(arr => arr.join(',')).join(';')
23+
}
24+
325
export function createGoogleCompatibleProvider(name: WebFontsProviders, host: string): Provider {
426
return {
527
name,
628
getImportUrl(fonts) {
7-
const sort = (weights: string[][]) => {
8-
const firstW = weights.map(w => w[0])
9-
const lastW = weights.map(w => w[1])
10-
return `${firstW.join(';')};${lastW.join(';')}`
11-
}
12-
1329
const strings = fonts
1430
.map((i) => {
1531
let name = i.name.replace(/\s+/g, '+')
16-
if (i.weights?.length) {
17-
name += i.italic
18-
? `:ital,wght@${sort(i.weights.map(w => [`0,${w}`, `1,${w}`]))}`
19-
: `:wght@${i.weights.join(';')}`
32+
/**
33+
* When using the Google Fonts API, be sure to list them alphabetically.
34+
* @see https://fonts.google.com/knowledge/using_type/styling_type_on_the_web_with_variable_fonts
35+
* @example ital, opsz, slnt, wdth, wght
36+
*/
37+
const axisValues: FontAxis[] = []
38+
if (i.italic)
39+
axisValues.push({ axis: 'ital', values: ['0', '1'] })
40+
41+
if (i.widths?.length)
42+
axisValues.push({ axis: 'wdth', values: i.widths.map(w => w.toString()) })
43+
44+
if (i.weights?.length)
45+
axisValues.push({ axis: 'wght', values: i.weights.map(w => w.toString()) })
46+
47+
if (axisValues.length) {
48+
name += ':'
49+
name += axisValues.map(a => a.axis).join(',')
50+
name += '@'
51+
name += generateFontAxes(axisValues)
2052
}
2153
return `family=${name}`
2254
})

packages-presets/preset-web-fonts/src/types.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@ export interface WebFontMeta {
2020
*/
2121
italic?: boolean // ital axis
2222

23+
/**
24+
* Font width(s) to include, and respect the width order
25+
* @example [62.5, 125]
26+
*/
27+
widths?: (string | number)[] // wdth axis
28+
2329
/**
2430
* Variable font settings
2531
* @example

test/preset-web-fonts.test.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ it('web-fonts (inline: true)', async () => {
6464
expect(css).toContain('@font-face')
6565
})
6666

67-
it('web-fonts weight sort', async () => {
67+
it('web-fonts width & weight sort', async () => {
6868
const uno = await createGenerator({
6969
presets: [
7070
presetMini({ preflight: false }),
@@ -76,6 +76,7 @@ it('web-fonts weight sort', async () => {
7676
{
7777
name: 'Lato',
7878
weights: ['1000', '200'],
79+
widths: ['125', '62.5'],
7980
italic: true,
8081
},
8182
],
@@ -87,7 +88,7 @@ it('web-fonts weight sort', async () => {
8788

8889
const { css } = await uno.generate(classes)
8990
const importUrl = css.match(/@import url\('(.*)'\)/)![1]
90-
expect(importUrl).toMatchInlineSnapshot('"https://fonts.googleapis.com/css2?family=Fira+Mono:wght@200;1000&family=Lato:ital,wght@0,200;0,1000;1,200;1,1000&display=swap"')
91+
expect(importUrl).toMatchInlineSnapshot(`"https://fonts.googleapis.com/css2?family=Fira+Mono:wght@200;1000&family=Lato:ital,wdth,wght@0,62.5,200;0,62.5,1000;0,125,200;0,125,1000;1,62.5,200;1,62.5,1000;1,125,200;1,125,1000&display=swap"`)
9192
})
9293

9394
it('web-fonts weight deduplicate', async () => {

0 commit comments

Comments
 (0)