UNPKG

@anolilab/unplugin-favicons

Version:

Generate favicons for your project with caching for blazing fast rebuilds.

7 lines (6 loc) 11.3 kB
var _=Object.defineProperty;var d=(e,a)=>_(e,"name",{value:a,configurable:!0});import{resolve as B,join as E,basename as H,parse as L}from"node:path";import{colorize as v}from"consola/utils";import{favicons as M}from"favicons";import{consola as W}from"consola/basic";import{readFileSync as K}from"node:fs";import V from"fast-json-stable-stringify";import{findCacheDirSync as G}from"@visulima/find-cache-dir";import{get as q,put as z}from"cacache";import{fromData as Q}from"ssri";import{parseFragment as X}from"parse5";import Y from"node:module";import{findPackageJsonSync as Z}from"@visulima/package";import T from"parse-author";const y="@anolilab/unplugin-favicons",ee={android:!1,appleIcon:!1,appleStartup:!1,coast:!1,favicons:!1,firefox:!1,windows:!1,yandex:!1},F={appShortName:void 0,appleStatusBarStyle:"black-translucent",background:"#fff",dir:"auto",display:"standalone",icons:{android:!0,appleIcon:!0,appleStartup:!0,favicons:!0,windows:!0,yandex:!1},lang:"en-US",loadManifestWithCredentials:!1,orientation:"any",pixel_art:!1,scope:"/",start_url:"/?homescreen=1",theme_color:"#fff",version:"1.0"},f=W.withTag(y);var ae=Object.defineProperty,S=d((e,a)=>ae(e,"name",{value:a,configurable:!0}),"o$4");const w=G(y),J=S(e=>Q(e).toString(),"computeKey"),P=S(async(e,{logLabel:a})=>{if(!w)throw new Error("Unable to find a suitable cache directory.");const n=J(e),t=`cache:get${a?`:${a}`:""}`;a&&f.debug(`${t} Generated digest for ${v("green",a)}:`,n);try{const s=await q(w,n),{data:u}=s;return a&&f.debug(`${t} Cache hit for ${a}`),u}catch(s){a&&(String(s?.message).includes("No cache entry")?f.debug(`${t} ${v("yellow","Cache miss.")}`):f.error(`${t} ${s}`));return}},"get"),O=S(async(e,a,{logLabel:n})=>{if(!w)throw new Error("Unable to find a suitable cache directory.");const t=J(e);if(await z(w,t,a),n){const s=`cache:put:${n}`;f.debug(`${s} ${v("green","Put OK.")}`)}},"put");var ne=Object.defineProperty,te=d((e,a)=>ne(e,"name",{value:a,configurable:!0}),"o$3");const oe=te(async e=>J(V({...e,source:K(e.source,{encoding:"utf8"})})),"generateCacheKeyForJob");var re=Object.defineProperty,se=d((e,a)=>re(e,"name",{value:a,configurable:!0}),"c$1");const ie=se(async(e,a)=>{const n=await P(e,{logLabel:a??""});if(!n)return;const t=JSON.parse(n.toString("utf8")),s=Promise.all(t.images.map(async o=>{const m=`${e}/images/${o.name}`,l=await P(m,{logLabel:o.name});if(!l)throw new Error(`Expected cached contents for "${m}"`);return{...o,contents:l}})),u=Promise.all(t.files.map(async o=>{const m=`${e}/files/${o.name}`,l=await P(m,{logLabel:o.name});if(!l)throw new Error(`Expected cached contents for "${m}"`);return{...o,contents:l.toString("utf8")}})),[p,c]=await Promise.all([u,s]);return{...t,files:p,images:c}},"getCacheResponse");var ce=Object.defineProperty,le=d((e,a)=>ce(e,"name",{value:a,configurable:!0}),"l$2");const ue=le(async(e,a,n)=>{const t={files:[],html:[],images:[]},s=Promise.all(a.images.map(async o=>{const{contents:m,...l}=o,i=`${e}/images/${l.name}`;t.images.push(l),f.verbose(`${n??""} Caching ${v("green",l.name)}.`),await O(i,m,{logLabel:l.name})})),u=Promise.all(a.files.map(async o=>{const{contents:m,...l}=o,i=`${e}/files/${l.name}`;t.files.push(l),f.verbose(`${n??""} Caching ${v("green",l.name)}.`),await O(i,m,{logLabel:l.name})}));a.html.forEach(o=>{t.html.push(o)});const p=JSON.stringify(t),c=O(e,p,{logLabel:n??""});await Promise.all([u,s,c])},"putCacheResponse");var pe=Object.defineProperty,D=d((e,a)=>pe(e,"name",{value:a,configurable:!0}),"g$2");const me=D(e=>{const{icons:a,...n}=e.favicons??{};return Object.entries(e.icons).reduce((t,[s,u])=>{const{source:p,...c}=u,o={...ee,[s]:c},m={config:{...n,icons:o},iconType:s,source:p};return[...t,m]},[])},"mapOptionsToJobs"),fe=D(e=>e.reduce((a,n)=>(n.files.forEach(t=>{a.files.push(t)}),n.images.forEach(t=>{a.images.push(t)}),n.html.forEach(t=>{a.html.push(t)}),a),{files:[],html:[],images:[]}),"reduceResponses"),ge=D(async e=>{const a=[];if(e.icons&&!e.logo)a.push(...me(e));else{const t={...F,...e.favicons,icons:{...F.icons,...e.favicons?.icons}};e.logo=B(e.logo??E("assets","logo.png")),a.push({config:t,iconType:"logo",source:e.logo})}const n=a.map(async t=>{const s=await oe(t),{config:u,iconType:p,source:c}=t,o=H(c);if(e.cache){const l=await ie(s,p);if(l)return f.verbose(`Using cached ${v("bold",p)} assets from source ${v("green",o)}.`),l}const m=await M(c,u);return e.cache&&ue(s,m,p).then(()=>{f.verbose(`Cached rendered ${v("bold",p)} assets from source ${v("green",o)}.`)}),m});return fe(await Promise.all(n))},"generateFavicons");var de=Object.defineProperty,he=d((e,a)=>de(e,"name",{value:a,configurable:!0}),"i$2");const N=he((e,a)=>{const n=L(a).name;return e.find(t=>n===L(t.name).name)},"findEmittedFile");var ve=Object.defineProperty,be=d((e,a)=>ve(e,"name",{value:a,configurable:!0}),"s$2");const $e=be((e,a,n="/")=>a.flatMap(t=>{const s=t;return X(t).childNodes.map(u=>{const p=u.attrs.map(c=>{if(c.name==="href"){const o=N(e,c.value);if(o)c.value=`${n}${o.resolvedName}`;else throw new Error(`Unable to find a corresponding file for href: ${c.value}`)}return[c.name,c.value]});return{attrs:Object.fromEntries(p),fragment:s,injectTo:"head",tag:u.nodeName}}).filter(Boolean)}),"parseHtml");var ye=Object.defineProperty,we=d((e,a)=>ye(e,"name",{value:a,configurable:!0}),"s$1");const ke=we((e,a)=>{const n=JSON.parse(a);return Array.isArray(n.icons)?n.icons=n.icons.map(t=>{const s=N(e,t.src);if(!s)throw new Error(`Unable to find a corresponding emitted file for manifest entry: ${t.src}`);return{...t,src:`/${s.resolvedName}`}}):typeof n.icons=="object"&&Object.keys(n.icons).length>0&&(n.icons=Object.fromEntries(Object.entries(n.icons).map(([t,s])=>{const u=N(e,s);if(!u)throw new Error(`Unable to find a corresponding emitted file for manifest entry: ${s}`);return[t,`/${u.resolvedName}`]}))),JSON.stringify(n)},"updateManifest");var Pe=Object.defineProperty,Oe=d((e,a)=>Pe(e,"name",{value:a,configurable:!0}),"o$1");const je=Oe(e=>{const{compiler:{options:a}}=e,n=a.plugins.find(t=>t?.constructor?.name==="HtmlRspackPlugin")?.constructor;if(n!==void 0)return n},"findHtmlRspackPlugin");var Ee=Object.defineProperty,C=d((e,a)=>Ee(e,"name",{value:a,configurable:!0}),"t$1");const U=Y.createRequire(import.meta.url),Ne=C(()=>{try{const e=U.resolve("html-webpack-plugin/package.json"),{version:a}=U(e);return`found html-webpack-plugin ${a} at ${e}`}catch{return"html-webpack-plugin not found"}},"getHtmlWebpackPluginVersion"),x=C(e=>{const{compiler:a}=e,n=a.options.plugins.find(t=>t?.constructor?.name==="HtmlWebpackPlugin")?.constructor;if(n!==void 0){if(n.version>=5)return n;e.errors.push(new a.webpack.WebpackError(`This @anolilab/unplugin-favicons version is not compatible with your current HtmlWebpackPlugin version. Please upgrade to HtmlWebpackPlugin >= 5 ${Ne()}`))}},"findHtmlWebpackPlugin");var Se=Object.defineProperty,Je=d((e,a)=>Se(e,"name",{value:a,configurable:!0}),"n");const De=Je(e=>{e<0&&(e=-e);const a={day:Math.floor(e/864e5),hour:Math.floor(e/36e5)%24,minute:Math.floor(e/6e4)%60,second:Math.floor(e/1e3)%60,ms:Math.floor(e)%1e3};return Object.entries(a).filter(n=>n[1]!==0).map(n=>n[0]==="ms"?`${n[1]} ${n[0]}`:`${n[1]} ${n[1]===1?n[0]:`${n[0]}s`}`).join(", ")},"formatDuration");var Ae=Object.defineProperty,Le=d((e,a)=>Ae(e,"name",{value:a,configurable:!0}),"a");class Te{static{d(this,"o")}static{Le(this,"Oracle")}packageJson;constructor(a){try{const n=Z(a);this.packageJson=n?.packageJson}catch{}}guessAppName(){return this.packageJson?.name}guessDescription(){return this.packageJson?.description}guessDeveloper(){if(this.packageJson?.author!==void 0){if(typeof this.packageJson.author=="string")return T(this.packageJson.author);if(typeof this.packageJson.author=="object"&&this.packageJson.author!==null)return{email:this.packageJson.author?.email,name:this.packageJson.author.name,url:this.packageJson.author?.url}}if(this.packageJson?.maintainers!==void 0&&Array.isArray(this.packageJson.maintainers)&&this.packageJson.maintainers.length>0){const a=this.packageJson.maintainers[0];if(typeof a=="string")return T(a);if(typeof a=="object"&&a!==null)return{email:a?.email,name:a.name,url:a?.url}}return{email:void 0,name:void 0,url:void 0}}guessVersion(){return this.packageJson?.version}}var Fe=Object.defineProperty,j=d((e,a)=>Fe(e,"name",{value:a,configurable:!0}),"g");const ze=j((e,a)=>{const n={cache:!0,inject:!0,...e},t=new Te(n?.projectRoot),s=t.guessDeveloper();n.favicons={appDescription:t.guessDescription(),appName:t.guessAppName(),developerName:s.name,developerURL:s.url,version:t.guessVersion(),...n.favicons};let u="",p,c=[],o=n.inject||n.inject?"ENABLED":"DISABLED";a.framework==="esbuild"&&(u="/",f.warn("html injection in esbuild is not supported, injection was disabled."),o="NOT_SUPPORTED");const m=j((i,r)=>{const{files:g,html:h,images:k}=r,A=k.map(b=>{const $=E(n.outputPath??"",b.name);return i.emitFile({fileName:$,source:b.contents,type:"asset"}),f.debug(`emit ${v("green",String($))}`),{name:b.name,resolvedName:$}}),I=g.map(b=>{const $=E(n.outputPath??"",b.name),R=b.name.includes("manifest")?ke(A,b.contents):b.contents;return i.emitFile({fileName:$,source:R,type:"asset"}),f.debug(`emit ${v("green",$)}`),{name:b.name,resolvedName:$}});c=$e([...I,...A],h,u)},"emitFiles"),l=j((i,r)=>{r&&r.getHooks(i)?.alterAssetTags?.tapPromise(y,async g=>(g.plugin.userOptions.favicon!==!1&&g.plugin.userOptions.favicons!==!1&&g.assetTags.meta.push(...c.map(h=>({attributes:h.attrs,meta:{plugin:y},tagName:h.tag,voidTag:!0}))),g))},"injectHtmlPlugin");return{apply:"build",async buildStart(){const i=Date.now(),r=await ge(n);f.info(`Generated assets in ${De(Date.now()-i)}.`),m(this,r),o==="DISABLED"&&(f.info("Inject is disabled, a webapp html file will be generated."),this.emitFile({fileName:"webapp.html",source:c.map(g=>g.fragment).join(` `),type:"asset"}))},name:y,order:"post",rollup:{generateBundle(i,r){o==="ENABLED"&&r["index.html"]&&typeof r["index.html"].source=="string"&&(r["index.html"].source=r["index.html"].source.replace("</head>",`${c.map(g=>g.fragment).join(` `)} </head>`))}},rspack(i){u="/",i.hooks.make.tapPromise(y,async r=>{if(o==="ENABLED"){const g=je(r),h=x(r);g?l(r,g):h?l(r,h):(f.warn('No "@rspack/plugin-html" or "html-webpack-plugin" plugin was found, injection was disabled, currently the builtin html is not supported.'),o="NOT_SUPPORTED")}})},vite:{configResolved(i){u=i.base,i.plugins.forEach(r=>{p===void 0&&r.name.includes("sveltekit")?(p="sveltekit",n.outputPath="_app/immutable/assets/"):p===void 0&&r.name.includes("astro")?p="astro":p===void 0&&r.name.includes("vike")&&(p="vike",n.outputPath="assets")})},generateBundle(i,r){p==="astro"&&Object.keys(r).forEach(g=>{const h=r[g];h?.fileName?.includes(".astro")&&(h.code=h.code.replaceAll(/<link rel="icon".*?>/gu,""),h.code=h.code.replace("</head>",`${c.map(k=>k.fragment).join("")}</head>`))})},transformIndexHtml:{handler(i){return o==="ENABLED"&&(i=i.replaceAll(/<link rel="icon".*?>/gu,""),i=i.replace("</head>",`${c.map(r=>r.fragment).join("")}</head>`)),i},order:"post"}},webpack(i){i.options.output.path?.includes(".next")?(n.outputPath="static/media/favicons/",o="NOT_SUPPORTED"):u="/",i.hooks.make.tapPromise(y,async r=>{f.info(r),o==="ENABLED"&&l(r,x(r))})}}},"unpluginFactory");export{ze as U};