Skip to content

Commit 68b366b

Browse files
committed
chore: wip
1 parent b4d36f7 commit 68b366b

35 files changed

+1495
-2627
lines changed

README.md

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ For casual chit-chat with others using this package:
216216

217217
## Postcardware
218218

219-
Software that is free, but hopes for a postcard. We love receiving postcards from around the world showing where `imgx` is being used! We showcase them on our website too.
219+
"Software that is free, but hopes for a postcard." We love receiving postcards from around the world showing where `imgx` is being used! We showcase them on our website too.
220220

221221
Our address: Stacks.js, 12665 Village Ln #2306, Playa Vista, CA 90094, United States 🌎
222222

@@ -238,6 +238,68 @@ The MIT License (MIT). Please see [LICENSE](LICENSE.md) for more information.
238238

239239
Made with 💙
240240

241+
## App Icon Generation
242+
243+
You can now use imgx to generate properly sized app icons for macOS and iOS applications from a single source image.
244+
245+
### Command Line Usage
246+
247+
```bash
248+
# Generate app icons for all platforms (macOS and iOS)
249+
imgx app-icon source-icon.png
250+
251+
# Generate only macOS app icons
252+
imgx app-icon source-icon.png -p macos
253+
254+
# Generate only iOS app icons
255+
imgx app-icon source-icon.png -p ios
256+
257+
# Specify a custom output directory
258+
imgx app-icon source-icon.png -o ./my-app/assets
259+
```
260+
261+
### Programmatic Usage
262+
263+
```typescript
264+
import { generateAppIcons } from 'imgx'
265+
266+
// Generate app icons for all platforms
267+
await generateAppIcons('path/to/source-icon.png')
268+
269+
// Generate only macOS app icons
270+
await generateAppIcons('path/to/source-icon.png', {
271+
platform: 'macos',
272+
outputDir: './my-app/assets'
273+
})
274+
```
275+
276+
### Configuration
277+
278+
You can configure the app icon generation in your `imgx.config.ts` file:
279+
280+
```typescript
281+
import type { ImgxConfig } from 'imgx'
282+
283+
const config: ImgxConfig = {
284+
// Other configuration options...
285+
286+
appIcon: {
287+
outputDir: 'assets/app-icons', // Default output directory
288+
platform: 'all', // Default platform target ('macos', 'ios', or 'all')
289+
},
290+
}
291+
292+
export default config
293+
```
294+
295+
### Output
296+
297+
The tool will generate:
298+
299+
1. All required app icon sizes for the selected platform(s)
300+
2. A properly formatted `Contents.json` file for Xcode
301+
3. A README.md with installation instructions
302+
241303
<!-- Badges -->
242304
[npm-version-src]: https://img.shields.io/npm/v/@stacksjs/imgx?style=flat-square
243305
[npm-version-href]: https://npmjs.com/package/@stacksjs/imgx

bun.lock

Lines changed: 0 additions & 2326 deletions
This file was deleted.

imgx.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { ProxyOptions } from './src/types'
1+
import type { ProxyOptions } from './packages/imgx/src/types'
22

