datocms-plugin-asset-optimization 0.7.8 → 0.7.9
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 +41 -5
- package/dist/assets/{assetReplacer-B50CwPJj.js → assetReplacer-DhwFMV6v.js} +1 -1
- package/dist/assets/{index-CV8dvyAg.js → index-PtBA-34N.js} +11 -11
- package/dist/assets/index-zYoXliGp.css +1 -0
- package/dist/index.html +2 -2
- package/package.json +3 -3
- package/dist/assets/index-QKXhJ4Sk.css +0 -1
package/README.md
CHANGED
|
@@ -14,6 +14,13 @@ The DatoCMS Asset Optimization Plugin leverages Imgix's powerful image processin
|
|
|
14
14
|
- Convert images to modern formats like AVIF or WebP
|
|
15
15
|
- Track optimization progress with detailed logs
|
|
16
16
|
- View statistics on storage savings
|
|
17
|
+
- Preview the impact of your settings before replacing anything
|
|
18
|
+
|
|
19
|
+
## Where it lives in DatoCMS
|
|
20
|
+
|
|
21
|
+
After installation, the plugin adds an **Asset Management → Optimize assets** entry in your environment's **Configuration** section. The plugin's configuration screen also provides a shortcut button to that page.
|
|
22
|
+
|
|
23
|
+
The plugin requires the `currentUserAccessToken` permission so it can replace assets on your behalf.
|
|
17
24
|
|
|
18
25
|
## Installation
|
|
19
26
|
|
|
@@ -21,7 +28,6 @@ The DatoCMS Asset Optimization Plugin leverages Imgix's powerful image processin
|
|
|
21
28
|
2. Go to Settings > Plugins
|
|
22
29
|
3. Search for "Asset Optimization"
|
|
23
30
|
4. Click "Install"
|
|
24
|
-
5. Configure the plugin settings as desired
|
|
25
31
|
|
|
26
32
|
## Important: Use Sandbox Environments First
|
|
27
33
|
|
|
@@ -39,11 +45,40 @@ This approach allows you to safely experiment with different optimization parame
|
|
|
39
45
|
|
|
40
46
|
## Usage
|
|
41
47
|
|
|
42
|
-
1.
|
|
48
|
+
1. Open **Configuration → Optimize assets**.
|
|
43
49
|
2. Configure the optimization settings according to your needs
|
|
44
|
-
3. Click
|
|
45
|
-
4.
|
|
46
|
-
5.
|
|
50
|
+
3. Click **Preview Optimization** to dry-run the process and see expected savings without touching any assets
|
|
51
|
+
4. When you're happy with the projected results, click **Start Optimization**. You'll be asked to confirm twice before any asset is replaced
|
|
52
|
+
5. Watch the progress and the live activity log as the plugin processes your assets
|
|
53
|
+
6. Review the final statistics, including per-category lists of optimized, skipped, and failed assets
|
|
54
|
+
|
|
55
|
+
### Settings reference
|
|
56
|
+
|
|
57
|
+
The form groups settings into four sections:
|
|
58
|
+
|
|
59
|
+
- **Size Thresholds**
|
|
60
|
+
- *Large Asset (MB)* and *Very Large Asset (MB)* — assets above each threshold get their own quality and resize profile
|
|
61
|
+
- *Minimum Size Reduction (%)* — only replace an asset if Imgix can shrink it by at least this much
|
|
62
|
+
|
|
63
|
+
- **Basic Optimization**
|
|
64
|
+
- *Preserve Original Format* — keep JPG/PNG/etc. instead of converting (`fm` parameter)
|
|
65
|
+
- *Auto Compress* — let Imgix pick compression automatically (`auto=compress`)
|
|
66
|
+
- *Target Format* (when not preserving) — `webp` or `avif`
|
|
67
|
+
- *Resize Large Images* — toggle to limit max width via `max-w`
|
|
68
|
+
|
|
69
|
+
- **Resize Dimensions** (visible when resize is enabled)
|
|
70
|
+
- *Large Image Max Width (px)* and *Very Large Image Max Width (px)*
|
|
71
|
+
|
|
72
|
+
- **Compression Settings**
|
|
73
|
+
- *Large Image Quality* / *Very Large Image Quality* — `q` value 0–100 (hidden in lossless mode)
|
|
74
|
+
|
|
75
|
+
- **Advanced Options**
|
|
76
|
+
- *Use Lossless Compression* (`lossless=1`)
|
|
77
|
+
- *Use DPR Optimization* (`dpr=2` for Retina)
|
|
78
|
+
- *Enhanced Chroma Sampling* (`chromasub=444` for JPEGs)
|
|
79
|
+
- *Preserve Color Profiles* (`cs=origin`)
|
|
80
|
+
|
|
81
|
+
A *Restore Defaults* button is available at any time.
|
|
47
82
|
|
|
48
83
|
### Asset Filtering & Optimization
|
|
49
84
|
|
|
@@ -69,6 +104,7 @@ This approach allows you to safely experiment with different optimization parame
|
|
|
69
104
|
- Mass-update existing media libraries with optimized assets
|
|
70
105
|
- Apply consistent optimization settings across your entire asset collection
|
|
71
106
|
- Save time compared to manual optimization workflows
|
|
107
|
+
- Up to 10 assets are processed in parallel for faster runs
|
|
72
108
|
|
|
73
109
|
## Development
|
|
74
110
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{b as y,A as g}from"./index-
|
|
1
|
+
import{b as y,A as g}from"./index-PtBA-34N.js";const w=t=>new Promise(e=>setTimeout(e,t)),R=(t,e,s,r)=>{const c=e*r**t;return Math.min(c,s)},C=(t,e)=>{const s=t?Number.parseInt(t,10):0;return s>0?s*1e3:R(e.retryCount,e.initialRetryDelay,e.maxRetryDelay,e.retryBackoffFactor)},q=(t,e,s)=>y({apiToken:t,environment:e,autoRetry:!1,...s?{baseUrl:s}:{}}),v=t=>t instanceof g&&t.response.status===429,b=t=>t.response.headers["retry-after"]??t.response.headers["x-ratelimit-reset"],$=t=>{const e={};for(const[s,r]of Object.entries(t))typeof r=="string"?e[s]=r:(typeof r=="number"||typeof r=="boolean")&&(e[s]=String(r));return e},A=async(t,e,s)=>{const r=await fetch(t);if(!r.ok)throw new Error(`Failed to fetch image from URL: ${r.status} ${r.statusText}`);const l=await(await r.blob()).arrayBuffer(),i=new Uint8Array(l),a=await fetch(e,{method:"PUT",headers:{...s,"Content-Length":i.length.toString()},body:i});if(!a.ok)throw new Error(`Failed to upload file to S3: ${a.status} ${a.statusText}`)};async function p(t,e,s,r,c,l,i=0,a=1e3,u=6e4,h=2){if(console.log(`Replacing DatoCMS asset ID ${t} with image from URL: ${e}${i>0?` (retry ${i})`:""}`),!t||!s)throw new Error("Missing required parameters: assetId and apiToken are required");const d={retryCount:i,initialRetryDelay:a,maxRetryDelay:u,retryBackoffFactor:h},m=async(o=1)=>p(t,e,s,r,c,l,i+o,a,u,h);try{const o=q(s,r,c),n=await o.uploadRequest.create({filename:l||"optimized-image.jpg"});await A(e,n.url,$(n.request_headers));const f=await o.uploads.rawUpdate(t,{data:{id:t,type:"upload",attributes:{path:n.id}}});return console.log("Asset replaced successfully:",f),f}catch(o){if(v(o)&&i<5){const n=C(b(o),d);return console.error(`Rate limit exceeded while replacing asset. Retrying in ${n}ms...`),await w(n),m()}throw console.error("Error replacing asset:",o),o}}class D{queue=[];activeCount=0;config;processing=!1;completedCount=0;failedCount=0;resolvePromise=null;constructor(e){this.config={...e,concurrency:e.concurrency||3,initialRetryDelay:e.initialRetryDelay||1e3,maxRetryDelay:e.maxRetryDelay||6e4,retryBackoffFactor:e.retryBackoffFactor||2}}addTask(e,s,r){this.queue.push({assetId:e,newImageUrl:s,filename:r,retryCount:0})}async processTask(e){try{await p(e.assetId,e.newImageUrl,this.config.apiToken,this.config.environment,this.config.baseUrl,e.filename,e.retryCount,this.config.initialRetryDelay,this.config.maxRetryDelay,this.config.retryBackoffFactor),this.completedCount++}catch(s){console.error(`Failed to replace asset ${e.assetId} after multiple retries:`,s),this.failedCount++}finally{this.activeCount--,this.processQueue()}}processQueue(){if(this.queue.length===0&&this.activeCount===0&&this.resolvePromise){this.resolvePromise({succeeded:this.completedCount,failed:this.failedCount}),this.resolvePromise=null,this.processing=!1;return}for(;this.queue.length>0&&this.activeCount<(this.config.concurrency||3);){const e=this.queue.shift();e&&(this.activeCount++,this.processTask(e))}}start(){return this.processing?Promise.reject(new Error("Asset replacer is already processing")):(this.processing=!0,this.completedCount=0,this.failedCount=0,new Promise(e=>{this.resolvePromise=e,this.processQueue()}))}getStatus(){return{queued:this.queue.length,active:this.activeCount,completed:this.completedCount,failed:this.failedCount}}}export{D as AssetReplacer,p as default};
|