html-to-image icon indicating copy to clipboard operation
html-to-image copied to clipboard

Load specified fonts only instead of loading hundreds of fonts

Open myszkin81 opened this issue 2 years ago • 7 comments

Current state

html-to-image now calls for about 150 fonts on the first call, ten some more for ther second call. I only need 2 fonts to be downloaded.

Expected Behavior

I would like to specify the fonts I need and not to download any more fonts.

Possible Solution

Defining needed fonts in font.config file

myszkin81 avatar May 23 '23 13:05 myszkin81

👋 @myszkin81

Thanks for opening your first issue here! If you're reporting a 🐞 bug, please make sure you include steps to reproduce it. To help make it easier for us to investigate your issue, please follow the contributing guidelines.

We get a lot of issues on this repo, so please be patient and we will get back to you as soon as we can.

biiibooo[bot] avatar May 23 '23 13:05 biiibooo[bot]

I have the same problem, it loads a lot of font assets and makes project very slow and laggy.

mahmonirbkh avatar Jun 06 '23 13:06 mahmonirbkh

Same problem here as well.

aadi-paypay avatar Sep 06 '23 11:09 aadi-paypay

@aadi-paypay , @mahmonirbkh , @myszkin81 How are you loading the fonts? Can you show us the code snippet that you are using to load the fonts

Parth909 avatar Jan 07 '24 13:01 Parth909

@aadi-paypay , @mahmonirbkh , @myszkin81 How are you loading the fonts? Can you show us the code snippet that you are using to load the fonts

I use sass, so for loading fonts a mixin's been defined like below:

$fontpath2: '../assets/fonts';
$fontFolder2: 'inter';
$fontFamily2: 'Inter';
$fontWeights2: 100, 200, 300, 400, 500, 600, 700, 800, 900;
$fontExtension2: 'woff2';

@mixin fontface($folder2, $ffamily2, $fweight2, $fname2) {
    @font-face {
        @if $ffamily2 {
            font-family: $ffamily2;
        }

        @if $fweight2 {
            font-weight: $fweight2;
        }

        font-display: swap;
        font-style: normal;

        @if $folder2 {
            src: url('#{$fontpath2}/#{$folder2}/#{$fname2}.#{$fontExtension2}') format($fontExtension2);
        } @else {
            src: url('#{$fontpath2}/#{$fname2}.#{$fontExtension2}') format($fontExtension2);
        }
    }
}

mahmonirbkh avatar Jan 08 '24 09:01 mahmonirbkh

maybe you can use fontEmbedCSS to customize the fonts you want to load. first you need to find all font families in the target DOM yourself.

function findAllFontFamily(root: HTMLElement) {
  const familyList = new Set<string>()
  const queue: HTMLElement[] = [root]
  while (queue.length) {
    const node = queue.shift()
    if (!node) continue
    const styleValue = node?.attributes?.getNamedItem('style')?.value
    const fontFamilyMatch = styleValue?.match(/font-family:([^;]*)/)
    if (fontFamilyMatch && fontFamilyMatch[1]) {
      familyList .add(fontFamilyMatch[1].trim())
    }
    // const { fontFamily } = window.getComputedStyle(node)
    if (node.children) {
      queue.push(...node.children as any)
    }
  }
  return [ ...familyList ]
}

next

import { fetchAsDataURL } from 'html-to-image/src/dataurl'
import { toJpeg  } from 'html-to-image'

(async () => {
    const config: ExportImageConfig = {
      quality: 1,
      width: 1600
      }
      const embedFamilyList = findAllFontFamily(rootDom)
      const dataUrls = []
      for (const family of embedFamilyList) {
        const dataUrl:string = await fetchAsDataURL(`https://host.com/path/to/${family}.woff2`, {}, ({result}) => {
          return `
          @font-face {
            font-display: swap;
            font-family: ${family};
            src: url('${result}') format('woff2');
          }
          `
        })
        dataUrls.push(dataUrl)
      }
      config.fontEmbedCSS = dataUrls.join('')
      await toJpeg(rootDom, config)
})()

Here is an idea, not the complete code

Howlcn1997 avatar Mar 19 '24 10:03 Howlcn1997