33
const config: ProxyOptions = {
44
https: true,

package.json

Lines changed: 13 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
{
2-
"name": "@stacksjs/imgx",
2+
"name": "imgx",
33
"type": "module",
44
"version": "0.0.0",
5+
"private": true,
56
"description": "Modern image optimizations & manipulations.",
67
"author": "Chris Breuer <chris@stacksjs.org>",
78
"license": "MIT",
@@ -28,17 +29,6 @@
2829
"typescript",
2930
"javascript"
3031
],
31-
"exports": {
32-
".": {
33-
"import": "./dist/src/index.js"
34-
}
35-
},
36-
"module": "./dist/src/index.js",
37-
"types": "./dist/index.d.ts",
38-
"bin": {
39-
"imgx": "./dist/bin/cli.js"
40-
},
41-
"files": ["README.md", "dist"],
4232
"scripts": {
4333
"build": "bun build.ts && bun run compile",
4434
"compile": "bun build ./bin/cli.ts --compile --minify --outfile bin/imgx",
@@ -67,22 +57,13 @@
6757
"zip:darwin-x64": "zip -j bin/imgx-darwin-x64.zip bin/imgx-darwin-x64"
6858
},
6959
"devDependencies": {
70-
"@stacksjs/docs": "^0.69.3",
71-
"@stacksjs/eslint-config": "^3.13.1-beta.2",
72-
"@stacksjs/tlsx": "^0.10.0",
73-
"@types/bun": "^1.2.5",
74-
"bumpp": "^10.1.0",
75-
"bun-plugin-dtsx": "^0.21.9",
76-
"bunfig": "^0.8.2",
77-
"cac": "^6.7.14",
78-
"changelogen": "^0.6.1",
79-
"consola": "^3.4.2",
80-
"image-size": "^2.0.1",
81-
"sharp": "^0.33.5",
82-
"svgo": "^3.3.2",
83-
"typescript": "^5.8.2",
84-
"unocss": "^66.0.0",
85-
"webpack": "^5.98.0"
60+
"@stacksjs/docs": "^0.70.23",
61+
"@stacksjs/eslint-config": "^4.10.2-beta.3",
62+
"@types/bun": "^1.2.2",
63+
"bumpp": "^10.0.3",
64+
"changelogen": "^0.5.7",
65+
"typescript": "^5.7.3",
66+
"unocss": "^66.1.1"
8667
},
8768
"overrides": {
8869
"unconfig": "0.3.10"
@@ -92,5 +73,8 @@
9273
},
9374
"lint-staged": {
9475
"*.{js,ts}": "bunx eslint . --fix"
95-
}
76+
},
77+
"workspaces": [
78+
"packages/*"
79+
]
9680
}

packages/bun-plugin/package.json

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
{
2+
"name": "imgx",
3+
"type": "module",
4+
"version": "0.0.0",
5+
"private": true,
6+
"description": "Modern image optimizations & manipulations.",
7+
"author": "Chris Breuer <chris@stacksjs.org>",
8+
"license": "MIT",
9+
"homepage": "https://github.com/stacksjs/imgx",
10+
"repository": {
11+
"type": "git",
12+
"url": "git+https://github.com/stacksjs/imgx.git"
13+
},
14+
"bugs": {
15+
"url": "https://github.com/stacksjs/imgx/issues"
16+
},
17+
"keywords": [
18+
"image",
19+
"manipulation",
20+
"compression",
21+
"web optimization",
22+
"jpg",
23+
"png",
24+
"avif",
25+
"webp",
26+
"sharp",
27+
"bun",
28+
"stacks",
29+
"typescript",
30+
"javascript"
31+
],
32+
"exports": {
33+
".": {
34+
"import": "./dist/src/index.js"
35+
}
36+
},
37+
"module": "./dist/src/index.js",
38+
"types": "./dist/index.d.ts",
39+
"bin": {
40+
"imgx": "./dist/bin/cli.js"
41+
},
42+
"files": ["README.md", "dist"],
43+
"scripts": {
44+
"build": "bun build.ts && bun run compile",
45+
"compile": "bun build ./bin/cli.ts --compile --minify --outfile bin/imgx",
46+
"compile:all": "bun run compile:linux-x64 && bun run compile:linux-arm64 && bun run compile:windows-x64 && bun run compile:darwin-x64 && bun run compile:darwin-arm64",
47+
"compile:linux-x64": "bun build ./bin/cli.ts --compile --minify --target=bun-linux-x64 --outfile bin/imgx-linux-x64",
48+
"compile:linux-arm64": "bun build ./bin/cli.ts --compile --minify --target=bun-linux-arm64 --outfile bin/imgx-linux-arm64",
49+
"compile:windows-x64": "bun build ./bin/cli.ts --compile --minify --target=bun-windows-x64 --outfile bin/imgx-windows-x64.exe",
50+
"compile:darwin-x64": "bun build ./bin/cli.ts --compile --minify --target=bun-darwin-x64 --outfile bin/imgx-darwin-x64",
51+
"compile:darwin-arm64": "bun build ./bin/cli.ts --compile --minify --target=bun-darwin-arm64 --outfile bin/imgx-darwin-arm64",
52+
"lint": "bunx --bun eslint .",
53+
"lint:fix": "bunx --bun eslint . --fix",
54+
"fresh": "bunx rimraf node_modules/ bun.lock && bun i",
55+
"changelog": "bunx changelogen --output CHANGELOG.md",
56+
"prepublishOnly": "bun --bun run build && bun run compile:all",
57+
"release": "bun run changelog && bunx bumpp package.json --all",
58+
"test": "bun test",
59+
"typecheck": "bunx tsc --noEmit",
60+
"dev:docs": "bun --bun vitepress dev docs",
61+
"build:docs": "bun --bun vitepress build docs",
62+
"preview:docs": "bun --bun vitepress preview docs"
63+
},
64+
"devDependencies": {
65+
"@stacksjs/docs": "^0.69.3",
66+
"@stacksjs/eslint-config": "^3.13.1-beta.2",
67+
"@stacksjs/tlsx": "^0.10.0",
68+
"@types/bun": "^1.2.2",
69+
"bumpp": "^10.0.3",
70+
"bun-plugin-dtsx": "^0.21.9",
71+
"bunfig": "^0.5.3",
72+
"cac": "^6.7.14",
73+
"changelogen": "^0.5.7",
74+
"consola": "^3.4.0",
75+
"image-size": "^1.2.0",
76+
"sharp": "^0.33.5",
77+
"svgo": "^3.3.2",
78+
"typescript": "^5.7.3",
79+
"unocss": "^65.4.3",
80+
"webpack": "^5.97.1"
81+
},
82+
"overrides": {
83+
"unconfig": "0.3.10"
84+
},
85+
"simple-git-hooks": {
86+
"pre-commit": "bunx lint-staged"
87+
},
88+
"lint-staged": {
89+
"*.{js,ts}": "bunx eslint . --fix"
90+
}
91+
}

