maplibre-font-maker-node 0.1.0 → 0.2.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/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # font-maker-node
1
+ # maplibre-font-maker-node
2
2
 
3
3
  A TypeScript library for generating MapLibre-compatible glyph PBF files in memory from TTF, OTF, WOFF, or WOFF2 font bytes.
4
4
  Variable fonts are supported, but a specific instantiation must be chosen, so you should supply a value for each axis.
@@ -6,7 +6,7 @@ Variable fonts are supported, but a specific instantiation must be chosen, so yo
6
6
  ## Usage
7
7
 
8
8
  ```ts
9
- import { generateGlyphPbfFiles, latinRanges } from 'font-maker-node';
9
+ import { generateGlyphPbfFiles, latinRanges } from 'maplibre-font-maker-node';
10
10
 
11
11
  const files = await generateGlyphPbfFiles({
12
12
  fontstack: 'Barlow Regular',
@@ -33,6 +33,46 @@ The result is an array of in-memory files:
33
33
 
34
34
  The caller is responsible for writing files to disk if desired. The public API does not read font files or write output files. The only filesystem access performed by the library is loading the vendored `maplibre-font-maker/sdfglyph.js` and `maplibre-font-maker/sdfglyph.wasm` runtime files during initialization.
35
35
 
36
+ ## CLI
37
+
38
+ The same package ships a thin command-line wrapper around `generateGlyphPbfFiles`. It reads a font file, generates the glyphs, and writes them to disk.
39
+
40
+ ```bash
41
+ npx maplibre-font-maker-node \
42
+ --font ./fonts/Barlow-Regular.ttf \
43
+ --fontstack "Barlow Regular" \
44
+ --output ./dist/fonts \
45
+ --ranges latin
46
+ ```
47
+
48
+ This writes the MapLibre-ready layout `<output>/<fontstack>/<start>-<end>.pbf`, e.g. `./dist/fonts/Barlow Regular/0-255.pbf` — exactly the `{fontstack}/{range}.pbf` structure MapLibre's `glyphs` URL expects. Output directories are created automatically.
49
+
50
+ | Option | Description |
51
+ | --- | --- |
52
+ | `--font <path>` | Input font file (TTF, OTF, WOFF, or WOFF2). Required. |
53
+ | `--fontstack <name>` | MapLibre font stack name. Required. |
54
+ | `--output <dir>` | Output directory. Required. |
55
+ | `--ranges <preset>` | Glyph range preset: `basic-latin`, `latin`, or `all-bmp`. Default: `latin`. |
56
+ | `--force` | Overwrite existing output files. Without it, the command fails if any target file already exists. |
57
+ | `--help` | Show usage. |
58
+ | `--version` | Show the package version. |
59
+
60
+ The CLI exits with code `1` on any failure (missing argument, font not found, invalid preset, generation error), so it fails the surrounding script in CI.
61
+
62
+ ### Use it as a build step
63
+
64
+ Because npm exposes the binary on `node_modules/.bin`, you can call it by name from a downstream project's lifecycle scripts to generate glyphs into your build output:
65
+
66
+ ```json
67
+ {
68
+ "scripts": {
69
+ "prebuild": "maplibre-font-maker-node --font ./fonts/Barlow-Regular.ttf --fontstack \"Barlow Regular\" --output ./dist/fonts --ranges latin --force"
70
+ }
71
+ }
72
+ ```
73
+
74
+ `prebuild` runs automatically before `build`. Use `--force` so repeated builds don't fail on already-generated files. Each invocation handles one font; chain multiple commands with `&&` for several font stacks.
75
+
36
76
  ## API
37
77
 
38
78
  ```ts
