mirror of
https://github.com/lucide-icons/lucide.git
synced 2025-12-16 13:17:42 +01:00
Changed font creation process (#1413)
* Changed font creation process * Class name prefix Class name prefix added for backward compatibility. * Container option in workflow removed Removed the container option in github workflow lucide-font because it is not needed anymore, workflow was changed to nodejs only * Fixed whitespaces in package.json * Use releaseInformation instead of info.json * Added workflow step * Moved unicode numbers to convert function * Added locale argument to sort function * Delete pnpm-lock * Updated versions, recreated pnpm-lock * Updated dependencies --------- Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
This commit is contained in:
9
.github/workflows/lucide-font.yml
vendored
9
.github/workflows/lucide-font.yml
vendored
@@ -10,7 +10,6 @@ on:
|
||||
jobs:
|
||||
lucide-font:
|
||||
runs-on: ubuntu-latest
|
||||
container: ericfennis/lucide-font:latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3.4.1
|
||||
@@ -43,11 +42,11 @@ jobs:
|
||||
- name: Outline svg Icons
|
||||
run: pnpm build:outline-icons
|
||||
|
||||
- name: Create directory
|
||||
run: mkdir lucide-font
|
||||
- name: Install dependencies
|
||||
run: pnpm install --filter build-font
|
||||
|
||||
- name: Build font
|
||||
run: fontcustom compile "./outlined" -h -n "lucide" -o ./lucide-font -F
|
||||
- name: Create font in ./lucide-font
|
||||
run: pnpm build:font
|
||||
|
||||
- name: "Upload to Artifacts"
|
||||
uses: actions/upload-artifact@v1
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
"lucide-static": "pnpm --filter lucide-static",
|
||||
"build:icons": "node ./scripts/buildIcons.mjs --templateSrc ./packages/lucide/scripts/exportTemplate.mjs",
|
||||
"build:outline-icons": "pnpm --filter outline-svg start",
|
||||
"build:font": "pnpm --filter docs prebuild:releaseJson && pnpm --filter build-font start",
|
||||
"generate:supersprite": "node ./scripts/generateSuperSVG.mjs",
|
||||
"optimize": "node ./scripts/optimizeSvgs.mjs",
|
||||
"addjsons": "node scripts/addMissingIconJsonFiles.mjs",
|
||||
|
||||
2671
pnpm-lock.yaml
generated
2671
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
124
tools/build-font/main.mjs
Normal file
124
tools/build-font/main.mjs
Normal file
@@ -0,0 +1,124 @@
|
||||
import { readJson } from 'fs-extra/esm';
|
||||
import svgtofont from 'svgtofont';
|
||||
import getArgumentOptions from 'minimist';
|
||||
import path from 'path';
|
||||
|
||||
const fontName = 'lucide';
|
||||
const classNamePrefix = 'icon';
|
||||
const startUnicode = 57400;
|
||||
|
||||
const inputDir = path.join(process.cwd(), '../../', 'outlined');
|
||||
const cliArguments = getArgumentOptions(process.argv.slice(2));
|
||||
const { outputDir = 'lucide-font' } = cliArguments;
|
||||
const targetDir = path.join(process.cwd(), '../../', outputDir);
|
||||
const releaseMetaDataDir = path.join(process.cwd(), '../../', 'docs/.vitepress/data');
|
||||
const releaseMetaDataPath = path.resolve(releaseMetaDataDir, 'releaseMetaData.json');
|
||||
|
||||
const releaseMetaData = convertReleaseMetaData(await getReleaseMetaData());
|
||||
|
||||
async function getReleaseMetaData() {
|
||||
let releaseMetaData = {};
|
||||
try {
|
||||
releaseMetaData = await readJson(releaseMetaDataPath);
|
||||
} catch (err) {
|
||||
throw new Error('Execution stopped because no release information was found.');
|
||||
}
|
||||
return releaseMetaData;
|
||||
}
|
||||
|
||||
function convertReleaseMetaData(releaseMetaData) {
|
||||
return Object.entries(releaseMetaData)
|
||||
.map(([key, value]) => [key, addAttribute(value, 'name', key)])
|
||||
.map(([, value]) => value)
|
||||
.sort((a, b) => sortMultiple(a, b, [sortByCreatedReleaseDate, sortByName]))
|
||||
.map((value, index) => addAttribute(value, 'index', index))
|
||||
.map((value, index) => addAttribute(value, 'unicode', index + startUnicode));
|
||||
}
|
||||
|
||||
function addAttribute(obj, attribute, value) {
|
||||
obj[attribute] = value;
|
||||
return obj;
|
||||
}
|
||||
|
||||
function sortMultiple(a, b, collators = []) {
|
||||
const comparison = collators.shift()(a, b);
|
||||
if (comparison === 0 && collators.length > 0) return sortMultiple(a, b, collators);
|
||||
return comparison;
|
||||
}
|
||||
|
||||
function sortByCreatedReleaseDate(a, b) {
|
||||
const dates = [a, b].map((value) => new Date(value.createdRelease.date).valueOf());
|
||||
return (dates[0] > dates[1]) - (dates[0] < dates[1]);
|
||||
}
|
||||
|
||||
function sortByName(a, b) {
|
||||
return new Intl.Collator('en-US').compare(a.name, b.name);
|
||||
}
|
||||
|
||||
function getIconUnicode(name) {
|
||||
const { unicode } = releaseMetaData.find(({ name: iconname }) => iconname === name);
|
||||
return String.fromCharCode(unicode);
|
||||
}
|
||||
|
||||
async function init() {
|
||||
console.time('Font generation');
|
||||
try {
|
||||
await svgtofont({
|
||||
src: path.resolve(process.cwd(), inputDir),
|
||||
dist: path.resolve(process.cwd(), targetDir),
|
||||
// styleTemplates: path.resolve(process.cwd(), 'styles'), // Add different templates if needed
|
||||
fontName,
|
||||
classNamePrefix,
|
||||
css: {
|
||||
fontSize: 'inherit',
|
||||
},
|
||||
emptyDist: true,
|
||||
useCSSVars: false,
|
||||
outSVGReact: false,
|
||||
outSVGPath: false,
|
||||
svgicons2svgfont: {
|
||||
fontHeight: 1000, // At least 1000 is recommended
|
||||
normalize: false,
|
||||
},
|
||||
generateInfoData: true,
|
||||
website: {
|
||||
title: 'Lucide',
|
||||
logo: null,
|
||||
meta: {
|
||||
description: 'Lucide icons as TTF/EOT/WOFF/WOFF2/SVG.',
|
||||
keywords: 'Lucide,TTF,EOT,WOFF,WOFF2,SVG',
|
||||
},
|
||||
corners: {
|
||||
url: 'https://github.com/lucide-icons/lucide',
|
||||
width: 62, // default: 60
|
||||
height: 62, // default: 60
|
||||
bgColor: '#dc3545', // default: '#151513'
|
||||
},
|
||||
links: [
|
||||
{
|
||||
title: 'GitHub',
|
||||
url: 'https://github.com/lucide-icons/lucide',
|
||||
},
|
||||
{
|
||||
title: 'Feedback',
|
||||
url: 'https://github.com/lucide-icons/lucide/issues',
|
||||
},
|
||||
{
|
||||
title: 'Font Class',
|
||||
url: 'index.html',
|
||||
},
|
||||
{
|
||||
title: 'Unicode',
|
||||
url: 'unicode.html',
|
||||
},
|
||||
],
|
||||
},
|
||||
getIconUnicode,
|
||||
});
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
}
|
||||
console.timeEnd('Font generation');
|
||||
}
|
||||
|
||||
init();
|
||||
18
tools/build-font/package.json
Normal file
18
tools/build-font/package.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"name": "build-font",
|
||||
"private": true,
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"start": "node ./main.mjs"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"fs-extra": "^11.1.1",
|
||||
"minimist": "^1.2.8",
|
||||
"svgtofont": "^3.25.4"
|
||||
}
|
||||
}
|
||||
0
tools/build-font/styles/.gitkeep
Normal file
0
tools/build-font/styles/.gitkeep
Normal file
@@ -1,6 +1,5 @@
|
||||
import { promises as fs } from 'fs';
|
||||
import outlineStroke from 'svg-outline-stroke';
|
||||
import { parse, stringify } from 'svgson';
|
||||
import SVGFixer from 'oslllo-svg-fixer';
|
||||
import getArgumentOptions from 'minimist';
|
||||
import path from 'path';
|
||||
|
||||
@@ -9,31 +8,6 @@ const cliArguments = getArgumentOptions(process.argv.slice(2));
|
||||
const { outputDir = 'outlined' } = cliArguments;
|
||||
const targetDir = path.join(process.cwd(), '../../', outputDir);
|
||||
|
||||
function transformForward(node) {
|
||||
if (node.name === 'svg') {
|
||||
return {
|
||||
...node,
|
||||
attributes: {
|
||||
...node.attributes,
|
||||
width: 960,
|
||||
height: 960,
|
||||
},
|
||||
};
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
function transformBackwards(node) {
|
||||
if (node.name === 'svg') {
|
||||
const { width, height, ...attributes } = node.attributes;
|
||||
return {
|
||||
...node,
|
||||
attributes,
|
||||
};
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
async function init() {
|
||||
console.time('icon outliner');
|
||||
try {
|
||||
@@ -41,29 +15,10 @@ async function init() {
|
||||
await fs.mkdir(targetDir);
|
||||
} catch (error) {} // eslint-disable-line no-empty
|
||||
|
||||
const icons = (await fs.readdir(inputDir)).filter((file) => path.extname(file) === '.svg');
|
||||
const parsedIconNodes = await Promise.all(
|
||||
icons.map(async (file) => {
|
||||
const inputFilePath = path.resolve(process.cwd(), inputDir, file);
|
||||
const iconContent = await fs.readFile(inputFilePath);
|
||||
const iconNode = await parse(iconContent.toString(), {
|
||||
transformNode: transformForward,
|
||||
});
|
||||
return [file, iconNode];
|
||||
}),
|
||||
);
|
||||
|
||||
await Promise.all(
|
||||
parsedIconNodes.map(async ([file, iconNode]) => {
|
||||
const outlined = await outlineStroke(stringify(iconNode));
|
||||
const outlinedWithoutAttrs = await parse(outlined, {
|
||||
transformNode: transformBackwards,
|
||||
});
|
||||
|
||||
const filePath = path.join(targetDir, file);
|
||||
await fs.writeFile(filePath, stringify(outlinedWithoutAttrs));
|
||||
}),
|
||||
);
|
||||
await SVGFixer(inputDir, targetDir, {
|
||||
showProgressBar: true,
|
||||
traceResolution: 800,
|
||||
}).fix();
|
||||
|
||||
console.timeEnd('icon outliner');
|
||||
} catch (err) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "outline-svg",
|
||||
"private": true,
|
||||
"version": "1.0.0",
|
||||
"version": "2.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
@@ -11,8 +11,7 @@
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"minimist": "^1.2.6",
|
||||
"svg-outline-stroke": "^1.3.1",
|
||||
"svgson": "^5.2.1"
|
||||
"minimist": "^1.2.8",
|
||||
"oslllo-svg-fixer": "^2.2.0"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user