shellfie-cli 1.0.3 → 2.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/README.md CHANGED
@@ -1,24 +1,253 @@
1
1
  # shellfie-cli
2
- create beautiful terminal screenshots using formatted string
3
2
 
4
- # usage
5
- ```bash
6
- shellfie '\x1b[105mSHELLFIE\\x1b[0m🤳' '\x1b[38;5;225mthe easiest way' '\x1b[38;5;213mto create beautiful' '\x1b[38;5;14mCLI screenshots 📸' '\x1b[38;5;199mprogrammatically 🚀' -h 300 -w 400
3
+ Transform your terminal output into beautiful SVG screenshots, directly from the command line.
4
+
5
+ ```sh
6
+ npm test | npx shellfie --title "Test Results" -o tests.svg
7
+ ```
8
+
9
+ ![npm test](examples/tests.svg)
10
+
11
+ ✅ **Zero friction** - Pipe any command output and get an SVG instantly.
12
+ ✅ **Beautiful defaults** - macOS-style terminal window with syntax highlighting.
13
+ ✅ **Fully customizable** - 12 themes, 3 templates, custom fonts, and more.
14
+ ✅ **Portable SVGs** - Embed fonts for consistent rendering everywhere.
15
+ ✅ **Run everywhere** - Terminal, CI/CD, npm scripts.
16
+
17
+ ## Installation
18
+
19
+ ```sh
20
+ # Use directly with npx (no install needed)
21
+ npx shellfie-cli --help
22
+
23
+ # Or install globally
24
+ npm install -g shellfie-cli
25
+
26
+ # Or add to your project
27
+ npm install shellfie-cli --save-dev
28
+ ```
29
+
30
+ ## Quick Start
31
+
32
+ ### Pipe command output
33
+
34
+ ```sh
35
+ # Capture npm test output
36
+ npm test 2>&1 | shellfie -o test-results.svg
37
+
38
+ # Capture git log
39
+ git log --oneline -10 | shellfie --title "Recent Commits" -o commits.svg
40
+
41
+ # Capture any command with colors
42
+ ls -la --color=always | shellfie --theme nord
43
+ ```
44
+
45
+ ```sh
46
+ lolcat --help | shellfie -o lolcat
47
+ ```
48
+
49
+ ![npm test](examples/lolcat.svg)
50
+
51
+ ### Read from a file
52
+
53
+ ```sh
54
+ # Convert a log file to SVG
55
+ shellfie error.log -o error-screenshot.svg
56
+
57
+ # ASCII art
58
+ shellfie banner.txt --template minimal --theme monokai
59
+ ```
60
+
61
+ ### Output to stdout
62
+
63
+ ```sh
64
+ # Pipe SVG to another command or file
65
+ cat output.txt | shellfie --stdout > output.svg
66
+
67
+ # Use with clipboard (macOS)
68
+ echo "Hello World" | shellfie --stdout | pbcopy
69
+ ```
70
+
71
+ ## Options
72
+
73
+ | Option | Alias | Description |
74
+ |--------|-------|-------------|
75
+ | `--output <path>` | `-o` | Output file path (default: `./shellfie.svg`) |
76
+ | `--name <name>` | `-n` | Output filename (without extension) |
77
+ | `--stdout` | | Print SVG to stdout instead of file |
78
+ | `--template <name>` | `-t` | Window style: `macos`, `windows`, `minimal` |
79
+ | `--theme <name>` | `-T` | Color theme (see [Themes](#themes)) |
80
+ | `--title <text>` | | Window title bar text |
81
+ | `--watermark <text>` | | Text in bottom-right corner (supports ANSI colors) |
82
+ | `--width <cols>` | `-w` | Terminal width in columns (auto-detected) |
83
+ | `--padding <value>` | `-p` | Padding in pixels (`16` or `top,right,bottom,left`) |
84
+ | `--font-size <px>` | | Font size in pixels (default: `14`) |
85
+ | `--line-height <n>` | | Line height multiplier (default: `1.4`) |
86
+ | `--font-family <css>` | | CSS font-family string |
87
+ | `--embed-font` | | Embed system font for portable SVGs |
88
+ | `--no-controls` | | Hide window control buttons |
89
+ | `--no-custom-glyphs` | | Use font glyphs instead of pixel-perfect box drawing |
90
+ | `--header-height <px>` | | Custom header bar height |
91
+ | `--header-color <hex>` | | Header background color |
92
+ | `--footer-height <px>` | | Footer bar height |
93
+ | `--footer-color <hex>` | | Footer background color |
94
+ | `--list-themes` | | List all available themes |
95
+ | `--list-templates` | | List all available templates |
96
+ | `--help` | `-h` | Show help |
97
+ | `--version` | `-v` | Show version |
98
+
99
+ ## Themes
100
+
101
+ ```sh
102
+ shellfie --list-themes
103
+ ```
104
+
105
+ Available themes:
106
+
107
+ | Theme | Description |
108
+ |-------|-------------|
109
+ | `dracula` | Dark, vibrant purple |
110
+ | `nord` | Arctic, bluish colors |
111
+ | `tokyoNight` | Dark, moody |
112
+ | `oneDark` | VS Code One Dark |
113
+ | `monokai` | Classic dark |
114
+ | `catppuccinMocha` | Warm, cozy dark |
115
+ | `githubDark` | GitHub dark mode |
116
+ | `githubLight` | GitHub light mode |
117
+ | `gruvboxDark` | Retro dark |
118
+ | `gruvboxLight` | Retro light |
119
+ | `solarizedDark` | Solarized dark |
120
+ | `solarizedLight` | Solarized light |
121
+
122
+ ## Templates
123
+
124
+ ```sh
125
+ shellfie --list-templates
126
+ ```
127
+
128
+ | Template | Description |
129
+ |----------|-------------|
130
+ | `macos` | macOS-style with traffic light buttons (default) |
131
+ | `windows` | Windows-style with square buttons |
132
+ | `minimal` | Clean, no window chrome |
133
+
134
+ ## Examples
135
+
136
+ ### Capture test results with a theme
137
+
138
+ ```sh
139
+ npm test 2>&1 | shellfie --theme dracula --title "Unit Tests" -o tests.svg
7
140
  ```
8
- ![](https://github.com/tool3/shellfie/blob/master/shellfies/shellfie.png?raw=true)
9
- or
10
- ```bash
11
- echo "\x1b[34mHello world" | shellfie -w 200 -h 200 -n hello
141
+ ![tests dracula](examples/tests-dracula.svg)
142
+
143
+ ### Git log with minimal template
144
+
145
+ ```sh
146
+ git log --oneline --graph --color=always | shellfie -t minimal --theme githubDark -o git-log.svg
147
+ ```
148
+ ![git log](examples/git-log.svg)
149
+
150
+ ### Custom padding and font size
151
+
152
+ ```sh
153
+ cat script.sh | shellfie --padding "20,30" --font-size 30 -o script.svg
154
+ ```
155
+ ![script](examples/script.svg)
156
+
157
+ ### Embed font for sharing
158
+
159
+ ```sh
160
+ ls -l | lolcat -f | shellfie --embed-font -o portable.svg
161
+ ```
162
+ ![portable](examples/portable.svg)
163
+
164
+ ### Add watermark
165
+
166
+ ```sh
167
+ ifconfig | grep inet | shellfie --watermark "@$USER" --theme monokai
168
+ ```
169
+ ![watermark](examples/watermark.svg)
170
+
171
+ ### Colored watermark
172
+
173
+ Watermarks support ANSI escape sequences for colors and styles:
174
+
175
+ ```sh
176
+ # Red watermark using octal notation
177
+ echo "test" | shellfie --watermark '\033[31m@username\033[0m'
178
+
179
+ # Green watermark using hex notation
180
+ echo "test" | shellfie --watermark '\x1b[32m@username\x1b[0m'
181
+
182
+ # Bold blue watermark using shorthand notation
183
+ echo "test" | shellfie --watermark '\e[1;34m@username\e[0m'
184
+
185
+ # Works with bash variables
186
+ echo "test" | shellfie --watermark '\e[1;32m@$USER\e[0m'
187
+ ```
188
+
189
+ ### With header and footer bars
190
+
191
+ ```sh
192
+ htop -n 1 | shellfie --header-height 30 --footer-height 20 -o system.svg
193
+ ```
194
+
195
+ ## Tips
196
+
197
+ ### Preserve colors
198
+
199
+ Many commands disable colors when piped. Force them with:
200
+
201
+ ```sh
202
+ # ls
203
+ ls -la --color=always | shellfie
204
+
205
+ # grep
206
+ grep --color=always pattern file | shellfie
207
+
208
+ # git
209
+ git -c color.ui=always log | shellfie
210
+
211
+ # npm
212
+ npm test --color | shellfie
213
+ ```
214
+
215
+ ### Capture stderr too
216
+
217
+ Include error output with `2>&1`:
218
+
219
+ ```sh
220
+ npm test 2>&1 | shellfie -o output.svg
221
+ ```
222
+
223
+ ### CI/CD Integration
224
+
225
+ ```yaml
226
+ # GitHub Actions example
227
+ - name: Generate test screenshot
228
+ run: npm test 2>&1 | npx shellfie-cli --theme githubDark -o test-output.svg
229
+
230
+ - name: Upload artifact
231
+ uses: actions/upload-artifact@v4
232
+ with:
233
+ name: test-screenshot
234
+ path: test-output.svg
12
235
  ```
