appshot-cli 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 +21 -0
- package/README.md +381 -0
- package/bin/appshot.js +5 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +31 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/build.d.ts +3 -0
- package/dist/commands/build.d.ts.map +1 -0
- package/dist/commands/build.js +200 -0
- package/dist/commands/build.js.map +1 -0
- package/dist/commands/caption.d.ts +3 -0
- package/dist/commands/caption.d.ts.map +1 -0
- package/dist/commands/caption.js +118 -0
- package/dist/commands/caption.js.map +1 -0
- package/dist/commands/check.d.ts +3 -0
- package/dist/commands/check.d.ts.map +1 -0
- package/dist/commands/check.js +121 -0
- package/dist/commands/check.js.map +1 -0
- package/dist/commands/clean.d.ts +3 -0
- package/dist/commands/clean.d.ts.map +1 -0
- package/dist/commands/clean.js +133 -0
- package/dist/commands/clean.js.map +1 -0
- package/dist/commands/init.d.ts +3 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +84 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/localize.d.ts +3 -0
- package/dist/commands/localize.d.ts.map +1 -0
- package/dist/commands/localize.js +31 -0
- package/dist/commands/localize.js.map +1 -0
- package/dist/commands/presets.d.ts +3 -0
- package/dist/commands/presets.d.ts.map +1 -0
- package/dist/commands/presets.js +135 -0
- package/dist/commands/presets.js.map +1 -0
- package/dist/commands/specs.d.ts +3 -0
- package/dist/commands/specs.d.ts.map +1 -0
- package/dist/commands/specs.js +69 -0
- package/dist/commands/specs.js.map +1 -0
- package/dist/commands/validate.d.ts +3 -0
- package/dist/commands/validate.d.ts.map +1 -0
- package/dist/commands/validate.js +183 -0
- package/dist/commands/validate.js.map +1 -0
- package/dist/core/app-store-specs.d.ts +55 -0
- package/dist/core/app-store-specs.d.ts.map +1 -0
- package/dist/core/app-store-specs.js +457 -0
- package/dist/core/app-store-specs.js.map +1 -0
- package/dist/core/compose.d.ts +30 -0
- package/dist/core/compose.d.ts.map +1 -0
- package/dist/core/compose.js +420 -0
- package/dist/core/compose.js.map +1 -0
- package/dist/core/devices.d.ts +50 -0
- package/dist/core/devices.d.ts.map +1 -0
- package/dist/core/devices.js +404 -0
- package/dist/core/devices.js.map +1 -0
- package/dist/core/files.d.ts +5 -0
- package/dist/core/files.d.ts.map +1 -0
- package/dist/core/files.js +35 -0
- package/dist/core/files.js.map +1 -0
- package/dist/core/frames-analyzer.d.ts +24 -0
- package/dist/core/frames-analyzer.d.ts.map +1 -0
- package/dist/core/frames-analyzer.js +97 -0
- package/dist/core/frames-analyzer.js.map +1 -0
- package/dist/core/frames-loader.d.ts +113 -0
- package/dist/core/frames-loader.d.ts.map +1 -0
- package/dist/core/frames-loader.js +440 -0
- package/dist/core/frames-loader.js.map +1 -0
- package/dist/core/mask-generator.d.ts +10 -0
- package/dist/core/mask-generator.d.ts.map +1 -0
- package/dist/core/mask-generator.js +99 -0
- package/dist/core/mask-generator.js.map +1 -0
- package/dist/core/render.d.ts +10 -0
- package/dist/core/render.d.ts.map +1 -0
- package/dist/core/render.js +92 -0
- package/dist/core/render.js.map +1 -0
- package/dist/core/text-renderer.d.ts +18 -0
- package/dist/core/text-renderer.d.ts.map +1 -0
- package/dist/core/text-renderer.js +148 -0
- package/dist/core/text-renderer.js.map +1 -0
- package/dist/types.d.ts +57 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/caption-history.d.ts +35 -0
- package/dist/utils/caption-history.d.ts.map +1 -0
- package/dist/utils/caption-history.js +233 -0
- package/dist/utils/caption-history.js.map +1 -0
- package/frames/Frames.json +308 -0
- package/frames/MacBook Air 2020.png +0 -0
- package/frames/MacBook Air 2022.png +0 -0
- package/frames/MacBook Pro 13.png +0 -0
- package/frames/MacBook Pro 2021 14.png +0 -0
- package/frames/MacBook Pro 2021 16.png +0 -0
- package/frames/Watch Series 10 42.png +0 -0
- package/frames/Watch Series 10 42_mask.png +0 -0
- package/frames/Watch Series 10 46.png +0 -0
- package/frames/Watch Series 10 46_mask.png +0 -0
- package/frames/Watch Series 4 40.png +0 -0
- package/frames/Watch Series 4 44.png +0 -0
- package/frames/Watch Series 7 41.png +0 -0
- package/frames/Watch Series 7 45.png +0 -0
- package/frames/Watch Ultra 2024.png +0 -0
- package/frames/iMac 2021.png +0 -0
- package/frames/iPad 2021 Landscape.png +0 -0
- package/frames/iPad 2021 Portrait.png +0 -0
- package/frames/iPad Air 2020 Landscape.png +0 -0
- package/frames/iPad Air 2020 Portrait.png +0 -0
- package/frames/iPad Pro 2018-2021 11 Landscape.png +0 -0
- package/frames/iPad Pro 2018-2021 11 Portrait.png +0 -0
- package/frames/iPad Pro 2018-2021 Landscape.png +0 -0
- package/frames/iPad Pro 2018-2021 Portrait.png +0 -0
- package/frames/iPad Pro 2024 11 Landscape.png +0 -0
- package/frames/iPad Pro 2024 11 Portrait.png +0 -0
- package/frames/iPad Pro 2024 13 Landscape.png +0 -0
- package/frames/iPad Pro 2024 13 Portrait.png +0 -0
- package/frames/iPad mini 2021 Landscape.png +0 -0
- package/frames/iPad mini 2021 Portrait.png +0 -0
- package/frames/iPhone 11 Landscape.png +0 -0
- package/frames/iPhone 11 Portrait.png +0 -0
- package/frames/iPhone 11 Pro Max Landscape.png +0 -0
- package/frames/iPhone 11 Pro Max Portrait.png +0 -0
- package/frames/iPhone 11 Pro Portrait.png +0 -0
- package/frames/iPhone 12-13 Pro Landscape.png +0 -0
- package/frames/iPhone 12-13 Pro Max Landscape.png +0 -0
- package/frames/iPhone 12-13 Pro Max Landscape_mask.png +0 -0
- package/frames/iPhone 12-13 Pro Max Portrait.png +0 -0
- package/frames/iPhone 12-13 Pro Max Portrait_mask.png +0 -0
- package/frames/iPhone 12-13 Pro Portrait.png +0 -0
- package/frames/iPhone 12-13 mini Landscape.png +0 -0
- package/frames/iPhone 12-13 mini Portrait.png +0 -0
- package/frames/iPhone 16 Landscape.png +0 -0
- package/frames/iPhone 16 Landscape_frame_no_island.png +0 -0
- package/frames/iPhone 16 Landscape_mask.png +0 -0
- package/frames/iPhone 16 Plus Landscape.png +0 -0
- package/frames/iPhone 16 Plus Landscape_frame_no_island.png +0 -0
- package/frames/iPhone 16 Plus Landscape_mask.png +0 -0
- package/frames/iPhone 16 Plus Portrait.png +0 -0
- package/frames/iPhone 16 Plus Portrait_frame_no_island.png +0 -0
- package/frames/iPhone 16 Plus Portrait_mask.png +0 -0
- package/frames/iPhone 16 Portrait.png +0 -0
- package/frames/iPhone 16 Portrait_frame_no_island.png +0 -0
- package/frames/iPhone 16 Portrait_mask.png +0 -0
- package/frames/iPhone 16 Pro Landscape.png +0 -0
- package/frames/iPhone 16 Pro Landscape_frame_no_island.png +0 -0
- package/frames/iPhone 16 Pro Landscape_mask.png +0 -0
- package/frames/iPhone 16 Pro Max Landscape.png +0 -0
- package/frames/iPhone 16 Pro Max Landscape_frame_no_island.png +0 -0
- package/frames/iPhone 16 Pro Max Landscape_mask.png +0 -0
- package/frames/iPhone 16 Pro Max Portrait.png +0 -0
- package/frames/iPhone 16 Pro Max Portrait_frame_no_island.png +0 -0
- package/frames/iPhone 16 Pro Max Portrait_mask.png +0 -0
- package/frames/iPhone 16 Pro Portrait.png +0 -0
- package/frames/iPhone 16 Pro Portrait_frame_no_island.png +0 -0
- package/frames/iPhone 16 Pro Portrait_mask.png +0 -0
- package/frames/iPhone 8 Plus Landscape.png +0 -0
- package/frames/iPhone 8 Plus Portrait.png +0 -0
- 2020 SE.png +0 -0
- package/frames/version.txt +1 -0
- package/package.json +61 -0
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import sharp from 'sharp';
|
|
2
|
+
/**
|
|
3
|
+
* Generate a rounded rectangle mask without using SVG
|
|
4
|
+
* This creates a mask where white pixels are visible and black pixels are transparent
|
|
5
|
+
*/
|
|
6
|
+
export async function generateRoundedRectMask(width, height, cornerRadius) {
|
|
7
|
+
// Create a raw pixel buffer for the mask
|
|
8
|
+
const channels = 4; // RGBA
|
|
9
|
+
const pixelCount = width * height;
|
|
10
|
+
const buffer = Buffer.alloc(pixelCount * channels);
|
|
11
|
+
// Fill the buffer with white pixels, making corners transparent
|
|
12
|
+
for (let y = 0; y < height; y++) {
|
|
13
|
+
for (let x = 0; x < width; x++) {
|
|
14
|
+
const offset = (y * width + x) * channels;
|
|
15
|
+
// Check if pixel is in a corner region
|
|
16
|
+
let inCorner = false;
|
|
17
|
+
// Top-left corner
|
|
18
|
+
if (x < cornerRadius && y < cornerRadius) {
|
|
19
|
+
const dx = cornerRadius - x;
|
|
20
|
+
const dy = cornerRadius - y;
|
|
21
|
+
const distance = Math.sqrt(dx * dx + dy * dy);
|
|
22
|
+
inCorner = distance > cornerRadius;
|
|
23
|
+
}
|
|
24
|
+
// Top-right corner
|
|
25
|
+
else if (x >= width - cornerRadius && y < cornerRadius) {
|
|
26
|
+
const dx = x - (width - cornerRadius);
|
|
27
|
+
const dy = cornerRadius - y;
|
|
28
|
+
const distance = Math.sqrt(dx * dx + dy * dy);
|
|
29
|
+
inCorner = distance > cornerRadius;
|
|
30
|
+
}
|
|
31
|
+
// Bottom-left corner
|
|
32
|
+
else if (x < cornerRadius && y >= height - cornerRadius) {
|
|
33
|
+
const dx = cornerRadius - x;
|
|
34
|
+
const dy = y - (height - cornerRadius);
|
|
35
|
+
const distance = Math.sqrt(dx * dx + dy * dy);
|
|
36
|
+
inCorner = distance > cornerRadius;
|
|
37
|
+
}
|
|
38
|
+
// Bottom-right corner
|
|
39
|
+
else if (x >= width - cornerRadius && y >= height - cornerRadius) {
|
|
40
|
+
const dx = x - (width - cornerRadius);
|
|
41
|
+
const dy = y - (height - cornerRadius);
|
|
42
|
+
const distance = Math.sqrt(dx * dx + dy * dy);
|
|
43
|
+
inCorner = distance > cornerRadius;
|
|
44
|
+
}
|
|
45
|
+
if (inCorner) {
|
|
46
|
+
// Transparent (black in mask)
|
|
47
|
+
buffer[offset] = 0; // R
|
|
48
|
+
buffer[offset + 1] = 0; // G
|
|
49
|
+
buffer[offset + 2] = 0; // B
|
|
50
|
+
buffer[offset + 3] = 0; // A
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
// Visible (white in mask)
|
|
54
|
+
buffer[offset] = 255; // R
|
|
55
|
+
buffer[offset + 1] = 255; // G
|
|
56
|
+
buffer[offset + 2] = 255; // B
|
|
57
|
+
buffer[offset + 3] = 255; // A
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
// Convert raw buffer to PNG using Sharp
|
|
62
|
+
const mask = await sharp(buffer, {
|
|
63
|
+
raw: {
|
|
64
|
+
width: width,
|
|
65
|
+
height: height,
|
|
66
|
+
channels: 4
|
|
67
|
+
}
|
|
68
|
+
})
|
|
69
|
+
.png()
|
|
70
|
+
.toBuffer();
|
|
71
|
+
return mask;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Apply a rounded rectangle mask to an image
|
|
75
|
+
*/
|
|
76
|
+
export async function applyRoundedCorners(imageBuffer, width, height, cornerRadius) {
|
|
77
|
+
if (cornerRadius <= 0) {
|
|
78
|
+
return imageBuffer;
|
|
79
|
+
}
|
|
80
|
+
try {
|
|
81
|
+
// Generate the mask
|
|
82
|
+
const mask = await generateRoundedRectMask(width, height, cornerRadius);
|
|
83
|
+
// Apply the mask using composite
|
|
84
|
+
const result = await sharp(imageBuffer)
|
|
85
|
+
.ensureAlpha()
|
|
86
|
+
.composite([{
|
|
87
|
+
input: mask,
|
|
88
|
+
blend: 'dest-in'
|
|
89
|
+
}])
|
|
90
|
+
.png()
|
|
91
|
+
.toBuffer();
|
|
92
|
+
return result;
|
|
93
|
+
}
|
|
94
|
+
catch (error) {
|
|
95
|
+
console.warn('Failed to apply rounded corners:', error);
|
|
96
|
+
return imageBuffer;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=mask-generator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mask-generator.js","sourceRoot":"","sources":["../../src/core/mask-generator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { GradientConfig, CaptionConfig } from '../types.js';
|
|
2
|
+
export declare function renderGradient(width: number, height: number, config: GradientConfig): Promise<Buffer>;
|
|
3
|
+
export declare function addCaption(image: Buffer, text: string, config: CaptionConfig): Promise<Buffer>;
|
|
4
|
+
export declare function compositeScreenshot(screenshot: Buffer, frame: Buffer | null, frameMetadata?: {
|
|
5
|
+
screenX: number;
|
|
6
|
+
screenY: number;
|
|
7
|
+
screenWidth: number;
|
|
8
|
+
screenHeight: number;
|
|
9
|
+
}): Promise<Buffer>;
|
|
10
|
+
//# sourceMappingURL=render.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../src/core/render.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAGjE,wBAAsB,cAAc,CAClC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,cAAc,GACrB,OAAO,CAAC,MAAM,CAAC,CAsBjB;AAED,wBAAsB,UAAU,CAC9B,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,MAAM,CAAC,CAyCjB;AAED,wBAAsB,mBAAmB,CACvC,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,MAAM,GAAG,IAAI,EACpB,aAAa,CAAC,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,GAC9F,OAAO,CAAC,MAAM,CAAC,CAwBjB"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import sharp from 'sharp';
|
|
2
|
+
import { createGradientBitmap } from './text-renderer.js';
|
|
3
|
+
export async function renderGradient(width, height, config) {
|
|
4
|
+
// Use bitmap gradient instead of SVG
|
|
5
|
+
const { colors, direction } = config;
|
|
6
|
+
// Use bitmap gradient instead of SVG - works without librsvg!
|
|
7
|
+
const directionMap = {
|
|
8
|
+
'top-bottom': 'vertical',
|
|
9
|
+
'bottom-top': 'vertical', // Will need to reverse colors
|
|
10
|
+
'left-right': 'horizontal',
|
|
11
|
+
'right-left': 'horizontal', // Will need to reverse colors
|
|
12
|
+
'diagonal': 'diagonal'
|
|
13
|
+
};
|
|
14
|
+
const mappedDirection = directionMap[direction || 'top-bottom'] || 'vertical';
|
|
15
|
+
let effectiveColors = [...colors];
|
|
16
|
+
// Reverse colors for bottom-top or right-left
|
|
17
|
+
if (direction === 'bottom-top' || direction === 'right-left') {
|
|
18
|
+
effectiveColors = effectiveColors.reverse();
|
|
19
|
+
}
|
|
20
|
+
return await createGradientBitmap(width, height, effectiveColors, mappedDirection);
|
|
21
|
+
}
|
|
22
|
+
export async function addCaption(image, text, config) {
|
|
23
|
+
if (!text)
|
|
24
|
+
return image;
|
|
25
|
+
const metadata = await sharp(image).metadata();
|
|
26
|
+
const width = metadata.width || 1000;
|
|
27
|
+
const height = metadata.height || 1000;
|
|
28
|
+
// Create text as SVG
|
|
29
|
+
const textY = config.paddingTop + config.fontsize;
|
|
30
|
+
let textAnchor = 'middle';
|
|
31
|
+
let textX = width / 2;
|
|
32
|
+
if (config.align === 'left') {
|
|
33
|
+
textAnchor = 'start';
|
|
34
|
+
textX = config.paddingLeft || 50;
|
|
35
|
+
}
|
|
36
|
+
else if (config.align === 'right') {
|
|
37
|
+
textAnchor = 'end';
|
|
38
|
+
textX = width - (config.paddingRight || 50);
|
|
39
|
+
}
|
|
40
|
+
const svg = `
|
|
41
|
+
<svg width="${width}" height="${height}" xmlns="http://www.w3.org/2000/svg">
|
|
42
|
+
<text
|
|
43
|
+
x="${textX}"
|
|
44
|
+
y="${textY}"
|
|
45
|
+
font-family="${config.font}"
|
|
46
|
+
font-size="${config.fontsize}"
|
|
47
|
+
fill="${config.color}"
|
|
48
|
+
text-anchor="${textAnchor}"
|
|
49
|
+
>${escapeXml(text)}</text>
|
|
50
|
+
</svg>
|
|
51
|
+
`;
|
|
52
|
+
// Composite text over image
|
|
53
|
+
return sharp(image)
|
|
54
|
+
.composite([{
|
|
55
|
+
input: Buffer.from(svg),
|
|
56
|
+
top: 0,
|
|
57
|
+
left: 0
|
|
58
|
+
}])
|
|
59
|
+
.toBuffer();
|
|
60
|
+
}
|
|
61
|
+
export async function compositeScreenshot(screenshot, frame, frameMetadata) {
|
|
62
|
+
if (!frame)
|
|
63
|
+
return screenshot;
|
|
64
|
+
// Default frame metadata (will be customized per device)
|
|
65
|
+
const meta = frameMetadata || {
|
|
66
|
+
screenX: 100,
|
|
67
|
+
screenY: 200,
|
|
68
|
+
screenWidth: 1084,
|
|
69
|
+
screenHeight: 2378
|
|
70
|
+
};
|
|
71
|
+
// Resize screenshot to fit frame screen area
|
|
72
|
+
const resizedScreenshot = await sharp(screenshot)
|
|
73
|
+
.resize(meta.screenWidth, meta.screenHeight, { fit: 'fill' })
|
|
74
|
+
.toBuffer();
|
|
75
|
+
// Composite screenshot into frame
|
|
76
|
+
return sharp(frame)
|
|
77
|
+
.composite([{
|
|
78
|
+
input: resizedScreenshot,
|
|
79
|
+
left: meta.screenX,
|
|
80
|
+
top: meta.screenY
|
|
81
|
+
}])
|
|
82
|
+
.toBuffer();
|
|
83
|
+
}
|
|
84
|
+
function escapeXml(text) {
|
|
85
|
+
return text
|
|
86
|
+
.replace(/&/g, '&')
|
|
87
|
+
.replace(/</g, '<')
|
|
88
|
+
.replace(/>/g, '>')
|
|
89
|
+
.replace(/"/g, '"')
|
|
90
|
+
.replace(/'/g, ''');
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=render.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render.js","sourceRoot":"","sources":["../../src/core/render.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Render text by creating a bitmap with text
|
|
3
|
+
* This works without SVG or any external dependencies
|
|
4
|
+
*/
|
|
5
|
+
export declare function renderTextBitmap(text: string, width: number, height: number, _config: {
|
|
6
|
+
fontsize: number;
|
|
7
|
+
color: string;
|
|
8
|
+
align?: 'left' | 'center' | 'right';
|
|
9
|
+
paddingTop: number;
|
|
10
|
+
paddingLeft?: number;
|
|
11
|
+
paddingRight?: number;
|
|
12
|
+
font?: string;
|
|
13
|
+
}): Promise<Buffer>;
|
|
14
|
+
/**
|
|
15
|
+
* Create a gradient using pure bitmap manipulation
|
|
16
|
+
*/
|
|
17
|
+
export declare function createGradientBitmap(width: number, height: number, colors: string[], direction?: 'vertical' | 'horizontal' | 'diagonal'): Promise<Buffer>;
|
|
18
|
+
//# sourceMappingURL=text-renderer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text-renderer.d.ts","sourceRoot":"","sources":["../../src/core/text-renderer.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,OAAO,EAAE;IACP,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;IACpC,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,GACA,OAAO,CAAC,MAAM,CAAC,CA+CjB;AAuDD;;GAEG;AACH,wBAAsB,oBAAoB,CACxC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EAAE,EAChB,SAAS,GAAE,UAAU,GAAG,YAAY,GAAG,UAAuB,GAC7D,OAAO,CAAC,MAAM,CAAC,CAsDjB"}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import sharp from 'sharp';
|
|
2
|
+
/**
|
|
3
|
+
* Render text by creating a bitmap with text
|
|
4
|
+
* This works without SVG or any external dependencies
|
|
5
|
+
*/
|
|
6
|
+
export async function renderTextBitmap(text, width, height, _config) {
|
|
7
|
+
// Validate and sanitize color to prevent XSS
|
|
8
|
+
const _validateColor = (color) => {
|
|
9
|
+
// Remove any whitespace and convert to lowercase
|
|
10
|
+
const clean = color.trim().toLowerCase();
|
|
11
|
+
// Check if it's a valid hex color
|
|
12
|
+
const hexPattern = /^#?([0-9a-f]{3}|[0-9a-f]{6})$/;
|
|
13
|
+
if (hexPattern.test(clean)) {
|
|
14
|
+
return clean.startsWith('#') ? clean : `#${clean}`;
|
|
15
|
+
}
|
|
16
|
+
// Check if it's a valid named color (basic set)
|
|
17
|
+
const namedColors = ['black', 'white', 'red', 'green', 'blue', 'yellow', 'cyan', 'magenta', 'gray', 'grey'];
|
|
18
|
+
if (namedColors.includes(clean)) {
|
|
19
|
+
return clean;
|
|
20
|
+
}
|
|
21
|
+
// Default to black if invalid
|
|
22
|
+
console.warn(`Invalid color "${color}" provided, using default #000000`);
|
|
23
|
+
return '#000000';
|
|
24
|
+
};
|
|
25
|
+
// Create a transparent background
|
|
26
|
+
const background = await sharp({
|
|
27
|
+
create: {
|
|
28
|
+
width,
|
|
29
|
+
height,
|
|
30
|
+
channels: 4,
|
|
31
|
+
background: { r: 0, g: 0, b: 0, alpha: 0 }
|
|
32
|
+
}
|
|
33
|
+
})
|
|
34
|
+
.png()
|
|
35
|
+
.toBuffer();
|
|
36
|
+
// Use Sharp's text annotation feature which doesn't require SVG
|
|
37
|
+
try {
|
|
38
|
+
// Simple text rendering without Pango to avoid dimension issues
|
|
39
|
+
// For now, just return the transparent background
|
|
40
|
+
// Text rendering with Pango requires librsvg which we're avoiding
|
|
41
|
+
return background;
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
console.log('[INFO] Text rendering using Pango not available, trying fallback...');
|
|
45
|
+
// Fallback: Return background without text but continue processing
|
|
46
|
+
return background;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
function _escapeText(text) {
|
|
50
|
+
return text
|
|
51
|
+
.replace(/&/g, '&')
|
|
52
|
+
.replace(/</g, '<')
|
|
53
|
+
.replace(/>/g, '>')
|
|
54
|
+
.replace(/"/g, '"')
|
|
55
|
+
.replace(/'/g, ''');
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Wrap text to fit within a given width
|
|
59
|
+
*/
|
|
60
|
+
function _wrapText(text, width, fontSize, maxLines = 3) {
|
|
61
|
+
// Estimate characters per line (rough approximation)
|
|
62
|
+
const charsPerLine = Math.floor(width / (fontSize * 0.45)); // Adjusted for better fit
|
|
63
|
+
if (text.length <= charsPerLine) {
|
|
64
|
+
return text;
|
|
65
|
+
}
|
|
66
|
+
// Simple word wrapping
|
|
67
|
+
const words = text.split(' ');
|
|
68
|
+
const lines = [];
|
|
69
|
+
let currentLine = '';
|
|
70
|
+
for (const word of words) {
|
|
71
|
+
const testLine = currentLine ? `${currentLine} ${word}` : word;
|
|
72
|
+
if (testLine.length <= charsPerLine && lines.length < maxLines - 1) {
|
|
73
|
+
currentLine = testLine;
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
if (currentLine && lines.length < maxLines) {
|
|
77
|
+
lines.push(currentLine);
|
|
78
|
+
}
|
|
79
|
+
currentLine = word;
|
|
80
|
+
}
|
|
81
|
+
// Stop if we've reached max lines
|
|
82
|
+
if (lines.length >= maxLines - 1 && currentLine) {
|
|
83
|
+
// Put remaining words on last line
|
|
84
|
+
const remainingWords = words.slice(words.indexOf(word));
|
|
85
|
+
lines.push(remainingWords.join(' '));
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
if (currentLine && lines.length < maxLines) {
|
|
90
|
+
lines.push(currentLine);
|
|
91
|
+
}
|
|
92
|
+
// Join with newlines for Pango markup
|
|
93
|
+
return lines.slice(0, maxLines).join('\n');
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Create a gradient using pure bitmap manipulation
|
|
97
|
+
*/
|
|
98
|
+
export async function createGradientBitmap(width, height, colors, direction = 'vertical') {
|
|
99
|
+
// Parse hex colors
|
|
100
|
+
const parseHex = (hex) => {
|
|
101
|
+
const clean = hex.replace('#', '');
|
|
102
|
+
return {
|
|
103
|
+
r: parseInt(clean.slice(0, 2), 16),
|
|
104
|
+
g: parseInt(clean.slice(2, 4), 16),
|
|
105
|
+
b: parseInt(clean.slice(4, 6), 16)
|
|
106
|
+
};
|
|
107
|
+
};
|
|
108
|
+
const startColor = parseHex(colors[0] || '#6B46C1');
|
|
109
|
+
const endColor = parseHex(colors[colors.length - 1] || '#9333EA');
|
|
110
|
+
// Create raw pixel buffer for gradient
|
|
111
|
+
const channels = 3;
|
|
112
|
+
const pixelCount = width * height;
|
|
113
|
+
const buffer = Buffer.alloc(pixelCount * channels);
|
|
114
|
+
// Generate gradient pixels
|
|
115
|
+
for (let y = 0; y < height; y++) {
|
|
116
|
+
for (let x = 0; x < width; x++) {
|
|
117
|
+
let ratio;
|
|
118
|
+
if (direction === 'horizontal') {
|
|
119
|
+
ratio = x / width;
|
|
120
|
+
}
|
|
121
|
+
else if (direction === 'diagonal') {
|
|
122
|
+
ratio = (x + y) / (width + height);
|
|
123
|
+
}
|
|
124
|
+
else { // vertical
|
|
125
|
+
ratio = y / height;
|
|
126
|
+
}
|
|
127
|
+
// Linear interpolation between colors
|
|
128
|
+
const r = Math.round(startColor.r + (endColor.r - startColor.r) * ratio);
|
|
129
|
+
const g = Math.round(startColor.g + (endColor.g - startColor.g) * ratio);
|
|
130
|
+
const b = Math.round(startColor.b + (endColor.b - startColor.b) * ratio);
|
|
131
|
+
const offset = (y * width + x) * channels;
|
|
132
|
+
buffer[offset] = r;
|
|
133
|
+
buffer[offset + 1] = g;
|
|
134
|
+
buffer[offset + 2] = b;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
// Convert raw buffer to PNG using Sharp
|
|
138
|
+
return await sharp(buffer, {
|
|
139
|
+
raw: {
|
|
140
|
+
width,
|
|
141
|
+
height,
|
|
142
|
+
channels
|
|
143
|
+
}
|
|
144
|
+
})
|
|
145
|
+
.png()
|
|
146
|
+
.toBuffer();
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=text-renderer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text-renderer.js","sourceRoot":"","sources":["../../src/core/text-renderer.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
export interface GradientConfig {
|
|
2
|
+
colors: string[];
|
|
3
|
+
direction: 'top-bottom' | 'bottom-top' | 'left-right' | 'right-left' | 'diagonal';
|
|
4
|
+
}
|
|
5
|
+
export interface CaptionConfig {
|
|
6
|
+
font: string;
|
|
7
|
+
fontsize: number;
|
|
8
|
+
color: string;
|
|
9
|
+
align: 'left' | 'center' | 'right';
|
|
10
|
+
paddingTop: number;
|
|
11
|
+
paddingBottom?: number;
|
|
12
|
+
paddingLeft?: number;
|
|
13
|
+
paddingRight?: number;
|
|
14
|
+
position?: 'overlay' | 'above';
|
|
15
|
+
}
|
|
16
|
+
export interface DeviceConfig {
|
|
17
|
+
input: string;
|
|
18
|
+
resolution: string;
|
|
19
|
+
frame?: string;
|
|
20
|
+
autoFrame?: boolean;
|
|
21
|
+
preferredFrame?: string;
|
|
22
|
+
partialFrame?: boolean;
|
|
23
|
+
frameOffset?: number;
|
|
24
|
+
}
|
|
25
|
+
export interface AppshotConfig {
|
|
26
|
+
output: string;
|
|
27
|
+
frames: string;
|
|
28
|
+
gradient: GradientConfig;
|
|
29
|
+
caption: CaptionConfig;
|
|
30
|
+
devices: {
|
|
31
|
+
[key: string]: DeviceConfig;
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
export interface CaptionEntry {
|
|
35
|
+
[lang: string]: string;
|
|
36
|
+
}
|
|
37
|
+
export interface CaptionsFile {
|
|
38
|
+
[filename: string]: string | CaptionEntry;
|
|
39
|
+
}
|
|
40
|
+
export interface CaptionSuggestions {
|
|
41
|
+
global: string[];
|
|
42
|
+
iphone?: string[];
|
|
43
|
+
ipad?: string[];
|
|
44
|
+
mac?: string[];
|
|
45
|
+
watch?: string[];
|
|
46
|
+
[device: string]: string[] | undefined;
|
|
47
|
+
}
|
|
48
|
+
export interface CaptionFrequency {
|
|
49
|
+
[caption: string]: number;
|
|
50
|
+
}
|
|
51
|
+
export interface CaptionHistory {
|
|
52
|
+
suggestions: CaptionSuggestions;
|
|
53
|
+
frequency: CaptionFrequency;
|
|
54
|
+
patterns: string[];
|
|
55
|
+
lastUpdated: string;
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,SAAS,EAAE,YAAY,GAAG,YAAY,GAAG,YAAY,GAAG,YAAY,GAAG,UAAU,CAAC;CACnF;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC;CAChC;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,cAAc,CAAC;IACzB,OAAO,EAAE,aAAa,CAAC;IACvB,OAAO,EAAE;QACP,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,CAAC;KAC7B,CAAC;CACH;AAED,MAAM,WAAW,YAAY;IAC3B,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,YAAY;IAC3B,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,YAAY,CAAC;CAC3C;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC;CACxC;AAED,MAAM,WAAW,gBAAgB;IAC/B,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,kBAAkB,CAAC;IAChC,SAAS,EAAE,gBAAgB,CAAC;IAC5B,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;CACrB"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { CaptionHistory } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Load caption history from file
|
|
4
|
+
*/
|
|
5
|
+
export declare function loadCaptionHistory(): Promise<CaptionHistory>;
|
|
6
|
+
/**
|
|
7
|
+
* Save caption history to file
|
|
8
|
+
*/
|
|
9
|
+
export declare function saveCaptionHistory(history: CaptionHistory): Promise<void>;
|
|
10
|
+
/**
|
|
11
|
+
* Update frequency count for a caption
|
|
12
|
+
*/
|
|
13
|
+
export declare function updateFrequency(history: CaptionHistory, caption: string): void;
|
|
14
|
+
/**
|
|
15
|
+
* Add a caption to suggestions if it's new
|
|
16
|
+
*/
|
|
17
|
+
export declare function addToSuggestions(history: CaptionHistory, caption: string, device?: string): void;
|
|
18
|
+
/**
|
|
19
|
+
* Extract patterns from a caption
|
|
20
|
+
* e.g., "Track your workouts" -> "Track your *"
|
|
21
|
+
*/
|
|
22
|
+
export declare function extractPatterns(caption: string): string[];
|
|
23
|
+
/**
|
|
24
|
+
* Learn from existing caption files
|
|
25
|
+
*/
|
|
26
|
+
export declare function learnFromExistingCaptions(history: CaptionHistory): Promise<void>;
|
|
27
|
+
/**
|
|
28
|
+
* Get suggestions for autocomplete
|
|
29
|
+
*/
|
|
30
|
+
export declare function getSuggestions(history: CaptionHistory, device?: string, currentInput?: string): string[];
|
|
31
|
+
/**
|
|
32
|
+
* Clear caption history
|
|
33
|
+
*/
|
|
34
|
+
export declare function clearCaptionHistory(): Promise<void>;
|
|
35
|
+
//# sourceMappingURL=caption-history.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"caption-history.d.ts","sourceRoot":"","sources":["../../src/utils/caption-history.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAoC,MAAM,aAAa,CAAC;AAMpF;;GAEG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,cAAc,CAAC,CAmClE;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAY/E;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAK9E;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,cAAc,EACvB,OAAO,EAAE,MAAM,EACf,MAAM,CAAC,EAAE,MAAM,GACd,IAAI,CAoBN;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAkBzD;AAED;;GAEG;AACH,wBAAsB,yBAAyB,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAyCtF;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,cAAc,EACvB,MAAM,CAAC,EAAE,MAAM,EACf,YAAY,CAAC,EAAE,MAAM,GACpB,MAAM,EAAE,CA8CV;AAmCD;;GAEG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC,CAQzD"}
|