appshot-cli 0.2.2 → 0.4.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 +1329 -589
- package/dist/cli.js +5 -1
- package/dist/cli.js.map +1 -1
- package/dist/commands/build.d.ts.map +1 -1
- package/dist/commands/build.js +11 -4
- package/dist/commands/build.js.map +1 -1
- package/dist/commands/caption.d.ts.map +1 -1
- package/dist/commands/caption.js +74 -2
- package/dist/commands/caption.js.map +1 -1
- package/dist/commands/fonts.d.ts +3 -0
- package/dist/commands/fonts.d.ts.map +1 -0
- package/dist/commands/fonts.js +384 -0
- package/dist/commands/fonts.js.map +1 -0
- package/dist/commands/localize.d.ts.map +1 -1
- package/dist/commands/localize.js +150 -14
- package/dist/commands/localize.js.map +1 -1
- package/dist/commands/migrate.d.ts +3 -0
- package/dist/commands/migrate.d.ts.map +1 -0
- package/dist/commands/migrate.js +123 -0
- package/dist/commands/migrate.js.map +1 -0
- package/dist/commands/style.d.ts.map +1 -1
- package/dist/commands/style.js +92 -1
- package/dist/commands/style.js.map +1 -1
- package/dist/core/compose.d.ts +4 -0
- package/dist/core/compose.d.ts.map +1 -1
- package/dist/core/compose.js +102 -9
- package/dist/core/compose.js.map +1 -1
- package/dist/services/fonts.d.ts +71 -0
- package/dist/services/fonts.d.ts.map +1 -0
- package/dist/services/fonts.js +314 -0
- package/dist/services/fonts.js.map +1 -0
- package/dist/services/translation.d.ts +18 -0
- package/dist/services/translation.d.ts.map +1 -0
- package/dist/services/translation.js +201 -0
- package/dist/services/translation.js.map +1 -0
- package/dist/types/ai.d.ts +25 -0
- package/dist/types/ai.d.ts.map +1 -0
- package/dist/types/ai.js +73 -0
- package/dist/types/ai.js.map +1 -0
- package/dist/types.d.ts +2 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/language.d.ts +32 -0
- package/dist/utils/language.d.ts.map +1 -0
- package/dist/utils/language.js +103 -0
- package/dist/utils/language.js.map +1 -0
- package/package.json +3 -1
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
export interface FontInfo {
|
|
2
|
+
name: string;
|
|
3
|
+
family?: string;
|
|
4
|
+
style?: string;
|
|
5
|
+
category?: 'system' | 'recommended' | 'web-safe';
|
|
6
|
+
fallback?: string;
|
|
7
|
+
installed?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export interface FontCategory {
|
|
10
|
+
name: string;
|
|
11
|
+
fonts: FontInfo[];
|
|
12
|
+
}
|
|
13
|
+
export interface FontStatus {
|
|
14
|
+
name: string;
|
|
15
|
+
installed: boolean;
|
|
16
|
+
category?: 'system' | 'recommended' | 'web-safe';
|
|
17
|
+
fallback: string;
|
|
18
|
+
warning?: string;
|
|
19
|
+
}
|
|
20
|
+
export declare class FontService {
|
|
21
|
+
private static instance;
|
|
22
|
+
private systemFontsCache;
|
|
23
|
+
static getInstance(): FontService;
|
|
24
|
+
/**
|
|
25
|
+
* Get list of system fonts based on platform
|
|
26
|
+
*/
|
|
27
|
+
getSystemFonts(): Promise<string[]>;
|
|
28
|
+
/**
|
|
29
|
+
* Get fonts on macOS using system_profiler
|
|
30
|
+
*/
|
|
31
|
+
private getMacOSFonts;
|
|
32
|
+
/**
|
|
33
|
+
* Get fonts on Linux using fc-list
|
|
34
|
+
*/
|
|
35
|
+
private getLinuxFonts;
|
|
36
|
+
/**
|
|
37
|
+
* Get fonts on Windows using PowerShell
|
|
38
|
+
*/
|
|
39
|
+
private getWindowsFonts;
|
|
40
|
+
/**
|
|
41
|
+
* Get recommended fonts with installation status
|
|
42
|
+
*/
|
|
43
|
+
getRecommendedFonts(): Promise<FontInfo[]>;
|
|
44
|
+
/**
|
|
45
|
+
* Get basic recommended fonts (without async check) for backward compatibility
|
|
46
|
+
*/
|
|
47
|
+
getRecommendedFontsSync(): FontInfo[];
|
|
48
|
+
/**
|
|
49
|
+
* Get fonts organized by category with installation status
|
|
50
|
+
*/
|
|
51
|
+
getFontCategories(): Promise<FontCategory[]>;
|
|
52
|
+
/**
|
|
53
|
+
* Check if a font is actually installed on the system
|
|
54
|
+
* This is the TRUTH - only returns true if font can actually be used
|
|
55
|
+
*/
|
|
56
|
+
isFontInstalled(fontName: string): Promise<boolean>;
|
|
57
|
+
/**
|
|
58
|
+
* Validate if a font can be rendered
|
|
59
|
+
* NOW only checks if actually installed, not just "recommended"
|
|
60
|
+
*/
|
|
61
|
+
validateFont(fontName: string): Promise<boolean>;
|
|
62
|
+
/**
|
|
63
|
+
* Get detailed status about a font
|
|
64
|
+
*/
|
|
65
|
+
getFontStatus(fontName: string): Promise<FontStatus>;
|
|
66
|
+
/**
|
|
67
|
+
* Get a font's fallback chain (synchronous for backward compatibility)
|
|
68
|
+
*/
|
|
69
|
+
getFontFallback(fontName: string): string;
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=fonts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fonts.d.ts","sourceRoot":"","sources":["../../src/services/fonts.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,QAAQ,GAAG,aAAa,GAAG,UAAU,CAAC;IACjD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,QAAQ,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,QAAQ,GAAG,aAAa,GAAG,UAAU,CAAC;IACjD,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAc;IACrC,OAAO,CAAC,gBAAgB,CAAyB;WAEnC,WAAW,IAAI,WAAW;IAOxC;;OAEG;IACG,cAAc,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IA8BzC;;OAEG;YACW,aAAa;IA8B3B;;OAEG;YACW,aAAa;IAwB3B;;OAEG;YACW,eAAe;IAkB7B;;OAEG;IACG,mBAAmB,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;IA8ChD;;OAEG;IACH,uBAAuB,IAAI,QAAQ,EAAE;IAcrC;;OAEG;IACG,iBAAiB,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;IAsDlD;;;OAGG;IACG,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAKzD;;;OAGG;IACG,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAKtD;;OAEG;IACG,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAyB1D;;OAEG;IACH,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM;CAgD1C"}
|
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
import { exec } from 'child_process';
|
|
2
|
+
import { promisify } from 'util';
|
|
3
|
+
import { platform } from 'os';
|
|
4
|
+
const execAsync = promisify(exec);
|
|
5
|
+
export class FontService {
|
|
6
|
+
static instance;
|
|
7
|
+
systemFontsCache = null;
|
|
8
|
+
static getInstance() {
|
|
9
|
+
if (!FontService.instance) {
|
|
10
|
+
FontService.instance = new FontService();
|
|
11
|
+
}
|
|
12
|
+
return FontService.instance;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Get list of system fonts based on platform
|
|
16
|
+
*/
|
|
17
|
+
async getSystemFonts() {
|
|
18
|
+
if (this.systemFontsCache) {
|
|
19
|
+
return this.systemFontsCache;
|
|
20
|
+
}
|
|
21
|
+
const os = platform();
|
|
22
|
+
let fonts = [];
|
|
23
|
+
try {
|
|
24
|
+
switch (os) {
|
|
25
|
+
case 'darwin': // macOS
|
|
26
|
+
fonts = await this.getMacOSFonts();
|
|
27
|
+
break;
|
|
28
|
+
case 'linux':
|
|
29
|
+
fonts = await this.getLinuxFonts();
|
|
30
|
+
break;
|
|
31
|
+
case 'win32':
|
|
32
|
+
fonts = await this.getWindowsFonts();
|
|
33
|
+
break;
|
|
34
|
+
default:
|
|
35
|
+
console.warn(`Font detection not implemented for platform: ${os}`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
console.error('Error detecting system fonts:', error);
|
|
40
|
+
}
|
|
41
|
+
this.systemFontsCache = fonts;
|
|
42
|
+
return fonts;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Get fonts on macOS using system_profiler
|
|
46
|
+
*/
|
|
47
|
+
async getMacOSFonts() {
|
|
48
|
+
try {
|
|
49
|
+
const { stdout } = await execAsync('system_profiler SPFontsDataType -json', {
|
|
50
|
+
maxBuffer: 10 * 1024 * 1024 // 10MB buffer to handle large font lists
|
|
51
|
+
});
|
|
52
|
+
const data = JSON.parse(stdout);
|
|
53
|
+
const fonts = new Set();
|
|
54
|
+
// Parse the JSON structure
|
|
55
|
+
if (data.SPFontsDataType) {
|
|
56
|
+
for (const font of data.SPFontsDataType) {
|
|
57
|
+
// Extract typefaces
|
|
58
|
+
if (font.typefaces) {
|
|
59
|
+
for (const typefaceKey of Object.keys(font.typefaces)) {
|
|
60
|
+
const typeface = font.typefaces[typefaceKey];
|
|
61
|
+
if (typeface.family) {
|
|
62
|
+
fonts.add(typeface.family);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return Array.from(fonts).sort();
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
console.error('Error getting macOS fonts:', error);
|
|
72
|
+
return [];
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Get fonts on Linux using fc-list
|
|
77
|
+
*/
|
|
78
|
+
async getLinuxFonts() {
|
|
79
|
+
try {
|
|
80
|
+
const { stdout } = await execAsync('fc-list : family');
|
|
81
|
+
const fonts = new Set();
|
|
82
|
+
const lines = stdout.split('\n');
|
|
83
|
+
for (const line of lines) {
|
|
84
|
+
const fontName = line.trim();
|
|
85
|
+
if (fontName) {
|
|
86
|
+
// fc-list may return comma-separated font names
|
|
87
|
+
const names = fontName.split(',');
|
|
88
|
+
for (const name of names) {
|
|
89
|
+
fonts.add(name.trim());
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return Array.from(fonts).sort();
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
console.warn('fc-list not available, using fallback fonts');
|
|
97
|
+
return this.getRecommendedFontsSync().map(f => f.name);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Get fonts on Windows using PowerShell
|
|
102
|
+
*/
|
|
103
|
+
async getWindowsFonts() {
|
|
104
|
+
try {
|
|
105
|
+
const { stdout } = await execAsync('powershell -Command "[System.Reflection.Assembly]::LoadWithPartialName(\'System.Drawing\'); (New-Object System.Drawing.Text.InstalledFontCollection).Families | ForEach-Object { $_.Name }"');
|
|
106
|
+
const fonts = stdout
|
|
107
|
+
.split('\n')
|
|
108
|
+
.map(line => line.trim())
|
|
109
|
+
.filter(line => line.length > 0);
|
|
110
|
+
return fonts.sort();
|
|
111
|
+
}
|
|
112
|
+
catch {
|
|
113
|
+
console.warn('Could not get Windows fonts, using fallback fonts');
|
|
114
|
+
return this.getRecommendedFontsSync().map(f => f.name);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Get recommended fonts with installation status
|
|
119
|
+
*/
|
|
120
|
+
async getRecommendedFonts() {
|
|
121
|
+
const systemFonts = await this.getSystemFonts();
|
|
122
|
+
const systemFontSet = new Set(systemFonts.map(f => f.toLowerCase()));
|
|
123
|
+
const fonts = [
|
|
124
|
+
// Sans-serif fonts (web-safe are usually installed)
|
|
125
|
+
{ name: 'Helvetica', family: 'Helvetica', category: 'web-safe', fallback: 'Arial, sans-serif' },
|
|
126
|
+
{ name: 'Arial', family: 'Arial', category: 'web-safe', fallback: 'Helvetica, sans-serif' },
|
|
127
|
+
{ name: 'Roboto', family: 'Roboto', category: 'recommended', fallback: 'Arial, sans-serif' },
|
|
128
|
+
{ name: 'Open Sans', family: 'Open Sans', category: 'recommended', fallback: 'Arial, sans-serif' },
|
|
129
|
+
{ name: 'Montserrat', family: 'Montserrat', category: 'recommended', fallback: 'Arial, sans-serif' },
|
|
130
|
+
{ name: 'Lato', family: 'Lato', category: 'recommended', fallback: 'Arial, sans-serif' },
|
|
131
|
+
{ name: 'Poppins', family: 'Poppins', category: 'recommended', fallback: 'Arial, sans-serif' },
|
|
132
|
+
{ name: 'Inter', family: 'Inter', category: 'recommended', fallback: 'Arial, sans-serif' },
|
|
133
|
+
// Serif fonts
|
|
134
|
+
{ name: 'Georgia', family: 'Georgia', category: 'web-safe', fallback: 'Times New Roman, serif' },
|
|
135
|
+
{ name: 'Times New Roman', family: 'Times New Roman', category: 'web-safe', fallback: 'Georgia, serif' },
|
|
136
|
+
{ name: 'Playfair Display', family: 'Playfair Display', category: 'recommended', fallback: 'Georgia, serif' },
|
|
137
|
+
{ name: 'Merriweather', family: 'Merriweather', category: 'recommended', fallback: 'Georgia, serif' },
|
|
138
|
+
// Monospace fonts
|
|
139
|
+
{ name: 'Courier New', family: 'Courier New', category: 'web-safe', fallback: 'monospace' },
|
|
140
|
+
{ name: 'Monaco', family: 'Monaco', category: 'web-safe', fallback: 'Courier New, monospace' },
|
|
141
|
+
{ name: 'Consolas', family: 'Consolas', category: 'web-safe', fallback: 'Courier New, monospace' },
|
|
142
|
+
// Display fonts
|
|
143
|
+
{ name: 'Impact', family: 'Impact', category: 'web-safe', fallback: 'Arial Black, sans-serif' },
|
|
144
|
+
{ name: 'Arial Black', family: 'Arial Black', category: 'web-safe', fallback: 'Impact, sans-serif' },
|
|
145
|
+
// System fonts
|
|
146
|
+
{ name: 'SF Pro', family: 'SF Pro', category: 'system', fallback: 'system-ui, -apple-system, sans-serif' },
|
|
147
|
+
{ name: 'SF Pro Display', family: 'SF Pro Display', category: 'system', fallback: 'system-ui, -apple-system, sans-serif' },
|
|
148
|
+
{ name: 'San Francisco', family: 'San Francisco', category: 'system', fallback: 'system-ui, -apple-system, sans-serif' },
|
|
149
|
+
{ name: 'New York', family: 'New York', category: 'system', fallback: 'Georgia, serif' },
|
|
150
|
+
{ name: 'Segoe UI', family: 'Segoe UI', category: 'system', fallback: 'system-ui, sans-serif' }
|
|
151
|
+
];
|
|
152
|
+
// Mark which fonts are actually installed
|
|
153
|
+
for (const font of fonts) {
|
|
154
|
+
font.installed = systemFontSet.has(font.name.toLowerCase());
|
|
155
|
+
}
|
|
156
|
+
return fonts;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Get basic recommended fonts (without async check) for backward compatibility
|
|
160
|
+
*/
|
|
161
|
+
getRecommendedFontsSync() {
|
|
162
|
+
return [
|
|
163
|
+
// Only return truly web-safe fonts that are almost always available
|
|
164
|
+
{ name: 'Helvetica', family: 'Helvetica', category: 'web-safe', fallback: 'Arial, sans-serif' },
|
|
165
|
+
{ name: 'Arial', family: 'Arial', category: 'web-safe', fallback: 'Helvetica, sans-serif' },
|
|
166
|
+
{ name: 'Georgia', family: 'Georgia', category: 'web-safe', fallback: 'Times New Roman, serif' },
|
|
167
|
+
{ name: 'Times New Roman', family: 'Times New Roman', category: 'web-safe', fallback: 'Georgia, serif' },
|
|
168
|
+
{ name: 'Courier New', family: 'Courier New', category: 'web-safe', fallback: 'monospace' },
|
|
169
|
+
{ name: 'Monaco', family: 'Monaco', category: 'web-safe', fallback: 'Courier New, monospace' },
|
|
170
|
+
{ name: 'Impact', family: 'Impact', category: 'web-safe', fallback: 'Arial Black, sans-serif' },
|
|
171
|
+
{ name: 'Arial Black', family: 'Arial Black', category: 'web-safe', fallback: 'Impact, sans-serif' }
|
|
172
|
+
];
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Get fonts organized by category with installation status
|
|
176
|
+
*/
|
|
177
|
+
async getFontCategories() {
|
|
178
|
+
const systemFonts = await this.getSystemFonts();
|
|
179
|
+
const recommendedFonts = await this.getRecommendedFonts();
|
|
180
|
+
// Create a set of recommended font names for quick lookup
|
|
181
|
+
const recommendedNames = new Set(recommendedFonts.map(f => f.name.toLowerCase()));
|
|
182
|
+
// Filter system fonts to exclude ones already in recommended
|
|
183
|
+
const additionalSystemFonts = systemFonts
|
|
184
|
+
.filter(font => !recommendedNames.has(font.toLowerCase()))
|
|
185
|
+
.slice(0, 20) // Limit to top 20 to avoid overwhelming the user
|
|
186
|
+
.map(name => ({
|
|
187
|
+
name,
|
|
188
|
+
category: 'system',
|
|
189
|
+
installed: true // These are from system fonts, so they're installed
|
|
190
|
+
}));
|
|
191
|
+
// Separate installed vs not installed
|
|
192
|
+
const installedWebSafe = recommendedFonts.filter(f => f.category === 'web-safe' && f.installed);
|
|
193
|
+
const installedRecommended = recommendedFonts.filter(f => f.category === 'recommended' && f.installed);
|
|
194
|
+
const notInstalledRecommended = recommendedFonts.filter(f => f.category === 'recommended' && !f.installed);
|
|
195
|
+
const categories = [
|
|
196
|
+
{
|
|
197
|
+
name: 'Installed Fonts (Web-Safe)',
|
|
198
|
+
fonts: installedWebSafe
|
|
199
|
+
}
|
|
200
|
+
];
|
|
201
|
+
if (installedRecommended.length > 0) {
|
|
202
|
+
categories.push({
|
|
203
|
+
name: 'Installed Fonts (Popular)',
|
|
204
|
+
fonts: installedRecommended
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
if (notInstalledRecommended.length > 0) {
|
|
208
|
+
categories.push({
|
|
209
|
+
name: 'Popular Fonts (Not Installed - Will Use Fallback)',
|
|
210
|
+
fonts: notInstalledRecommended
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
categories.push({
|
|
214
|
+
name: 'System Fonts',
|
|
215
|
+
fonts: [
|
|
216
|
+
...recommendedFonts.filter(f => f.category === 'system' && f.installed),
|
|
217
|
+
...additionalSystemFonts
|
|
218
|
+
]
|
|
219
|
+
});
|
|
220
|
+
return categories;
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Check if a font is actually installed on the system
|
|
224
|
+
* This is the TRUTH - only returns true if font can actually be used
|
|
225
|
+
*/
|
|
226
|
+
async isFontInstalled(fontName) {
|
|
227
|
+
const systemFonts = await this.getSystemFonts();
|
|
228
|
+
return systemFonts.some(f => f.toLowerCase() === fontName.toLowerCase());
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Validate if a font can be rendered
|
|
232
|
+
* NOW only checks if actually installed, not just "recommended"
|
|
233
|
+
*/
|
|
234
|
+
async validateFont(fontName) {
|
|
235
|
+
// Only return true if font is ACTUALLY installed
|
|
236
|
+
return this.isFontInstalled(fontName);
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Get detailed status about a font
|
|
240
|
+
*/
|
|
241
|
+
async getFontStatus(fontName) {
|
|
242
|
+
const installed = await this.isFontInstalled(fontName);
|
|
243
|
+
const recommended = await this.getRecommendedFonts();
|
|
244
|
+
const fontInfo = recommended.find(f => f.name.toLowerCase() === fontName.toLowerCase());
|
|
245
|
+
const status = {
|
|
246
|
+
name: fontName,
|
|
247
|
+
installed,
|
|
248
|
+
category: fontInfo?.category,
|
|
249
|
+
fallback: this.getFontFallback(fontName)
|
|
250
|
+
};
|
|
251
|
+
if (!installed) {
|
|
252
|
+
if (fontInfo?.category === 'recommended') {
|
|
253
|
+
status.warning = `Font "${fontName}" is not installed. Install it from Google Fonts or the fallback (${status.fallback}) will be used.`;
|
|
254
|
+
}
|
|
255
|
+
else if (fontInfo?.category === 'system') {
|
|
256
|
+
status.warning = `System font "${fontName}" is not available on this machine. The fallback (${status.fallback}) will be used.`;
|
|
257
|
+
}
|
|
258
|
+
else {
|
|
259
|
+
status.warning = `Font "${fontName}" is not installed on your system. The fallback (${status.fallback}) will be used.`;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
return status;
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Get a font's fallback chain (synchronous for backward compatibility)
|
|
266
|
+
*/
|
|
267
|
+
getFontFallback(fontName) {
|
|
268
|
+
// Use sync version for immediate fallback lookup
|
|
269
|
+
const recommended = this.getRecommendedFontsSync();
|
|
270
|
+
const font = recommended.find(f => f.name.toLowerCase() === fontName.toLowerCase());
|
|
271
|
+
if (font?.fallback) {
|
|
272
|
+
return font.fallback;
|
|
273
|
+
}
|
|
274
|
+
// Check extended list if not found in basic web-safe fonts
|
|
275
|
+
const extendedFonts = [
|
|
276
|
+
{ name: 'Roboto', fallback: 'Arial, sans-serif' },
|
|
277
|
+
{ name: 'Open Sans', fallback: 'Arial, sans-serif' },
|
|
278
|
+
{ name: 'Montserrat', fallback: 'Arial, sans-serif' },
|
|
279
|
+
{ name: 'Lato', fallback: 'Arial, sans-serif' },
|
|
280
|
+
{ name: 'Poppins', fallback: 'Arial, sans-serif' },
|
|
281
|
+
{ name: 'Inter', fallback: 'Arial, sans-serif' },
|
|
282
|
+
{ name: 'Playfair Display', fallback: 'Georgia, serif' },
|
|
283
|
+
{ name: 'Merriweather', fallback: 'Georgia, serif' },
|
|
284
|
+
{ name: 'SF Pro', fallback: 'system-ui, -apple-system, sans-serif' },
|
|
285
|
+
{ name: 'SF Pro Display', fallback: 'system-ui, -apple-system, sans-serif' },
|
|
286
|
+
{ name: 'San Francisco', fallback: 'system-ui, -apple-system, sans-serif' },
|
|
287
|
+
{ name: 'New York', fallback: 'Georgia, serif' },
|
|
288
|
+
{ name: 'Segoe UI', fallback: 'system-ui, sans-serif' }
|
|
289
|
+
];
|
|
290
|
+
const extendedFont = extendedFonts.find(f => f.name.toLowerCase() === fontName.toLowerCase());
|
|
291
|
+
if (extendedFont) {
|
|
292
|
+
return extendedFont.fallback;
|
|
293
|
+
}
|
|
294
|
+
// Default fallback based on font characteristics
|
|
295
|
+
const lowerFont = fontName.toLowerCase();
|
|
296
|
+
if (lowerFont.includes('serif') && !lowerFont.includes('sans')) {
|
|
297
|
+
// Serif font
|
|
298
|
+
return 'Georgia, Times New Roman, serif';
|
|
299
|
+
}
|
|
300
|
+
else if (lowerFont.includes('mono') || lowerFont.includes('code') || lowerFont.includes('console')) {
|
|
301
|
+
// Monospace font
|
|
302
|
+
return 'Courier New, Monaco, monospace';
|
|
303
|
+
}
|
|
304
|
+
else if (lowerFont.includes('display') || lowerFont.includes('headline')) {
|
|
305
|
+
// Display font
|
|
306
|
+
return 'Impact, Arial Black, sans-serif';
|
|
307
|
+
}
|
|
308
|
+
else {
|
|
309
|
+
// Default to sans-serif
|
|
310
|
+
return 'Arial, Helvetica, sans-serif';
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
//# sourceMappingURL=fonts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fonts.js","sourceRoot":"","sources":["../../src/services/fonts.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { OpenAIModel, ModelConfig, TranslationOptions, TranslationResult, AIConfig } from '../types/ai.js';
|
|
2
|
+
export declare class TranslationService {
|
|
3
|
+
private client;
|
|
4
|
+
private config;
|
|
5
|
+
constructor();
|
|
6
|
+
private initialize;
|
|
7
|
+
hasApiKey(): boolean;
|
|
8
|
+
loadConfig(): Promise<void>;
|
|
9
|
+
saveConfig(config: Partial<AIConfig>): Promise<void>;
|
|
10
|
+
private getCacheKey;
|
|
11
|
+
translate(options: TranslationOptions): Promise<TranslationResult>;
|
|
12
|
+
translateBatch(captions: string[], targetLanguages: string[], model?: OpenAIModel, onProgress?: (current: number, total: number) => void): Promise<Map<string, TranslationResult>>;
|
|
13
|
+
getAvailableModels(): OpenAIModel[];
|
|
14
|
+
getModelInfo(model: OpenAIModel): ModelConfig | undefined;
|
|
15
|
+
clearCache(): void;
|
|
16
|
+
}
|
|
17
|
+
export declare const translationService: TranslationService;
|
|
18
|
+
//# sourceMappingURL=translation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"translation.d.ts","sourceRoot":"","sources":["../../src/services/translation.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,WAAW,EACX,WAAW,EACX,kBAAkB,EAClB,iBAAiB,EACjB,QAAQ,EACT,MAAM,gBAAgB,CAAC;AAMxB,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,MAAM,CAAW;;IAYzB,OAAO,CAAC,UAAU;IAQX,SAAS,IAAI,OAAO;IAId,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAW3B,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAQjE,OAAO,CAAC,WAAW;IAIN,SAAS,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,iBAAiB,CAAC;IA8HlE,cAAc,CACzB,QAAQ,EAAE,MAAM,EAAE,EAClB,eAAe,EAAE,MAAM,EAAE,EACzB,KAAK,CAAC,EAAE,WAAW,EACnB,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,GACpD,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;IA+BnC,kBAAkB,IAAI,WAAW,EAAE;IAInC,YAAY,CAAC,KAAK,EAAE,WAAW,GAAG,WAAW,GAAG,SAAS;IAIzD,UAAU,IAAI,IAAI;CAG1B;AAGD,eAAO,MAAM,kBAAkB,oBAA2B,CAAC"}
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import OpenAI from 'openai';
|
|
2
|
+
import { promises as fs } from 'fs';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import pc from 'picocolors';
|
|
5
|
+
import { MODEL_CONFIGS } from '../types/ai.js';
|
|
6
|
+
// Cache for translations to avoid duplicate API calls
|
|
7
|
+
const translationCache = new Map();
|
|
8
|
+
export class TranslationService {
|
|
9
|
+
client = null;
|
|
10
|
+
config;
|
|
11
|
+
constructor() {
|
|
12
|
+
this.config = {
|
|
13
|
+
defaultModel: 'gpt-4o-mini',
|
|
14
|
+
temperature: 0.3,
|
|
15
|
+
cache: true
|
|
16
|
+
};
|
|
17
|
+
this.initialize();
|
|
18
|
+
}
|
|
19
|
+
initialize() {
|
|
20
|
+
const apiKey = process.env.OPENAI_API_KEY;
|
|
21
|
+
if (apiKey) {
|
|
22
|
+
this.client = new OpenAI({ apiKey });
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
hasApiKey() {
|
|
26
|
+
return !!process.env.OPENAI_API_KEY;
|
|
27
|
+
}
|
|
28
|
+
async loadConfig() {
|
|
29
|
+
try {
|
|
30
|
+
const configPath = path.join(process.cwd(), '.appshot', 'ai-config.json');
|
|
31
|
+
const content = await fs.readFile(configPath, 'utf8');
|
|
32
|
+
const loadedConfig = JSON.parse(content);
|
|
33
|
+
this.config = { ...this.config, ...loadedConfig };
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
// Config file doesn't exist, use defaults
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
async saveConfig(config) {
|
|
40
|
+
const configPath = path.join(process.cwd(), '.appshot', 'ai-config.json');
|
|
41
|
+
this.config = { ...this.config, ...config };
|
|
42
|
+
await fs.mkdir(path.dirname(configPath), { recursive: true });
|
|
43
|
+
await fs.writeFile(configPath, JSON.stringify(this.config, null, 2), 'utf8');
|
|
44
|
+
}
|
|
45
|
+
getCacheKey(text, languages, model) {
|
|
46
|
+
return `${model}:${languages.sort().join(',')}:${text}`;
|
|
47
|
+
}
|
|
48
|
+
async translate(options) {
|
|
49
|
+
if (!this.client) {
|
|
50
|
+
throw new Error('OpenAI API key not found. Set OPENAI_API_KEY environment variable.');
|
|
51
|
+
}
|
|
52
|
+
const model = options.model || this.config.defaultModel;
|
|
53
|
+
const modelConfig = MODEL_CONFIGS[model];
|
|
54
|
+
if (!modelConfig) {
|
|
55
|
+
throw new Error(`Unknown model: ${model}`);
|
|
56
|
+
}
|
|
57
|
+
// Check cache
|
|
58
|
+
if (this.config.cache) {
|
|
59
|
+
const cacheKey = this.getCacheKey(options.text, options.targetLanguages, model);
|
|
60
|
+
const cached = translationCache.get(cacheKey);
|
|
61
|
+
if (cached) {
|
|
62
|
+
return cached;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
// Build language map for the prompt
|
|
66
|
+
const languageNames = {
|
|
67
|
+
'es': 'Spanish',
|
|
68
|
+
'fr': 'French',
|
|
69
|
+
'de': 'German',
|
|
70
|
+
'it': 'Italian',
|
|
71
|
+
'pt': 'Portuguese',
|
|
72
|
+
'pt-BR': 'Brazilian Portuguese',
|
|
73
|
+
'ru': 'Russian',
|
|
74
|
+
'ja': 'Japanese',
|
|
75
|
+
'ko': 'Korean',
|
|
76
|
+
'zh-CN': 'Simplified Chinese',
|
|
77
|
+
'zh-TW': 'Traditional Chinese',
|
|
78
|
+
'ar': 'Arabic',
|
|
79
|
+
'hi': 'Hindi',
|
|
80
|
+
'nl': 'Dutch',
|
|
81
|
+
'sv': 'Swedish',
|
|
82
|
+
'no': 'Norwegian',
|
|
83
|
+
'da': 'Danish',
|
|
84
|
+
'fi': 'Finnish',
|
|
85
|
+
'pl': 'Polish',
|
|
86
|
+
'tr': 'Turkish',
|
|
87
|
+
'th': 'Thai',
|
|
88
|
+
'vi': 'Vietnamese',
|
|
89
|
+
'id': 'Indonesian',
|
|
90
|
+
'ms': 'Malay',
|
|
91
|
+
'he': 'Hebrew'
|
|
92
|
+
};
|
|
93
|
+
const targetLangs = options.targetLanguages
|
|
94
|
+
.map(code => `${code}: ${languageNames[code] || code}`)
|
|
95
|
+
.join(', ');
|
|
96
|
+
const systemPrompt = options.systemPrompt || this.config.systemPrompt ||
|
|
97
|
+
`You are a professional app localization expert. Translate the given app screenshot caption into the requested languages.
|
|
98
|
+
The captions are marketing text for mobile app screenshots.
|
|
99
|
+
Keep translations concise, impactful, and culturally appropriate.
|
|
100
|
+
Maintain the marketing tone and appeal of the original text.`;
|
|
101
|
+
const userPrompt = `Translate this app screenshot caption into the following languages: ${targetLangs}
|
|
102
|
+
|
|
103
|
+
Caption: "${options.text}"
|
|
104
|
+
|
|
105
|
+
Return ONLY a JSON object with language codes as keys and translations as values. Example:
|
|
106
|
+
{
|
|
107
|
+
"es": "Spanish translation here",
|
|
108
|
+
"fr": "French translation here"
|
|
109
|
+
}`;
|
|
110
|
+
try {
|
|
111
|
+
// Build the request parameters based on model type
|
|
112
|
+
const params = {
|
|
113
|
+
model: modelConfig.model,
|
|
114
|
+
messages: [
|
|
115
|
+
{ role: 'system', content: systemPrompt },
|
|
116
|
+
{ role: 'user', content: userPrompt }
|
|
117
|
+
],
|
|
118
|
+
temperature: modelConfig.temperature,
|
|
119
|
+
response_format: { type: 'json_object' }
|
|
120
|
+
};
|
|
121
|
+
// Use the appropriate max tokens parameter based on model
|
|
122
|
+
if (modelConfig.maxTokensParam === 'max_completion_tokens') {
|
|
123
|
+
params.max_completion_tokens = Math.min(modelConfig.maxTokens, 2000); // Limit for translations
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
params.max_tokens = Math.min(modelConfig.maxTokens, 2000);
|
|
127
|
+
}
|
|
128
|
+
const response = await this.client.chat.completions.create(params);
|
|
129
|
+
const content = response.choices[0]?.message?.content;
|
|
130
|
+
if (!content) {
|
|
131
|
+
throw new Error('No response from OpenAI');
|
|
132
|
+
}
|
|
133
|
+
const translations = JSON.parse(content);
|
|
134
|
+
// Validate that we got all requested languages
|
|
135
|
+
for (const lang of options.targetLanguages) {
|
|
136
|
+
if (!translations[lang]) {
|
|
137
|
+
console.warn(pc.yellow(`Warning: Translation for ${lang} not returned by API`));
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
// Cache the result
|
|
141
|
+
if (this.config.cache) {
|
|
142
|
+
const cacheKey = this.getCacheKey(options.text, options.targetLanguages, model);
|
|
143
|
+
translationCache.set(cacheKey, translations);
|
|
144
|
+
}
|
|
145
|
+
return translations;
|
|
146
|
+
}
|
|
147
|
+
catch (error) {
|
|
148
|
+
if (error instanceof OpenAI.APIError) {
|
|
149
|
+
if (error.status === 401) {
|
|
150
|
+
throw new Error('Invalid OpenAI API key');
|
|
151
|
+
}
|
|
152
|
+
else if (error.status === 429) {
|
|
153
|
+
throw new Error('OpenAI API rate limit exceeded. Please try again later.');
|
|
154
|
+
}
|
|
155
|
+
else if (error.status === 404) {
|
|
156
|
+
throw new Error(`Model ${model} not found. You may not have access to this model.`);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
throw error;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
async translateBatch(captions, targetLanguages, model, onProgress) {
|
|
163
|
+
const results = new Map();
|
|
164
|
+
const total = captions.length;
|
|
165
|
+
for (let i = 0; i < captions.length; i++) {
|
|
166
|
+
if (onProgress) {
|
|
167
|
+
onProgress(i + 1, total);
|
|
168
|
+
}
|
|
169
|
+
try {
|
|
170
|
+
const translations = await this.translate({
|
|
171
|
+
text: captions[i],
|
|
172
|
+
targetLanguages,
|
|
173
|
+
model
|
|
174
|
+
});
|
|
175
|
+
results.set(captions[i], translations);
|
|
176
|
+
}
|
|
177
|
+
catch (error) {
|
|
178
|
+
console.error(pc.red(`Failed to translate: "${captions[i]}"`));
|
|
179
|
+
console.error(pc.dim(error instanceof Error ? error.message : String(error)));
|
|
180
|
+
// Continue with other translations
|
|
181
|
+
}
|
|
182
|
+
// Add a small delay to avoid rate limits
|
|
183
|
+
if (i < captions.length - 1) {
|
|
184
|
+
await new Promise(resolve => setTimeout(resolve, 200));
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
return results;
|
|
188
|
+
}
|
|
189
|
+
getAvailableModels() {
|
|
190
|
+
return Object.keys(MODEL_CONFIGS);
|
|
191
|
+
}
|
|
192
|
+
getModelInfo(model) {
|
|
193
|
+
return MODEL_CONFIGS[model];
|
|
194
|
+
}
|
|
195
|
+
clearCache() {
|
|
196
|
+
translationCache.clear();
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
// Singleton instance
|
|
200
|
+
export const translationService = new TranslationService();
|
|
201
|
+
//# sourceMappingURL=translation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"translation.js","sourceRoot":"","sources":["../../src/services/translation.ts"],"names":[],"mappings":"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"}
|