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

Compatibility with Yarn and Plug'n'Play mode #17

Closed jmariller closed 2 years ago

jmariller commented 2 years ago

Hi,

We are currently using fontawesome-subset in our project, where the package manager is Yarn version 1. I am trying to migrate to Yarn modern version and to enable the Plug'n'Play mode, which basically removes the node_modules folder and uses the .yarn folder instead. Now when I try to run the script to generate the subset, I get the following error message:

Unable to find either the Free or Pro FontAwesome files in node_modules folder. Double-check that you have your preferred fontawesome package as a dependency in package.json and rerun the installation.

I understand the script is checking for existence of Font-Awesome in node_modules

    if (!(existsSync("node_modules/@fortawesome/fontawesome-free") || existsSync("node_modules/@fortawesome/fontawesome-pro"))) {

This should be done differently for Yarn Modern version, although I am not completely sure what would be the best way. Could you possibly look into this?

Many thanks for your help!

jmariller commented 2 years ago

PS: I found the problem can be solved by using require.resolve, like so:

existsSync(require.resolve("@fortawesome/fontawesome-free"))

instead of:

existsSync("node_modules/@fortawesome/fontawesome-free")

This must be done for each instance where the source is supposed to be node_modules.

callaginn commented 6 months ago

Based on my understanding of the above, the changes made in #20 should make this compatible with Yarn 4 PnP projects?

If so, I'm having trouble getting this to work. Every time I try to run it, it gives me this error:

node:fs:453
    return binding.readFileUtf8(path, stringToFlags(options.flag));
                   ^
Error: ENOENT: no such file or directory, open '/Users/bob/Sites/test-site/metadata/icons.yml'
    at Object.readFileSync (node:fs:453:20)
    at NodeFS.readFileSync (/Users/bob/Sites/test-site/.pnp.cjs:13172:24)
    at makeCallSync.subPath.subPath (/Users/bob/Sites/test-site/.pnp.cjs:13840:26)
    at ZipOpenFS.makeCallSync (/Users/bob/Sites/test-site/.pnp.cjs:13959:14)
    at ZipOpenFS.readFileSync (/Users/bob/Sites/test-site/.pnp.cjs:13839:17)
    at VirtualFS.readFileSync (/Users/bob/Sites/test-site/.pnp.cjs:12793:24)
    at PosixFS.readFileSync (/Users/bob/Sites/test-site/.pnp.cjs:12793:24)
    at NodePathFS.readFileSync (/Users/bob/Sites/test-site/.pnp.cjs:12793:24)
    at fontawesomeSubset (/Users/bob/Sites/test-site/.yarn/unplugged/fontawesome-subset-virtual-e78ecf781e/node_modules/fontawesome-subset/dist/index.js:51:65)
    at file:///Users/bob/Sites/test-site/resolve-subsetter.js:37:1 {
  errno: -2,
  code: 'ENOENT',
  syscall: 'open',
  path: '/Users/bob/Sites/test-site/metadata/icons.yml'
}

The only way I've figured out how to make this to work is to do the following:

  1. Convert this project to a Yarn 4 PnP project
  2. Add these lines to the top:
    import url from 'url';
    const __filename = url.fileURLToPath(import.meta.url);
    const __dirname = dirname(__filename);
    import pnpapi from "pnpapi";
  3. And use these lines as the resolution steps:
    let packageLocation = pnpapi.resolveToUnqualified(`@fortawesome/fontawesome-${packageType}`, __dirname).slice(0, -1);
    const fontMeta = `${packageLocation}/metadata/icons.yml`;
    const fontFamilyMeta = `${packageLocation}/metadata/icon-families.yml`;
    const fontFiles = `${packageLocation}/webfonts`;

Unfortunately, I'm not familiar enough with typescript, so I had to convert a lot of this code to plain javascript, since it won't compile with those additions. If needed, I can post the code I've got to a repo.

Any idea what's going on there?

omacranger commented 6 months ago

@callaginn Do you have a small repro project (with the standard fontawesome package / setup with it failing) you can share?

callaginn commented 6 months ago

@omacranger Somewhat; that is, I managed to create a test case that shows it failing. However, this test can only be run if you have access to Font Awesome v5's private repo:

Here's the test: https://github.com/callaginn/fa-subset-test

That being said, just setting up this simple test case helped me a LOT 😄, because it forced me to reduce it down to the basics. I quickly realized that what "could" be causing it to fail is Font Awesome itself. So after a bit of digging and dealing with annoying Yarn caching, I discovered there's a few key differences in their package.json:

  1. Their "name" field has a value of "font-awesome-pro" at the base level, instead of "@fortawesome/fontawesome-pro".
  2. Their "main" entry point with a value of "js/fontawesome.js" was missing.
  3. Their "style" entry point with a value of "css/fontawesome.css" was missing.

Once I changed those three things on a forked private repo, everything started working.


Interestingly, I did notice those values were correct/present in their "js-packages/@fortawesome/fontawesome-pro" folder.

So what I assume is going on is the FA packages within "js-packages" were being served by NPM (which probably always worked). However, I only had access to their private Github repo, which had a different config at the base level.

omacranger commented 6 months ago

Glad you got it working! Have you considered using their scoped registry instead? May save you some of the hassle of dealing with their private repo.

If you run into something else let me know / open an issue.

callaginn commented 6 months ago

@omacranger I'm not sure I can. I was an early backer of Font Awesome 5, so have a perpetual license to the FA5 Pro repo -- but haven't had a subscription to Pro for some time. Is there a way to do that without a subscription?

Also, thanks so much for this script! We've been using it in a lot of our projects for years.

omacranger commented 6 months ago

@callaginn I don't believe it's possible without a subscription, sadly. I don't have access to the private repo (I think) so I'm not sure I could make some suggestions there. Do they offer releases on Github with the prebundled / packaged package? You may also be able to checkout the repo and build it depending on the complexity of the project / then import it as an NPM package.