UNPKG

visionary-url

Version:

A lightweight library for generating image URLs with baked-in blurhash placeholders.

2 lines (1 loc) 9.62 kB
"use strict";var ge=Object.defineProperty;var me=(r,t,o)=>t in r?ge(r,t,{enumerable:!0,configurable:!0,writable:!0,value:o}):r[t]=o;var Y=(r,t,o)=>me(r,typeof t!="symbol"?t+"":t,o);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const u=require("./constants-BbfMtzIs.cjs");var I=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{},w={},J={exports:{}};(function(r,t){(function(o,a){r.exports=a()})(typeof self<"u"?self:typeof window<"u"?window:I,function(){var o="3.7.7",a=o,i=typeof Buffer=="function",l=typeof TextDecoder=="function"?new TextDecoder:void 0,h=typeof TextEncoder=="function"?new TextEncoder:void 0,y="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",p=Array.prototype.slice.call(y),c=function(e){var n={};return e.forEach(function(f,d){return n[f]=d}),n}(p),k=/^(?:[A-Za-z\d+\/]{4})*?(?:[A-Za-z\d+\/]{2}(?:==)?|[A-Za-z\d+\/]{3}=?)?$/,s=String.fromCharCode.bind(String),T=typeof Uint8Array.from=="function"?Uint8Array.from.bind(Uint8Array):function(e){return new Uint8Array(Array.prototype.slice.call(e,0))},v=function(e){return e.replace(/=/g,"").replace(/[+\/]/g,function(n){return n=="+"?"-":"_"})},x=function(e){return e.replace(/[^A-Za-z0-9\+\/]/g,"")},U=function(e){for(var n,f,d,b,g="",D=e.length%3,_=0;_<e.length;){if((f=e.charCodeAt(_++))>255||(d=e.charCodeAt(_++))>255||(b=e.charCodeAt(_++))>255)throw new TypeError("invalid character found");n=f<<16|d<<8|b,g+=p[n>>18&63]+p[n>>12&63]+p[n>>6&63]+p[n&63]}return D?g.slice(0,D-3)+"===".substring(D):g},m=typeof btoa=="function"?function(e){return btoa(e)}:i?function(e){return Buffer.from(e,"binary").toString("base64")}:U,C=i?function(e){return Buffer.from(e).toString("base64")}:function(e){for(var n=4096,f=[],d=0,b=e.length;d<b;d+=n)f.push(s.apply(null,e.subarray(d,d+n)));return m(f.join(""))},E=function(e,n){return n===void 0&&(n=!1),n?v(C(e)):C(e)},se=function(e){if(e.length<2){var n=e.charCodeAt(0);return n<128?e:n<2048?s(192|n>>>6)+s(128|n&63):s(224|n>>>12&15)+s(128|n>>>6&63)+s(128|n&63)}else{var n=65536+(e.charCodeAt(0)-55296)*1024+(e.charCodeAt(1)-56320);return s(240|n>>>18&7)+s(128|n>>>12&63)+s(128|n>>>6&63)+s(128|n&63)}},fe=/[\uD800-\uDBFF][\uDC00-\uDFFFF]|[^\x00-\x7F]/g,V=function(e){return e.replace(fe,se)},j=i?function(e){return Buffer.from(e,"utf8").toString("base64")}:h?function(e){return C(h.encode(e))}:function(e){return m(V(e))},A=function(e,n){return n===void 0&&(n=!1),n?v(j(e)):j(e)},N=function(e){return A(e,!0)},le=/[\xC0-\xDF][\x80-\xBF]|[\xE0-\xEF][\x80-\xBF]{2}|[\xF0-\xF7][\x80-\xBF]{3}/g,ce=function(e){switch(e.length){case 4:var n=(7&e.charCodeAt(0))<<18|(63&e.charCodeAt(1))<<12|(63&e.charCodeAt(2))<<6|63&e.charCodeAt(3),f=n-65536;return s((f>>>10)+55296)+s((f&1023)+56320);case 3:return s((15&e.charCodeAt(0))<<12|(63&e.charCodeAt(1))<<6|63&e.charCodeAt(2));default:return s((31&e.charCodeAt(0))<<6|63&e.charCodeAt(1))}},P=function(e){return e.replace(le,ce)},W=function(e){if(e=e.replace(/\s+/g,""),!k.test(e))throw new TypeError("malformed base64.");e+="==".slice(2-(e.length&3));for(var n,f="",d,b,g=0;g<e.length;)n=c[e.charAt(g++)]<<18|c[e.charAt(g++)]<<12|(d=c[e.charAt(g++)])<<6|(b=c[e.charAt(g++)]),f+=d===64?s(n>>16&255):b===64?s(n>>16&255,n>>8&255):s(n>>16&255,n>>8&255,n&255);return f},O=typeof atob=="function"?function(e){return atob(x(e))}:i?function(e){return Buffer.from(e,"base64").toString("binary")}:W,Z=i?function(e){return T(Buffer.from(e,"base64"))}:function(e){return T(O(e).split("").map(function(n){return n.charCodeAt(0)}))},H=function(e){return Z($(e))},de=i?function(e){return Buffer.from(e,"base64").toString("utf8")}:l?function(e){return l.decode(Z(e))}:function(e){return P(O(e))},$=function(e){return x(e.replace(/[-_]/g,function(n){return n=="-"?"+":"/"}))},F=function(e){return de($(e))},he=function(e){if(typeof e!="string")return!1;var n=e.replace(/\s+/g,"").replace(/={0,2}$/,"");return!/[^\s0-9a-zA-Z\+/]/.test(n)||!/[^\s0-9a-zA-Z\-_]/.test(n)},G=function(e){return{value:e,enumerable:!1,writable:!0,configurable:!0}},M=function(){var e=function(n,f){return Object.defineProperty(String.prototype,n,G(f))};e("fromBase64",function(){return F(this)}),e("toBase64",function(n){return A(this,n)}),e("toBase64URI",function(){return A(this,!0)}),e("toBase64URL",function(){return A(this,!0)}),e("toUint8Array",function(){return H(this)})},X=function(){var e=function(n,f){return Object.defineProperty(Uint8Array.prototype,n,G(f))};e("toBase64",function(n){return E(this,n)}),e("toBase64URI",function(){return E(this,!0)}),e("toBase64URL",function(){return E(this,!0)})},pe=function(){M(),X()},B={version:o,VERSION:a,atob:O,atobPolyfill:W,btoa:m,btoaPolyfill:U,fromBase64:F,toBase64:A,encode:A,encodeURI:N,encodeURL:N,utob:V,btou:P,decode:F,isValid:he,fromUint8Array:E,toUint8Array:H,extendString:M,extendUint8Array:X,extendBuiltins:pe};return B.Base64={},Object.keys(B).forEach(function(e){return B.Base64[e]=B[e]}),B})})(J);var be=J.exports;Object.defineProperty(w,"__esModule",{value:!0});var K=w.decodeBase64Url=ee=w.encodeBase64Url=void 0;const Q=be,ye=r=>{if(typeof r!="string")throw new Error("encodeBase64Url: input must be a string");return(0,Q.encode)(r).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")};var ee=w.encodeBase64Url=ye;const ve=r=>{if(typeof r!="string")throw new Error("decodeBase64Url: input must be a string");return(0,Q.decode)(r.replace(/-/g,"+").replace(/_/g,"/"))};K=w.decodeBase64Url=ve;const xe=r=>r.filter(Boolean),q=r=>{try{return new URL(r)}catch{return null}},Ue=r=>{switch(r){case u.ImageFormatToken.AVIF:return{contentType:"image/avif",extension:"avif"};case u.ImageFormatToken.JPEG:return{contentType:"image/jpeg",extension:"jpg"};case u.ImageFormatToken.WEBP:return{contentType:"image/webp",extension:"webp"};default:throw new Error(`formatToContentType: unknown format ${r}`)}},S=(r="")=>/^[A-Za-z0-9_-]*$/.test(r),Ae=(r,t)=>{const o=r/t,a=u.BASE_BLURHASH_DIMENSIONS;let i=u.BASE_BLURHASH_DIMENSIONS;return o>=1.6&&(i=3),[a,i]},re=r=>{const{altText:t,bcc:o,blurhash:a,blurhashX:i,blurhashY:l,sourceHeight:h,sourceWidth:y,url:p}=r;if(!p||!y||!h)return new Error("Cannot construct visionary code: missing required url/width/height");const c=[p,y,h];return!o||(c.push(o),!a||!i||!l)||(c.push(a,i,l),t&&t.length&&c.push(t)),R(c)},R=r=>ee(r.join(u.V_CODE_SEPARATOR)),z=r=>{if(typeof r!="string")return null;const t=r.trim();if(!t.length||!S(t))return null;const o=K(t);if(!o)return null;const a=o.split(u.V_CODE_SEPARATOR);if(a.length<3)return null;const[i,l,h,y,p,c,k,s]=a,T=i.trim();if(!T.length)return console.error("Cannot parse code, empty file id"),null;const v=Number(l.trim()),x=Number(h.trim());if(isNaN(v)||isNaN(x)||!v||!x)return console.error("Cannot parse Visionary Code: invalid image dimensions",l,h),null;const U=Number(c)??0,m=Number(k)??0;return U<1||m<1?(console.error("Cannot parse Visionary Code: invalid blurhash x, y component dimensions",U,m),null):{altText:s,bcc:y,blurhash:p,blurhashX:U,blurhashY:m,sourceHeight:x,sourceWidth:v,url:T}};class Te extends Error{constructor(){super(...arguments);Y(this,"message","invalid endpoint URL (does it contain http/https?)")}}const ne=r=>r===u.UrlOptionToken.DEBUG,te=r=>r===u.UrlOptionToken.DOWNLOAD,oe=r=>r===u.UrlOptionToken.FOLLOW,ae=r=>Object.values(u.ImageFormatToken).includes(r),L=r=>Object.values(u.ImageSizeToken).includes(r),ie=(r=[])=>{const t={};for(const o of r)L(o)?t.size=u.ImageSizeToken[o]:ne(o)?t.debug=!0:te(o)?t.download=!0:oe(o)?t.follow=!0:ae(o)&&(t.format=o);return t},Be=r=>{if(!r||typeof r!="object")return null;const t=[];return r.debug&&t.push(u.UrlOptionToken.DEBUG),r.download&&t.push(u.UrlOptionToken.DOWNLOAD),r.follow&&t.push(u.UrlOptionToken.FOLLOW),r.format&&r.format!==u.ImageFormatToken.AUTO&&t.push(r.format),r.size&&L(r.size)&&t.push(r.size),t.length?t.sort().join(","):null},we=(r="")=>ie(r.split(",")),Ce=r=>{if(S(r)){const o=z(r);if(o)return{fields:o,options:{}}}return ue(r)},ue=r=>{if(!r)return null;const t=r.trim();if(!t)return null;try{const o=_e(t);if(!o)return null;const{code:a,optionTokens:i}=o,l=z(a);if(!l)return null;const h=ie(i);return{fields:l,options:h}}catch(o){o instanceof Error?console.error(`Error parsing URL: ${o.message}`,o):console.error("uncaught error",o)}return null},Ee=(r,t)=>{const o=re(r);if(o instanceof Error)return null;let a=null;if(t!=null&&t.endpoint&&(a=q(t==null?void 0:t.endpoint),!a))throw new Te("Cannot construct URL: bad endpoint. Ensure endpoint starts with http:// or https://");a||(a=q(u.DEFAULT_ENDPOINT));const i=[a.origin,"image",o],l=t?Be(t):null;return l&&i.push(l),t!=null&&t.filename?i.push(t.filename):i.push("image.jpg"),i.join("/")},_e=r=>{try{const t=new URL(r),o=xe(t.pathname.split("/"));if(o[0]!=="image"||![3,4].includes(o.length))throw new Error("Unrecognized URL");const a=o[1].trim();if(!a.length||!S(a))throw new Error("URL is not formatted as base64url");if(o.length===4){const i=o[2].split(",");return{code:a,optionTokens:i}}if(o.length===3)return{code:a,optionTokens:[]}}catch{return null}return null};exports.ImageFormatToken=u.ImageFormatToken;exports.ImageSizeToken=u.ImageSizeToken;exports.UrlOptionToken=u.UrlOptionToken;exports.formatToContentType=Ue;exports.generateVisionaryCode=re;exports.generateVisionaryUrl=Ee;exports.isBase64UrlEncoded=S;exports.isDebugToken=ne;exports.isDownloadToken=te;exports.isFollowToken=oe;exports.isImageFormatToken=ae;exports.isImageSizeToken=L;exports.parseOptionsString=we;exports.parseVisionaryCode=z;exports.parseVisionaryString=Ce;exports.parseVisionaryUrl=ue;exports.suggestedBlurhashComponentDimensions=Ae;