@fastkit/icon-font-gen 0.16.3 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { _ as IconFontGenError, d as DEFAULT_DEST_DIRNAME, i as generate, l as version, u as DEFAULT_CONFIG_FILENAME } from "./generator-qyNKkkyy.mjs";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { esbuildRequire, findPackageDir } from "@fastkit/node-util";
|
|
4
4
|
import { cac } from "cac";
|
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
|
-
import {
|
|
2
|
+
import { TinyLogger, createTinyError } from "@fastkit/tiny-logger";
|
|
3
3
|
import fs from "fs-extra";
|
|
4
4
|
import chokidar from "chokidar";
|
|
5
5
|
import { EV } from "@fastkit/ev";
|
|
6
|
-
import {
|
|
6
|
+
import { HashComparator } from "@fastkit/node-util";
|
|
7
|
+
//#region src/logger.ts
|
|
8
|
+
const name = "icon-font-gen";
|
|
9
|
+
const logger = new TinyLogger(name);
|
|
10
|
+
const IconFontGenError = createTinyError(name);
|
|
11
|
+
//#endregion
|
|
7
12
|
//#region src/schema.ts
|
|
8
13
|
/**
|
|
9
14
|
* Every format this package knows how to emit, in the order they are written to
|
|
@@ -34,15 +39,34 @@ const ICON_FONT_FORMAT_MAP = {
|
|
|
34
39
|
* @see {@link IconFontOptions.runtimeModule}
|
|
35
40
|
*/
|
|
36
41
|
const DEFAULT_ICON_FONT_RUNTIME_MODULE = "@fastkit/icon-font";
|
|
42
|
+
/**
|
|
43
|
+
* Removed source sentinel.
|
|
44
|
+
*
|
|
45
|
+
* `src: '@mdi'` used to mean "find `@mdi/svg`, and `pnpm add` it if it is not
|
|
46
|
+
* there", then build a font from its SVGs. Installing a package as a side effect
|
|
47
|
+
* of a build is a bad bargain wherever the build is not also the place
|
|
48
|
+
* dependencies are managed: in a container image built with `--prod`, where that
|
|
49
|
+
* devDependency was pruned, it failed with `ERR_PNPM_INCLUDED_DEPS_CONFLICT`
|
|
50
|
+
* rather than anything a reader could act on.
|
|
51
|
+
*
|
|
52
|
+
* `@fastkit/vui` now ships a Material Design Icons webfont it generated at its
|
|
53
|
+
* own build time, so nothing has to build one at a consumer's, and this package
|
|
54
|
+
* has no reason to know that `@mdi/svg` exists. `src` is a directory of SVGs,
|
|
55
|
+
* with no special cases.
|
|
56
|
+
*/
|
|
57
|
+
const REMOVED_MDI_SENTINEL = "@mdi";
|
|
37
58
|
async function resolveRawIconFontEntry(rootDir, rawEntry) {
|
|
38
59
|
const entry = { ...rawEntry };
|
|
39
|
-
if (entry.src ===
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
60
|
+
if (entry.src === REMOVED_MDI_SENTINEL) throw new IconFontGenError([
|
|
61
|
+
`The \`src: '${REMOVED_MDI_SENTINEL}'\` sentinel has been removed.`,
|
|
62
|
+
"",
|
|
63
|
+
"`@fastkit/vui` ships a pre-generated Material Design Icons webfont, so a",
|
|
64
|
+
"project using it needs no entry at all. Using this generator on its own,",
|
|
65
|
+
"point `src` at a directory of SVG files -- for MDI, install `@mdi/svg`",
|
|
66
|
+
"yourself and name its `svg` directory:",
|
|
67
|
+
"",
|
|
68
|
+
" { src: './node_modules/@mdi/svg/svg', name: 'mdi', fontHeight: 512, descent: 64 }"
|
|
69
|
+
].join("\n"));
|
|
46
70
|
const name = entry.name || path.basename(entry.src);
|
|
47
71
|
const fontName = entry.fontName || `${name}-icon`;
|
|
48
72
|
const dest = path.join(rootDir, name);
|
|
@@ -57,22 +81,14 @@ async function resolveRawIconFontEntry(rootDir, rawEntry) {
|
|
|
57
81
|
display
|
|
58
82
|
};
|
|
59
83
|
}
|
|
60
|
-
function findOrInstallMDI() {
|
|
61
|
-
return installPackage("@mdi/svg", { dev: true });
|
|
62
|
-
}
|
|
63
84
|
const DEFAULT_CONFIG_FILENAME = "icon-font.config";
|
|
64
85
|
const DEFAULT_DEST_DIRNAME = ".icon-font";
|
|
65
86
|
function ceateIconFontConfig(options) {
|
|
66
87
|
return options;
|
|
67
88
|
}
|
|
68
89
|
//#endregion
|
|
69
|
-
//#region src/logger.ts
|
|
70
|
-
const name = "icon-font-gen";
|
|
71
|
-
const logger = new TinyLogger(name);
|
|
72
|
-
const IconFontGenError = createTinyError(name);
|
|
73
|
-
//#endregion
|
|
74
90
|
//#region package.json
|
|
75
|
-
var version = "0.
|
|
91
|
+
var version = "1.0.0";
|
|
76
92
|
//#endregion
|
|
77
93
|
//#region src/generator.ts
|
|
78
94
|
const DEFAULT_OPTIONS = {
|
|
@@ -331,6 +347,6 @@ var IconFontRunner = class extends EV {
|
|
|
331
347
|
}
|
|
332
348
|
};
|
|
333
349
|
//#endregion
|
|
334
|
-
export {
|
|
350
|
+
export { IconFontGenError as _, generateEntry as a, toHashInputs as c, DEFAULT_DEST_DIRNAME as d, DEFAULT_ICON_FONT_RUNTIME_MODULE as f, resolveRawIconFontEntry as g, ceateIconFontConfig as h, generate as i, version as l, ICON_FONT_FORMAT_MAP as m, IconFontRunner as n, generateIndex as o, ICON_FONT_FORMATS as p, IconFontRunnerItem as r, mergeDefaults as s, DEFAULT_OPTIONS as t, DEFAULT_CONFIG_FILENAME as u };
|
|
335
351
|
|
|
336
|
-
//# sourceMappingURL=generator-
|
|
352
|
+
//# sourceMappingURL=generator-qyNKkkyy.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generator-qyNKkkyy.mjs","names":["pkg.version"],"sources":["../src/logger.ts","../src/schema.ts","../package.json","../src/generator.ts"],"sourcesContent":["import { TinyLogger, createTinyError } from '@fastkit/tiny-logger';\n\nconst name = 'icon-font-gen';\n\nexport const logger = new TinyLogger(name);\n\nexport const IconFontGenError = createTinyError(name);\n","import type { webfont } from 'webfont';\nimport path from 'node:path';\nimport { IconFontGenError } from './logger';\n\n/**\n * Derived from webfont's public signature. webfont 12 added an `exports` map\n * that only publishes the package root, so its internal `dist` type paths are no\n * longer reachable. Tracking the upstream union means a format added there shows\n * up here as a missing key in {@link ICON_FONT_FORMAT_MAP}.\n */\nexport type IconFontFormat = NonNullable<\n NonNullable<Parameters<typeof webfont>[0]>['formats']\n>[number];\n\n/**\n * Every format this package knows how to emit, in the order they are written to\n * the `@font-face` `src` list. Only the formats actually requested through\n * `formats` are generated, so appending to this list does not change the output\n * of an existing configuration.\n */\nexport const ICON_FONT_FORMATS: IconFontFormat[] = [\n 'eot',\n 'woff',\n 'woff2',\n 'svg',\n 'ttf',\n 'otf',\n];\n\nexport const ICON_FONT_FORMAT_MAP: Record<IconFontFormat, string> = {\n eot: 'embedded-opentype',\n woff2: 'woff2',\n woff: 'woff',\n ttf: 'truetype',\n svg: 'svg',\n otf: 'opentype',\n};\n\nexport interface IconFontSettings {\n fixedWidth?: boolean;\n centerHorizontally?: boolean;\n normalize?: boolean;\n fontHeight?: number;\n round?: number;\n descent?: number;\n disablePrefix?: boolean;\n absolutePath?: boolean;\n addHashInFontUrl?: boolean;\n}\n\nexport interface IconFontEntry extends IconFontSettings {\n name: string;\n fontName: string;\n formats?: IconFontFormat[];\n startUnicode?: number;\n prefix: string;\n src: string;\n dest: string;\n display: 'block' | 'swap';\n}\n\nexport interface RawIconFontEntry extends Omit<\n IconFontEntry,\n 'name' | 'fontName' | 'prefix' | 'dest' | 'display'\n> {\n name?: string;\n fontName?: string;\n /**\n * @default block\n */\n display?: 'block' | 'swap';\n}\n\n// export type RawIconFontOptions = IconFontEntry | IconFontEntry[];\n\n/**\n * Module the generated code imports the icon-name registry from, and augments\n * with the names it generated.\n *\n * @see {@link IconFontOptions.runtimeModule}\n */\nexport const DEFAULT_ICON_FONT_RUNTIME_MODULE = '@fastkit/icon-font';\n\nexport interface IconFontOptions {\n entries: RawIconFontEntry[];\n dest: string;\n /**\n * Module the generated code imports `registerIconNames` / `IconName` from,\n * and whose `IconNameMap` it augments with the generated names.\n *\n * The generated files live in the *consuming* project, so this specifier is\n * resolved from there -- and pnpm places into a project's `node_modules` only\n * what the project itself declares, not what a peer declaration asks for. So\n * whatever this names becomes a package the project has to declare.\n *\n * Point it at a module the project already declares and that re-exports\n * `@fastkit/icon-font` -- a UI kit built on it, say -- and the project needs\n * nothing beyond that kit. Module augmentation follows a re-export to the\n * interface it aliases, so `IconNameMap` still merges into the one\n * `@fastkit/icon-font` declares, and every type derived from it agrees.\n *\n * @default '@fastkit/icon-font'\n */\n runtimeModule?: string;\n}\n\n/**\n * Removed source sentinel.\n *\n * `src: '@mdi'` used to mean \"find `@mdi/svg`, and `pnpm add` it if it is not\n * there\", then build a font from its SVGs. Installing a package as a side effect\n * of a build is a bad bargain wherever the build is not also the place\n * dependencies are managed: in a container image built with `--prod`, where that\n * devDependency was pruned, it failed with `ERR_PNPM_INCLUDED_DEPS_CONFLICT`\n * rather than anything a reader could act on.\n *\n * `@fastkit/vui` now ships a Material Design Icons webfont it generated at its\n * own build time, so nothing has to build one at a consumer's, and this package\n * has no reason to know that `@mdi/svg` exists. `src` is a directory of SVGs,\n * with no special cases.\n */\nconst REMOVED_MDI_SENTINEL = '@mdi';\n\nexport async function resolveRawIconFontEntry(\n rootDir: string,\n rawEntry: RawIconFontEntry,\n): Promise<IconFontEntry> {\n const entry = {\n ...rawEntry,\n };\n\n if (entry.src === REMOVED_MDI_SENTINEL) {\n // Worth naming explicitly: left alone, `'@mdi'` is just a directory that\n // does not exist, and this generator skips an entry whose source is\n // missing -- so the failure mode is a silently empty font, not an error.\n throw new IconFontGenError(\n [\n `The \\`src: '${REMOVED_MDI_SENTINEL}'\\` sentinel has been removed.`,\n '',\n '`@fastkit/vui` ships a pre-generated Material Design Icons webfont, so a',\n 'project using it needs no entry at all. Using this generator on its own,',\n 'point `src` at a directory of SVG files -- for MDI, install `@mdi/svg`',\n 'yourself and name its `svg` directory:',\n '',\n \" { src: './node_modules/@mdi/svg/svg', name: 'mdi', fontHeight: 512, descent: 64 }\",\n ].join('\\n'),\n );\n }\n\n const name = entry.name || path.basename(entry.src);\n const fontName = entry.fontName || `${name}-icon`;\n const dest = path.join(rootDir, name);\n const prefix = entry.disablePrefix ? '' : `${name}-`;\n const display = entry.display || 'block';\n return {\n ...entry,\n name,\n fontName,\n prefix,\n dest,\n display,\n };\n}\n\nexport const DEFAULT_CONFIG_FILENAME = 'icon-font.config';\n\nexport const DEFAULT_DEST_DIRNAME = '.icon-font';\n\nexport interface IconFontConfig extends Omit<IconFontOptions, 'dest'> {\n dest?: string;\n}\n\nexport function ceateIconFontConfig(options: IconFontConfig) {\n return options;\n}\n","","import fs from 'fs-extra';\nimport path from 'node:path';\nimport chokidar, { FSWatcher } from 'chokidar';\nimport { EV } from '@fastkit/ev';\nimport { HashComparator } from '@fastkit/node-util';\nimport { UnPromisify } from '@fastkit/helpers';\nimport type webfont from 'webfont';\nimport { logger } from './logger';\nimport pkg from '../package.json';\nimport {\n IconFontOptions,\n IconFontEntry,\n RawIconFontEntry,\n resolveRawIconFontEntry,\n ICON_FONT_FORMATS,\n IconFontFormat,\n ICON_FONT_FORMAT_MAP,\n DEFAULT_ICON_FONT_RUNTIME_MODULE,\n} from './schema';\n\nexport type IconFontEntryResult = {\n entry: IconFontEntry;\n result?: UnPromisify<ReturnType<typeof webfont>>;\n};\n\nexport const DEFAULT_OPTIONS: Partial<IconFontEntry> = {\n formats: ['woff2'],\n fixedWidth: true,\n normalize: true,\n};\n\nconst BANNER = `\n/**\n * This is auto generated file.\n * Do not edit !!!\n *\n * @see: https://github.com/dadajam4/fastkit/tree/main/packages/icon-font-gen\n */\n`.trim();\n\nexport function mergeDefaults(entry: IconFontEntry): IconFontEntry {\n return {\n ...DEFAULT_OPTIONS,\n ...entry,\n };\n}\n\nasync function generateTS(\n entry: IconFontEntry,\n ids: string[],\n runtimeModule: string,\n) {\n const code = `\n/* eslint-disable */\n// @ts-nocheck\n${BANNER}\nimport type { IconName, IconNameMap } from '${runtimeModule}';\nimport { registerIconNames } from '${runtimeModule}';\ndeclare module \"${runtimeModule}\" {\n export interface IconNameMap {\n${ids.map((id) => ` '${id}': true,`).join('\\n')}\n }\n}\nexport const ICON_NAMES = registerIconNames([\n ${ids.map((id) => `'${id}'`).join(',\\n ')}\n]);\nexport type { IconName, IconNameMap } from '${runtimeModule}';\n `.trim();\n const fileName = `${entry.name || 'icons'}.ts`;\n const dest = path.resolve(entry.dest, fileName);\n await fs.writeFile(dest, code);\n return {\n fileName,\n dest,\n code,\n };\n}\n\n/**\n * What the generated output depends on besides the contents of `src`.\n *\n * The source files are hashed separately; this covers the rest, so that an\n * upgrade of this package — or a change to an option — regenerates instead of\n * leaving the previous output in place. Without it a project whose icons had not\n * changed kept output from an older generator indefinitely, and the only way out\n * was to delete the destination by hand.\n *\n * `src` and `dest` are left out on purpose. `src` is already covered by its own\n * content hash, `dest` holds the meta file so a change to it has nothing to\n * compare against anyway, and keeping absolute paths out of the fingerprint\n * keeps the meta file portable between machines and CI.\n */\nexport function toHashInputs(\n options: IconFontEntry,\n runtimeModule: string = DEFAULT_ICON_FONT_RUNTIME_MODULE,\n) {\n const { src, dest, ...rest } = options;\n return { generator: pkg.version, runtimeModule, options: rest };\n}\n\nexport async function generateEntry(\n entry: IconFontEntry,\n runtimeModule: string = DEFAULT_ICON_FONT_RUNTIME_MODULE,\n): Promise<IconFontEntryResult> {\n const options = mergeDefaults(entry);\n\n // @TODO support empty prefix\n // const namePrefix = options.name;\n const cssPrefix = `icon-${options.prefix}`;\n\n const hash = new HashComparator(options.src, options.dest, {\n inputs: toHashInputs(options, runtimeModule),\n });\n const srcHash = await hash.hasChanged();\n if (!srcHash) {\n logger.info(`Has not changed files. Skip process. >>> ${options.src}`);\n return { entry };\n }\n\n await fs.ensureDir(options.dest);\n\n const { webfont } = await import('webfont');\n\n // const { startUnicode = 0xea01 } = options;\n const { startUnicode = 0xba01 } = options;\n\n let i = startUnicode;\n\n const result = await webfont({\n files: options.src,\n fontName: options.fontName,\n formats: options.formats,\n fixedWidth: options.fixedWidth,\n centerHorizontally: options.centerHorizontally,\n normalize: options.normalize,\n fontHeight: options.fontHeight,\n round: options.round,\n descent: options.descent,\n addHashInFontUrl: options.addHashInFontUrl,\n glyphTransformFn: (obj) => {\n const char = String.fromCodePoint(i);\n obj.unicode = [char];\n i++;\n return obj;\n },\n });\n\n const buildedFormats: { format: IconFontFormat; code: string | Buffer }[] =\n [];\n ICON_FONT_FORMATS.forEach((format) => {\n const code = result[format];\n if (code) {\n buildedFormats.push({ format, code });\n }\n });\n\n await Promise.all(\n buildedFormats.map(({ format, code }) =>\n fs.writeFile(\n path.join(options.dest, `${options.name}.${format}`),\n code as string | Uint8Array,\n ),\n ),\n );\n\n const glyphs: { name: string; code: string }[] = [];\n\n result.glyphsData!.forEach(({ metadata }) => {\n if (!metadata) return;\n const { name, unicode } = metadata;\n if (!unicode) {\n return;\n }\n\n const code = unicode[0].charCodeAt(0).toString(16);\n glyphs.push({ name, code });\n });\n\n const urlPath = options.absolutePath ? options.dest : '.';\n const hashSuffix = options.addHashInFontUrl ? `?${Date.now()}` : '';\n const src = buildedFormats\n .map(\n ({ format }) =>\n `url(\"${urlPath}/${options.name}.${format}${hashSuffix}\") format(\"${ICON_FONT_FORMAT_MAP[format]}\")`,\n )\n .join(',');\n\n const cssCode = `/* stylelint-disable */\n@font-face {\n font-family: \"${options.fontName}\";\n font-display: ${options.display};\n font-style: normal;\n font-weight: 400;\n src: ${src};\n}\n\ni[class^=\"${cssPrefix}\"]:before, i[class*=\" ${cssPrefix}\"]:before {\n font-family: ${options.fontName} !important;\n font-style: normal;\n font-weight: normal !important;\n font-variant: normal;\n text-transform: none;\n text-rendering: auto;\n line-height: 1;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n${glyphs\n .map(\n ({ name, code }) => `\n.${cssPrefix}${name}:before { content: \"\\\\${code}\"; }\n `,\n )\n .join('\\n')}\n `;\n await fs.writeFile(path.join(options.dest, `${options.name}.css`), cssCode);\n\n // const prefix = options.prefix ? `${options.prefix}-` : '';\n const ids = glyphs.map(({ name }) => `${options.prefix}${name}`);\n await generateTS(options, ids, runtimeModule);\n await hash.commit(srcHash);\n return {\n entry,\n result,\n };\n}\n\nexport async function generateIndex(\n dest: string,\n entries: IconFontEntry[],\n runtimeModule: string = DEFAULT_ICON_FONT_RUNTIME_MODULE,\n) {\n const names = entries.map(({ name }) => name);\n const tsCode = `\n/* eslint-disable */\n// @ts-nocheck\nimport './index.css';\n${BANNER}\n${names\n .map(\n (name, index) =>\n // `import { IconName as IconName_${index}, IconNameMap as IconNameMap_${index} } from './${name}/${name}';`,\n `import './${name}/${name}';`,\n )\n .join('\\n')}\nexport type { IconName } from '${runtimeModule}';\nexport { ICON_NAMES } from '${runtimeModule}';\n `.trim();\n const tsDest = path.join(dest, 'index.ts');\n await fs.writeFile(tsDest, tsCode);\n\n const cssCode = `\n/* stylelint-disable */\n${BANNER}\n${names.map((name) => `@import './${name}/${name}.css';`).join('\\n')}\n `.trim();\n const cssDest = path.join(dest, 'index.css');\n await fs.writeFile(cssDest, cssCode);\n}\n\nexport async function generate(opts: IconFontOptions) {\n const runtimeModule = opts.runtimeModule ?? DEFAULT_ICON_FONT_RUNTIME_MODULE;\n await fs.emptyDir(opts.dest);\n const results = await Promise.all(\n opts.entries.map((entry) =>\n resolveRawIconFontEntry(opts.dest, entry).then((_entry) =>\n generateEntry(_entry, runtimeModule),\n ),\n ),\n );\n const entries = results.map(({ entry }) => entry);\n await generateIndex(opts.dest, entries, runtimeModule);\n}\n\nexport class IconFontRunnerItem extends EV<{\n build: IconFontEntryResult;\n}> {\n readonly entry: RawIconFontEntry;\n\n readonly ctx: IconFontRunner;\n\n private _resolveEntryPromise?: Promise<IconFontEntry>;\n\n private _watcher: FSWatcher | null = null;\n\n watchMode: boolean;\n\n // get name() {\n // return this.entry.name;\n // }\n\n constructor(ctx: IconFontRunner, entry: RawIconFontEntry, watch = false) {\n super();\n this.ctx = ctx;\n this.entry = entry;\n this.watchMode = watch;\n this.build = this.build.bind(this);\n }\n\n async run() {\n const result = await this.build();\n if (this.watchMode && !this._watcher) {\n const watchDir = path.resolve(this.entry.src);\n this._watcher = chokidar.watch(watchDir, { ignoreInitial: true });\n this._watcher.on('all', this.build);\n }\n return result;\n }\n\n resolveEntry() {\n if (!this._resolveEntryPromise) {\n this._resolveEntryPromise = resolveRawIconFontEntry(\n this.ctx.dest,\n this.entry,\n );\n }\n return this._resolveEntryPromise;\n }\n\n async build() {\n const entry = await this.resolveEntry();\n const result = await generateEntry(entry, this.ctx.runtimeModule);\n this.emit('build', result);\n return { entry };\n }\n\n destroy() {\n if (this._watcher) {\n this._watcher.close();\n this._watcher = null;\n }\n this.offAll();\n if (this.ctx) {\n delete (this as any).ctx;\n }\n }\n}\n\nexport class IconFontRunner extends EV<{\n build: {\n item: IconFontRunnerItem;\n result: IconFontEntryResult;\n };\n}> {\n readonly items: IconFontRunnerItem[] = [];\n\n readonly dest: string;\n\n /** @see {@link IconFontOptions.runtimeModule} */\n readonly runtimeModule: string;\n\n constructor(opts: IconFontOptions, watch?: boolean) {\n super();\n\n this.dest = opts.dest;\n this.runtimeModule = opts.runtimeModule ?? DEFAULT_ICON_FONT_RUNTIME_MODULE;\n\n opts.entries.forEach((entry) => {\n const item = new IconFontRunnerItem(this, entry, watch);\n item.on('build', (result) => {\n this.emit('build', { item, result });\n });\n this.items.push(item);\n });\n }\n\n async buildIndex() {\n const entries = await Promise.all(\n this.items.map((item) => item.resolveEntry()),\n );\n return generateIndex(this.dest, entries, this.runtimeModule);\n }\n\n async run() {\n await fs.ensureDir(this.dest);\n await Promise.all([\n this.buildIndex(),\n Promise.all(this.items.map((item) => item.run())),\n ]);\n }\n\n destroy() {\n this.items.forEach((item) => item.destroy());\n this.items.length = 0;\n this.offAll();\n delete (this as any)._opts;\n }\n}\n"],"mappings":"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"}
|
package/dist/icon-font-gen.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { a as generateEntry, c as toHashInputs, d as DEFAULT_DEST_DIRNAME, f as DEFAULT_ICON_FONT_RUNTIME_MODULE, g as resolveRawIconFontEntry, h as ceateIconFontConfig, i as generate, m as ICON_FONT_FORMAT_MAP, n as IconFontRunner, o as generateIndex, p as ICON_FONT_FORMATS, r as IconFontRunnerItem, s as mergeDefaults, t as DEFAULT_OPTIONS, u as DEFAULT_CONFIG_FILENAME } from "./generator-qyNKkkyy.mjs";
|
|
2
2
|
export { DEFAULT_CONFIG_FILENAME, DEFAULT_DEST_DIRNAME, DEFAULT_ICON_FONT_RUNTIME_MODULE, DEFAULT_OPTIONS, ICON_FONT_FORMATS, ICON_FONT_FORMAT_MAP, IconFontRunner, IconFontRunnerItem, ceateIconFontConfig, generate, generateEntry, generateIndex, mergeDefaults, resolveRawIconFontEntry, toHashInputs };
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"generator-bCFFCSuU.mjs","names":["pkg.version"],"sources":["../src/schema.ts","../src/logger.ts","../package.json","../src/generator.ts"],"sourcesContent":["import type { webfont } from 'webfont';\nimport path from 'node:path';\nimport { installPackage } from '@fastkit/node-util';\n\n/**\n * Derived from webfont's public signature. webfont 12 added an `exports` map\n * that only publishes the package root, so its internal `dist` type paths are no\n * longer reachable. Tracking the upstream union means a format added there shows\n * up here as a missing key in {@link ICON_FONT_FORMAT_MAP}.\n */\nexport type IconFontFormat = NonNullable<\n NonNullable<Parameters<typeof webfont>[0]>['formats']\n>[number];\n\n/**\n * Every format this package knows how to emit, in the order they are written to\n * the `@font-face` `src` list. Only the formats actually requested through\n * `formats` are generated, so appending to this list does not change the output\n * of an existing configuration.\n */\nexport const ICON_FONT_FORMATS: IconFontFormat[] = [\n 'eot',\n 'woff',\n 'woff2',\n 'svg',\n 'ttf',\n 'otf',\n];\n\nexport const ICON_FONT_FORMAT_MAP: Record<IconFontFormat, string> = {\n eot: 'embedded-opentype',\n woff2: 'woff2',\n woff: 'woff',\n ttf: 'truetype',\n svg: 'svg',\n otf: 'opentype',\n};\n\nexport interface IconFontSettings {\n fixedWidth?: boolean;\n centerHorizontally?: boolean;\n normalize?: boolean;\n fontHeight?: number;\n round?: number;\n descent?: number;\n disablePrefix?: boolean;\n absolutePath?: boolean;\n addHashInFontUrl?: boolean;\n}\n\nexport interface IconFontEntry extends IconFontSettings {\n name: string;\n fontName: string;\n formats?: IconFontFormat[];\n startUnicode?: number;\n prefix: string;\n src: string;\n dest: string;\n display: 'block' | 'swap';\n}\n\nexport interface RawIconFontEntry extends Omit<\n IconFontEntry,\n 'name' | 'fontName' | 'prefix' | 'dest' | 'display'\n> {\n name?: string;\n fontName?: string;\n /**\n * @default block\n */\n display?: 'block' | 'swap';\n}\n\n// export type RawIconFontOptions = IconFontEntry | IconFontEntry[];\n\n/**\n * Module the generated code imports the icon-name registry from, and augments\n * with the names it generated.\n *\n * @see {@link IconFontOptions.runtimeModule}\n */\nexport const DEFAULT_ICON_FONT_RUNTIME_MODULE = '@fastkit/icon-font';\n\nexport interface IconFontOptions {\n entries: RawIconFontEntry[];\n dest: string;\n /**\n * Module the generated code imports `registerIconNames` / `IconName` from,\n * and whose `IconNameMap` it augments with the generated names.\n *\n * The generated files live in the *consuming* project, so this specifier is\n * resolved from there -- and pnpm places into a project's `node_modules` only\n * what the project itself declares, not what a peer declaration asks for. So\n * whatever this names becomes a package the project has to declare.\n *\n * Point it at a module the project already declares and that re-exports\n * `@fastkit/icon-font` -- a UI kit built on it, say -- and the project needs\n * nothing beyond that kit. Module augmentation follows a re-export to the\n * interface it aliases, so `IconNameMap` still merges into the one\n * `@fastkit/icon-font` declares, and every type derived from it agrees.\n *\n * @default '@fastkit/icon-font'\n */\n runtimeModule?: string;\n}\n\nexport async function resolveRawIconFontEntry(\n rootDir: string,\n rawEntry: RawIconFontEntry,\n): Promise<IconFontEntry> {\n const entry = {\n ...rawEntry,\n };\n\n // mdi support\n if (entry.src === '@mdi') {\n const installedDir = await findOrInstallMDI();\n entry.src = path.join(installedDir, 'svg');\n if (entry.fontHeight == null) {\n entry.fontHeight = 512;\n }\n if (entry.descent == null) {\n entry.descent = 64;\n }\n if (entry.name == null) {\n entry.name = 'mdi';\n }\n }\n\n const name = entry.name || path.basename(entry.src);\n const fontName = entry.fontName || `${name}-icon`;\n const dest = path.join(rootDir, name);\n const prefix = entry.disablePrefix ? '' : `${name}-`;\n const display = entry.display || 'block';\n return {\n ...entry,\n name,\n fontName,\n prefix,\n dest,\n display,\n };\n}\n\nfunction findOrInstallMDI() {\n return installPackage('@mdi/svg', { dev: true });\n}\n\nexport const DEFAULT_CONFIG_FILENAME = 'icon-font.config';\n\nexport const DEFAULT_DEST_DIRNAME = '.icon-font';\n\nexport interface IconFontConfig extends Omit<IconFontOptions, 'dest'> {\n dest?: string;\n}\n\nexport function ceateIconFontConfig(options: IconFontConfig) {\n return options;\n}\n","import { TinyLogger, createTinyError } from '@fastkit/tiny-logger';\n\nconst name = 'icon-font-gen';\n\nexport const logger = new TinyLogger(name);\n\nexport const IconFontGenError = createTinyError(name);\n","","import fs from 'fs-extra';\nimport path from 'node:path';\nimport chokidar, { FSWatcher } from 'chokidar';\nimport { EV } from '@fastkit/ev';\nimport { HashComparator } from '@fastkit/node-util';\nimport { UnPromisify } from '@fastkit/helpers';\nimport type webfont from 'webfont';\nimport { logger } from './logger';\nimport pkg from '../package.json';\nimport {\n IconFontOptions,\n IconFontEntry,\n RawIconFontEntry,\n resolveRawIconFontEntry,\n ICON_FONT_FORMATS,\n IconFontFormat,\n ICON_FONT_FORMAT_MAP,\n DEFAULT_ICON_FONT_RUNTIME_MODULE,\n} from './schema';\n\nexport type IconFontEntryResult = {\n entry: IconFontEntry;\n result?: UnPromisify<ReturnType<typeof webfont>>;\n};\n\nexport const DEFAULT_OPTIONS: Partial<IconFontEntry> = {\n formats: ['woff2'],\n fixedWidth: true,\n normalize: true,\n};\n\nconst BANNER = `\n/**\n * This is auto generated file.\n * Do not edit !!!\n *\n * @see: https://github.com/dadajam4/fastkit/tree/main/packages/icon-font-gen\n */\n`.trim();\n\nexport function mergeDefaults(entry: IconFontEntry): IconFontEntry {\n return {\n ...DEFAULT_OPTIONS,\n ...entry,\n };\n}\n\nasync function generateTS(\n entry: IconFontEntry,\n ids: string[],\n runtimeModule: string,\n) {\n const code = `\n/* eslint-disable */\n// @ts-nocheck\n${BANNER}\nimport type { IconName, IconNameMap } from '${runtimeModule}';\nimport { registerIconNames } from '${runtimeModule}';\ndeclare module \"${runtimeModule}\" {\n export interface IconNameMap {\n${ids.map((id) => ` '${id}': true,`).join('\\n')}\n }\n}\nexport const ICON_NAMES = registerIconNames([\n ${ids.map((id) => `'${id}'`).join(',\\n ')}\n]);\nexport type { IconName, IconNameMap } from '${runtimeModule}';\n `.trim();\n const fileName = `${entry.name || 'icons'}.ts`;\n const dest = path.resolve(entry.dest, fileName);\n await fs.writeFile(dest, code);\n return {\n fileName,\n dest,\n code,\n };\n}\n\n/**\n * What the generated output depends on besides the contents of `src`.\n *\n * The source files are hashed separately; this covers the rest, so that an\n * upgrade of this package — or a change to an option — regenerates instead of\n * leaving the previous output in place. Without it a project whose icons had not\n * changed kept output from an older generator indefinitely, and the only way out\n * was to delete the destination by hand.\n *\n * `src` and `dest` are left out on purpose. `src` is already covered by its own\n * content hash, `dest` holds the meta file so a change to it has nothing to\n * compare against anyway, and keeping absolute paths out of the fingerprint\n * keeps the meta file portable between machines and CI.\n */\nexport function toHashInputs(\n options: IconFontEntry,\n runtimeModule: string = DEFAULT_ICON_FONT_RUNTIME_MODULE,\n) {\n const { src, dest, ...rest } = options;\n return { generator: pkg.version, runtimeModule, options: rest };\n}\n\nexport async function generateEntry(\n entry: IconFontEntry,\n runtimeModule: string = DEFAULT_ICON_FONT_RUNTIME_MODULE,\n): Promise<IconFontEntryResult> {\n const options = mergeDefaults(entry);\n\n // @TODO support empty prefix\n // const namePrefix = options.name;\n const cssPrefix = `icon-${options.prefix}`;\n\n const hash = new HashComparator(options.src, options.dest, {\n inputs: toHashInputs(options, runtimeModule),\n });\n const srcHash = await hash.hasChanged();\n if (!srcHash) {\n logger.info(`Has not changed files. Skip process. >>> ${options.src}`);\n return { entry };\n }\n\n await fs.ensureDir(options.dest);\n\n const { webfont } = await import('webfont');\n\n // const { startUnicode = 0xea01 } = options;\n const { startUnicode = 0xba01 } = options;\n\n let i = startUnicode;\n\n const result = await webfont({\n files: options.src,\n fontName: options.fontName,\n formats: options.formats,\n fixedWidth: options.fixedWidth,\n centerHorizontally: options.centerHorizontally,\n normalize: options.normalize,\n fontHeight: options.fontHeight,\n round: options.round,\n descent: options.descent,\n addHashInFontUrl: options.addHashInFontUrl,\n glyphTransformFn: (obj) => {\n const char = String.fromCodePoint(i);\n obj.unicode = [char];\n i++;\n return obj;\n },\n });\n\n const buildedFormats: { format: IconFontFormat; code: string | Buffer }[] =\n [];\n ICON_FONT_FORMATS.forEach((format) => {\n const code = result[format];\n if (code) {\n buildedFormats.push({ format, code });\n }\n });\n\n await Promise.all(\n buildedFormats.map(({ format, code }) =>\n fs.writeFile(\n path.join(options.dest, `${options.name}.${format}`),\n code as string | Uint8Array,\n ),\n ),\n );\n\n const glyphs: { name: string; code: string }[] = [];\n\n result.glyphsData!.forEach(({ metadata }) => {\n if (!metadata) return;\n const { name, unicode } = metadata;\n if (!unicode) {\n return;\n }\n\n const code = unicode[0].charCodeAt(0).toString(16);\n glyphs.push({ name, code });\n });\n\n const urlPath = options.absolutePath ? options.dest : '.';\n const hashSuffix = options.addHashInFontUrl ? `?${Date.now()}` : '';\n const src = buildedFormats\n .map(\n ({ format }) =>\n `url(\"${urlPath}/${options.name}.${format}${hashSuffix}\") format(\"${ICON_FONT_FORMAT_MAP[format]}\")`,\n )\n .join(',');\n\n const cssCode = `/* stylelint-disable */\n@font-face {\n font-family: \"${options.fontName}\";\n font-display: ${options.display};\n font-style: normal;\n font-weight: 400;\n src: ${src};\n}\n\ni[class^=\"${cssPrefix}\"]:before, i[class*=\" ${cssPrefix}\"]:before {\n font-family: ${options.fontName} !important;\n font-style: normal;\n font-weight: normal !important;\n font-variant: normal;\n text-transform: none;\n text-rendering: auto;\n line-height: 1;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n${glyphs\n .map(\n ({ name, code }) => `\n.${cssPrefix}${name}:before { content: \"\\\\${code}\"; }\n `,\n )\n .join('\\n')}\n `;\n await fs.writeFile(path.join(options.dest, `${options.name}.css`), cssCode);\n\n // const prefix = options.prefix ? `${options.prefix}-` : '';\n const ids = glyphs.map(({ name }) => `${options.prefix}${name}`);\n await generateTS(options, ids, runtimeModule);\n await hash.commit(srcHash);\n return {\n entry,\n result,\n };\n}\n\nexport async function generateIndex(\n dest: string,\n entries: IconFontEntry[],\n runtimeModule: string = DEFAULT_ICON_FONT_RUNTIME_MODULE,\n) {\n const names = entries.map(({ name }) => name);\n const tsCode = `\n/* eslint-disable */\n// @ts-nocheck\nimport './index.css';\n${BANNER}\n${names\n .map(\n (name, index) =>\n // `import { IconName as IconName_${index}, IconNameMap as IconNameMap_${index} } from './${name}/${name}';`,\n `import './${name}/${name}';`,\n )\n .join('\\n')}\nexport type { IconName } from '${runtimeModule}';\nexport { ICON_NAMES } from '${runtimeModule}';\n `.trim();\n const tsDest = path.join(dest, 'index.ts');\n await fs.writeFile(tsDest, tsCode);\n\n const cssCode = `\n/* stylelint-disable */\n${BANNER}\n${names.map((name) => `@import './${name}/${name}.css';`).join('\\n')}\n `.trim();\n const cssDest = path.join(dest, 'index.css');\n await fs.writeFile(cssDest, cssCode);\n}\n\nexport async function generate(opts: IconFontOptions) {\n const runtimeModule = opts.runtimeModule ?? DEFAULT_ICON_FONT_RUNTIME_MODULE;\n await fs.emptyDir(opts.dest);\n const results = await Promise.all(\n opts.entries.map((entry) =>\n resolveRawIconFontEntry(opts.dest, entry).then((_entry) =>\n generateEntry(_entry, runtimeModule),\n ),\n ),\n );\n const entries = results.map(({ entry }) => entry);\n await generateIndex(opts.dest, entries, runtimeModule);\n}\n\nexport class IconFontRunnerItem extends EV<{\n build: IconFontEntryResult;\n}> {\n readonly entry: RawIconFontEntry;\n\n readonly ctx: IconFontRunner;\n\n private _resolveEntryPromise?: Promise<IconFontEntry>;\n\n private _watcher: FSWatcher | null = null;\n\n watchMode: boolean;\n\n // get name() {\n // return this.entry.name;\n // }\n\n constructor(ctx: IconFontRunner, entry: RawIconFontEntry, watch = false) {\n super();\n this.ctx = ctx;\n this.entry = entry;\n this.watchMode = watch;\n this.build = this.build.bind(this);\n }\n\n async run() {\n const result = await this.build();\n if (this.watchMode && !this._watcher) {\n const watchDir = path.resolve(this.entry.src);\n this._watcher = chokidar.watch(watchDir, { ignoreInitial: true });\n this._watcher.on('all', this.build);\n }\n return result;\n }\n\n resolveEntry() {\n if (!this._resolveEntryPromise) {\n this._resolveEntryPromise = resolveRawIconFontEntry(\n this.ctx.dest,\n this.entry,\n );\n }\n return this._resolveEntryPromise;\n }\n\n async build() {\n const entry = await this.resolveEntry();\n const result = await generateEntry(entry, this.ctx.runtimeModule);\n this.emit('build', result);\n return { entry };\n }\n\n destroy() {\n if (this._watcher) {\n this._watcher.close();\n this._watcher = null;\n }\n this.offAll();\n if (this.ctx) {\n delete (this as any).ctx;\n }\n }\n}\n\nexport class IconFontRunner extends EV<{\n build: {\n item: IconFontRunnerItem;\n result: IconFontEntryResult;\n };\n}> {\n readonly items: IconFontRunnerItem[] = [];\n\n readonly dest: string;\n\n /** @see {@link IconFontOptions.runtimeModule} */\n readonly runtimeModule: string;\n\n constructor(opts: IconFontOptions, watch?: boolean) {\n super();\n\n this.dest = opts.dest;\n this.runtimeModule = opts.runtimeModule ?? DEFAULT_ICON_FONT_RUNTIME_MODULE;\n\n opts.entries.forEach((entry) => {\n const item = new IconFontRunnerItem(this, entry, watch);\n item.on('build', (result) => {\n this.emit('build', { item, result });\n });\n this.items.push(item);\n });\n }\n\n async buildIndex() {\n const entries = await Promise.all(\n this.items.map((item) => item.resolveEntry()),\n );\n return generateIndex(this.dest, entries, this.runtimeModule);\n }\n\n async run() {\n await fs.ensureDir(this.dest);\n await Promise.all([\n this.buildIndex(),\n Promise.all(this.items.map((item) => item.run())),\n ]);\n }\n\n destroy() {\n this.items.forEach((item) => item.destroy());\n this.items.length = 0;\n this.offAll();\n delete (this as any)._opts;\n }\n}\n"],"mappings":"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"}
|