Commit e462ada5 authored by Manvel Saroyan's avatar Manvel Saroyan Committed by Winsley

Issue 7091 - create font generation tool

parent 8ce17d53
......@@ -185,6 +185,14 @@ Format of the exported CSV files:
| Modified | options.json | cancel | Cancel button label | | Cancel | Kanselleer | ይቅር | ... |
| Added | options.json | domain | Domain input example | {"domain":{"content":"$1"}} | e.g. $domain$ | | | ... |
Fonts generation
----------------
`npm run fonts-gen` - Generates font subsets and css file with `@font-face`
and `:lang()` rules using unicode ranges extracted from extension locales.
See `build/font-generation/config.js` for the script configuration.
firstRun.html
-------------
......
/*
* This file is part of Adblock Plus <https://adblockplus.org/>,
* Copyright (C) 2006-present eyeo GmbH
*
* Adblock Plus is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* Adblock Plus is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
// Directory where the locales are located
const localesDir = "./locale";
// Folder for fonts generation
const outputDir = "./build/font-generation/output";
// Path for the font css file generation
const fontFile = `${outputDir}/font.css`;
// Input directory containing source fonts
const inputDir = "./build/font-generation/fonts";
// determines which font to use for specific locales
const fontToLocalesMap = {
"Cairo.ttf": ["ar"],
"Athiti.ttf": ["th"],
"SourceSansPro.ttf": ["af", "ast", "az", "be", "bg", "br", "bs", "ca", "cs",
"cy", "da", "de", "dsb", "el", "en_GB", "en_US", "eo",
"es", "es_AR", "es_CL", "es_MX", "et", "eu", "fi",
"fil", "fr", "fy", "gl", "hr", "hsb", "hu", "id", "is",
"it", "kab", "kk", "it", "lv", "mg", "mk", "ms", "nb",
"nl", "nn", "pl", "pt_BR", "pt_PT", "rm", "ro", "ru",
"sk", "sl", "sq", "sr", "sv", "sw", "tr", "uk", "uz",
"vi"]
};
module.exports = {localesDir, inputDir, outputDir, fontToLocalesMap, fontFile};
/*
* This file is part of Adblock Plus <https://adblockplus.org/>,
* Copyright (C) 2006-present eyeo GmbH
*
* Adblock Plus is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* Adblock Plus is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
// Used for the css file generation
const license = `
/*
* This file is part of Adblock Plus <https://adblockplus.org/>,
* Copyright (C) 2006-present eyeo GmbH
*
* Adblock Plus is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* Adblock Plus is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>.
*/
`;
/**
* Generates @font-face rule
* @param {String} name value of font-family property
* @param {String} weight value of weight property
* @param {String} url value of src property's url()
* @param {String} range value of unicode-range property
* @returns {String}
*/
const generateFontFace = (name, weight, url, range) =>
{
return `
@font-face
{
font-family: "${name}";
font-style: normal;
font-weight: ${weight};
/* local("Ø") forces using no local font called Source Sans Pro */
src: local("Ø"), url("${url}")
format("woff2");
unicode-range: ${range};
}`;
};
/**
* Generates :lang() rule
* @param {Array} locales list of locales to be used by fonts
* @param {String} fontFamily value of font-family property
* @returns {String}
*/
const generateLangRule = (locales, fontFamily) =>
{
const separator = ", ";
const reducer = (acc, locale) => acc + `${separator}:lang(${locale})`;
const selector = locales.reduce(reducer, "").replace(separator, "");
return `
${selector}
{
font-family: "${fontFamily}";
}`;
};
module.exports = {license, generateFontFace, generateLangRule};
/*
* This file is part of Adblock Plus <https://adblockplus.org/>,
* Copyright (C) 2006-present eyeo GmbH
*
* Adblock Plus is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* Adblock Plus is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
const localRange = require("local-range");
const fs = require("fs");
const path = require("path");
const {localesDir, inputDir, outputDir, fontToLocalesMap,
fontFile} = require("./config");
const {generateFontFace, license, generateLangRule} = require("./css");
const {promisify} = require("util");
const {ensureDir, cammelToSentence, getLastDir} = require("./utils");
const exec = promisify(require("child_process").exec);
const glob = promisify(require("glob").glob);
/**
* Uses local-range(see: https://www.npmjs.com/package/local-range) to generate
* unicode ranges.
* @param {Array} include locale directory names
* @returns {String} unicode ranges
*/
function getUnicodeRange(include)
{
const options = {
folder: path.resolve(localesDir),
include
};
return localRange.toSubsetRanges(options);
}
/**
* Generate font using fontTools (see: https://github.com/fonttools/fonttools)
* @param {String} inputFile directory with the font sources
* @param {String} outputFile font generation directory path
* @param {Array} locales locale directory names
* @returns {Array} output file, unicode range and passed locales
*/
function generateFont(inputFile, outputFile, locales)
{
return getUnicodeRange(locales).then((unicodeRange) =>
{
const {dir} = path.parse(outputFile);
ensureDir(dir);
const unicodes = `--unicodes=${unicodeRange}`;
const flavor = "--flavor=woff2";
const output = `--output-file=${outputFile}`;
return exec(`pyftsubset ${inputFile} ${unicodes} ${flavor} ${output}`).
then(() =>
{
// eslint-disable-next-line no-console
console.log(`${outputFile} is generated`);
return [outputFile, unicodeRange, locales];
});
});
}
glob(`${inputDir}/**/*.*`).then((fonts) =>
{
ensureDir(outputDir);
const fontGenerationPromises = [];
for (const inputFile of fonts)
{
const {base, name} = path.parse(inputFile);
const weight = getLastDir(inputFile);
const outputFile = path.join(outputDir, weight, name + ".woff2");
const locales = fontToLocalesMap[base];
fontGenerationPromises.push(generateFont(inputFile, outputFile, locales));
}
Promise.all(fontGenerationPromises).then((generatedFonts) =>
{
let cssFile = license;
const fontLocales = [];
for (const [filePath, unicodeRange, locales] of generatedFonts)
{
const {name} = path.parse(filePath);
const weight = getLastDir(filePath);
const fontName = cammelToSentence(name);
if (!fontLocales.some(fontLocale => fontLocale.fontName == fontName))
fontLocales.push({fontName, locales});
cssFile += generateFontFace(fontName, weight, filePath, unicodeRange);
}
for (const {fontName, locales} of fontLocales)
{
cssFile += generateLangRule(locales, fontName);
}
fs.writeFileSync(fontFile, cssFile);
// eslint-disable-next-line no-console
console.log(`${fontFile} is created`);
});
}).catch(console.error);
/*
* This file is part of Adblock Plus <https://adblockplus.org/>,
* Copyright (C) 2006-present eyeo GmbH
*
* Adblock Plus is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* Adblock Plus is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
const fs = require("fs");
const path = require("path");
/**
* Creates directory if one doesn't exists
* @param {String} dir directory to ensure
*/
const ensureDir = (dir) =>
{
// Ensure directory
if (!fs.existsSync(dir))
fs.mkdirSync(dir);
};
/**
* Convert cammelCase text into Sentence Case
* @param {String} text cammelCase text
* @returns {String} Sentence Case text
*/
const cammelToSentence = (text) =>
{
const result = text.replace(/([A-Z])/g, " $1").trim();
return result.charAt(0).toUpperCase() + result.slice(1);
};
/**
* @param {String} filePath path to the file
* @returns {String} Directory name where the file is located
*/
const getLastDir = (filePath) =>
{
return path.basename(path.dirname(filePath));
}
module.exports = {ensureDir, cammelToSentence, getLastDir};
......@@ -6,6 +6,7 @@
"$": "npm-dollar",
"dev-build": "npm run $ bundle && npm run $ dev-build",
"bundle": "npm run $ bundle",
"fonts-gen": "node build/font-generation/index.js",
"lint": "npm run $ lint",
"postinstall": "npm run bundle",
"start": "http-server & npm run watch",
......@@ -131,6 +132,7 @@
"browserify": "^16.2.2",
"document-register-element": "^1.11.0",
"hyperhtml-element": "^3.1.0",
"local-range": "^0.0.4",
"node-sass": "^4.9.3",
"npm-dollar": "^2.1.0",
"website-defaults": "github:adblockplus/website-defaults#255e4f1"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment