Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(preset-web-fonts): fix creation of import URL for bunny #2766

Merged
merged 5 commits into from Jun 26, 2023
Merged

fix(preset-web-fonts): fix creation of import URL for bunny #2766

merged 5 commits into from Jun 26, 2023

Conversation

arunanshub
Copy link
Contributor

Fixes the issue #2574.

@arunanshub arunanshub requested a review from antfu as a code owner June 15, 2023 12:57
@netlify
Copy link

netlify bot commented Jun 15, 2023

Deploy Preview for unocss ready!

Built without sensitive environment variables

Name Link
🔨 Latest commit f90c314
🔍 Latest deploy log https://app.netlify.com/sites/unocss/deploys/648f11e96e44a70008b2f8e3
😎 Deploy Preview https://deploy-preview-2766--unocss.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site settings.

@arunanshub arunanshub changed the title Fix creation of import URL for Bunny fonts fix(preset-web-fonts/bunny): fix creation of import URL Jun 15, 2023
@antfu
Copy link
Member

antfu commented Jun 15, 2023

Can you explain what is happening and why this fix would need? I guess it should be bunny's responsibility to align with Google's params?

@arunanshub
Copy link
Contributor Author

arunanshub commented Jun 15, 2023

Can you explain what is happening and why this fix would need?

@antfu As highlighted in the linked issue, it simply fixes how the import URL is created. Earlier, it used to create the URL in a Google Fonts compatible manner. However, it seems like Bunny has a new way of specifying how fonts are loaded.

I guess it should be bunny's responsibility to align with Google's params?

It does work with Google's params when executed in a browser, but strangely refuses to work with UnoCSS when configured via webFonts.provider. It might also be related to caching:

