Resolve asset to public path in `bud.config.js`/JavaScript

bud.path(...) and bud.relPath(...) can be used to resolve the path to an asset (including aliases) in the bud.config.js/JavaScript. How can path to the public path with hash resolved?

Alternatively, can bud resolve aliases/paths used in wpjson.settings; set(...), notably typography.fontFamilies for the WordPress Web Fonts API:

    .wpjson
      .settings(theme =>
        theme
          .set("typography.fontFamilies", [
            {
              "fontFamily": "\"Some self-hosted (e.g. licensed) font\", Arial, sans-serif",
              "slug": "tertiary",
              "name": "Self-hosted",
              "fontFace": [
                {
                  "fontFamily":  "Self hosted",
                  "fontWeight":  "normal",
                  "fontStyle":   "normal",
                  "fontStretch": "normal",
                  "src": [
                    "file:@fonts/licensed/self-hosted/file.woff",
                    "file:@fonts/licensed/self-hosted/file.woff2",
                  ]
                }
              ]
            }
          ])
      )

Those asset paths (@fonts/...) are not resolved (also not the @fonts alias).

1 Like

The problem we’re going to bump into is that those files don’t actually exist in time for bud.path to resolve them. And, I don’t really want to start going down the road of interpreting the data provided too much because I don’t spend a lot of time with the API and don’t want to be in a position where we have to respond to changes upstream.

Still, worth thinking about. I get the need.

I think the easiest way to handle this right now is to register a function with bud.after to read the manifest and update the data accordingly:

export default async (app) => {
  app.after(async () => {
    const manifest = await app.fs.read(`public/manifest.json`);
    const data = app.container(await app.fs.read(`theme.json`));

    data.set(`settings.typography.fontFamilies.[0].fontFace.[0].src`, [
      `file:${manifest[`fonts/example.woff`]}`,
    ]);

    await app.fs.write(`theme.json`, data.all());
  });
}
  • You don’t have to use the container API if you prefer to handle it with ES6 or a different tool.
  • app.fs.read will give you an object if you ask it for the contents of a json file
  • app.fs.write will handle stringifying the data for you
  • unless you specify otherwise, app.fs will always resolve relative to project root.
  • If you need the publicPath you can get it from app.publicPath()
2 Likes

Edit: I should more RTFM: bud.assets | bud.js

Follow up:

public/ has to be prefixed to the paths (in the manifest)

export default async (app) => {
  app.after(async () => {
    const manifest = await app.fs.read(`public/manifest.json`);
    const data = app.container(await app.fs.read(`theme.json`));

    data.set(`settings.typography.fontFamilies.[0].fontFace.[0].src`, [
      `file:./public/${manifest[`fonts/example.woff`]}`,
    ]);

    await app.fs.write(`theme.json`, data.all());
  });
}