cryosnap 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/cryosnap.node ADDED
Binary file
package/index.d.ts ADDED
@@ -0,0 +1,102 @@
1
+ export type BoxValue = number | number[] | string;
2
+ export type LinesValue = number | number[] | string;
3
+
4
+ export interface BorderConfig {
5
+ radius?: number;
6
+ width?: number;
7
+ color?: string;
8
+ }
9
+
10
+ export interface ShadowConfig {
11
+ blur?: number;
12
+ x?: number;
13
+ y?: number;
14
+ }
15
+
16
+ export interface FontConfig {
17
+ family?: string;
18
+ file?: string;
19
+ filePath?: string;
20
+ size?: number;
21
+ ligatures?: boolean;
22
+ }
23
+
24
+ export interface PngConfig {
25
+ optimize?: boolean;
26
+ level?: number;
27
+ optimizeLevel?: number;
28
+ strip?: 'none' | 'safe' | 'all';
29
+ quantize?: boolean;
30
+ quantize_preset?: 'fast' | 'balanced' | 'best';
31
+ quantizePreset?: 'fast' | 'balanced' | 'best';
32
+ quantize_quality?: number;
33
+ quantizeQuality?: number;
34
+ quantize_speed?: number;
35
+ quantizeSpeed?: number;
36
+ quantize_dither?: number;
37
+ quantizeDither?: number;
38
+ }
39
+
40
+ export interface RasterConfig {
41
+ scale?: number;
42
+ max_pixels?: number;
43
+ maxPixels?: number;
44
+ backend?: 'auto' | 'resvg' | 'rsvg';
45
+ }
46
+
47
+ export interface TitleConfig {
48
+ enabled?: boolean;
49
+ text?: string;
50
+ path_style?: 'absolute' | 'relative' | 'basename';
51
+ pathStyle?: 'absolute' | 'relative' | 'basename';
52
+ tmux_format?: string;
53
+ tmuxFormat?: string;
54
+ align?: 'left' | 'center' | 'right';
55
+ size?: number;
56
+ color?: string;
57
+ opacity?: number;
58
+ max_width?: number;
59
+ maxWidth?: number;
60
+ ellipsis?: string;
61
+ }
62
+
63
+ export interface RenderConfig {
64
+ theme?: string;
65
+ background?: string;
66
+ padding?: BoxValue;
67
+ margin?: BoxValue;
68
+ width?: number;
69
+ height?: number;
70
+ window?: boolean;
71
+ windowControls?: boolean;
72
+ show_line_numbers?: boolean;
73
+ showLineNumbers?: boolean;
74
+ language?: string;
75
+ execute_timeout_ms?: number;
76
+ executeTimeoutMs?: number;
77
+ wrap?: number;
78
+ lines?: LinesValue;
79
+ border?: BorderConfig;
80
+ shadow?: ShadowConfig;
81
+ font?: FontConfig;
82
+ raster?: RasterConfig;
83
+ png?: PngConfig;
84
+ title?: TitleConfig;
85
+ line_height?: number;
86
+ lineHeight?: number;
87
+ }
88
+
89
+ export interface RenderOptions {
90
+ input: string;
91
+ inputKind?: 'text' | 'file' | 'command';
92
+ configJson?: string;
93
+ config?: RenderConfig;
94
+ format?: 'svg' | 'png' | 'webp';
95
+ }
96
+
97
+ export function render(options: RenderOptions): Buffer;
98
+ export function renderSvg(options: RenderOptions): Buffer;
99
+ export function renderPng(options: RenderOptions): Buffer;
100
+ export function renderWebp(options: RenderOptions): Buffer;
101
+ export function renderToFile(options: RenderOptions, outputPath: string): string;
102
+ export function version(): string;
package/index.js ADDED
@@ -0,0 +1,141 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+
4
+ function normalizeConfig(config) {
5
+ if (!config || typeof config !== 'object') return config;
6
+ const out = { ...config };
7
+
8
+ if (out.window === undefined && out.windowControls !== undefined) {
9
+ out.window = out.windowControls;
10
+ }
11
+ if (out.show_line_numbers === undefined && out.showLineNumbers !== undefined) {
12
+ out.show_line_numbers = out.showLineNumbers;
13
+ }
14
+ if (out.line_height === undefined && out.lineHeight !== undefined) {
15
+ out.line_height = out.lineHeight;
16
+ }
17
+ if (out.execute_timeout_ms === undefined && out.executeTimeoutMs !== undefined) {
18
+ out.execute_timeout_ms = out.executeTimeoutMs;
19
+ }
20
+
21
+ if (out.font && typeof out.font === 'object') {
22
+ const font = { ...out.font };
23
+ if (font.filePath !== undefined && font.file === undefined) {
24
+ font.file = font.filePath;
25
+ }
26
+ out.font = font;
27
+ }
28
+
29
+ if (out.png && typeof out.png === 'object') {
30
+ const png = { ...out.png };
31
+ if (png.optimizeLevel !== undefined && png.level === undefined) {
32
+ png.level = png.optimizeLevel;
33
+ }
34
+ if (png.quantizeQuality !== undefined && png.quantize_quality === undefined) {
35
+ png.quantize_quality = png.quantizeQuality;
36
+ }
37
+ if (png.quantizeSpeed !== undefined && png.quantize_speed === undefined) {
38
+ png.quantize_speed = png.quantizeSpeed;
39
+ }
40
+ if (png.quantizeDither !== undefined && png.quantize_dither === undefined) {
41
+ png.quantize_dither = png.quantizeDither;
42
+ }
43
+ if (png.quantizePreset !== undefined && png.quantize_preset === undefined) {
44
+ png.quantize_preset = png.quantizePreset;
45
+ }
46
+ if (png.quantizePreset !== undefined && png.quantize === undefined) {
47
+ png.quantize = true;
48
+ }
49
+ out.png = png;
50
+ }
51
+
52
+ if (out.raster && typeof out.raster === 'object') {
53
+ const raster = { ...out.raster };
54
+ if (raster.maxPixels !== undefined && raster.max_pixels === undefined) {
55
+ raster.max_pixels = raster.maxPixels;
56
+ }
57
+ out.raster = raster;
58
+ }
59
+
60
+ if (out.title && typeof out.title === 'object') {
61
+ const title = { ...out.title };
62
+ if (title.pathStyle !== undefined && title.path_style === undefined) {
63
+ title.path_style = title.pathStyle;
64
+ }
65
+ if (title.tmuxFormat !== undefined && title.tmux_format === undefined) {
66
+ title.tmux_format = title.tmuxFormat;
67
+ }
68
+ if (title.maxWidth !== undefined && title.max_width === undefined) {
69
+ title.max_width = title.maxWidth;
70
+ }
71
+ out.title = title;
72
+ }
73
+
74
+ return out;
75
+ }
76
+
77
+ function applyConfig(options) {
78
+ const opts = { ...(options || {}) };
79
+ if (opts.inputKind !== undefined && opts.input_kind === undefined) {
80
+ opts.input_kind = opts.inputKind;
81
+ }
82
+ if (opts.configJson !== undefined && opts.config_json === undefined) {
83
+ opts.config_json = opts.configJson;
84
+ }
85
+ if (opts.config && !opts.configJson) {
86
+ const normalized = normalizeConfig(opts.config);
87
+ opts.configJson = JSON.stringify(normalized);
88
+ if (opts.config_json === undefined) {
89
+ opts.config_json = opts.configJson;
90
+ }
91
+ }
92
+ delete opts.config;
93
+ delete opts.inputKind;
94
+ return opts;
95
+ }
96
+
97
+ function resolveFormatFromPath(outputPath) {
98
+ const ext = path.extname(outputPath).toLowerCase();
99
+ if (ext === '.png') return 'png';
100
+ if (ext === '.svg') return 'svg';
101
+ if (ext === '.webp') return 'webp';
102
+ return null;
103
+ }
104
+
105
+ try {
106
+ // Built by `napi build`
107
+ const native = require('./cryosnap.node');
108
+ const render = (options) => native.render(applyConfig(options));
109
+ const renderSvg = (options) => render({ ...(options || {}), format: 'svg' });
110
+ const renderPng = (options) => render({ ...(options || {}), format: 'png' });
111
+ const renderWebp = (options) => render({ ...(options || {}), format: 'webp' });
112
+ const renderToFile = (options, outputPath) => {
113
+ if (!outputPath) {
114
+ throw new Error('outputPath is required');
115
+ }
116
+ const opts = { ...(options || {}) };
117
+ if (!opts.format) {
118
+ const inferred = resolveFormatFromPath(outputPath);
119
+ if (inferred) opts.format = inferred;
120
+ }
121
+ const bytes = render(opts);
122
+ fs.writeFileSync(outputPath, bytes);
123
+ return outputPath;
124
+ };
125
+
126
+ module.exports = {
127
+ ...native,
128
+ render,
129
+ renderSvg,
130
+ renderPng,
131
+ renderWebp,
132
+ renderToFile
133
+ };
134
+ } catch (err) {
135
+ const message = [
136
+ 'Unable to load cryosnap native module.',
137
+ 'Run `npm run build` in crates/cryosnap-node first.',
138
+ err && err.message ? `Original error: ${err.message}` : ''
139
+ ].filter(Boolean).join('\n');
140
+ throw new Error(message);
141
+ }
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "cryosnap",
3
+ "version": "0.1.0",
4
+ "description": "Node/TS bindings for cryosnap",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/Wangnov/cryosnap.git",
9
+ "directory": "crates/cryosnap-node"
10
+ },
11
+ "homepage": "https://github.com/Wangnov/cryosnap#readme",
12
+ "bugs": {
13
+ "url": "https://github.com/Wangnov/cryosnap/issues"
14
+ },
15
+ "keywords": [
16
+ "screenshot",
17
+ "code",
18
+ "terminal",
19
+ "svg",
20
+ "png",
21
+ "napi"
22
+ ],
23
+ "main": "index.js",
24
+ "types": "index.d.ts",
25
+ "files": [
26
+ "index.js",
27
+ "index.d.ts",
28
+ "*.node"
29
+ ],
30
+ "scripts": {
31
+ "build": "node -e \"require('fs').mkdirSync('../../tmp',{recursive:true})\" && napi build --release --no-js --dts ../../tmp/cryosnap-node.d.ts",
32
+ "build:debug": "node -e \"require('fs').mkdirSync('../../tmp',{recursive:true})\" && napi build --no-js --dts ../../tmp/cryosnap-node.d.ts"
33
+ },
34
+ "napi": {
35
+ "binaryName": "cryosnap"
36
+ },
37
+ "devDependencies": {
38
+ "@napi-rs/cli": "^3.5.1"
39
+ }
40
+ }