@@ -0,0 +1,17 @@
1
+ export interface CliOptions {
2
+ font: string;
3
+ fontstack: string;
4
+ output: string;
5
+ ranges: string;
6
+ force: boolean;
7
+ }
8
+ export type ParsedArgs = {
9
+ kind: 'help';
10
+ } | {
11
+ kind: 'version';
12
+ } | {
13
+ kind: 'run';
14
+ options: CliOptions;
15
+ };
16
+ export declare function parseCliArgs(argv: string[]): ParsedArgs;
17
+ //# sourceMappingURL=parse-args.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-args.d.ts","sourceRoot":"","sources":["../../src/cli/parse-args.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,MAAM,UAAU,GAClB;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,GACnB;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,UAAU,CAAA;CAAE,CAAC;AAIzC,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,UAAU,CA6CvD"}
@@ -0,0 +1,49 @@
1
+ import { parseArgs } from 'node:util';
2
+ import { RANGE_PRESETS } from './resolve-ranges.js';
3
+ const DEFAULT_RANGES = 'latin';
4
+ export function parseCliArgs(argv) {
5
+ let values;
6
+ try {
7
+ ({ values } = parseArgs({
8
+ args: argv,
9
+ allowPositionals: false,
10
+ strict: true,
11
+ options: {
12
+ font: { type: 'string' },
13
+ fontstack: { type: 'string' },
14
+ output: { type: 'string' },
15
+ ranges: { type: 'string', default: DEFAULT_RANGES },
16
+ force: { type: 'boolean', default: false },
17
+ help: { type: 'boolean', default: false },
18
+ version: { type: 'boolean', default: false },
19
+ },
20
+ }));
21
+ }
22
+ catch (error) {
23
+ throw new Error(error instanceof Error ? error.message : String(error));
24
+ }
25
+ if (values.help) {
26
+ return { kind: 'help' };
27
+ }
28
+ if (values.version) {
29
+ return { kind: 'version' };
30
+ }
31
+ const font = requireOption(values.font, 'font');
32
+ const fontstack = requireOption(values.fontstack, 'fontstack');
33
+ const output = requireOption(values.output, 'output');
34
+ const ranges = values.ranges ?? DEFAULT_RANGES;
35
+ if (!RANGE_PRESETS.includes(ranges)) {
36
+ throw new Error(`Invalid --ranges preset "${ranges}". Valid presets are: ${RANGE_PRESETS.join(', ')}.`);
37
+ }
38
+ return {
39
+ kind: 'run',
40
+ options: { font, fontstack, output, ranges, force: values.force ?? false },
41
+ };
42
+ }
43
+ function requireOption(value, name) {
44
+ if (typeof value !== 'string' || value.length === 0) {
45
+ throw new Error(`Missing required option --${name}.`);
46
+ }
47
+ return value;
48
+ }
49
+ //# sourceMappingURL=parse-args.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-args.js","sourceRoot":"","sources":["../../src/cli/parse-args.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAepD,MAAM,cAAc,GAAG,OAAO,CAAC;AAE/B,MAAM,UAAU,YAAY,CAAC,IAAc;IACzC,IAAI,MAAM,CAAC;IAEX,IAAI,CAAC;QACH,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;YACtB,IAAI,EAAE,IAAI;YACV,gBAAgB,EAAE,KAAK;YACvB,MAAM,EAAE,IAAI;YACZ,OAAO,EAAE;gBACP,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;gBACxB,SAAS,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;gBAC7B,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;gBAC1B,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,cAAc,EAAE;gBACnD,KAAK,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE;gBAC1C,IAAI,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE;gBACzC,OAAO,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE;aAC7C;SACF,CAAC,CAAC,CAAC;IACN,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IAC1E,CAAC;IAED,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;QAChB,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAC1B,CAAC;IAED,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QACnB,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;IAC7B,CAAC;IAED,MAAM,IAAI,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAChD,MAAM,SAAS,GAAG,aAAa,CAAC,MAAM,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;IAC/D,MAAM,MAAM,GAAG,aAAa,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACtD,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,IAAI,cAAc,CAAC;IAE/C,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QACpC,MAAM,IAAI,KAAK,CACb,4BAA4B,MAAM,yBAAyB,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CACvF,CAAC;IACJ,CAAC;IAED,OAAO;QACL,IAAI,EAAE,KAAK;QACX,OAAO,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,KAAK,EAAE;KAC3E,CAAC;AACJ,CAAC;AAED,SAAS,aAAa,CAAC,KAAyB,EAAE,IAAY;IAC5D,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACpD,MAAM,IAAI,KAAK,CAAC,6BAA6B,IAAI,GAAG,CAAC,CAAC;IACxD,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,7 @@
1
+ export interface Summary {
2
+ fontstack: string;
3
+ fileCount: number;
4
+ output: string;
5
+ }
6
+ export declare function printSummary({ fontstack, fileCount, output }: Summary): void;
7
+ //# sourceMappingURL=print-summary.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"print-summary.d.ts","sourceRoot":"","sources":["../../src/cli/print-summary.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,OAAO;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,YAAY,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE,OAAO,GAAG,IAAI,CAM5E"}
@@ -0,0 +1,8 @@
1
+ export function printSummary({ fontstack, fileCount, output }) {
2
+ console.log('Generated:');
3
+ console.log(` Font stack: ${fontstack}`);
4
+ console.log(` Files: ${fileCount}`);
5
+ console.log(` Output: ${output}`);
6
+ console.log('Done.');
7
+ }
8
+ //# sourceMappingURL=print-summary.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"print-summary.js","sourceRoot":"","sources":["../../src/cli/print-summary.ts"],"names":[],"mappings":"AAMA,MAAM,UAAU,YAAY,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,EAAW;IACpE,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IAC1B,OAAO,CAAC,GAAG,CAAC,kBAAkB,SAAS,EAAE,CAAC,CAAC;IAC3C,OAAO,CAAC,GAAG,CAAC,kBAAkB,SAAS,EAAE,CAAC,CAAC;IAC3C,OAAO,CAAC,GAAG,CAAC,kBAAkB,MAAM,EAAE,CAAC,CAAC;IACxC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AACvB,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { GlyphRange } from '../index.js';
2
+ export declare const RANGE_PRESETS: string[];
3
+ export declare function resolveRanges(preset: string): GlyphRange[];
4
+ //# sourceMappingURL=resolve-ranges.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-ranges.d.ts","sourceRoot":"","sources":["../../src/cli/resolve-ranges.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAQ9C,eAAO,MAAM,aAAa,UAAuB,CAAC;AAElD,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,EAAE,CAU1D"}
@@ -0,0 +1,15 @@
1
+ import { allBmpRanges, basicLatinRanges, latinRanges } from '../index.js';
2
+ const PRESETS = {
3
+ 'basic-latin': basicLatinRanges,
4
+ latin: latinRanges,
5
+ 'all-bmp': allBmpRanges,
6
+ };
7
+ export const RANGE_PRESETS = Object.keys(PRESETS);
8
+ export function resolveRanges(preset) {
9
+ const build = PRESETS[preset];
10
+ if (!build) {
11
+ throw new Error(`Invalid --ranges preset "${preset}". Valid presets are: ${RANGE_PRESETS.join(', ')}.`);
12
+ }
13
+ return build();
14
+ }
15
+ //# sourceMappingURL=resolve-ranges.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-ranges.js","sourceRoot":"","sources":["../../src/cli/resolve-ranges.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAI1E,MAAM,OAAO,GAAuC;IAClD,aAAa,EAAE,gBAAgB;IAC/B,KAAK,EAAE,WAAW;IAClB,SAAS,EAAE,YAAY;CACxB,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AAElD,MAAM,UAAU,aAAa,CAAC,MAAc;IAC1C,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAE9B,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CACb,4BAA4B,MAAM,yBAAyB,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CACvF,CAAC;IACJ,CAAC;IAED,OAAO,KAAK,EAAE,CAAC;AACjB,CAAC"}
@@ -0,0 +1,6 @@
1
+ import type { GeneratedGlyphPbfFile } from '../index.js';
2
+ export interface WriteOptions {
3
+ force: boolean;
4
+ }
5
+ export declare function writeGeneratedFiles(files: GeneratedGlyphPbfFile[], outputDirectory: string, { force }: WriteOptions): Promise<void>;
6
+ //# sourceMappingURL=write-generated-files.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"write-generated-files.d.ts","sourceRoot":"","sources":["../../src/cli/write-generated-files.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAEzD,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,qBAAqB,EAAE,EAC9B,eAAe,EAAE,MAAM,EACvB,EAAE,KAAK,EAAE,EAAE,YAAY,GACtB,OAAO,CAAC,IAAI,CAAC,CAqBf"}
@@ -0,0 +1,32 @@
1
+ import { access, mkdir, writeFile } from 'node:fs/promises';
2
+ import { dirname, join } from 'node:path';
3
+ export async function writeGeneratedFiles(files, outputDirectory, { force }) {
4
+ const destinations = files.map((file) => ({
5
+ bytes: file.bytes,
6
+ path: join(outputDirectory, file.filename),
7
+ }));
8
+ if (!force) {
9
+ const existing = await findExisting(destinations.map((destination) => destination.path));
10
+ if (existing.length > 0) {
11
+ throw new Error(`Refusing to overwrite ${existing.length} existing file(s). Pass --force to overwrite:\n` +
12
+ existing.map((path) => ` ${path}`).join('\n'));
13
+ }
14
+ }
15
+ for (const destination of destinations) {
16
+ await mkdir(dirname(destination.path), { recursive: true });
17
+ await writeFile(destination.path, destination.bytes);
18
+ }
19
+ }
20
+ async function findExisting(paths) {
21
+ const checks = await Promise.all(paths.map(async (path) => {
22
+ try {
23
+ await access(path);
24
+ return path;
25
+ }
26
+ catch {
27
+ return undefined;
28
+ }
29
+ }));
30
+ return checks.filter((path) => path !== undefined);
31
+ }
32
+ //# sourceMappingURL=write-generated-files.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"write-generated-files.js","sourceRoot":"","sources":["../../src/cli/write-generated-files.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC5D,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAQ1C,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,KAA8B,EAC9B,eAAuB,EACvB,EAAE,KAAK,EAAgB;IAEvB,MAAM,YAAY,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACxC,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,IAAI,EAAE,IAAI,CAAC,eAAe,EAAE,IAAI,CAAC,QAAQ,CAAC;KAC3C,CAAC,CAAC,CAAC;IAEJ,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC;QAEzF,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACxB,MAAM,IAAI,KAAK,CACb,yBAAyB,QAAQ,CAAC,MAAM,iDAAiD;gBACvF,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CACjD,CAAC;QACJ,CAAC;IACH,CAAC;IAED,KAAK,MAAM,WAAW,IAAI,YAAY,EAAE,CAAC;QACvC,MAAM,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5D,MAAM,SAAS,CAAC,WAAW,CAAC,IAAI,EAAE,WAAW,CAAC,KAAK,CAAC,CAAC;IACvD,CAAC;AACH,CAAC;AAED,KAAK,UAAU,YAAY,CAAC,KAAe;IACzC,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,CAC9B,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;QACvB,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,IAAI,CAAC,CAAC;YACnB,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,SAAS,CAAC;QACnB,CAAC;IACH,CAAC,CAAC,CACH,CAAC;IAEF,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,EAAkB,EAAE,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC;AACrE,CAAC"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export declare function run(argv: string[]): Promise<void>;
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAgCA,wBAAsB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAcvD"}
package/dist/cli.js ADDED
@@ -0,0 +1,84 @@
1
+ #!/usr/bin/env node
2
+ import { readFile } from 'node:fs/promises';
3
+ import { pathToFileURL } from 'node:url';
4
+ import { generateGlyphPbfFiles } from './index.js';
5
+ import { parseCliArgs } from './cli/parse-args.js';
6
+ import { printSummary } from './cli/print-summary.js';
7
+ import { resolveRanges } from './cli/resolve-ranges.js';
8
+ import { writeGeneratedFiles } from './cli/write-generated-files.js';
9
+ const HELP_TEXT = `maplibre-font-maker-node
10
+
11
+ Generate MapLibre glyph PBF files from TTF, OTF, WOFF, or WOFF2 fonts.
12
+
13
+ Usage:
14
+ maplibre-font-maker-node \\
15
+ --font <file.ttf> \\
16
+ --fontstack "Barlow Regular" \\
17
+ --output ./fonts
18
+
19
+ Options:
20
+ --font Input font file (required)
21
+ --fontstack MapLibre font stack name (required)
22
+ --output Output directory (required)
23
+ --ranges Glyph range preset: basic-latin | latin | all-bmp (default: latin)
24
+ --force Overwrite existing files
25
+ --help Show this help
26
+ --version Show version
27
+ `;
28
+ export async function run(argv) {
29
+ const parsed = parseCliArgs(argv);
30
+ if (parsed.kind === 'help') {
31
+ console.log(HELP_TEXT);
32
+ return;
33
+ }
34
+ if (parsed.kind === 'version') {
35
+ console.log(await readVersion());
36
+ return;
37
+ }
38
+ await generate(parsed.options);
39
+ }
40
+ async function generate(options) {
41
+ const fontBytes = await readFontFile(options.font);
42
+ const ranges = resolveRanges(options.ranges);
43
+ const files = await generateGlyphPbfFiles({
44
+ fontstack: options.fontstack,
45
+ fonts: [{ name: options.fontstack, bytes: fontBytes }],
46
+ ranges,
47
+ });
48
+ await writeGeneratedFiles(files, options.output, { force: options.force });
49
+ printSummary({
50
+ fontstack: options.fontstack,
51
+ fileCount: files.length,
52
+ output: options.output,
53
+ });
54
+ }
55
+ async function readFontFile(path) {
56
+ try {
57
+ return new Uint8Array(await readFile(path));
58
+ }
59
+ catch (error) {
60
+ if (isErrnoException(error) && error.code === 'ENOENT') {
61
+ throw new Error(`Font file not found: ${path}`);
62
+ }
63
+ throw new Error(`Failed to read font file "${path}": ${formatError(error)}`);
64
+ }
65
+ }
66
+ async function readVersion() {
67
+ const packageUrl = new URL('../package.json', import.meta.url);
68
+ const manifest = JSON.parse(await readFile(packageUrl, 'utf8'));
69
+ return manifest.version ?? 'unknown';
70
+ }
71
+ function isErrnoException(error) {
72
+ return error instanceof Error && 'code' in error;
73
+ }
74
+ function formatError(error) {
75
+ return error instanceof Error ? error.message : String(error);
76
+ }
77
+ const invokedPath = process.argv[1];
78
+ if (invokedPath && pathToFileURL(invokedPath).href === import.meta.url) {
79
+ run(process.argv.slice(2)).catch((error) => {
80
+ console.error(formatError(error));
81
+ process.exitCode = 1;
82
+ });
83
+ }
84
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "maplibre-font-maker-node",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Generate MapLibre-compatible glyph PBF files in memory from TTF, OTF, WOFF, or WOFF2 font bytes.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -11,6 +11,9 @@
11
11
  "import": "./dist/index.js"
12
12
  }
13
13
  },
14
+ "bin": {
15
+ "maplibre-font-maker-node": "./dist/cli.js"
16
+ },
14
17
  "files": [
15
18
  "dist",
16
19
  "maplibre-font-maker",