vite-plugin-svg-symbols
Version:
Vite plugin for creating SVG symbol sprite
22 lines (20 loc) • 6.87 kB
JavaScript
;Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const i=require("node:path"),S=require("node:fs/promises"),J=require("node:crypto"),Z=(e=[],n)=>{const c=new Map,f=async s=>{const m=await S.stat(s);if(c.has(s)){const[g,I]=c.get(s)||[0,[]];if(g===m.mtimeMs){const[l]=I;return l}}const p=await S.readFile(s,{encoding:"utf8"}),y=await(typeof n=="function"?n(p,s):Promise.resolve(p));return c.set(s,[m.mtimeMs,[y]]),y},o=async s=>{const m=await S.stat(s);if(c.has(s)){const[g,I]=c.get(s)||[0,[]];if(g===m.mtimeMs)return I}const p=[],y=await S.readdir(s,{withFileTypes:!0});for(const g of y){if(g.isDirectory()){const I=await o(i.join(s,g.name));p.push(...I)}(e.length===0||e.includes(i.extname(g.name)))&&p.push(i.join(s,g.name))}return c.set(s,[m.mtimeMs,p]),p};return{store:c,getDirContent:o,getFileContent:f}},K=()=>{const e={isDevMode:!1,isTestMode:!1,root:"",base:"",assets:"",aliases:{}},n=o=>o.reduce((s,m)=>(typeof m.find=="string"&&(s[m.find]=m.replacement),s),{});return{config:e,updateConfig:o=>{e.isDevMode=o.command==="serve",e.isTestMode=o.mode==="plugintest",e.root=o.root,e.base=o.base,e.assets=o.build.assetsDir,e.aliases={"@icons":i.join(e.root,"src","icons"),...n(o.resolve.alias)}},findAliasName:o=>{const[s=[]]=Object.entries(e.aliases).filter(([p,y])=>o.startsWith(y)).sort(([,p],[,y])=>y.length-p.length),[m=""]=s;return m.replace("@","")}}},Q="\0virtual:",R="\0virtual:symbol:",W="\0virtual:svg:symbols",P=".svg?symbol",tt="svg:symbols@",B="/@id/__vite-plugin-svg-symbols__.svg",et={"aria-hidden":"true",style:["position:absolute;","top:0;","left:0;","width:1px;","height:1px;","visibility:hidden;","opacity:0;"].join("")},st=["fill","stroke","stroke-dasharray","stroke-dashoffset","stroke-linecap","stroke-linejoin","stroke-miterlimit","stroke-opacity","stroke-width"],ot=`declare module 'svg:symbols@[alias]' {
[content]
const symbols: Record<string, string>;
export default symbols;
}`,nt=`/**
* @see [see]
*/`,U=`/**
* Vite plugin for creating SVG symbol sprite
* @see [Documentation on Github](https://github.com/werty1001/vite-plugin-svg-symbols)
*/`,rt=`declare module '*.svg?symbol' {
const src: string
export default src
}`,at=(e,n)=>i.relative(e,n).split(i.sep).join("_").replace(/[-_]([a-z0-9])/gi,(f,o)=>o.toUpperCase()).replace(".svg","").concat("Icon"),H=(e,n=8)=>J.createHash("sha256").update(e).digest("hex").slice(0,n),it=(e,n=".svg")=>e.replace(n,"").trim().concat(n),V=e=>`<svg xmlns="http://www.w3.org/2000/svg">${e}</svg>`,Y=e=>{const[,n=""]=e.split("#");return n},ct=(e,n)=>i.relative(n,e).replace(".svg","").replace("node_modules".concat(i.sep),"").replace("src".concat(i.sep),"").split(i.sep).join("-"),lt=(e,n,c,f)=>{const o=/<svg([^>]*)>([\s\S]*?)<\/svg>/,s=/([a-zA-Z-]+)\s*=\s*["']([^"']*)["']/g,[,m="",p=""]=e.match(o)||[],y=p.trim().replace(/>((\r\n|\n|\r)(\s+)?)</g,"><"),g={viewBox:"0 0 24 24"},I=m.matchAll(s);if(I)for(const j of I){const[,_,T]=j;g[_.trim()]=T.trim()}const l=f.reduce((j,_)=>{const T=g[_];return T&&j.push([_,`"${T}"`].join("=")),j},[]).join(" "),x=l?`<g ${l}>${y}</g>`:y,E=g.viewBox;return[`<symbol viewBox="${E}" id="${c}">${x}</symbol>`,{symbolId:c,symbolBody:x,symbolViewBox:E,svgBody:y,svgPath:n,svgAttrs:g}]},dt=(e,n)=>{const c=new RegExp(n.concat("#([^'\"`]*)"),"gi"),f=Object.keys(e).reduce((o,s)=>{if(s.endsWith(".js")||s.endsWith(".mjs")){const p=e[s].code.match(c)||[];o.push(...p)}return o},[]);return new Set(f)},ut=(e,n,c)=>{Object.keys(e).forEach(f=>{if(!f.endsWith(".js")&&!f.endsWith(".mjs"))return;const o=e[f];o.code&&(o.code=o.code.replace(n,c))})},q=et,z=st,mt=e=>{const{fileName:n="sprite-[hash]",shouldInheritAttrs:c=z,shouldInjectToHtml:f=!1,injectAttrs:o=q,transformIcon:s=t=>t,transformIconId:m=t=>t,transformSymbol:p=t=>t,transformSprite:y=t=>t,transformImportName:g=t=>t,transformImportComment:I=t=>t}=e||{},{config:l,updateConfig:x,findAliasName:E}=K(),{getDirContent:j,getFileContent:_}=Z([".svg"],s),T=new Map,D=async t=>{const r=l.isDevMode?`?v=${Date.now()}`:"",a=await m(ct(t,l.root),t);return[B.concat(r),a].join("#")},L=async t=>{const[r,a]=await Promise.all([_(t),D(t)]),[u,d]=lt(r,t,Y(a),c),v=await p(u,d);return T.set(t,v),a},O=async t=>{const r=Array.from(T.keys()).sort((u,d)=>{const v=i.relative(l.root,u),h=i.relative(l.root,d);return v>h?1:-1});let a="";for(const u of r){const d=T.get(u)||"";if(!t){a+=d;continue}const v=await D(u);t.has(v)&&(a+=d)}return y(a)},k=new Map,G=async t=>{const r=l.aliases[`@${t}`]||"";if(!r)throw new Error([`The alias @${t} is not defined.`,"Please add it to your vite.config.ts"].join(" "));const a=await j(r),u=[];let d="",v="";for(const h of a){const[b,w]=await Promise.all([g(at(r,h),h),L(h)]);d+=`export const ${b} = '${w}';
`,v+=`${b}, `,u.push([h,b,w])}return k.set(t,u),d.concat(`export default { ${v}};`)},X=async()=>{let t="";for(const[a,u]of k.entries()){let d="";for(const[h,b,w]of u){const M=i.relative(l.root,h),A=nt.replace("[see]",`[${M}](file://${h})`),$=await I(A,h),N=`export const ${b}: '#${Y(w)}'`;d+=[$,N,`
`].join(`
`)}const v=ot.replace("[alias]",a).replace("[content]",d);t+=[U,v,`
`].join(`
`)}t+=[[U,rt].join(`
`)].join(`
`);const r=l.isTestMode?i.join(l.root,"app","client.d.ts"):i.join(l.root,"node_modules","vite-plugin-svg-symbols","client.d.ts");return S.writeFile(r,t)};let C,F="";return{name:"vite-plugin-svg-symbols",enforce:"pre",closeWatcher(){clearTimeout(C)},configResolved(t){x(t)},configureServer({watcher:t,middlewares:r,ws:a,moduleGraph:u}){const d=new Set,v=()=>{for(const b of d){const w=W.concat("@",b),M=u.getModuleById(w);M&&u.invalidateModule(M)}d.clear(),a.send({type:"full-reload",path:"*"})},h=()=>{clearTimeout(C),C=setTimeout(v,50)};t.on("all",(b,w)=>{if(!w.endsWith(".svg"))return;const M=E(w);M&&(d.add(M),h())}),r.use(B,async(b,w)=>{const M=await O(),A=V(M),$=H(A,32),N=b.headers["if-none-match"];if($===N){w.writeHead(304,{"Content-Length":0}).end("");return}w.writeHead(200,{"Content-Length":Buffer.byteLength(A),"Content-Type":"image/svg+xml","Cache-Control":"no-cache",Etag:$}).end(A)})},resolveId(t,r=""){if(t.endsWith(P)){const a=i.isAbsolute(t)?t:i.resolve(i.dirname(r),t);return R.concat(a.replace(P,".svg"))}return t.startsWith(tt)?Q.concat(t):null},async load(t){if(t.startsWith(R)){const r=t.replace(R,"");return`export default '${await L(r)}';`}if(t.startsWith(W)){const[,r="icons"]=t.split("@"),a=await G(r);return await X(),a}return null},transformIndexHtml(){if(!(l.isDevMode||!f))return[{tag:"svg",attrs:o,children:F,injectTo:"body-prepend"}]},async generateBundle(t,r){if(l.isDevMode)return;const a=dt(r,B),u=await O(a),d=V(u),v=H(d),h=it(n.replace("[hash]",v)),b=f?"":i.join(l.base,l.assets,h),w=new RegExp(B,"g");ut(r,w,b),f?F=u:this.emitFile({type:"asset",fileName:i.join(l.assets,h),source:d})}}};exports.default=mt;exports.defaultInheritAttrs=z;exports.defaultInjectAttrs=q;