packages/bun-plugin/src/index.ts

Whitespace-only changes.

packages/bun-plugin/tsconfig.json

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"compilerOptions": {
3+
"target": "esnext",
4+
"lib": ["esnext"],
5+
"moduleDetection": "force",
6+
"module": "esnext",
7+
"moduleResolution": "bundler",
8+
"resolveJsonModule": true,
9+
"allowImportingTsExtensions": true,
10+
"strict": true,
11+
"strictNullChecks": true,
12+
"noFallthroughCasesInSwitch": true,
13+
"declaration": true,
14+
"noEmit": true,
15+
"outDir": "./dist",
16+
"esModuleInterop": true,
17+
"forceConsistentCasingInFileNames": true,
18+
"isolatedDeclarations": true,
19+
"verbatimModuleSyntax": true,
20+
"skipDefaultLibCheck": true,
21+
"skipLibCheck": true
22+
}
23+
}

bin/cli.ts renamed to packages/imgx/bin/cli.ts

Lines changed: 101 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,75 @@
11
import type { ImgxOptions, ProcessOptions } from '../src/types'
22
import { Buffer } from 'node:buffer'
3-
import { writeFile } from 'node:fs/promises'
4-
import { join } from 'node:path'
3+
import { copyFile, stat, writeFile } from 'node:fs/promises'
4+
import { join, resolve } from 'node:path'
55
import proc from 'node:process'
66
import { CAC } from 'cac'
77
import { version } from '../package.json'
88
import { formatReport, generateReport } from '../src/analyze'
9+
import { generateAppIcons } from '../src/app-icon'
910
import { process } from '../src/core'
1011
import { generateSprite } from '../src/sprite-generator'
1112
import { generateThumbHash } from '../src/thumbhash'
1213
import { debugLog, formatBytes, getFiles } from '../src/utils'
1314