const importCache: Record<string, Promise<string>> = {}
async function importUrl(url: string) {
if (inlineImports) {
if (!importCache[url]) {
const userAgentWoff2 = 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36'
const promise = customFetch
? customFetch(url)
: (await import('ofetch')).$fetch(url, { headers: { 'User-Agent': userAgentWoff2 }, retry: 3 })
importCache[url] = promise.catch((e) => {
console.error('Failed to fetch web fonts')
console.error(e)
if (typeof process !== 'undefined' && process.env.CI)
throw e
})
}
return await importCache[url]

However I have yet to test out this hypothesis.

This is not an issue with UnoCSS' caching.

The important point here is that it only fails with Bunny, not Google. Hence if both are equally compatible with each other, and Google's loader works but Bunny's loader fails, it can be safely said there is something wrong with Bunny's loader.

Investigation

I've decided to fetch the import URLs manually to see if it is an issue with the URLs itself. I'll use Tor browser to perform the tests.

Using Google Fonts compatible URL with Bunny

Here, I use the following import URL:

https://fonts.bunny.net/css2?family=Audiowide&family=Anton&display=swap
Details
/* latin */
@font-face {
  font-family: 'Audiowide';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(https://fonts.bunny.net/audiowide/files/audiowide-latin-400-normal.woff2) format('woff2'), url(https://fonts.bunny.net/audiowide/files/audiowide-latin-400-normal.woff) format('woff'); 
  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;
}

/* latin-ext */
@font-face {
font-family: 'Audiowide';
font-style: normal;
font-weight: 400;
font-display: swap;
src: url(https://fonts.bunny.net/audiowide/files/audiowide-latin-ext-400-normal.woff2) format('woff2'), url(https://fonts.bunny.net/audiowide/files/audiowide-latin-ext-400-normal.woff) format('woff');
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;
}

/* latin */
@font-face {
font-family: 'Anton';
font-style: normal;
font-weight: 400;
font-display: swap;
src: url(https://fonts.bunny.net/anton/files/anton-latin-400-normal.woff2) format('woff2'), url(https://fonts.bunny.net/anton/files/anton-latin-400-normal.woff) format('woff');
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;
}

/* latin-ext */
@font-face {
font-family: 'Anton';
font-style: normal;
font-weight: 400;
font-display: swap;
src: url(https://fonts.bunny.net/anton/files/anton-latin-ext-400-normal.woff2) format('woff2'), url(https://fonts.bunny.net/anton/files/anton-latin-ext-400-normal.woff) format('woff');
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;
}

/* vietnamese */
@font-face {
font-family: 'Anton';
font-style: normal;
font-weight: 400;
font-display: swap;
src: url(https://fonts.bunny.net/anton/files/anton-vietnamese-400-normal.woff2) format('woff2'), url(https://fonts.bunny.net/anton/files/anton-vietnamese-400-normal.woff) format('woff');
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;
}

However, if we modify the URL such that a different font is used:

https://fonts.bunny.net/css2?family=Audiowide&family=Roboto&display=swap

Here, we swap Anton with Roboto and fetch again on a new tab of Tor Browser:

Details
/* latin */
@font-face {
  font-family: 'Audiowide';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(https://fonts.bunny.net/audiowide/files/audiowide-latin-400-normal.woff2) format('woff2'), url(https://fonts.bunny.net/audiowide/files/audiowide-latin-400-normal.woff) format('woff'); 
  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;
}

/* latin-ext */
@font-face {
font-family: 'Audiowide';
font-style: normal;
font-weight: 400;
font-display: swap;
src: url(https://fonts.bunny.net/audiowide/files/audiowide-latin-ext-400-normal.woff2) format('woff2'), url(https://fonts.bunny.net/audiowide/files/audiowide-latin-ext-400-normal.woff) format('woff');
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;
}

/* latin */
@font-face {
font-family: 'Anton';
font-style: normal;
font-weight: 400;
font-display: swap;
src: url(https://fonts.bunny.net/anton/files/anton-latin-400-normal.woff2) format('woff2'), url(https://fonts.bunny.net/anton/files/anton-latin-400-normal.woff) format('woff');
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;
}

/* latin-ext */
@font-face {
font-family: 'Anton';
font-style: normal;
font-weight: 400;
font-display: swap;
src: url(https://fonts.bunny.net/anton/files/anton-latin-ext-400-normal.woff2) format('woff2'), url(https://fonts.bunny.net/anton/files/anton-latin-ext-400-normal.woff) format('woff');
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;
}

/* vietnamese */
@font-face {
font-family: 'Anton';
font-style: normal;
font-weight: 400;
font-display: swap;
src: url(https://fonts.bunny.net/anton/files/anton-vietnamese-400-normal.woff2) format('woff2'), url(https://fonts.bunny.net/anton/files/anton-vietnamese-400-normal.woff) format('woff');
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;
}

We can see that Bunny Fonts is somehow caching the calls.

Using Bunny's import URL format

https://fonts.bunny.net/css?family=audiowide|anton
Details
/* latin */
@font-face {
  font-family: 'Audiowide';
  font-style: normal;
  font-weight: 400;
  src: url(https://fonts.bunny.net/audiowide/files/audiowide-latin-400-normal.woff2) format('woff2'), url(https://fonts.bunny.net/audiowide/files/audiowide-latin-400-normal.woff) format('woff'); 
  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;
}

/* latin-ext */
@font-face {
font-family: 'Audiowide';
font-style: normal;
font-weight: 400;
src: url(https://fonts.bunny.net/audiowide/files/audiowide-latin-ext-400-normal.woff2) format('woff2'), url(https://fonts.bunny.net/audiowide/files/audiowide-latin-ext-400-normal.woff) format('woff');
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;
}

/* latin */
@font-face {
font-family: 'Anton';
font-style: normal;
font-weight: 400;
src: url(https://fonts.bunny.net/anton/files/anton-latin-400-normal.woff2) format('woff2'), url(https://fonts.bunny.net/anton/files/anton-latin-400-normal.woff) format('woff');
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;
}

/* latin-ext */
@font-face {
font-family: 'Anton';
font-style: normal;
font-weight: 400;
src: url(https://fonts.bunny.net/anton/files/anton-latin-ext-400-normal.woff2) format('woff2'), url(https://fonts.bunny.net/anton/files/anton-latin-ext-400-normal.woff) format('woff');
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;
}

/* vietnamese */
@font-face {
font-family: 'Anton';
font-style: normal;
font-weight: 400;
src: url(https://fonts.bunny.net/anton/files/anton-vietnamese-400-normal.woff2) format('woff2'), url(https://fonts.bunny.net/anton/files/anton-vietnamese-400-normal.woff) format('woff');
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;
}

We now swap anton with roboto

https://fonts.bunny.net/css?family=audiowide|roboto
Details
/* latin */
@font-face {
  font-family: 'Audiowide';
  font-style: normal;
  font-weight: 400;
  src: url(https://fonts.bunny.net/audiowide/files/audiowide-latin-400-normal.woff2) format('woff2'), url(https://fonts.bunny.net/audiowide/files/audiowide-latin-400-normal.woff) format('woff'); 
  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;
}

/* latin-ext */
@font-face {
font-family: 'Audiowide';
font-style: normal;
font-weight: 400;
src: url(https://fonts.bunny.net/audiowide/files/audiowide-latin-ext-400-normal.woff2) format('woff2'), url(https://fonts.bunny.net/audiowide/files/audiowide-latin-ext-400-normal.woff) format('woff');
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;
}

/* cyrillic */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 400;
src: url(https://fonts.bunny.net/roboto/files/roboto-cyrillic-400-normal.woff2) format('woff2'), url(https://fonts.bunny.net/roboto/files/roboto-cyrillic-400-normal.woff) format('woff');
unicode-range: U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116;
}

/* cyrillic-ext */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 400;
src: url(https://fonts.bunny.net/roboto/files/roboto-cyrillic-ext-400-normal.woff2) format('woff2'), url(https://fonts.bunny.net/roboto/files/roboto-cyrillic-ext-400-normal.woff) format('woff');
unicode-range: U+0460-052F,U+1C80-1C88,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F;
}

/* greek */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 400;
src: url(https://fonts.bunny.net/roboto/files/roboto-greek-400-normal.woff2) format('woff2'), url(https://fonts.bunny.net/roboto/files/roboto-greek-400-normal.woff) format('woff');
unicode-range: U+0370-03FF;
}

/* greek-ext */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 400;
src: url(https://fonts.bunny.net/roboto/files/roboto-greek-ext-400-normal.woff2) format('woff2'), url(https://fonts.bunny.net/roboto/files/roboto-greek-ext-400-normal.woff) format('woff');
unicode-range: U+1F00-1FFF;
}

/* latin */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 400;
src: url(https://fonts.bunny.net/roboto/files/roboto-latin-400-normal.woff2) format('woff2'), url(https://fonts.bunny.net/roboto/files/roboto-latin-400-normal.woff) format('woff');
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;
}

/* latin-ext */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 400;
src: url(https://fonts.bunny.net/roboto/files/roboto-latin-ext-400-normal.woff2) format('woff2'), url(https://fonts.bunny.net/roboto/files/roboto-latin-ext-400-normal.woff) format('woff');
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;
}

/* vietnamese */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 400;
src: url(https://fonts.bunny.net/roboto/files/roboto-vietnamese-400-normal.woff2) format('woff2'), url(https://fonts.bunny.net/roboto/files/roboto-vietnamese-400-normal.woff) format('woff');
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;
}

We can see that it's working the way it should.

If the weights argument is null or an empty array, we skip the iteration and apply the italic variant if flag is set.
@zyyv zyyv changed the title fix(preset-web-fonts/bunny): fix creation of import URL fix(preset-web-fonts): fix creation of import URL for bunny Jun 18, 2023
@antfu
Copy link
Member

antfu commented Jun 22, 2023

It does sound like a bunny issue isn't it? I am still not very sure if we should keep the complexity on us.

@arunanshub
Copy link
Contributor Author

arunanshub commented Jun 23, 2023

It does sound like a bunny issue isn't it? I am still not very sure if we should keep the complexity on us.

While the issue indeed lies with Bunny fonts trying to be compatible with Google, it is essential to note that the proposed fix is relatively straightforward and can be implemented within approximately 10 lines of code.

Plus, we should see Bunny as a separate font provider service and a privacy-respecting competitor to Google Fonts.

@antfu antfu merged commit 3c28607 into unocss:main Jun 26, 2023
5 checks passed
@zyyv zyyv linked an issue Jul 9, 2023 that may be closed by this pull request
4 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

presetWebFonts/bunny provider unreliable
2 participants