UNPKG

piconvert

Version:

Convert pictures to other formats. Supports ai, cdr, vsd, pdf, and more formats. GitHub Actions & CLI Tool.

5 lines (4 loc) 8.03 kB
#!/usr/bin/env node import{fileURLToPath as A}from"url";import G from"path";var H=()=>A(import.meta.url),K=()=>G.dirname(H()),g=K();import{existsSync as at,readFileSync as lt}from"node:fs";import{resolve as P}from"node:path";import{program as h}from"commander";import{greenBright as S,redBright as w,yellowBright as u,cyanBright as k,blueBright as U,magentaBright as C}from"chalk";import{existsSync as x,mkdirSync as ot,readFileSync as D,readdirSync as et,statSync as O,writeFileSync as st}from"node:fs";import{basename as N,dirname as rt,resolve as f}from"node:path";import it from"events";import T from"js-yaml";import{execSync as M}from"node:child_process";import Q from"sharp";function I(i){var t;return i=(((t=i.split("."))==null?void 0:t.pop())||"").toLowerCase().trim(),{jpg:"jpeg"}[i]||i}var W=["jpeg","png","webp","gif","avif","tiff"],X=["svg","png","ps","eps","pdf","emf","wmf","xaml"];async function E(i,a,t,o,n=!1){a=I(a);let e=`svg -> ${a} ${t||""}x${o||""}`;n&&(console.log(`Normalized Type: ${a}`),console.time(e));let p;if(["svg"].includes(a))p=Buffer.from(i);else if(W.includes(a)){n&&console.log("Use: sharp");let s=Q(Buffer.from(i));(t===null||t<=0)&&(t=null),(o===null||o<=0)&&(o=null),(t||o)&&s.resize(t,o),p=await s[a]().toBuffer()}else if(X.includes(a)){n&&console.log("Use: inkscape");let s=["--export-area-page",`--export-type ${a}`];t!==null&&t>0&&s.push(`--export-width ${t}`),o!==null&&o>0&&s.push(`--export-height ${o}`),p=M(`inkscape --pipe ${s.join(" ")} --export-filename -`,{input:i,stdio:"pipe"})}else throw new Error(`Unsupported file type: ${a}`);return n&&console.timeEnd(e),p}import{spawn as Y}from"node:child_process";import{optimize as Z}from"svgo";var tt=["ai","cdr","vsd","pdf","jpg","jpeg","png","gif","bmp"];async function $(i,a=!1){let t=I(i),o=`${t} -> svg`;a&&(console.log(`Normalized Type: ${t}`),console.time(o));let n="";if(tt.includes(t)){let p=Y("inkscape",["--pipe","--export-plain-svg","--pdf-poppler","--export-type","svg","--export-filename","-",i]);p.stdout.on("data",s=>n+=s.toString()),await new Promise(s=>p.on("close",()=>s(n)))}else throw new Error(`Unsupported file type: ${t}`);let e=Z(n,{multipass:!0});return a&&console.timeEnd(o),e.data}var j=class extends it{constructor(){super(...arguments);this.imports=[];this.exports={}}emit(t,...o){return super.emit(t,...o)}on(t,o){return super.on(t,o)}async convert(t,o,n,e,p=!1){this.emit("task-start",o,n,e);try{let s=f(n,`${N(o.split(".").slice(0,-1).join("."))}${e.width||e.height?`.${e.width||""}x${e.height||""}`:""}.${e.format}`);if(e.force||!x(s)){x(n)||ot(n,{recursive:!0});let r=await E(t,e.format,e.width,e.height,p);st(s,r),this.emit("task-succeeded",o,n,e)}else this.emit("task-skipped",o,n,e)}catch(s){p&&console.error(s),this.emit("task-failed",o,n,e)}}async convert_file(t,o,n,e=!1,p=!1){this.emit("file-start",t,o,n,e,p);let s=f(rt(t),t.split(".").slice(0,-1).join(".")),r=x(s+".yml")?s+".yml":x(s+".yaml")?s+".yaml":null,m=n;r&&(m=T.load(D(r,"utf8")));let l=Object.keys(m),_=[];for(let v of l){let d=m[v];if(d)for(let c of d){let R=typeof c=="number"?c:parseInt(c.split("x")[0])||0,q=typeof c=="number"?c:parseInt(c.split("x")[1])||0;_.push({format:v,width:R,height:q,force:e})}else _.push({format:v,width:0,height:0,force:e})}let F=await $(t,p);for(let v of _)await this.convert(F,t,o,v,p);this.emit("file-finish",t,o,n,e,p)}async convert_directory(t,o,n,e,p=!1,s=!1,r=!0){this.emit("directory-start",t,o,n,e,p,s,r);let m=et(t),l=m.filter(d=>O(f(t,d)).isFile()).filter(d=>{var c;return n.includes((c=d.split(".").pop())==null?void 0:c.toLowerCase())}),_=m.filter(d=>O(f(t,d)).isDirectory()),F=x(f(t,"piconvert.yml"))?f(t,"piconvert.yml"):x(f(t,"piconvert.yaml"))?f(t,"piconvert.yaml"):x(f(t,".piconvert.yml"))?f(t,".piconvert.yml"):x(f(t,".piconvert.yaml"))?f(t,".piconvert.yaml"):null,v=e;F&&(v=T.load(D(F,"utf8")));for(let d of l)await this.convert_file(f(t,d),o,v,p,s);if(this.emit("directory-finish",t,o,n,e,p,s,r),r){let d=_.filter(c=>c[0]&&c[0]!==".").map(c=>f(t,c));for(let c of d)await this.convert_directory(c,f(o,N(c)),n,v,p,s,r)}}export(t,o=null){return this.exports[t]=o,this}clear_exports(){return this.exports={},this}import(t){return this.imports.push(t),this}clear_imports(){return this.imports=[],this}async run(t,o,n=!0,e=!1,p=!1){t=f(t),o=f(o),this.emit("conversion-start",t,o),x(t)&&(O(t).isDirectory()?await this.convert_directory(t,o,this.imports,this.exports,e,p,n):await this.convert_file(t,o,this.exports,e,p)),this.emit("conversion-finish",t,o)}},V=j;import{execSync as pt}from"node:child_process";import{execSync as nt}from"node:child_process";var B=["ai","cdr","vsd","pdf","jpg","jpeg","png","gif","bmp"],z=["svg","png","ps","eps","pdf","emf","wmf","xaml"];function b(){try{return nt("inkscape --version",{stdio:"pipe"}).toString().match(/\d+\.\d+\.\d+/)!==null}catch{return!1}}async function J(i=!1){if(b())return!0;{let a=process.getuid&&process.getuid()===0?"sudo ":"",t="";process.platform==="linux"?t=`${a}add-apt-repository -y ppa:inkscape.dev/stable && ${a}apt update && ${a}apt install -y inkscape`:process.platform==="darwin"?t="brew install --cask inkscape":process.platform==="win32"?t="choco install inkscape":t="echo 'Please download from https://inkscape.org/release/ and install manually.'",pt(t,{stdio:i?"inherit":"ignore"})}return b()}var L=JSON.parse(lt(P(g,"../package.json"),"utf8"));h.version(k("piconvert")+" "+u("v"+L.version)+` `+L.description);h.argument("[path]","Source path. If it's a directory, all files matched selected import types in it and its subdirectories will be converted.","pictures").option("-d, --dir <directory>","Output directory","piconvert").option("-i, --inputs <formats>","Import (input) formats. Supports: "+B.map(i=>u(i)).join(","),"ai").option("-o, --outputs <formats>","Export (output) formats. Supports: "+z.map(i=>u(i)).join(","),"svg,png").option("-f, --force","Overwrite existing files",!1).option("-s, --silent","Silent mode, no output",!1).option("-v, --verbose","Verbose mode, print all Inkscape output",!1).action(async i=>{console.log(k("piconvert")+" "+u("v"+L.version)),i=P(i);let a=P(h.opts().dir),t=h.opts().inputs.split(",").map(r=>{let m=r.trim().toLowerCase();return B.includes(m)?m:null}).filter(r=>r!==null),o=h.opts().outputs.split(",").map(r=>{let m=r.trim().toLowerCase();return z.includes(m)?m:null}).filter(r=>r!==null),n=h.opts().force,e=h.opts().silent,p=h.opts().verbose;b()===!1&&(console.error(w("Inkscape is not installed.")),process.platform==="linux"?console.log("Install via: "+u("add-apt-repository -y ppa:inkscape.dev/stable && apt update && apt install -y inkscape")):process.platform==="darwin"?console.log("Install via: "+u("brew install --cask inkscape")):console.log("Install from: "+u("https://www.inkscape.org/release/")),process.exit(1)),at(i)||(console.error(w(`Input path does not exist. Path: ${i}`)),process.exit(1));let s=new V;for(let r of t)s.import(r);for(let r of o)s.export(r);s.on("conversion-start",(r,m)=>{e||console.log(C("[Conversion started] ")+u(r)+" -> "+u(m))}),s.on("conversion-finish",(r,m)=>{e||console.log(C("[Conversion finished] ")+u(r)+" -> "+u(m))}),s.on("directory-start",()=>{e||console.group()}),s.on("directory-finish",()=>{e||console.groupEnd()}),s.on("file-start",r=>{e||console.log(C("[File]"),U(r.replace(i,"").substring(1))),e||console.group()}),s.on("file-finish",()=>{e||console.groupEnd()}),s.on("task-succeeded",(r,m,l)=>{e||console.log(S("[Succeeded]"),k(l.format+" "+(l.width||"")+(l.width||l.height?"x":"")+(l.height||"")))}),s.on("task-failed",(r,m,l)=>{e||console.log(w("[Failed]"),k(l.format+" "+(l.width||"")+(l.width||l.height?"x":"")+(l.height||"")))}),s.on("task-skipped",(r,m,l)=>{e||console.log(u("[Skipped]"),k(l.format+" "+(l.width||"")+(l.width||l.height?"x":"")+(l.height||"")))}),s.run(i,a,!0,n,p)});h.command("install").option("-v, --verbose","Verbose mode, print execution output",!1).action(async()=>{let i=await J(h.opts().verbose);console.log(i?S("Inkscape installed."):w("Cannot install Inkscape."))});h.parse();