Add unhinted webfont targets (#1363)
This commit is contained in:
parent
dd627b4556
commit
5d747b9a66
3 changed files with 148 additions and 97 deletions
|
@ -38,13 +38,15 @@ To create a custom build, you need:
|
|||
|
||||
3. Run `npm run build -- contents::<your plan name>` and the built fonts would be available in `dist/`. Aside from `contents::<plan>`, other options are:
|
||||
|
||||
1. `contents::<plan>` : TTF (Hinted and Unhinted), WOFF(2) and Web font CSS;
|
||||
2. `ttf::<plan>` : TTF;
|
||||
1. `contents::<plan>` : Everything (TTF + webfont, hinted + unhinted);
|
||||
2. `ttf::<plan>` : TTF only;
|
||||
3. `ttf-unhinted::<plan>` : Unhinted TTF only;
|
||||
4. `webfont::<plan>` : Web fonts only (CSS + WOFF2);
|
||||
4. `webfont-unhinted::<plan>` : Unhinted web fonts only (CSS + WOFF2);
|
||||
5. `woff2::<plan>` : WOFF2 only.
|
||||
5. `woff2-unhinted::<plan>` : Unhinted WOFF2 only.
|
||||
|
||||
⚠️ **Important:** By default, the build system will schedule a number of concurrently running jobs equal to the number of threads available on the CPU, which *will* push CPU usage and also likely RAM usage, if you do not have very much to work with, to the ceiling (each job consumes more than 1 GB of RAM at its peak). If this is an issue for you, pass an additional argument `--jCmd=<number of concurrent jobs>`.
|
||||
⚠️ **Important**: By default, the build system will schedule a number of concurrently running jobs equal to the number of threads available on the CPU, which *will* push CPU usage and also likely RAM usage, if you do not have very much to work with, to the ceiling (each job consumes more than 1 GB of RAM at its peak). If this is an issue for you, pass an additional argument `--jCmd=<number of concurrent jobs>`.
|
||||
|
||||
### Configuring Custom Build
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ const WebfontFormatMap = new Map([
|
|||
["woff2", "woff2"],
|
||||
["ttf", "truetype"]
|
||||
]);
|
||||
module.exports = function (output, family, hs, formats) {
|
||||
module.exports = function (output, family, hs, formats, unhinted) {
|
||||
if (!formats) {
|
||||
fs.writeFileSync(output, "");
|
||||
return;
|
||||
|
@ -17,8 +17,13 @@ module.exports = function (output, family, hs, formats) {
|
|||
if (!WebfontFormatMap.get(ext)) throw new TypeError("Invalid webfont file format " + ext);
|
||||
}
|
||||
for (const term of hs) {
|
||||
const dirSuffix = unhinted ? "-unhinted" : "";
|
||||
const src = formats
|
||||
.map(ext => `url('${ext}/${term.name}.${ext}') format('${WebfontFormatMap.get(ext)}')`)
|
||||
.map(
|
||||
ext =>
|
||||
`url('${ext}${dirSuffix}/${term.name}.${ext}') ` +
|
||||
`format('${WebfontFormatMap.get(ext)}')`
|
||||
)
|
||||
.join(", ");
|
||||
ans += `
|
||||
@font-face {
|
||||
|
|
228
verdafile.js
228
verdafile.js
|
@ -352,7 +352,6 @@ const DistUnhintedTTF = file.make(
|
|||
}
|
||||
}
|
||||
);
|
||||
|
||||
const BuildCM = file.make(
|
||||
(gr, f) => `${BUILD}/ttf/${gr}/${f}.charmap.mpz`,
|
||||
async (target, output, gr, f) => {
|
||||
|
@ -360,65 +359,10 @@ const BuildCM = file.make(
|
|||
}
|
||||
);
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
////// Font Distribution //////
|
||||
///////////////////////////////////////////////////////////
|
||||
|
||||
// Group-level
|
||||
const GroupContents = task.group("contents", async (target, gr) => {
|
||||
await target.need(GroupFonts(gr), DistWebFontCSS(gr));
|
||||
return gr;
|
||||
});
|
||||
|
||||
// Webfont CSS
|
||||
const DistWebFontCSS = file.make(
|
||||
gr => `${DIST}/${gr}/${gr}.css`,
|
||||
async (target, out, gr) => {
|
||||
const [plan] = await target.need(BuildPlanOf(gr));
|
||||
await target.need(de(out.dir));
|
||||
await createWebFontCssImpl(target, out.full, gr, plan.webfontFormats);
|
||||
}
|
||||
);
|
||||
async function createWebFontCssImpl(target, output, gr, formats) {
|
||||
const [bp, ts] = await target.need(BuildPlanOf(gr), GroupFontsOf(gr));
|
||||
const hs = await target.need(...ts.map(FontInfoOf));
|
||||
echo.action(echo.hl.command(`Create WebFont CSS`), gr, echo.hl.operator("->"), output);
|
||||
await silently.node("utility/make-webfont-css.js", output, bp.family, hs, formats);
|
||||
function formatSuffix(fmt, unhinted) {
|
||||
return fmt + (unhinted ? "-unhinted" : "");
|
||||
}
|
||||
|
||||
// Content files
|
||||
const GroupTTFs = task.group("ttf", async (target, gr) => {
|
||||
const [ts] = await target.need(GroupFontsOf(gr));
|
||||
await target.need(ts.map(tn => DistHintedTTF(gr, tn)));
|
||||
});
|
||||
const GroupUnhintedTTFs = task.group("ttf-unhinted", async (target, gr) => {
|
||||
const [ts] = await target.need(GroupFontsOf(gr));
|
||||
await target.need(ts.map(tn => DistUnhintedTTF(gr, tn)));
|
||||
});
|
||||
const GroupWebFonts = task.group("webfont", async (target, gr) => {
|
||||
const [bp] = await target.need(BuildPlanOf(gr));
|
||||
const groupsNeeded = [];
|
||||
for (const ext of bp.webfontFormats) {
|
||||
switch (ext) {
|
||||
case "ttf":
|
||||
groupsNeeded.push(GroupTTFs(gr));
|
||||
break;
|
||||
case "woff2":
|
||||
groupsNeeded.push(GroupWoff2s(gr));
|
||||
break;
|
||||
}
|
||||
}
|
||||
await target.need(groupsNeeded, DistWebFontCSS(gr));
|
||||
});
|
||||
const GroupWoff2s = task.group("woff2", async (target, gr) => {
|
||||
const [ts] = await target.need(GroupFontsOf(gr));
|
||||
await target.need(ts.map(tn => DistWoff2(gr, tn)));
|
||||
});
|
||||
const GroupFonts = task.group("fonts", async (target, gr) => {
|
||||
await target.need(GroupTTFs(gr), GroupUnhintedTTFs(gr), GroupWoff2s(gr));
|
||||
});
|
||||
|
||||
// Per group file
|
||||
const DistHintedTTF = file.make(
|
||||
(gr, fn) => `${DIST}/${gr}/ttf/${fn}.ttf`,
|
||||
async (target, out, gr, fn) => {
|
||||
|
@ -428,15 +372,103 @@ const DistHintedTTF = file.make(
|
|||
await silently.run(hint, hintParams, from.full, out.full);
|
||||
}
|
||||
);
|
||||
|
||||
const DistWoff2 = file.make(
|
||||
(gr, fn) => `${DIST}/${gr}/woff2/${fn}.woff2`,
|
||||
async (target, out, group, f) => {
|
||||
const [from] = await target.need(DistHintedTTF(group, f), de`${out.dir}`);
|
||||
(gr, fn, unhinted) => `${DIST}/${gr}/${formatSuffix("woff2", unhinted)}/${fn}.woff2`,
|
||||
async (target, out, group, f, unhinted) => {
|
||||
const Ctor = unhinted ? DistUnhintedTTF : DistHintedTTF;
|
||||
|
||||
const [from] = await target.need(Ctor(group, f), de`${out.dir}`);
|
||||
echo.action(echo.hl.command("Create WOFF2"), from.full, echo.hl.operator("->"), out.full);
|
||||
await silently.node(`utility/ttf-to-woff2.js`, from.full, out.full);
|
||||
}
|
||||
);
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
////// Font Distribution //////
|
||||
///////////////////////////////////////////////////////////
|
||||
|
||||
// Group-level entry points
|
||||
const Entry_GroupContents = task.group("contents", async (target, gr) => {
|
||||
await target.need(Entry_GroupFonts(gr), Entry_GroupUnhintedFonts(gr));
|
||||
return gr;
|
||||
});
|
||||
const Entry_GroupTTFs = task.group("ttf", async (target, gr) => {
|
||||
await target.need(GroupTtfsImpl(gr, false));
|
||||
});
|
||||
const Entry_GroupUnhintedTTFs = task.group("ttf-unhinted", async (target, gr) => {
|
||||
await target.need(GroupTtfsImpl(gr, true));
|
||||
});
|
||||
const Entry_GroupWoff2s = task.group("woff2", async (target, gr) => {
|
||||
await target.need(GroupWoff2Impl(gr, false));
|
||||
});
|
||||
const Entry_GroupUnhintedWoff2s = task.group("woff2-unhinted", async (target, gr) => {
|
||||
await target.need(GroupWoff2Impl(gr, true));
|
||||
});
|
||||
const Entry_GroupWebFonts = task.group("webfont", async (target, gr) => {
|
||||
await target.need(GroupWebFontsImpl(gr, false));
|
||||
});
|
||||
const Entry_GroupUnhintedWebFonts = task.group("webfont-unhinted", async (target, gr) => {
|
||||
await target.need(GroupWebFontsImpl(gr, true));
|
||||
});
|
||||
const Entry_GroupFonts = task.group("fonts", async (target, gr) => {
|
||||
await target.need(GroupTtfsImpl(gr, false), GroupWebFontsImpl(gr, false));
|
||||
});
|
||||
const Entry_GroupUnhintedFonts = task.group("fonts-unhinted", async (target, gr) => {
|
||||
await target.need(GroupTtfsImpl(gr, true), GroupWebFontsImpl(gr, true));
|
||||
});
|
||||
|
||||
// Webfont CSS
|
||||
const DistWebFontCSS = file.make(
|
||||
(gr, unhinted) => `${DIST}/${gr}/${formatSuffix(gr, unhinted)}.css`,
|
||||
async (target, out, gr, unhinted) => {
|
||||
const [plan] = await target.need(BuildPlanOf(gr));
|
||||
await target.need(de(out.dir));
|
||||
await createWebFontCssImpl(target, out.full, gr, plan.webfontFormats, unhinted);
|
||||
}
|
||||
);
|
||||
async function createWebFontCssImpl(target, output, gr, formats, unhinted) {
|
||||
const [bp, ts] = await target.need(BuildPlanOf(gr), GroupFontsOf(gr));
|
||||
const hs = await target.need(...ts.map(FontInfoOf));
|
||||
echo.action(echo.hl.command(`Create WebFont CSS`), gr, echo.hl.operator("->"), output);
|
||||
await silently.node("utility/make-webfont-css.js", output, bp.family, hs, formats, unhinted);
|
||||
}
|
||||
|
||||
// Content files
|
||||
const GroupTtfsImpl = task.make(
|
||||
(gr, unhinted) => `group-${formatSuffix("ttf-impl", unhinted)}::${gr}`,
|
||||
async (target, gr, unhinted) => {
|
||||
const Ctor = unhinted ? DistUnhintedTTF : DistHintedTTF;
|
||||
const [ts] = await target.need(GroupFontsOf(gr));
|
||||
await target.need(ts.map(tn => Ctor(gr, tn)));
|
||||
}
|
||||
);
|
||||
const GroupWoff2Impl = task.make(
|
||||
(gr, unhinted) => `group-${formatSuffix("woff2-impl", unhinted)}::${gr}`,
|
||||
async (target, gr, unhinted) => {
|
||||
const [ts] = await target.need(GroupFontsOf(gr));
|
||||
await target.need(ts.map(tn => DistWoff2(gr, tn, unhinted)));
|
||||
}
|
||||
);
|
||||
const GroupWebFontsImpl = task.make(
|
||||
(gr, unhinted) => `group-${formatSuffix("webfont-impl", unhinted)}::${gr}`,
|
||||
async (target, gr, unhinted) => {
|
||||
const [bp] = await target.need(BuildPlanOf(gr));
|
||||
const groupsNeeded = [];
|
||||
for (const ext of bp.webfontFormats) {
|
||||
switch (ext) {
|
||||
case "ttf":
|
||||
groupsNeeded.push(GroupTtfsImpl(gr, unhinted));
|
||||
break;
|
||||
case "woff2":
|
||||
groupsNeeded.push(GroupWoff2Impl(gr, unhinted));
|
||||
break;
|
||||
}
|
||||
}
|
||||
await target.need(groupsNeeded, DistWebFontCSS(gr, unhinted));
|
||||
}
|
||||
);
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
////// Font Collection Plans //////
|
||||
///////////////////////////////////////////////////////////
|
||||
|
@ -582,7 +614,7 @@ async function buildGlyphSharingTtc(target, parts, out) {
|
|||
///////////////////////////////////////////////////////////
|
||||
|
||||
// Collection Archives
|
||||
const TtcArchiveFile = file.make(
|
||||
const TtcZip = file.make(
|
||||
(cgr, version) => `${ARCHIVE_DIR}/ttc-${cgr}-${version}.zip`,
|
||||
async (target, out, cgr) => {
|
||||
const [cPlan] = await target.need(CollectPlans, de`${out.dir}`);
|
||||
|
@ -591,7 +623,7 @@ const TtcArchiveFile = file.make(
|
|||
await CreateGroupArchiveFile(`${BUILD}/ttc-collect/${cgr}`, out, `*.ttc`);
|
||||
}
|
||||
);
|
||||
const SuperTtcArchiveFile = file.make(
|
||||
const SuperTtcZip = file.make(
|
||||
(cgr, version) => `${ARCHIVE_DIR}/super-ttc-${cgr}-${version}.zip`,
|
||||
async (target, out, cgr) => {
|
||||
await target.need(de`${out.dir}`, CollectedSuperTtcFile(cgr));
|
||||
|
@ -600,29 +632,32 @@ const SuperTtcArchiveFile = file.make(
|
|||
);
|
||||
|
||||
// Single-group Archives
|
||||
const GroupTtfArchiveFile = file.make(
|
||||
(gr, version) => `${ARCHIVE_DIR}/ttf-${gr}-${version}.zip`,
|
||||
async (target, out, gr) => {
|
||||
const GroupTtfZip = file.make(
|
||||
(gr, version, unhinted) =>
|
||||
`${ARCHIVE_DIR}/${formatSuffix("ttf", unhinted)}-${gr}-${version}.zip`,
|
||||
async (target, out, gr, _version_, unhinted) => {
|
||||
await target.need(de`${out.dir}`);
|
||||
await target.need(GroupContents(gr));
|
||||
await CreateGroupArchiveFile(`${DIST}/${gr}/ttf`, out, "*.ttf");
|
||||
await target.need(GroupTtfsImpl(gr, unhinted));
|
||||
await CreateGroupArchiveFile(
|
||||
`${DIST}/${gr}/${formatSuffix("ttf", unhinted)}`,
|
||||
out,
|
||||
"*.ttf"
|
||||
);
|
||||
}
|
||||
);
|
||||
const GroupTtfUnhintedArchiveFile = file.make(
|
||||
(gr, version) => `${ARCHIVE_DIR}/ttf-unhinted-${gr}-${version}.zip`,
|
||||
async (target, out, gr) => {
|
||||
await target.need(de`${out.dir}`);
|
||||
await target.need(GroupContents(gr));
|
||||
await CreateGroupArchiveFile(`${DIST}/${gr}/ttf-unhinted`, out, "*.ttf");
|
||||
}
|
||||
);
|
||||
const GroupWebArchiveFile = file.make(
|
||||
(gr, version) => `${ARCHIVE_DIR}/webfont-${gr}-${version}.zip`,
|
||||
async (target, out, gr) => {
|
||||
const GroupWebZip = file.make(
|
||||
(gr, version, unhinted) =>
|
||||
`${ARCHIVE_DIR}/${formatSuffix("webfont", unhinted)}-${gr}-${version}.zip`,
|
||||
async (target, out, gr, _version_, unhinted) => {
|
||||
const [plan] = await target.need(BuildPlanOf(gr));
|
||||
await target.need(de`${out.dir}`);
|
||||
await target.need(GroupContents(gr));
|
||||
await CreateGroupArchiveFile(`${DIST}/${gr}`, out, "*.css", ...plan.webfontFormats);
|
||||
await target.need(GroupWebFontsImpl(gr, unhinted));
|
||||
await CreateGroupArchiveFile(
|
||||
`${DIST}/${gr}`,
|
||||
out,
|
||||
`${formatSuffix(gr, unhinted)}.css`,
|
||||
...plan.webfontFormats.map(format => formatSuffix(format, unhinted))
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -681,7 +716,7 @@ const PagesFontExport = task.group(`pages:font-export`, async (target, gr) => {
|
|||
const [pagesDir] = await target.need(PagesDir);
|
||||
if (!pagesDir) return;
|
||||
const outDir = Path.resolve(pagesDir, "shared/fonts", gr);
|
||||
await target.need(GroupWebFonts(gr), de(outDir));
|
||||
await target.need(GroupWebFontsImpl(gr, false), de(outDir));
|
||||
await cp(`${DIST}/${gr}/woff2`, Path.resolve(outDir, "woff2"));
|
||||
await createWebFontCssImpl(target, Path.resolve(outDir, `${gr}.css`), gr, webfontFormatsPages);
|
||||
await rm(Path.resolve(outDir, "ttf"));
|
||||
|
@ -692,7 +727,7 @@ const PagesFastFontExport = task.group(`pages:fast-font-export`, async (target,
|
|||
const [pagesDir] = await target.need(PagesDir);
|
||||
if (!pagesDir) return;
|
||||
const outDir = Path.resolve(pagesDir, "shared/fonts", gr);
|
||||
await target.need(GroupUnhintedTTFs(gr), de(outDir));
|
||||
await target.need(GroupTtfsImpl(gr, true), de(outDir));
|
||||
|
||||
// Next.js 12 has some problem about refreshing fonts, so write an empty CSS first
|
||||
await createWebFontCssImpl(target, Path.resolve(outDir, `${gr}.css`), gr, null);
|
||||
|
@ -723,10 +758,10 @@ const SampleImages = task(`sample-images`, async target => {
|
|||
|
||||
const SampleImagesPre = task(`sample-images:pre`, async target => {
|
||||
const [sans, slab, aile, etoile] = await target.need(
|
||||
GroupContents`iosevka`,
|
||||
GroupContents`iosevka-slab`,
|
||||
GroupContents`iosevka-aile`,
|
||||
GroupContents`iosevka-etoile`,
|
||||
GroupWebFontsImpl(`iosevka`, false),
|
||||
GroupWebFontsImpl(`iosevka-slab`, false),
|
||||
GroupWebFontsImpl(`iosevka-aile`, false),
|
||||
GroupWebFontsImpl(`iosevka-etoile`, false),
|
||||
SnapShotStatic("index.js"),
|
||||
SnapShotStatic("get-snap.js"),
|
||||
SnapShotJson,
|
||||
|
@ -928,12 +963,12 @@ phony(`release`, async target => {
|
|||
for (const [cgr, plan] of Object.entries(collectPlans)) {
|
||||
if (!plan.inRelease) continue;
|
||||
const subGroups = collectPlans[cgr].groupDecomposition;
|
||||
goals.push(TtcArchiveFile(cgr, version));
|
||||
goals.push(SuperTtcArchiveFile(cgr, version));
|
||||
goals.push(TtcZip(cgr, version));
|
||||
goals.push(SuperTtcZip(cgr, version));
|
||||
for (const gr of subGroups) {
|
||||
goals.push(GroupTtfArchiveFile(gr, version));
|
||||
goals.push(GroupTtfUnhintedArchiveFile(gr, version));
|
||||
goals.push(GroupWebArchiveFile(gr, version));
|
||||
goals.push(GroupTtfZip(gr, version, false));
|
||||
goals.push(GroupTtfZip(gr, version, true));
|
||||
goals.push(GroupWebZip(gr, version, false));
|
||||
}
|
||||
}
|
||||
const [archiveFiles] = await target.need(goals);
|
||||
|
@ -943,6 +978,15 @@ phony(`release`, async target => {
|
|||
// Images and release notes
|
||||
await target.need(SampleImages, Pages, AmendReadme, ReleaseNotes, ChangeLog);
|
||||
});
|
||||
phony.group(`release-test`, async (target, gr) => {
|
||||
const [version] = await target.need(Version);
|
||||
await target.need(
|
||||
GroupTtfZip(gr, version, false),
|
||||
GroupTtfZip(gr, version, true),
|
||||
GroupWebZip(gr, version, false),
|
||||
GroupWebZip(gr, version, true)
|
||||
);
|
||||
});
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
////// Script Building //////
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue