mirror of
https://github.com/ksyasuda/dotfiles.git
synced 2026-03-21 18:11:27 -07:00
update skills
This commit is contained in:
115
.agents/skills/cloudflare-deploy/references/images/patterns.md
Normal file
115
.agents/skills/cloudflare-deploy/references/images/patterns.md
Normal file
@@ -0,0 +1,115 @@
|
||||
# Common Patterns
|
||||
|
||||
## URL Transform Options
|
||||
|
||||
```
|
||||
width=<PX> height=<PX> fit=scale-down|contain|cover|crop|pad
|
||||
quality=85 format=auto|webp|avif|jpeg|png dpr=2
|
||||
gravity=auto|face|left|right|top|bottom sharpen=2 blur=10
|
||||
rotate=90|180|270 background=white metadata=none|copyright|keep
|
||||
```
|
||||
|
||||
## Responsive Images (srcset)
|
||||
|
||||
```html
|
||||
<img src="https://imagedelivery.net/{hash}/{id}/width=800"
|
||||
srcset=".../{id}/width=400 400w, .../{id}/width=800 800w, .../{id}/width=1200 1200w"
|
||||
sizes="(max-width: 600px) 400px, 800px" />
|
||||
```
|
||||
|
||||
## Format Negotiation
|
||||
|
||||
```typescript
|
||||
async fetch(request: Request, env: Env): Promise<Response> {
|
||||
const accept = request.headers.get('Accept') || '';
|
||||
const format = /image\/avif/.test(accept) ? 'avif' : /image\/webp/.test(accept) ? 'webp' : 'jpeg';
|
||||
return env.IMAGES.input(buffer).transform({ format, quality: 85 }).output().response();
|
||||
}
|
||||
```
|
||||
|
||||
## Direct Creator Upload
|
||||
|
||||
```typescript
|
||||
// Backend: Generate upload URL
|
||||
const response = await fetch(
|
||||
`https://api.cloudflare.com/client/v4/accounts/${env.ACCOUNT_ID}/images/v2/direct_upload`,
|
||||
{ method: 'POST', headers: { 'Authorization': `Bearer ${env.API_TOKEN}` },
|
||||
body: JSON.stringify({ requireSignedURLs: false, metadata: { userId } }) }
|
||||
);
|
||||
|
||||
// Frontend: Upload to returned uploadURL
|
||||
const formData = new FormData();
|
||||
formData.append('file', file);
|
||||
await fetch(result.uploadURL, { method: 'POST', body: formData });
|
||||
// Use: https://imagedelivery.net/{hash}/${result.id}/public
|
||||
```
|
||||
|
||||
## Transform & Store to R2
|
||||
|
||||
```typescript
|
||||
async fetch(request: Request, env: Env): Promise<Response> {
|
||||
const file = (await request.formData()).get('image') as File;
|
||||
const transformed = await env.IMAGES
|
||||
.input(await file.arrayBuffer())
|
||||
.transform({ width: 800, format: 'avif', quality: 80 })
|
||||
.output();
|
||||
await env.R2.put(`images/${Date.now()}.avif`, transformed.response().body);
|
||||
return Response.json({ success: true });
|
||||
}
|
||||
```
|
||||
|
||||
## Watermarking
|
||||
|
||||
```typescript
|
||||
const watermark = await env.ASSETS.fetch(new URL('/watermark.png', request.url));
|
||||
const result = await env.IMAGES
|
||||
.input(await image.arrayBuffer())
|
||||
.draw(env.IMAGES.input(watermark.body).transform({ width: 100 }), { bottom: 20, right: 20, opacity: 0.7 })
|
||||
.transform({ format: 'avif' })
|
||||
.output();
|
||||
return result.response();
|
||||
```
|
||||
|
||||
## Device-Based Transforms
|
||||
|
||||
```typescript
|
||||
const ua = request.headers.get('User-Agent') || '';
|
||||
const isMobile = /Mobile|Android|iPhone/i.test(ua);
|
||||
return env.IMAGES.input(buffer)
|
||||
.transform({ width: isMobile ? 400 : 1200, quality: isMobile ? 75 : 85, format: 'avif' })
|
||||
.output().response();
|
||||
```
|
||||
|
||||
## Caching Strategy
|
||||
|
||||
```typescript
|
||||
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
|
||||
const cache = caches.default;
|
||||
let response = await cache.match(request);
|
||||
if (!response) {
|
||||
response = await env.IMAGES.input(buffer).transform({ width: 800, format: 'avif' }).output().response();
|
||||
response = new Response(response.body, { headers: { ...response.headers, 'Cache-Control': 'public, max-age=86400' } });
|
||||
ctx.waitUntil(cache.put(request, response.clone()));
|
||||
}
|
||||
return response;
|
||||
}
|
||||
```
|
||||
|
||||
## Batch Processing
|
||||
|
||||
```typescript
|
||||
const results = await Promise.all(images.map(buffer =>
|
||||
env.IMAGES.input(buffer).transform({ width: 800, fit: 'cover', format: 'avif' }).output()
|
||||
));
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
```typescript
|
||||
try {
|
||||
return (await env.IMAGES.input(buffer).transform({ width: 800 }).output()).response();
|
||||
} catch (error) {
|
||||
console.error('Transform failed:', error);
|
||||
return new Response('Image processing failed', { status: 500 });
|
||||
}
|
||||
```
|
||||
Reference in New Issue
Block a user