@svfig/build 0.1.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/main.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=main.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":""}
package/dist/main.js ADDED
@@ -0,0 +1,28 @@
1
+ import { readFile, writeFile } from 'node:fs/promises';
2
+ import { dirname, resolve as resolvePath } from 'node:path';
3
+ import { parse } from '@svfig/core';
4
+ import { cac } from 'cac';
5
+ import { renderSvg } from './index';
6
+ const app = cac('svfig');
7
+ app
8
+ .command('<input>', 'Render an .svfig file to SVG')
9
+ .option('-o, --out <file>', 'Output path (default: stdout)')
10
+ .action(async (input, opts) => {
11
+ const inputPath = resolvePath(input);
12
+ const document = parse(await readFile(inputPath, 'utf8'), inputPath);
13
+ const svg = await renderSvg(document, { baseDir: dirname(inputPath) });
14
+ if (opts.out)
15
+ await writeFile(resolvePath(opts.out), svg, 'utf8');
16
+ else
17
+ process.stdout.write(svg);
18
+ });
19
+ app.help();
20
+ app.version('0.1.0');
21
+ const main = async () => {
22
+ app.parse(process.argv, { run: false });
23
+ await app.runMatchedCommand();
24
+ };
25
+ main().catch((e) => {
26
+ process.stderr.write(`svfig: ${e instanceof Error ? e.message : String(e)}\n`);
27
+ process.exit(1);
28
+ });
package/dist/path.d.ts ADDED
@@ -0,0 +1,24 @@
1
+ import type { PartialElement } from '@svfig/core';
2
+ export interface ResolveOptions {
3
+ baseDir?: string;
4
+ }
5
+ export type Resolved = {
6
+ kind: 'local';
7
+ source: string;
8
+ filename: string;
9
+ mime: string;
10
+ } | {
11
+ kind: 'remote';
12
+ source: string;
13
+ url: string;
14
+ mime: string;
15
+ } | {
16
+ kind: 'data';
17
+ source: string;
18
+ href: string;
19
+ };
20
+ export declare const imagePaths: (elements: PartialElement[]) => string[];
21
+ export declare const resolveImage: (path: string, opts?: ResolveOptions) => Promise<Resolved>;
22
+ export declare const imageWatchPath: (path: string, opts?: ResolveOptions) => Promise<string | null>;
23
+ export declare const imageDataUri: (path: string, opts?: ResolveOptions) => Promise<string>;
24
+ //# sourceMappingURL=path.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path.d.ts","sourceRoot":"","sources":["../src/path.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,MAAM,WAAW,cAAc;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,MAAM,QAAQ,GAChB;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACjE;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC7D;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAwBnD,eAAO,MAAM,UAAU,GAAI,UAAU,cAAc,EAAE,KAAG,MAAM,EACgC,CAAC;AAE/F,eAAO,MAAM,YAAY,GAAU,MAAM,MAAM,EAAE,OAAM,cAAmB,KAAG,OAAO,CAAC,QAAQ,CAQ5F,CAAC;AAEF,eAAO,MAAM,cAAc,GAAU,MAAM,MAAM,EAAE,OAAM,cAAmB,KAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAGnG,CAAC;AAEF,eAAO,MAAM,YAAY,GAAU,MAAM,MAAM,EAAE,OAAM,cAAmB,KAAG,OAAO,CAAC,MAAM,CAK1F,CAAC"}
package/dist/path.js ADDED
@@ -0,0 +1,54 @@
1
+ import { Buffer } from 'node:buffer';
2
+ import { readFile } from 'node:fs/promises';
3
+ import { isAbsolute, resolve } from 'node:path';
4
+ const MIME = {
5
+ '.png': 'image/png',
6
+ '.jpg': 'image/jpeg',
7
+ '.jpeg': 'image/jpeg',
8
+ '.svg': 'image/svg+xml',
9
+ '.webp': 'image/webp',
10
+ '.gif': 'image/gif',
11
+ };
12
+ const DATA = /^data:image\//i;
13
+ const BLOB = /^blob:/i;
14
+ const REMOTE = /^https?:\/\//i;
15
+ const stripQuery = (p) => p.split(/[?#]/, 1)[0];
16
+ const mimeOf = (p) => {
17
+ const path = stripQuery(p);
18
+ const mime = MIME[path.slice(path.lastIndexOf('.')).toLowerCase()];
19
+ if (!mime)
20
+ throw new Error(`Unsupported image extension: ${p}`);
21
+ return mime;
22
+ };
23
+ export const imagePaths = (elements) => Array.from(new Set(elements.flatMap((e) => (e.kind === 'image' && e.path ? [e.path] : []))));
24
+ export const resolveImage = async (path, opts = {}) => {
25
+ if (DATA.test(path))
26
+ return { kind: 'data', source: path, href: path };
27
+ if (BLOB.test(path))
28
+ throw new Error(`Blob image paths cannot be resolved during build: ${path}`);
29
+ if (REMOTE.test(path))
30
+ return { kind: 'remote', source: path, url: path, mime: mimeOf(path) };
31
+ const local = stripQuery(path);
32
+ const filename = isAbsolute(local) ? local : resolve(opts.baseDir || process.cwd(), local);
33
+ return { kind: 'local', source: path, filename, mime: mimeOf(path) };
34
+ };
35
+ export const imageWatchPath = async (path, opts = {}) => {
36
+ const r = await resolveImage(path, opts);
37
+ return r.kind === 'local' ? r.filename : null;
38
+ };
39
+ export const imageDataUri = async (path, opts = {}) => {
40
+ const r = await resolveImage(path, opts);
41
+ if (r.kind === 'data')
42
+ return r.href;
43
+ const bytes = await readBytes(r);
44
+ return `data:${r.mime};base64,${Buffer.from(bytes).toString('base64')}`;
45
+ };
46
+ const readBytes = async (r) => {
47
+ if (r.kind === 'remote') {
48
+ const res = await fetch(r.url);
49
+ if (!res.ok)
50
+ throw new Error(`Failed to fetch image "${r.source}": ${res.status} ${res.statusText}`);
51
+ return new Uint8Array(await res.arrayBuffer());
52
+ }
53
+ return readFile(r.filename);
54
+ };
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "@svfig/build",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "main": "./dist/index.js",
6
+ "types": "./dist/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "import": "./dist/index.js"
11
+ },
12
+ "./path": {
13
+ "types": "./dist/path.d.ts",
14
+ "import": "./dist/path.js"
15
+ }
16
+ },
17
+ "files": [
18
+ "dist"
19
+ ],
20
+ "sideEffects": false,
21
+ "dependencies": {
22
+ "cac": "^7.0.0",
23
+ "react": "^19.1.0",
24
+ "react-dom": "^19.1.0",
25
+ "@svfig/core": "0.1.0"
26
+ },
27
+ "devDependencies": {
28
+ "@types/node": "^22.19.19",
29
+ "@types/react": "^19.1.0",
30
+ "@types/react-dom": "^19.1.0",
31
+ "esbuild": "^0.27.0"
32
+ },
33
+ "scripts": {
34
+ "build": "tsc -p tsconfig.build.json && pnpm exec esbuild src/main.ts --bundle --platform=node --format=cjs --target=node20 --outfile=dist/main.cjs --banner:js='#!/usr/bin/env node' && chmod +x dist/main.cjs",
35
+ "typecheck": "tsc -p tsconfig.json --noEmit"
36
+ },
37
+ "bin": {
38
+ "build": "./dist/main.cjs"
39
+ }
40
+ }