pulp-image 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/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Rebellion Geeks
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
package/README.md ADDED
@@ -0,0 +1,332 @@
1
+ # pulp-image
2
+
3
+ A powerful, safety-first CLI tool for processing images with resize, format conversion, and optimization.
4
+
5
+ ![Version](https://img.shields.io/badge/version-0.1.0-blue)
6
+ ![License](https://img.shields.io/badge/license-MIT-green)
7
+ ![Node](https://img.shields.io/badge/node-%3E%3D18.0.0-brightgreen)
8
+
9
+ ## Features
10
+
11
+ - šŸ–¼ļø **Resize images** with aspect ratio preservation
12
+ - šŸ”„ **Convert formats** (PNG, JPG, WebP, AVIF)
13
+ - šŸ“¦ **Batch process** entire directories
14
+ - šŸ›”ļø **Safety-first** defaults (no overwrites, no accidental deletions)
15
+ - šŸ“Š **Detailed statistics** and summary reports
16
+ - šŸŽØ **Transparency handling** with customizable backgrounds
17
+ - ⚔ **Optimization** with quality and lossless options
18
+
19
+ ## Installation
20
+
21
+ ### From GitHub
22
+
23
+ 1. **Clone or download the repository:**
24
+ ```bash
25
+ git clone https://github.com/rebelliongeeks/pulp-image.git
26
+ cd pulp-image
27
+ ```
28
+
29
+ 2. **Install dependencies:**
30
+ ```bash
31
+ npm install
32
+ ```
33
+
34
+ 3. **Link the CLI globally:**
35
+ ```bash
36
+ npm link
37
+ ```
38
+
39
+ This will make the `pulp` command available globally on your system.
40
+
41
+ ### Alternative: Install directly from GitHub
42
+
43
+ You can also install directly from GitHub without cloning:
44
+
45
+ ```bash
46
+ npm install -g github:rebelliongeeks/pulp-image
47
+ ```
48
+
49
+ ### Global Installation (Persistent)
50
+
51
+ If you want the `pulp` command to work even after deleting the project folder, use global installation instead of `npm link`:
52
+
53
+ ```bash
54
+ npm install -g .
55
+ ```
56
+
57
+ This copies the files to your global npm directory, so the command persists even if you delete the source folder.
58
+
59
+ **Note:** `npm link` creates a symlink (breaks if you delete the folder). `npm install -g` copies files (persists after deletion).
60
+
61
+ ### Requirements
62
+
63
+ - Node.js >= 18.0.0
64
+ - npm (comes with Node.js)
65
+
66
+ ## Quick Start
67
+
68
+ ```bash
69
+ # Resize an image
70
+ pulp image.png --width 800
71
+
72
+ # Convert format
73
+ pulp image.png --format webp
74
+
75
+ # Process all images in a directory
76
+ pulp ./images --format webp --out ./output
77
+ ```
78
+
79
+ ## Usage
80
+
81
+ ```bash
82
+ pulp [input] [options]
83
+ ```
84
+
85
+ ### Arguments
86
+
87
+ - `[input]` - Input file or directory (required)
88
+
89
+ ### Common Options
90
+
91
+ #### Resize
92
+ - `-w, --width <number>` - Output width in pixels (preserves aspect ratio if height not specified)
93
+ - `-h, --height <number>` - Output height in pixels (preserves aspect ratio if width not specified)
94
+
95
+ #### Format
96
+ - `-f, --format <format>` - Output format: `png`, `jpg`, `webp`, or `avif`
97
+
98
+ #### Output
99
+ - `-o, --out <dir>` - Output directory (default: `./pulp-image-results`)
100
+ - **Why use --out?** This keeps your original files safe and organizes processed images in a dedicated folder. The output directory is created automatically if it doesn't exist.
101
+
102
+ #### Quality
103
+ - `--quality <number>` - Quality for lossy formats (1-100). Defaults: JPG=80, WebP=80, AVIF=50
104
+ - `--lossless` - Use lossless compression where supported (PNG, WebP, AVIF)
105
+
106
+ **Compression Behavior:**
107
+ - **PNG**: Always lossless (no quality setting available)
108
+ - **JPG**: Always lossy, default quality 80 (does not support lossless)
109
+ - **WebP**: Lossy by default (quality 80), can use `--lossless` for lossless compression
110
+ - **AVIF**: Lossy by default (quality 50), can use `--lossless` for lossless compression
111
+
112
+ **Note:** Resize operations do NOT affect compression. Resizing only changes image dimensions. Compression/quality is determined by the format and quality settings.
113
+
114
+ #### Transparency
115
+ - `--background <color>` - Background color for flattening transparency (hex format, default: `#ffffff`)
116
+ - `--alpha-mode <mode>` - Alpha handling: `flatten` (default) or `error`
117
+
118
+ #### Safety
119
+ - `--overwrite` - Overwrite existing output files (default: skip existing files)
120
+ - `--delete-original` - Delete original files after successful processing (only if paths differ)
121
+
122
+ #### Other
123
+ - `-v, --verbose` - Show detailed per-file processing information
124
+ - `--help` - Display help information
125
+ - `--version` - Show version number
126
+
127
+ ## Examples
128
+
129
+ ### Resize Images
130
+
131
+ ```bash
132
+ # Resize by width (preserves aspect ratio)
133
+ pulp image.png --width 800
134
+
135
+ # Resize by height (preserves aspect ratio)
136
+ pulp image.png --height 600
137
+
138
+ # Resize to exact dimensions
139
+ pulp image.png --width 800 --height 600
140
+ ```
141
+
142
+ ### Format Conversion
143
+
144
+ ```bash
145
+ # Convert PNG to WebP (preserves transparency)
146
+ pulp image.png --format webp
147
+
148
+ # Convert PNG to JPG (flattens transparency to white)
149
+ pulp image.png --format jpg
150
+
151
+ # Convert with custom background color
152
+ pulp image.png --format jpg --background "#ff0000"
153
+
154
+ # Convert to lossless WebP
155
+ pulp image.png --format webp --lossless
156
+ ```
157
+
158
+ ### Suffix Options
159
+
160
+ ```bash
161
+ # Auto suffix (adds size to filename)
162
+ pulp image.png --width 800 --auto-suffix
163
+ # Output: image-800w.png
164
+
165
+ # Custom suffix
166
+ pulp image.png --suffix "optimized"
167
+ # Output: image-optimized.png
168
+
169
+ # Combined suffixes (auto first, custom second)
170
+ pulp image.png --width 800 --auto-suffix --suffix "thumb"
171
+ # Output: image-800w-thumb.png
172
+ ```
173
+
174
+ ### Batch Processing
175
+
176
+ ```bash
177
+ # Process all images in a directory
178
+ pulp ./images --format webp --out ./output
179
+
180
+ # Resize all images with auto-suffix
181
+ pulp ./images --width 800 --auto-suffix --out ./output
182
+
183
+ # Verbose mode (shows per-file details)
184
+ pulp ./images --format webp --out ./output --verbose
185
+
186
+ # Overwrite existing files
187
+ pulp ./images --format webp --out ./output --overwrite
188
+ ```
189
+
190
+ ### Safety Features
191
+
192
+ ```bash
193
+ # Safe processing (output to separate directory)
194
+ pulp image.png --format webp --out ./pulp-image-results
195
+
196
+ # Overwrite existing output files
197
+ pulp image.png --format webp --out ./pulp-image-results --overwrite
198
+
199
+ # Delete original after successful processing
200
+ pulp image.png --format webp --out ./pulp-image-results --delete-original
201
+ ```
202
+
203
+ ## Safety Features
204
+
205
+ pulp-image is designed with safety in mind:
206
+
207
+ - **No overwrites by default** - Existing output files are skipped unless `--overwrite` is used
208
+ - **Delete original safety** - Only deletes after successful processing and only if input/output paths differ
209
+ - **Same path protection** - Prevents accidental in-place overwrites
210
+ - **Batch resilience** - Continues processing even if individual files fail
211
+ - **Clear error messages** - Helpful guidance when something goes wrong
212
+
213
+ ## Output Directory (--out)
214
+
215
+ The `--out` option specifies where processed images are saved. Here's why it's useful:
216
+
217
+ - **Keeps originals safe** - Your source files remain untouched
218
+ - **Organizes outputs** - All processed images in one place
219
+ - **Prevents accidents** - No risk of overwriting originals
220
+ - **Default location** - Uses `./pulp-image-results` if not specified
221
+ - **Auto-creation** - Creates the directory if it doesn't exist
222
+
223
+ Example:
224
+ ```bash
225
+ # Process images and save to ./output directory
226
+ pulp ./images --format webp --out ./output
227
+
228
+ # Your originals in ./images remain safe
229
+ # Processed images go to ./output
230
+ ```
231
+
232
+ ## Supported Formats
233
+
234
+ ### Input Formats
235
+ - PNG
236
+ - JPG/JPEG
237
+ - WebP
238
+ - AVIF
239
+
240
+ ### Output Formats
241
+ - PNG
242
+ - JPG
243
+ - WebP
244
+ - AVIF
245
+
246
+ ## Compression & Quality
247
+
248
+ ### Default Compression Behavior
249
+
250
+ Each format has different default compression behavior:
251
+
252
+ - **PNG**: Always lossless (no quality setting available)
253
+ - **JPG**: Always lossy, default quality 80 (does not support lossless)
254
+ - **WebP**: Lossy by default (quality 80), supports lossless with `--lossless`
255
+ - **AVIF**: Lossy by default (quality 50), supports lossless with `--lossless`
256
+
257
+ **Important:** Resize operations do NOT affect compression. Resizing only changes image dimensions. Compression/quality is determined by the format and quality settings.
258
+
259
+ ### Using Lossless Compression
260
+
261
+ ```bash
262
+ # Lossless WebP
263
+ pulp image.png --format webp --lossless
264
+
265
+ # Lossless AVIF
266
+ pulp image.png --format avif --lossless
267
+
268
+ # PNG is already lossless (no flag needed)
269
+ pulp image.jpg --format png
270
+ ```
271
+
272
+ ### Custom Quality Settings
273
+
274
+ ```bash
275
+ # High quality JPG
276
+ pulp image.png --format jpg --quality 95
277
+
278
+ # Lower quality WebP (smaller file)
279
+ pulp image.png --format webp --quality 60
280
+
281
+ # Custom AVIF quality
282
+ pulp image.png --format avif --quality 70
283
+ ```
284
+
285
+ ## Transparency Handling
286
+
287
+ When converting images with transparency to formats that don't support it (like JPG):
288
+
289
+ - **Default behavior**: Flattens transparency onto white background
290
+ - **Custom background**: Use `--background "#color"` to specify a color
291
+ - **Error mode**: Use `--alpha-mode error` to fail instead of flattening
292
+
293
+ Example:
294
+ ```bash
295
+ # Flatten transparency to red background
296
+ pulp image.png --format jpg --background "#ff0000"
297
+
298
+ # Fail if transparency exists
299
+ pulp image.png --format jpg --alpha-mode error
300
+ ```
301
+
302
+ ## Statistics and Reporting
303
+
304
+ pulp-image provides detailed statistics:
305
+
306
+ - **Per-file stats**: Original size, final size, bytes saved, percent saved
307
+ - **Batch summary**: Total files processed, total sizes, overall savings
308
+ - **Skipped files**: Count and reasons (in verbose mode)
309
+ - **Failed files**: Count and errors (in verbose mode)
310
+
311
+ Example output:
312
+ ```
313
+ āœ“ Processed: 7 file(s)
314
+ Total original size: 10.07 MB
315
+ Total final size: 821.78 KB
316
+ Total saved: 9.26 MB (92.03%)
317
+ ```
318
+
319
+ ## Interactive Documentation
320
+
321
+ For a beautiful interactive documentation with examples, open:
322
+ ```
323
+ docs/index.html
324
+ ```
325
+
326
+ ## License
327
+
328
+ MIT
329
+
330
+ ## Author
331
+
332
+ Rebellion Geeks
package/bin/pulp.js ADDED
@@ -0,0 +1,251 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { readFileSync } from 'fs';
4
+ import { dirname, resolve } from 'path';
5
+ import { fileURLToPath } from 'url';
6
+ const __filename = fileURLToPath(import.meta.url);
7
+ const __dirname = dirname(__filename);
8
+
9
+ const pkg = JSON.parse(
10
+ readFileSync(resolve(__dirname, '../package.json'), 'utf-8')
11
+ );
12
+
13
+
14
+ import { Command } from 'commander';
15
+ import chalk from 'chalk';
16
+ import { banner } from '../src/banner.js';
17
+ import { formatBytes } from '../src/stats.js';
18
+ import { planTasks } from '../src/planTasks.js';
19
+ import { Reporter } from '../src/reporter.js';
20
+ import { runJob } from '../src/runJob.js';
21
+ import { startUIServer } from '../src/uiServer.js';
22
+ import { statSync, existsSync } from 'fs';
23
+
24
+ const program = new Command();
25
+
26
+ program
27
+ .name('pulp')
28
+ .description('A CLI tool for processing images with resize, format conversion, and optimization')
29
+ .version(pkg.version)
30
+ .addHelpText('before', chalk.cyan(banner))
31
+ .argument('[input]', 'Input file or directory')
32
+ .option('-w, --width <number>', 'Output width in pixels')
33
+ .option('-h, --height <number>', 'Output height in pixels')
34
+ .option('-f, --format <format>', 'Output format (png, jpg, webp, avif)')
35
+ .option('-o, --out <dir>', 'Output directory (default: ./pulp-image-results). Creates directory if it doesn\'t exist. Keeps originals safe by saving processed images separately.')
36
+ .option('--suffix <text>', 'Custom suffix to add before extension')
37
+ .option('--auto-suffix', 'Automatically add size-based suffix')
38
+ .option('--quality <number>', 'Quality for lossy formats (1-100). Defaults: JPG=80, WebP=80, AVIF=50')
39
+ .option('--lossless', 'Use lossless compression where supported (PNG, WebP, AVIF). Note: PNG is always lossless. JPG does not support lossless.')
40
+ .option('--background <color>', 'Background color for transparency flattening', '#ffffff')
41
+ .option('--alpha-mode <mode>', 'Alpha handling: flatten or error', 'flatten')
42
+ .option('--overwrite', 'Overwrite existing output files')
43
+ .option('--delete-original', 'Delete original files after processing')
44
+ .option('-v, --verbose', 'Verbose output')
45
+ .addHelpText('after', `
46
+ Examples:
47
+ $ pulp image.png --format webp --quality 95
48
+ $ pulp image.png --width 800
49
+ $ pulp image.png --format webp --out ./output
50
+ $ pulp image.png --format jpg --quality 95
51
+ $ pulp image.png --format webp --quality 60
52
+ $ pulp image.png --width 800 --height 600 --auto-suffix
53
+ $ pulp ./images --format webp --out ./output --verbose
54
+ $ pulp image.png --format jpg --background "#ff0000"
55
+ $ pulp image.png --format avif --quality 70
56
+ $ pulp ./images --width 800 --auto-suffix --suffix "thumb" --out ./pulp-image-results
57
+
58
+ About --out:
59
+ The --out option specifies where processed images are saved (default: ./pulp-image-results).
60
+ This keeps your original files safe and organizes outputs in a dedicated folder.
61
+ The output directory is created automatically if it doesn't exist.
62
+
63
+ Compression Behavior:
64
+ PNG: Always lossless (no quality setting)
65
+ JPG: Always lossy, default quality 80 (does not support lossless)
66
+ WebP: Lossy by default (quality 80), use --lossless for lossless
67
+ AVIF: Lossy by default (quality 50), use --lossless for lossless
68
+ Note: Resize does not affect compression - it only changes dimensions.
69
+
70
+ `)
71
+ .action(async (input, options) => {
72
+ // Display banner
73
+ console.log(chalk.cyan(banner));
74
+
75
+ // Normalize config
76
+ const config = {
77
+ input: input || null,
78
+ width: options.width ? parseInt(options.width, 10) : null,
79
+ height: options.height ? parseInt(options.height, 10) : null,
80
+ format: options.format || null,
81
+ out: options.out || './pulp-image-results',
82
+ suffix: options.suffix || null,
83
+ autoSuffix: options.autoSuffix || false,
84
+ quality: options.quality ? parseInt(options.quality, 10) : null,
85
+ lossless: options.lossless || false,
86
+ background: options.background || '#ffffff',
87
+ alphaMode: options.alphaMode || 'flatten',
88
+ overwrite: options.overwrite || false,
89
+ deleteOriginal: options.deleteOriginal || false,
90
+ verbose: options.verbose || false
91
+ };
92
+
93
+ if (!input) {
94
+ console.log(chalk.yellow('\nNo input specified. Use --help for usage information.'));
95
+ process.exit(1);
96
+ }
97
+
98
+ // Resolve input path
99
+ const inputPath = resolve(input);
100
+
101
+ if (!existsSync(inputPath)) {
102
+ console.error(chalk.red(`\nError: Input not found: ${inputPath}`));
103
+ process.exit(1);
104
+ }
105
+
106
+ const inputStats = statSync(inputPath);
107
+ const isDirectory = inputStats.isDirectory();
108
+ const isFile = inputStats.isFile();
109
+
110
+ if (!isFile && !isDirectory) {
111
+ console.error(chalk.red(`\nError: Input must be a file or directory: ${inputPath}`));
112
+ process.exit(1);
113
+ }
114
+
115
+ // Handle directory planning for display (before runJob)
116
+ if (isDirectory) {
117
+ let tasks;
118
+ try {
119
+ tasks = planTasks(inputPath);
120
+ } catch (error) {
121
+ console.error(chalk.red(`\nError reading directory: ${error.message}`));
122
+ process.exit(1);
123
+ }
124
+
125
+ if (tasks.length === 0) {
126
+ console.log(chalk.yellow(`\nNo supported image files found in: ${inputPath}`));
127
+ process.exit(0);
128
+ }
129
+
130
+ console.log(chalk.gray(`\nFound ${tasks.length} image file(s) to process...\n`));
131
+ }
132
+
133
+ // Use runJob for orchestration (no terminal output from runJob)
134
+ let results;
135
+ try {
136
+ if (isFile && config.verbose) {
137
+ console.log(chalk.gray(`\nProcessing: ${inputPath}`));
138
+ }
139
+
140
+ results = await runJob(inputPath, config);
141
+ } catch (error) {
142
+ console.error(chalk.red(`\nError: ${error.message}`));
143
+ if (config.verbose) {
144
+ console.error(error);
145
+ }
146
+ process.exit(1);
147
+ }
148
+
149
+ // Display results exactly as before
150
+ if (isFile) {
151
+ // Single file: show detailed result or skip/error
152
+ if (results.processed.length > 0) {
153
+ const result = results.processed[0];
154
+ console.log(chalk.green(`\nāœ“ Processed: ${result.outputPath}`));
155
+ console.log(chalk.gray(` Original: ${formatBytes(result.originalSize)} (${result.metadata.width}x${result.metadata.height})`));
156
+ console.log(chalk.gray(` Final: ${formatBytes(result.finalSize)}`));
157
+ console.log(chalk.gray(` Saved: ${formatBytes(result.bytesSaved)} (${result.percentSaved}%)`));
158
+
159
+ if (result.deleteError) {
160
+ console.log(chalk.yellow(` Warning: Failed to delete original: ${result.deleteError}`));
161
+ }
162
+ } else if (results.skipped.length > 0) {
163
+ const skipped = results.skipped[0];
164
+ console.log(chalk.yellow(`\n⚠ Skipped: ${skipped.filePath}`));
165
+ console.log(chalk.gray(` Reason: ${skipped.reason}`));
166
+ } else if (results.failed.length > 0) {
167
+ const failed = results.failed[0];
168
+ console.error(chalk.red(`\nāœ— Error: ${failed.error}`));
169
+ if (config.verbose) {
170
+ console.error(failed);
171
+ }
172
+ }
173
+ } else {
174
+ // Directory: show per-file results in verbose mode, then summary
175
+ if (config.verbose) {
176
+ // Reconstruct reporter for per-file display
177
+ const reporter = new Reporter();
178
+ results.processed.forEach(r => reporter.recordProcessed(r));
179
+ results.skipped.forEach(s => reporter.recordSkipped(s.filePath, s.reason));
180
+ results.failed.forEach(f => reporter.recordFailed(f.filePath, new Error(f.error)));
181
+
182
+ // Show per-file results
183
+ results.processed.forEach(result => {
184
+ reporter.printFileResult(result, true);
185
+ });
186
+
187
+ // Show skipped files
188
+ results.skipped.forEach(({ filePath, reason }) => {
189
+ console.log(chalk.yellow(`⚠ Skipped: ${filePath}`));
190
+ console.log(chalk.gray(` Reason: ${reason}`));
191
+ });
192
+
193
+ // Show failed files
194
+ results.failed.forEach(({ filePath, error }) => {
195
+ console.error(chalk.red(`āœ— Failed: ${filePath}`));
196
+ console.error(chalk.gray(` Error: ${error}`));
197
+ });
198
+ } else {
199
+ // Non-verbose: just show failures
200
+ results.failed.forEach(({ filePath, error }) => {
201
+ console.error(chalk.red(`āœ— Failed: ${filePath}`));
202
+ });
203
+ }
204
+ }
205
+
206
+ // Print summary for batch processing or if there were issues
207
+ if (isDirectory || results.skipped.length > 0 || results.failed.length > 0) {
208
+ const reporter = new Reporter();
209
+ results.processed.forEach(r => reporter.recordProcessed(r));
210
+ results.skipped.forEach(s => reporter.recordSkipped(s.filePath, s.reason));
211
+ results.failed.forEach(f => reporter.recordFailed(f.filePath, new Error(f.error)));
212
+ reporter.printSummary(config.verbose);
213
+ }
214
+ });
215
+
216
+ // UI command
217
+ program
218
+ .command('ui')
219
+ .description('Start the browser-based UI')
220
+ .option('-p, --port <number>', 'Port to run server on', '3000')
221
+ .action(async (options) => {
222
+ const port = parseInt(options.port || '3000', 10);
223
+
224
+ if (isNaN(port) || port < 1 || port > 65535) {
225
+ console.error(chalk.red(`\nError: Invalid port number: ${options.port}`));
226
+ process.exit(1);
227
+ }
228
+
229
+ try {
230
+ const { server } = await startUIServer(port);
231
+
232
+ // Handle graceful shutdown
233
+ const shutdown = () => {
234
+ console.log(chalk.gray('\n\nShutting down server...'));
235
+ server.close(() => {
236
+ console.log(chalk.green('Server stopped.'));
237
+ process.exit(0);
238
+ });
239
+ };
240
+
241
+ process.on('SIGINT', shutdown);
242
+ process.on('SIGTERM', shutdown);
243
+
244
+ } catch (error) {
245
+ console.error(chalk.red(`\nError starting UI server: ${error.message}`));
246
+ process.exit(1);
247
+ }
248
+ });
249
+
250
+ program.parse();
251
+
package/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "pulp-image",
3
+ "version": "0.1.0",
4
+ "description": "A CLI tool for processing images with resize, format conversion, and optimization",
5
+ "type": "module",
6
+ "main": "bin/pulp.js",
7
+ "bin": {
8
+ "pulp": "./bin/pulp.js"
9
+ },
10
+ "scripts": {
11
+ "test": "echo \"Error: no test specified\" && exit 1"
12
+ },
13
+ "keywords": [
14
+ "image",
15
+ "resize",
16
+ "convert",
17
+ "optimize",
18
+ "cli"
19
+ ],
20
+ "author": "Rebellion Geeks",
21
+ "license": "MIT",
22
+ "repository": {
23
+ "type": "git",
24
+ "url": "https://github.com/rebelliongeeks/pulp-image.git"
25
+ },
26
+ "engines": {
27
+ "node": ">=18.0.0"
28
+ },
29
+ "dependencies": {
30
+ "chalk": "^5.6.2",
31
+ "commander": "^14.0.2",
32
+ "express": "^4.18.2",
33
+ "multer": "^2.0.2",
34
+ "open": "^8.4.2",
35
+ "sharp": "^0.34.5"
36
+ }
37
+ }
package/src/banner.js ADDED
@@ -0,0 +1,10 @@
1
+ export const banner = `
2
+ ╔════════════════════════════════════════╗
3
+ ā•‘ ā•‘
4
+ ā•‘ pulp-image v0.1.0 ā•‘
5
+ ā•‘ ā•‘
6
+ ā•‘ Image processing made simple ā•‘
7
+ ā•‘ ā•‘
8
+ ā•šā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•
9
+ `;
10
+