VEKTOR CONVERT
FILES 0
SAVED 0B
TOKENS 0
SOVEREIGN · LOCAL · FREE
Drop Files · Click to Browse
Images · PDF · SVG · Markdown · CSV · JSON · YAML
PROCESSING…
✓ COMPLETE
FILES
ORIGINAL
CONVERTED
SAVED
TOKENS SAVED
Supported Formats
Images
Raster & Vector
JPG · PNG · WebP · AVIF
GIF · BMP · TIFF · ICO
SVG → Raster
Documents
PDF & Markup
PDF → Images
PDF → Text
Markdown ↔ HTML
Data
Structured Formats
CSV ↔ JSON
JSON ↔ YAML
TSV ↔ JSON
Coming Soon
Server-Side
DOCX · HEIC · RAW
MP3 · WAV · OGG
MP4 · WEBM
Audio/Video require FFmpeg server — coming in VEKTOR CONVERT PRO
Output Format
Images PDF / Docs Data
Image Settings
Quality65%
Max Width1024px
Options
Auto-Download
On complete
Copy to Clipboard
Single file
Pretty Print
Format JSON/YAML
⊘ SLIPSTREAM FEATURE
Save to VEKTOR Memory

Ingest any converted file directly into your agent's persistent memory graph.

VEKTOR CONVERT · FREE · SOVEREIGN · NO UPLOADS · NO LIMITS
`;return{blob:new Blob([h],{type:'text/html'}),name:ne(f.name)+'.html'}} if(fmt==='html-md'){const t=await f.text();return{blob:new Blob([html2md(t)],{type:'text/markdown'}),name:ne(f.name)+'.md'}} if(fmt==='csv-json'){const t=await f.text();const j=csv2json(t,',');const pp=document.getElementById('tog-pp').classList.contains('on');return{blob:new Blob([JSON.stringify(j,null,pp?2:0)],{type:'application/json'}),name:ne(f.name)+'.json'}} if(fmt==='tsv-json'){const t=await f.text();const j=csv2json(t,'\t');const pp=document.getElementById('tog-pp').classList.contains('on');return{blob:new Blob([JSON.stringify(j,null,pp?2:0)],{type:'application/json'}),name:ne(f.name)+'.json'}} if(fmt==='json-csv'){const t=await f.text();return{blob:new Blob([json2csv(JSON.parse(t))],{type:'text/csv'}),name:ne(f.name)+'.csv'}} if(fmt==='json-yaml'){const t=await f.text();return{blob:new Blob([j2y(JSON.parse(t))],{type:'text/yaml'}),name:ne(f.name)+'.yaml'}} if(fmt==='yaml-json'){const t=await f.text();const pp=document.getElementById('tog-pp').classList.contains('on');return{blob:new Blob([JSON.stringify(y2j(t),null,pp?2:0)],{type:'application/json'}),name:ne(f.name)+'.json'}} if(fmt==='xml-json'){const t=await f.text();const pp=document.getElementById('tog-pp').classList.contains('on');return{blob:new Blob([JSON.stringify(xml2json(t),null,pp?2:0)],{type:'application/json'}),name:ne(f.name)+'.json'}} return{blob:f,name:f.name}; } async function imgConvert(f,fmt){ const bm=await createImageBitmap(f); const cv=document.createElement('canvas'); const mw=parseInt(ws.value),scale=Math.min(1,mw/bm.width); cv.width=Math.round(bm.width*scale);cv.height=Math.round(bm.height*scale); cv.getContext('2d').drawImage(bm,0,0,cv.width,cv.height); const mime=fmt==='jpg'||fmt==='jpeg'?'image/jpeg':fmt==='png'?'image/png':fmt==='avif'?'image/avif':fmt==='gif'?'image/gif':fmt==='bmp'?'image/bmp':'image/webp'; const q=parseInt(qs.value)/100; return new Promise((rs,rj)=>cv.toBlob(b=>b?rs(b):rj(new Error('fail')),mime,q)); } async function svgConvert(f,fmt){ const txt=await f.text(); const img=new Image(); const url=URL.createObjectURL(new Blob([txt],{type:'image/svg+xml'})); await new Promise((rs,rj)=>{img.onload=rs;img.onerror=rj;img.src=url}); const cv=document.createElement('canvas'); const mw=parseInt(ws.value),w=img.naturalWidth||800,h=img.naturalHeight||600,sc=Math.min(1,mw/w); cv.width=Math.round(w*sc);cv.height=Math.round(h*sc); cv.getContext('2d').drawImage(img,0,0,cv.width,cv.height); URL.revokeObjectURL(url); const mime=fmt==='png'?'image/png':'image/webp'; return new Promise((rs,rj)=>cv.toBlob(b=>b?rs(b):rj(new Error('fail')),mime,parseInt(qs.value)/100)); } async function pdfTxt(f){ const buf=await f.arrayBuffer(); const pdf=await pdfjsLib.getDocument({data:buf}).promise; let out=''; for(let i=1;i<=pdf.numPages;i++){ const pg=await pdf.getPage(i); const tc=await pg.getTextContent(); out+=`\n\n--- PAGE ${i} ---\n\n`+tc.items.map(x=>x.str).join(' '); setP(Math.round(i/pdf.numPages*100),`PAGE ${i}/${pdf.numPages}`); } return new Blob([out.trim()],{type:'text/plain'}); } async function pdfImg(f){ const buf=await f.arrayBuffer(); const pdf=await pdfjsLib.getDocument({data:buf}).promise; const pg=await pdf.getPage(1); const vp=pg.getViewport({scale:2}); const cv=document.createElement('canvas'); cv.width=vp.width;cv.height=vp.height; await pg.render({canvasContext:cv.getContext('2d'),viewport:vp}).promise; if(pdf.numPages>1)toast(`PDF HAS ${pdf.numPages} PAGES — DOWNLOADING PAGE 1`); return new Promise(rs=>cv.toBlob(rs,'image/png')); } // ── DATA CONVERTERS ──────────────────────────────────── function csv2json(csv,sep=','){ const lines=csv.trim().split('\n'); const hdrs=parseLine(lines[0],sep); return lines.slice(1).filter(l=>l.trim()).map(l=>{ const v=parseLine(l,sep); return Object.fromEntries(hdrs.map((h,i)=>[h.trim(),autoType(v[i])])); }); } function parseLine(l,sep){ if(sep==='\t')return l.split('\t').map(v=>v.replace(/^"|"$/g,'').trim()); const re=/(".*?"|[^",\n]+)(?=\s*,|\s*$)/g; return(l.match(re)||[]).map(v=>v.replace(/^"|"$/g,'').trim()); } function autoType(v){if(v===undefined||v==='')return '';if(v==='true')return true;if(v==='false')return false;if(!isNaN(v)&&v!=='')return Number(v);return v} function json2csv(data){ if(!Array.isArray(data)||!data.length)return ''; const h=Object.keys(data[0]); return[h.join(','),...data.map(r=>h.map(k=>JSON.stringify(r[k]??'')).join(','))].join('\n'); } function j2y(o,ind=0){ const sp=' '.repeat(ind); if(o===null)return'null'; if(typeof o==='boolean'||typeof o==='number')return String(o); if(typeof o==='string')return o.includes('\n')?`|\n${sp} ${o.replace(/\n/g,'\n'+sp+' ')}`:/[:{}\[\],&*#?|<>=!%@`]/.test(o)?`"${o.replace(/"/g,'\\"')}"`:o; if(Array.isArray(o))return o.map(v=>`${sp}- ${j2y(v,ind+1)}`).join('\n'); return Object.entries(o).map(([k,v])=>{const vy=j2y(v,ind+1);return typeof v==='object'&&v!==null?`${sp}${k}:\n${vy}`:`${sp}${k}: ${vy}`}).join('\n'); } function y2j(yaml){ const lines=yaml.split('\n');const root={};const stack=[{obj:root,ind:-1}]; for(const line of lines){ if(!line.trim()||line.trim().startsWith('#'))continue; const ind=line.match(/^(\s*)/)[1].length,t=line.trim(); if(t.startsWith('- ')){const p=stack[stack.length-1];if(!Array.isArray(p.arr))p.arr=[];p.arr.push(pyv(t.slice(2).trim()));} else{const[k,...r]=t.split(':');const v=r.join(':').trim();while(stack.length>1&&stack[stack.length-1].ind>=ind)stack.pop();const p=stack[stack.length-1].obj;if(v){p[k.trim()]=pyv(v);}else{const no={};p[k.trim()]=no;stack.push({obj:no,ind});}} } return root; } function pyv(v){if(v==='true')return true;if(v==='false')return false;if(v==='null'||v==='~')return null;if(!isNaN(v)&&v!=='')return Number(v);return v.replace(/^['"]|['"]$/g,'')} function xml2json(xml){ const parser=new DOMParser(); const doc=parser.parseFromString(xml,'text/xml'); function node2obj(n){ if(n.nodeType===3)return n.textContent.trim()||undefined; const obj={}; if(n.attributes)Array.from(n.attributes).forEach(a=>{obj['@'+a.name]=a.value}); Array.from(n.childNodes).forEach(c=>{ const v=node2obj(c);if(v===undefined)return; const k=c.nodeName==='#text'?'#text':c.nodeName; if(obj[k]===undefined)obj[k]=v; else if(Array.isArray(obj[k]))obj[k].push(v); else obj[k]=[obj[k],v]; }); return obj; } return node2obj(doc.documentElement); } function html2md(h){ return h .replace(/]*>(.*?)<\/h\1>/gi,(_,n,t)=>'#'.repeat(n)+' '+t.trim()+'\n\n') .replace(/]*>(.*?)<\/strong>/gi,'**$1**') .replace(/]*>(.*?)<\/b>/gi,'**$1**') .replace(/]*>(.*?)<\/em>/gi,'_$1_') .replace(/]*>(.*?)<\/i>/gi,'_$1_') .replace(/]*>(.*?)<\/code>/gi,'`$1`') .replace(/]+href="([^"]*)"[^>]*>(.*?)<\/a>/gi,'[$2]($1)') .replace(/]+src="([^"]*)"[^>]*alt="([^"]*)"[^>]*>/gi,'![$2]($1)') .replace(/]*>(.*?)<\/li>/gi,'- $1\n') .replace(/]*>(.*?)<\/p>/gi,'$1\n\n') .replace(//gi,'\n') .replace(/<[^>]+>/g,'') .replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>').replace(/"/g,'"').replace(/ /g,' ') .replace(/\n{3,}/g,'\n\n').trim(); } // ── DOWNLOAD ─────────────────────────────────────────── function dlBlob(blob,name){const url=URL.createObjectURL(blob);const a=document.createElement('a');a.href=url;a.download=name;a.click();setTimeout(()=>URL.revokeObjectURL(url),1000)} function dlAll(){S.results.forEach(( {blob,name},i)=>setTimeout(()=>dlBlob(blob,name),i*100))} // ── UTILS ────────────────────────────────────────────── function setSt(i,cls,txt){const el=document.getElementById('st'+i);if(el){el.className='fi-st '+cls;el.textContent=txt}} function setP(pct,txt){pgf.style.width=pct+'%';pgfR.style.width=pct+'%';pgt.textContent=txt} function updateTopStats(){document.getElementById('ts-f').textContent=S.stats.f;document.getElementById('ts-s').textContent=fb(S.stats.b);document.getElementById('ts-t').textContent=ft(S.stats.t)} function fb(b){if(!b)return'0B';if(b<1024)return b+'B';if(b<1048576)return(b/1024).toFixed(1)+'KB';return(b/1048576).toFixed(2)+'MB'} function ft(n){if(!n)return'0';if(n<1000)return String(n);if(n<1e6)return(n/1000).toFixed(1)+'K';return(n/1e6).toFixed(2)+'M'} function xExt(n){return n.split('.').pop().toUpperCase().slice(0,5)||'FILE'} function ne(n){return n.replace(/\.[^.]+$/,'')} function toast(msg,type=''){const t=document.getElementById('toast');t.textContent=msg;t.className='toast show '+type;setTimeout(()=>t.className='toast',3000)} async function ping(o,n,fc){try{await fetch('https://vektormemory.com/api/snap/analytics',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({tool:'vektor-convert',originalSize:o,newSize:n,fileCount:fc,savings:Math.round((1-n/o)*100),ts:Date.now()}),keepalive:true})}catch(e){}} function toggleRef(){ const p=document.getElementById('refPanel'); p.style.display=p.style.display==='none'?'block':'none'; }