ActivearkJWT / grunt-font-optimizer

Optimize TTF fonts with Grunt
MIT License
18 stars 5 forks source link

Subsetting not automatically possible #11

Open the-hotmann opened 3 years ago

the-hotmann commented 3 years ago

I would like to remove ALL unused chars automatically, and not having to use options.chars. I would like to pass some .html files to this processor so he automatically removes all subsets which are not included.

Something similar is available here: https://github.com/caiguanhao/grunt-ziti (archived project)

jehna commented 3 years ago

Good idea!

I'm a bit worried though that this change would make this plugin specialized for html files, while you could want to grab those chars from e.g. JSON file that has your translations or from a third party service.

I think you can do this without any changes to this plugin though — something like (in your Gruntfile):

const { JSDOM } = require('jsdom')
const fs = require('fs')

grunt.registerTask('update_chars', 'Set chars setting for grunt-font-optimizer dynamically', () => {
  const yourHTMLFile = fs.readFileSync('yourhtmlfile.html')
  const chars = [...new Set(new JSDOM(yourHTMLFile).window.document.body.textContent.split(''))].join('')
  grunt.config.set('font_optimizer.default.options.chars', chars);
});

Then you can run update_chars before you run font_optimizer and you should have a dynamic configuration

(sorry for the horrible one-liner for extracting the chars, please refactor before pushing to your own codebase)

the-hotmann commented 3 years ago

What a nice workaround, thanks!

I'm a bit worried though that this change would make this plugin specialized for html files

Thats not the plan :) But it also should support HTML, actually it should support all common textfiles and at least be able to parse text from the most widely spreaded ones.

But that does not entirely address the problem of unoptimized fonts. Let me explain a bit.

On most websites I use more then one font. One for Headlines, one for basic text. The one for headlines (and copyright) therefore does need a different subset ad the one for basic text. So more then just parsing the content and checking which chars are used must be done. It must be done for each font. To determinate which fonts needs which chars not just the HTML is needed but also the CSS, then the HTML must be rendered and then a script can determinate which font actually needs which perfect subset. Also: it should be possible to actually pass multiple HTML files the script so it can create (if wished) one font that matches ALL chars in the subset for this font.

My current subsets:

  1. '0123456789ÄÖÜABCDEFGHIJKLMNOPQRSTUVWXYZäöüabcdefghijklmnopqrstuvwxyz-,.&§ß©',
  2. '0123456789ÄÖÜABCDEFGHIJKLMNOPQRSTUVWXYZäöüabcdefghijklmnopqrstuvwxyz-,;.:&ß?()|/@',

The difference is small as I dont want to remove normal alphabetic chars as you could anytime need them. But if the check and subsetting would be done automatically this would make sense! ATM the only difference is in special chars.

Thats why I refered to grunt-ziti as there it was possible to pass HTML and CSS and JS to the parser and then it checked which subset is the perfect for the provided font. Also it must be clear which font you try to optimize, so a mapping must be done ('Font-Name', 'Font-Weight', 'Font-Style') which matches the @font-face from the CSS file so the parser knows which font he actually to generate the subset-chars for.

I know such a feature is much work and I'am apparently have never created any Grunt-Application/Task, but it at least seems to be possible to do this dynamically integrated into an proccess flow and thats why I would like to test this.

ATM I am setting my subset.chars manually for each font, which is close to perfect, but is just not completely perfect.

And on the other hand I ATM get the very same error as #7 so I switched over to a different grunt-application but would switch back anytime this feature gets implemented, just for the sake of perfection.