13
- ![](https://github.com/tool3/shellfie-cli/blob/master/shellfies/hello.png?raw=true)
14
236
 
15
- # useful examples
16
- ```bash
17
- lolcat --help > help.txt
18
- cat help.txt | shellfie -m raw
237
+ ### npm scripts
238
+
239
+ ```json
240
+ {
241
+ "scripts": {
242
+ "test:screenshot": "npm test 2>&1 | shellfie --theme dracula -o tests.svg"
243
+ }
244
+ }
19
245
  ```
20
- ![](https://github.com/tool3/shellfied/blob/master/lolcat.png?raw=true)
21
246
 
22
- # options
247
+ ## Related
248
+
249
+ - [shellfie](https://github.com/tool3/shellfie) - The core library for programmatic use
250
+
251
+ ## License
23
252
 
24
- see [shellfie](https://github.com/tool3/shellfie)
253
+ MIT
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/dist/cli.js ADDED
@@ -0,0 +1,183 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ const yargs_1 = __importDefault(require("yargs"));
8
+ const spinner_1 = require("./spinner");
9
+ const shellfie_1 = require("./shellfie");
10
+ const createParser = () => yargs_1.default
11
+ .scriptName('shellfie')
12
+ .usage('$0 [options] [file]')
13
+ .usage('')
14
+ .usage('Transform terminal output into beautiful SVG images')
15
+ .option('output', {
16
+ alias: 'o',
17
+ type: 'string',
18
+ describe: 'Output file path (defaults to ./shellfie.svg)',
19
+ })
20
+ .option('name', {
21
+ alias: 'n',
22
+ type: 'string',
23
+ describe: 'Output filename (without extension)',
24
+ })
25
+ .option('stdout', {
26
+ type: 'boolean',
27
+ describe: 'Output SVG to stdout instead of file',
28
+ default: false,
29
+ })
30
+ .option('template', {
31
+ alias: 't',
32
+ type: 'string',
33
+ choices: shellfie_1.TEMPLATE_NAMES,
34
+ describe: 'Window template style',
35
+ default: 'macos',
36
+ })
37
+ .option('theme', {
38
+ alias: 'T',
39
+ type: 'string',
40
+ choices: shellfie_1.THEME_NAMES,
41
+ describe: 'Color theme',
42
+ })
43
+ .option('title', {
44
+ type: 'string',
45
+ describe: 'Window title text',
46
+ })
47
+ .option('width', {
48
+ alias: 'w',
49
+ type: 'number',
50
+ describe: 'Terminal width in columns (auto-detected if not set)',
51
+ })
52
+ .option('padding', {
53
+ alias: 'p',
54
+ type: 'string',
55
+ describe: 'Padding in pixels (single value or "top,right,bottom,left")',
56
+ })
57
+ .option('font-size', {
58
+ type: 'number',
59
+ describe: 'Font size in pixels',
60
+ default: 14,
61
+ })
62
+ .option('line-height', {
63
+ type: 'number',
64
+ describe: 'Line height multiplier',
65
+ default: 1.4,
66
+ })
67
+ .option('watermark', {
68
+ type: 'string',
69
+ describe: 'Watermark text (bottom-right corner)',
70
+ })
71
+ .option('no-controls', {
72
+ type: 'boolean',
73
+ describe: 'Hide window control buttons',
74
+ default: false,
75
+ })
76
+ .option('no-custom-glyphs', {
77
+ type: 'boolean',
78
+ describe: 'Use font glyphs instead of pixel-perfect box drawing',
79
+ default: false,
80
+ })
81
+ .option('font-family', {
82
+ type: 'string',
83
+ describe: 'CSS font-family string',
84
+ })
85
+ .option('embed-font', {
86
+ type: 'boolean',
87
+ describe: 'Embed system font in SVG (for portability)',
88
+ default: false,
89
+ })
90
+ .option('header-height', {
91
+ type: 'number',
92
+ describe: 'Custom header bar height (enables header)',
93
+ })
94
+ .option('header-color', {
95
+ type: 'string',
96
+ describe: 'Header background color (hex)',
97
+ })
98
+ .option('footer-height', {
99
+ type: 'number',
100
+ describe: 'Footer bar height (enables footer)',
101
+ })
102
+ .option('footer-color', {
103
+ type: 'string',
104
+ describe: 'Footer background color (hex)',
105
+ })
106
+ .option('list-themes', {
107
+ type: 'boolean',
108
+ describe: 'List all available themes',
109
+ })
110
+ .option('list-templates', {
111
+ type: 'boolean',
112
+ describe: 'List all available templates',
113
+ })
114
+ .example('cat output.txt | $0 -o screenshot.svg', 'Create SVG from piped input')
115
+ .example('$0 terminal.txt --theme dracula', 'Create SVG from file with theme')
116
+ .example('npm test 2>&1 | $0 --title "Tests"', 'Capture command output with title')
117
+ .example('$0 --list-themes', 'List all available themes')
118
+ .demandCommand(0)
119
+ .help()
120
+ .alias('help', 'h')
121
+ .version()
122
+ .alias('version', 'v')
123
+ .wrap(Math.min(100, process.stdout.columns || 80))
124
+ .showHelpOnFail(true);
125
+ const exit = (code, message) => {
126
+ if (message)
127
+ console.error(message);
128
+ process.exit(code);
129
+ };
130
+ const handleListCommands = (argv) => {
131
+ if (argv['list-themes']) {
132
+ (0, shellfie_1.listThemes)();
133
+ return true;
134
+ }
135
+ if (argv['list-templates']) {
136
+ (0, shellfie_1.listTemplates)();
137
+ return true;
138
+ }
139
+ return false;
140
+ };
141
+ const fetchInput = async (inputFile) => (0, shellfie_1.loadInput)(inputFile).catch(() => {
142
+ throw new Error(`Cannot read file "${inputFile}"`);
143
+ });
144
+ const validateInput = (input) => {
145
+ if (!input.trim())
146
+ throw new Error('Input is empty.');
147
+ };
148
+ const writeSvg = (svg, argv, inputFile) => {
149
+ const outputPath = (0, shellfie_1.resolveOutputPath)(argv, inputFile);
150
+ if (argv.stdout) {
151
+ (0, shellfie_1.outputToStdout)(svg);
152
+ process.exit(0);
153
+ }
154
+ (0, shellfie_1.outputToFile)(svg, outputPath);
155
+ return outputPath;
156
+ };
157
+ const run = async () => {
158
+ const parser = createParser();
159
+ const argv = (await parser.parse());
160
+ if (handleListCommands(argv))
161
+ process.exit(0);
162
+ const inputFile = argv._[0];
163
+ const input = await fetchInput(inputFile).catch((err) => exit(1, `Error: ${err.message}`));
164
+ if (!input) {
165
+ parser.showHelp();
166
+ process.exit(0);
167
+ }
168
+ validateInput(input);
169
+ const spinner = (0, spinner_1.createSpinner)('Creating SVG');
170
+ if (!argv.stdout)
171
+ spinner.start();
172
+ try {
173
+ const svg = await (0, shellfie_1.generateSvg)(input, argv);
174
+ const outputPath = writeSvg(svg, argv, inputFile);
175
+ spinner.success(`Created ${outputPath}`);
176
+ }
177
+ catch (err) {
178
+ spinner.fail('Failed to create SVG');
179
+ exit(1, err instanceof Error ? err.message : String(err));
180
+ }
181
+ };
182
+ run();
183
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import { themes, type shellfieOptions, type Theme } from 'shellfie';
2
+ import { type CliArgs, type BuildOptionsResult } from './utils';
3
+ export declare const THEME_NAMES: (keyof typeof themes)[];
4
+ export declare const TEMPLATE_NAMES: readonly ["macos", "windows", "minimal"];
5
+ export declare const listThemes: () => void;
6
+ export declare const listTemplates: () => void;
7
+ export declare const resolveTheme: (themeName?: string) => Theme | undefined;
8
+ export declare const toShellfieOptions: ({ themeName, ...rest }: BuildOptionsResult) => shellfieOptions;
9
+ export declare const loadInput: (inputFile?: string) => Promise<string>;
10
+ export declare const generateSvg: (input: string, argv: Partial<CliArgs>) => Promise<string>;
11
+ export declare const outputToStdout: (svg: string) => void;
12
+ export declare const outputToFile: (svg: string, outputPath: string) => void;
13
+ export declare const resolveOutputPath: (argv: {
14
+ output?: string;
15
+ name?: string;
16
+ }, inputFile?: string) => string;
17
+ //# sourceMappingURL=shellfie.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shellfie.d.ts","sourceRoot":"","sources":["../src/shellfie.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAiB,KAAK,eAAe,EAAE,KAAK,KAAK,EAAE,MAAM,UAAU,CAAC;AACnF,OAAO,EAA0C,KAAK,OAAO,EAAE,KAAK,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAExG,eAAO,MAAM,WAAW,EAA0B,CAAC,MAAM,OAAO,MAAM,CAAC,EAAE,CAAC;AAC1E,eAAO,MAAM,cAAc,0CAA2C,CAAC;AAOvE,eAAO,MAAM,UAAU,QAAO,IAAmD,CAAC;AAElF,eAAO,MAAM,aAAa,QAAO,IAAyD,CAAC;AAE3F,eAAO,MAAM,YAAY,GAAI,YAAY,MAAM,KAAG,KAAK,GAAG,SACmB,CAAC;AAE9E,eAAO,MAAM,iBAAiB,GAAI,wBAAwB,kBAAkB,KAAG,eAG7E,CAAC;AAEH,eAAO,MAAM,SAAS,GAAI,YAAY,MAAM,KAAG,OAAO,CAAC,MAAM,CAAyB,CAAC;AAEvF,eAAO,MAAM,WAAW,GAAI,OAAO,MAAM,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,KAAG,OAAO,CAAC,MAAM,CACrB,CAAC;AAE9D,eAAO,MAAM,cAAc,GAAI,KAAK,MAAM,KAAG,IAE5C,CAAC;AAEF,eAAO,MAAM,YAAY,GAAI,KAAK,MAAM,EAAE,YAAY,MAAM,KAAG,IAE9D,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAC5B,MAAM;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,EACxC,YAAY,MAAM,KACjB,MACiE,CAAC"}
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resolveOutputPath = exports.outputToFile = exports.outputToStdout = exports.generateSvg = exports.loadInput = exports.toShellfieOptions = exports.resolveTheme = exports.listTemplates = exports.listThemes = exports.TEMPLATE_NAMES = exports.THEME_NAMES = void 0;
4
+ const node_fs_1 = require("node:fs");
5
+ const shellfie_1 = require("shellfie");
6
+ const utils_1 = require("./utils");
7
+ exports.THEME_NAMES = Object.keys(shellfie_1.themes);
8
+ exports.TEMPLATE_NAMES = ['macos', 'windows', 'minimal'];
9
+ const printList = (title, items) => {
10
+ console.log(title);
11
+ items.forEach((name) => console.log(` ${name}`));
12
+ };
13
+ const listThemes = () => printList('Available themes:', exports.THEME_NAMES);
14
+ exports.listThemes = listThemes;
15
+ const listTemplates = () => printList('Available templates:', exports.TEMPLATE_NAMES);
16
+ exports.listTemplates = listTemplates;
17
+ const resolveTheme = (themeName) => themeName ? shellfie_1.themes[themeName] : undefined;
18
+ exports.resolveTheme = resolveTheme;
19
+ const toShellfieOptions = ({ themeName, ...rest }) => ({
20
+ ...rest,
21
+ theme: (0, exports.resolveTheme)(themeName),
22
+ });
23
+ exports.toShellfieOptions = toShellfieOptions;
24
+ const loadInput = (inputFile) => (0, utils_1.readInput)(inputFile);
25
+ exports.loadInput = loadInput;
26
+ const generateSvg = (input, argv) => (0, shellfie_1.shellfieAsync)(input, (0, exports.toShellfieOptions)((0, utils_1.buildOptions)(argv)));
27
+ exports.generateSvg = generateSvg;
28
+ const outputToStdout = (svg) => {
29
+ process.stdout.write(svg);
30
+ };
31
+ exports.outputToStdout = outputToStdout;
32
+ const outputToFile = (svg, outputPath) => {
33
+ (0, node_fs_1.writeFileSync)(outputPath, svg, 'utf-8');
34
+ };
35
+ exports.outputToFile = outputToFile;
36
+ const resolveOutputPath = (argv, inputFile) => (0, utils_1.getOutputPath)({ output: argv.output, name: argv.name, inputFile });
37
+ exports.resolveOutputPath = resolveOutputPath;
38
+ //# sourceMappingURL=shellfie.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shellfie.js","sourceRoot":"","sources":["../src/shellfie.ts"],"names":[],"mappings":";;;AAAA,qCAAwC;AACxC,uCAAmF;AACnF,mCAAwG;AAE3F,QAAA,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,iBAAM,CAA4B,CAAC;AAC7D,QAAA,cAAc,GAAG,CAAC,OAAO,EAAE,SAAS,EAAE,SAAS,CAAU,CAAC;AAEvE,MAAM,SAAS,GAAG,CAAC,KAAa,EAAE,KAAwB,EAAQ,EAAE;IAClE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACnB,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC;AACpD,CAAC,CAAC;AAEK,MAAM,UAAU,GAAG,GAAS,EAAE,CAAC,SAAS,CAAC,mBAAmB,EAAE,mBAAW,CAAC,CAAC;AAArE,QAAA,UAAU,cAA2D;AAE3E,MAAM,aAAa,GAAG,GAAS,EAAE,CAAC,SAAS,CAAC,sBAAsB,EAAE,sBAAc,CAAC,CAAC;AAA9E,QAAA,aAAa,iBAAiE;AAEpF,MAAM,YAAY,GAAG,CAAC,SAAkB,EAAqB,EAAE,CACpE,SAAS,CAAC,CAAC,CAAE,iBAAM,CAAC,SAAgC,CAAW,CAAC,CAAC,CAAC,SAAS,CAAC;AADjE,QAAA,YAAY,gBACqD;AAEvE,MAAM,iBAAiB,GAAG,CAAC,EAAE,SAAS,EAAE,GAAG,IAAI,EAAsB,EAAmB,EAAE,CAAC,CAAC;IACjG,GAAG,IAAI;IACP,KAAK,EAAE,IAAA,oBAAY,EAAC,SAAS,CAAC;CAC/B,CAAC,CAAC;AAHU,QAAA,iBAAiB,qBAG3B;AAEI,MAAM,SAAS,GAAG,CAAC,SAAkB,EAAmB,EAAE,CAAC,IAAA,iBAAS,EAAC,SAAS,CAAC,CAAC;AAA1E,QAAA,SAAS,aAAiE;AAEhF,MAAM,WAAW,GAAG,CAAC,KAAa,EAAE,IAAsB,EAAmB,EAAE,CACpF,IAAA,wBAAa,EAAC,KAAK,EAAE,IAAA,yBAAiB,EAAC,IAAA,oBAAY,EAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AADjD,QAAA,WAAW,eACsC;AAEvD,MAAM,cAAc,GAAG,CAAC,GAAW,EAAQ,EAAE;IAClD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;AAC5B,CAAC,CAAC;AAFW,QAAA,cAAc,kBAEzB;AAEK,MAAM,YAAY,GAAG,CAAC,GAAW,EAAE,UAAkB,EAAQ,EAAE;IACpE,IAAA,uBAAa,EAAC,UAAU,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC;AAC1C,CAAC,CAAC;AAFW,QAAA,YAAY,gBAEvB;AAEK,MAAM,iBAAiB,GAAG,CAC/B,IAAwC,EACxC,SAAkB,EACV,EAAE,CACV,IAAA,qBAAa,EAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;AAJxD,QAAA,iBAAiB,qBAIuC"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Minimal spinner implementation with zero dependencies.
3
+ * Shows a spinning animation while processing.
4
+ */
5
+ export interface Spinner {
6
+ start(): void;
7
+ stop(): void;
8
+ success(message: string): void;
9
+ fail(message: string): void;
10
+ }
11
+ export declare function createSpinner(text: string): Spinner;
12
+ //# sourceMappingURL=spinner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spinner.d.ts","sourceRoot":"","sources":["../src/spinner.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,MAAM,WAAW,OAAO;IACtB,KAAK,IAAI,IAAI,CAAC;IACd,IAAI,IAAI,IAAI,CAAC;IACb,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAgDnD"}
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ /**
3
+ * Minimal spinner implementation with zero dependencies.
4
+ * Shows a spinning animation while processing.
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.createSpinner = createSpinner;
8
+ const SPINNER_FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
9
+ const FRAME_INTERVAL = 80;
10
+ function createSpinner(text) {
11
+ let frameIndex = 0;
12
+ let intervalId = null;
13
+ let currentText = text;
14
+ const clearLine = () => {
15
+ if (process.stdout.isTTY) {
16
+ process.stdout.clearLine(0);
17
+ process.stdout.cursorTo(0);
18
+ }
19
+ };
20
+ const render = () => {
21
+ clearLine();
22
+ const frame = SPINNER_FRAMES[frameIndex];
23
+ process.stdout.write(`${frame} ${currentText}`);
24
+ frameIndex = (frameIndex + 1) % SPINNER_FRAMES.length;
25
+ };
26
+ return {
27
+ start() {
28
+ if (!process.stdout.isTTY) {
29
+ // Non-TTY: just print the message once
30
+ console.log(`... ${currentText}`);
31
+ return;
32
+ }
33
+ render();
34
+ intervalId = setInterval(render, FRAME_INTERVAL);
35
+ },
36
+ stop() {
37
+ if (intervalId) {
38
+ clearInterval(intervalId);
39
+ intervalId = null;
40
+ }
41
+ clearLine();
42
+ },
43
+ success(message) {
44
+ this.stop();
45
+ console.log(`\x1b[32m✓ ${message}\x1b[0m`);
46
+ },
47
+ fail(message) {
48
+ this.stop();
49
+ console.log(`\x1b[31m✗ ${message}\x1b[0m`);
50
+ },
51
+ };
52
+ }
53
+ //# sourceMappingURL=spinner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spinner.js","sourceRoot":"","sources":["../src/spinner.ts"],"names":[],"mappings":";AAAA;;;GAGG;;AAYH,sCAgDC;AA1DD,MAAM,cAAc,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;AAC1E,MAAM,cAAc,GAAG,EAAE,CAAC;AAS1B,SAAgB,aAAa,CAAC,IAAY;IACxC,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,IAAI,UAAU,GAA0B,IAAI,CAAC;IAC7C,IAAI,WAAW,GAAG,IAAI,CAAC;IAEvB,MAAM,SAAS,GAAG,GAAS,EAAE;QAC3B,IAAI,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;YACzB,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;YAC5B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,MAAM,GAAG,GAAS,EAAE;QACxB,SAAS,EAAE,CAAC;QACZ,MAAM,KAAK,GAAG,cAAc,CAAC,UAAU,CAAC,CAAC;QACzC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,KAAK,IAAI,WAAW,EAAE,CAAC,CAAC;QAChD,UAAU,GAAG,CAAC,UAAU,GAAG,CAAC,CAAC,GAAG,cAAc,CAAC,MAAM,CAAC;IACxD,CAAC,CAAC;IAEF,OAAO;QACL,KAAK;YACH,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;gBAC1B,uCAAuC;gBACvC,OAAO,CAAC,GAAG,CAAC,OAAO,WAAW,EAAE,CAAC,CAAC;gBAClC,OAAO;YACT,CAAC;YACD,MAAM,EAAE,CAAC;YACT,UAAU,GAAG,WAAW,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;QACnD,CAAC;QAED,IAAI;YACF,IAAI,UAAU,EAAE,CAAC;gBACf,aAAa,CAAC,UAAU,CAAC,CAAC;gBAC1B,UAAU,GAAG,IAAI,CAAC;YACpB,CAAC;YACD,SAAS,EAAE,CAAC;QACd,CAAC;QAED,OAAO,CAAC,OAAe;YACrB,IAAI,CAAC,IAAI,EAAE,CAAC;YACZ,OAAO,CAAC,GAAG,CAAC,aAAa,OAAO,SAAS,CAAC,CAAC;QAC7C,CAAC;QAED,IAAI,CAAC,OAAe;YAClB,IAAI,CAAC,IAAI,EAAE,CAAC;YACZ,OAAO,CAAC,GAAG,CAAC,aAAa,OAAO,SAAS,CAAC,CAAC;QAC7C,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,59 @@
1
+ export interface CliArgs {
2
+ _: (string | number)[];
3
+ output?: string;
4
+ name?: string;
5
+ stdout: boolean;
6
+ template: string;
7
+ theme?: string;
8
+ title?: string;
9
+ width?: number;
10
+ padding?: string;
11
+ 'font-size': number;
12
+ 'line-height': number;
13
+ watermark?: string;
14
+ 'no-controls': boolean;
15
+ 'no-custom-glyphs': boolean;
16
+ 'font-family'?: string;
17
+ 'embed-font': boolean;
18
+ 'header-height'?: number;
19
+ 'header-color'?: string;
20
+ 'footer-height'?: number;
21
+ 'footer-color'?: string;
22
+ 'list-themes'?: boolean;
23
+ 'list-templates'?: boolean;
24
+ }
25
+ export interface BuildOptionsResult {
26
+ template: 'macos' | 'windows' | 'minimal';
27
+ themeName?: string;
28
+ title?: string;
29
+ width?: number;
30
+ padding?: number | [number, number] | [number, number, number, number];
31
+ fontSize: number;
32
+ lineHeight: number;
33
+ watermark?: string;
34
+ controls: boolean;
35
+ customGlyphs: boolean;
36
+ fontFamily?: string;
37
+ embedFont: boolean;
38
+ header?: {
39
+ height?: number;
40
+ backgroundColor?: string;
41
+ };
42
+ footer?: {
43
+ height?: number;
44
+ backgroundColor?: string;
45
+ };
46
+ }
47
+ type Padding = number | [number, number] | [number, number, number, number];
48
+ export declare const parseEscapeSequences: (input: string) => string;
49
+ export declare const readStdin: () => Promise<string>;
50
+ export declare const readInput: (inputFile?: string) => Promise<string>;
51
+ export declare const parsePadding: (input: string) => Padding;
52
+ export declare const getOutputPath: (options: {
53
+ output?: string;
54
+ name?: string;
55
+ inputFile?: string;
56
+ }) => string;
57
+ export declare const buildOptions: (argv: Partial<CliArgs>) => BuildOptionsResult;
58
+ export {};
59
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,OAAO;IACtB,CAAC,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,OAAO,CAAC;IACvB,kBAAkB,EAAE,OAAO,CAAC;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,OAAO,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,OAAO,GAAG,SAAS,GAAG,SAAS,CAAC;IAC1C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACvE,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;IAClB,YAAY,EAAE,OAAO,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,eAAe,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACvD,MAAM,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,eAAe,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACxD;AAED,KAAK,OAAO,GAAG,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;AAQ5E,eAAO,MAAM,oBAAoB,GAAI,OAAO,MAAM,KAAG,MACkD,CAAC;AAExG,eAAO,MAAM,SAAS,QAAO,OAAO,CAAC,MAAM,CAMvC,CAAC;AAEL,eAAO,MAAM,SAAS,GAAU,YAAY,MAAM,KAAG,OAAO,CAAC,MAAM,CAIlE,CAAC;AAEF,eAAO,MAAM,YAAY,GAAI,OAAO,MAAM,KAAG,OAyB5C,CAAC;AAKF,eAAO,MAAM,aAAa,GAAI,SAAS;IACrC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,KAAG,MAQH,CAAC;AAaF,eAAO,MAAM,YAAY,GAAI,MAAM,OAAO,CAAC,OAAO,CAAC,KAAG,kBAepD,CAAC"}
package/dist/utils.js ADDED
@@ -0,0 +1,86 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildOptions = exports.getOutputPath = exports.parsePadding = exports.readInput = exports.readStdin = exports.parseEscapeSequences = void 0;
4
+ const node_fs_1 = require("node:fs");
5
+ const node_path_1 = require("node:path");
6
+ const ESCAPE_REPLACEMENTS = [
7
+ [/\\033/g, '\x1b'],
8
+ [/\\x1[bB]/g, '\x1b'],
9
+ [/\\e/g, '\x1b'],
10
+ ];
11
+ const parseEscapeSequences = (input) => ESCAPE_REPLACEMENTS.reduce((str, [pattern, replacement]) => str.replace(pattern, replacement), input);
12
+ exports.parseEscapeSequences = parseEscapeSequences;
13
+ const readStdin = () => new Promise((resolve, reject) => {
14
+ const chunks = [];
15
+ process.stdin.on('data', (chunk) => chunks.push(chunk));
16
+ process.stdin.on('end', () => resolve(Buffer.concat(chunks).toString('utf-8')));
17
+ process.stdin.on('error', reject);
18
+ });
19
+ exports.readStdin = readStdin;
20
+ const readInput = async (inputFile) => {
21
+ if (inputFile)
22
+ return (0, node_fs_1.readFileSync)((0, node_path_1.resolve)(inputFile), 'utf-8');
23
+ if (!process.stdin.isTTY)
24
+ return (0, exports.readStdin)();
25
+ return '';
26
+ };
27
+ exports.readInput = readInput;
28
+ const parsePadding = (input) => {
29
+ const values = input
30
+ .split(/[,\s]+/)
31
+ .map((v) => v.trim())
32
+ .filter(Boolean)
33
+ .map(Number);
34
+ if (values.some(isNaN)) {
35
+ throw new Error(`Invalid padding value: "${input}". Use numbers only.`);
36
+ }
37
+ const paddingByLength = {
38
+ 1: () => values[0],
39
+ 2: () => values,
40
+ 4: () => values,
41
+ };
42
+ const toPadding = paddingByLength[values.length];
43
+ if (!toPadding) {
44
+ throw new Error(`Invalid padding format: "${input}". Use 1, 2, or 4 values (e.g., "16", "10,20", "10,20,15,25").`);
45
+ }
46
+ return toPadding();
47
+ };
48
+ exports.parsePadding = parsePadding;
49
+ const ensureSvgExtension = (path) => path.endsWith('.svg') ? path : `${path}.svg`;
50
+ const getOutputPath = (options) => {
51
+ const { output, name, inputFile } = options;
52
+ if (output)
53
+ return ensureSvgExtension((0, node_path_1.resolve)(output));
54
+ if (name)
55
+ return (0, node_path_1.resolve)(process.cwd(), ensureSvgExtension(name));
56
+ if (inputFile)
57
+ return (0, node_path_1.resolve)(process.cwd(), `${(0, node_path_1.basename)(inputFile).replace(/\.[^.]+$/, '')}.svg`);
58
+ return (0, node_path_1.resolve)(process.cwd(), 'shellfie.svg');
59
+ };
60
+ exports.getOutputPath = getOutputPath;
61
+ const buildHeaderFooter = (height, color) => {
62
+ if (height === undefined && color === undefined)
63
+ return undefined;
64
+ return {
65
+ ...(height !== undefined && { height }),
66
+ ...(color !== undefined && { backgroundColor: color }),
67
+ };
68
+ };
69
+ const buildOptions = (argv) => ({
70
+ template: argv.template ?? 'macos',
71
+ fontSize: argv['font-size'] ?? 14,
72
+ lineHeight: argv['line-height'] ?? 1.4,
73
+ embedFont: argv['embed-font'] ?? false,
74
+ controls: !argv['no-controls'],
75
+ customGlyphs: !argv['no-custom-glyphs'],
76
+ ...(argv.theme && { themeName: argv.theme }),
77
+ ...(argv.title !== undefined && { title: argv.title }),
78
+ ...(argv.width !== undefined && { width: argv.width }),
79
+ ...(argv.padding !== undefined && { padding: (0, exports.parsePadding)(argv.padding) }),
80
+ ...(argv.watermark !== undefined && { watermark: (0, exports.parseEscapeSequences)(argv.watermark) }),
81
+ ...(argv['font-family'] !== undefined && { fontFamily: argv['font-family'] }),
82
+ ...({ header: buildHeaderFooter(argv['header-height'], argv['header-color']) }),
83
+ ...({ footer: buildHeaderFooter(argv['footer-height'], argv['footer-color']) }),
84
+ });
85
+ exports.buildOptions = buildOptions;
86
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,36 +1,46 @@
1
1
  {
2
2
  "name": "shellfie-cli",
3
- "version": "1.0.3",
4
- "description": "create beautiful terminal screenshots",
5
- "main": "index.js",
6
- "scripts": {
7
- "test": "echo 'set your tests here'"
3
+ "version": "2.0.0",
4
+ "description": "Transform terminal output into beautiful SVG images from the command line",
5
+ "bin": {
6
+ "shellfie": "./dist/cli.js"
8
7
  },
9
- "repository": {
10
- "type": "git",
11
- "url": "git+https://github.com/tool3/shellfie-cli.git"
8
+ "main": "dist/cli.js",
9
+ "types": "dist/cli.d.ts",
10
+ "files": [
11
+ "dist"
12
+ ],
13
+ "scripts": {
14
+ "build": "tsc",
15
+ "test": "vitest run",
16
+ "test:watch": "vitest",
17
+ "dev": "tsc --watch",
18
+ "prepublishOnly": "npm run build"
12
19
  },
13
20
  "keywords": [
14
21
  "terminal",
15
- "xterm",
22
+ "svg",
16
23
  "screenshot",
17
24
  "ansi",
18
- "cli"
25
+ "cli",
26
+ "shellfie",
27
+ "tty",
28
+ "carbon",
29
+ "terminal-screenshot"
19
30
  ],
20
- "author": "Tal Hayut",
31
+ "author": "tool3",
21
32
  "license": "MIT",
22
- "bugs": {
23
- "url": "https://github.com/tool3/shellfie-cli/issues"
24
- },
25
- "bin": {
26
- "shellfie": "index.js"
27
- },
28
- "homepage": "https://github.com/tool3/shellfie-cli#readme",
29
33
  "dependencies": {
30
- "shellfie": "^1.2.4",
31
- "yargs": "^16.1.1"
34
+ "shellfie": "^2.0.0",
35
+ "yargs": "^17.7.2"
32
36
  },
33
37
  "devDependencies": {
34
- "mocha": "^8.2.1"
38
+ "@types/node": "^20.10.0",
39
+ "@types/yargs": "^17.0.32",
40
+ "typescript": "^5.3.0",
41
+ "vitest": "^4.0.18"
42
+ },
43
+ "engines": {
44
+ "node": ">=18.0.0"
35
45
  }
36
46
  }
@@ -1,18 +0,0 @@
1
- name: test
2
-
3
- on:
4
- push:
5
- branches:
6
- - master
7
-
8
- jobs:
9
- test:
10
- runs-on: ubuntu-latest
11
- steps:
12
- - uses: actions/checkout@v1
13
- - uses: actions/setup-node@v1
14
- with:
15
- node-version: 12
16
- - run: |
17
- yarn
18
- yarn test
package/LICENSE DELETED
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2021 Tal Hayut
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.
package/commands/load.js DELETED
@@ -1,38 +0,0 @@
1
- #!/usr/bin/env node
2
- const fs = require('fs');
3
-
4
- const validOpts = opts => {
5
- if(!opts || !opts.commands) return true;
6
- return process.argv[2].includes(opts.commands) ? true : false;
7
- };
8
-
9
- module.exports.load = opts => {
10
-
11
- if(!validOpts(opts)) return false;
12
- if (process.stdin.isTTY) return false;
13
-
14
- const BUFSIZE = 65536;
15
- let nbytes = 0;
16
- let chunks = [];
17
- let buffer = '';
18
-
19
- while(true) {
20
- try {
21
- buffer = Buffer.alloc(BUFSIZE);
22
- nbytes = fs.readSync(0, buffer, 0, BUFSIZE, null);
23
- }
24
- catch (e) {
25
- if (e.code != 'EAGAIN') throw e;
26
- }
27
-
28
- if (nbytes === 0) break;
29
- chunks.push(buffer.slice(0, nbytes));
30
- }
31
-
32
- const stdin = Buffer.concat(chunks).toString();
33
- if (stdin) {
34
- process.argv.push(stdin.trim());
35
- return true;
36
- }
37
-
38
- };
@@ -1,17 +0,0 @@
1
- const shellfie = require('shellfie');
2
- const path = require('path');
3
-
4
- async function shellify(argv) {
5
- const options = {};
6
- if (argv.width || argv.height) {
7
- const viewport = { ...argv };
8
- argv.viewport = viewport;
9
- }
10
- const name = argv.name || 'a randomly named image';
11
- Object.assign(options, argv);
12
- const { string , location } = argv;
13
- await shellfie(string, options);
14
- console.log(`📸 \x1b[32;1m${name}.png\x1b[0m \x1b[32mwas saved at \x1b[0;2m${path.resolve(location)}\x1b[0m`)
15
- }
16
-
17
- module.exports = shellify;
package/index.js DELETED
@@ -1,36 +0,0 @@
1
- #!/usr/bin/env node
2
- require('./commands/load').load();
3
- const yargs = require('yargs');
4
- const shellify = require('./commands/shellify');
5
-
6
- yargs
7
- .config({
8
- location: `${process.env.INIT_CWD || process.cwd()}/shellfies`
9
- })
10
- .command(
11
- '$0 <string|string..>',
12
- 'create terminal screenshots from ansi string',
13
- { },
14
- async argv => {
15
- try {
16
- await shellify(argv);
17
- } catch (error) {
18
- console.error(error);
19
- }
20
-
21
- })
22
- .example('$0 \x1b[32mI\'m Green! --width 200')
23
- .option('name', { alias: 'n', type: 'string', desc: 'image name' })
24
- .option('mode', { alias: 'm', type: 'string', desc: 'input mode (can also be \'raw\')', default: 'default'})
25
- .option('width', { alias: 'w', type: 'number', desc: 'set width' })
26
- .option('height', { alias: 'h', type: 'number', desc: 'set height' })
27
- .option('background', { alias: 'b', type: 'string', desc: 'set background color' })
28
- .option('foreground', { alias: 'f', type: 'string', desc: 'set default text color' })
29
- .option('font-family', { alias: 'ff', type: 'string', desc: 'set font family' })
30
- .option('font-size', { alias: 'fs', type: 'number', desc: 'set font size' })
31
- .option('font-weight', { alias: 'fw', type: 'string', desc: 'set font weight' })
32
- .option('location', { alias: 'l', type: 'string', desc: 'destination folder', default: './shellfies' })
33
- .option('puppeteerArgs', { alias: 'p', type: 'array', desc: 'optional puppeteer args', default: ['--no-sandbox', '--disable-setuid-sandbox']})
34
- .help()
35
- .wrap(90)
36
- .argv