appshot-cli 0.8.1 → 0.8.6
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 +128 -4
- package/dist/cli.js +6 -3
- package/dist/cli.js.map +1 -1
- package/dist/commands/backgrounds.d.ts +3 -0
- package/dist/commands/backgrounds.d.ts.map +1 -0
- package/dist/commands/backgrounds.js +323 -0
- package/dist/commands/backgrounds.js.map +1 -0
- package/dist/commands/build.d.ts.map +1 -1
- package/dist/commands/build.js +35 -2
- package/dist/commands/build.js.map +1 -1
- package/dist/commands/check.d.ts.map +1 -1
- package/dist/commands/check.js +60 -0
- package/dist/commands/check.js.map +1 -1
- package/dist/core/background.d.ts +31 -0
- package/dist/core/background.d.ts.map +1 -0
- package/dist/core/background.js +240 -0
- package/dist/core/background.js.map +1 -0
- package/dist/core/compose.d.ts +3 -2
- package/dist/core/compose.d.ts.map +1 -1
- package/dist/core/compose.js +38 -26
- package/dist/core/compose.js.map +1 -1
- package/dist/core/files.d.ts +1 -0
- package/dist/core/files.d.ts.map +1 -1
- package/dist/core/files.js +6 -0
- package/dist/core/files.js.map +1 -1
- package/dist/services/doctor.js +1 -1
- package/dist/types.d.ts +17 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,11 +4,13 @@
|
|
|
4
4
|
|
|
5
5
|
[](https://github.com/chrisvanbuskirk/appshot/actions/workflows/ci.yml)
|
|
6
6
|
[](https://www.npmjs.com/package/appshot-cli)
|
|
7
|
+
[](https://www.npmjs.com/package/appshot-cli)
|
|
8
|
+
[](https://nodejs.org)
|
|
7
9
|
[](https://opensource.org/licenses/MIT)
|
|
8
10
|
|
|
9
|
-
🆕 **Version 0.8.
|
|
11
|
+
🆕 **Version 0.8.6** - **Background Images** - Replace gradients with custom static images, auto-detection, and dimension validation!
|
|
10
12
|
|
|
11
|
-
> ⚠️ **NEW in v0.8.
|
|
13
|
+
> ⚠️ **NEW in v0.8.6**: Use custom background images instead of gradients! Auto-detects `background.png` in device folders, supports multiple fit modes, and validates dimensions against App Store specs.
|
|
12
14
|
|
|
13
15
|
> ⚠️ **BREAKING CHANGE in v0.4.0**: Output structure now always uses language subdirectories.
|
|
14
16
|
> Single language builds now output to `final/device/lang/` instead of `final/device/`.
|
|
@@ -265,6 +267,129 @@ appshot gradients --sample
|
|
|
265
267
|
}
|
|
266
268
|
```
|
|
267
269
|
|
|
270
|
+
### Background System (NEW in v0.8.6)
|
|
271
|
+
|
|
272
|
+
Replace gradients with custom static background images for a unique, branded look. Appshot supports automatic detection, multiple formats, and intelligent scaling.
|
|
273
|
+
|
|
274
|
+
#### Background Locations
|
|
275
|
+
|
|
276
|
+
Backgrounds are searched in priority order:
|
|
277
|
+
|
|
278
|
+
1. **Device-specific**: `screenshots/<device>/background.png`
|
|
279
|
+
2. **Global**: `screenshots/background.png`
|
|
280
|
+
3. **Custom**: Path specified via config or CLI
|
|
281
|
+
|
|
282
|
+
#### Background Commands
|
|
283
|
+
|
|
284
|
+
```bash
|
|
285
|
+
# Set background for a device
|
|
286
|
+
appshot backgrounds set iphone ./backgrounds/sunset.jpg
|
|
287
|
+
|
|
288
|
+
# Set global background for all devices
|
|
289
|
+
appshot backgrounds set --global ./backgrounds/brand-bg.png
|
|
290
|
+
|
|
291
|
+
# Validate dimensions against App Store specs
|
|
292
|
+
appshot backgrounds validate
|
|
293
|
+
|
|
294
|
+
# List all configured backgrounds
|
|
295
|
+
appshot backgrounds list
|
|
296
|
+
|
|
297
|
+
# Clear background configuration
|
|
298
|
+
appshot backgrounds clear iphone
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
#### Build Options
|
|
302
|
+
|
|
303
|
+
```bash
|
|
304
|
+
# Auto-detect background.png in device folders
|
|
305
|
+
appshot build --auto-background
|
|
306
|
+
|
|
307
|
+
# Use specific background image
|
|
308
|
+
appshot build --background ./assets/custom-bg.png
|
|
309
|
+
|
|
310
|
+
# Set background fit mode
|
|
311
|
+
appshot build --background-fit cover
|
|
312
|
+
|
|
313
|
+
# Disable backgrounds (transparent)
|
|
314
|
+
appshot build --no-background
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
#### Fit Modes
|
|
318
|
+
|
|
319
|
+
- **`cover`** - Scale to cover entire area (may crop)
|
|
320
|
+
- **`contain`** - Scale to fit within area (may add letterbox bars)
|
|
321
|
+
- **`fill`** - Stretch to exact dimensions (may distort)
|
|
322
|
+
- **`scale-down`** - Only scale down if larger, never scale up
|
|
323
|
+
|
|
324
|
+
#### Creating Backgrounds with ImageMagick
|
|
325
|
+
|
|
326
|
+
ImageMagick is a powerful CLI tool for creating custom backgrounds:
|
|
327
|
+
|
|
328
|
+
```bash
|
|
329
|
+
# Solid color background
|
|
330
|
+
magick -size 1290x2796 canvas:navy background.png
|
|
331
|
+
|
|
332
|
+
# Gradient background
|
|
333
|
+
magick -size 1290x2796 gradient:blue-purple background.png
|
|
334
|
+
|
|
335
|
+
# Radial gradient
|
|
336
|
+
magick -size 1290x2796 radial-gradient:white-darkblue background.png
|
|
337
|
+
|
|
338
|
+
# Plasma fractal pattern
|
|
339
|
+
magick -size 1290x2796 plasma:fractal background.png
|
|
340
|
+
|
|
341
|
+
# Blurred noise texture
|
|
342
|
+
magick -size 1290x2796 xc: +noise Random -blur 0x10 background.png
|
|
343
|
+
|
|
344
|
+
# Tiled pattern
|
|
345
|
+
magick -size 100x100 pattern:checkerboard -scale 1290x2796 background.png
|
|
346
|
+
|
|
347
|
+
# Multi-point color interpolation
|
|
348
|
+
magick -size 1290x2796 xc: -sparse-color barycentric \
|
|
349
|
+
'0,0 skyblue 1290,0 white 645,2796 lightblue' background.png
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
#### Configuration
|
|
353
|
+
|
|
354
|
+
```json
|
|
355
|
+
{
|
|
356
|
+
"background": {
|
|
357
|
+
"mode": "image",
|
|
358
|
+
"image": "./backgrounds/global.png",
|
|
359
|
+
"fit": "cover"
|
|
360
|
+
},
|
|
361
|
+
"devices": {
|
|
362
|
+
"iphone": {
|
|
363
|
+
"background": {
|
|
364
|
+
"image": "./backgrounds/iphone.png",
|
|
365
|
+
"fit": "contain"
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
#### Mixed Configurations
|
|
373
|
+
|
|
374
|
+
You can mix backgrounds and gradients across devices:
|
|
375
|
+
|
|
376
|
+
- iPhone uses a custom background image
|
|
377
|
+
- iPad falls back to gradient
|
|
378
|
+
- Mac uses a different background
|
|
379
|
+
- Watch uses the global background
|
|
380
|
+
|
|
381
|
+
This flexibility allows you to optimize each device's appearance independently.
|
|
382
|
+
|
|
383
|
+
#### Dimension Validation
|
|
384
|
+
|
|
385
|
+
Appshot validates background dimensions and warns about:
|
|
386
|
+
|
|
387
|
+
- Images smaller than target resolution (will be upscaled)
|
|
388
|
+
- Aspect ratio mismatches (may cause cropping/distortion)
|
|
389
|
+
- Large file sizes (>10MB triggers optimization suggestion)
|
|
390
|
+
|
|
391
|
+
Use `appshot backgrounds validate` to check all backgrounds before building.
|
|
392
|
+
|
|
268
393
|
### Font System
|
|
269
394
|
|
|
270
395
|
Version 0.4.0 introduces comprehensive font management with intelligent fallbacks.
|
|
@@ -2042,8 +2167,7 @@ For security vulnerabilities, please see [SECURITY.md](SECURITY.md).
|
|
|
2042
2167
|
### NPM Package
|
|
2043
2168
|
|
|
2044
2169
|
- 📦 [appshot-cli on NPM](https://www.npmjs.com/package/appshot-cli)
|
|
2045
|
-
- 🔄 Latest version: 0.8.
|
|
2046
|
-
- ⬇️ Weekly downloads: 
|
|
2170
|
+
- 🔄 Latest version: 0.8.6
|
|
2047
2171
|
|
|
2048
2172
|
---
|
|
2049
2173
|
|
package/dist/cli.js
CHANGED
|
@@ -12,6 +12,7 @@ import presetsCmd from './commands/presets.js';
|
|
|
12
12
|
import validateCmd from './commands/validate.js';
|
|
13
13
|
import styleCmd from './commands/style.js';
|
|
14
14
|
import gradientsCmd from './commands/gradients.js';
|
|
15
|
+
import backgroundsCmd from './commands/backgrounds.js';
|
|
15
16
|
import fontsCmd from './commands/fonts.js';
|
|
16
17
|
import migrateCmd from './commands/migrate.js';
|
|
17
18
|
import { createCleanCommand } from './commands/clean.js';
|
|
@@ -23,12 +24,12 @@ import watchStatusCmd from './commands/watch-status.js';
|
|
|
23
24
|
const program = new Command();
|
|
24
25
|
program
|
|
25
26
|
.name('appshot')
|
|
26
|
-
.description(`Generate App Store–ready screenshots with frames,
|
|
27
|
+
.description(`Generate App Store–ready screenshots with frames, backgrounds, and captions.
|
|
27
28
|
|
|
28
29
|
${pc.bold('Features:')}
|
|
29
30
|
• Auto-detects portrait/landscape orientation
|
|
30
31
|
• 8 embedded font families with italic & bold variants
|
|
31
|
-
• 24+ gradient presets
|
|
32
|
+
• Custom background images or 24+ gradient presets
|
|
32
33
|
• AI-powered translation to 25+ languages
|
|
33
34
|
• Smart caption wrapping and positioning
|
|
34
35
|
• All official App Store resolutions
|
|
@@ -44,6 +45,7 @@ ${pc.bold('Quick Start:')}
|
|
|
44
45
|
${pc.bold('Common Workflows:')}
|
|
45
46
|
$ appshot fonts --set "Poppins Italic" # Set italic font
|
|
46
47
|
$ appshot gradients select # Pick gradient
|
|
48
|
+
$ appshot backgrounds set iphone bg.jpg # Set background image
|
|
47
49
|
$ appshot frame ./screenshots --recursive # Batch frame images
|
|
48
50
|
$ appshot build --preset iphone-6-9,ipad-13 # App Store presets
|
|
49
51
|
$ appshot localize --langs es,fr,de # Batch translate${platform() === 'darwin' ? `
|
|
@@ -51,7 +53,7 @@ ${pc.bold('Common Workflows:')}
|
|
|
51
53
|
$ appshot watch start --process # Auto-process new screenshots` : ''}
|
|
52
54
|
|
|
53
55
|
${pc.dim('Docs: https://github.com/chrisvanbuskirk/appshot')}`)
|
|
54
|
-
.version('0.8.
|
|
56
|
+
.version('0.8.6')
|
|
55
57
|
.addHelpText('after', `\n${pc.bold('Environment Variables:')}
|
|
56
58
|
OPENAI_API_KEY API key for translation features
|
|
57
59
|
APPSHOT_DISABLE_FONT_SCAN Skip system font detection (CI optimization)
|
|
@@ -66,6 +68,7 @@ program.addCommand(initCmd());
|
|
|
66
68
|
program.addCommand(captionCmd());
|
|
67
69
|
program.addCommand(styleCmd());
|
|
68
70
|
program.addCommand(gradientsCmd());
|
|
71
|
+
program.addCommand(backgroundsCmd());
|
|
69
72
|
program.addCommand(fontsCmd());
|
|
70
73
|
program.addCommand(localizeCmd());
|
|
71
74
|
program.addCommand(buildCmd());
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,QAAQ,EAAE,MAAM,IAAI,CAAC;AAC9B,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,OAAO,MAAM,oBAAoB,CAAC;AACzC,OAAO,UAAU,MAAM,uBAAuB,CAAC;AAC/C,OAAO,WAAW,MAAM,wBAAwB,CAAC;AACjD,OAAO,QAAQ,MAAM,qBAAqB,CAAC;AAC3C,OAAO,QAAQ,MAAM,qBAAqB,CAAC;AAC3C,OAAO,QAAQ,MAAM,qBAAqB,CAAC;AAC3C,OAAO,SAAS,MAAM,sBAAsB,CAAC;AAC7C,OAAO,UAAU,MAAM,uBAAuB,CAAC;AAC/C,OAAO,WAAW,MAAM,wBAAwB,CAAC;AACjD,OAAO,QAAQ,MAAM,qBAAqB,CAAC;AAC3C,OAAO,YAAY,MAAM,yBAAyB,CAAC;AACnD,OAAO,QAAQ,MAAM,qBAAqB,CAAC;AAC3C,OAAO,UAAU,MAAM,uBAAuB,CAAC;AAC/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,QAAQ,MAAM,qBAAqB,CAAC;AAC3C,OAAO,SAAS,MAAM,sBAAsB,CAAC;AAC7C,OAAO,QAAQ,MAAM,qBAAqB,CAAC;AAC3C,OAAO,UAAU,MAAM,uBAAuB,CAAC;AAC/C,OAAO,cAAc,MAAM,4BAA4B,CAAC;AAExD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,SAAS,CAAC;KACf,WAAW,CAAC;;EAEb,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC;;;;;;;;;;EAUpB,EAAE,CAAC,IAAI,CAAC,cAAc,CAAC;;;;;;EAMvB,EAAE,CAAC,IAAI,CAAC,mBAAmB,CAAC
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backgrounds.d.ts","sourceRoot":"","sources":["../../src/commands/backgrounds.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAQpC,MAAM,CAAC,OAAO,UAAU,kBAAkB,IAAI,OAAO,CAmWpD"}
|
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import { promises as fs } from 'fs';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import pc from 'picocolors';
|
|
5
|
+
import { select, input } from '@inquirer/prompts';
|
|
6
|
+
import { validateBackgroundDimensions, detectBestFit } from '../core/background.js';
|
|
7
|
+
import { loadConfig, saveConfig } from '../core/files.js';
|
|
8
|
+
export default function backgroundsCommand() {
|
|
9
|
+
const cmd = new Command('backgrounds')
|
|
10
|
+
.description('Manage background images for screenshots')
|
|
11
|
+
.addHelpText('after', `
|
|
12
|
+
${pc.bold('Examples:')}
|
|
13
|
+
$ appshot backgrounds set iphone ./backgrounds/sunset.jpg
|
|
14
|
+
$ appshot backgrounds validate
|
|
15
|
+
$ appshot backgrounds preview
|
|
16
|
+
$ appshot backgrounds clear iphone
|
|
17
|
+
$ appshot backgrounds list
|
|
18
|
+
|
|
19
|
+
${pc.bold('Background Locations:')}
|
|
20
|
+
Device-specific: screenshots/<device>/background.png
|
|
21
|
+
Global: screenshots/background.png
|
|
22
|
+
Custom: Specified via config or command
|
|
23
|
+
|
|
24
|
+
${pc.bold('Fit Modes:')}
|
|
25
|
+
cover Scale to cover entire area (may crop)
|
|
26
|
+
contain Scale to fit within area (may add bars)
|
|
27
|
+
fill Stretch to exact dimensions (may distort)
|
|
28
|
+
scale-down Only scale down if larger, never scale up
|
|
29
|
+
`);
|
|
30
|
+
// Set background for a device
|
|
31
|
+
cmd
|
|
32
|
+
.command('set')
|
|
33
|
+
.description('Set background image for a device')
|
|
34
|
+
.argument('[device]', 'Device type (iphone, ipad, mac, watch)')
|
|
35
|
+
.argument('[image]', 'Path to background image')
|
|
36
|
+
.option('-f, --fit <mode>', 'Fit mode: cover, contain, fill, scale-down', 'cover')
|
|
37
|
+
.option('--global', 'Set as global background for all devices')
|
|
38
|
+
.action(async (device, image, options) => {
|
|
39
|
+
try {
|
|
40
|
+
// Interactive mode if arguments not provided
|
|
41
|
+
if (!device && !options.global) {
|
|
42
|
+
device = await select({
|
|
43
|
+
message: 'Select device type:',
|
|
44
|
+
choices: [
|
|
45
|
+
{ name: 'iPhone', value: 'iphone' },
|
|
46
|
+
{ name: 'iPad', value: 'ipad' },
|
|
47
|
+
{ name: 'Mac', value: 'mac' },
|
|
48
|
+
{ name: 'Watch', value: 'watch' },
|
|
49
|
+
{ name: 'All Devices (Global)', value: 'global' }
|
|
50
|
+
]
|
|
51
|
+
});
|
|
52
|
+
if (device === 'global') {
|
|
53
|
+
options.global = true;
|
|
54
|
+
device = undefined;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
if (!image) {
|
|
58
|
+
image = await input({
|
|
59
|
+
message: 'Enter path to background image:',
|
|
60
|
+
validate: async (value) => {
|
|
61
|
+
try {
|
|
62
|
+
await fs.access(value);
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
return 'File not found';
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
// Validate image exists
|
|
72
|
+
try {
|
|
73
|
+
await fs.access(image);
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
console.error(pc.red(`❌ Background image not found: ${image}`));
|
|
77
|
+
process.exit(1);
|
|
78
|
+
}
|
|
79
|
+
// Load config
|
|
80
|
+
const config = await loadConfig();
|
|
81
|
+
// Initialize background config if not exists
|
|
82
|
+
if (!config.background) {
|
|
83
|
+
config.background = {
|
|
84
|
+
mode: 'image',
|
|
85
|
+
warnOnMismatch: true
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
// Set background
|
|
89
|
+
if (options.global) {
|
|
90
|
+
config.background.image = image;
|
|
91
|
+
config.background.fit = options.fit;
|
|
92
|
+
console.log(pc.green(`✅ Set global background: ${image}`));
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
// Device-specific background
|
|
96
|
+
if (!config.devices[device]) {
|
|
97
|
+
console.error(pc.red(`❌ Device '${device}' not found in config`));
|
|
98
|
+
console.log(pc.dim(`Available devices: ${Object.keys(config.devices).join(', ')}`));
|
|
99
|
+
process.exit(1);
|
|
100
|
+
}
|
|
101
|
+
if (!config.devices[device].background) {
|
|
102
|
+
config.devices[device].background = {};
|
|
103
|
+
}
|
|
104
|
+
config.devices[device].background.image = image;
|
|
105
|
+
config.devices[device].background.fit = options.fit;
|
|
106
|
+
console.log(pc.green(`✅ Set ${device} background: ${image}`));
|
|
107
|
+
}
|
|
108
|
+
// Save config
|
|
109
|
+
await saveConfig(config);
|
|
110
|
+
console.log(pc.dim('Configuration saved'));
|
|
111
|
+
}
|
|
112
|
+
catch (error) {
|
|
113
|
+
console.error(pc.red('Error setting background:'), error);
|
|
114
|
+
process.exit(1);
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
// Validate backgrounds
|
|
118
|
+
cmd
|
|
119
|
+
.command('validate')
|
|
120
|
+
.description('Validate background dimensions against App Store specs')
|
|
121
|
+
.option('-d, --device <type>', 'Validate specific device only')
|
|
122
|
+
.action(async (options) => {
|
|
123
|
+
try {
|
|
124
|
+
const config = await loadConfig();
|
|
125
|
+
let hasWarnings = false;
|
|
126
|
+
// Get devices to validate
|
|
127
|
+
const devices = options.device
|
|
128
|
+
? [options.device]
|
|
129
|
+
: Object.keys(config.devices);
|
|
130
|
+
console.log(pc.bold('\n📐 Validating background dimensions...\n'));
|
|
131
|
+
for (const device of devices) {
|
|
132
|
+
const deviceConfig = config.devices[device];
|
|
133
|
+
if (!deviceConfig)
|
|
134
|
+
continue;
|
|
135
|
+
// Find background image
|
|
136
|
+
let backgroundPath = null;
|
|
137
|
+
if (deviceConfig.background?.image) {
|
|
138
|
+
backgroundPath = deviceConfig.background.image;
|
|
139
|
+
}
|
|
140
|
+
else if (config.background?.image) {
|
|
141
|
+
backgroundPath = config.background.image;
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
// Check for auto-detected background
|
|
145
|
+
const candidates = [
|
|
146
|
+
path.join(deviceConfig.input, 'background.png'),
|
|
147
|
+
path.join(deviceConfig.input, 'background.jpg'),
|
|
148
|
+
path.join('screenshots', 'background.png'),
|
|
149
|
+
path.join('screenshots', 'background.jpg')
|
|
150
|
+
];
|
|
151
|
+
for (const candidate of candidates) {
|
|
152
|
+
try {
|
|
153
|
+
await fs.access(candidate);
|
|
154
|
+
backgroundPath = candidate;
|
|
155
|
+
break;
|
|
156
|
+
}
|
|
157
|
+
catch {
|
|
158
|
+
// Continue checking
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
if (!backgroundPath) {
|
|
163
|
+
console.log(pc.dim(`${device}: No background image found`));
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
// Get target dimensions
|
|
167
|
+
const [width, height] = deviceConfig.resolution.split('x').map(Number);
|
|
168
|
+
// Validate
|
|
169
|
+
const validation = await validateBackgroundDimensions(backgroundPath, width, height);
|
|
170
|
+
// Display results
|
|
171
|
+
console.log(pc.cyan(`${device}:`));
|
|
172
|
+
console.log(pc.dim(` Background: ${backgroundPath}`));
|
|
173
|
+
console.log(pc.dim(` Source: ${validation.dimensions.source.width}x${validation.dimensions.source.height}`));
|
|
174
|
+
console.log(pc.dim(` Target: ${validation.dimensions.target.width}x${validation.dimensions.target.height}`));
|
|
175
|
+
if (validation.warnings.length > 0) {
|
|
176
|
+
hasWarnings = true;
|
|
177
|
+
validation.warnings.forEach(warning => {
|
|
178
|
+
console.log(pc.yellow(` ⚠️ ${warning}`));
|
|
179
|
+
});
|
|
180
|
+
// Suggest best fit mode
|
|
181
|
+
const bestFit = detectBestFit(validation.dimensions.source.width, validation.dimensions.source.height, validation.dimensions.target.width, validation.dimensions.target.height);
|
|
182
|
+
console.log(pc.cyan(` 💡 Suggested fit mode: ${bestFit}`));
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
console.log(pc.green(' ✅ Dimensions OK'));
|
|
186
|
+
}
|
|
187
|
+
console.log();
|
|
188
|
+
}
|
|
189
|
+
if (hasWarnings) {
|
|
190
|
+
console.log(pc.yellow('⚠️ Some backgrounds have dimension warnings'));
|
|
191
|
+
console.log(pc.dim('Run "appshot backgrounds set" to adjust fit modes'));
|
|
192
|
+
}
|
|
193
|
+
else {
|
|
194
|
+
console.log(pc.green('✅ All backgrounds validated successfully'));
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
catch (error) {
|
|
198
|
+
console.error(pc.red('Error validating backgrounds:'), error);
|
|
199
|
+
process.exit(1);
|
|
200
|
+
}
|
|
201
|
+
});
|
|
202
|
+
// Preview backgrounds
|
|
203
|
+
cmd
|
|
204
|
+
.command('preview')
|
|
205
|
+
.description('Generate preview of screenshots with backgrounds')
|
|
206
|
+
.option('-d, --device <type>', 'Preview specific device only')
|
|
207
|
+
.option('-o, --output <dir>', 'Output directory', './preview')
|
|
208
|
+
.action(async (options) => {
|
|
209
|
+
try {
|
|
210
|
+
const config = await loadConfig();
|
|
211
|
+
const outputDir = options.output;
|
|
212
|
+
// Create output directory
|
|
213
|
+
await fs.mkdir(outputDir, { recursive: true });
|
|
214
|
+
console.log(pc.bold('\n🎨 Generating background previews...\n'));
|
|
215
|
+
// This would integrate with the compose system
|
|
216
|
+
// For now, just show what would be generated
|
|
217
|
+
const devices = options.device
|
|
218
|
+
? [options.device]
|
|
219
|
+
: Object.keys(config.devices);
|
|
220
|
+
for (const device of devices) {
|
|
221
|
+
console.log(pc.cyan(`${device}:`));
|
|
222
|
+
console.log(pc.dim(` Would generate preview in ${outputDir}/${device}/`));
|
|
223
|
+
}
|
|
224
|
+
console.log(pc.dim('\nNote: Full preview generation requires running "appshot build --preview"'));
|
|
225
|
+
}
|
|
226
|
+
catch (error) {
|
|
227
|
+
console.error(pc.red('Error generating preview:'), error);
|
|
228
|
+
process.exit(1);
|
|
229
|
+
}
|
|
230
|
+
});
|
|
231
|
+
// Clear background
|
|
232
|
+
cmd
|
|
233
|
+
.command('clear')
|
|
234
|
+
.description('Remove background configuration')
|
|
235
|
+
.argument('[device]', 'Device type to clear (or "all" for global)')
|
|
236
|
+
.action(async (device) => {
|
|
237
|
+
try {
|
|
238
|
+
if (!device) {
|
|
239
|
+
device = await select({
|
|
240
|
+
message: 'Clear background for:',
|
|
241
|
+
choices: [
|
|
242
|
+
{ name: 'iPhone', value: 'iphone' },
|
|
243
|
+
{ name: 'iPad', value: 'ipad' },
|
|
244
|
+
{ name: 'Mac', value: 'mac' },
|
|
245
|
+
{ name: 'Watch', value: 'watch' },
|
|
246
|
+
{ name: 'All Devices (Global)', value: 'all' }
|
|
247
|
+
]
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
const config = await loadConfig();
|
|
251
|
+
if (device === 'all') {
|
|
252
|
+
// Clear global background
|
|
253
|
+
if (config.background) {
|
|
254
|
+
delete config.background.image;
|
|
255
|
+
console.log(pc.green('✅ Cleared global background'));
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
else {
|
|
259
|
+
// Clear device-specific background
|
|
260
|
+
if (config.devices[device]?.background) {
|
|
261
|
+
delete config.devices[device].background.image;
|
|
262
|
+
console.log(pc.green(`✅ Cleared ${device} background`));
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
await saveConfig(config);
|
|
266
|
+
console.log(pc.dim('Configuration saved'));
|
|
267
|
+
}
|
|
268
|
+
catch (error) {
|
|
269
|
+
console.error(pc.red('Error clearing background:'), error);
|
|
270
|
+
process.exit(1);
|
|
271
|
+
}
|
|
272
|
+
});
|
|
273
|
+
// List backgrounds
|
|
274
|
+
cmd
|
|
275
|
+
.command('list')
|
|
276
|
+
.description('List configured backgrounds')
|
|
277
|
+
.action(async () => {
|
|
278
|
+
try {
|
|
279
|
+
const config = await loadConfig();
|
|
280
|
+
console.log(pc.bold('\n📋 Configured Backgrounds:\n'));
|
|
281
|
+
// Global background
|
|
282
|
+
if (config.background?.image) {
|
|
283
|
+
console.log(pc.cyan('Global:'));
|
|
284
|
+
console.log(pc.dim(` Image: ${config.background.image}`));
|
|
285
|
+
console.log(pc.dim(` Fit: ${config.background.fit || 'cover'}`));
|
|
286
|
+
console.log();
|
|
287
|
+
}
|
|
288
|
+
// Device-specific backgrounds
|
|
289
|
+
for (const [device, deviceConfig] of Object.entries(config.devices)) {
|
|
290
|
+
if (deviceConfig.background?.image) {
|
|
291
|
+
console.log(pc.cyan(`${device}:`));
|
|
292
|
+
console.log(pc.dim(` Image: ${deviceConfig.background.image}`));
|
|
293
|
+
console.log(pc.dim(` Fit: ${deviceConfig.background.fit || 'cover'}`));
|
|
294
|
+
console.log();
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
// Auto-detected backgrounds
|
|
298
|
+
console.log(pc.bold('Auto-detected backgrounds:'));
|
|
299
|
+
for (const [device, deviceConfig] of Object.entries(config.devices)) {
|
|
300
|
+
const candidates = [
|
|
301
|
+
path.join(deviceConfig.input, 'background.png'),
|
|
302
|
+
path.join(deviceConfig.input, 'background.jpg')
|
|
303
|
+
];
|
|
304
|
+
for (const candidate of candidates) {
|
|
305
|
+
try {
|
|
306
|
+
await fs.access(candidate);
|
|
307
|
+
console.log(pc.dim(` ${device}: ${candidate}`));
|
|
308
|
+
break;
|
|
309
|
+
}
|
|
310
|
+
catch {
|
|
311
|
+
// Not found
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
catch (error) {
|
|
317
|
+
console.error(pc.red('Error listing backgrounds:'), error);
|
|
318
|
+
process.exit(1);
|
|
319
|
+
}
|
|
320
|
+
});
|
|
321
|
+
return cmd;
|
|
322
|
+
}
|
|
323
|
+
//# sourceMappingURL=backgrounds.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backgrounds.js","sourceRoot":"","sources":["../../src/commands/backgrounds.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/commands/build.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAUpC,MAAM,CAAC,OAAO,UAAU,QAAQ,
|
|
1
|
+
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/commands/build.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAUpC,MAAM,CAAC,OAAO,UAAU,QAAQ,YA6V/B"}
|
package/dist/commands/build.js
CHANGED
|
@@ -19,6 +19,10 @@ export default function buildCmd() {
|
|
|
19
19
|
.option('--no-frame', 'skip device frames')
|
|
20
20
|
.option('--no-gradient', 'skip gradient backgrounds')
|
|
21
21
|
.option('--no-caption', 'skip captions')
|
|
22
|
+
.option('--background <image>', 'use specific background image')
|
|
23
|
+
.option('--no-background', 'disable background (transparent)')
|
|
24
|
+
.option('--background-fit <mode>', 'background fit mode: cover, contain, fill, scale-down', 'cover')
|
|
25
|
+
.option('--auto-background', 'auto-detect background.png in device folders')
|
|
22
26
|
.option('--dry-run', 'show what would be rendered without generating images')
|
|
23
27
|
.option('--verbose', 'show detailed rendering information')
|
|
24
28
|
.addHelpText('after', `
|
|
@@ -41,6 +45,12 @@ ${pc.bold('Examples:')}
|
|
|
41
45
|
${pc.dim('# Frames only (no gradient/caption)')}
|
|
42
46
|
$ appshot build --no-gradient --no-caption
|
|
43
47
|
|
|
48
|
+
${pc.dim('# Use custom background image')}
|
|
49
|
+
$ appshot build --background ./assets/sunset.jpg
|
|
50
|
+
|
|
51
|
+
${pc.dim('# Auto-detect background.png in device folders')}
|
|
52
|
+
$ appshot build --auto-background
|
|
53
|
+
|
|
44
54
|
${pc.dim('# Preview what would be built')}
|
|
45
55
|
$ appshot build --dry-run
|
|
46
56
|
|
|
@@ -93,9 +103,10 @@ ${pc.bold('Language Detection:')}
|
|
|
93
103
|
}
|
|
94
104
|
// Create device output directory
|
|
95
105
|
await fs.mkdir(outputDir, { recursive: true });
|
|
96
|
-
// Get screenshots
|
|
106
|
+
// Get screenshots (excluding background images)
|
|
97
107
|
const screenshots = (await fs.readdir(inputDir))
|
|
98
108
|
.filter(f => f.match(/\.(png|jpg|jpeg)$/i))
|
|
109
|
+
.filter(f => !f.match(/^background\.(png|jpg|jpeg)$/i))
|
|
99
110
|
.sort();
|
|
100
111
|
if (screenshots.length === 0) {
|
|
101
112
|
console.log(pc.yellow('⚠'), `No screenshots found in ${inputDir}`);
|
|
@@ -223,6 +234,27 @@ ${pc.bold('Language Detection:')}
|
|
|
223
234
|
// Actual rendering
|
|
224
235
|
let image;
|
|
225
236
|
try {
|
|
237
|
+
// Configure background
|
|
238
|
+
let backgroundConfig = config.background;
|
|
239
|
+
// Override with command line options
|
|
240
|
+
if (opts.background) {
|
|
241
|
+
backgroundConfig = {
|
|
242
|
+
mode: 'image',
|
|
243
|
+
image: opts.background,
|
|
244
|
+
fit: opts.backgroundFit || 'cover',
|
|
245
|
+
warnOnMismatch: true
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
else if (opts.autoBackground) {
|
|
249
|
+
backgroundConfig = {
|
|
250
|
+
mode: 'auto',
|
|
251
|
+
fit: opts.backgroundFit || 'cover',
|
|
252
|
+
warnOnMismatch: true
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
else if (opts.noBackground) {
|
|
256
|
+
backgroundConfig = undefined;
|
|
257
|
+
}
|
|
226
258
|
image = await composeAppStoreScreenshot({
|
|
227
259
|
screenshot: screenshotBuffer,
|
|
228
260
|
frame: frame,
|
|
@@ -237,7 +269,8 @@ ${pc.bold('Language Detection:')}
|
|
|
237
269
|
} : undefined,
|
|
238
270
|
caption: opts.caption !== false ? captionText : undefined,
|
|
239
271
|
captionConfig: config.caption,
|
|
240
|
-
gradientConfig: config.gradient,
|
|
272
|
+
gradientConfig: opts.gradient === false ? undefined : config.gradient,
|
|
273
|
+
backgroundConfig: backgroundConfig,
|
|
241
274
|
deviceConfig: deviceConfig,
|
|
242
275
|
outputWidth: outWidth,
|
|
243
276
|
outputHeight: outHeight,
|