@macrulez/devtoolz 0.4.1 → 0.4.3
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 +16 -1
- package/dist/cli.js +2 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/image-batch/cli.js +16 -0
- package/dist/commands/image-batch/cli.js.map +1 -1
- package/dist/commands/image-batch/config.d.ts +1 -0
- package/dist/commands/image-batch/config.js +11 -0
- package/dist/commands/image-batch/config.js.map +1 -1
- package/dist/commands/image-batch/run.d.ts +5 -1
- package/dist/commands/image-batch/run.js +7 -0
- package/dist/commands/image-batch/run.js.map +1 -1
- package/dist/commands/image-hash/sharp-loader.d.ts +3 -0
- package/dist/commands/image-hash/sharp-loader.js.map +1 -1
- package/dist/commands/ui/cli.d.ts +2 -0
- package/dist/commands/ui/cli.js +78 -0
- package/dist/commands/ui/cli.js.map +1 -0
- package/dist/commands/ui/fs-routes.d.ts +7 -0
- package/dist/commands/ui/fs-routes.js +135 -0
- package/dist/commands/ui/fs-routes.js.map +1 -0
- package/dist/commands/ui/http.d.ts +41 -0
- package/dist/commands/ui/http.js +81 -0
- package/dist/commands/ui/http.js.map +1 -0
- package/dist/commands/ui/jobs.d.ts +15 -0
- package/dist/commands/ui/jobs.js +73 -0
- package/dist/commands/ui/jobs.js.map +1 -0
- package/dist/commands/ui/modules/checks.d.ts +28 -0
- package/dist/commands/ui/modules/checks.js +556 -0
- package/dist/commands/ui/modules/checks.js.map +1 -0
- package/dist/commands/ui/modules/cleanup.d.ts +2 -0
- package/dist/commands/ui/modules/cleanup.js +305 -0
- package/dist/commands/ui/modules/cleanup.js.map +1 -0
- package/dist/commands/ui/modules/image-batch-backups.d.ts +2 -0
- package/dist/commands/ui/modules/image-batch-backups.js +116 -0
- package/dist/commands/ui/modules/image-batch-backups.js.map +1 -0
- package/dist/commands/ui/modules/image-batch-manage.d.ts +2 -0
- package/dist/commands/ui/modules/image-batch-manage.js +245 -0
- package/dist/commands/ui/modules/image-batch-manage.js.map +1 -0
- package/dist/commands/ui/modules/image-batch.d.ts +2 -0
- package/dist/commands/ui/modules/image-batch.js +225 -0
- package/dist/commands/ui/modules/image-batch.js.map +1 -0
- package/dist/commands/ui/modules/image-hash.d.ts +2 -0
- package/dist/commands/ui/modules/image-hash.js +158 -0
- package/dist/commands/ui/modules/image-hash.js.map +1 -0
- package/dist/commands/ui/modules/index.d.ts +2 -0
- package/dist/commands/ui/modules/index.js +11 -0
- package/dist/commands/ui/modules/index.js.map +1 -0
- package/dist/commands/ui/open-browser.d.ts +1 -0
- package/dist/commands/ui/open-browser.js +18 -0
- package/dist/commands/ui/open-browser.js.map +1 -0
- package/dist/commands/ui/scan.d.ts +20 -0
- package/dist/commands/ui/scan.js +57 -0
- package/dist/commands/ui/scan.js.map +1 -0
- package/dist/commands/ui/server.d.ts +18 -0
- package/dist/commands/ui/server.js +196 -0
- package/dist/commands/ui/server.js.map +1 -0
- package/dist/ui/assets/ChecksPage-Ia4QJkV3.js +1 -0
- package/dist/ui/assets/ChecksPage-VewKhd5A.css +1 -0
- package/dist/ui/assets/CleanupPage-DqqrgWSI.js +4 -0
- package/dist/ui/assets/CleanupPage-nxJE8S0P.css +1 -0
- package/dist/ui/assets/FolderBrowser-Cdzt7edI.js +1 -0
- package/dist/ui/assets/FolderBrowser-CkH9R4jg.css +1 -0
- package/dist/ui/assets/ImageBatchPage-9HgS9uVf.js +4 -0
- package/dist/ui/assets/ImageBatchPage-EhlvnXbP.css +1 -0
- package/dist/ui/assets/ImageHashPage-BT4S8t3Y.css +1 -0
- package/dist/ui/assets/ImageHashPage-C0ltmpOF.js +1 -0
- package/dist/ui/assets/SourcePicker-6fQmtLgo.css +1 -0
- package/dist/ui/assets/SourcePicker-xk00AG2e.js +1 -0
- package/dist/ui/assets/UiSegmented-BT3dOelo.css +1 -0
- package/dist/ui/assets/UiSegmented-CsTRUZoX.js +1 -0
- package/dist/ui/assets/core-DVezgdzc.js +12 -0
- package/dist/ui/assets/css-Z72CF80r.js +1 -0
- package/dist/ui/assets/engine-javascript-CNmxVhbB.js +141 -0
- package/dist/ui/assets/github-dark-DHJKELXO.js +1 -0
- package/dist/ui/assets/github-light-DAi9KRSo.js +1 -0
- package/dist/ui/assets/highlight-DT7vvdYt.js +2 -0
- package/dist/ui/assets/html-BlS82ilI.js +1 -0
- package/dist/ui/assets/index-Ch5kTxCO.css +1 -0
- package/dist/ui/assets/index-D8H-zVzo.js +11 -0
- package/dist/ui/assets/javascript-wDzz0qaB.js +1 -0
- package/dist/ui/assets/json-Cp-IABpG.js +1 -0
- package/dist/ui/assets/jsx-g9-lgVsj.js +1 -0
- package/dist/ui/assets/markdown-Cvjx9yec.js +1 -0
- package/dist/ui/assets/scss-Cw6XMfVs.js +1 -0
- package/dist/ui/assets/tsx-COt5Ahok.js +1 -0
- package/dist/ui/assets/typescript-BPQ3VLAy.js +1 -0
- package/dist/ui/assets/useCopy-i_vlQfC-.js +1 -0
- package/dist/ui/assets/vue-CwSeJimo.js +1 -0
- package/dist/ui/assets/yaml-Buea-lGh.js +1 -0
- package/dist/ui/index.html +17 -0
- package/package.json +17 -4
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{d as re,x as E,I as Ae,r as P,a as se,o as _,c as y,h,t as w,j as R,F as L,l as O,i as $,k as Xe,v as nt,s as pe,b as Q,n as Y,w as be,C as we,q as Ne,B as Le,O as ot,P as it,p as ne,e as We,g as xe,E as Te,y as De,z as rt}from"./index-D8H-zVzo.js";import{U as st,F as lt}from"./FolderBrowser-Cdzt7edI.js";import{U as at}from"./UiSegmented-CsTRUZoX.js";import{u as ct}from"./useCopy-i_vlQfC-.js";import{p as Ue,h as ut}from"./highlight-DT7vvdYt.js";const dt=re({__name:"ChecksOverview",props:{checks:{type:Array,required:!0},outcomes:{type:Object,required:!0},running:{type:Boolean,required:!0},progress:{type:Object,required:!0},tookMs:{type:null,required:!0}},emits:["run-all","open"],setup(n,{expose:t,emit:i}){t();const e=n,s=i,l=P(!1),o=[{id:"code",title:"Code"},{id:"dependencies",title:"Dependencies"},{id:"docs",title:"Documentation"}],r=E(()=>e.checks.filter(d=>d.slow).map(d=>d.title)),c=E(()=>o.map(d=>({...d,items:e.checks.filter(x=>x.group===d.id)})).filter(d=>d.items.length>0)),a=E(()=>e.progress.total>0?Math.round(e.progress.done/e.progress.total*100):0),p=E(()=>e.checks.filter(d=>e.outcomes[d.id])),m=E(()=>p.value.filter(d=>{const x=e.outcomes[d.id];return x&&x.findings.length===0&&!x.error}).length),g=E(()=>{const d={error:0,warning:0,info:0};for(const x of p.value)for(const M of e.outcomes[x.id]?.findings??[])d[M.severity]+=1;return d}),v=E(()=>g.value.error+g.value.warning+g.value.info);function C(d){const x={error:0,warning:0,info:0};for(const M of e.outcomes[d]?.findings??[])x[M.severity]+=1;return x}function f(d){const x=e.outcomes[d];return x?x.error?"broken":x.findings.length===0?"clean":"found":"idle"}const u={props:e,emit:s,includeSlow:l,GROUPS:o,slowNames:r,grouped:c,percent:a,ran:p,clean:m,totals:g,total:v,breakdown:C,state:f,Icon:Ae};return Object.defineProperty(u,"__isScriptSetup",{enumerable:!1,value:!0}),u}}),ft={class:"overview"},ht={class:"card block"},vt={class:"head"},_t={key:0,class:"muted"},gt={key:1,class:"muted"},yt=["disabled"],mt={key:0,class:"check"},pt=["disabled"],wt={key:1,class:"progress-wrap",role:"status"},xt={class:"progress"},kt={class:"muted small"},bt={key:2,class:"chips"},Ct={key:0,class:"sev sev--error"},Mt={key:1,class:"sev sev--warning"},Nt={key:2,class:"sev"},St={key:3,class:"sev sev--ok"},Ot={class:"group__title"},jt={class:"cards"},It=["onClick"],zt={class:"tile__top"},Pt={class:"tile__state"},At={class:"tile__text muted"},Ft={key:0,class:"tile__sev"},Et={key:0,class:"sev sev--error"},Lt={key:1,class:"sev sev--warning"},Tt={key:2,class:"sev"},Dt={key:1,class:"tile__slow muted"};function Ut(n,t,i,e,s,l){return _(),y("div",ft,[h("section",ht,[h("div",vt,[h("div",null,[t[3]||(t[3]=h("h2",null,"Project health",-1)),e.ran.length?(_(),y("p",_t,[h("strong",null,w(e.clean)+" of "+w(e.ran.length),1),t[2]||(t[2]=R(" checks are clean · ",-1)),h("strong",null,w(e.total),1),R(" finding"+w(e.total===1?"":"s")+" ",1),i.tookMs!==void 0?(_(),y(L,{key:0},[R(" · "+w((i.tookMs/1e3).toFixed(1))+" s",1)],64)):O("v-if",!0)])):(_(),y("p",gt,"Run every check at once to see where the project stands."))]),h("button",{class:"btn btn--primary",disabled:i.running,onClick:t[0]||(t[0]=o=>e.emit("run-all",e.includeSlow))},[$(e.Icon,{name:"play",size:15}),R(" "+w(i.running?"Checking…":e.ran.length?"Run all again":"Run all checks"),1)],8,yt)]),e.slowNames.length?(_(),y("label",mt,[Xe(h("input",{"onUpdate:modelValue":t[1]||(t[1]=o=>e.includeSlow=o),type:"checkbox",disabled:i.running},null,8,pt),[[nt,e.includeSlow]]),h("span",null,[R(" Include the slow check ("+w(e.slowNames.join(", "))+") ",1),t[4]||(t[4]=h("small",{class:"muted"}," — it type-checks the whole project",-1))])])):O("v-if",!0),i.running?(_(),y("div",wt,[h("div",xt,[h("div",{class:"progress__bar",style:pe({width:`${e.percent}%`})},null,4)]),h("span",kt,[R(w(i.progress.done)+" of "+w(i.progress.total)+" ",1),i.progress.current?(_(),y(L,{key:0},[R(" · "+w(i.progress.current),1)],64)):O("v-if",!0)])])):O("v-if",!0),e.ran.length?(_(),y("div",bt,[e.totals.error?(_(),y("span",Ct,w(e.totals.error)+" error"+w(e.totals.error===1?"":"s"),1)):O("v-if",!0),e.totals.warning?(_(),y("span",Mt,w(e.totals.warning)+" warning"+w(e.totals.warning===1?"":"s"),1)):O("v-if",!0),e.totals.info?(_(),y("span",Nt,w(e.totals.info)+" note"+w(e.totals.info===1?"":"s"),1)):O("v-if",!0),e.total===0?(_(),y("span",St,"Everything is clean")):O("v-if",!0)])):O("v-if",!0)]),(_(!0),y(L,null,Q(e.grouped,o=>(_(),y("section",{key:o.id,class:"group"},[h("h3",Ot,w(o.title),1),h("div",jt,[(_(!0),y(L,null,Q(o.items,r=>(_(),y("button",{key:r.id,class:Y(["tile",`tile--${e.state(r.id)}`]),onClick:c=>e.emit("open",r.id)},[h("span",zt,[h("strong",null,w(r.title),1),h("span",Pt,[e.state(r.id)==="idle"?(_(),y(L,{key:0},[R("not run")],64)):e.state(r.id)==="clean"?(_(),y(L,{key:1},[R("✓ clean")],64)):e.state(r.id)==="broken"?(_(),y(L,{key:2},[R("couldn’t run")],64)):(_(),y(L,{key:3},[R(w(i.outcomes[r.id]?.findings.length),1)],64))])]),h("span",At,w(i.outcomes[r.id]?.summary??r.description),1),e.state(r.id)==="found"?(_(),y("span",Ft,[e.breakdown(r.id).error?(_(),y("span",Et,w(e.breakdown(r.id).error)+" error",1)):O("v-if",!0),e.breakdown(r.id).warning?(_(),y("span",Lt,w(e.breakdown(r.id).warning)+" warning",1)):O("v-if",!0),e.breakdown(r.id).info?(_(),y("span",Tt,w(e.breakdown(r.id).info)+" note",1)):O("v-if",!0)])):O("v-if",!0),r.slow&&e.state(r.id)==="idle"?(_(),y("span",Dt,"slow")):O("v-if",!0)],10,It))),128))])]))),128))])}const Rt=se(dt,[["render",Ut],["__scopeId","data-v-21773826"],["__file","C:/work/NPM/devtoolz/ui/src/modules/checks/ChecksOverview.vue"]]);function Vt(n,t){var i,e=1;n==null&&(n=0),t==null&&(t=0);function s(){var l,o=i.length,r,c=0,a=0;for(l=0;l<o;++l)r=i[l],c+=r.x,a+=r.y;for(c=(c/o-n)*e,a=(a/o-t)*e,l=0;l<o;++l)r=i[l],r.x-=c,r.y-=a}return s.initialize=function(l){i=l},s.x=function(l){return arguments.length?(n=+l,s):n},s.y=function(l){return arguments.length?(t=+l,s):t},s.strength=function(l){return arguments.length?(e=+l,s):e},s}function Bt(n){const t=+this._x.call(null,n),i=+this._y.call(null,n);return Ke(this.cover(t,i),t,i,n)}function Ke(n,t,i,e){if(isNaN(t)||isNaN(i))return n;var s,l=n._root,o={data:e},r=n._x0,c=n._y0,a=n._x1,p=n._y1,m,g,v,C,f,u,d,x;if(!l)return n._root=o,n;for(;l.length;)if((f=t>=(m=(r+a)/2))?r=m:a=m,(u=i>=(g=(c+p)/2))?c=g:p=g,s=l,!(l=l[d=u<<1|f]))return s[d]=o,n;if(v=+n._x.call(null,l.data),C=+n._y.call(null,l.data),t===v&&i===C)return o.next=l,s?s[d]=o:n._root=o,n;do s=s?s[d]=new Array(4):n._root=new Array(4),(f=t>=(m=(r+a)/2))?r=m:a=m,(u=i>=(g=(c+p)/2))?c=g:p=g;while((d=u<<1|f)===(x=(C>=g)<<1|v>=m));return s[x]=l,s[d]=o,n}function qt(n){var t,i,e=n.length,s,l,o=new Array(e),r=new Array(e),c=1/0,a=1/0,p=-1/0,m=-1/0;for(i=0;i<e;++i)isNaN(s=+this._x.call(null,t=n[i]))||isNaN(l=+this._y.call(null,t))||(o[i]=s,r[i]=l,s<c&&(c=s),s>p&&(p=s),l<a&&(a=l),l>m&&(m=l));if(c>p||a>m)return this;for(this.cover(c,a).cover(p,m),i=0;i<e;++i)Ke(this,o[i],r[i],n[i]);return this}function Gt(n,t){if(isNaN(n=+n)||isNaN(t=+t))return this;var i=this._x0,e=this._y0,s=this._x1,l=this._y1;if(isNaN(i))s=(i=Math.floor(n))+1,l=(e=Math.floor(t))+1;else{for(var o=s-i||1,r=this._root,c,a;i>n||n>=s||e>t||t>=l;)switch(a=(t<e)<<1|n<i,c=new Array(4),c[a]=r,r=c,o*=2,a){case 0:s=i+o,l=e+o;break;case 1:i=s-o,l=e+o;break;case 2:s=i+o,e=l-o;break;case 3:i=s-o,e=l-o;break}this._root&&this._root.length&&(this._root=r)}return this._x0=i,this._y0=e,this._x1=s,this._y1=l,this}function Yt(){var n=[];return this.visit(function(t){if(!t.length)do n.push(t.data);while(t=t.next)}),n}function Ht(n){return arguments.length?this.cover(+n[0][0],+n[0][1]).cover(+n[1][0],+n[1][1]):isNaN(this._x0)?void 0:[[this._x0,this._y0],[this._x1,this._y1]]}function H(n,t,i,e,s){this.node=n,this.x0=t,this.y0=i,this.x1=e,this.y1=s}function Xt(n,t,i){var e,s=this._x0,l=this._y0,o,r,c,a,p=this._x1,m=this._y1,g=[],v=this._root,C,f;for(v&&g.push(new H(v,s,l,p,m)),i==null?i=1/0:(s=n-i,l=t-i,p=n+i,m=t+i,i*=i);C=g.pop();)if(!(!(v=C.node)||(o=C.x0)>p||(r=C.y0)>m||(c=C.x1)<s||(a=C.y1)<l))if(v.length){var u=(o+c)/2,d=(r+a)/2;g.push(new H(v[3],u,d,c,a),new H(v[2],o,d,u,a),new H(v[1],u,r,c,d),new H(v[0],o,r,u,d)),(f=(t>=d)<<1|n>=u)&&(C=g[g.length-1],g[g.length-1]=g[g.length-1-f],g[g.length-1-f]=C)}else{var x=n-+this._x.call(null,v.data),M=t-+this._y.call(null,v.data),k=x*x+M*M;if(k<i){var I=Math.sqrt(i=k);s=n-I,l=t-I,p=n+I,m=t+I,e=v.data}}return e}function Wt(n){if(isNaN(p=+this._x.call(null,n))||isNaN(m=+this._y.call(null,n)))return this;var t,i=this._root,e,s,l,o=this._x0,r=this._y0,c=this._x1,a=this._y1,p,m,g,v,C,f,u,d;if(!i)return this;if(i.length)for(;;){if((C=p>=(g=(o+c)/2))?o=g:c=g,(f=m>=(v=(r+a)/2))?r=v:a=v,t=i,!(i=i[u=f<<1|C]))return this;if(!i.length)break;(t[u+1&3]||t[u+2&3]||t[u+3&3])&&(e=t,d=u)}for(;i.data!==n;)if(s=i,!(i=i.next))return this;return(l=i.next)&&delete i.next,s?(l?s.next=l:delete s.next,this):t?(l?t[u]=l:delete t[u],(i=t[0]||t[1]||t[2]||t[3])&&i===(t[3]||t[2]||t[1]||t[0])&&!i.length&&(e?e[d]=i:this._root=i),this):(this._root=l,this)}function Kt(n){for(var t=0,i=n.length;t<i;++t)this.remove(n[t]);return this}function Qt(){return this._root}function Jt(){var n=0;return this.visit(function(t){if(!t.length)do++n;while(t=t.next)}),n}function Zt(n){var t=[],i,e=this._root,s,l,o,r,c;for(e&&t.push(new H(e,this._x0,this._y0,this._x1,this._y1));i=t.pop();)if(!n(e=i.node,l=i.x0,o=i.y0,r=i.x1,c=i.y1)&&e.length){var a=(l+r)/2,p=(o+c)/2;(s=e[3])&&t.push(new H(s,a,p,r,c)),(s=e[2])&&t.push(new H(s,l,p,a,c)),(s=e[1])&&t.push(new H(s,a,o,r,p)),(s=e[0])&&t.push(new H(s,l,o,a,p))}return this}function $t(n){var t=[],i=[],e;for(this._root&&t.push(new H(this._root,this._x0,this._y0,this._x1,this._y1));e=t.pop();){var s=e.node;if(s.length){var l,o=e.x0,r=e.y0,c=e.x1,a=e.y1,p=(o+c)/2,m=(r+a)/2;(l=s[0])&&t.push(new H(l,o,r,p,m)),(l=s[1])&&t.push(new H(l,p,r,c,m)),(l=s[2])&&t.push(new H(l,o,m,p,a)),(l=s[3])&&t.push(new H(l,p,m,c,a))}i.push(e)}for(;e=i.pop();)n(e.node,e.x0,e.y0,e.x1,e.y1);return this}function en(n){return n[0]}function tn(n){return arguments.length?(this._x=n,this):this._x}function nn(n){return n[1]}function on(n){return arguments.length?(this._y=n,this):this._y}function Fe(n,t,i){var e=new Ee(t??en,i??nn,NaN,NaN,NaN,NaN);return n==null?e:e.addAll(n)}function Ee(n,t,i,e,s,l){this._x=n,this._y=t,this._x0=i,this._y0=e,this._x1=s,this._y1=l,this._root=void 0}function Re(n){for(var t={data:n.data},i=t;n=n.next;)i=i.next={data:n.data};return t}var W=Fe.prototype=Ee.prototype;W.copy=function(){var n=new Ee(this._x,this._y,this._x0,this._y0,this._x1,this._y1),t=this._root,i,e;if(!t)return n;if(!t.length)return n._root=Re(t),n;for(i=[{source:t,target:n._root=new Array(4)}];t=i.pop();)for(var s=0;s<4;++s)(e=t.source[s])&&(e.length?i.push({source:e,target:t.target[s]=new Array(4)}):t.target[s]=Re(e));return n};W.add=Bt;W.addAll=qt;W.cover=Gt;W.data=Yt;W.extent=Ht;W.find=Xt;W.remove=Wt;W.removeAll=Kt;W.root=Qt;W.size=Jt;W.visit=Zt;W.visitAfter=$t;W.x=tn;W.y=on;function X(n){return function(){return n}}function oe(n){return(n()-.5)*1e-6}function rn(n){return n.x+n.vx}function sn(n){return n.y+n.vy}function ln(n){var t,i,e,s=1,l=1;typeof n!="function"&&(n=X(n==null?1:+n));function o(){for(var a,p=t.length,m,g,v,C,f,u,d=0;d<l;++d)for(m=Fe(t,rn,sn).visitAfter(r),a=0;a<p;++a)g=t[a],f=i[g.index],u=f*f,v=g.x+g.vx,C=g.y+g.vy,m.visit(x);function x(M,k,I,V,q){var T=M.data,b=M.r,S=f+b;if(T){if(T.index>g.index){var z=v-T.x-T.vx,D=C-T.y-T.vy,U=z*z+D*D;U<S*S&&(z===0&&(z=oe(e),U+=z*z),D===0&&(D=oe(e),U+=D*D),U=(S-(U=Math.sqrt(U)))/U*s,g.vx+=(z*=U)*(S=(b*=b)/(u+b)),g.vy+=(D*=U)*S,T.vx-=z*(S=1-S),T.vy-=D*S)}return}return k>v+S||V<v-S||I>C+S||q<C-S}}function r(a){if(a.data)return a.r=i[a.data.index];for(var p=a.r=0;p<4;++p)a[p]&&a[p].r>a.r&&(a.r=a[p].r)}function c(){if(t){var a,p=t.length,m;for(i=new Array(p),a=0;a<p;++a)m=t[a],i[m.index]=+n(m,a,t)}}return o.initialize=function(a,p){t=a,e=p,c()},o.iterations=function(a){return arguments.length?(l=+a,o):l},o.strength=function(a){return arguments.length?(s=+a,o):s},o.radius=function(a){return arguments.length?(n=typeof a=="function"?a:X(+a),c(),o):n},o}function an(n){return n.index}function Ve(n,t){var i=n.get(t);if(!i)throw new Error("node not found: "+t);return i}function cn(n){var t=an,i=m,e,s=X(30),l,o,r,c,a,p=1;n==null&&(n=[]);function m(u){return 1/Math.min(r[u.source.index],r[u.target.index])}function g(u){for(var d=0,x=n.length;d<p;++d)for(var M=0,k,I,V,q,T,b,S;M<x;++M)k=n[M],I=k.source,V=k.target,q=V.x+V.vx-I.x-I.vx||oe(a),T=V.y+V.vy-I.y-I.vy||oe(a),b=Math.sqrt(q*q+T*T),b=(b-l[M])/b*u*e[M],q*=b,T*=b,V.vx-=q*(S=c[M]),V.vy-=T*S,I.vx+=q*(S=1-S),I.vy+=T*S}function v(){if(o){var u,d=o.length,x=n.length,M=new Map(o.map((I,V)=>[t(I,V,o),I])),k;for(u=0,r=new Array(d);u<x;++u)k=n[u],k.index=u,typeof k.source!="object"&&(k.source=Ve(M,k.source)),typeof k.target!="object"&&(k.target=Ve(M,k.target)),r[k.source.index]=(r[k.source.index]||0)+1,r[k.target.index]=(r[k.target.index]||0)+1;for(u=0,c=new Array(x);u<x;++u)k=n[u],c[u]=r[k.source.index]/(r[k.source.index]+r[k.target.index]);e=new Array(x),C(),l=new Array(x),f()}}function C(){if(o)for(var u=0,d=n.length;u<d;++u)e[u]=+i(n[u],u,n)}function f(){if(o)for(var u=0,d=n.length;u<d;++u)l[u]=+s(n[u],u,n)}return g.initialize=function(u,d){o=u,a=d,v()},g.links=function(u){return arguments.length?(n=u,v(),g):n},g.id=function(u){return arguments.length?(t=u,g):t},g.iterations=function(u){return arguments.length?(p=+u,g):p},g.strength=function(u){return arguments.length?(i=typeof u=="function"?u:X(+u),C(),g):i},g.distance=function(u){return arguments.length?(s=typeof u=="function"?u:X(+u),f(),g):s},g}var un={value:()=>{}};function Qe(){for(var n=0,t=arguments.length,i={},e;n<t;++n){if(!(e=arguments[n]+"")||e in i||/[\s.]/.test(e))throw new Error("illegal type: "+e);i[e]=[]}return new ke(i)}function ke(n){this._=n}function dn(n,t){return n.trim().split(/^|\s+/).map(function(i){var e="",s=i.indexOf(".");if(s>=0&&(e=i.slice(s+1),i=i.slice(0,s)),i&&!t.hasOwnProperty(i))throw new Error("unknown type: "+i);return{type:i,name:e}})}ke.prototype=Qe.prototype={constructor:ke,on:function(n,t){var i=this._,e=dn(n+"",i),s,l=-1,o=e.length;if(arguments.length<2){for(;++l<o;)if((s=(n=e[l]).type)&&(s=fn(i[s],n.name)))return s;return}if(t!=null&&typeof t!="function")throw new Error("invalid callback: "+t);for(;++l<o;)if(s=(n=e[l]).type)i[s]=Be(i[s],n.name,t);else if(t==null)for(s in i)i[s]=Be(i[s],n.name,null);return this},copy:function(){var n={},t=this._;for(var i in t)n[i]=t[i].slice();return new ke(n)},call:function(n,t){if((s=arguments.length-2)>0)for(var i=new Array(s),e=0,s,l;e<s;++e)i[e]=arguments[e+2];if(!this._.hasOwnProperty(n))throw new Error("unknown type: "+n);for(l=this._[n],e=0,s=l.length;e<s;++e)l[e].value.apply(t,i)},apply:function(n,t,i){if(!this._.hasOwnProperty(n))throw new Error("unknown type: "+n);for(var e=this._[n],s=0,l=e.length;s<l;++s)e[s].value.apply(t,i)}};function fn(n,t){for(var i=0,e=n.length,s;i<e;++i)if((s=n[i]).name===t)return s.value}function Be(n,t,i){for(var e=0,s=n.length;e<s;++e)if(n[e].name===t){n[e]=un,n=n.slice(0,e).concat(n.slice(e+1));break}return i!=null&&n.push({name:t,value:i}),n}var le=0,ue=0,ae=0,Je=1e3,Ce,de,Me=0,ie=0,Se=0,fe=typeof performance=="object"&&performance.now?performance:Date,Ze=typeof window=="object"&&window.requestAnimationFrame?window.requestAnimationFrame.bind(window):function(n){setTimeout(n,17)};function $e(){return ie||(Ze(hn),ie=fe.now()+Se)}function hn(){ie=0}function ze(){this._call=this._time=this._next=null}ze.prototype=et.prototype={constructor:ze,restart:function(n,t,i){if(typeof n!="function")throw new TypeError("callback is not a function");i=(i==null?$e():+i)+(t==null?0:+t),!this._next&&de!==this&&(de?de._next=this:Ce=this,de=this),this._call=n,this._time=i,Pe()},stop:function(){this._call&&(this._call=null,this._time=1/0,Pe())}};function et(n,t,i){var e=new ze;return e.restart(n,t,i),e}function vn(){$e(),++le;for(var n=Ce,t;n;)(t=ie-n._time)>=0&&n._call.call(void 0,t),n=n._next;--le}function qe(){ie=(Me=fe.now())+Se,le=ue=0;try{vn()}finally{le=0,gn(),ie=0}}function _n(){var n=fe.now(),t=n-Me;t>Je&&(Se-=t,Me=n)}function gn(){for(var n,t=Ce,i,e=1/0;t;)t._call?(e>t._time&&(e=t._time),n=t,t=t._next):(i=t._next,t._next=null,t=n?n._next=i:Ce=i);de=n,Pe(e)}function Pe(n){if(!le){ue&&(ue=clearTimeout(ue));var t=n-ie;t>24?(n<1/0&&(ue=setTimeout(qe,n-fe.now()-Se)),ae&&(ae=clearInterval(ae))):(ae||(Me=fe.now(),ae=setInterval(_n,Je)),le=1,Ze(qe))}}const yn=1664525,mn=1013904223,Ge=4294967296;function pn(){let n=1;return()=>(n=(yn*n+mn)%Ge)/Ge}function wn(n){return n.x}function xn(n){return n.y}var kn=10,bn=Math.PI*(3-Math.sqrt(5));function Cn(n){var t,i=1,e=.001,s=1-Math.pow(e,1/300),l=0,o=.6,r=new Map,c=et(m),a=Qe("tick","end"),p=pn();n==null&&(n=[]);function m(){g(),a.call("tick",t),i<e&&(c.stop(),a.call("end",t))}function g(f){var u,d=n.length,x;f===void 0&&(f=1);for(var M=0;M<f;++M)for(i+=(l-i)*s,r.forEach(function(k){k(i)}),u=0;u<d;++u)x=n[u],x.fx==null?x.x+=x.vx*=o:(x.x=x.fx,x.vx=0),x.fy==null?x.y+=x.vy*=o:(x.y=x.fy,x.vy=0);return t}function v(){for(var f=0,u=n.length,d;f<u;++f){if(d=n[f],d.index=f,d.fx!=null&&(d.x=d.fx),d.fy!=null&&(d.y=d.fy),isNaN(d.x)||isNaN(d.y)){var x=kn*Math.sqrt(.5+f),M=f*bn;d.x=x*Math.cos(M),d.y=x*Math.sin(M)}(isNaN(d.vx)||isNaN(d.vy))&&(d.vx=d.vy=0)}}function C(f){return f.initialize&&f.initialize(n,p),f}return v(),t={tick:g,restart:function(){return c.restart(m),t},stop:function(){return c.stop(),t},nodes:function(f){return arguments.length?(n=f,v(),r.forEach(C),t):n},alpha:function(f){return arguments.length?(i=+f,t):i},alphaMin:function(f){return arguments.length?(e=+f,t):e},alphaDecay:function(f){return arguments.length?(s=+f,t):+s},alphaTarget:function(f){return arguments.length?(l=+f,t):l},velocityDecay:function(f){return arguments.length?(o=1-f,t):1-o},randomSource:function(f){return arguments.length?(p=f,r.forEach(C),t):p},force:function(f,u){return arguments.length>1?(u==null?r.delete(f):r.set(f,C(u)),t):r.get(f)},find:function(f,u,d){var x=0,M=n.length,k,I,V,q,T;for(d==null?d=1/0:d*=d,x=0;x<M;++x)q=n[x],k=f-q.x,I=u-q.y,V=k*k+I*I,V<d&&(T=q,d=V);return T},on:function(f,u){return arguments.length>1?(a.on(f,u),t):a.on(f)}}}function Mn(){var n,t,i,e,s=X(-30),l,o=1,r=1/0,c=.81;function a(v){var C,f=n.length,u=Fe(n,wn,xn).visitAfter(m);for(e=v,C=0;C<f;++C)t=n[C],u.visit(g)}function p(){if(n){var v,C=n.length,f;for(l=new Array(C),v=0;v<C;++v)f=n[v],l[f.index]=+s(f,v,n)}}function m(v){var C=0,f,u,d=0,x,M,k;if(v.length){for(x=M=k=0;k<4;++k)(f=v[k])&&(u=Math.abs(f.value))&&(C+=f.value,d+=u,x+=u*f.x,M+=u*f.y);v.x=x/d,v.y=M/d}else{f=v,f.x=f.data.x,f.y=f.data.y;do C+=l[f.data.index];while(f=f.next)}v.value=C}function g(v,C,f,u){if(!v.value)return!0;var d=v.x-t.x,x=v.y-t.y,M=u-C,k=d*d+x*x;if(M*M/c<k)return k<r&&(d===0&&(d=oe(i),k+=d*d),x===0&&(x=oe(i),k+=x*x),k<o&&(k=Math.sqrt(o*k)),t.vx+=d*v.value*e/k,t.vy+=x*v.value*e/k),!0;if(v.length||k>=r)return;(v.data!==t||v.next)&&(d===0&&(d=oe(i),k+=d*d),x===0&&(x=oe(i),k+=x*x),k<o&&(k=Math.sqrt(o*k)));do v.data!==t&&(M=l[v.data.index]*e/k,t.vx+=d*M,t.vy+=x*M);while(v=v.next)}return a.initialize=function(v,C){n=v,i=C,p()},a.strength=function(v){return arguments.length?(s=typeof v=="function"?v:X(+v),p(),a):s},a.distanceMin=function(v){return arguments.length?(o=v*v,a):Math.sqrt(o)},a.distanceMax=function(v){return arguments.length?(r=v*v,a):Math.sqrt(r)},a.theta=function(v){return arguments.length?(c=v*v,a):Math.sqrt(c)},a}function Nn(n){var t=X(.1),i,e,s;typeof n!="function"&&(n=X(n==null?0:+n));function l(r){for(var c=0,a=i.length,p;c<a;++c)p=i[c],p.vx+=(s[c]-p.x)*e[c]*r}function o(){if(i){var r,c=i.length;for(e=new Array(c),s=new Array(c),r=0;r<c;++r)e[r]=isNaN(s[r]=+n(i[r],r,i))?0:+t(i[r],r,i)}}return l.initialize=function(r){i=r,o()},l.strength=function(r){return arguments.length?(t=typeof r=="function"?r:X(+r),o(),l):t},l.x=function(r){return arguments.length?(n=typeof r=="function"?r:X(+r),o(),l):n},l}function Sn(n){var t=X(.1),i,e,s;typeof n!="function"&&(n=X(n==null?0:+n));function l(r){for(var c=0,a=i.length,p;c<a;++c)p=i[c],p.vy+=(s[c]-p.y)*e[c]*r}function o(){if(i){var r,c=i.length;for(e=new Array(c),s=new Array(c),r=0;r<c;++r)e[r]=isNaN(s[r]=+n(i[r],r,i))?0:+t(i[r],r,i)}}return l.initialize=function(r){i=r,o()},l.strength=function(r){return arguments.length?(t=typeof r=="function"?r:X(+r),o(),l):t},l.y=function(r){return arguments.length?(n=typeof r=="function"?r:X(+r),o(),l):n},l}const ve=900,_e=560,ce=9,On=re({__name:"CycleGraph",props:{cycles:{type:Array,required:!0},selected:{type:[Number,null],required:!0}},emits:["select-cycle","open-file"],setup(n,{expose:t,emit:i}){t();const e=n,s=i,l=P(null),o=P({x:0,y:0,w:ve,h:_e}),r=P({x:0,y:0,w:ve,h:_e}),c=P(null),a=P();function p(b){return b.split("/").pop()??b}function m(b){const S=b.split("/");return S.pop(),S.join("/")}const g=E(()=>{const b=new Map,S=new Map;for(const A of e.cycles)A.files.forEach((B,K)=>{const Z=b.get(B)??{id:B,label:p(B),dir:m(B),cycles:new Set};Z.cycles.add(A.id),b.set(B,Z);const ee=A.files[(K+1)%A.files.length],G=`${B}>${ee}`,te=S.get(G)??{key:G,from:B,to:ee,cycles:new Set,typeOnly:!0};te.cycles.add(A.id),A.typeOnly||(te.typeOnly=!1),S.set(G,te)});const z=[...b.values()];z.forEach((A,B)=>{const K=B/Math.max(z.length,1)*Math.PI*2;A.x=Math.cos(K)*160,A.y=Math.sin(K)*160});const D=[...S.values()].map(A=>({source:A.from,target:A.to})),U=Cn(z).force("link",cn(D).id(A=>A.id).distance(120)).force("charge",Mn().strength(-300)).force("x",Nn(0).strength(.09)).force("y",Sn(0).strength(.09)).force("center",Vt(0,0)).force("collide",ln(46)).stop(),J=Math.min(400,120+z.length*4);for(let A=0;A<J;A++)U.tick();return{nodes:z,edges:[...S.values()]}}),v=E(()=>new Map(g.value.nodes.map(b=>[b.id,{x:b.x??0,y:b.y??0}])));function C(){const b=[...v.value.values()];if(b.length===0)return;const S=90,z=Math.min(...b.map(G=>G.x))-S,D=Math.max(...b.map(G=>G.x))+S,U=Math.min(...b.map(G=>G.y))-S,J=Math.max(...b.map(G=>G.y))+S;let A=D-z,B=J-U;const K=a.value?.getBoundingClientRect(),Z=K&&K.height>0?K.width/K.height:ve/_e;A/B<Z?A=B*Z:B=A/Z;const ee={x:(z+D)/2-A/2,y:(U+J)/2-B/2,w:A,h:B};r.value=ee,o.value={...ee}}be(g,()=>we(C)),Ne(C);const f=E(()=>e.cycles.find(b=>b.id===e.selected));function u(b){return f.value?b.cycles.has(f.value.id):l.value?b.id===l.value||g.value.edges.some(S=>S.from===l.value&&S.to===b.id||S.to===l.value&&S.from===b.id):!0}function d(b){return f.value?b.cycles.has(f.value.id):l.value?b.from===l.value||b.to===l.value:!0}function x(b){const S=v.value.get(b.from),z=v.value.get(b.to);if(!S||!z)return"";const D=z.x-S.x,U=z.y-S.y,J=Math.hypot(D,U)||1,A=D/J,B=U/J,K=S.x+A*(ce+2),Z=S.y+B*(ce+2),ee=z.x-A*(ce+7),G=z.y-B*(ce+7),te=Math.min(26,J*.18),Oe=(K+ee)/2-B*te,he=(Z+G)/2+A*te;return`M ${K} ${Z} Q ${Oe} ${he} ${ee} ${G}`}function M(b){b.preventDefault();const S=a.value?.getBoundingClientRect();if(!S)return;const z=b.deltaY>0?1.15:1/1.15,D=Math.min(Math.max(o.value.w*z,r.value.w/8),r.value.w*4),U=D/(o.value.w/o.value.h),J=(b.clientX-S.left)/S.width,A=(b.clientY-S.top)/S.height;o.value={x:o.value.x+(o.value.w-D)*J,y:o.value.y+(o.value.h-U)*A,w:D,h:U}}function k(b){b.target.closest(".node")||(c.value={x:b.clientX,y:b.clientY},b.currentTarget.setPointerCapture(b.pointerId))}function I(b){const S=c.value,z=a.value?.getBoundingClientRect();!S||!z||(o.value={...o.value,x:o.value.x-(b.clientX-S.x)/z.width*o.value.w,y:o.value.y-(b.clientY-S.y)/z.height*o.value.h},c.value={x:b.clientX,y:b.clientY})}function V(){c.value=null}function q(b){return b.cycles.size>1?"node--hub":"node--single"}const T={props:e,emit:s,WIDTH:ve,HEIGHT:_e,RADIUS:ce,hovered:l,view:o,home:r,dragging:c,svg:a,baseName:p,dirName:m,graph:g,positions:v,fit:C,activeCycle:f,nodeOn:u,edgeOn:d,edgePath:x,zoom:M,down:k,move:I,up:V,nodeClass:q};return Object.defineProperty(T,"__isScriptSetup",{enumerable:!1,value:!0}),T}}),jn={class:"graph"},In=["viewBox"],zn=["d","marker-end"],Pn=["transform","aria-label","onMouseenter","onFocus","onClick","onKeydown"],An={class:"node__label",y:"-16","text-anchor":"middle"},Fn={key:0,class:"node__dir",y:"26","text-anchor":"middle"},En={class:"graph__bar"};function Ln(n,t,i,e,s,l){return _(),y("div",jn,[(_(),y("svg",{ref:"svg",class:Y(["graph__svg",{"graph__svg--drag":e.dragging}]),viewBox:`${e.view.x} ${e.view.y} ${e.view.w} ${e.view.h}`,role:"img","aria-label":"Graph of the import cycles",onWheel:e.zoom,onPointerdown:e.down,onPointermove:e.move,onPointerup:e.up,onClick:t[2]||(t[2]=Le(o=>e.emit("select-cycle",null),["self"]))},[t[4]||(t[4]=h("defs",null,[h("marker",{id:"arrow",viewBox:"0 0 10 10",refX:"8",refY:"5",markerWidth:"7",markerHeight:"7",orient:"auto-start-reverse"},[h("path",{d:"M 0 0 L 10 5 L 0 10 z",class:"arrow"})]),h("marker",{id:"arrow-on",viewBox:"0 0 10 10",refX:"8",refY:"5",markerWidth:"7",markerHeight:"7",orient:"auto-start-reverse"},[h("path",{d:"M 0 0 L 10 5 L 0 10 z",class:"arrow arrow--on"})])],-1)),(_(!0),y(L,null,Q(e.graph.edges,o=>(_(),y("path",{key:o.key,class:Y(["edge",{"edge--dim":!e.edgeOn(o),"edge--on":!!e.activeCycle&&e.edgeOn(o),"edge--type":o.typeOnly,"edge--strong":o.cycles.size>1}]),d:e.edgePath(o),"marker-end":e.activeCycle&&e.edgeOn(o)?"url(#arrow-on)":"url(#arrow)"},null,10,zn))),128)),(_(!0),y(L,null,Q(e.graph.nodes,o=>(_(),y("g",{key:o.id,class:Y(["node",[e.nodeClass(o),{"node--dim":!e.nodeOn(o)}]]),transform:`translate(${o.x??0}, ${o.y??0})`,tabindex:"0",role:"button","aria-label":`${o.id}, in ${o.cycles.size} cycle${o.cycles.size===1?"":"s"}`,onMouseenter:r=>e.hovered=o.id,onMouseleave:t[0]||(t[0]=r=>e.hovered=null),onFocus:r=>e.hovered=o.id,onBlur:t[1]||(t[1]=r=>e.hovered=null),onClick:Le(r=>e.emit("open-file",o.id),["stop"]),onKeydown:ot(r=>e.emit("open-file",o.id),["enter"])},[h("title",null,w(o.id)+" — in "+w(o.cycles.size)+" cycle"+w(o.cycles.size===1?"":"s"),1),h("circle",{r:e.RADIUS,class:"node__dot"}),h("text",An,w(o.label),1),o.dir?(_(),y("text",Fn,w(o.dir),1)):O("v-if",!0)],42,Pn))),128))],42,In)),h("div",En,[t[5]||(t[5]=it('<span class="legend" data-v-613d80bb><i class="legend__dot legend__dot--single" data-v-613d80bb></i> in one cycle</span><span class="legend" data-v-613d80bb><i class="legend__dot legend__dot--hub" data-v-613d80bb></i> in several cycles</span><span class="legend" data-v-613d80bb><i class="legend__line legend__line--type" data-v-613d80bb></i> type-only import</span><span class="spacer" data-v-613d80bb></span>',4)),h("button",{class:"btn btn--small",onClick:t[3]||(t[3]=o=>e.view={...e.home})},"Fit to screen")]),t[6]||(t[6]=h("p",{class:"muted small"}," Scroll to zoom, drag to move. Click a file to open it, or pick a cycle in the list to light it up. ",-1))])}const Tn=se(On,[["render",Ln],["__scopeId","data-v-613d80bb"],["__file","C:/work/NPM/devtoolz/ui/src/modules/checks/CycleGraph.vue"]]),Ye=40,Dn=re({__name:"FindingsList",props:{findings:{type:Array,required:!0}},emits:["open"],setup(n,{expose:t,emit:i}){t();const e=n,s=i,l=P(Ye),o=P(new Set),r=E(()=>{const m=new Map;for(const g of e.findings){const v=g.file??"Project",C=m.get(v);C?C.push(g):m.set(v,[g])}return[...m.entries()].map(([g,v])=>({file:g,items:[...v].sort((C,f)=>(C.line??0)-(f.line??0))})).sort((g,v)=>g.file.localeCompare(v.file))});function c(m){const g=new Set(o.value);g.has(m)?g.delete(m):g.add(m),o.value=g}function a(m){return m.line?m.column?`${m.line}:${m.column}`:String(m.line):""}const p={props:e,emit:s,PAGE:Ye,shownGroups:l,collapsed:o,groups:r,toggle:c,place:a};return Object.defineProperty(p,"__isScriptSetup",{enumerable:!1,value:!0}),p}}),Un={class:"groups"},Rn=["aria-expanded","onClick"],Vn={class:"group__file"},Bn={class:"group__count"},qn={key:0,class:"items"},Gn=["onClick"],Yn={class:"item__place"},Hn=["title"],Xn={class:"item__text"},Wn={class:"item__message"},Kn={key:0,class:"item__hint muted"},Qn={class:"item__code"},Jn={key:0,class:"more"};function Zn(n,t,i,e,s,l){return _(),y("div",Un,[(_(!0),y(L,null,Q(e.groups.slice(0,e.shownGroups),o=>(_(),y("section",{key:o.file,class:"group"},[h("button",{class:"group__head","aria-expanded":!e.collapsed.has(o.file),onClick:r=>e.toggle(o.file)},[h("span",{class:Y(["group__caret",{"group__caret--open":!e.collapsed.has(o.file)}])},"▸",2),h("code",Vn,w(o.file),1),h("span",Bn,w(o.items.length),1)],8,Rn),e.collapsed.has(o.file)?O("v-if",!0):(_(),y("ul",qn,[(_(!0),y(L,null,Q(o.items,(r,c)=>(_(),y("li",{key:c,class:"item"},[h("button",{class:"item__main",onClick:a=>e.emit("open",r)},[h("span",Yn,w(e.place(r)),1),h("span",{class:Y(["dot",`dot--${r.severity}`]),title:r.severity},null,10,Hn),h("span",Xn,[h("span",Wn,w(r.message),1),r.hint?(_(),y("span",Kn,w(r.hint),1)):O("v-if",!0)]),h("span",Qn,w(r.code),1)],8,Gn)]))),128))]))]))),128)),e.shownGroups<e.groups.length?(_(),y("div",Jn,[h("button",{class:"btn",onClick:t[0]||(t[0]=o=>e.shownGroups+=e.PAGE)}," Show more files ("+w(e.groups.length-e.shownGroups)+" left) ",1),h("button",{class:"btn",onClick:t[1]||(t[1]=o=>e.shownGroups=e.groups.length)},"Show all")])):O("v-if",!0)])}const tt=se(Dn,[["render",Zn],["__scopeId","data-v-917e27d1"],["__file","C:/work/NPM/devtoolz/ui/src/modules/checks/FindingsList.vue"]]),$n=re({__name:"CyclesView",props:{findings:{type:Array,required:!0}},emits:["open-file","open"],setup(n,{expose:t,emit:i}){t();const e=n,s=i,l=P("graph"),o=P(null),r=E(()=>e.findings.filter(m=>m.files&&m.files.length>0).map((m,g)=>({id:g,files:m.files,typeOnly:m.code==="type-only"})));function c(m){o.value=o.value===m?null:m}function a(m){return[...m.files.map(g=>g.split("/").pop()??g),m.files[0]?.split("/").pop()].join(" → ")}const p={props:e,emit:s,mode:l,selected:o,cycles:r,pick:c,chain:a,UiSegmented:at,CycleGraph:Tn,FindingsList:tt};return Object.defineProperty(p,"__isScriptSetup",{enumerable:!1,value:!0}),p}}),eo={class:"cycles"},to={key:0,class:"split"},no={class:"side","aria-label":"Cycles"},oo={class:"side__title"},io={class:"side__list"},ro=["onClick"],so={class:"cycle__head"},lo={class:"muted"},ao={key:0,class:"cycle__tag"},co={class:"cycle__chain"};function uo(n,t,i,e,s,l){return _(),y("div",eo,[$(e.UiSegmented,{modelValue:e.mode,"onUpdate:modelValue":t[0]||(t[0]=o=>e.mode=o),label:"View",options:[{value:"graph",label:"Graph"},{value:"list",label:"List"}]},null,8,["modelValue"]),e.mode==="graph"?(_(),y("div",to,[$(e.CycleGraph,{cycles:e.cycles,selected:e.selected,onSelectCycle:t[1]||(t[1]=o=>e.selected=o),onOpenFile:t[2]||(t[2]=o=>e.emit("open-file",o))},null,8,["cycles","selected"]),h("aside",no,[h("h3",oo,w(e.cycles.length)+" cycle"+w(e.cycles.length===1?"":"s"),1),h("ul",io,[(_(!0),y(L,null,Q(e.cycles,o=>(_(),y("li",{key:o.id},[h("button",{class:Y(["cycle",{"cycle--on":e.selected===o.id}]),onClick:r=>e.pick(o.id)},[h("span",so,[h("strong",null,"Cycle "+w(o.id+1),1),h("span",lo,w(o.files.length)+" files",1),o.typeOnly?(_(),y("span",ao,"types only")):O("v-if",!0)]),h("span",co,w(e.chain(o)),1)],10,ro)]))),128))])])])):(_(),ne(e.FindingsList,{key:1,findings:i.findings,onOpen:t[3]||(t[3]=o=>e.emit("open",o))},null,8,["findings"]))])}const fo=se($n,[["render",uo],["__scopeId","data-v-dbccb5a2"],["__file","C:/work/NPM/devtoolz/ui/src/modules/checks/CyclesView.vue"]]),ge=400,He=1500,ho=re({__name:"UiCode",props:{text:{type:String,required:!0},lang:{type:String,required:!0},focusLine:{type:null,required:!1},focusColumn:{type:null,required:!1}},setup(n,{expose:t}){t();const i=n,e=P(Ue(i.text)),s=P(!1),l=P(),o=E(()=>e.value.length),r=E(()=>!s.value&&o.value>He),c=E(()=>{if(!r.value)return 0;const f=i.focusLine??1;return Math.max(0,Math.min(f-1-ge/2,o.value-ge))}),a=E(()=>r.value?Math.min(o.value,c.value+ge):o.value),p=E(()=>e.value.slice(c.value,a.value)),m=E(()=>String(o.value).length);async function g(){e.value=Ue(i.text),e.value=await ut(i.text,i.lang),await we(),v()}function v(){const f=l.value?.querySelector('[data-focus="true"]');if(f instanceof HTMLElement&&l.value){const u=l.value;u.scrollTop=f.offsetTop-u.clientHeight/2+f.clientHeight/2}}be(()=>[i.text,i.lang],g),be(()=>[i.focusLine,i.focusColumn],async()=>{await we(),v()}),Ne(g);const C={props:i,WINDOW:ge,FULL_LIMIT:He,lines:e,full:s,scroller:l,total:o,windowed:r,start:c,end:a,visible:p,gutter:m,render:g,reveal:v,nextTick:we};return Object.defineProperty(C,"__isScriptSetup",{enumerable:!1,value:!0}),C}}),vo={ref:"scroller",class:"code",tabindex:"0",role:"region","aria-label":"Source code"},_o={key:0,class:"code__note"},go=["data-focus"],yo={class:"line__text"},mo={key:0};function po(n,t,i,e,s,l){return _(),y("div",vo,[e.windowed?(_(),y("p",_o,[R(" Showing lines "+w(e.start+1)+"–"+w(e.end)+" of "+w(e.total)+". ",1),h("button",{class:"code__link",onClick:t[0]||(t[0]=o=>(e.full=!0,e.nextTick().then(e.reveal)))}," Show the whole file ")])):O("v-if",!0),(_(!0),y(L,null,Q(e.visible,(o,r)=>(_(),y("div",{key:e.start+r,class:Y(["line",{"line--focus":e.start+r+1===i.focusLine}]),"data-focus":e.start+r+1===i.focusLine},[h("span",{class:"line__no",style:pe({width:`${e.gutter+1}ch`})},w(e.start+r+1),5),h("span",yo,[(_(!0),y(L,null,Q(o,(c,a)=>(_(),y("span",{key:a,class:Y(["tok",{"tok--bold":c.bold,"tok--italic":c.italic}]),style:pe({"--light":c.light||"var(--text)","--dark":c.dark||"var(--text)"})},w(c.text),7))),128)),!o.length||o.length===1&&o[0]?.text===""?(_(),y("span",mo," ")):O("v-if",!0)]),e.start+r+1===i.focusLine&&i.focusColumn?(_(),y("span",{key:0,class:"line__marker",style:pe({left:`calc(${e.gutter+1}ch + ${Math.max(0,i.focusColumn-1)}ch + 12px)`})},null,4)):O("v-if",!0)],10,go))),128))],512)}const wo=se(ho,[["render",po],["__scopeId","data-v-e79e57a2"],["__file","C:/work/NPM/devtoolz/ui/src/ui-components/UiCode.vue"]]),xo=re({__name:"SourceModal",props:{project:{type:String,required:!0},findings:{type:Array,required:!0},index:{type:Number,required:!0}},emits:["close","update:index"],setup(n,{expose:t,emit:i}){t();const e=n,s=i,{copied:l,copy:o}=ct(),r=P(),c=P(""),a=P(!1),p=new Map,m=E(()=>e.findings[e.index]),g=E(()=>e.index>0),v=E(()=>e.index<e.findings.length-1),C=E(()=>{if(!r.value)return"";const M=[r.value.abs.replace(/\\/g,"/")];return m.value.line&&M.push(String(m.value.line)),m.value.line&&m.value.column&&M.push(String(m.value.column)),`vscode://file/${M.join(":")}`});async function f(){const M=m.value.file;if(c.value="",!M){r.value=void 0;return}const k=p.get(M);if(k){r.value=k;return}a.value=!0;try{const I=await xe.get(`/api/source?project=${encodeURIComponent(e.project)}&path=${encodeURIComponent(M)}`);p.set(M,I),r.value=I}catch(I){r.value=void 0,c.value=I instanceof Error?I.message:String(I)}finally{a.value=!1}}function u(M){const k=e.index+M;k>=0&&k<e.findings.length&&s("update:index",k)}function d(M){M.target instanceof HTMLInputElement||(M.key==="ArrowLeft"&&u(-1),M.key==="ArrowRight"&&u(1))}be(()=>e.index,f,{immediate:!0}),Ne(()=>window.addEventListener("keydown",d)),We(()=>window.removeEventListener("keydown",d));const x={props:e,emit:s,copied:l,copy:o,source:r,failure:c,loading:a,cache:p,finding:m,hasPrev:g,hasNext:v,editorLink:C,load:f,go:u,onKey:d,Icon:Ae,UiCode:wo,UiModal:st};return Object.defineProperty(x,"__isScriptSetup",{enumerable:!1,value:!0}),x}}),ko={class:"muted counter"},bo=["disabled"],Co=["disabled"],Mo={class:"body"},No={class:"finding"},So={key:0,class:"muted"},Oo={key:0,class:"notice notice--error"},jo={key:1,class:"muted"},Io={key:2,class:"muted"},zo={class:"bar"},Po={class:"path"},Ao=["href"];function Fo(n,t,i,e,s,l){return _(),ne(e.UiModal,{title:e.finding.file??"Project",width:"1100px",onClose:t[3]||(t[3]=o=>e.emit("close"))},{actions:Te(()=>[h("span",ko,w(i.index+1)+" / "+w(i.findings.length),1),h("button",{class:"btn btn--small",disabled:!e.hasPrev,"aria-label":"Previous finding",onClick:t[0]||(t[0]=o=>e.go(-1))},[$(e.Icon,{name:"left",size:15})],8,bo),h("button",{class:"btn btn--small",disabled:!e.hasNext,"aria-label":"Next finding",onClick:t[1]||(t[1]=o=>e.go(1))},[$(e.Icon,{name:"right",size:15})],8,Co)]),default:Te(()=>[h("div",Mo,[h("div",No,[h("span",{class:Y(["badge",`badge--${e.finding.severity}`])},w(e.finding.code),3),h("strong",null,w(e.finding.message),1),e.finding.hint?(_(),y("p",So,w(e.finding.hint),1)):O("v-if",!0)]),e.failure?(_(),y("p",Oo,w(e.failure),1)):e.loading?(_(),y("p",jo,"Loading…")):e.finding.file?e.source?(_(),y(L,{key:3},[h("div",zo,[h("code",Po,[R(w(e.source.path),1),e.finding.line?(_(),y(L,{key:0},[R(":"+w(e.finding.line),1)],64)):O("v-if",!0)]),h("button",{class:"btn btn--small",onClick:t[2]||(t[2]=o=>e.copy("path",e.source.abs))},[$(e.Icon,{name:e.copied==="path"?"check":"copy",size:14},null,8,["name"]),R(" "+w(e.copied==="path"?"Copied":"Copy path"),1)]),h("a",{class:"btn btn--small",href:e.editorLink},[$(e.Icon,{name:"external",size:14}),t[4]||(t[4]=R(" Open in VS Code ",-1))],8,Ao)]),$(e.UiCode,{class:"viewer",text:e.source.text,lang:e.source.lang,"focus-line":e.finding.line,"focus-column":e.finding.column},null,8,["text","lang","focus-line","focus-column"])],64)):O("v-if",!0):(_(),y("p",Io,"This finding is not tied to a source file."))])]),_:1},8,["title"])}const Eo=se(xo,[["render",Fo],["__scopeId","data-v-88d2cb60"],["__file","C:/work/NPM/devtoolz/ui/src/modules/checks/SourceModal.vue"]]);function ye(n){return Object.fromEntries(n.options.map(t=>[t.key,t.default]))}const je="devtoolz-ui.checks-project",Ie="devtoolz-ui.checks-selected",me="overview",Lo=re({__name:"ChecksPage",props:{module:{type:Object,required:!0},status:{type:null,required:!0}},setup(n,{expose:t}){t();const i=n,e=P([]),s=P(""),l=P(""),o=P({}),r=P({}),c=P(""),a=P(""),p=P(!1),m=P(""),g=P(""),v=P(null),C=P(null),f=P(!1),u=P(!1),d=P({done:0,total:0,current:""}),x=P();let M;const k=E(()=>s.value===me),I=E(()=>e.value.find(N=>N.id===s.value)),V=E(()=>r.value[s.value]),q=E(()=>{const N=V.value?.findings??[],j=m.value.trim().toLowerCase();return N.filter(F=>(g.value===""||F.code===g.value)&&(j===""||`${F.file??""} ${F.message} ${F.code}`.toLowerCase().includes(j)))}),T=E(()=>{const N=new Map;for(const j of V.value?.findings??[]){const F=N.get(j.code);F?F.count+=1:N.set(j.code,{count:1,severity:j.severity})}return[...N.entries()].map(([j,F])=>({code:j,...F}))}),b=E(()=>[{id:"code",title:"Code",items:e.value.filter(N=>N.group==="code")},{id:"dependencies",title:"Dependencies",items:e.value.filter(N=>N.group==="dependencies")},{id:"docs",title:"Documentation",items:e.value.filter(N=>N.group==="docs")}]);function S(N,j){try{localStorage.setItem(N,j)}catch{return}}function z(N){try{return localStorage.getItem(N)??""}catch{return""}}function D(N){s.value=N,m.value="",g.value="",v.value=null,S(Ie,N)}function U(N){p.value=!1;const j=N[0];!j||j===l.value||(l.value=j,r.value={},x.value=void 0,S(je,j))}function J(N){return r.value[N]?.findings.length}async function A(N){if(!(u.value||c.value)){M?.(),u.value=!0,a.value="",d.value={done:0,total:0,current:""};try{const{jobId:j}=await xe.post("/api/checks/all/run",{project:l.value,includeSlow:N});M=De(j,{onProgress:F=>{d.value=F},onDone:F=>{r.value={...r.value,...F.outcomes},x.value=F.tookMs,u.value=!1},onFailed:F=>{a.value=F,u.value=!1}})}catch(j){a.value=j instanceof Error?j.message:String(j),u.value=!1}}}async function B(){const N=I.value;if(!(!N||c.value)){M?.(),c.value=N.id,a.value="";try{const{jobId:j}=await xe.post(`/api/checks/${N.id}/run`,{project:l.value,options:o.value[N.id]??ye(N)});M=De(j,{onDone:F=>{r.value={...r.value,[N.id]:F},c.value="",m.value="",g.value=""},onFailed:F=>{a.value=F,c.value=""}})}catch(j){a.value=j instanceof Error?j.message:String(j),c.value=""}}}function K(N,j){const F=I.value;F&&(o.value={...o.value,[F.id]:{...o.value[F.id]??ye(F),[N]:j}})}function Z(N,j){const F=I.value;F&&(o.value={...o.value,[F.id]:{...o.value[F.id]??ye(F),[N]:j}})}function ee(N){const j=I.value;return j?(o.value[j.id]??ye(j))[N]??"":""}function G(N){C.value=[{file:N,severity:"info",code:"file",message:N}]}function te(N){N.file&&G(N.file)}function Oe(N){const j=q.value.indexOf(N);v.value=j>=0?j:0}Ne(async()=>{l.value=z(je)||i.status?.cwd||"";try{e.value=await xe.get("/api/checks");const N=z(Ie);s.value=N===me||e.value.some(j=>j.id===N)?N:me}catch(N){a.value=N instanceof Error?N.message:String(N)}}),We(()=>M?.());const he={props:i,PROJECT_KEY:je,CHECK_KEY:Ie,OVERVIEW:me,checks:e,selectedId:s,project:l,options:o,outcomes:r,running:c,failure:a,browsing:p,query:m,codeFilter:g,viewing:v,peek:C,optionsOpen:f,runningAll:u,allProgress:d,overviewMs:x,get stop(){return M},set stop(N){M=N},isOverview:k,selected:I,outcome:V,filtered:q,codes:T,groups:b,remember:S,recall:z,select:D,setProject:U,countOf:J,runAll:A,run:B,setFlag:K,setText:Z,valueOf:ee,openFile:G,openCycle:te,open:Oe,FolderBrowser:lt,Icon:Ae,ChecksOverview:Rt,CyclesView:fo,FindingsList:tt,SourceModal:Eo};return Object.defineProperty(he,"__isScriptSetup",{enumerable:!1,value:!0}),he}}),To={class:"page"},Do={class:"page__head"},Uo={class:"muted"},Ro={class:"project"},Vo=["title"],Bo={key:0,class:"notice notice--error"},qo={key:1,class:"layout"},Go={class:"menu","aria-label":"Checks"},Yo=["aria-current"],Ho={key:0,class:"menu__title"},Xo=["aria-current","onClick"],Wo={class:"menu__name"},Ko={class:"main"},Qo={key:0,class:"notice notice--error"},Jo={class:"card block"},Zo={class:"head"},$o={class:"muted"},ei=["disabled"],ti={key:0,class:"options"},ni={key:0,class:"check"},oi=["checked","onChange"],ii={class:"muted"},ri={key:1,class:"field"},si={class:"muted"},li=["value","onInput"],ai={key:0,class:"notice notice--error"},ci={key:1,class:"card block",role:"status"},ui={key:2,class:"card block"},di={class:"head"},fi={class:"muted small"},hi={key:0,class:"notice notice--error"},vi={key:1,class:"clean"},_i={class:"filters"},gi={class:"chips"},yi=["onClick"],mi={key:0,class:"muted"},pi={key:3,class:"card block empty"};function wi(n,t,i,e,s,l){return _(),y("div",To,[h("header",Do,[h("h1",null,w(i.module.title),1),h("p",Uo,w(i.module.description),1),h("p",Ro,[$(e.Icon,{name:"folder",size:15}),t[9]||(t[9]=h("span",{class:"muted"},"Project",-1)),h("code",{title:e.project},w(e.project),9,Vo),h("button",{class:"btn btn--small",onClick:t[0]||(t[0]=o=>e.browsing=!0)},"Change…")])]),e.failure&&!e.selected?(_(),y("p",Bo,w(e.failure),1)):O("v-if",!0),e.checks.length?(_(),y("div",qo,[h("nav",Go,[h("button",{class:Y(["menu__item",{"menu__item--on":e.isOverview}]),"aria-current":e.isOverview?"page":void 0,onClick:t[1]||(t[1]=o=>e.select(e.OVERVIEW))},[...t[10]||(t[10]=[h("span",{class:"menu__name"},"Overview",-1)])],10,Yo),(_(!0),y(L,null,Q(e.groups,o=>(_(),y(L,{key:o.id},[o.items.length?(_(),y("h3",Ho,w(o.title),1)):O("v-if",!0),(_(!0),y(L,null,Q(o.items,r=>(_(),y("button",{key:r.id,class:Y(["menu__item",{"menu__item--on":r.id===e.selectedId}]),"aria-current":r.id===e.selectedId?"page":void 0,onClick:c=>e.select(r.id)},[h("span",Wo,w(r.title),1),e.countOf(r.id)!==void 0?(_(),y("span",{key:0,class:Y(["menu__count",{"menu__count--clean":e.countOf(r.id)===0}])},w(e.countOf(r.id)===0?"✓":e.countOf(r.id)),3)):O("v-if",!0)],10,Xo))),128))],64))),128))]),h("main",Ko,[e.failure&&e.isOverview?(_(),y("p",Qo,w(e.failure),1)):O("v-if",!0),e.isOverview?(_(),ne(e.ChecksOverview,{key:1,checks:e.checks,outcomes:e.outcomes,running:e.runningAll,progress:e.allProgress,"took-ms":e.overviewMs,onRunAll:e.runAll,onOpen:e.select},null,8,["checks","outcomes","running","progress","took-ms"])):e.selected?(_(),y(L,{key:2},[h("section",Jo,[h("div",Zo,[h("div",null,[h("h2",null,w(e.selected.title),1),h("p",$o,w(e.selected.description),1)]),h("button",{class:"btn btn--primary",disabled:e.running!==""||e.project==="",onClick:e.run},[$(e.Icon,{name:"play",size:15}),R(" "+w(e.running===e.selected.id?"Checking…":e.outcome?"Run again":"Run check"),1)],8,ei)]),h("button",{class:"link",onClick:t[2]||(t[2]=o=>e.optionsOpen=!e.optionsOpen)},w(e.optionsOpen?"Hide":"Show")+" options ",1),e.optionsOpen?(_(),y("div",ti,[(_(!0),y(L,null,Q(e.selected.options,o=>(_(),y(L,{key:o.key},[o.type==="boolean"?(_(),y("label",ni,[h("input",{type:"checkbox",checked:e.valueOf(o.key)===!0,onChange:r=>e.setFlag(o.key,r.target.checked)},null,40,oi),h("span",null,[R(w(o.label)+" ",1),h("small",ii," — "+w(o.help),1)])])):(_(),y("label",ri,[h("span",null,[R(w(o.label)+" ",1),h("small",si,"— "+w(o.help),1)]),h("textarea",{class:"textarea",rows:"3",spellcheck:"false",value:String(e.valueOf(o.key)),onInput:r=>e.setText(o.key,r.target.value)},null,40,li)]))],64))),128))])):O("v-if",!0)]),e.failure?(_(),y("p",ai,w(e.failure),1)):O("v-if",!0),e.running===e.selected.id?(_(),y("section",ci,[...t[11]||(t[11]=[h("p",{class:"muted"},"Scanning the project…",-1)])])):e.outcome?(_(),y("section",ui,[h("div",di,[h("div",null,[h("h2",null,w(e.outcome.summary),1),h("p",fi,[R(w((e.outcome.tookMs/1e3).toFixed(1))+" s ",1),e.outcome.filesScanned!==void 0?(_(),y(L,{key:0},[R(" · "+w(e.outcome.filesScanned)+" files scanned",1)],64)):O("v-if",!0)])])]),(_(!0),y(L,null,Q(e.outcome.notes??[],o=>(_(),y("p",{key:o,class:"notice notice--warn"},w(o),1))),128)),e.outcome.error?(_(),y("p",hi,w(e.outcome.error),1)):O("v-if",!0),e.outcome.findings.length===0&&!e.outcome.error?(_(),y("p",vi,[$(e.Icon,{name:"check",size:18}),t[12]||(t[12]=R(" Nothing to report. This check is clean. ",-1))])):O("v-if",!0),e.selected.id==="circular-imports"&&e.outcome.findings.length?(_(),ne(e.CyclesView,{key:2,findings:e.outcome.findings,onOpenFile:e.openFile,onOpen:e.openCycle},null,8,["findings"])):e.outcome.findings.length?(_(),y(L,{key:3},[h("div",_i,[Xe(h("input",{"onUpdate:modelValue":t[3]||(t[3]=o=>e.query=o),class:"input search",placeholder:"Filter by file or text","aria-label":"Filter findings"},null,512),[[rt,e.query]]),h("div",gi,[h("button",{class:Y(["chip",{"chip--on":e.codeFilter===""}]),onClick:t[4]||(t[4]=o=>e.codeFilter="")}," all "+w(e.outcome.findings.length),3),(_(!0),y(L,null,Q(e.codes,o=>(_(),y("button",{key:o.code,class:Y(["chip",[`chip--${o.severity}`,{"chip--on":e.codeFilter===o.code}]]),onClick:r=>e.codeFilter=e.codeFilter===o.code?"":o.code},w(o.code)+" "+w(o.count),11,yi))),128))])]),e.filtered.length===0?(_(),y("p",mi,"No findings match the filter.")):(_(),ne(e.FindingsList,{key:1,findings:e.filtered,onOpen:e.open},null,8,["findings"]))],64)):O("v-if",!0)])):e.running?O("v-if",!0):(_(),y("section",pi,[...t[13]||(t[13]=[h("p",{class:"muted"},"Press “Run check” to scan the project.",-1)])]))],64)):O("v-if",!0)])])):O("v-if",!0),e.peek?(_(),ne(e.SourceModal,{key:2,index:0,project:e.project,findings:e.peek,onClose:t[5]||(t[5]=o=>e.peek=null)},null,8,["project","findings"])):O("v-if",!0),e.viewing!==null&&e.filtered.length?(_(),ne(e.SourceModal,{key:3,index:e.viewing,"onUpdate:index":t[6]||(t[6]=o=>e.viewing=o),project:e.project,findings:e.filtered,onClose:t[7]||(t[7]=o=>e.viewing=null)},null,8,["index","project","findings"])):O("v-if",!0),e.browsing?(_(),ne(e.FolderBrowser,{key:4,start:e.project||i.status?.cwd||"",mode:"folder",title:"Choose the project folder",onClose:t[8]||(t[8]=o=>e.browsing=!1),onConfirm:e.setProject},null,8,["start"])):O("v-if",!0)])}const Ni=se(Lo,[["render",wi],["__scopeId","data-v-2621f21d"],["__file","C:/work/NPM/devtoolz/ui/src/modules/checks/ChecksPage.vue"]]);export{Ni as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.overview[data-v-21773826]{display:flex;flex-direction:column;gap:16px}.block[data-v-21773826]{display:flex;flex-direction:column;gap:12px;padding:18px}.head[data-v-21773826]{display:flex;flex-wrap:wrap;align-items:flex-start;justify-content:space-between;gap:12px}.small[data-v-21773826]{font-size:12px}.progress-wrap[data-v-21773826]{display:flex;flex-direction:column;gap:8px}.progress[data-v-21773826]{height:8px;overflow:hidden;border-radius:999px;background:var(--surface-2)}.progress__bar[data-v-21773826]{height:100%;background:var(--accent);transition:width .15s}.chips[data-v-21773826]{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.sev[data-v-21773826]{padding:2px 10px;border-radius:999px;background:var(--surface-2);font-size:12px}.sev--error[data-v-21773826]{background:var(--danger-soft);color:var(--danger)}.sev--warning[data-v-21773826]{background:var(--warn-soft);color:var(--warn)}.sev--ok[data-v-21773826]{background:color-mix(in srgb,var(--ok) 18%,transparent);color:var(--ok)}.group[data-v-21773826]{display:flex;flex-direction:column;gap:8px}.group__title[data-v-21773826]{font-size:12px;font-weight:600;letter-spacing:.02em;color:var(--muted);text-transform:uppercase}.cards[data-v-21773826]{display:grid;grid-template-columns:repeat(auto-fill,minmax(260px,1fr));gap:12px}.tile[data-v-21773826]{display:flex;flex-direction:column;gap:8px;background:var(--surface);border:1px solid var(--border);border-radius:12px;box-shadow:var(--shadow);padding:12px 16px;text-align:left;cursor:pointer;transition:border-color .15s}.tile[data-v-21773826]:focus-visible{outline:2px solid var(--accent);outline-offset:1px}.tile[data-v-21773826]:hover{border-color:var(--accent)}.tile--clean[data-v-21773826]{border-left:3px solid var(--ok)}.tile--found[data-v-21773826]{border-left:3px solid var(--warn)}.tile--broken[data-v-21773826]{border-left:3px solid var(--danger)}.tile__top[data-v-21773826]{display:flex;align-items:center;justify-content:space-between;gap:8px}.tile__state[data-v-21773826]{color:var(--muted);font-size:12px;font-weight:600}.tile--clean .tile__state[data-v-21773826]{color:var(--ok)}.tile--found .tile__state[data-v-21773826]{color:var(--warn)}.tile--broken .tile__state[data-v-21773826]{color:var(--danger)}.tile__text[data-v-21773826]{font-size:12px}.tile__sev[data-v-21773826]{display:flex;flex-wrap:wrap;align-items:center;gap:4px}.tile__slow[data-v-21773826]{font-size:11px}.graph[data-v-613d80bb]{display:flex;flex-direction:column;gap:8px}.graph__svg[data-v-613d80bb]{width:100%;height:520px;border:1px solid var(--border);border-radius:9px;background:var(--surface-2);cursor:grab;touch-action:none}.graph__svg--drag[data-v-613d80bb]{cursor:grabbing}.graph__bar[data-v-613d80bb]{display:flex;flex-wrap:wrap;align-items:center;gap:16px;font-size:12px}.spacer[data-v-613d80bb]{flex:1}.small[data-v-613d80bb]{font-size:12px}.edge[data-v-613d80bb]{fill:none;stroke:var(--muted);stroke-width:1.4;opacity:.75;transition:opacity .15s}.edge--strong[data-v-613d80bb]{stroke-width:2.2}.edge--type[data-v-613d80bb]{stroke-dasharray:5 4}.edge--on[data-v-613d80bb]{stroke:var(--accent);stroke-width:2.6;opacity:1}.edge--dim[data-v-613d80bb]{opacity:.12}.arrow[data-v-613d80bb]{fill:var(--muted)}.arrow--on[data-v-613d80bb]{fill:var(--accent)}.node[data-v-613d80bb]{cursor:pointer;outline:none;transition:opacity .15s}.node__dot[data-v-613d80bb]{stroke:var(--surface);stroke-width:2}.node--single .node__dot[data-v-613d80bb]{fill:var(--warn)}.node--hub .node__dot[data-v-613d80bb]{fill:var(--danger)}.node:hover .node__dot[data-v-613d80bb],.node:focus-visible .node__dot[data-v-613d80bb]{stroke:var(--accent);stroke-width:3}.node--dim[data-v-613d80bb]{opacity:.2}.node__label[data-v-613d80bb]{fill:var(--text);font-size:13px;font-weight:600;paint-order:stroke;stroke:var(--surface-2);stroke-width:4px;stroke-linejoin:round}.node__dir[data-v-613d80bb]{fill:var(--muted);font-size:10px;paint-order:stroke;stroke:var(--surface-2);stroke-width:3px}.legend[data-v-613d80bb]{display:inline-flex;align-items:center;gap:6px}.legend__dot[data-v-613d80bb]{width:10px;height:10px;border-radius:50%}.legend__dot--single[data-v-613d80bb]{background:var(--warn)}.legend__dot--hub[data-v-613d80bb]{background:var(--danger)}.legend__line[data-v-613d80bb]{width:22px;border-top:2px dashed var(--muted)}.legend__line--type[data-v-613d80bb]{border-top-style:dashed}.groups[data-v-917e27d1]{display:flex;flex-direction:column;gap:8px}.group[data-v-917e27d1]{border:1px solid var(--border);border-radius:9px;overflow:hidden}.group__head[data-v-917e27d1]{display:flex;align-items:center;gap:8px;width:100%;padding:8px 12px;border:0;background:var(--surface-2);text-align:left;cursor:pointer}.group__head[data-v-917e27d1]:focus-visible{outline:2px solid var(--accent);outline-offset:1px}.group__caret[data-v-917e27d1]{flex:none;color:var(--muted);transition:transform .15s}.group__caret--open[data-v-917e27d1]{transform:rotate(90deg)}.group__file[data-v-917e27d1]{flex:1;min-width:0;font-size:12px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.group__count[data-v-917e27d1]{flex:none;padding:0 8px;border-radius:999px;background:var(--surface);color:var(--muted);font-size:11px}.items[data-v-917e27d1]{margin:0;padding:0;list-style:none}.item[data-v-917e27d1]{border-top:1px solid var(--border)}.item__main[data-v-917e27d1]{display:flex;align-items:flex-start;gap:12px;width:100%;padding:8px 12px;border:0;background:transparent;text-align:left;cursor:pointer;transition:background .15s}.item__main[data-v-917e27d1]:hover:not(:disabled){background:var(--surface-2)}.item__main[data-v-917e27d1]:focus-visible{outline:2px solid var(--accent);outline-offset:1px}.item__place[data-v-917e27d1]{flex:none;width:56px;color:var(--muted);font-family:ui-monospace,Cascadia Code,SF Mono,Menlo,Consolas,monospace;font-size:12px;text-align:right}.item__text[data-v-917e27d1]{display:flex;flex-direction:column;gap:2px;flex:1;min-width:0}.item__hint[data-v-917e27d1]{font-size:12px}.item__code[data-v-917e27d1]{flex:none;padding:1px 8px;border-radius:999px;background:var(--surface-2);color:var(--muted);font-size:11px}.dot[data-v-917e27d1]{flex:none;width:8px;height:8px;margin-top:7px;border-radius:50%;background:var(--muted)}.dot--error[data-v-917e27d1]{background:var(--danger)}.dot--warning[data-v-917e27d1]{background:var(--warn)}.more[data-v-917e27d1]{display:flex;flex-wrap:wrap;align-items:center;gap:8px;justify-content:center}.cycles[data-v-dbccb5a2]{display:flex;flex-direction:column;gap:12px}.split[data-v-dbccb5a2]{display:grid;grid-template-columns:minmax(0,1fr) 280px;gap:16px;align-items:start}@media(max-width:1100px){.split[data-v-dbccb5a2]{grid-template-columns:1fr}}.side[data-v-dbccb5a2]{display:flex;flex-direction:column;gap:8px;max-height:600px;overflow-y:auto}.side__title[data-v-dbccb5a2]{font-size:12px;font-weight:600;letter-spacing:.02em;color:var(--muted);text-transform:uppercase}.side__list[data-v-dbccb5a2]{display:flex;flex-direction:column;gap:8px;margin:0;padding:0;list-style:none}.cycle[data-v-dbccb5a2]{display:flex;flex-direction:column;gap:2px;width:100%;padding:8px 12px;border:1px solid var(--border);border-radius:9px;background:var(--surface);text-align:left;cursor:pointer}.cycle[data-v-dbccb5a2]:focus-visible{outline:2px solid var(--accent);outline-offset:1px}.cycle--on[data-v-dbccb5a2]{border-color:var(--accent);background:var(--accent-soft)}.cycle__head[data-v-dbccb5a2]{display:flex;align-items:center;gap:8px;font-size:12px}.cycle__tag[data-v-dbccb5a2]{padding:0 8px;border-radius:999px;background:var(--surface-2);font-size:11px}.cycle__chain[data-v-dbccb5a2]{color:var(--muted);font-family:ui-monospace,Cascadia Code,SF Mono,Menlo,Consolas,monospace;font-size:11px;word-break:break-all}.code[data-v-e79e57a2]{position:relative;overflow:auto;border:1px solid var(--border);border-radius:9px;background:var(--surface-2);font-family:ui-monospace,Cascadia Code,SF Mono,Menlo,Consolas,monospace;font-size:12px;line-height:1.6;tab-size:2}.code[data-v-e79e57a2]:focus-visible{outline:2px solid var(--accent);outline-offset:1px}.code__note[data-v-e79e57a2]{position:sticky;top:0;z-index:1;padding:6px 12px;background:var(--warn-soft);color:var(--warn)}.code__link[data-v-e79e57a2]{padding:0;border:0;background:transparent;color:inherit;text-decoration:underline;cursor:pointer}.line[data-v-e79e57a2]{position:relative;display:flex;min-width:max-content}.line--focus[data-v-e79e57a2]{background:color-mix(in srgb,var(--warn) 22%,transparent);box-shadow:inset 3px 0 0 var(--warn)}.line__no[data-v-e79e57a2]{flex:none;padding:0 12px;color:var(--muted);text-align:right;user-select:none;box-sizing:content-box}.line__text[data-v-e79e57a2]{white-space:pre;padding-right:16px}.line__marker[data-v-e79e57a2]{position:absolute;bottom:0;width:1ch;height:2px;background:var(--danger);pointer-events:none}.tok[data-v-e79e57a2]{color:var(--light)}.tok--bold[data-v-e79e57a2]{font-weight:600}.tok--italic[data-v-e79e57a2]{font-style:italic}@media(prefers-color-scheme:dark){.tok[data-v-e79e57a2]{color:var(--dark)}}.counter[data-v-88d2cb60]{font-size:12px}.body[data-v-88d2cb60]{display:flex;flex-direction:column;gap:12px;padding:16px;min-height:0}.finding[data-v-88d2cb60]{display:flex;flex-direction:column;gap:4px}.bar[data-v-88d2cb60]{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.path[data-v-88d2cb60]{flex:1;min-width:0;font-size:12px;word-break:break-all}.viewer[data-v-88d2cb60]{max-height:58vh}.badge[data-v-88d2cb60]{align-self:flex-start;padding:1px 8px;border-radius:999px;background:var(--surface-2);font-size:11px;text-transform:uppercase;letter-spacing:.03em}.badge--error[data-v-88d2cb60]{background:var(--danger-soft);color:var(--danger)}.badge--warning[data-v-88d2cb60]{background:var(--warn-soft);color:var(--warn)}a.btn[data-v-88d2cb60]{text-decoration:none}.page[data-v-2621f21d]{display:flex;flex-direction:column;gap:16px;padding:28px 28px 60px}@media(max-width:760px){.page[data-v-2621f21d]{padding:18px 14px 40px}}.page__head p[data-v-2621f21d]{margin-top:4px}.project[data-v-2621f21d]{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin-top:8px;font-size:12px}.project code[data-v-2621f21d]{padding:2px 8px;border-radius:6px;background:var(--surface-2);word-break:break-all}.layout[data-v-2621f21d]{display:grid;grid-template-columns:250px minmax(0,1fr);gap:20px;align-items:start}@media(max-width:760px){.layout[data-v-2621f21d]{grid-template-columns:1fr}}.menu[data-v-2621f21d]{display:flex;flex-direction:column;gap:2px}.menu__title[data-v-2621f21d]{font-size:12px;font-weight:600;letter-spacing:.02em;color:var(--muted);text-transform:uppercase;margin:12px 0 4px 8px}.menu__item[data-v-2621f21d]{display:flex;align-items:center;gap:8px;padding:9px 10px;border:0;border-radius:9px;background:transparent;text-align:left;cursor:pointer;transition:background .15s}.menu__item[data-v-2621f21d]:hover:not(:disabled){background:var(--surface-2)}.menu__item[data-v-2621f21d]:focus-visible{outline:2px solid var(--accent);outline-offset:1px}.menu__item--on[data-v-2621f21d]{background:var(--accent-soft);color:var(--accent);font-weight:600}.menu__name[data-v-2621f21d]{flex:1}.menu__count[data-v-2621f21d]{padding:0 8px;border-radius:999px;background:var(--warn-soft);color:var(--warn);font-size:11px;font-weight:600}.menu__count--clean[data-v-2621f21d]{background:color-mix(in srgb,var(--ok) 18%,transparent);color:var(--ok)}.main[data-v-2621f21d]{display:flex;flex-direction:column;gap:16px;min-width:0}.block[data-v-2621f21d]{display:flex;flex-direction:column;gap:12px;padding:18px}.head[data-v-2621f21d]{display:flex;flex-wrap:wrap;align-items:flex-start;justify-content:space-between;gap:12px}.small[data-v-2621f21d]{font-size:12px}.link[data-v-2621f21d]{align-self:flex-start;padding:0;border:0;background:transparent;color:var(--accent);cursor:pointer}.link[data-v-2621f21d]:focus-visible{outline:2px solid var(--accent);outline-offset:1px}.options[data-v-2621f21d]{display:flex;flex-direction:column;gap:12px}.textarea[data-v-2621f21d]{padding:8px 12px;border:1px solid var(--border);border-radius:9px;background:var(--surface);font-family:ui-monospace,Cascadia Code,SF Mono,Menlo,Consolas,monospace;font-size:12px}.textarea[data-v-2621f21d]:focus-visible{outline:2px solid var(--accent);outline-offset:1px}.filters[data-v-2621f21d]{display:flex;flex-direction:column;gap:8px}.search[data-v-2621f21d]{max-width:420px}.chips[data-v-2621f21d]{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.chip[data-v-2621f21d]{padding:2px 10px;border:1px solid var(--border);border-radius:999px;background:var(--surface);font-size:12px;cursor:pointer}.chip[data-v-2621f21d]:focus-visible{outline:2px solid var(--accent);outline-offset:1px}.chip--on[data-v-2621f21d]{border-color:var(--accent);background:var(--accent-soft);color:var(--accent)}.clean[data-v-2621f21d]{display:flex;align-items:center;gap:8px;color:var(--ok);font-weight:600}.empty[data-v-2621f21d]{text-align:center}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import{d as ne,r as d,w as ye,q as se,a as oe,o as a,c as i,F as _,b as P,h as s,t as o,n as T,s as me,j as C,l as v,x as z,g as D,e as be,I as we,y as Se,i as K,k as xe,z as Ce,p as te}from"./index-D8H-zVzo.js";import{F as je}from"./FolderBrowser-Cdzt7edI.js";import{U as Ne}from"./UiSegmented-CsTRUZoX.js";import{h as Oe}from"./highlight-DT7vvdYt.js";const Pe=ne({__name:"DiffView",props:{diff:{type:String,required:!0},lang:{type:String,required:!0}},setup(E,{expose:c}){c();const p=E;function e(u){const w=[];let f,k=0,m=0;for(const h of u.split(`
|
|
2
|
+
`)){const N=/^@@ -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@(.*)$/.exec(h);if(N){k=Number(N[1]),m=Number(N[2]),f={header:h,lines:[]},w.push(f);continue}if(!f||h.startsWith("\\"))continue;const S=h[0];S==="+"?f.lines.push({type:"add",text:h.slice(1),oldNo:null,newNo:m++}):S==="-"?f.lines.push({type:"del",text:h.slice(1),oldNo:k++,newNo:null}):S===" "&&f.lines.push({type:"ctx",text:h.slice(1),oldNo:k++,newNo:m++})}return w}const j=d(e(p.diff));async function y(){const u=e(p.diff);j.value=u;for(const w of u){const f=await Oe(w.lines.map(k=>k.text).join(`
|
|
3
|
+
`),p.lang);w.lines.forEach((k,m)=>{k.tokens=f[m]})}j.value=[...u]}ye(()=>[p.diff,p.lang],y),se(y);function t(u){return u==="add"?"+":u==="del"?"−":" "}const r={props:p,parse:e,hunks:j,colour:y,sign:t};return Object.defineProperty(r,"__isScriptSetup",{enumerable:!1,value:!0}),r}}),Ee={class:"diff",role:"region","aria-label":"Changes in this file"},Ie={class:"hunk__head"},Be={class:"row__no"},Ve={class:"row__no"},ze={class:"row__sign"},De={class:"row__text"},Fe={key:2};function Ue(E,c,p,e,j,y){return a(),i("div",Ee,[(a(!0),i(_,null,P(e.hunks,(t,r)=>(a(),i("section",{key:r,class:"hunk"},[s("div",Ie,o(t.header),1),(a(!0),i(_,null,P(t.lines,(u,w)=>(a(),i("div",{key:w,class:T(["row",`row--${u.type}`])},[s("span",Be,o(u.oldNo??""),1),s("span",Ve,o(u.newNo??""),1),s("span",ze,o(e.sign(u.type)),1),s("span",De,[u.tokens?(a(!0),i(_,{key:0},P(u.tokens,(f,k)=>(a(),i("span",{key:k,class:"tok",style:me({"--light":f.light||"var(--text)","--dark":f.dark||"var(--text)"})},o(f.text),5))),128)):(a(),i(_,{key:1},[C(o(u.text),1)],64)),u.text===""?(a(),i("span",Fe," ")):v("v-if",!0)])],2))),128))]))),128))])}const qe=oe(Pe,[["render",Ue],["__scopeId","data-v-fab0cc77"],["__file","C:/work/NPM/devtoolz/ui/src/modules/cleanup/DiffView.vue"]]),Y="devtoolz-ui.checks-project",Q=40,Ae=ne({__name:"CleanupPage",props:{module:{type:Object,required:!0},status:{type:null,required:!0}},setup(E,{expose:c}){c();const p=E,e={"embedded-in-expression":"inside a larger expression","braceless-body":"the only statement of an if/loop without braces"},j=d([]),y=d("strip-comments"),t=d(""),r=d({}),u=d(!1),w=d(!1),f=d(!1),k=d(!1),m=d(),h=d(new Set),N=d(new Set),S=d(new Set),X=d(""),O=d(""),F=d(""),U=d([]),I=d(""),W=d([]),M=d(Q);let B;const G=z(()=>j.value.find(n=>n.id===y.value)),H=z(()=>{const n=X.value.trim().toLowerCase();return(m.value?.files??[]).filter(l=>n===""||l.file.toLowerCase().includes(n))}),le=z(()=>H.value.slice(0,M.value)),q=z(()=>h.value.size),J=z(()=>(m.value?.files??[]).filter(n=>h.value.has(n.file)).reduce((n,l)=>n+l.count,0));function Z(n){try{localStorage.setItem(Y,n)}catch{return}}function $(){try{return localStorage.getItem(Y)??""}catch{return""}}function A(){const n=G.value;return n?{...Object.fromEntries(n.options.map(g=>[g.key,g.default])),...r.value[n.id]??{}}:{}}function ae(n,l){r.value={...r.value,[y.value]:{...A(),[n]:l}}}function ie(n){const l=n.slice(n.lastIndexOf(".")+1).toLowerCase();return l==="ts"?"ts":l==="tsx"?"tsx":l==="vue"?"vue":l==="jsx"?"jsx":"js"}function ce(n){let l=0,g=0;for(const b of(n??"").split(`
|
|
4
|
+
`))b.startsWith("+")&&!b.startsWith("+++")?l+=1:b.startsWith("-")&&!b.startsWith("---")&&(g+=1);return{added:l,removed:g}}function re(n){const l=new Set(h.value);l.has(n)?l.delete(n):l.add(n),h.value=l}function de(n){const l=new Set(N.value);l.has(n)?l.delete(n):l.add(n),N.value=l}function ue(){h.value=new Set(H.value.filter(n=>!S.value.has(n.file)).map(n=>n.file))}function fe(){h.value=new Set}function he(n){w.value=!1;const l=n[0];!l||l===t.value||(t.value=l,Z(l),R(),V())}function R(){m.value=void 0,h.value=new Set,N.value=new Set,S.value=new Set,U.value=[],I.value="",F.value="",O.value=""}function ve(n){y.value=n,R()}async function _e(){if(!f.value){B?.(),R(),f.value=!0,M.value=Q;try{const{jobId:n}=await D.post(`/api/cleanup/${y.value}/scan`,{project:t.value,options:A()});B=Se(n,{onDone:l=>{m.value=l,f.value=!1},onFailed:l=>{O.value=l,f.value=!1}})}catch(n){O.value=n instanceof Error?n.message:String(n),f.value=!1}}}async function V(){try{const n=await D.get(`/api/cleanup/history?project=${encodeURIComponent(t.value)}`);W.value=n.backups}catch{W.value=[]}}async function pe(){const n=m.value;if(!(!n||q.value===0||k.value||!window.confirm(`Change ${q.value} file${q.value===1?"":"s"}? ${J.value} ${G.value?.verb??"item"}${J.value===1?"":"s"} will be removed. A backup is saved first, and you can undo this afterwards.`))){k.value=!0,O.value="";try{const g=n.files.filter(x=>h.value.has(x.file)),b=await D.post(`/api/cleanup/${y.value}/apply`,{project:t.value,options:A(),files:g.map(x=>({file:x.file,hash:x.hash}))});U.value=b.results,I.value=b.backupDir??"";const L=b.results.filter(x=>x.status==="applied").map(x=>x.file);S.value=new Set([...S.value,...L]),h.value=new Set([...h.value].filter(x=>!L.includes(x))),F.value=`${L.length} file${L.length===1?"":"s"} changed.`,await V()}catch(g){O.value=g instanceof Error?g.message:String(g)}finally{k.value=!1}}}async function ke(n){if(window.confirm("Put the files back as they were before this cleanup?"))try{const l=await D.post("/api/cleanup/undo",{project:t.value,dir:n}),g=l.counts.restored??0,b=l.counts.modified??0;F.value=`Restored ${g} file${g===1?"":"s"}.`+(b?` ${b} changed since and were left alone.`:""),n===I.value&&(I.value="",U.value=[],S.value=new Set),await V()}catch(l){O.value=l instanceof Error?l.message:String(l)}}function ge(n){const l=new Date(n);return Number.isNaN(l.getTime())?n:l.toLocaleString()}se(async()=>{t.value=$()||p.status?.cwd||"";try{j.value=await D.get("/api/cleanup/tools")}catch(n){O.value=n instanceof Error?n.message:String(n)}await V()}),be(()=>B?.());const ee={props:p,PROJECT_KEY:Y,PAGE:Q,REASONS:e,tools:j,toolId:y,project:t,options:r,optionsOpen:u,browsing:w,scanning:f,applying:k,scan:m,picked:h,expanded:N,done:S,query:X,failure:O,note:F,results:U,lastBackup:I,history:W,shown:M,get stop(){return B},set stop(n){B=n},tool:G,files:H,visible:le,pickedCount:q,pickedRemovals:J,remember:Z,recall:$,currentOptions:A,setOption:ae,langOf:ie,stats:ce,togglePicked:re,toggleExpanded:de,selectAll:ue,selectNone:fe,setProject:he,reset:R,chooseTool:ve,runScan:_e,loadHistory:V,apply:pe,undo:ke,when:ge,FolderBrowser:je,Icon:we,UiSegmented:Ne,DiffView:qe};return Object.defineProperty(ee,"__isScriptSetup",{enumerable:!1,value:!0}),ee}}),Re={class:"page"},Le={class:"page__head"},Te={class:"muted"},We={class:"project"},Me=["title"],Ge={key:0,class:"card block"},He={class:"head"},Je=["disabled"],Ke={class:"muted"},Ye={key:0,class:"options"},Qe={key:0,class:"check"},Xe=["checked","onChange"],Ze={class:"muted"},$e={key:1,class:"field"},et={class:"muted"},tt=["value","onInput"],nt={key:1,class:"notice notice--error"},st={key:2,class:"notice"},ot={key:3,class:"card block"},lt={class:"results"},at={class:"muted"},it={key:0,class:"actions"},ct={key:4,class:"card block",role:"status"},rt={key:5,class:"card block"},dt={class:"head"},ut={class:"muted small"},ft={key:0,class:"notice notice--warn"},ht={class:"skipped"},vt={class:"toolbar"},_t=["disabled"],pt={class:"files"},kt={class:"file__row"},gt=["checked","disabled","aria-label","onChange"],yt=["aria-expanded","onClick"],mt={class:"file__name"},bt={class:"file__count"},wt={class:"file__stat file__stat--del"},St={key:0,class:"file__stat file__stat--add"},xt={key:1,class:"file__done"},Ct={key:0,class:"actions"},jt={key:6,class:"card block"},Nt={class:"history"},Ot={class:"muted"},Pt=["onClick"];function Et(E,c,p,e,j,y){return a(),i("div",Re,[s("header",Le,[s("h1",null,o(p.module.title),1),s("p",Te,o(p.module.description),1),s("p",We,[K(e.Icon,{name:"folder",size:15}),c[7]||(c[7]=s("span",{class:"muted"},"Project",-1)),s("code",{title:e.project},o(e.project),9,Me),s("button",{class:"btn btn--small",onClick:c[0]||(c[0]=t=>e.browsing=!0)},"Change…")])]),e.tool?(a(),i("section",Ge,[s("div",He,[K(e.UiSegmented,{"model-value":e.toolId,label:"What to remove",options:e.tools.map(t=>({value:t.id,label:t.title})),"onUpdate:modelValue":e.chooseTool},null,8,["model-value","options"]),s("button",{class:"btn btn--primary",disabled:e.scanning||e.applying||e.project==="",onClick:e.runScan},[K(e.Icon,{name:"search",size:15}),C(" "+o(e.scanning?"Scanning…":e.scan?"Scan again":"Scan the project"),1)],8,Je)]),s("p",Ke,o(e.tool.description)+" Nothing is changed until you choose the files and confirm. ",1),s("button",{class:"link",onClick:c[1]||(c[1]=t=>e.optionsOpen=!e.optionsOpen)},o(e.optionsOpen?"Hide":"Show")+" options ",1),e.optionsOpen?(a(),i("div",Ye,[(a(!0),i(_,null,P(e.tool.options,t=>(a(),i(_,{key:t.key},[t.type==="boolean"?(a(),i("label",Qe,[s("input",{type:"checkbox",checked:e.currentOptions()[t.key]===!0,onChange:r=>e.setOption(t.key,r.target.checked)},null,40,Xe),s("span",null,[C(o(t.label)+" ",1),s("small",Ze,"— "+o(t.help),1)])])):(a(),i("label",$e,[s("span",null,[C(o(t.label)+" ",1),s("small",et,"— "+o(t.help),1)]),s("textarea",{class:"textarea",rows:"3",spellcheck:"false",value:String(e.currentOptions()[t.key]??""),onInput:r=>e.setOption(t.key,r.target.value)},null,40,tt)]))],64))),128))])):v("v-if",!0)])):v("v-if",!0),e.failure?(a(),i("p",nt,o(e.failure),1)):v("v-if",!0),e.note?(a(),i("p",st,o(e.note),1)):v("v-if",!0),e.lastBackup||e.results.length?(a(),i("section",ot,[c[8]||(c[8]=s("h2",null,"Result",-1)),s("ul",lt,[(a(!0),i(_,null,P(e.results,t=>(a(),i("li",{key:t.file,class:T(["result",`result--${t.status}`])},[s("code",null,o(t.file),1),s("span",at,[t.status==="applied"?(a(),i(_,{key:0},[C("changed, "+o(t.count)+" removed",1)],64)):(a(),i(_,{key:1},[C(o(t.message??t.status),1)],64))])],2))),128))]),e.lastBackup?(a(),i("div",it,[s("button",{class:"btn",onClick:c[2]||(c[2]=t=>e.undo(e.lastBackup))},"Undo this cleanup")])):v("v-if",!0)])):v("v-if",!0),e.scanning?(a(),i("section",ct,[...c[9]||(c[9]=[s("p",{class:"muted"},"Scanning the project…",-1)])])):e.scan?(a(),i("section",rt,[s("div",dt,[s("div",null,[s("h2",null,[e.scan.files.length===0?(a(),i(_,{key:0},[C("Nothing to remove")],64)):(a(),i(_,{key:1},[C(o(e.scan.total)+" "+o(e.tool?.verb)+o(e.scan.total===1?"":"s")+" in "+o(e.scan.files.length)+" file"+o(e.scan.files.length===1?"":"s"),1)],64))]),s("p",ut,o(e.scan.filesScanned)+" files scanned · "+o((e.scan.tookMs/1e3).toFixed(1))+" s ",1)])]),e.scan.skipped.length?(a(),i("div",ft,[s("strong",null,o(e.scan.skipped.length)+" call"+o(e.scan.skipped.length===1?"":"s")+" left alone",1),c[10]||(c[10]=C(", because removing them is not safe: ",-1)),s("ul",ht,[(a(!0),i(_,null,P(e.scan.skipped,(t,r)=>(a(),i("li",{key:r},[s("code",null,o(t.file)+":"+o(t.line),1),C(" — "+o(e.REASONS[t.reason]??t.reason),1)]))),128))])])):v("v-if",!0),e.scan.files.length?(a(),i(_,{key:1},[s("div",vt,[xe(s("input",{"onUpdate:modelValue":c[3]||(c[3]=t=>e.query=t),class:"input search",placeholder:"Filter files","aria-label":"Filter files"},null,512),[[Ce,e.query]]),s("button",{class:"btn btn--small",onClick:e.selectAll},"Select all"),s("button",{class:"btn btn--small",onClick:e.selectNone},"Select none"),c[11]||(c[11]=s("span",{class:"spacer"},null,-1)),s("button",{class:"btn btn--primary",disabled:e.pickedCount===0||e.applying,onClick:e.apply},o(e.applying?"Changing…":`Change ${e.pickedCount} file${e.pickedCount===1?"":"s"}`),9,_t)]),s("ul",pt,[(a(!0),i(_,null,P(e.visible,t=>(a(),i("li",{key:t.file,class:T(["file",{"file--done":e.done.has(t.file)}])},[s("div",kt,[s("input",{type:"checkbox",checked:e.picked.has(t.file),disabled:e.done.has(t.file),"aria-label":`Change ${t.file}`,onChange:r=>e.togglePicked(t.file)},null,40,gt),s("button",{class:"file__main","aria-expanded":e.expanded.has(t.file),onClick:r=>e.toggleExpanded(t.file)},[s("span",{class:T(["file__caret",{"file__caret--open":e.expanded.has(t.file)}])},"▸",2),s("code",mt,o(t.file),1),s("span",bt,o(t.count)+" "+o(e.tool?.verb)+o(t.count===1?"":"s"),1),s("span",wt,"−"+o(e.stats(t.diff).removed),1),e.stats(t.diff).added?(a(),i("span",St,"+"+o(e.stats(t.diff).added),1)):v("v-if",!0),e.done.has(t.file)?(a(),i("span",xt,"✓ changed")):v("v-if",!0)],8,yt)]),e.expanded.has(t.file)&&t.diff?(a(),te(e.DiffView,{key:0,diff:t.diff,lang:e.langOf(t.file)},null,8,["diff","lang"])):v("v-if",!0)],2))),128))]),e.shown<e.files.length?(a(),i("div",Ct,[s("button",{class:"btn",onClick:c[4]||(c[4]=t=>e.shown+=e.PAGE)}," Show more ("+o(e.files.length-e.shown)+" left) ",1),s("button",{class:"btn",onClick:c[5]||(c[5]=t=>e.shown=e.files.length)},"Show all")])):v("v-if",!0)],64)):v("v-if",!0)])):v("v-if",!0),e.history.length?(a(),i("section",jt,[c[12]||(c[12]=s("h2",null,"Recent cleanups",-1)),s("ul",Nt,[(a(!0),i(_,null,P(e.history,t=>(a(),i("li",{key:t.dir,class:"history__row"},[s("span",null,[s("strong",null,o(e.tools.find(r=>r.id===t.tool)?.title??t.tool),1),s("span",Ot," · "+o(t.files)+" file"+o(t.files===1?"":"s")+" · "+o(e.when(t.createdAt)),1)]),s("button",{class:"btn btn--small",onClick:r=>e.undo(t.dir)},"Undo",8,Pt)]))),128))])])):v("v-if",!0),e.browsing?(a(),te(e.FolderBrowser,{key:7,start:e.project||p.status?.cwd||"",mode:"folder",title:"Choose the project folder",onClose:c[6]||(c[6]=t=>e.browsing=!1),onConfirm:e.setProject},null,8,["start"])):v("v-if",!0)])}const Dt=oe(Ae,[["render",Et],["__scopeId","data-v-70a493ad"],["__file","C:/work/NPM/devtoolz/ui/src/modules/cleanup/CleanupPage.vue"]]);export{Dt as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.diff[data-v-fab0cc77]{overflow:auto;border:1px solid var(--border);border-radius:9px;background:var(--surface-2);font-family:ui-monospace,Cascadia Code,SF Mono,Menlo,Consolas,monospace;font-size:12px;line-height:1.6;max-height:460px}.hunk[data-v-fab0cc77]{min-width:max-content}.hunk__head[data-v-fab0cc77]{padding:2px 12px;background:var(--accent-soft);color:var(--accent);font-size:11px}.row[data-v-fab0cc77]{display:flex}.row--add[data-v-fab0cc77]{background:color-mix(in srgb,var(--ok) 16%,transparent)}.row--del[data-v-fab0cc77]{background:color-mix(in srgb,var(--danger) 16%,transparent)}.row__no[data-v-fab0cc77]{flex:none;width:4ch;padding:0 6px;color:var(--muted);text-align:right;user-select:none}.row__sign[data-v-fab0cc77]{flex:none;width:2ch;color:var(--muted);user-select:none}.row--add .row__sign[data-v-fab0cc77]{color:var(--ok)}.row--del .row__sign[data-v-fab0cc77]{color:var(--danger)}.row__text[data-v-fab0cc77]{white-space:pre;padding-right:16px}.tok[data-v-fab0cc77]{color:var(--light)}@media(prefers-color-scheme:dark){.tok[data-v-fab0cc77]{color:var(--dark)}}.page[data-v-70a493ad]{display:flex;flex-direction:column;gap:16px;padding:28px 28px 60px}@media(max-width:760px){.page[data-v-70a493ad]{padding:18px 14px 40px}}.page__head p[data-v-70a493ad]{margin-top:4px}.project[data-v-70a493ad]{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin-top:8px;font-size:12px}.project code[data-v-70a493ad]{padding:2px 8px;border-radius:6px;background:var(--surface-2);word-break:break-all}.block[data-v-70a493ad]{display:flex;flex-direction:column;gap:12px;padding:18px}.head[data-v-70a493ad]{display:flex;flex-wrap:wrap;align-items:flex-start;justify-content:space-between;gap:12px}.small[data-v-70a493ad]{font-size:12px}.link[data-v-70a493ad]{align-self:flex-start;padding:0;border:0;background:transparent;color:var(--accent);cursor:pointer}.link[data-v-70a493ad]:focus-visible{outline:2px solid var(--accent);outline-offset:1px}.options[data-v-70a493ad]{display:flex;flex-direction:column;gap:12px}.textarea[data-v-70a493ad]{padding:8px 12px;border:1px solid var(--border);border-radius:9px;background:var(--surface);font-family:ui-monospace,Cascadia Code,SF Mono,Menlo,Consolas,monospace;font-size:12px}.textarea[data-v-70a493ad]:focus-visible{outline:2px solid var(--accent);outline-offset:1px}.toolbar[data-v-70a493ad]{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.search[data-v-70a493ad]{width:260px}.spacer[data-v-70a493ad]{flex:1}.actions[data-v-70a493ad]{display:flex;flex-wrap:wrap;align-items:center;gap:8px;justify-content:center}.skipped[data-v-70a493ad]{margin:8px 0 0;padding-left:20px;font-size:12px}.files[data-v-70a493ad]{display:flex;flex-direction:column;gap:8px;margin:0;padding:0;list-style:none}.file[data-v-70a493ad]{display:flex;flex-direction:column;gap:8px;padding:4px 12px 8px;border:1px solid var(--border);border-radius:9px}.file--done[data-v-70a493ad]{opacity:.6}.file__row[data-v-70a493ad]{display:flex;align-items:center;gap:12px}.file__main[data-v-70a493ad]{display:flex;flex:1;align-items:center;gap:8px;min-width:0;padding:8px 0;border:0;background:transparent;text-align:left;cursor:pointer}.file__main[data-v-70a493ad]:focus-visible{outline:2px solid var(--accent);outline-offset:1px}.file__caret[data-v-70a493ad]{flex:none;color:var(--muted);transition:transform .15s}.file__caret--open[data-v-70a493ad]{transform:rotate(90deg)}.file__name[data-v-70a493ad]{flex:1;min-width:0;font-size:12px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.file__count[data-v-70a493ad]{flex:none;color:var(--muted);font-size:12px}.file__stat[data-v-70a493ad]{flex:none;font-family:ui-monospace,Cascadia Code,SF Mono,Menlo,Consolas,monospace;font-size:11px}.file__stat--del[data-v-70a493ad]{color:var(--danger)}.file__stat--add[data-v-70a493ad]{color:var(--ok)}.file__done[data-v-70a493ad]{flex:none;color:var(--ok);font-size:12px}.results[data-v-70a493ad]{display:flex;flex-direction:column;gap:4px;margin:0;padding:0;list-style:none}.result[data-v-70a493ad]{display:flex;gap:12px;font-size:12px}.result--changed[data-v-70a493ad],.result--error[data-v-70a493ad],.result--refused[data-v-70a493ad]{color:var(--danger)}.history[data-v-70a493ad]{display:flex;flex-direction:column;gap:8px;margin:0;padding:0;list-style:none}.history__row[data-v-70a493ad]{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:12px;padding:8px 12px;border:1px solid var(--border);border-radius:9px}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{d as V,q as A,e as Q,I as D,r as g,a as W,o as s,c as l,h as n,t as u,A as I,i as y,l as v,s as X,n as z,B as L,x as U,g as Y,C as Z,D as $,f as ee,p as oe,E as P,j as B,F as E,b as N,k as T,z as te,v as ie}from"./index-D8H-zVzo.js";const ne=V({__name:"UiModal",props:{title:{type:String,required:!0},width:{type:String,required:!1,default:"820px"},fixedHeight:{type:Boolean,required:!1,default:!1}},emits:["close"],setup(f,{expose:o,emit:c}){o();const e=f,m=c,r=g();function t(b){b.key==="Escape"&&m("close")}A(()=>{window.addEventListener("keydown",t),document.body.style.overflow="hidden",r.value?.focus()}),Q(()=>{window.removeEventListener("keydown",t),document.body.style.overflow=""});const _={props:e,emit:m,dialog:r,onKey:t,Icon:D};return Object.defineProperty(_,"__isScriptSetup",{enumerable:!1,value:!0}),_}}),se=["aria-label"],ae={class:"dialog__head"},le={class:"dialog__title"},de={class:"dialog__body"},re={key:0,class:"dialog__foot"};function ce(f,o,c,e,m,r){return s(),l("div",{class:"overlay",onMousedown:o[1]||(o[1]=L(t=>e.emit("close"),["self"]))},[n("div",{ref:"dialog",class:z(["dialog",{"dialog--fixed":e.props.fixedHeight}]),style:X({"--dialog-width":e.props.width}),role:"dialog","aria-modal":"true","aria-label":e.props.title,tabindex:"-1"},[n("header",ae,[n("h2",le,u(e.props.title),1),I(f.$slots,"actions",{},void 0),n("button",{class:"btn btn--ghost btn--small","aria-label":"Close",onClick:o[0]||(o[0]=t=>e.emit("close"))},[y(e.Icon,{name:"close"})])]),n("div",de,[I(f.$slots,"default",{},void 0)]),f.$slots.footer?(s(),l("footer",re,[I(f.$slots,"footer",{},void 0)])):v("v-if",!0)],14,se)],32)}const fe=W(ne,[["render",ce],["__scopeId","data-v-8bd877a3"],["__file","C:/work/NPM/devtoolz/ui/src/ui-components/UiModal.vue"]]),me=V({__name:"FolderBrowser",props:{start:{type:String,required:!0},mode:{type:String,required:!1,default:"sources"},title:{type:String,required:!1,default:""}},emits:["close","confirm"],setup(f,{expose:o,emit:c}){o();const e=f,m=c,r=g(),t=g(e.start),_=g(!1),b=g(!1),C=g(""),k=g(new Set),S=g(),h=new Map,p=U(()=>r.value?.path.includes("\\")?"\\":"/"),O=U(()=>(r.value?.entries??[]).filter(i=>e.mode!=="folder"||i.kind==="dir")),R=U(()=>r.value?.entries.filter(i=>i.kind==="image").length??0);function w(i){const a=r.value?.path??"";return a.endsWith(p.value)?a+i:a+p.value+i}function M(i,a){const d=a.endsWith("\\")||a.endsWith("/")?a:a+p.value;return i!==a&&i.startsWith(d)}async function x(i){const a=r.value?.path;a!==void 0&&h.set(a,S.value?.scrollTop??0),b.value=!0,C.value="";try{const d=await Y.get(`/api/fs/list?path=${encodeURIComponent(i)}&hidden=${_.value?1:0}`);r.value=d,t.value=d.path;for(const F of[...h.keys()])M(F,d.path)&&h.delete(F);await Z(),S.value?.scrollTo({top:h.get(d.path)??0})}catch(d){C.value=d instanceof Error?d.message:String(d)}finally{b.value=!1}}function H(i){i.kind==="dir"&&x(w(i.name))}function j(i){const a=w(i.name),d=new Set(k.value);d.has(a)?d.delete(a):d.add(a),k.value=d}function G(i){i.kind==="dir"?H(i):e.mode==="image"?m("confirm",[w(i.name)]):j(i)}function K(){r.value&&m("confirm",[r.value.path])}function J(){m("confirm",[...k.value])}A(()=>{x(e.start)});const q={props:e,emit:m,listing:r,pathInput:t,showHidden:_,loading:b,failure:C,picked:k,list:S,positions:h,separator:p,entries:O,imageCount:R,join:w,isInside:M,load:x,enter:H,toggle:j,onRow:G,addCurrent:K,addPicked:J,get formatBytes(){return ee},get imageUrl(){return $},UiModal:fe,Icon:D};return Object.defineProperty(q,"__isScriptSetup",{enumerable:!1,value:!0}),q}}),ue={class:"bar"},ve=["disabled"],ge=["value"],_e=["value"],be={class:"check muted"},he={key:0,class:"notice notice--error notice-inset"},ke=["aria-busy"],pe={key:0,class:"muted empty"},we=["checked","aria-label","onChange"],ye=["onClick"],Ce={key:0,class:"row__icon"},Se=["src"],xe={class:"row__name"},Ie={key:2,class:"muted"},Ue={key:1,class:"muted empty"},Be={class:"muted"},ze=["disabled"],Me=["disabled"];function He(f,o,c,e,m,r){return s(),oe(e.UiModal,{title:c.title||(c.mode==="folder"?"Choose a folder":c.mode==="image"?"Choose an image":"Add folders or images"),"fixed-height":"",onClose:o[8]||(o[8]=t=>e.emit("close"))},{footer:P(()=>[n("span",Be,u(e.imageCount)+" image"+u(e.imageCount===1?"":"s")+" here",1),o[13]||(o[13]=n("span",{class:"spacer"},null,-1)),c.mode!=="image"?(s(),l("button",{key:0,class:z(["btn",{"btn--primary":c.mode==="folder"}]),disabled:!e.listing,onClick:e.addCurrent},u(c.mode==="folder"?"Use this folder":"Add this folder"),11,ze)):v("v-if",!0),c.mode==="sources"?(s(),l("button",{key:1,class:"btn btn--primary",disabled:e.picked.size===0,onClick:e.addPicked}," Add "+u(e.picked.size)+" selected ",9,Me)):v("v-if",!0)]),default:P(()=>[n("div",ue,[n("button",{class:"btn btn--small",disabled:!e.listing?.parent,title:"Parent folder",onClick:o[0]||(o[0]=t=>e.listing?.parent&&e.load(e.listing.parent))},[y(e.Icon,{name:"up",size:15}),o[9]||(o[9]=B(" Up ",-1))],8,ve),n("button",{class:"btn btn--small",title:"Home folder",onClick:o[1]||(o[1]=t=>e.listing&&e.load(e.listing.home))},[y(e.Icon,{name:"home",size:15}),o[10]||(o[10]=B(" Home ",-1))]),n("button",{class:"btn btn--small",title:"Start folder",onClick:o[2]||(o[2]=t=>e.listing&&e.load(e.listing.cwd))}," Start folder "),(e.listing?.roots.length??0)>1?(s(),l("select",{key:0,class:"select bar__roots",value:e.listing?.root,"aria-label":"Drive",onChange:o[3]||(o[3]=t=>e.load(t.target.value))},[(s(!0),l(E,null,N(e.listing?.roots,t=>(s(),l("option",{key:t,value:t},u(t),9,_e))),128))],40,ge)):v("v-if",!0),n("form",{class:"bar__path",onSubmit:o[5]||(o[5]=L(t=>e.load(e.pathInput),["prevent"]))},[T(n("input",{"onUpdate:modelValue":o[4]||(o[4]=t=>e.pathInput=t),class:"input",spellcheck:"false","aria-label":"Folder path"},null,512),[[te,e.pathInput]]),o[11]||(o[11]=n("button",{class:"btn btn--small",type:"submit"},"Go",-1))],32),n("label",be,[T(n("input",{"onUpdate:modelValue":o[6]||(o[6]=t=>e.showHidden=t),type:"checkbox",onChange:o[7]||(o[7]=t=>e.listing&&e.load(e.listing.path))},null,544),[[ie,e.showHidden]]),o[12]||(o[12]=B(" Hidden ",-1))])]),e.failure?(s(),l("div",he,u(e.failure),1)):v("v-if",!0),n("div",{ref:"list",class:"list","aria-busy":e.loading},[e.listing&&e.entries.length===0?(s(),l("div",pe," This folder has no subfolders or images. ")):v("v-if",!0),(s(!0),l(E,null,N(e.entries,t=>(s(),l("div",{key:t.name,class:z(["row",{"row--picked":e.picked.has(e.join(t.name))}])},[c.mode==="sources"?(s(),l("input",{key:0,type:"checkbox",checked:e.picked.has(e.join(t.name)),"aria-label":`Select ${t.name}`,onChange:_=>e.toggle(t)},null,40,we)):v("v-if",!0),n("button",{class:"row__main",onClick:_=>e.onRow(t)},[t.kind==="dir"?(s(),l("span",Ce,[y(e.Icon,{name:"folder"})])):(s(),l("img",{key:1,class:"row__thumb",loading:"lazy",alt:"",src:e.imageUrl(e.join(t.name),96)},null,8,Se)),n("span",xe,u(t.name),1),t.size!==void 0?(s(),l("span",Ie,u(e.formatBytes(t.size)),1)):v("v-if",!0)],8,ye)],2))),128)),e.listing?.truncated?(s(),l("div",Ue,"Only the first entries are shown.")):v("v-if",!0)],8,ke)]),_:1},8,["title"])}const qe=W(me,[["render",He],["__scopeId","data-v-93beb91d"],["__file","C:/work/NPM/devtoolz/ui/src/components/FolderBrowser.vue"]]);export{qe as F,fe as U};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.overlay[data-v-8bd877a3]{position:fixed;inset:0;z-index:20;display:flex;align-items:center;justify-content:center;padding:20px;overflow:hidden;background:var(--backdrop)}.dialog[data-v-8bd877a3]{background:var(--surface);border:1px solid var(--border);border-radius:12px;box-shadow:var(--shadow);box-shadow:var(--shadow-lg);display:flex;flex-direction:column;width:min(var(--dialog-width),100%);max-height:100%;outline:none}.dialog--fixed[data-v-8bd877a3]{height:min(680px,100%)}.dialog__head[data-v-8bd877a3],.dialog__foot[data-v-8bd877a3]{display:flex;align-items:center;gap:10px;padding:12px 16px}.dialog__head[data-v-8bd877a3]{border-bottom:1px solid var(--border)}.dialog__title[data-v-8bd877a3]{flex:1;font-size:16px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dialog__body[data-v-8bd877a3]{flex:1;min-height:0;display:flex;flex-direction:column}.dialog__foot[data-v-8bd877a3]{border-top:1px solid var(--border)}.bar[data-v-93beb91d]{display:flex;flex-wrap:wrap;align-items:center;gap:8px;padding:12px 16px}.bar__path[data-v-93beb91d]{display:flex;flex:1;gap:6px;min-width:200px}.bar__path .input[data-v-93beb91d]{flex:1;height:28px;font-family:ui-monospace,Cascadia Code,SF Mono,Menlo,Consolas,monospace;font-size:12px}.bar__roots[data-v-93beb91d]{height:28px}.notice-inset[data-v-93beb91d]{margin:0 16px 12px}.spacer[data-v-93beb91d]{flex:1}.list[data-v-93beb91d]{flex:1;min-height:0;padding:0 8px 8px;overflow-y:auto;overscroll-behavior:contain;scrollbar-width:thin;scrollbar-color:var(--border) transparent}.empty[data-v-93beb91d]{padding:24px;text-align:center}.row[data-v-93beb91d]{display:flex;align-items:center;gap:8px;padding:2px 8px;border-radius:9px}.row[data-v-93beb91d]:hover{background:var(--surface-2)}.row--picked[data-v-93beb91d]{background:var(--accent-soft)}.row__main[data-v-93beb91d]{display:flex;flex:1;align-items:center;gap:10px;min-width:0;padding:4px 0;border:0;background:transparent;text-align:left;cursor:pointer}.row__icon[data-v-93beb91d]{display:grid;place-items:center;width:40px;height:40px;color:var(--accent)}.row__thumb[data-v-93beb91d]{width:40px;height:40px;border-radius:6px;background:var(--surface-2);object-fit:cover}.row__name[data-v-93beb91d]{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import{d as oe,x as E,q as ce,I as ue,r as c,g as F,D as Ue,f as Me,a as ne,o as s,c as l,h as n,t as a,l as d,j as b,F as p,b as N,B as Xe,k as T,z as Y,i as U,n as te,v as fe,p as $,L as $e,M as pe,u as et,m as tt,w as ge,e as xe,J as De,K as ae,y as ot,s as Ve,N as Ne}from"./index-D8H-zVzo.js";import{U as he}from"./UiSegmented-CsTRUZoX.js";import{F as Oe}from"./FolderBrowser-Cdzt7edI.js";import{S as nt}from"./SourcePicker-xk00AG2e.js";const ke="devtoolz-ui.open-backup",we=30,st=oe({__name:"BackupsView",props:{cwd:{type:String,required:!0}},setup(f,{expose:t}){t();const i={restored:"restored","would-restore":"can be restored",modified:"changed since","missing-backup":"copy missing","damaged-backup":"copy damaged",error:"error"},e=c(""),m=c([]),g=c(),o=c(""),r=c(""),y=c(!1),S=c(!1),M=c(we),A=c(""),B=c(!1),z=E(()=>{const w=g.value?.counts;return w?w.modified+w["missing-backup"]+w["damaged-backup"]+w.error:0}),O=E(()=>g.value?.counts["would-restore"]??0),k=E(()=>g.value?.entries.slice(0,M.value)??[]);function v(w){const I=new Date(w);return Number.isNaN(I.getTime())?w:I.toLocaleString()}function C(w){return w==="would-restore"||w==="restored"?"good":w==="modified"?"warn":"bad"}function j(w){o.value=w instanceof Error?w.message:String(w)}async function R(){try{const w=await F.get("/api/image-batch/backups");e.value=w.root,m.value=w.backups}catch(w){j(w)}}async function P(w){o.value="",r.value="",S.value=!1,M.value=we;try{g.value=await F.get(`/api/image-batch/backup?dir=${encodeURIComponent(w)}`)}catch(I){g.value=void 0,j(I)}}function Z(w){const I=w?.[0]??A.value;B.value=!1,I.trim()!==""&&(A.value=I,P(I))}async function D(){const w=g.value;if(!w)return;const I=S.value?w.files:O.value;if(window.confirm(`Put back ${I} original file${I===1?"":"s"} from this backup?`+(S.value?" Files changed after the replacement will be overwritten too.":""))){y.value=!0;try{const H=await F.post("/api/image-batch/backup/restore",{dir:w.dir,force:S.value});r.value=`Restored ${H.counts.restored} file${H.counts.restored===1?"":"s"}.`,await P(w.dir)}catch(H){j(H)}finally{y.value=!1}}}async function K(w){if(window.confirm("Delete this backup for good? The saved originals cannot be recovered afterwards."))try{await F.post("/api/image-batch/backup/delete",{dir:w}),r.value="The backup was deleted.",g.value?.dir===w&&(g.value=void 0),await R()}catch(I){j(I)}}ce(async()=>{await R();try{const w=localStorage.getItem(ke);w&&(localStorage.removeItem(ke),await P(w))}catch{g.value=void 0}});const q={OPEN_KEY:ke,PAGE:we,LABELS:i,root:e,rows:m,detail:g,failure:o,note:r,busy:y,force:S,shown:M,customDir:A,browsing:B,problems:z,restorable:O,visible:k,when:v,tone:C,fail:j,load:R,open:P,openCustom:Z,restore:D,remove:K,get formatBytes(){return Me},get imageUrl(){return Ue},FolderBrowser:Oe,Icon:ue};return Object.defineProperty(q,"__isScriptSetup",{enumerable:!1,value:!0}),q}}),lt={class:"view"},it={key:0,class:"card block"},at={key:0,class:"notice"},rt={key:1,class:"notice notice--error"},dt={key:2,class:"muted"},ct={class:"list"},ut={class:"item__main"},ft={class:"muted"},vt=["title"],mt={class:"item__actions"},pt=["onClick"],gt=["onClick"],ht={class:"custom"},bt=["disabled"],_t={key:1,class:"card block"},yt={class:"head"},kt={class:"muted"},wt={class:"item__path"},St={key:0,class:"notice"},Ct={key:1,class:"notice notice--error"},Vt={class:"chips"},xt={key:2,class:"notice notice--warn"},Ot={class:"actions"},Et=["disabled"],zt={key:0,class:"check"},Bt={class:"rows"},jt=["src"],Nt=["src"],Tt={class:"row__text"},At=["title"],It={class:"muted small"},Ut={key:0,class:"small row__message"},Mt={key:3,class:"actions"},Dt={key:4,class:"muted small"};function qt(f,t,i,e,m,g){return s(),l("div",lt,[e.detail?(s(),l("section",_t,[n("div",yt,[n("div",null,[n("h2",null,"Backup of "+a(e.when(e.detail.createdAt)),1),n("p",kt,a(e.detail.files)+" file"+a(e.detail.files===1?"":"s")+" · "+a(e.formatBytes(e.detail.bytesBefore))+" originals, "+a(e.formatBytes(e.detail.bytesAfter))+" after the replacement ",1),n("code",wt,a(e.detail.dir),1)]),n("button",{class:"btn btn--ghost",onClick:t[3]||(t[3]=o=>(e.detail=void 0,e.load()))},[U(e.Icon,{name:"close",size:16}),t[15]||(t[15]=b(" Back to the list ",-1))])]),e.note?(s(),l("p",St,a(e.note),1)):d("v-if",!0),e.failure?(s(),l("p",Ct,a(e.failure),1)):d("v-if",!0),n("div",Vt,[(s(!0),l(p,null,N(e.detail.counts,(o,r)=>T((s(),l("span",{key:r,class:te(["chip",`chip--${e.tone(r)}`])},a(o)+" "+a(e.LABELS[r]),3)),[[$e,o>0]])),128))]),e.detail.counts.modified?(s(),l("p",xt,a(e.detail.counts.modified)+" file"+a(e.detail.counts.modified===1?" was":"s were")+" changed after the replacement. They are left alone unless you tick the box below. ",1)):d("v-if",!0),n("div",Ot,[n("button",{class:"btn btn--primary",disabled:e.busy||e.restorable===0&&!e.force,onClick:e.restore}," Restore "+a(e.force?"everything":`${e.restorable} file${e.restorable===1?"":"s"}`),9,Et),e.detail.counts.modified?(s(),l("label",zt,[T(n("input",{"onUpdate:modelValue":t[4]||(t[4]=o=>e.force=o),type:"checkbox"},null,512),[[fe,e.force]]),t[16]||(t[16]=b(" Overwrite files that changed since ",-1))])):d("v-if",!0),n("button",{class:"btn btn--danger",onClick:t[5]||(t[5]=o=>e.remove(e.detail.dir))},"Delete this backup")]),n("ul",Bt,[(s(!0),l(p,null,N(e.visible,o=>(s(),l("li",{key:o.path,class:"row"},[n("img",{class:"row__thumb",loading:"lazy",alt:"Original",src:e.imageUrl(o.backup,120)},null,8,jt),t[17]||(t[17]=n("span",{class:"row__arrow muted"},"⇄",-1)),n("img",{class:"row__thumb",loading:"lazy",alt:"Now",src:e.imageUrl(o.path,120)},null,8,Nt),n("div",Tt,[n("span",{class:"row__name",title:o.path},a(o.path),9,At),n("span",It," original "+a(e.formatBytes(o.bytesBefore))+" · replaced with "+a(e.formatBytes(o.bytesAfter)),1),o.message?(s(),l("span",Ut,a(o.message),1)):d("v-if",!0)]),n("span",{class:te(["chip",`chip--${e.tone(o.status)}`])},a(e.LABELS[o.status]),3)]))),128))]),e.detail&&e.shown<e.detail.entries.length?(s(),l("div",Mt,[n("button",{class:"btn",onClick:t[6]||(t[6]=o=>e.shown+=e.PAGE)}," Show more ("+a(e.detail.entries.length-e.shown)+" left) ",1),n("button",{class:"btn",onClick:t[7]||(t[7]=o=>e.shown=e.detail.entries.length)}," Show all ("+a(e.detail.entries.length)+") ",1)])):d("v-if",!0),e.problems?(s(),l("p",Dt," The left picture is the saved original, the right one is the file as it is now on disk. ")):d("v-if",!0)])):(s(),l("section",it,[t[14]||(t[14]=n("div",{class:"head"},[n("div",null,[n("h2",null,"Backups"),n("p",{class:"muted"}," “Replace the originals” copies each file here first, so a replacement can be undone. ")])],-1)),e.note?(s(),l("p",at,a(e.note),1)):d("v-if",!0),e.failure?(s(),l("p",rt,a(e.failure),1)):d("v-if",!0),e.rows.length===0?(s(),l("p",dt,[t[9]||(t[9]=b(" No backups in ",-1)),n("code",null,a(e.root),1),t[10]||(t[10]=b(" yet. ",-1))])):d("v-if",!0),n("ul",ct,[(s(!0),l(p,null,N(e.rows,o=>(s(),l("li",{key:o.dir,class:"item"},[n("div",ut,[n("strong",null,a(e.when(o.createdAt)),1),n("span",ft,a(o.files)+" file"+a(o.files===1?"":"s")+" · "+a(e.formatBytes(o.bytesBefore))+" → "+a(e.formatBytes(o.bytesAfter)),1),n("code",{class:"item__path",title:o.dir},a(o.dir),9,vt)]),n("div",mt,[n("button",{class:"btn btn--small",onClick:r=>e.open(o.dir)},"Open",8,pt),n("button",{class:"btn btn--small btn--danger",onClick:r=>e.remove(o.dir)},"Delete",8,gt)])]))),128))]),n("div",ht,[t[12]||(t[12]=n("h3",null,"Another backup folder",-1)),t[13]||(t[13]=n("p",{class:"muted small"},[b(" If you chose your own backup folder, pick the dated folder inside it (the one with a "),n("code",null,"journal.json"),b("). ")],-1)),n("form",{class:"pathrow",onSubmit:t[2]||(t[2]=Xe(o=>e.openCustom(),["prevent"]))},[T(n("input",{"onUpdate:modelValue":t[0]||(t[0]=o=>e.customDir=o),class:"input",spellcheck:"false",placeholder:"Path to the dated backup folder"},null,512),[[Y,e.customDir]]),n("button",{class:"btn",type:"button",onClick:t[1]||(t[1]=o=>e.browsing=!0)},[U(e.Icon,{name:"folder",size:16}),t[11]||(t[11]=b(" Browse ",-1))]),n("button",{class:"btn btn--primary",type:"submit",disabled:e.customDir.trim()===""}," Open ",8,bt)],32)])])),e.browsing?(s(),$(e.FolderBrowser,{key:2,start:i.cwd,mode:"folder",title:"Choose the backup folder",onClose:t[8]||(t[8]=o=>e.browsing=!1),onConfirm:e.openCustom},null,8,["start"])):d("v-if",!0)])}const Lt=ne(st,[["render",qt],["__scopeId","data-v-276a3888"],["__file","C:/work/NPM/devtoolz/ui/src/modules/image-batch/BackupsView.vue"]]),be=Symbol("image-batch-navigate"),Ee=Symbol("image-batch-project"),qe={cwd:"",name:"this project",home:""};function Pt(f,t){const i=f.split(/[\\/]/).filter(Boolean);return{cwd:f,home:t,name:i[i.length-1]??f}}const Rt=oe({__name:"SharpenSettings",props:tt({options:{type:Object,required:!0},manage:{type:Boolean,required:!1}},{modelValue:{type:Object,required:!0},modelModifiers:{}}),emits:["update:modelValue"],setup(f,{expose:t}){t();const i=f,e=pe(be,()=>{}),m=et(f,"modelValue"),g=c([]),o=c(!1),r=E(()=>g.value.filter(O=>!O.error)),y=E(()=>g.value.find(O=>O.name===m.value.preset));function S(O){const k=O.fields??{};return Object.entries(k).map(([v,C])=>`${v} ${C}`).join(", ")}function M(O){m.value={...m.value,mode:O},O==="preset"&&!m.value.preset&&r.value[0]&&(m.value={...m.value,mode:O,preset:r.value[0].name})}function A(O,k){m.value={...m.value,fine:{...m.value.fine,[O]:k}}}function B(O){const k=i.options.sharpen.fine.find(v=>v.key===O);return k?`${k.range[0]}–${k.range[1]}`:""}ce(async()=>{try{g.value=await F.get("/api/image-batch/sharpen-presets")}catch{g.value=[]}});const z={props:i,navigate:e,state:m,presets:g,fineOpen:o,usable:r,chosen:y,describe:S,setMode:M,setFine:A,rangeText:B,UiSegmented:he};return Object.defineProperty(z,"__isScriptSetup",{enumerable:!1,value:!0}),z}}),Ft={class:"sharpen"},Jt={key:0,class:"grid"},Ht={class:"field"},Wt=["value"],Gt=["value"],Kt={key:1,class:"hint muted"},Qt={class:"grid"},Yt={class:"field"},Zt=["value"],Xt=["value"],$t={class:"field"},eo=["value"],to=["value"],oo={key:0,class:"grid"},no={class:"muted"},so=["value","onInput"];function lo(f,t,i,e,m,g){return s(),l("div",Ft,[U(e.UiSegmented,{"model-value":e.state.mode,label:"Sharpening",options:[{value:"none",label:"None"},{value:"preset",label:"Saved preset"},{value:"custom",label:"Custom"}],"onUpdate:modelValue":e.setMode},null,8,["model-value"]),e.state.mode==="preset"?(s(),l("div",Jt,[n("label",Ht,[t[5]||(t[5]=n("span",null,"Preset",-1)),n("select",{class:"select",value:e.state.preset,onChange:t[0]||(t[0]=o=>e.state={...e.state,preset:o.target.value})},[(s(!0),l(p,null,N(e.usable,o=>(s(),l("option",{key:o.name,value:o.name},a(o.name)+" · "+a(o.scope),9,Gt))),128))],40,Wt)]),i.manage?(s(),l("button",{key:0,class:"link",onClick:t[1]||(t[1]=o=>e.navigate("sharpen"))},"Manage presets")):d("v-if",!0),e.chosen?(s(),l("p",Kt,[e.chosen.description?(s(),l(p,{key:0},[b(a(e.chosen.description)+" — ",1)],64)):d("v-if",!0),b(" "+a(e.describe(e.chosen)),1)])):d("v-if",!0)])):d("v-if",!0),e.state.mode==="custom"?(s(),l(p,{key:1},[n("div",Qt,[n("label",Yt,[t[6]||(t[6]=n("span",null,"Sharpen for",-1)),n("select",{class:"select",value:e.state.for,onChange:t[2]||(t[2]=o=>e.state={...e.state,for:o.target.value})},[(s(!0),l(p,null,N(i.options.sharpen.targets,o=>(s(),l("option",{key:o,value:o},a(o),9,Xt))),128))],40,Zt)]),n("label",$t,[t[7]||(t[7]=n("span",null,"Amount",-1)),n("select",{class:"select",value:e.state.amount,onChange:t[3]||(t[3]=o=>e.state={...e.state,amount:o.target.value})},[(s(!0),l(p,null,N(i.options.sharpen.amounts,o=>(s(),l("option",{key:o,value:o},a(o),9,to))),128))],40,eo)])]),n("button",{class:"link",onClick:t[4]||(t[4]=o=>e.fineOpen=!e.fineOpen)},a(e.fineOpen?"Hide":"Show")+" fine settings ",1),e.fineOpen?(s(),l("div",oo,[(s(!0),l(p,null,N(i.options.sharpen.fine,o=>(s(),l("label",{key:o.key,class:"field"},[n("span",null,[b(a(o.key)+" ",1),n("small",no,"("+a(e.rangeText(o.key))+")",1)]),n("input",{class:"input",inputmode:"decimal",placeholder:"table value",value:e.state.fine[o.key],onInput:r=>e.setFine(o.key,r.target.value)},null,40,so)]))),128))])):d("v-if",!0)],64)):d("v-if",!0)])}const Le=ne(Rt,[["render",lo],["__scopeId","data-v-1a683036"],["__file","C:/work/NPM/devtoolz/ui/src/modules/image-batch/SharpenSettings.vue"]]);function Pe(){return{mode:"none",preset:"",for:"screen",amount:"standard",fine:{radius:"",flat:"",jagged:"",threshold:""}}}function io(f){if(f.mode==="none")return;if(f.mode==="preset")return f.preset?{preset:f.preset}:void 0;const t={for:f.for,amount:f.amount};for(const[i,e]of Object.entries(f.fine))e.trim()!==""&&(t[i]=Number(e));return t}const Re=["widths","heights","size","longEdge","shortEdge","megapixels","percent"],ao={widths:[800,1600],heights:[600],size:"1920x1080",longEdge:[1600],shortEdge:[1080],megapixels:[2],percent:[50]};function ro(f,t,i){const e={...f};return i===void 0||i===""||Array.isArray(i)&&i.length===0||typeof i=="number"&&Number.isNaN(i)?delete e[t]:e[t]=i,e}function co(f){for(const t of Re)if(f[t]!==void 0)return t;return"original"}function uo(f,t){const i={...f};for(const e of Re)delete i[e];return delete i.matchOrientation,t!=="original"&&(i[t]=ao[t]),i}function fo(f,t){if(t==="original")return"";const i=f[t];return Array.isArray(i)?i.join(", "):String(i??"")}function vo(f){const t=f.split(/[,\s]+/).filter(Boolean);if(t.length===0)return[];const i=t.map(Number);return i.some(e=>!Number.isFinite(e))?void 0:i}function Te(f){const t=Pe();if(f==null)return{state:t,lossy:!1};if(typeof f=="string")return{state:{...t,mode:"preset",preset:f},lossy:!1};if(typeof f!="object"||Array.isArray(f))return{state:t,lossy:!0};const i=f;if(typeof i.preset=="string")return Object.keys(i).filter(g=>g!=="preset").length===0?{state:{...t,mode:"preset",preset:i.preset},lossy:!1}:{state:{...t,mode:"preset",preset:i.preset},lossy:!0};const e={...t,mode:"custom"};typeof i.for=="string"&&(e.for=i.for),typeof i.amount=="string"&&(e.amount=i.amount);for(const m of["radius","flat","jagged","threshold"])i[m]!==void 0&&(e.fine[m]=String(i[m]));return{state:e,lossy:!1}}function Ae(f){if(f.mode==="none")return;if(f.mode==="preset")return f.preset||void 0;const t={for:f.for,amount:f.amount};for(const[i,e]of Object.entries(f.fine))e.trim()!==""&&(t[i]=Number(e));return t}function mo(){return{name:"New config",outputs:[{id:"responsive",widths:[400,800,1200],formats:["webp","jpg"],quality:"high"}]}}function po(f){return{id:`recipe-${f}`,widths:[800],formats:["webp"],quality:"high"}}const go=oe({__name:"RecipeForm",props:{modelValue:{type:Object,required:!0},options:{type:Object,required:!0},presetNames:{type:Array,required:!1},isDefaults:{type:Boolean,required:!1}},emits:["update:modelValue"],setup(f,{expose:t,emit:i}){t();const e=f,m=i,g={original:"Keep the original size",widths:"By width (px)",heights:"By height (px)",size:"Fit into a box",longEdge:"By the long side (px)",shortEdge:"By the short side (px)",megapixels:"By area (megapixels)",percent:"By percentage"},o=[{key:"metadata",label:"Metadata",options:["strip","keep","keep-icc"]},{key:"rotate",label:"Rotate (degrees)",options:["90","180","270"]}],r=[{key:"withoutEnlargement",label:"Never enlarge"},{key:"autoOrient",label:"Turn by EXIF orientation"},{key:"grayscale",label:"Grayscale"},{key:"flip",label:"Flip vertically"},{key:"flop",label:"Mirror horizontally"}],y=c(""),S=c(!1),M=c(!1),A=c(!1),B=c(Te(e.modelValue.sharpen).state),z=E(()=>co(e.modelValue)),O=E(()=>Array.isArray(e.modelValue.formats)?e.modelValue.formats:void 0),k=E(()=>e.modelValue.formats!==void 0&&O.value===void 0),v=E(()=>e.modelValue.quality),C=E(()=>v.value!==void 0&&typeof v.value=="object"),j=E(()=>{const u=v.value;return u===void 0?"":typeof u=="number"?"custom":String(u)}),R=E(()=>typeof e.modelValue.name=="string"?e.modelValue.name:""),P=E(()=>e.modelValue.maxBytes===void 0?"":String(e.modelValue.maxBytes)),Z=E(()=>{const u=e.modelValue.sharpen;return u!==void 0&&typeof u!="string"&&typeof u!="object"});function D(u,_){m("update:modelValue",ro(e.modelValue,u,_))}function K(){y.value=fo(e.modelValue,z.value),S.value=!1}ge(z,K,{immediate:!0}),ge(()=>e.modelValue.sharpen,u=>{const _=Te(u);A.value=_.lossy,JSON.stringify(Ae(B.value))!==JSON.stringify(u)&&(B.value=_.state)},{immediate:!0});function q(u){m("update:modelValue",uo(e.modelValue,u.target.value))}function w(u){y.value=u;const _=vo(u);S.value=_===void 0,_&&_.length>0&&z.value!=="original"&&z.value!=="size"&&D(z.value,_)}function I(u){const _=O.value??[];D("formats",_.includes(u)?_.filter(X=>X!==u):[..._,u])}function J(u){u===""?D("quality",void 0):u==="custom"?D("quality",82):D("quality",u)}function H(u){const _=u.trim();_===""?D("maxBytes",void 0):D("maxBytes",/^\d+$/.test(_)?Number(_):_)}function re(u){B.value=u,D("sharpen",Ae(u))}function ee(u){const _=e.modelValue[u];return _===void 0?"":String(_)}function Q(u,_){D(u,_===""?void 0:_==="true")}function de(u){D("name",(R.value||"{dir}/{name}")+"{"+u+"}")}function W(u){return"{"+u+"}"}const G={props:e,emit:m,METHOD_LABELS:g,ADVANCED_SELECTS:o,ADVANCED_FLAGS:r,draft:y,draftError:S,advancedOpen:M,sharpenLossy:A,sharpenState:B,method:z,formatsList:O,formatsComplex:k,qualityValue:v,qualityComplex:C,qualityChoice:j,template:R,maxBytesText:P,sharpenMissing:Z,update:D,syncDraft:K,changeMethod:q,changeValues:w,toggleFormat:I,changeQuality:J,changeMaxBytes:H,changeSharpen:re,triState:ee,setTriState:Q,insertToken:de,tokenLabel:W,SharpenSettings:Le};return Object.defineProperty(G,"__isScriptSetup",{enumerable:!1,value:!0}),G}}),ho={class:"recipe"},bo={key:0,class:"grid"},_o={class:"field"},yo=["value"],ko={key:0,class:"field"},wo=["value"],So=["value"],Co={class:"group"},Vo={class:"grid"},xo={class:"field"},Oo=["value"],Eo=["value"],zo={key:0,class:"field"},Bo=["value"],jo={key:1,class:"field"},No=["value"],To={key:2,class:"field"},Ao=["value"],Io=["value"],Uo={key:0,class:"check"},Mo=["checked"],Do={class:"group"},qo={key:0,class:"notice notice--warn"},Lo={key:1,class:"pills"},Po=["checked","onChange"],Ro={key:0,class:"muted small"},Fo={class:"grid"},Jo={key:0,class:"field"},Ho=["value"],Wo=["value"],Go={key:1,class:"field"},Ko=["value"],Qo={key:2,class:"notice notice--warn"},Yo={class:"field"},Zo=["value"],Xo={class:"group"},$o=["value","placeholder"],en={class:"pills"},tn=["onClick"],on={class:"group"},nn={key:0,class:"notice notice--warn"},sn={class:"group"},ln={key:0,class:"grid"},an=["value","onChange"],rn=["value"],dn=["value","onChange"],cn={class:"field"},un=["value"],fn={class:"field"},vn=["value"];function mn(f,t,i,e,m,g){return s(),l("div",ho,[i.isDefaults?d("v-if",!0):(s(),l("div",bo,[n("label",_o,[t[13]||(t[13]=n("span",null,"Recipe name",-1)),n("input",{class:"input",spellcheck:"false",value:String(i.modelValue.id??""),onInput:t[0]||(t[0]=o=>e.update("id",o.target.value))},null,40,yo)]),i.presetNames&&i.presetNames.length?(s(),l("label",ko,[t[15]||(t[15]=n("span",null,"Based on preset",-1)),n("select",{class:"select",value:String(i.modelValue.preset??""),onChange:t[1]||(t[1]=o=>e.update("preset",o.target.value))},[t[14]||(t[14]=n("option",{value:""},"None",-1)),(s(!0),l(p,null,N(i.presetNames,o=>(s(),l("option",{key:o,value:o},a(o),9,So))),128))],40,wo)])):d("v-if",!0)])),n("div",Co,[t[21]||(t[21]=n("h4",null,"Size",-1)),n("div",Vo,[n("label",xo,[t[16]||(t[16]=n("span",null,"Method",-1)),n("select",{class:"select",value:e.method,onChange:e.changeMethod},[(s(!0),l(p,null,N(i.options.sizeMethods,o=>(s(),l("option",{key:o,value:o},a(e.METHOD_LABELS[o]),9,Eo))),128))],40,Oo)]),e.method==="size"?(s(),l("label",zo,[t[17]||(t[17]=n("span",null,"Box (width × height)",-1)),n("input",{class:"input",spellcheck:"false",value:String(i.modelValue.size??""),onInput:t[2]||(t[2]=o=>e.update("size",o.target.value))},null,40,Bo)])):e.method!=="original"?(s(),l("label",jo,[t[18]||(t[18]=n("span",null,"Values (comma-separated)",-1)),n("input",{class:te(["input",{"input--bad":e.draftError}]),spellcheck:"false",value:e.draft,onInput:t[3]||(t[3]=o=>e.changeValues(o.target.value))},null,42,No)])):d("v-if",!0),e.method==="size"?(s(),l("label",To,[t[19]||(t[19]=n("span",null,"How it fills the box",-1)),n("select",{class:"select",value:String(i.modelValue.fit??"inside"),onChange:t[4]||(t[4]=o=>e.update("fit",o.target.value))},[(s(!0),l(p,null,N(i.options.fitModes,o=>(s(),l("option",{key:o,value:o},a(o),9,Io))),128))],40,Ao)])):d("v-if",!0)]),e.method==="size"?(s(),l("label",Uo,[n("input",{type:"checkbox",checked:i.modelValue.matchOrientation===!0,onChange:t[5]||(t[5]=o=>e.update("matchOrientation",o.target.checked||void 0))},null,40,Mo),t[20]||(t[20]=b(" Turn the box around for portrait images ",-1))])):d("v-if",!0)]),n("div",Do,[t[27]||(t[27]=n("h4",null,"Formats and quality",-1)),e.formatsComplex?(s(),l("p",qo," The formats of this recipe are set in a form the editor cannot show. Use the JSON tab. ")):(s(),l("div",Lo,[(s(!0),l(p,null,N(i.options.formats,o=>(s(),l("label",{key:o,class:te(["pill",{"pill--on":e.formatsList?.includes(o)}])},[n("input",{type:"checkbox",checked:e.formatsList?.includes(o),onChange:r=>e.toggleFormat(o)},null,40,Po),b(" "+a(o),1)],2))),128)),e.formatsList?d("v-if",!0):(s(),l("span",Ro,"none chosen — inherited from the defaults"))])),n("div",Fo,[e.qualityComplex?d("v-if",!0):(s(),l("label",Jo,[t[24]||(t[24]=n("span",null,"Quality",-1)),n("select",{class:"select",value:e.qualityChoice,onChange:t[6]||(t[6]=o=>e.changeQuality(o.target.value))},[t[22]||(t[22]=n("option",{value:""},"Default (high)",-1)),(s(!0),l(p,null,N(i.options.qualityLevels,o=>(s(),l("option",{key:o,value:o},a(o),9,Wo))),128)),t[23]||(t[23]=n("option",{value:"custom"},"A number…",-1))],40,Ho)])),e.qualityChoice==="custom"?(s(),l("label",Go,[t[25]||(t[25]=n("span",null,"Quality (1–100)",-1)),n("input",{class:"input",inputmode:"numeric",value:String(i.modelValue.quality),onInput:t[7]||(t[7]=o=>e.update("quality",Number(o.target.value)))},null,40,Ko)])):d("v-if",!0),e.qualityComplex?(s(),l("p",Qo," Quality is set per format here. Use the JSON tab to change it. ")):d("v-if",!0),n("label",Yo,[t[26]||(t[26]=n("span",null,"Largest file size",-1)),n("input",{class:"input",spellcheck:"false",placeholder:"e.g. 200KB (optional)",value:e.maxBytesText,onInput:t[8]||(t[8]=o=>e.changeMaxBytes(o.target.value))},null,40,Zo)])])]),n("div",Xo,[t[28]||(t[28]=n("h4",null,"File names",-1)),n("input",{class:"input",spellcheck:"false",value:e.template,placeholder:i.options.defaultTemplates[e.method],"aria-label":"File name template",onInput:t[9]||(t[9]=o=>e.update("name",o.target.value))},null,40,$o),n("div",en,[(s(!0),l(p,null,N(i.options.templateVariables,o=>(s(),l("button",{key:o,class:"pill pill--button",onClick:r=>e.insertToken(o)},a(e.tokenLabel(o)),9,tn))),128))])]),n("div",on,[t[29]||(t[29]=n("h4",null,"Sharpening",-1)),e.sharpenLossy||e.sharpenMissing?(s(),l("p",nn," This sharpening combines a preset with extra values. Use the JSON tab to edit it. ")):(s(),$(e.SharpenSettings,{key:1,"model-value":e.sharpenState,options:i.options,"onUpdate:modelValue":e.changeSharpen},null,8,["model-value","options"]))]),n("div",sn,[n("button",{class:"link",onClick:t[10]||(t[10]=o=>e.advancedOpen=!e.advancedOpen)},a(e.advancedOpen?"Hide":"Show")+" advanced settings ",1),e.advancedOpen?(s(),l("div",ln,[(s(),l(p,null,N(e.ADVANCED_SELECTS,o=>n("label",{key:o.key,class:"field"},[n("span",null,a(o.label),1),n("select",{class:"select",value:o.key==="rotate"?String(i.modelValue.rotate??""):String(i.modelValue[o.key]??""),onChange:r=>e.update(o.key,o.key==="rotate"&&r.target.value?Number(r.target.value):r.target.value)},[t[30]||(t[30]=n("option",{value:""},"Default",-1)),(s(!0),l(p,null,N(o.options,r=>(s(),l("option",{key:r,value:r},a(r),9,rn))),128))],40,an)])),64)),(s(),l(p,null,N(e.ADVANCED_FLAGS,o=>n("label",{key:o.key,class:"field"},[n("span",null,a(o.label),1),n("select",{class:"select",value:e.triState(o.key),onChange:r=>e.setTriState(o.key,r.target.value)},[...t[31]||(t[31]=[n("option",{value:""},"Default",-1),n("option",{value:"true"},"Yes",-1),n("option",{value:"false"},"No",-1)])],40,dn)])),64)),n("label",cn,[t[32]||(t[32]=n("span",null,"Blur (sigma)",-1)),n("input",{class:"input",inputmode:"decimal",value:i.modelValue.blur===void 0?"":String(i.modelValue.blur),onInput:t[11]||(t[11]=o=>e.update("blur",o.target.value===""?void 0:Number(o.target.value)))},null,40,un)]),n("label",fn,[t[33]||(t[33]=n("span",null,"Background (#rrggbb)",-1)),n("input",{class:"input",spellcheck:"false",value:String(i.modelValue.background??""),onInput:t[12]||(t[12]=o=>e.update("background",o.target.value))},null,40,vn)])])):d("v-if",!0)])])}const pn=ne(go,[["render",mn],["__scopeId","data-v-92a49f1e"],["__file","C:/work/NPM/devtoolz/ui/src/modules/image-batch/RecipeForm.vue"]]),gn=oe({__name:"ConfigEditor",props:{options:{type:Object,required:!0},initial:{type:null,required:!1},copyOf:{type:null,required:!1}},emits:["saved","cancel"],setup(f,{expose:t,emit:i}){t();const e=f,m=i,g=pe(Ee,qe),o=c(e.initial!==void 0),r=c(e.copyOf?structuredClone(e.copyOf.raw):mo()),y=c(e.initial?e.initial.name:e.copyOf?`${e.copyOf.name}-copy`:""),S=c(e.initial?.scope??"project"),M=c("form"),A=c(""),B=c(""),z=c(),O=c(""),k=c(!1),v=c(0);let C;const j=E(()=>Array.isArray(r.value.outputs)?r.value.outputs:[]),R=E(()=>r.value.defaults&&typeof r.value.defaults=="object"?r.value.defaults:{}),P=E(()=>r.value.presets&&typeof r.value.presets=="object"?Object.keys(r.value.presets):[]),Z=E(()=>{const h=[];return P.value.length&&h.push(`${P.value.length} preset(s)`),Array.isArray(r.value.match)&&r.value.match.length&&h.push(`${r.value.match.length} rule(s)`),r.value.placeholders&&h.push("placeholders"),h}),D=E(()=>(z.value?.lines??[]).join(`
|
|
2
|
+
`)),K=E(()=>!k.value&&y.value.trim()!==""&&z.value?.ok===!0&&B.value==="");function q(h){r.value=h}function w(h,V){const L={...r.value};V.trim()===""?delete L[h]:L[h]=V,q(L)}function I(h){const V={...r.value};Object.keys(h).length===0?delete V.defaults:V.defaults=h,q(V)}function J(h,V){const L=[...j.value];L[h]=V,q({...r.value,outputs:L})}function H(){q({...r.value,outputs:[...j.value,po(j.value.length+1)]}),v.value=j.value.length}function re(h){q({...r.value,outputs:j.value.filter((V,L)=>L!==h)}),v.value=Math.max(0,v.value-1)}function ee(h){const V=structuredClone(j.value[h]??{});typeof V.id=="string"&&(V.id=`${V.id}-copy`);const L=[...j.value];L.splice(h+1,0,V),q({...r.value,outputs:L}),v.value=h+1}function Q(h,V){const L=h+V;if(L<0||L>=j.value.length)return;const ve=[...j.value],[_e]=ve.splice(h,1);ve.splice(L,0,_e),q({...r.value,outputs:ve}),v.value=L}function de(h,V){return typeof h.id=="string"&&h.id?h.id:`Recipe ${V+1}`}function W(h){const V=[];for(const L of["widths","heights","longEdge","shortEdge","megapixels","percent"])Array.isArray(h[L])&&V.push(`${L} ${h[L].join(", ")}`);return typeof h.size=="string"&&V.push(`box ${h.size}`),Array.isArray(h.formats)&&V.push(h.formats.join("/")),V.join(" · ")}function G(h){A.value=h;try{const V=JSON.parse(h);if(V===null||typeof V!="object"||Array.isArray(V)){B.value="A config is a JSON object.";return}B.value="",r.value=V}catch(V){B.value=V instanceof Error?V.message:String(V)}}function u(h){if(h==="json"){A.value=JSON.stringify(r.value,null,2),B.value="",M.value="json";return}B.value||(M.value="form")}async function _(){try{z.value=await F.post("/api/image-batch/config/validate",{raw:r.value})}catch(h){z.value={ok:!1,error:h instanceof Error?h.message:String(h)}}}ge(r,()=>{clearTimeout(C),C=setTimeout(()=>{_()},350)},{deep:!0});async function X(h=!1){k.value=!0,O.value="";try{await F.post("/api/image-batch/config/save",{name:y.value,scope:S.value,raw:r.value,overwrite:h,...e.initial?{originalName:e.initial.name,originalScope:e.initial.scope}:{}}),m("saved",y.value)}catch(V){if(V instanceof De&&V.status===409&&V.body.exists===!0){if(window.confirm(`${V.message}. Replace it?`)){await X(!0);return}}else O.value=V instanceof Error?V.message:String(V)}finally{k.value=!1}}ce(async()=>{if(e.initial)try{const h=await F.get(`/api/image-batch/config?name=${encodeURIComponent(e.initial.name)}&scope=${e.initial.scope}`);r.value=h.raw}catch(h){O.value=h instanceof Error?h.message:String(h)}finally{o.value=!1}_()}),xe(()=>clearTimeout(C));const se={props:e,emit:m,project:g,loading:o,raw:r,name:y,scope:S,tab:M,jsonText:A,jsonError:B,check:z,failure:O,saving:k,openRecipe:v,get timer(){return C},set timer(h){C=h},outputs:j,defaults:R,presetNames:P,extras:Z,checkText:D,canSave:K,setRaw:q,setTitle:w,setDefaults:I,setOutput:J,addRecipe:H,removeRecipe:re,duplicateRecipe:ee,moveRecipe:Q,recipeTitle:de,recipeSummary:W,onJson:G,switchTab:u,validate:_,save:X,Icon:ue,UiSegmented:he,RecipeForm:pn};return Object.defineProperty(se,"__isScriptSetup",{enumerable:!1,value:!0}),se}}),hn={class:"card block"},bn={class:"head"},_n={key:0,class:"muted"},yn={class:"grid"},kn={class:"field"},wn={class:"field"},Sn={value:"project"},Cn={class:"field"},Vn=["value"],xn={class:"field"},On=["value"],En={key:0,class:"notice"},zn={class:"panel"},Bn={class:"panel__body"},jn={class:"recipes"},Nn={class:"panel__head"},Tn=["onClick"],An={class:"muted small"},In={class:"panel__actions"},Un=["disabled","onClick"],Mn=["disabled","onClick"],Dn=["onClick"],qn=["onClick"],Ln={key:0,class:"panel__body"},Pn=["value"],Rn={key:0,class:"notice notice--error"},Fn={key:0,class:"lines"},Jn={key:3,class:"notice notice--error"},Hn={class:"actions"},Wn=["disabled"];function Gn(f,t,i,e,m,g){return s(),l("section",hn,[n("div",bn,[n("h2",null,a(i.initial?`Edit ${i.initial.name}`:i.copyOf?"Copy of a config":"New config"),1),n("button",{class:"btn btn--ghost",onClick:t[0]||(t[0]=o=>e.emit("cancel"))},[U(e.Icon,{name:"close",size:16}),t[8]||(t[8]=b(" Close ",-1))])]),e.loading?(s(),l("p",_n,"Loading…")):(s(),l(p,{key:1},[n("div",yn,[n("label",kn,[t[9]||(t[9]=n("span",null,"File name",-1)),T(n("input",{"onUpdate:modelValue":t[1]||(t[1]=o=>e.name=o),class:"input",spellcheck:"false",placeholder:"web"},null,512),[[Y,e.name]])]),n("label",wn,[t[11]||(t[11]=n("span",null,"Where to keep it",-1)),T(n("select",{"onUpdate:modelValue":t[2]||(t[2]=o=>e.scope=o),class:"select"},[n("option",Sn,"This project ("+a(e.project.name)+")",1),t[10]||(t[10]=n("option",{value:"global"},"All projects (your home folder)",-1))],512),[[ae,e.scope]])]),n("label",Cn,[t[12]||(t[12]=n("span",null,"Title",-1)),n("input",{class:"input",value:String(e.raw.name??""),onInput:t[3]||(t[3]=o=>e.setTitle("name",o.target.value))},null,40,Vn)]),n("label",xn,[t[13]||(t[13]=n("span",null,"Description",-1)),n("input",{class:"input",value:String(e.raw.description??""),onInput:t[4]||(t[4]=o=>e.setTitle("description",o.target.value))},null,40,On)])]),U(e.UiSegmented,{"model-value":e.tab,label:"Editor mode",options:[{value:"form",label:"Form"},{value:"json",label:"JSON"}],"onUpdate:modelValue":e.switchTab},null,8,["model-value"]),e.tab==="form"?(s(),l(p,{key:0},[e.extras.length?(s(),l("p",En," This config also has "+a(e.extras.join(", "))+". They are kept as they are; edit them in the JSON tab. ",1)):d("v-if",!0),n("details",zn,[t[14]||(t[14]=n("summary",null,"Defaults for every recipe",-1)),n("div",Bn,[U(e.RecipeForm,{"model-value":e.defaults,options:i.options,"preset-names":e.presetNames,"is-defaults":"","onUpdate:modelValue":e.setDefaults},null,8,["model-value","options","preset-names"])])]),n("div",jn,[(s(!0),l(p,null,N(e.outputs,(o,r)=>(s(),l("div",{key:r,class:te(["panel",{"panel--open":e.openRecipe===r}])},[n("div",Nn,[n("button",{class:"panel__title",onClick:y=>e.openRecipe=e.openRecipe===r?-1:r},[n("strong",null,a(e.recipeTitle(o,r)),1),n("span",An,a(e.recipeSummary(o)),1)],8,Tn),n("div",In,[n("button",{class:"btn btn--ghost btn--small",disabled:r===0,"aria-label":"Move up",onClick:y=>e.moveRecipe(r,-1)},[U(e.Icon,{name:"up",size:14})],8,Un),n("button",{class:"btn btn--ghost btn--small",disabled:r===e.outputs.length-1,"aria-label":"Move down",onClick:y=>e.moveRecipe(r,1)},[U(e.Icon,{name:"down",size:14})],8,Mn),n("button",{class:"btn btn--ghost btn--small","aria-label":"Duplicate recipe",onClick:y=>e.duplicateRecipe(r)},[U(e.Icon,{name:"copy",size:14})],8,Dn),n("button",{class:"btn btn--ghost btn--small btn--danger","aria-label":"Remove recipe",onClick:y=>e.removeRecipe(r)},[U(e.Icon,{name:"close",size:14})],8,qn)])]),e.openRecipe===r?(s(),l("div",Ln,[U(e.RecipeForm,{"model-value":o,options:i.options,"preset-names":e.presetNames,"onUpdate:modelValue":y=>e.setOutput(r,y)},null,8,["model-value","options","preset-names","onUpdate:modelValue"])])):d("v-if",!0)],2))),128))]),n("button",{class:"btn",onClick:e.addRecipe},[U(e.Icon,{name:"plus",size:16}),t[15]||(t[15]=b(" Add a recipe",-1))])],64)):(s(),l(p,{key:1},[n("textarea",{class:"json",spellcheck:"false",value:e.jsonText,"aria-label":"Config JSON",onInput:t[5]||(t[5]=o=>e.onJson(o.target.value))},null,40,Pn),e.jsonError?(s(),l("p",Rn,a(e.jsonError),1)):d("v-if",!0)],64)),e.check?(s(),l("div",{key:2,class:te(["check-panel",e.check.ok?"check-panel--ok":"check-panel--bad"]),role:"status"},[e.check.ok?(s(),l(p,{key:0},[t[16]||(t[16]=n("strong",null,"The config is valid.",-1)),e.check.lines?.length?(s(),l("pre",Fn,a(e.checkText),1)):d("v-if",!0)],64)):(s(),l(p,{key:1},[b(a(e.check.error),1)],64))],2)):d("v-if",!0),e.failure?(s(),l("p",Jn,a(e.failure),1)):d("v-if",!0),n("div",Hn,[n("button",{class:"btn btn--primary",disabled:!e.canSave,onClick:t[6]||(t[6]=o=>e.save(!1))},[U(e.Icon,{name:"save",size:15}),t[17]||(t[17]=b(" Save config ",-1))],8,Wn),n("button",{class:"btn",onClick:t[7]||(t[7]=o=>e.emit("cancel"))},"Cancel")])],64))])}const Kn=ne(gn,[["render",Gn],["__scopeId","data-v-6b6acd65"],["__file","C:/work/NPM/devtoolz/ui/src/modules/image-batch/ConfigEditor.vue"]]),Qn=oe({__name:"ConfigsView",props:{options:{type:Object,required:!0}},setup(f,{expose:t}){t();const i=c([]),e=c(""),m=c(""),g=c("list"),o=c(),r=c();async function y(){try{i.value=await F.get("/api/image-batch/configs")}catch(k){e.value=k instanceof Error?k.message:String(k)}}function S(){o.value=void 0,r.value=void 0,g.value="edit"}function M(k){o.value=k,r.value=void 0,g.value="edit"}async function A(k){try{const v=await F.get(`/api/image-batch/config?name=${encodeURIComponent(k.name)}&scope=${k.scope}`);o.value=void 0,r.value={name:k.name,raw:v.raw},g.value="edit"}catch(v){e.value=v instanceof Error?v.message:String(v)}}async function B(k){if(window.confirm(`Delete the config “${k.name}”? A .bak copy is kept next to it.`))try{await F.post("/api/image-batch/config/delete",{name:k.name,scope:k.scope}),m.value=`Deleted ${k.name}.`,await y()}catch(v){e.value=v instanceof Error?v.message:String(v)}}async function z(k){g.value="list",m.value=`Saved ${k}.`,await y()}ce(y);const O={rows:i,failure:e,note:m,mode:g,editing:o,copying:r,load:y,create:S,edit:M,duplicate:A,remove:B,saved:z,Icon:ue,ConfigEditor:Kn};return Object.defineProperty(O,"__isScriptSetup",{enumerable:!1,value:!0}),O}}),Yn={class:"view"},Zn={key:1,class:"card block"},Xn={class:"head"},$n={key:0,class:"notice"},es={key:1,class:"notice notice--error"},ts={key:2,class:"muted"},os={class:"list"},ns={class:"item__main"},ss={class:"item__title"},ls={class:"tag"},is={key:0,class:"tag"},as={key:0,class:"item__error"},rs={key:1,class:"muted"},ds=["title"],cs={class:"item__actions"},us=["onClick"],fs=["onClick"],vs=["onClick"];function ms(f,t,i,e,m,g){return s(),l("div",Yn,[e.mode==="edit"?(s(),$(e.ConfigEditor,{key:0,options:i.options,initial:e.editing?{name:e.editing.name,scope:e.editing.scope}:void 0,"copy-of":e.copying,onSaved:e.saved,onCancel:t[0]||(t[0]=o=>e.mode="list")},null,8,["options","initial","copy-of"])):(s(),l("section",Zn,[n("div",Xn,[t[2]||(t[2]=n("div",null,[n("h2",null,"Configs"),n("p",{class:"muted"}," A config is a reusable set of rules: sizes, formats, quality, names, sharpening. Apply it to any folder from the Convert tab. ")],-1)),n("button",{class:"btn btn--primary",onClick:e.create},[U(e.Icon,{name:"plus",size:16}),t[1]||(t[1]=b(" New config ",-1))])]),e.note?(s(),l("p",$n,a(e.note),1)):d("v-if",!0),e.failure?(s(),l("p",es,a(e.failure),1)):d("v-if",!0),e.rows.length===0&&!e.failure?(s(),l("p",ts," No configs yet. Create the first one, or use quick settings on the Convert tab. ")):d("v-if",!0),n("ul",os,[(s(!0),l(p,null,N(e.rows,o=>(s(),l("li",{key:o.scope+o.name+o.path,class:"item"},[n("div",ns,[n("div",ss,[n("strong",null,a(o.name),1),n("span",ls,a(o.scope),1),o.kind!=="json"?(s(),l("span",is,"."+a(o.kind),1)):d("v-if",!0)]),o.error?(s(),l("p",as,a(o.error),1)):(s(),l("p",rs,[o.title?(s(),l(p,{key:0},[b(a(o.title)+" — ",1)],64)):d("v-if",!0),b(" "+a(o.recipes)+" recipe"+a(o.recipes===1?"":"s")+" ",1),o.rules?(s(),l(p,{key:1},[b(", "+a(o.rules)+" rule"+a(o.rules===1?"":"s"),1)],64)):d("v-if",!0),o.description?(s(),l(p,{key:2},[b(" · "+a(o.description),1)],64)):d("v-if",!0)])),n("code",{class:"item__path",title:o.path},a(o.path),9,ds)]),n("div",cs,[o.editable?(s(),l("button",{key:0,class:"btn btn--small",onClick:r=>e.edit(o)},"Edit",8,us)):d("v-if",!0),o.editable&&!o.error?(s(),l("button",{key:1,class:"btn btn--small",onClick:r=>e.duplicate(o)}," Duplicate ",8,fs)):d("v-if",!0),n("button",{class:"btn btn--small btn--danger",onClick:r=>e.remove(o)},"Delete",8,vs)])]))),128))])]))])}const ps=ne(Qn,[["render",ms],["__scopeId","data-v-2e26c039"],["__file","C:/work/NPM/devtoolz/ui/src/modules/image-batch/ConfigsView.vue"]]),Ie=30,gs=oe({__name:"BatchResults",props:{report:{type:Object,required:!0}},setup(f,{expose:t}){t();const i=f,e=pe(be,()=>{});function m(){try{i.report.backupDir&&localStorage.setItem("devtoolz-ui.open-backup",i.report.backupDir)}catch{e("backups");return}e("backups")}const g=c(Ie),o={written:"written","up-to-date":"up to date",skipped:"skipped",conflict:"conflict","would-write":"would write","would-overwrite":"would overwrite",replaced:"replaced",kept:"kept original","already-processed":"already processed","would-replace":"would replace","would-keep":"would keep",error:"error"},r=new Set(["written","replaced","up-to-date"]),y=new Set(["error","conflict"]),S=new Set(["written","replaced","up-to-date","skipped","kept"]),M=E(()=>Object.entries(i.report.counts).filter(([,C])=>C>0)),A=E(()=>{const{bytesIn:C,bytesOut:j}=i.report;if(!(i.report.dryRun||C<=0||j<=0))return{bytes:C-j,percent:Math.round((1-j/C)*100)}}),B=E(()=>i.report.results.slice(0,g.value));function z(C){return r.has(C)?"good":y.has(C)?"bad":"neutral"}function O(C){if(C.before===void 0||C.bytes===void 0||C.before<=0)return"";const j=Math.round((C.bytes/C.before-1)*100);return`${j>0?"+":""}${j}%`}function k(C){return!i.report.dryRun&&S.has(C.status)&&C.status!=="skipped"}const v={props:i,navigate:e,openBackup:m,PAGE:Ie,shown:g,LABELS:o,GOOD:r,BAD:y,HAS_OUTPUT:S,counts:M,saved:A,rows:B,tone:z,delta:O,showsOutput:k,get formatBytes(){return Me},get imageUrl(){return Ue}};return Object.defineProperty(v,"__isScriptSetup",{enumerable:!1,value:!0}),v}}),hs={class:"card block"},bs={class:"head"},_s={class:"muted"},ys={class:"chips"},ks={key:0,class:"chip"},ws={key:1,class:"chip chip--good"},Ss={key:0,class:"notice"},Cs={key:1,class:"notice"},Vs={key:2,class:"muted small"},xs={key:3,class:"muted small"},Os={key:4,class:"errors"},Es={class:"rows"},zs=["src"],Bs=["src"],js={key:1,class:"row__thumb row__thumb--empty muted"},Ns={class:"row__text"},Ts=["title"],As={class:"muted small"},Is={key:0,class:"small row__message"},Us={class:"row__sizes"},Ms={key:0},Ds={key:1,class:"muted"},qs={key:2},Ls={key:5,class:"more"};function Ps(f,t,i,e,m,g){return s(),l("section",hs,[n("div",bs,[n("h2",null,a(i.report.dryRun?"Plan":"Result"),1),n("span",_s,[b(a(i.report.results.length)+" file"+a(i.report.results.length===1?"":"s")+" ",1),i.report.configLabel?(s(),l(p,{key:0},[b(" · config "+a(i.report.configLabel),1)],64)):d("v-if",!0)])]),n("div",ys,[(s(!0),l(p,null,N(e.counts,([o,r])=>(s(),l("span",{key:o,class:te(["chip",`chip--${e.tone(o)}`])},a(r)+" "+a(e.LABELS[o]),3))),128)),i.report.deduped?(s(),l("span",ks,a(i.report.deduped)+" merged (same result)",1)):d("v-if",!0),e.saved?(s(),l("span",ws,[b(" saved "+a(e.formatBytes(Math.max(e.saved.bytes,0)))+" ",1),e.saved.percent>0?(s(),l(p,{key:0},[b("(−"+a(e.saved.percent)+"%)",1)],64)):d("v-if",!0)])):d("v-if",!0)]),i.report.dryRun?(s(),l("p",Ss," This is a preview: nothing was written. Press “Convert” to do it. ")):d("v-if",!0),i.report.backupDir&&!i.report.dryRun?(s(),l("p",Cs,[t[2]||(t[2]=b(" Originals were copied to ",-1)),n("code",null,a(i.report.backupDir),1),t[3]||(t[3]=b(" first. ",-1)),n("button",{class:"link",onClick:e.openBackup},"View or restore this backup")])):d("v-if",!0),i.report.derived.length?(s(),l("p",Vs,a(i.report.derived.length)+" earlier result"+a(i.report.derived.length===1?" was":"s were")+" not treated as sources. ",1)):d("v-if",!0),i.report.vectors.length?(s(),l("p",xs,a(i.report.vectors.length)+" SVG file"+a(i.report.vectors.length===1?" was":"s were")+" left out of the replacement. ",1)):d("v-if",!0),i.report.failures.length?(s(),l("ul",Os,[(s(!0),l(p,null,N(i.report.failures,o=>(s(),l("li",{key:o.file},[n("code",null,a(o.file),1),b(" — "+a(o.message),1)]))),128))])):d("v-if",!0),n("ul",Es,[(s(!0),l(p,null,N(e.rows,o=>(s(),l("li",{key:`${o.sourceAbs}|${o.outputAbs}|${o.recipe}`,class:"row"},[n("img",{class:"row__thumb",loading:"lazy",alt:"",src:e.imageUrl(o.sourceAbs,120)},null,8,zs),t[4]||(t[4]=n("span",{class:"row__arrow muted"},"→",-1)),e.showsOutput(o)?(s(),l("img",{key:0,class:"row__thumb",loading:"lazy",alt:"",src:e.imageUrl(o.outputAbs,120)},null,8,Bs)):(s(),l("span",js,a(i.report.dryRun?"plan":"—"),1)),n("div",Ns,[n("span",{class:"row__name",title:o.outputAbs},a(o.output),9,Ts),n("span",As,[b(" from "+a(o.source)+" · "+a(o.width)+"×"+a(o.height)+" · "+a(o.format)+" ",1),o.recipe?(s(),l(p,{key:0},[b(" · "+a(o.recipe),1)],64)):d("v-if",!0)]),o.message?(s(),l("span",Is,a(o.message),1)):d("v-if",!0)]),n("div",Us,[o.before!==void 0?(s(),l("span",Ms,a(e.formatBytes(o.before)),1)):d("v-if",!0),o.before!==void 0&&o.bytes!==void 0?(s(),l("span",Ds,"→")):d("v-if",!0),o.bytes!==void 0?(s(),l("strong",qs,a(e.formatBytes(o.bytes)),1)):d("v-if",!0),e.delta(o)?(s(),l("span",{key:3,class:te(["row__delta",{"row__delta--down":e.delta(o).startsWith("-")}])},a(e.delta(o)),3)):d("v-if",!0)]),n("span",{class:te(["chip",`chip--${e.tone(o.status)}`])},a(e.LABELS[o.status]),3)]))),128))]),e.shown<i.report.results.length?(s(),l("div",Ls,[n("button",{class:"btn",onClick:t[0]||(t[0]=o=>e.shown+=e.PAGE)}," Show more ("+a(i.report.results.length-e.shown)+" left) ",1),n("button",{class:"btn",onClick:t[1]||(t[1]=o=>e.shown=i.report.results.length)}," Show all ("+a(i.report.results.length)+") ",1)])):d("v-if",!0)])}const Rs=ne(gs,[["render",Ps],["__scopeId","data-v-7e5d47ea"],["__file","C:/work/NPM/devtoolz/ui/src/modules/image-batch/BatchResults.vue"]]),Fs=oe({__name:"ConvertView",props:{cwd:{type:String,required:!0},options:{type:Object,required:!0}},setup(f,{expose:t}){t();const i=f,e=pe(be,()=>{}),m={original:"Keep the original size",widths:"By width (px)",heights:"By height (px)",size:"Fit into a box",longEdge:"By the long side (px)",shortEdge:"By the short side (px)",megapixels:"By area (megapixels)",percent:"By percentage"},g={original:"",widths:"e.g. 400, 800, 1200 — one file per size",heights:"e.g. 300, 600",size:"",longEdge:"e.g. 1600 — the same for landscape and portrait",shortEdge:"e.g. 1080",megapixels:"e.g. 2, 0.5",percent:"e.g. 50, 25"},o={name:"photo",ext:"jpg",orig:"photo.jpg",dir:"trips/2026",format:"webp",width:"800",height:"600",size:"800x600",long:"800",short:"600",mp:"0.48",percent:"50",scale:"2",index:"001",hash:"a1b2c3d4",date:"2026-10-08"},r=E(()=>i.options),y=c([]),S=c([]),M=c(!0),A=c(0),B=c("out"),z=c(""),O=c(!1),k=c("skip"),v=c(!0),C=c(!0),j=c(!1),R=c("quick"),P=c(""),Z=c(!1),D=c("widths"),K=c("800, 1600"),q=c("1920x1080"),w=c("inside"),I=c(!1),J=c(["webp"]),H=c(""),re=c("82"),ee=c(""),Q=c(""),de=c(Pe()),W=c("idle"),G=c({done:0,total:0}),u=c(""),_=c();let X;const se=E(()=>Z.value?D.value:"original"),h=E(()=>(r.value?.sizeMethods??[]).filter(x=>x!=="original")),V=E(()=>i.cwd.includes("\\")?"\\":"/"),L=E(()=>u.value.toLowerCase().includes("sharp")),ve=E(()=>y.value.find(x=>x.name===P.value)),_e=E(()=>G.value.total>0?Math.round(G.value.done/G.value.total*100):0),ye=E(()=>r.value?.defaultTemplates[se.value]??"{dir}/{name}.{format}"),Fe=E(()=>(Q.value.trim()||ye.value).replace(/\{([a-zA-Z]+)(?::(\d+))?\}/g,(le,ie)=>o[ie]??`{${ie}}`)),ze=E(()=>S.value.length===0?"Add at least one folder or image.":A.value===0&&S.value.length>0?"No images found in the added sources.":B.value==="out"&&z.value.trim()===""?"Choose the folder for the results.":R.value==="config"&&P.value===""?"Choose a saved config.":R.value==="quick"&&B.value!=="replace"&&J.value.length===0?"Pick at least one format.":""),Je=E(()=>ze.value===""&&W.value!=="running");function He(x){A.value=x?.total.files??0,S.value.length>0&&x===void 0&&(A.value=1)}function We(x){J.value=J.value.includes(x)?J.value.filter(le=>le!==x):[...J.value,x]}function Ge(x){return"{"+x+"}"}function Ke(x){z.value=x[0]??z.value,j.value=!1}function Qe(x){Q.value=(Q.value||ye.value)+`{${x}}`}function Ye(){const x=S.value[0];if(z.value!==""||!x)return;const le=x.replace(/[\\/]+$/,"");z.value=`${le}${V.value}converted`}function Be(){const x={sizeMethod:se.value};se.value==="size"?(x.box=q.value,x.fit=w.value,x.matchOrientation=I.value):se.value!=="original"&&(x.values=K.value.split(/[,\s]+/).filter(Boolean).map(Number)),x.formats=B.value==="replace"?["original"]:J.value,H.value==="custom"?x.quality=Number(re.value):H.value&&(x.quality=H.value),ee.value.trim()&&(x.maxBytes=ee.value.trim()),B.value!=="replace"&&Q.value.trim()&&(x.name=Q.value.trim());const le=io(de.value);return le&&(x.sharpen=le),x}async function Ze(x,le=!1){if(!(!x&&B.value==="replace"&&!window.confirm(`This rewrites ${A.value} original file${A.value===1?"":"s"} in place.`+(v.value?" The originals are copied to a backup folder first.":" No backup will be made.")+`
|
|
3
|
+
|
|
4
|
+
Continue?`))){X?.(),W.value="running",u.value="",_.value=void 0,G.value={done:0,total:0};try{const{jobId:ie}=await F.post("/api/image-batch/run",{paths:S.value,recursive:M.value,placement:B.value,out:z.value,flat:O.value,overwrite:k.value,backup:v.value,onlyIfSmaller:C.value,config:R.value==="config"?P.value:void 0,settings:R.value==="quick"?Be():void 0,dryRun:x,installSharp:le});X=ot(ie,{onProgress:me=>{G.value=me},onDone:me=>{_.value=me,W.value="done"},onFailed:me=>{u.value=me,W.value="failed"}})}catch(ie){u.value=ie instanceof Error?ie.message:String(ie),W.value="failed"}}}ce(async()=>{try{y.value=await F.get("/api/image-batch/configs")}catch(x){u.value=x instanceof Error?x.message:String(x),W.value="failed"}}),xe(()=>X?.());const je={props:i,navigate:e,METHOD_LABELS:m,METHOD_HINTS:g,SAMPLE_TOKENS:o,options:r,configs:y,sources:S,recursive:M,scanTotal:A,placement:B,outDir:z,flat:O,overwrite:k,backup:v,onlyIfSmaller:C,browsingOut:j,mode:R,configName:P,resize:Z,chosenMethod:D,sizeValues:K,box:q,fit:w,matchOrientation:I,formats:J,qualityLevel:H,qualityCustom:re,maxSize:ee,nameTemplate:Q,sharpen:de,phase:W,progress:G,failure:u,report:_,get stopWatching(){return X},set stopWatching(x){X=x},sizeMethod:se,resizeMethods:h,separator:V,needsSharp:L,chosenConfig:ve,percent:_e,defaultTemplate:ye,templateExample:Fe,problem:ze,canRun:Je,onScanned:He,toggleFormat:We,tokenLabel:Ge,chooseOut:Ke,insertToken:Qe,suggestOutDir:Ye,buildSettings:Be,run:Ze,FolderBrowser:Oe,Icon:ue,SourcePicker:nt,UiSegmented:he,BatchResults:Rs,SharpenSettings:Le};return Object.defineProperty(je,"__isScriptSetup",{enumerable:!1,value:!0}),je}}),Js={class:"view"},Hs={key:0,class:"notice notice--warn"},Ws={class:"card block"},Gs={class:"pathrow"},Ks={class:"check"},Qs={key:1,class:"muted"},Ys={class:"check"},Zs={class:"check"},Xs={key:3,class:"field narrow"},$s={class:"card block"},el={class:"head"},tl={key:0,class:"muted"},ol={class:"field narrow"},nl=["value","disabled"],sl={key:0,class:"muted"},ll={class:"group"},il={class:"check"},al={key:0,class:"muted small"},rl={key:1,class:"grid"},dl={class:"field"},cl=["value"],ul={key:0,class:"field"},fl={key:1,class:"field"},vl=["placeholder"],ml={key:2,class:"field"},pl=["value"],gl={key:2,class:"check"},hl={key:3,class:"muted small"},bl={class:"group"},_l={key:0,class:"muted small"},yl={key:1,class:"pills"},kl=["checked","onChange"],wl={class:"grid"},Sl={class:"field"},Cl=["value"],Vl={key:0,class:"field"},xl={class:"field"},Ol={key:0,class:"group"},El=["placeholder"],zl={class:"pills"},Bl=["onClick"],jl={class:"muted small"},Nl={class:"group"},Tl={class:"runbar"},Al=["disabled"],Il=["disabled"],Ul={key:0,class:"muted"},Ml={key:1,class:"card block",role:"status"},Dl={class:"progress"},ql={class:"muted"},Ll={key:2,class:"notice notice--error"};function Pl(f,t,i,e,m,g){return s(),l("div",Js,[e.options&&!e.options.sharp?(s(),l("div",Hs," The sharp image library is not installed yet. Previews are limited, and the first run will offer to install it. ")):d("v-if",!0),U(e.SourcePicker,{sources:e.sources,"onUpdate:sources":t[0]||(t[0]=o=>e.sources=o),recursive:e.recursive,"onUpdate:recursive":t[1]||(t[1]=o=>e.recursive=o),"scan-url":"/api/image-batch/scan",start:i.cwd,onScanned:e.onScanned},null,8,["sources","recursive","start"]),n("section",Ws,[t[35]||(t[35]=n("h2",null,"Where the results go",-1)),U(e.UiSegmented,{modelValue:e.placement,"onUpdate:modelValue":[t[2]||(t[2]=o=>e.placement=o),e.suggestOutDir],label:"Placement",options:[{value:"out",label:"A separate folder",hint:"the sources are not touched"},{value:"beside",label:"Next to each original",hint:"new files beside the sources"},{value:"replace",label:"Replace the originals",hint:"rewrites the files, with a backup"}]},null,8,["modelValue"]),e.placement==="out"?(s(),l(p,{key:0},[n("div",Gs,[T(n("input",{"onUpdate:modelValue":t[3]||(t[3]=o=>e.outDir=o),class:"input",spellcheck:"false",placeholder:"Folder for the results","aria-label":"Folder for the results"},null,512),[[Y,e.outDir]]),n("button",{class:"btn",onClick:t[4]||(t[4]=o=>e.browsingOut=!0)},[U(e.Icon,{name:"folder",size:16}),t[28]||(t[28]=b(" Browse ",-1))])]),n("label",Ks,[T(n("input",{"onUpdate:modelValue":t[5]||(t[5]=o=>e.flat=o),type:"checkbox"},null,512),[[fe,e.flat]]),t[29]||(t[29]=b(" Put everything in one folder (no subfolders) ",-1))])],64)):e.placement==="beside"?(s(),l("p",Qs," Each result is written next to its original, with the size or format in the name. ")):(s(),l(p,{key:2},[t[32]||(t[32]=n("p",{class:"notice notice--warn"}," Each original is overwritten with its converted version, keeping its own format. Use the preview first. ",-1)),n("label",Ys,[T(n("input",{"onUpdate:modelValue":t[6]||(t[6]=o=>e.backup=o),type:"checkbox"},null,512),[[fe,e.backup]]),t[30]||(t[30]=b(" Copy the originals to a backup folder first",-1))]),n("label",Zs,[T(n("input",{"onUpdate:modelValue":t[7]||(t[7]=o=>e.onlyIfSmaller=o),type:"checkbox"},null,512),[[fe,e.onlyIfSmaller]]),t[31]||(t[31]=b(" Replace a file only when the result is smaller ",-1))])],64)),e.placement!=="replace"?(s(),l("label",Xs,[t[34]||(t[34]=n("span",null,"If a result already exists",-1)),T(n("select",{"onUpdate:modelValue":t[8]||(t[8]=o=>e.overwrite=o),class:"select"},[...t[33]||(t[33]=[n("option",{value:"skip"},"Skip it",-1),n("option",{value:"overwrite"},"Overwrite it",-1),n("option",{value:"error"},"Stop and report it",-1)])],512),[[ae,e.overwrite]])])):d("v-if",!0)]),n("section",$s,[n("div",el,[t[36]||(t[36]=n("h2",null,"What to do",-1)),U(e.UiSegmented,{modelValue:e.mode,"onUpdate:modelValue":t[9]||(t[9]=o=>e.mode=o),label:"Settings source",options:[{value:"quick",label:"Quick settings"},{value:"config",label:"Saved config"}]},null,8,["modelValue"])]),e.mode==="config"?(s(),l(p,{key:0},[e.configs.length===0?(s(),l("p",tl,[t[37]||(t[37]=b(" No configs yet. ",-1)),n("button",{class:"link",onClick:t[10]||(t[10]=o=>e.navigate("configs"))},"Create the first one"),t[38]||(t[38]=b(" or use quick settings. ",-1))])):(s(),l(p,{key:1},[n("label",ol,[t[40]||(t[40]=n("span",null,"Config",-1)),T(n("select",{"onUpdate:modelValue":t[11]||(t[11]=o=>e.configName=o),class:"select"},[t[39]||(t[39]=n("option",{value:"",disabled:""},"Choose a config…",-1)),(s(!0),l(p,null,N(e.configs,o=>(s(),l("option",{key:o.name+o.scope,value:o.name,disabled:!!o.error},a(o.name)+" · "+a(o.scope),9,nl))),128))],512),[[ae,e.configName]])]),n("button",{class:"link",onClick:t[12]||(t[12]=o=>e.navigate("configs"))},"Manage configs"),e.chosenConfig?(s(),l("p",sl,[e.chosenConfig.title?(s(),l(p,{key:0},[b(a(e.chosenConfig.title)+" — ",1)],64)):d("v-if",!0),b(" "+a(e.chosenConfig.recipes)+" recipe"+a(e.chosenConfig.recipes===1?"":"s")+" ",1),e.chosenConfig.rules?(s(),l(p,{key:1},[b(", "+a(e.chosenConfig.rules)+" rule"+a(e.chosenConfig.rules===1?"":"s"),1)],64)):d("v-if",!0),e.chosenConfig.description?(s(),l(p,{key:2},[b(" · "+a(e.chosenConfig.description),1)],64)):d("v-if",!0)])):d("v-if",!0)],64))],64)):e.options?(s(),l(p,{key:1},[n("div",ll,[t[47]||(t[47]=n("h3",null,"Size",-1)),n("label",il,[T(n("input",{"onUpdate:modelValue":t[13]||(t[13]=o=>e.resize=o),type:"checkbox"},null,512),[[fe,e.resize]]),t[41]||(t[41]=b(" Resize the images ",-1))]),e.resize?d("v-if",!0):(s(),l("p",al," The size does not change: the images are only converted to the chosen format. ")),e.resize?(s(),l("div",rl,[n("label",dl,[t[42]||(t[42]=n("span",null,"Method",-1)),T(n("select",{"onUpdate:modelValue":t[14]||(t[14]=o=>e.chosenMethod=o),class:"select"},[(s(!0),l(p,null,N(e.resizeMethods,o=>(s(),l("option",{key:o,value:o},a(e.METHOD_LABELS[o]),9,cl))),128))],512),[[ae,e.chosenMethod]])]),e.resize&&e.sizeMethod==="size"?(s(),l("label",ul,[t[43]||(t[43]=n("span",null,"Box (width × height)",-1)),T(n("input",{"onUpdate:modelValue":t[15]||(t[15]=o=>e.box=o),class:"input",spellcheck:"false",placeholder:"1920x1080"},null,512),[[Y,e.box]])])):e.resize?(s(),l("label",fl,[t[44]||(t[44]=n("span",null,"Values",-1)),T(n("input",{"onUpdate:modelValue":t[16]||(t[16]=o=>e.sizeValues=o),class:"input",spellcheck:"false",placeholder:e.METHOD_HINTS[e.sizeMethod]},null,8,vl),[[Y,e.sizeValues]])])):d("v-if",!0),e.resize&&e.sizeMethod==="size"?(s(),l("label",ml,[t[45]||(t[45]=n("span",null,"How it fills the box",-1)),T(n("select",{"onUpdate:modelValue":t[17]||(t[17]=o=>e.fit=o),class:"select"},[(s(!0),l(p,null,N(e.options.fitModes,o=>(s(),l("option",{key:o,value:o},a(o),9,pl))),128))],512),[[ae,e.fit]])])):d("v-if",!0)])):d("v-if",!0),e.sizeMethod==="size"?(s(),l("label",gl,[T(n("input",{"onUpdate:modelValue":t[18]||(t[18]=o=>e.matchOrientation=o),type:"checkbox"},null,512),[[fe,e.matchOrientation]]),t[46]||(t[46]=b(" Turn the box around for portrait images ",-1))])):e.resize&&e.METHOD_HINTS[e.sizeMethod]?(s(),l("p",hl,a(e.METHOD_HINTS[e.sizeMethod])+". Images are never enlarged. ",1)):d("v-if",!0)]),n("div",bl,[t[53]||(t[53]=n("h3",null,"Formats",-1)),e.placement==="replace"?(s(),l("p",_l," Each file keeps its own format when the originals are replaced. ")):(s(),l("div",yl,[(s(!0),l(p,null,N(e.options.formats,o=>(s(),l("label",{key:o,class:te(["pill",{"pill--on":e.formats.includes(o)}])},[n("input",{type:"checkbox",checked:e.formats.includes(o),onChange:r=>e.toggleFormat(o)},null,40,kl),b(" "+a(o),1)],2))),128))])),n("div",wl,[n("label",Sl,[t[50]||(t[50]=n("span",null,"Quality",-1)),T(n("select",{"onUpdate:modelValue":t[19]||(t[19]=o=>e.qualityLevel=o),class:"select"},[t[48]||(t[48]=n("option",{value:""},"Default (high)",-1)),(s(!0),l(p,null,N(e.options.qualityLevels,o=>(s(),l("option",{key:o,value:o},a(o),9,Cl))),128)),t[49]||(t[49]=n("option",{value:"custom"},"A number…",-1))],512),[[ae,e.qualityLevel]])]),e.qualityLevel==="custom"?(s(),l("label",Vl,[t[51]||(t[51]=n("span",null,"Quality (1–100)",-1)),T(n("input",{"onUpdate:modelValue":t[20]||(t[20]=o=>e.qualityCustom=o),class:"input",inputmode:"numeric"},null,512),[[Y,e.qualityCustom]])])):d("v-if",!0),n("label",xl,[t[52]||(t[52]=n("span",null,"Largest file size",-1)),T(n("input",{"onUpdate:modelValue":t[21]||(t[21]=o=>e.maxSize=o),class:"input",spellcheck:"false",placeholder:"e.g. 200KB (optional)"},null,512),[[Y,e.maxSize]])])])]),e.placement!=="replace"?(s(),l("div",Ol,[t[55]||(t[55]=n("h3",null,"File names",-1)),T(n("input",{"onUpdate:modelValue":t[22]||(t[22]=o=>e.nameTemplate=o),class:"input",spellcheck:"false",placeholder:e.defaultTemplate,"aria-label":"File name template"},null,8,El),[[Y,e.nameTemplate]]),n("div",zl,[(s(!0),l(p,null,N(e.options.templateVariables,o=>(s(),l("button",{key:o,class:"pill pill--button",onClick:r=>e.insertToken(o)},a(e.tokenLabel(o)),9,Bl))),128))]),n("p",jl,[t[54]||(t[54]=b(" Example: ",-1)),n("code",null,a(e.templateExample),1),e.nameTemplate.trim()?d("v-if",!0):(s(),l(p,{key:0},[b(" (the default for this size method)")],64))])])):d("v-if",!0),n("div",Nl,[t[56]||(t[56]=n("h3",null,"Sharpening",-1)),U(e.SharpenSettings,{modelValue:e.sharpen,"onUpdate:modelValue":t[23]||(t[23]=o=>e.sharpen=o),options:e.options,manage:""},null,8,["modelValue","options"])])],64)):d("v-if",!0)]),n("div",Tl,[n("button",{class:"btn",disabled:!e.canRun,onClick:t[24]||(t[24]=o=>e.run(!0))},"Preview",8,Al),n("button",{class:"btn btn--primary",disabled:!e.canRun,onClick:t[25]||(t[25]=o=>e.run(!1))},[U(e.Icon,{name:"play",size:15}),b(" "+a(e.phase==="running"?"Working…":"Convert"),1)],8,Il),e.problem?(s(),l("span",Ul,a(e.problem),1)):d("v-if",!0)]),e.phase==="running"?(s(),l("div",Ml,[n("div",Dl,[n("div",{class:"progress__bar",style:Ve({width:`${e.percent}%`})},null,4)]),n("span",ql,a(e.progress.done)+" of "+a(e.progress.total||"…")+" files",1)])):d("v-if",!0),e.phase==="failed"?(s(),l("div",Ll,[n("p",null,a(e.failure),1),e.needsSharp?(s(),l("button",{key:0,class:"btn btn--small",onClick:t[26]||(t[26]=o=>e.run(!1,!0))}," Install sharp and retry ")):d("v-if",!0)])):d("v-if",!0),e.report?(s(),$(e.BatchResults,{key:3,report:e.report},null,8,["report"])):d("v-if",!0),e.browsingOut?(s(),$(e.FolderBrowser,{key:4,start:e.outDir||e.sources[0]||i.cwd,mode:"folder",title:"Choose the folder for the results",onClose:t[27]||(t[27]=o=>e.browsingOut=!1),onConfirm:e.chooseOut},null,8,["start"])):d("v-if",!0)])}const Rl=ne(Fs,[["render",Pl],["__scopeId","data-v-f483fd55"],["__file","C:/work/NPM/devtoolz/ui/src/modules/image-batch/ConvertView.vue"]]),Fl=oe({__name:"UiCompare",props:{before:{type:String,required:!0},after:{type:String,required:!0},beforeLabel:{type:String,required:!1},afterLabel:{type:String,required:!1}},setup(f,{expose:t}){t();const i=c(50),e=c(!0),m={position:i,loading:e};return Object.defineProperty(m,"__isScriptSetup",{enumerable:!1,value:!0}),m}}),Jl=["aria-busy"],Hl={class:"compare__scroll"},Wl={class:"compare__stage"},Gl=["src"],Kl=["src"],Ql={class:"compare__tag compare__tag--left"},Yl={class:"compare__tag compare__tag--right"};function Zl(f,t,i,e,m,g){return s(),l("div",{class:"compare","aria-busy":e.loading},[n("div",Hl,[n("div",Wl,[n("img",{class:"compare__img",alt:"Before",src:i.before,onLoad:t[0]||(t[0]=o=>e.loading=!1)},null,40,Gl),n("img",{class:"compare__img compare__img--top",alt:"After",src:i.after,style:Ve({clipPath:`inset(0 0 0 ${e.position}%)`})},null,12,Kl),n("span",{class:"compare__line",style:Ve({left:`${e.position}%`})},null,4),n("span",Ql,a(i.beforeLabel??"Before"),1),n("span",Yl,a(i.afterLabel??"After"),1)])]),T(n("input",{"onUpdate:modelValue":t[1]||(t[1]=o=>e.position=o),class:"compare__range",type:"range",min:"0",max:"100","aria-label":"Comparison position"},null,512),[[Y,e.position,void 0,{number:!0}]])],8,Jl)}const Xl=ne(Fl,[["render",Zl],["__scopeId","data-v-04dcb8d4"],["__file","C:/work/NPM/devtoolz/ui/src/ui-components/UiCompare.vue"]]),Se="devtoolz-ui.sharpen-sample",$l=oe({__name:"SharpenEditor",props:{options:{type:Object,required:!0},cwd:{type:String,required:!0},initial:{type:null,required:!1},copyOf:{type:null,required:!1}},emits:["saved","cancel"],setup(f,{expose:t,emit:i}){t();const e=f,m=i,g=pe(Ee,qe),o=["radius","flat","jagged","threshold"];function r(){return e.initial??e.copyOf}function y(u){const _=r()?.fields?.[u];return _===void 0?"":String(_)}const S=E(()=>e.initial!==void 0),M=c(e.initial?e.initial.name:e.copyOf?.name??""),A=c(e.initial&&e.initial.scope!=="built-in"?e.initial.scope:"project"),B=c(r()?.description??""),z=c(String(r()?.fields?.for??"")),O=c(String(r()?.fields?.amount??"")),k=c({radius:y("radius"),flat:y("flat"),jagged:y("jagged"),threshold:y("threshold")}),v=c(""),C=c("800"),j=c(!1),R=c(),P=c(""),Z=c(""),D=c(!1),K=c("");let q;const w=E(()=>Object.fromEntries(e.options.sharpen.fine.map(u=>[u.key,u.range])));function I(){const u={};z.value&&(u.for=z.value),O.value&&(u.amount=O.value);for(const _ of o)k.value[_].trim()!==""&&(u[_]=Number(k.value[_]));return u}function J(u){const _=new URLSearchParams({path:v.value,width:C.value||"800"});if(u){_.set("sharpen","1");for(const[X,se]of Object.entries(I()))_.set(X,String(se))}return`/api/image-batch/sharpen-preview?${_.toString()}&v=${K.value}`}const H=E(()=>v.value?J(!1):""),re=E(()=>v.value?J(!0):"");async function ee(){try{const u=await F.post("/api/image-batch/sharpen-preset/params",{fields:I()});R.value=u.params,P.value=""}catch(u){R.value=void 0,P.value=u instanceof Error?u.message:String(u)}K.value=JSON.stringify(I())+C.value}function Q(){clearTimeout(q),q=setTimeout(()=>{ee()},300)}ge([z,O,k,C],Q,{deep:!0});function de(u){v.value=u[0]??"",j.value=!1;try{localStorage.setItem(Se,v.value)}catch{v.value=u[0]??""}}async function W(u=!1){D.value=!0,Z.value="";try{await F.post("/api/image-batch/sharpen-preset/save",{name:M.value,scope:A.value,description:B.value,fields:I(),overwrite:u,...e.initial?{originalName:e.initial.name,originalScope:e.initial.scope}:{}}),m("saved",M.value)}catch(_){if(_ instanceof De&&_.status===409){if(window.confirm(`${_.message}. Replace it?`)){await W(!0);return}}else Z.value=_ instanceof Error?_.message:String(_)}finally{D.value=!1}}ce(()=>{try{v.value=localStorage.getItem(Se)??""}catch{v.value=""}ee()}),xe(()=>clearTimeout(q));const G={props:e,emit:m,project:g,FINE:o,SAMPLE_KEY:Se,seed:r,initialFine:y,editing:S,name:M,scope:A,description:B,target:z,amount:O,fine:k,sample:v,width:C,browsing:j,params:R,paramsError:P,failure:Z,saving:D,applied:K,get timer(){return q},set timer(u){q=u},rangeOf:w,fields:I,query:J,beforeUrl:H,afterUrl:re,refresh:ee,schedule:Q,chooseSample:de,save:W,FolderBrowser:Oe,Icon:ue,UiCompare:Xl};return Object.defineProperty(G,"__isScriptSetup",{enumerable:!1,value:!0}),G}}),ei={class:"card block"},ti={class:"head"},oi={class:"grid"},ni={class:"field"},si={class:"field"},li={value:"project"},ii={class:"field wide"},ai={class:"grid"},ri={class:"field"},di=["value"],ci={class:"field"},ui=["value"],fi={class:"grid"},vi={class:"muted"},mi=["onUpdate:modelValue"],pi={key:0,class:"notice notice--error"},gi={key:1,class:"muted small"},hi={class:"preview"},bi={class:"head"},_i={class:"previewbar"},yi={class:"field inline"},ki={key:0,class:"muted"},wi={key:2,class:"muted small"},Si={key:2,class:"notice notice--error"},Ci={class:"actions"},Vi=["disabled"];function xi(f,t,i,e,m,g){return s(),l("section",ei,[n("div",ti,[n("h2",null,a(e.editing?"Edit preset":i.copyOf?"Copy of a built-in preset":"New sharpening preset"),1),n("button",{class:"btn btn--ghost",onClick:t[0]||(t[0]=o=>e.emit("cancel"))},[U(e.Icon,{name:"close",size:16}),t[11]||(t[11]=b(" Close ",-1))])]),n("div",oi,[n("label",ni,[t[12]||(t[12]=n("span",null,"Name",-1)),T(n("input",{"onUpdate:modelValue":t[1]||(t[1]=o=>e.name=o),class:"input",spellcheck:"false",placeholder:"web-crisp"},null,512),[[Y,e.name]])]),n("label",si,[t[14]||(t[14]=n("span",null,"Where to keep it",-1)),T(n("select",{"onUpdate:modelValue":t[2]||(t[2]=o=>e.scope=o),class:"select"},[n("option",li,"This project ("+a(e.project.name)+")",1),t[13]||(t[13]=n("option",{value:"global"},"All projects (your home folder)",-1))],512),[[ae,e.scope]])]),n("label",ii,[t[15]||(t[15]=n("span",null,"Note (optional)",-1)),T(n("input",{"onUpdate:modelValue":t[3]||(t[3]=o=>e.description=o),class:"input",placeholder:"What it is for"},null,512),[[Y,e.description]])])]),n("div",ai,[n("label",ri,[t[17]||(t[17]=n("span",null,"Sharpen for",-1)),T(n("select",{"onUpdate:modelValue":t[4]||(t[4]=o=>e.target=o),class:"select"},[t[16]||(t[16]=n("option",{value:""},"Default (screen)",-1)),(s(!0),l(p,null,N(i.options.sharpen.targets,o=>(s(),l("option",{key:o,value:o},a(o),9,di))),128))],512),[[ae,e.target]])]),n("label",ci,[t[19]||(t[19]=n("span",null,"Amount",-1)),T(n("select",{"onUpdate:modelValue":t[5]||(t[5]=o=>e.amount=o),class:"select"},[t[18]||(t[18]=n("option",{value:""},"Default (standard)",-1)),(s(!0),l(p,null,N(i.options.sharpen.amounts,o=>(s(),l("option",{key:o,value:o},a(o),9,ui))),128))],512),[[ae,e.amount]])])]),n("div",fi,[(s(),l(p,null,N(e.FINE,o=>n("label",{key:o,class:"field"},[n("span",null,[b(a(o)+" ",1),n("small",vi,"("+a(e.rangeOf[o]?.[0])+"–"+a(e.rangeOf[o]?.[1])+")",1)]),T(n("input",{"onUpdate:modelValue":r=>e.fine[o]=r,class:"input",inputmode:"decimal",placeholder:"value from the table"},null,8,mi),[[Y,e.fine[o]]])])),64))]),e.paramsError?(s(),l("p",pi,a(e.paramsError),1)):e.params?(s(),l("p",gi,[b(" sharp receives: sigma "+a(e.params.sigma)+", flat "+a(e.params.m1)+", jagged "+a(e.params.m2),1),e.params.x1!==void 0?(s(),l(p,{key:0},[b(", threshold "+a(e.params.x1),1)],64)):d("v-if",!0)])):d("v-if",!0),n("div",hi,[n("div",bi,[t[21]||(t[21]=n("h3",null,"Preview",-1)),n("div",_i,[n("label",yi,[t[20]||(t[20]=n("span",null,"Width",-1)),T(n("input",{"onUpdate:modelValue":t[6]||(t[6]=o=>e.width=o),class:"input narrow",inputmode:"numeric","aria-label":"Preview width"},null,512),[[Y,e.width]])]),n("button",{class:"btn btn--small",onClick:t[7]||(t[7]=o=>e.browsing=!0)},[U(e.Icon,{name:"image",size:15}),b(" "+a(e.sample?"Change image":"Choose an image"),1)])])]),e.sample?e.paramsError?d("v-if",!0):(s(),$(e.UiCompare,{key:e.sample,before:e.beforeUrl,after:e.afterUrl,"before-label":"Without sharpening","after-label":"Sharpened"},null,8,["before","after"])):(s(),l("p",ki," Pick any photo to see the preset applied at the output size. Drag the slider to compare. ")),e.sample?(s(),l("p",wi,a(e.sample)+" — resized to "+a(e.width||800)+" px wide, then sharpened, as it would be at the output size. ",1)):d("v-if",!0)]),e.failure?(s(),l("p",Si,a(e.failure),1)):d("v-if",!0),n("div",Ci,[n("button",{class:"btn btn--primary",disabled:e.saving||e.name.trim()==="",onClick:t[8]||(t[8]=o=>e.save(!1))},[U(e.Icon,{name:"save",size:15}),t[22]||(t[22]=b(" Save preset ",-1))],8,Vi),n("button",{class:"btn",onClick:t[9]||(t[9]=o=>e.emit("cancel"))},"Cancel")]),e.browsing?(s(),$(e.FolderBrowser,{key:3,start:e.sample?e.sample.replace(/[\\/][^\\/]*$/,""):i.cwd,mode:"image",onClose:t[10]||(t[10]=o=>e.browsing=!1),onConfirm:e.chooseSample},null,8,["start"])):d("v-if",!0)])}const Oi=ne($l,[["render",xi],["__scopeId","data-v-064cdf5b"],["__file","C:/work/NPM/devtoolz/ui/src/modules/image-batch/SharpenEditor.vue"]]),Ei=oe({__name:"SharpenView",props:{options:{type:Object,required:!0},cwd:{type:String,required:!0}},setup(f,{expose:t}){t();const i=c([]),e=c(""),m=c(""),g=c("list"),o=c(),r=c();async function y(){try{i.value=await F.get("/api/image-batch/sharpen-presets")}catch(v){e.value=v instanceof Error?v.message:String(v)}}function S(){o.value=void 0,r.value=void 0,g.value="edit"}function M(v){o.value=v,r.value=void 0,g.value="edit"}function A(v){o.value=void 0,r.value=v,g.value="edit"}async function B(v){if(window.confirm(`Delete the preset “${v.name}”? A .bak copy is kept next to it.`))try{await F.post("/api/image-batch/sharpen-preset/delete",{name:v.name,scope:v.scope}),m.value=`Deleted ${v.name}.`,await y()}catch(C){e.value=C instanceof Error?C.message:String(C)}}async function z(v){g.value="list",m.value=`Saved ${v}.`,await y()}function O(v){return Object.entries(v.fields??{}).map(([C,j])=>`${C} ${j}`).join(" · ")}ce(y);const k={rows:i,failure:e,note:m,mode:g,editing:o,copying:r,load:y,create:S,edit:M,copy:A,remove:B,saved:z,summary:O,Icon:ue,SharpenEditor:Oi};return Object.defineProperty(k,"__isScriptSetup",{enumerable:!1,value:!0}),k}}),zi={class:"view"},Bi={key:1,class:"card block"},ji={class:"head"},Ni={key:0,class:"notice"},Ti={key:1,class:"notice notice--error"},Ai={class:"list"},Ii={class:"item__main"},Ui={class:"item__title"},Mi={key:0,class:"item__error"},Di={key:0,class:"muted"},qi={class:"item__facts"},Li={key:0,class:"muted"},Pi={class:"item__actions"},Ri=["onClick"],Fi=["onClick"],Ji=["onClick"];function Hi(f,t,i,e,m,g){return s(),l("div",zi,[e.mode==="edit"?(s(),$(e.SharpenEditor,{key:0,options:i.options,cwd:i.cwd,initial:e.editing,"copy-of":e.copying,onSaved:e.saved,onCancel:t[0]||(t[0]=o=>e.mode="list")},null,8,["options","cwd","initial","copy-of"])):(s(),l("section",Bi,[n("div",ji,[t[2]||(t[2]=n("div",null,[n("h2",null,"Sharpening presets"),n("p",{class:"muted"}," Save a set of sharpening values once and use it by name in any config or run. ")],-1)),n("button",{class:"btn btn--primary",onClick:e.create},[U(e.Icon,{name:"plus",size:16}),t[1]||(t[1]=b(" New preset ",-1))])]),e.note?(s(),l("p",Ni,a(e.note),1)):d("v-if",!0),e.failure?(s(),l("p",Ti,a(e.failure),1)):d("v-if",!0),n("ul",Ai,[(s(!0),l(p,null,N(e.rows,o=>(s(),l("li",{key:o.scope+o.name,class:"item"},[n("div",Ii,[n("div",Ui,[n("strong",null,a(o.name),1),n("span",{class:te(["tag",{"tag--builtin":o.scope==="built-in"}])},a(o.scope),3)]),o.error?(s(),l("p",Mi,a(o.error),1)):(s(),l(p,{key:1},[o.description?(s(),l("p",Di,a(o.description),1)):d("v-if",!0),n("p",qi,[b(a(e.summary(o))+" ",1),o.params?(s(),l("span",Li," — sigma "+a(o.params.sigma)+", flat "+a(o.params.m1)+", jagged "+a(o.params.m2),1)):d("v-if",!0)])],64))]),n("div",Pi,[o.scope!=="built-in"&&!o.error?(s(),l("button",{key:0,class:"btn btn--small",onClick:r=>e.edit(o)}," Edit ",8,Ri)):d("v-if",!0),o.error?d("v-if",!0):(s(),l("button",{key:1,class:"btn btn--small",onClick:r=>e.copy(o)},a(o.scope==="built-in"?"Copy to my presets":"Duplicate"),9,Fi)),o.scope!=="built-in"?(s(),l("button",{key:2,class:"btn btn--small btn--danger",onClick:r=>e.remove(o)}," Delete ",8,Ji)):d("v-if",!0)])]))),128))])]))])}const Wi=ne(Ei,[["render",Hi],["__scopeId","data-v-8f664bc5"],["__file","C:/work/NPM/devtoolz/ui/src/modules/image-batch/SharpenView.vue"]]),Ce="devtoolz-ui.image-batch-tab",Gi=oe({__name:"ImageBatchPage",props:{module:{type:Object,required:!0},status:{type:null,required:!0}},setup(f,{expose:t}){t();const i=f;function e(){try{const S=localStorage.getItem(Ce);if(S==="convert"||S==="configs"||S==="sharpen"||S==="backups")return S}catch{return"convert"}return"convert"}const m=c(e()),g=c(),o=c("");function r(S){m.value=S;try{localStorage.setItem(Ce,S)}catch{m.value=S}}Ne(be,r),Ne(Ee,E(()=>Pt(i.status?.cwd??"",i.status?.home??"")).value),ce(async()=>{try{g.value=await F.get("/api/image-batch/options")}catch(S){o.value=S instanceof Error?S.message:String(S)}});const y={props:i,TAB_KEY:Ce,initialTab:e,tab:m,options:g,failure:o,go:r,Icon:ue,UiSegmented:he,BackupsView:Lt,ConfigsView:ps,ConvertView:Rl,SharpenView:Wi};return Object.defineProperty(y,"__isScriptSetup",{enumerable:!1,value:!0}),y}}),Ki={class:"page"},Qi={class:"page__head"},Yi={class:"muted"},Zi=["title"],Xi={key:0,class:"notice notice--error"};function $i(f,t,i,e,m,g){return s(),l("div",Ki,[n("header",Qi,[n("h1",null,a(i.module.title),1),n("p",Yi,a(i.module.description),1),i.status?.cwd?(s(),l("p",{key:0,class:"context",title:`Everything marked “This project” lives in ${i.status.cwd}`},[U(e.Icon,{name:"folder",size:15}),t[0]||(t[0]=n("span",{class:"muted"},"Project folder",-1)),n("code",null,a(i.status.cwd),1)],8,Zi)):d("v-if",!0)]),U(e.UiSegmented,{"model-value":e.tab,label:"Image Batch sections",options:[{value:"convert",label:"Convert"},{value:"configs",label:"Configs"},{value:"sharpen",label:"Sharpening"},{value:"backups",label:"Backups"}],"onUpdate:modelValue":e.go},null,8,["model-value"]),e.failure?(s(),l("p",Xi,a(e.failure),1)):e.options?(s(),l(p,{key:1},[e.tab==="convert"?(s(),$(e.ConvertView,{key:0,cwd:e.props.status?.cwd??"",options:e.options},null,8,["cwd","options"])):e.tab==="configs"?(s(),$(e.ConfigsView,{key:1,options:e.options},null,8,["options"])):e.tab==="sharpen"?(s(),$(e.SharpenView,{key:2,options:e.options,cwd:e.props.status?.cwd??""},null,8,["options","cwd"])):(s(),$(e.BackupsView,{key:3,cwd:e.props.status?.cwd??""},null,8,["cwd"]))],64)):d("v-if",!0)])}const sa=ne(Gi,[["render",$i],["__scopeId","data-v-ec718b70"],["__file","C:/work/NPM/devtoolz/ui/src/modules/image-batch/ImageBatchPage.vue"]]);export{sa as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.view[data-v-276a3888]{display:flex;flex-direction:column;gap:16px}.block[data-v-276a3888]{display:flex;flex-direction:column;gap:12px;padding:18px}.head[data-v-276a3888]{display:flex;flex-wrap:wrap;align-items:flex-start;justify-content:space-between;gap:12px}.small[data-v-276a3888]{font-size:12px}.list[data-v-276a3888]{display:flex;flex-direction:column;gap:8px;margin:0;padding:0;list-style:none}.item[data-v-276a3888]{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:12px;padding:12px;border:1px solid var(--border);border-radius:9px}.item__main[data-v-276a3888]{display:flex;flex-direction:column;gap:2px;flex:1;min-width:260px}.item__path[data-v-276a3888]{color:var(--muted);font-size:11px;word-break:break-all}.item__actions[data-v-276a3888]{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.custom[data-v-276a3888]{display:flex;flex-direction:column;gap:8px;padding-top:12px;border-top:1px solid var(--border)}.custom h3[data-v-276a3888]{font-size:12px;font-weight:600;letter-spacing:.02em;color:var(--muted);text-transform:uppercase}.pathrow[data-v-276a3888]{display:flex;flex-wrap:wrap;gap:8px}.pathrow .input[data-v-276a3888]{flex:1;min-width:220px;font-family:ui-monospace,Cascadia Code,SF Mono,Menlo,Consolas,monospace;font-size:12px}.actions[data-v-276a3888]{display:flex;flex-wrap:wrap;align-items:center;gap:12px}.chips[data-v-276a3888]{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.chip[data-v-276a3888]{padding:2px 10px;border-radius:999px;background:var(--surface-2);font-size:12px;white-space:nowrap}.chip--good[data-v-276a3888]{background:color-mix(in srgb,var(--ok) 18%,transparent);color:var(--ok)}.chip--warn[data-v-276a3888]{background:var(--warn-soft);color:var(--warn)}.chip--bad[data-v-276a3888]{background:var(--danger-soft);color:var(--danger)}.rows[data-v-276a3888]{display:flex;flex-direction:column;gap:8px;margin:0;padding:0;list-style:none}.row[data-v-276a3888]{display:flex;align-items:center;gap:12px;padding:8px;border:1px solid var(--border);border-radius:9px}.row__thumb[data-v-276a3888]{flex:none;width:64px;height:64px;border-radius:6px;background:var(--surface-2);object-fit:cover}.row__text[data-v-276a3888]{display:flex;flex-direction:column;gap:2px;flex:1;min-width:0}.row__name[data-v-276a3888]{font-family:ui-monospace,Cascadia Code,SF Mono,Menlo,Consolas,monospace;font-size:12px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.row__message[data-v-276a3888]{color:var(--danger)}.sharpen[data-v-1a683036]{display:flex;flex-direction:column;gap:12px}.grid[data-v-1a683036]{display:grid;grid-template-columns:repeat(auto-fill,minmax(180px,1fr));gap:12px}.hint[data-v-1a683036]{align-self:end;font-size:12px}.link[data-v-1a683036]{align-self:flex-start;padding:0;border:0;background:transparent;color:var(--accent);cursor:pointer}.link[data-v-1a683036]:focus-visible{outline:2px solid var(--accent);outline-offset:1px}.recipe[data-v-92a49f1e]{display:flex;flex-direction:column;gap:16px}.group[data-v-92a49f1e]{display:flex;flex-direction:column;gap:10px}.group h4[data-v-92a49f1e]{font-size:12px;font-weight:600;letter-spacing:.02em;color:var(--muted);text-transform:uppercase;margin:0}.grid[data-v-92a49f1e]{display:grid;grid-template-columns:repeat(auto-fill,minmax(210px,1fr));gap:14px}.small[data-v-92a49f1e]{font-size:12px}.input--bad[data-v-92a49f1e]{border-color:var(--danger)}.pills[data-v-92a49f1e]{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.pill[data-v-92a49f1e]{display:inline-flex;align-items:center;gap:6px;padding:4px 12px;border:1px solid var(--border);border-radius:999px;background:var(--surface);font-size:12px;cursor:pointer}.pill input[data-v-92a49f1e]{display:none}.pill--on[data-v-92a49f1e]{border-color:var(--accent);background:var(--accent-soft);color:var(--accent);font-weight:600}.pill--button[data-v-92a49f1e]{font-family:ui-monospace,Cascadia Code,SF Mono,Menlo,Consolas,monospace}.pill--button[data-v-92a49f1e]:focus-visible{outline:2px solid var(--accent);outline-offset:1px}.link[data-v-92a49f1e]{align-self:flex-start;padding:0;border:0;background:transparent;color:var(--accent);cursor:pointer}.link[data-v-92a49f1e]:focus-visible{outline:2px solid var(--accent);outline-offset:1px}.block[data-v-6b6acd65]{display:flex;flex-direction:column;gap:16px;padding:18px}.head[data-v-6b6acd65]{display:flex;align-items:center;justify-content:space-between;gap:12px}.grid[data-v-6b6acd65]{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:14px}.small[data-v-6b6acd65]{font-size:12px}.recipes[data-v-6b6acd65]{display:flex;flex-direction:column;gap:8px}.panel[data-v-6b6acd65]{border:1px solid var(--border);border-radius:9px}.panel--open[data-v-6b6acd65]{border-color:var(--accent)}.panel__head[data-v-6b6acd65]{display:flex;align-items:center;gap:8px;padding:4px 8px 4px 12px}.panel__title[data-v-6b6acd65]{display:flex;flex-direction:column;gap:0;flex:1;min-width:0;padding:8px 0;border:0;background:transparent;text-align:left;cursor:pointer}.panel__title[data-v-6b6acd65]:focus-visible{outline:2px solid var(--accent);outline-offset:1px}.panel__title .small[data-v-6b6acd65]{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.panel__actions[data-v-6b6acd65]{display:flex;flex-wrap:wrap;align-items:center;gap:2px;flex:none}.panel__body[data-v-6b6acd65]{padding:12px 16px 16px;border-top:1px solid var(--border)}.panel summary[data-v-6b6acd65]{padding:12px;cursor:pointer;font-weight:600}details.panel>.panel__body[data-v-6b6acd65]{border-top:1px solid var(--border)}.json[data-v-6b6acd65]{min-height:420px;padding:12px;border:1px solid var(--border);border-radius:9px;background:var(--surface-2);font-family:ui-monospace,Cascadia Code,SF Mono,Menlo,Consolas,monospace;font-size:12px;resize:vertical;tab-size:2}.json[data-v-6b6acd65]:focus-visible{outline:2px solid var(--accent);outline-offset:1px}.check-panel[data-v-6b6acd65]{padding:10px 14px;border-radius:9px}.check-panel--ok[data-v-6b6acd65]{background:color-mix(in srgb,var(--ok) 14%,transparent)}.check-panel--bad[data-v-6b6acd65]{background:var(--danger-soft);color:var(--danger)}.lines[data-v-6b6acd65]{margin:8px 0 0;font-size:12px;white-space:pre-wrap}.actions[data-v-6b6acd65]{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.view[data-v-2e26c039]{display:flex;flex-direction:column;gap:16px}.block[data-v-2e26c039]{display:flex;flex-direction:column;gap:12px;padding:18px}.head[data-v-2e26c039]{display:flex;flex-wrap:wrap;align-items:flex-start;justify-content:space-between;gap:12px}.list[data-v-2e26c039]{display:flex;flex-direction:column;gap:8px;margin:0;padding:0;list-style:none}.item[data-v-2e26c039]{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:12px;padding:12px;border:1px solid var(--border);border-radius:9px}.item__main[data-v-2e26c039]{display:flex;flex-direction:column;gap:2px;flex:1;min-width:260px}.item__title[data-v-2e26c039]{display:flex;align-items:center;gap:8px}.item__path[data-v-2e26c039]{color:var(--muted);font-size:11px;word-break:break-all}.item__error[data-v-2e26c039]{color:var(--danger);font-size:12px}.item__actions[data-v-2e26c039]{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.tag[data-v-2e26c039]{padding:1px 8px;border-radius:999px;background:var(--surface-2);color:var(--muted);font-size:11px}.block[data-v-7e5d47ea]{display:flex;flex-direction:column;gap:12px;padding:18px}.head[data-v-7e5d47ea]{display:flex;align-items:center;justify-content:space-between;gap:12px}.small[data-v-7e5d47ea]{font-size:12px}.chips[data-v-7e5d47ea]{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.chip[data-v-7e5d47ea]{padding:2px 10px;border-radius:999px;background:var(--surface-2);font-size:12px;white-space:nowrap}.chip--good[data-v-7e5d47ea]{background:color-mix(in srgb,var(--ok) 18%,transparent);color:var(--ok)}.chip--bad[data-v-7e5d47ea]{background:var(--danger-soft);color:var(--danger)}.errors[data-v-7e5d47ea]{margin:0;padding:10px 14px 10px 28px;border-radius:10px;background:var(--danger-soft);color:var(--danger)}.rows[data-v-7e5d47ea]{display:flex;flex-direction:column;gap:8px;margin:0;padding:0;list-style:none}.row[data-v-7e5d47ea]{display:flex;align-items:center;gap:12px;padding:8px;border:1px solid var(--border);border-radius:9px}.row__thumb[data-v-7e5d47ea]{flex:none;width:64px;height:64px;border-radius:6px;background:var(--surface-2);object-fit:cover}.row__thumb--empty[data-v-7e5d47ea]{display:grid;place-items:center;font-size:11px}.row__text[data-v-7e5d47ea]{display:flex;flex-direction:column;gap:2px;flex:1;min-width:0}.row__name[data-v-7e5d47ea]{font-family:ui-monospace,Cascadia Code,SF Mono,Menlo,Consolas,monospace;font-size:12px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.row__message[data-v-7e5d47ea]{color:var(--danger)}.row__sizes[data-v-7e5d47ea]{display:flex;align-items:baseline;gap:6px;flex:none;font-size:12px}.row__delta[data-v-7e5d47ea]{color:var(--muted)}.row__delta--down[data-v-7e5d47ea]{color:var(--ok)}@media(max-width:760px){.row[data-v-7e5d47ea]{flex-wrap:wrap}.row__text[data-v-7e5d47ea]{flex-basis:60%}}.link[data-v-7e5d47ea]{padding:0;border:0;background:transparent;color:var(--accent);cursor:pointer;text-decoration:underline}.more[data-v-7e5d47ea]{display:flex;flex-wrap:wrap;align-items:center;gap:8px;justify-content:center}.view[data-v-f483fd55]{display:flex;flex-direction:column;gap:16px}.block[data-v-f483fd55]{display:flex;flex-direction:column;gap:14px;padding:18px}.head[data-v-f483fd55]{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:12px}.group[data-v-f483fd55]{display:flex;flex-direction:column;gap:10px}.group h3[data-v-f483fd55]{font-size:12px;font-weight:600;letter-spacing:.02em;color:var(--muted);text-transform:uppercase}.grid[data-v-f483fd55]{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:14px}.narrow[data-v-f483fd55]{max-width:320px}.small[data-v-f483fd55]{font-size:12px}.pathrow[data-v-f483fd55]{display:flex;gap:8px}.pathrow .input[data-v-f483fd55]{flex:1;font-family:ui-monospace,Cascadia Code,SF Mono,Menlo,Consolas,monospace;font-size:12px}.pills[data-v-f483fd55]{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.pill[data-v-f483fd55]{display:inline-flex;align-items:center;gap:6px;padding:4px 12px;border:1px solid var(--border);border-radius:999px;background:var(--surface);font-size:12px;cursor:pointer}.pill input[data-v-f483fd55]{display:none}.pill--on[data-v-f483fd55]{border-color:var(--accent);background:var(--accent-soft);color:var(--accent);font-weight:600}.pill--button[data-v-f483fd55]{font-family:ui-monospace,Cascadia Code,SF Mono,Menlo,Consolas,monospace}.pill--button[data-v-f483fd55]:focus-visible{outline:2px solid var(--accent);outline-offset:1px}.runbar[data-v-f483fd55]{display:flex;flex-wrap:wrap;align-items:center;gap:14px}.link[data-v-f483fd55]{align-self:flex-start;padding:0;border:0;background:transparent;color:var(--accent);cursor:pointer}.link[data-v-f483fd55]:focus-visible{outline:2px solid var(--accent);outline-offset:1px}.progress[data-v-f483fd55]{height:8px;overflow:hidden;border-radius:999px;background:var(--surface-2)}.progress__bar[data-v-f483fd55]{height:100%;background:var(--accent);transition:width .15s}.compare[data-v-04dcb8d4]{display:flex;flex-direction:column;gap:8px}.compare__scroll[data-v-04dcb8d4]{overflow:auto;border-radius:9px;background:var(--surface-2);max-height:70vh}.compare__stage[data-v-04dcb8d4]{position:relative;width:fit-content;margin:0 auto;line-height:0}.compare__img[data-v-04dcb8d4]{display:block;max-width:none}.compare__img--top[data-v-04dcb8d4]{position:absolute;inset:0}.compare__line[data-v-04dcb8d4]{position:absolute;top:0;bottom:0;width:2px;background:var(--accent);pointer-events:none}.compare__tag[data-v-04dcb8d4]{position:absolute;top:8px;padding:2px 8px;border-radius:6px;background:#0009;color:#fff;font-size:11px;line-height:1.4}.compare__tag--left[data-v-04dcb8d4]{left:8px}.compare__tag--right[data-v-04dcb8d4]{right:8px}.compare__range[data-v-04dcb8d4]{width:100%}.block[data-v-064cdf5b]{display:flex;flex-direction:column;gap:16px;padding:18px}.head[data-v-064cdf5b]{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:12px}.grid[data-v-064cdf5b]{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:14px}.wide[data-v-064cdf5b]{grid-column:1/-1}.small[data-v-064cdf5b]{font-size:12px}.preview[data-v-064cdf5b]{display:flex;flex-direction:column;gap:12px}.previewbar[data-v-064cdf5b]{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.inline[data-v-064cdf5b]{flex-direction:row;align-items:center}.narrow[data-v-064cdf5b]{width:90px}.actions[data-v-064cdf5b]{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.view[data-v-8f664bc5]{display:flex;flex-direction:column;gap:16px}.block[data-v-8f664bc5]{display:flex;flex-direction:column;gap:12px;padding:18px}.head[data-v-8f664bc5]{display:flex;flex-wrap:wrap;align-items:flex-start;justify-content:space-between;gap:12px}.list[data-v-8f664bc5]{display:flex;flex-direction:column;gap:8px;margin:0;padding:0;list-style:none}.item[data-v-8f664bc5]{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:12px;padding:12px;border:1px solid var(--border);border-radius:9px}.item__main[data-v-8f664bc5]{display:flex;flex-direction:column;gap:2px;flex:1;min-width:260px}.item__title[data-v-8f664bc5]{display:flex;align-items:center;gap:8px}.item__facts[data-v-8f664bc5]{font-family:ui-monospace,Cascadia Code,SF Mono,Menlo,Consolas,monospace;font-size:12px}.item__error[data-v-8f664bc5]{color:var(--danger);font-size:12px}.item__actions[data-v-8f664bc5]{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.tag[data-v-8f664bc5]{padding:1px 8px;border-radius:999px;background:var(--surface-2);color:var(--muted);font-size:11px}.tag--builtin[data-v-8f664bc5]{background:var(--accent-soft);color:var(--accent)}.page[data-v-ec718b70]{display:flex;flex-direction:column;gap:16px;padding:28px 28px 60px}@media(max-width:760px){.page[data-v-ec718b70]{padding:18px 14px 40px}}.page__head p[data-v-ec718b70]{margin-top:4px}.context[data-v-ec718b70]{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin-top:8px;font-size:12px}.context code[data-v-ec718b70]{padding:2px 8px;border-radius:6px;background:var(--surface-2);word-break:break-all}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.canvas[data-v-512bf9cf]{display:block;width:100%;height:100%;object-fit:cover;background:var(--surface-2)}.canvas--bad[data-v-512bf9cf]{display:grid;place-items:center;color:var(--danger)}.item[data-v-e50ba89f]{display:flex;flex-direction:column;gap:10px;padding:10px;min-width:0}.item__open[data-v-e50ba89f]{display:flex;flex-direction:column;gap:10px;padding:0;border:0;background:transparent;text-align:left;cursor:zoom-in}.item__open[data-v-e50ba89f]:focus-visible{outline:2px solid var(--accent);outline-offset:1px}.shots[data-v-e50ba89f]{display:block;overflow:hidden;border-radius:8px;background:var(--surface-2)}.shot[data-v-e50ba89f]{display:block;width:100%;height:100%;object-fit:cover;transition:transform .15s}.item__open:hover .shot[data-v-e50ba89f]{transform:scale(1.02)}.strip[data-v-e50ba89f]{display:flex;overflow:hidden;border-radius:8px}.strip__cell[data-v-e50ba89f]{position:relative;flex:1}.strip__label[data-v-e50ba89f]{position:absolute;left:4px;bottom:3px;padding:0 5px;border-radius:4px;background:#0000008c;color:#fff;font-size:10px}.preview[data-v-e50ba89f]{width:100%;border-radius:8px}.meta[data-v-e50ba89f]{display:flex;align-items:baseline;justify-content:space-between;gap:8px}.meta__name[data-v-e50ba89f]{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.hashes[data-v-e50ba89f]{display:flex;flex-direction:column;gap:2px;margin:0;padding:0;list-style:none}.hashes li[data-v-e50ba89f]{display:flex;align-items:center;gap:8px}.hashes__key[data-v-e50ba89f]{display:flex;align-items:center;gap:6px;flex:none;width:84px;color:var(--muted);font-size:12px}.hashes__value[data-v-e50ba89f]{flex:1;font-size:12px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.swatch[data-v-e50ba89f]{display:inline-block;width:12px;height:12px;border:1px solid var(--border);border-radius:4px}.counter[data-v-6aef2e16]{font-size:12px}.scroll[data-v-6aef2e16]{display:flex;flex-direction:column;gap:16px;padding:16px;min-height:0;overflow-y:auto;overscroll-behavior:contain;scrollbar-width:thin;scrollbar-color:var(--border) transparent}.stage[data-v-6aef2e16]{display:flex;align-items:center;justify-content:center;padding:12px;border-radius:9px;background:repeating-conic-gradient(var(--surface-2) 0% 25%,transparent 0% 50%) 50%/20px 20px}.stage__img[data-v-6aef2e16]{display:block;max-width:100%;max-height:56vh;border-radius:6px;object-fit:contain}.compare[data-v-6aef2e16]{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:12px}.compare__item[data-v-6aef2e16]{display:flex;flex-direction:column;gap:6px;margin:0}.compare__item figcaption[data-v-6aef2e16]{font-size:12px;font-weight:600;letter-spacing:.02em;color:var(--muted);text-transform:uppercase}.compare__frame[data-v-6aef2e16]{overflow:hidden;border-radius:9px;background:var(--surface-2)}.compare__preview[data-v-6aef2e16]{display:block;width:100%;height:100%;object-fit:cover}.facts[data-v-6aef2e16]{display:flex;flex-direction:column;gap:4px;margin:0}.facts__row[data-v-6aef2e16]{display:flex;align-items:center;gap:12px;min-height:32px}.facts dt[data-v-6aef2e16]{display:flex;align-items:center;gap:6px;flex:none;width:96px;color:var(--muted);font-size:12px}.facts dd[data-v-6aef2e16]{flex:1;min-width:0;margin:0}.facts__mono[data-v-6aef2e16]{font-family:ui-monospace,Cascadia Code,SF Mono,Menlo,Consolas,monospace;font-size:12px;word-break:break-all}.swatch[data-v-6aef2e16]{display:inline-block;width:12px;height:12px;border:1px solid var(--border);border-radius:4px}.page[data-v-0458e07e]{display:flex;flex-direction:column;gap:16px;padding:28px 28px 60px}@media(max-width:760px){.page[data-v-0458e07e]{padding:18px 14px 40px}}.page__head p[data-v-0458e07e]{margin-top:4px}.block[data-v-0458e07e]{display:flex;flex-direction:column;gap:14px;padding:18px}.block__head[data-v-0458e07e]{display:flex;align-items:center;justify-content:space-between;gap:12px}.types[data-v-0458e07e]{display:grid;grid-template-columns:repeat(auto-fill,minmax(210px,1fr));gap:10px}.type[data-v-0458e07e]{display:grid;grid-template-columns:auto 1fr;column-gap:10px;row-gap:2px;padding:12px;border:1px solid var(--border);border-radius:10px;cursor:pointer}.type--on[data-v-0458e07e]{border-color:var(--accent);background:var(--accent-soft)}.type input[data-v-0458e07e]{grid-row:1/3;margin-top:3px}.type__title[data-v-0458e07e]{font-weight:600}.type__text[data-v-0458e07e]{font-size:12px}.grid[data-v-0458e07e]{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:14px}.runbar[data-v-0458e07e]{display:flex;align-items:center;gap:14px}.progress[data-v-0458e07e]{height:8px;overflow:hidden;border-radius:999px;background:var(--surface-2)}.progress__bar[data-v-0458e07e]{height:100%;background:var(--accent);transition:width .15s}.errors[data-v-0458e07e]{margin:0;padding:10px 14px 10px 28px;border-radius:10px;background:var(--danger-soft);color:var(--danger)}.tabs[data-v-0458e07e]{display:flex;gap:4px;border-bottom:1px solid var(--border)}.tab[data-v-0458e07e]{padding:8px 14px;border:0;border-bottom:2px solid transparent;background:transparent;color:var(--muted);cursor:pointer}.tab[data-v-0458e07e]:focus-visible{outline:2px solid var(--accent);outline-offset:1px}.tab--on[data-v-0458e07e]{border-bottom-color:var(--accent);color:var(--text);font-weight:600}.gallery[data-v-0458e07e]{width:100%}.more[data-v-0458e07e]{display:flex;flex-wrap:wrap;align-items:center;gap:8px;justify-content:center}.outbar[data-v-0458e07e]{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.outbar__path[data-v-0458e07e]{flex:1;min-width:220px;height:28px;font-family:ui-monospace,Cascadia Code,SF Mono,Menlo,Consolas,monospace;font-size:12px}.output[data-v-0458e07e]{max-height:420px;margin:0;padding:14px;border-radius:10px;background:var(--surface-2);font-size:12px;white-space:pre-wrap;word-break:break-all;overflow:auto}
|