omacranger / fontawesome-subset

Creates subsets of FontAwesome fonts for optimized use on the web.
GNU General Public License v3.0
66 stars 15 forks source link

Version 6? #16

Closed quasipickle closed 2 years ago

quasipickle commented 2 years ago

It appears version 6 no longer ships with the webfont svgs - just sprite sheets. Is that fatal for this project?

omacranger commented 2 years ago

Good question! I've been meaning to rework the parsing process regardless, but I'm not aware of the changes brought in with v6 yet. I'll look into it.

christopherpickering commented 2 years ago

Well all the individual svg's are still there - so maybe instead of starting w/ a prebuild list and stopped the removed icons, start with the individual svg's and combine into a font file?

omacranger commented 2 years ago

Possibly. It seems in doing so [removing the SVG files] they also removed much of the context for mapping unicode characters to SVG glyphs as well. I'll have to get creative, and likely end up with more regexing.

cirosantilli commented 2 years ago

I tried a hello world:

package.json

{
  "name": "font",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@fortawesome/fontawesome-free": "^6.0.0",
    "fontawesome-subset": "^3.0.0"
  }
}

main.js

// Import fontawesome-subset
const fontawesomeSubset = require("fontawesome-subset");

// Create or append a task to be ran with your configuration
fontawesomeSubset.fontawesomeSubset(['check','square','caret-up'], 'sass/webfonts');

and it fails with:

Unable to find SVG font file for requested font style 'solid'. Skipping.

might be related to this.

christopherpickering commented 2 years ago

@cirosantilli pinning font awesome to v5.14.0 should resolve your problem until an update comes out.

"@fortawesome/fontawesome-free": "5.14.0",
omacranger commented 2 years ago

Unfortunately, standard SVGs and SVG fonts use different formats so the icons cannot just be assembled directly into an SVG font (so the remainder of the conversion can take place). As much as I hate the idea of relying on dependency on top of dependency that may just be what it takes. I do have some of this working with the new version so will keep pushing along and probably put out a beta version so some of you can assist in testing. I don't have access to FontAwesome Pro anymore so I'm a bit limited on testing some of the functionality / layout of the extended formats [like duotone].

saurori commented 2 years ago

@omacranger Would it be possible to use the otf or ttf files as a starting point vs SVG? I think it should be possible to manipulate those using something like opentype.js. FontAwesome provides a number of JS packages that can help with mapping of names to glyphs such as this file.

EDIT: All icons metadata

saurori commented 2 years ago

I put together a quick script that subsets FontAwesome 6 using the subset-font library. I'm sure some of this could be more elegant but it works:

const fs = require('fs')
const path = require('path')
const Glob = require("glob")
const YAML = require('yaml')
const subsetFont = require('subset-font')

const faFile = require.resolve('@fortawesome/fontawesome-free')
const faMetadata = path.resolve(faFile, '../../metadata/icons.yml')
const faWebFonts = path.resolve(faFile, '../../webfonts')
const outDir = path.resolve('./assets/fontawesome-subset')

const iconYaml = fs.readFileSync(faMetadata, 'utf8')
const icons = YAML.parse(iconYaml)

const iconSubset = [
  "check",
  "minus",
  "plus"
]

let iconSubSetUnicode = []

iconSubset.forEach((ico) => {
  console.log(icons[ico])
  iconSubSetUnicode.push(String.fromCodePoint(parseInt(icons[ico]['unicode'], 16)))
})

const outputTypes = [
  { targetFormat: 'woff2', fileExt: 'woff2' },
  { targetFormat: 'sfnt', fileExt: 'ttf' }
]

Glob.sync(faWebFonts + '/*.ttf').forEach((entry) => {
  console.log(entry)

  const fontData = fs.readFileSync(entry);

  outputTypes.forEach((ftype) => {

    const subsetBuffer = subsetFont(fontData, iconSubSetUnicode.join(' '), {
      targetFormat: ftype.targetFormat,
    });

    subsetBuffer.then((data) => {
      const fName = path.parse(entry).name + '.' + ftype.fileExt;
      const fPath = path.join(outDir, fName)
      fs.writeFile(fPath, data, err => {
        if (err) {
          console.error(err);
        }
      });
    })

  })
})
roeycohen commented 2 years ago

hi @saurori, subset-font library does a great job!! thank you for sharing this :)

Jieiku commented 2 years ago

@saurori Thank you for sharing your script, based on the paths in the script I made some assumptions... I am also not yet sure how to run this script.

saurori commented 2 years ago

@Jieiku

@saurori Thank you for sharing your script, based on the paths in the script I made some assumptions... I am also not yet sure how to run this script.

I use it in a project with Yarn. In my package.json I specify all the dependencies (or use yarn add), yarn install, then under scripts, example:

  "scripts": {
    "fonts": "node subfont.js"
  },

And then you can run yarn fonts. In the subfont.js. script, change the outDir to whatever path you want the resulting fonts to write to.

Jieiku commented 2 years ago

Thanks a ton, will work on implementing it now!

Is it ok to redistribute your script that you shared?

saurori commented 2 years ago

Thanks a ton, will work on implementing with yarn now!

Is it ok to redistribute your script that you shared?

Sure. My hope was the author of this repository would use it in some fashion to update with version 6 support, vs creating some new package.

Jieiku commented 2 years ago

I created a subset of fontawesome using FontForge for my Zola theme Abridge

Using FontForge worked, but it required many steps, so just trying to get something working on the command line for now.

GOT IT WORKING! Thanks again!

Jieiku commented 2 years ago

For anyone less familiar with setting these things up, or that just wants to save some time, you can use the repo here:

https://github.com/Jieiku/fontsubset

christopherpickering commented 2 years ago

Thanks @saurori , I put your nice code into a pr. #19 👏🏽 🚀

omacranger commented 2 years ago

Hey all, thank you for the contributions! Marvelous work. Simplifies a lot of things. I imagine it should still hold full support and would probably be backwards compatible aside from the reduction of output font types. I put together a PR in #20 (so I could tidy up some code style changes & refactor a few things while I was in there). Let me know what you guys think and I'll see if I can get it published / pushed here in the next few days.

dzhuang commented 2 years ago

Or just use the subset-iconfont package.

 // npm install --save-dev subset-iconfont @fortawesome/fontawesome-free

import { FaFreeProvider } from 'subset-iconfont';

const fa = new FaFreeProvider (['plus', 'clock', '500px'], {
  formats: ['ttf', 'woff2'],
});

fa.makeFonts('./outputDir').then((result) => {
  console.log('Done!');
});

That will generate exactly the same file structure, including scss and css, with LICENSE included, with codepoints same as the offical ones. A simple subclass would suffice for PRO version, but with thin, thick and duotone css / scss LICENSE restrictions, that should be done by user manually.