15+
// Helper function to parse file size strings like "5MB" or "500KB"
16+
function parseFileSize(sizeStr: string): number {
17+
const units = {
18+
b: 1,
19+
kb: 1024,
20+
mb: 1024 * 1024,
21+
gb: 1024 * 1024 * 1024,
22+
}
23+
24+
const match = sizeStr.match(/^(\d+(?:\.\d+)?)\s*([a-z]+)$/i)
25+
if (!match)
26+
return Number.parseInt(sizeStr, 10) || 0
27+
28+
const size = Number.parseFloat(match[1])
29+
const unit = match[2].toLowerCase()
30+
31+
return size * (units[unit] || 1)
32+
}
33+
34+
// Helper function to format a report
35+
function formatReport(report: any): string {
36+
const { stats, summary } = report
37+
38+
let output = `
39+
Image Analysis Report
40+
=====================
41+
42+
Summary:
43+
- Total images: ${summary.totalImages}
44+
- Total size: ${formatBytes(summary.totalSize)}
45+
- Average size: ${formatBytes(summary.averageSize)}
46+
- Potential savings: ${summary.potentialSavings}
47+
48+
Format breakdown:
49+
${Object.entries(summary.formatBreakdown)
50+
.map(([format, count]) => `- ${format}: ${count}`)
51+
.join('\n')}
52+
53+
Warnings:
54+
${summary.warnings.length ? summary.warnings.map(w => `- ${w}`).join('\n') : '- None'}
55+
56+
Details:
57+
`
58+
59+
for (const stat of stats) {
60+
output += `
61+
${stat.path}
62+
Size: ${formatBytes(stat.size)}
63+
Format: ${stat.format}
64+
Dimensions: ${stat.width}x${stat.height}
65+
Optimization potential: ${stat.optimizationPotential}
66+
${stat.warnings.length ? `Warnings:\n${stat.warnings.map(w => `- ${w}`).join('\n')}` : ''}
67+
`
68+
}
69+
70+
return output
71+
}
72+
1473
const cli = new CAC('imgx')
1574

1675
cli
@@ -432,6 +491,46 @@ cli
432491
console.log('Shell completion not implemented yet')
433492
})
434493

494+
cli
495+
.command('app-icon <input>', 'Generate app icons for macOS and iOS')
496+
.alias('icon')
497+
.option('-o, --output-dir <dir>', 'Output directory for app icons', { default: 'assets/app-icons' })
498+
.option('-p, --platform <platform>', 'Target platform (macos, ios, all)', { default: 'all' })
499+
.option('-v, --verbose', 'Enable verbose logging')
500+
.example('imgx app-icon app-icon.png')
501+
.example('imgx app-icon logo.png -o ./src/assets -p macos')
502+
.action(async (input: string, options?: { outputDir?: string, platform?: 'macos' | 'ios' | 'all', verbose?: boolean }) => {
503+
if (!input) {
504+
cli.outputHelp()
505+
return
506+
}
507+
508+
try {
509+
const results = await generateAppIcons(input, {
510+
outputDir: options.outputDir,
511+
platform: options.platform,
512+
})
513+
514+
console.log(`Generated app icons for ${results.map(r => r.platform).join(', ')}:`)
515+
516+
for (const result of results) {
517+
console.log(`\n${result.platform.toUpperCase()}:`)
518+
console.log(`- Output directory: ${options.outputDir}/AppIcon.appiconset`)
519+
console.log(`- Generated ${result.sizes.length} icon sizes`)
520+
521+
if (options.verbose) {
522+
for (const size of result.sizes) {
523+
console.log(` - ${size.filename} (${size.size}x${size.size}px)`)
524+
}
525+
}
526+
}
527+
}
528+
catch (error) {
529+
console.error(`Error generating app icons: ${error.message}`)
530+
proc.exit(1)
531+
}
532+
})
533+
435534
cli.version(version)
436535
cli.help()
437536
cli.parse()

packages/imgx/imgx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#!/usr/bin/env bun
2+
import('./bin/cli')

0 commit comments

Comments
 (0)