@takumi-rs/helpers 2.0.0-rc.9 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ const e=/url\(\s*(['"]?)(.*?)\1\s*\)/g;async function t(e,t={}){if(t.allowUrl&&!t.allowUrl(e))throw Error(`URL blocked by allowUrl policy: ${e}`);let n=t.fetch??globalThis.fetch,r=t.timeout??5e3,i=r<=0?void 0:AbortSignal.timeout(r),a=[t.signal,t.init?.signal,i].filter(e=>e!==void 0),o=a.length?AbortSignal.any(a):void 0,s=await n(e,{...t.init,signal:o});if(!s.ok)throw Error(`HTTP ${s.status} ${s.statusText} fetching ${e}`);return s}async function n(e,t){let n=Number(e.headers.get(`content-length`));if(Number.isFinite(n)&&n>t)throw Error(`Response exceeds ${t} bytes (content-length ${n})`);let r=e.body;if(!r)return e.arrayBuffer();let i=r.getReader(),a=[],o=0;for(;;){let{done:e,value:n}=await i.read();if(e)break;if(o+=n.byteLength,o>t)throw await i.cancel().catch(()=>{}),Error(`Response exceeds ${t} bytes`);a.push(n)}let s=new Uint8Array(o),c=0;for(let e of a)s.set(e,c),c+=e.byteLength;return s.buffer}function r(e){return e.startsWith(`https://`)||e.startsWith(`http://`)}function i(t,n){if(typeof t==`string`)for(let i of t.matchAll(e)){let e=i[2]?.trim();e&&r(e)&&n.add(e)}else if(Array.isArray(t))for(let e of t)i(e,n)}function a(e){let t=new Set,n=e=>{let a=e=>{e&&(i(e.backgroundImage,t),i(e.maskImage,t))};if(a(e.style),a(e.preset),i(e.tw,t),e.type===`image`){typeof e.src==`string`&&r(e.src)&&t.add(e.src);return}if(e.type===`container`)for(let t of e.children??[])n(t)};return n(e),[...t]}function o(e,r,i){let a=i?.get(e);if(a)return a;let o=t(e,r).then(e=>n(e,r.maxBytes??33554432)).catch(t=>{throw i?.delete(e),t});return i?.set(e,o),o}async function s({node:e,sources:t=[],fetchCache:n,fetch:r,timeout:i,signal:s,maxBytes:c,allowUrl:l,throwOnError:u=!0}){let d=Array.isArray(e)?e:[e],f=new Map;for(let e of t)f.set(e.src,e);let p=[...new Set(d.flatMap(a))].filter(e=>!f.has(e)),m={fetch:r,timeout:i,signal:s,maxBytes:c,allowUrl:l},h=p.map(async e=>({src:e,data:await o(e,m,n)})),g=u?await Promise.all(h):(await Promise.allSettled(h)).filter(e=>e.status===`fulfilled`).map(e=>e.value);return[...f.values(),...g]}const c=new Map;function l(e,t,n,r){let i=new Map(r),a=n.includes(`italic`),o=a?n.includes(`normal`)?[0,1]:[1]:[void 0],s=[...a?[`ital`]:[],...i.keys(),`wght`].sort(),c=o.flatMap(e=>t.map(t=>s.map(n=>n===`ital`?String(e):n===`wght`?t:i.get(n)??``).join(`,`))).sort();return`${e}:${s.join(`,`)}@${c.join(`;`)}`}function u(e){let t=new URL(e.baseUrl??`https://fonts.googleapis.com/css2`);for(let n of e.families){if(typeof n==`string`){t.searchParams.append(`family`,l(n,[`400`],[`normal`],[]));continue}let e=n.weight??400,r=(Array.isArray(e)?[...e].sort((e,t)=>e-t):[e]).map(String),i=n.style??`normal`,a=(Array.isArray(i)?i:[i]).map(String),o=Object.entries(n.axes??{}).filter(([e])=>e!==`ital`&&e!==`wght`).map(([e,t])=>[e,String(t)]);t.searchParams.append(`family`,l(n.name,r,a,o))}return e.display&&t.searchParams.set(`display`,e.display),t.toString()}function d(e,r){return t(e,{...r,init:{headers:{"User-Agent":`Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36`}}}).then(e=>n(e,r.maxBytes??2097152)).then(e=>new TextDecoder().decode(e))}function f(e,t){let n=t.cache??c,r=n.get(e);if(r)return r;let i=d(e,t);return n.set(e,i),i.catch(()=>n.delete(e)),i}const p=/(?:\/\*\s*([^*]+?)\s*\*\/\s*)?@font-face\s*\{([^}]*)\}/g;function m(e,r){let i=`${e.family} ${e.subset}`,a=e.ranges.map(([e,t])=>`${e}-${t}`).join(`,`);return{name:i,subsetOf:e.family,key:`${i}:${e.weight??``}:${e.style??``}:${a}`,weight:e.weight,style:e.style,ranges:e.ranges,data:()=>t(e.url,r).then(e=>n(e,r.maxBytes??33554432))}}function h(e){let t=[];for(let n of e.split(`,`)){let e=n.trim().replace(/^U\+/i,``);if(e)if(e.includes(`-`)){let[n,r]=e.split(`-`);n&&r&&t.push([parseInt(n,16),parseInt(r,16)])}else if(e.includes(`?`))t.push([parseInt(e.replace(/\?/g,`0`),16),parseInt(e.replace(/\?/g,`F`),16)]);else{let n=parseInt(e,16);t.push([n,n])}}return t}function g(e){let t=[],n=0;for(let r of e.matchAll(p)){let e=r[2];if(!e)continue;let i=e.match(/src:\s*url\(([^)]+)\)/)?.[1]?.replace(/['"]/g,``).trim(),a=e.match(/font-family:\s*['"]?([^'";]+)['"]?/)?.[1]?.trim();if(!i||!a)continue;let o=e.match(/unicode-range:\s*([^;]+)/)?.[1],s=e.match(/font-weight:\s*(\d+)(?:\s+(\d+))?/);t.push({family:a,subset:r[1]?.trim()||`subset-${n}`,url:i,weight:s&&!s[2]?Number(s[1]):void 0,style:e.match(/font-style:\s*([a-z]+)/i)?.[1],ranges:o?h(o):[]}),n+=1}return t}function _(e){let t=new Map;for(let n of e){let e=t.get(n.url)??new Set;e.add(n.weight),t.set(n.url,e)}let n=new Set,r=[];for(let i of e){if(n.has(i.url))continue;n.add(i.url);let e=(t.get(i.url)?.size??0)>1;r.push(e?{...i,weight:void 0}:i)}return r}function v(e){let t=new Set,n=e=>{for(let n of e)t.add(n.codePointAt(0))},r=e=>{e.type===`text`?n(e.text):e.type===`container`&&e.children?.forEach(r)};return typeof e==`string`?n(e):Array.isArray(e)?e.forEach(r):r(e),t}function y(e,t){if(e.length===0)return!0;for(let n of t)for(let[t,r]of e)if(n>=t&&n<=r)return!0;return!1}function b({fonts:e,source:t}){let n=v(t);return e.filter(e=>y(e.ranges??[],n))}function x(e,r={}){return{key:e,data:()=>t(e,r).then(e=>n(e,r.maxBytes??33554432))}}async function S(e){if(e.families.length===0)return[];let t=await f(u(e),e),n=new Map(e.families.map((e,t)=>[typeof e==`string`?e:e.name,t]));return _(g(t)).sort((e,t)=>(n.get(e.family)??0)-(n.get(t.family)??0)).map(t=>m(t,e))}Object.defineProperty(exports,"a",{enumerable:!0,get:function(){return 33554432}}),Object.defineProperty(exports,"c",{enumerable:!0,get:function(){return n}}),Object.defineProperty(exports,"i",{enumerable:!0,get:function(){return b}}),Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return x}}),Object.defineProperty(exports,"o",{enumerable:!0,get:function(){return t}}),Object.defineProperty(exports,"r",{enumerable:!0,get:function(){return S}}),Object.defineProperty(exports,"s",{enumerable:!0,get:function(){return s}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return v}});
@@ -0,0 +1 @@
1
+ const e=32*1024*1024,t=/url\(\s*(['"]?)(.*?)\1\s*\)/g;async function n(e,t={}){if(t.allowUrl&&!t.allowUrl(e))throw Error(`URL blocked by allowUrl policy: ${e}`);let n=t.fetch??globalThis.fetch,r=t.timeout??5e3,i=r<=0?void 0:AbortSignal.timeout(r),a=[t.signal,t.init?.signal,i].filter(e=>e!==void 0),o=a.length?AbortSignal.any(a):void 0,s=await n(e,{...t.init,signal:o});if(!s.ok)throw Error(`HTTP ${s.status} ${s.statusText} fetching ${e}`);return s}async function r(e,t){let n=Number(e.headers.get(`content-length`));if(Number.isFinite(n)&&n>t)throw Error(`Response exceeds ${t} bytes (content-length ${n})`);let r=e.body;if(!r)return e.arrayBuffer();let i=r.getReader(),a=[],o=0;for(;;){let{done:e,value:n}=await i.read();if(e)break;if(o+=n.byteLength,o>t)throw await i.cancel().catch(()=>{}),Error(`Response exceeds ${t} bytes`);a.push(n)}let s=new Uint8Array(o),c=0;for(let e of a)s.set(e,c),c+=e.byteLength;return s.buffer}function i(e){return e.startsWith(`https://`)||e.startsWith(`http://`)}function a(e,n){if(typeof e==`string`)for(let r of e.matchAll(t)){let e=r[2]?.trim();e&&i(e)&&n.add(e)}else if(Array.isArray(e))for(let t of e)a(t,n)}function o(e){let t=new Set,n=e=>{let r=e=>{e&&(a(e.backgroundImage,t),a(e.maskImage,t))};if(r(e.style),r(e.preset),a(e.tw,t),e.type===`image`){typeof e.src==`string`&&i(e.src)&&t.add(e.src);return}if(e.type===`container`)for(let t of e.children??[])n(t)};return n(e),[...t]}function s(e,t,i){let a=i?.get(e);if(a)return a;let o=n(e,t).then(e=>r(e,t.maxBytes??33554432)).catch(t=>{throw i?.delete(e),t});return i?.set(e,o),o}async function c({node:e,sources:t=[],fetchCache:n,fetch:r,timeout:i,signal:a,maxBytes:c,allowUrl:l,throwOnError:u=!0}){let d=Array.isArray(e)?e:[e],f=new Map;for(let e of t)f.set(e.src,e);let p=[...new Set(d.flatMap(o))].filter(e=>!f.has(e)),m={fetch:r,timeout:i,signal:a,maxBytes:c,allowUrl:l},h=p.map(async e=>({src:e,data:await s(e,m,n)})),g=u?await Promise.all(h):(await Promise.allSettled(h)).filter(e=>e.status===`fulfilled`).map(e=>e.value);return[...f.values(),...g]}const l=new Map;function u(e,t,n,r){let i=new Map(r),a=n.includes(`italic`),o=a?n.includes(`normal`)?[0,1]:[1]:[void 0],s=[...a?[`ital`]:[],...i.keys(),`wght`].sort(),c=o.flatMap(e=>t.map(t=>s.map(n=>n===`ital`?String(e):n===`wght`?t:i.get(n)??``).join(`,`))).sort();return`${e}:${s.join(`,`)}@${c.join(`;`)}`}function d(e){let t=new URL(e.baseUrl??`https://fonts.googleapis.com/css2`);for(let n of e.families){if(typeof n==`string`){t.searchParams.append(`family`,u(n,[`400`],[`normal`],[]));continue}let e=n.weight??400,r=(Array.isArray(e)?[...e].sort((e,t)=>e-t):[e]).map(String),i=n.style??`normal`,a=(Array.isArray(i)?i:[i]).map(String),o=Object.entries(n.axes??{}).filter(([e])=>e!==`ital`&&e!==`wght`).map(([e,t])=>[e,String(t)]);t.searchParams.append(`family`,u(n.name,r,a,o))}return e.display&&t.searchParams.set(`display`,e.display),t.toString()}function f(e,t){return n(e,{...t,init:{headers:{"User-Agent":`Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36`}}}).then(e=>r(e,t.maxBytes??2097152)).then(e=>new TextDecoder().decode(e))}function p(e,t){let n=t.cache??l,r=n.get(e);if(r)return r;let i=f(e,t);return n.set(e,i),i.catch(()=>n.delete(e)),i}const m=/(?:\/\*\s*([^*]+?)\s*\*\/\s*)?@font-face\s*\{([^}]*)\}/g;function h(e,t){let i=`${e.family} ${e.subset}`,a=e.ranges.map(([e,t])=>`${e}-${t}`).join(`,`);return{name:i,subsetOf:e.family,key:`${i}:${e.weight??``}:${e.style??``}:${a}`,weight:e.weight,style:e.style,ranges:e.ranges,data:()=>n(e.url,t).then(e=>r(e,t.maxBytes??33554432))}}function g(e){let t=[];for(let n of e.split(`,`)){let e=n.trim().replace(/^U\+/i,``);if(e)if(e.includes(`-`)){let[n,r]=e.split(`-`);n&&r&&t.push([parseInt(n,16),parseInt(r,16)])}else if(e.includes(`?`))t.push([parseInt(e.replace(/\?/g,`0`),16),parseInt(e.replace(/\?/g,`F`),16)]);else{let n=parseInt(e,16);t.push([n,n])}}return t}function _(e){let t=[],n=0;for(let r of e.matchAll(m)){let e=r[2];if(!e)continue;let i=e.match(/src:\s*url\(([^)]+)\)/)?.[1]?.replace(/['"]/g,``).trim(),a=e.match(/font-family:\s*['"]?([^'";]+)['"]?/)?.[1]?.trim();if(!i||!a)continue;let o=e.match(/unicode-range:\s*([^;]+)/)?.[1],s=e.match(/font-weight:\s*(\d+)(?:\s+(\d+))?/);t.push({family:a,subset:r[1]?.trim()||`subset-${n}`,url:i,weight:s&&!s[2]?Number(s[1]):void 0,style:e.match(/font-style:\s*([a-z]+)/i)?.[1],ranges:o?g(o):[]}),n+=1}return t}function v(e){let t=new Map;for(let n of e){let e=t.get(n.url)??new Set;e.add(n.weight),t.set(n.url,e)}let n=new Set,r=[];for(let i of e){if(n.has(i.url))continue;n.add(i.url);let e=(t.get(i.url)?.size??0)>1;r.push(e?{...i,weight:void 0}:i)}return r}function y(e){let t=new Set,n=e=>{for(let n of e)t.add(n.codePointAt(0))},r=e=>{e.type===`text`?n(e.text):e.type===`container`&&e.children?.forEach(r)};return typeof e==`string`?n(e):Array.isArray(e)?e.forEach(r):r(e),t}function b(e,t){if(e.length===0)return!0;for(let n of t)for(let[t,r]of e)if(n>=t&&n<=r)return!0;return!1}function x({fonts:e,source:t}){let n=y(t);return e.filter(e=>b(e.ranges??[],n))}function S(e,t={}){return{key:e,data:()=>n(e,t).then(e=>r(e,t.maxBytes??33554432))}}async function C(e){if(e.families.length===0)return[];let t=await p(d(e),e),n=new Map(e.families.map((e,t)=>[typeof e==`string`?e:e.name,t]));return v(_(t)).sort((e,t)=>(n.get(e.family)??0)-(n.get(t.family)??0)).map(t=>h(t,e))}export{e as a,r as c,x as i,S as n,n as o,C as r,c as s,y as t};
@@ -920,16 +920,21 @@ interface GoogleFontShapeFamilies {
920
920
  }
921
921
  //#endregion
922
922
  //#region src/utils.d.ts
923
+ declare const defaultMaxFetchBytes: number;
923
924
  type FetchLike = (input: string, init?: RequestInit) => Promise<Response>;
924
925
  type FetchOptions = {
925
- /** Custom fetch implementation. @default globalThis.fetch */fetch?: FetchLike; /** Abort the request after this many milliseconds. */
926
+ /** Custom fetch implementation. @default globalThis.fetch */fetch?: FetchLike; /** Abort the request after this many milliseconds; `0` or negative disables it. @default 5000 */
926
927
  timeout?: number; /** Caller abort signal, combined with the timeout. */
927
- signal?: AbortSignal;
928
+ signal?: AbortSignal; /** Reject bodies larger than this many bytes. @default 33554432 (32 MiB) */
929
+ maxBytes?: number; /** Return false to skip fetching a URL (e.g. SSRF allowlist). */
930
+ allowUrl?: (url: string) => boolean;
928
931
  };
929
932
  /** Fetches a URL, applying a timeout signal and throwing on a non-OK status. */
930
933
  declare function fetchOk(url: string, options?: FetchOptions & {
931
934
  init?: RequestInit;
932
935
  }): Promise<Response>;
936
+ /** Reads a response body, rejecting once it exceeds `maxBytes` (by content-length or streamed size). */
937
+ declare function readBodyLimited(response: Response, maxBytes: number): Promise<ArrayBuffer>;
933
938
  /**
934
939
  * A cache of image fetches keyed by URL. Sharing one across renders deduplicates concurrent
935
940
  * requests for the same URL (single-flight) and reuses their bytes. Any object with `Map`-like
@@ -966,6 +971,8 @@ declare function prepareImages<T extends {
966
971
  fetch,
967
972
  timeout,
968
973
  signal,
974
+ maxBytes,
975
+ allowUrl,
969
976
  throwOnError
970
977
  }: PrepareImagesOptions<T>): Promise<(T | FetchedImage)[]>;
971
978
  //#endregion
@@ -995,10 +1002,12 @@ type GoogleFontsOptions = FetchOptions & {
995
1002
  /** The families to load, each as a name or a name plus its weight/style axis. */families: GoogleFontFamily[]; /** `font-display` strategy passed through to the CSS request. */
996
1003
  display?: "auto" | "block" | "swap" | "fallback" | "optional";
997
1004
  /**
998
- * Cache for the Google Fonts CSS, keyed by request URL. Reuse one across renders (e.g. a
999
- * playground re-rendering on each edit) so the metadata is fetched and parsed once.
1005
+ * Cache for the Google Fonts CSS, keyed by request URL, so the metadata is fetched once across
1006
+ * renders (e.g. a playground re-rendering on each edit). Holds the in-flight promise, so
1007
+ * concurrent calls share one request; failures evict themselves. Defaults to a process-wide
1008
+ * cache; pass your own `Map` to scope it, or a fresh one per call to opt out.
1000
1009
  */
1001
- cache?: Pick<Map<string, string>, "has" | "get" | "set">;
1010
+ cache?: Pick<Map<string, Promise<string>>, "get" | "set" | "delete">;
1002
1011
  /**
1003
1012
  * css2 base URL. Defaults to Google Fonts; point it at an API-compatible mirror like
1004
1013
  * `https://fonts.bunny.net/css2`.
@@ -1034,7 +1043,7 @@ declare function subsetFonts<T>({
1034
1043
  * dedupe. Family name, weight, and style come from the font file. Lets `fonts` take a bare URL
1035
1044
  * string, e.g. `fonts: ["https://example.com/Inter.woff2"]`.
1036
1045
  */
1037
- declare function fontFromUrl(url: string): {
1046
+ declare function fontFromUrl(url: string, options?: FetchOptions): {
1038
1047
  key: string;
1039
1048
  data: () => Promise<ArrayBuffer>;
1040
1049
  };
@@ -1065,4 +1074,4 @@ declare function rem(rem: number): `${number}rem`;
1065
1074
  declare function fr(fr: number): `${number}fr`;
1066
1075
  declare function rgba(r: number, g: number, b: number, a?: number): `rgb(${number} ${number} ${number} / ${number})`;
1067
1076
  //#endregion
1068
- export { PrepareImagesOptions as C, ImageFetchCache as S, prepareImages as T, googleFonts as _, percentage as a, FetchOptions as b, style as c, vw as d, FontSubset as f, fontFromUrl as g, collectCodepoints as h, image as i, text as l, GoogleFontsOptions as m, em as n, rem as o, GoogleFontFamily as p, fr as r, rgba as s, container as t, vh as u, subsetFonts as v, fetchOk as w, FetchedImage as x, FetchLike as y };
1077
+ export { PrepareImagesOptions as C, readBodyLimited as D, prepareImages as E, ImageFetchCache as S, fetchOk as T, googleFonts as _, percentage as a, FetchOptions as b, style as c, vw as d, FontSubset as f, fontFromUrl as g, collectCodepoints as h, image as i, text as l, GoogleFontsOptions as m, em as n, rem as o, GoogleFontFamily as p, fr as r, rgba as s, container as t, vh as u, subsetFonts as v, defaultMaxFetchBytes as w, FetchedImage as x, FetchLike as y };
@@ -920,16 +920,21 @@ interface GoogleFontShapeFamilies {
920
920
  }
921
921
  //#endregion
922
922
  //#region src/utils.d.ts
923
+ declare const defaultMaxFetchBytes: number;
923
924
  type FetchLike = (input: string, init?: RequestInit) => Promise<Response>;
924
925
  type FetchOptions = {
925
- /** Custom fetch implementation. @default globalThis.fetch */fetch?: FetchLike; /** Abort the request after this many milliseconds. */
926
+ /** Custom fetch implementation. @default globalThis.fetch */fetch?: FetchLike; /** Abort the request after this many milliseconds; `0` or negative disables it. @default 5000 */
926
927
  timeout?: number; /** Caller abort signal, combined with the timeout. */
927
- signal?: AbortSignal;
928
+ signal?: AbortSignal; /** Reject bodies larger than this many bytes. @default 33554432 (32 MiB) */
929
+ maxBytes?: number; /** Return false to skip fetching a URL (e.g. SSRF allowlist). */
930
+ allowUrl?: (url: string) => boolean;
928
931
  };
929
932
  /** Fetches a URL, applying a timeout signal and throwing on a non-OK status. */
930
933
  declare function fetchOk(url: string, options?: FetchOptions & {
931
934
  init?: RequestInit;
932
935
  }): Promise<Response>;
936
+ /** Reads a response body, rejecting once it exceeds `maxBytes` (by content-length or streamed size). */
937
+ declare function readBodyLimited(response: Response, maxBytes: number): Promise<ArrayBuffer>;
933
938
  /**
934
939
  * A cache of image fetches keyed by URL. Sharing one across renders deduplicates concurrent
935
940
  * requests for the same URL (single-flight) and reuses their bytes. Any object with `Map`-like
@@ -966,6 +971,8 @@ declare function prepareImages<T extends {
966
971
  fetch,
967
972
  timeout,
968
973
  signal,
974
+ maxBytes,
975
+ allowUrl,
969
976
  throwOnError
970
977
  }: PrepareImagesOptions<T>): Promise<(T | FetchedImage)[]>;
971
978
  //#endregion
@@ -995,10 +1002,12 @@ type GoogleFontsOptions = FetchOptions & {
995
1002
  /** The families to load, each as a name or a name plus its weight/style axis. */families: GoogleFontFamily[]; /** `font-display` strategy passed through to the CSS request. */
996
1003
  display?: "auto" | "block" | "swap" | "fallback" | "optional";
997
1004
  /**
998
- * Cache for the Google Fonts CSS, keyed by request URL. Reuse one across renders (e.g. a
999
- * playground re-rendering on each edit) so the metadata is fetched and parsed once.
1005
+ * Cache for the Google Fonts CSS, keyed by request URL, so the metadata is fetched once across
1006
+ * renders (e.g. a playground re-rendering on each edit). Holds the in-flight promise, so
1007
+ * concurrent calls share one request; failures evict themselves. Defaults to a process-wide
1008
+ * cache; pass your own `Map` to scope it, or a fresh one per call to opt out.
1000
1009
  */
1001
- cache?: Pick<Map<string, string>, "has" | "get" | "set">;
1010
+ cache?: Pick<Map<string, Promise<string>>, "get" | "set" | "delete">;
1002
1011
  /**
1003
1012
  * css2 base URL. Defaults to Google Fonts; point it at an API-compatible mirror like
1004
1013
  * `https://fonts.bunny.net/css2`.
@@ -1034,7 +1043,7 @@ declare function subsetFonts<T>({
1034
1043
  * dedupe. Family name, weight, and style come from the font file. Lets `fonts` take a bare URL
1035
1044
  * string, e.g. `fonts: ["https://example.com/Inter.woff2"]`.
1036
1045
  */
1037
- declare function fontFromUrl(url: string): {
1046
+ declare function fontFromUrl(url: string, options?: FetchOptions): {
1038
1047
  key: string;
1039
1048
  data: () => Promise<ArrayBuffer>;
1040
1049
  };
@@ -1065,4 +1074,4 @@ declare function rem(rem: number): `${number}rem`;
1065
1074
  declare function fr(fr: number): `${number}fr`;
1066
1075
  declare function rgba(r: number, g: number, b: number, a?: number): `rgb(${number} ${number} ${number} / ${number})`;
1067
1076
  //#endregion
1068
- export { PrepareImagesOptions as C, ImageFetchCache as S, prepareImages as T, googleFonts as _, percentage as a, FetchOptions as b, style as c, vw as d, FontSubset as f, fontFromUrl as g, collectCodepoints as h, image as i, text as l, GoogleFontsOptions as m, em as n, rem as o, GoogleFontFamily as p, fr as r, rgba as s, container as t, vh as u, subsetFonts as v, fetchOk as w, FetchedImage as x, FetchLike as y };
1077
+ export { PrepareImagesOptions as C, readBodyLimited as D, prepareImages as E, ImageFetchCache as S, fetchOk as T, googleFonts as _, percentage as a, FetchOptions as b, style as c, vw as d, FontSubset as f, fontFromUrl as g, collectCodepoints as h, image as i, text as l, GoogleFontsOptions as m, em as n, rem as o, GoogleFontFamily as p, fr as r, rgba as s, container as t, vh as u, subsetFonts as v, defaultMaxFetchBytes as w, FetchedImage as x, FetchLike as y };
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./fonts-gcSpolCe.cjs"),t=require("./helpers-4kGcvc-Q.cjs");exports.collectCodepoints=e.t,exports.container=t.t,exports.em=t.n,exports.fetchOk=e.a,exports.fontFromUrl=e.n,exports.fr=t.r,exports.googleFonts=e.r,exports.image=t.i,exports.percentage=t.a,exports.prepareImages=e.o,exports.rem=t.o,exports.rgba=t.s,exports.style=t.c,exports.subsetFonts=e.i,exports.text=t.l,exports.vh=t.u,exports.vw=t.d;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./fonts-BJ3xMWLx.cjs"),t=require("./helpers-4kGcvc-Q.cjs");exports.collectCodepoints=e.t,exports.container=t.t,exports.defaultMaxFetchBytes=e.a,exports.em=t.n,exports.fetchOk=e.o,exports.fontFromUrl=e.n,exports.fr=t.r,exports.googleFonts=e.r,exports.image=t.i,exports.percentage=t.a,exports.prepareImages=e.s,exports.readBodyLimited=e.c,exports.rem=t.o,exports.rgba=t.s,exports.style=t.c,exports.subsetFonts=e.i,exports.text=t.l,exports.vh=t.u,exports.vw=t.d;
package/dist/index.d.cts CHANGED
@@ -1,3 +1,3 @@
1
1
  import { a as NodeMetadata, c as TextNode, i as NodeAttributes, n as ImageNode, o as ReactElementLike, r as Node, s as TextFit, t as ContainerNode } from "./types-xgX3CGse.cjs";
2
- import { C as PrepareImagesOptions, S as ImageFetchCache, T as prepareImages, _ as googleFonts, a as percentage, b as FetchOptions, c as style, d as vw, f as FontSubset, g as fontFromUrl, h as collectCodepoints, i as image, l as text, m as GoogleFontsOptions, n as em, o as rem, p as GoogleFontFamily, r as fr, s as rgba, t as container, u as vh, v as subsetFonts, w as fetchOk, x as FetchedImage, y as FetchLike } from "./index-C9T8g_Ys.cjs";
3
- export { ContainerNode, FetchLike, FetchOptions, FetchedImage, FontSubset, GoogleFontFamily, GoogleFontsOptions, ImageFetchCache, ImageNode, Node, NodeAttributes, NodeMetadata, PrepareImagesOptions, ReactElementLike, TextFit, TextNode, collectCodepoints, container, em, fetchOk, fontFromUrl, fr, googleFonts, image, percentage, prepareImages, rem, rgba, style, subsetFonts, text, vh, vw };
2
+ import { C as PrepareImagesOptions, D as readBodyLimited, E as prepareImages, S as ImageFetchCache, T as fetchOk, _ as googleFonts, a as percentage, b as FetchOptions, c as style, d as vw, f as FontSubset, g as fontFromUrl, h as collectCodepoints, i as image, l as text, m as GoogleFontsOptions, n as em, o as rem, p as GoogleFontFamily, r as fr, s as rgba, t as container, u as vh, v as subsetFonts, w as defaultMaxFetchBytes, x as FetchedImage, y as FetchLike } from "./index-rlDD8qfK.cjs";
3
+ export { ContainerNode, FetchLike, FetchOptions, FetchedImage, FontSubset, GoogleFontFamily, GoogleFontsOptions, ImageFetchCache, ImageNode, Node, NodeAttributes, NodeMetadata, PrepareImagesOptions, ReactElementLike, TextFit, TextNode, collectCodepoints, container, defaultMaxFetchBytes, em, fetchOk, fontFromUrl, fr, googleFonts, image, percentage, prepareImages, readBodyLimited, rem, rgba, style, subsetFonts, text, vh, vw };
package/dist/index.d.mts CHANGED
@@ -1,3 +1,3 @@
1
1
  import { a as NodeMetadata, c as TextNode, i as NodeAttributes, n as ImageNode, o as ReactElementLike, r as Node, s as TextFit, t as ContainerNode } from "./types-xgX3CGse.mjs";
2
- import { C as PrepareImagesOptions, S as ImageFetchCache, T as prepareImages, _ as googleFonts, a as percentage, b as FetchOptions, c as style, d as vw, f as FontSubset, g as fontFromUrl, h as collectCodepoints, i as image, l as text, m as GoogleFontsOptions, n as em, o as rem, p as GoogleFontFamily, r as fr, s as rgba, t as container, u as vh, v as subsetFonts, w as fetchOk, x as FetchedImage, y as FetchLike } from "./index-D66Ac3N4.mjs";
3
- export { ContainerNode, FetchLike, FetchOptions, FetchedImage, FontSubset, GoogleFontFamily, GoogleFontsOptions, ImageFetchCache, ImageNode, Node, NodeAttributes, NodeMetadata, PrepareImagesOptions, ReactElementLike, TextFit, TextNode, collectCodepoints, container, em, fetchOk, fontFromUrl, fr, googleFonts, image, percentage, prepareImages, rem, rgba, style, subsetFonts, text, vh, vw };
2
+ import { C as PrepareImagesOptions, D as readBodyLimited, E as prepareImages, S as ImageFetchCache, T as fetchOk, _ as googleFonts, a as percentage, b as FetchOptions, c as style, d as vw, f as FontSubset, g as fontFromUrl, h as collectCodepoints, i as image, l as text, m as GoogleFontsOptions, n as em, o as rem, p as GoogleFontFamily, r as fr, s as rgba, t as container, u as vh, v as subsetFonts, w as defaultMaxFetchBytes, x as FetchedImage, y as FetchLike } from "./index-BfHXErbT.mjs";
3
+ export { ContainerNode, FetchLike, FetchOptions, FetchedImage, FontSubset, GoogleFontFamily, GoogleFontsOptions, ImageFetchCache, ImageNode, Node, NodeAttributes, NodeMetadata, PrepareImagesOptions, ReactElementLike, TextFit, TextNode, collectCodepoints, container, defaultMaxFetchBytes, em, fetchOk, fontFromUrl, fr, googleFonts, image, percentage, prepareImages, readBodyLimited, rem, rgba, style, subsetFonts, text, vh, vw };
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import{a as e,i as t,n,o as r,r as i,t as a}from"./fonts-CrmMlf6O.mjs";import{a as o,c as s,d as c,i as l,l as u,n as d,o as f,r as p,s as m,t as h,u as g}from"./helpers-CVQCT1Rh.mjs";export{a as collectCodepoints,h as container,d as em,e as fetchOk,n as fontFromUrl,p as fr,i as googleFonts,l as image,o as percentage,r as prepareImages,f as rem,m as rgba,s as style,t as subsetFonts,u as text,g as vh,c as vw};
1
+ import{a as e,c as t,i as n,n as r,o as i,r as a,s as o,t as s}from"./fonts-DUzzGxwK.mjs";import{a as c,c as l,d as u,i as d,l as f,n as p,o as m,r as h,s as g,t as _,u as v}from"./helpers-CVQCT1Rh.mjs";export{s as collectCodepoints,_ as container,e as defaultMaxFetchBytes,p as em,i as fetchOk,r as fontFromUrl,h as fr,a as googleFonts,d as image,c as percentage,o as prepareImages,t as readBodyLimited,m as rem,g as rgba,l as style,n as subsetFonts,f as text,v as vh,u as vw};
package/dist/renderer.cjs CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./fonts-gcSpolCe.cjs");function t(e){return e instanceof Uint8Array||e instanceof ArrayBuffer||typeof Buffer<`u`&&Buffer.isBuffer(e)}function n(e){return t(e)?e:typeof e.data==`function`?e.data():e.data}function r(e){return t(e)?e:`key`in e&&e.key?e.key:typeof e.data==`function`?`${e.name??``}:${e.weight??``}:${e.style??``}`:e.data}async function i(e){let{sources:t=[],cache:n}=Array.isArray(e)?{sources:e}:e,r=new Map;for(let e of t)r.set(e.src,e);return Promise.all([...r.values()].map(async({src:e,data:t,cache:r})=>({src:e,data:typeof t==`function`?await t():t,cache:r??n})))}var a=class{registerInner;byKey=new Map;byData=new WeakMap;constructor(e){this.registerInner=e}getFont(e){return typeof e==`string`?this.byKey.get(e):this.byData.get(e)}setFont(e,t){typeof e==`string`?this.byKey.set(e,t):this.byData.set(e,t)}deleteFont(e){typeof e==`string`?this.byKey.delete(e):this.byData.delete(e)}async register(i){let a=typeof i==`string`?e.n(i):i,o=r(a),s=this.getFont(o);if(s)return s;let c=n(a),l=Promise.resolve(c).then(e=>this.registerInner(t(a)?e:{...a,data:e})).catch(e=>{throw this.deleteFont(o),e});return this.setFont(o,l),l}async prepareFonts(e){if(!e)return;let t=await Promise.all(e.map(e=>this.register(e)));return[...new Set(t.flat().map(e=>e.name))]}async resolveResources(e,t,n){let r=await this.prepareFonts(e);return{images:t?await i(t):void 0,fontFamilies:n??r}}};exports.FontRegistry=a,exports.resolveImageLoaders=i;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./fonts-BJ3xMWLx.cjs");function t(e){return e instanceof Uint8Array||e instanceof ArrayBuffer||typeof Buffer<`u`&&Buffer.isBuffer(e)}function n(e){return t(e)?e:typeof e.data==`function`?e.data():e.data}function r(e){return t(e)?e:`key`in e&&e.key?e.key:typeof e.data==`function`?`${e.name??``}:${e.weight??``}:${e.style??``}`:e.data}async function i(e){let{sources:t=[],cache:n}=Array.isArray(e)?{sources:e}:e,r=new Map;for(let e of t)r.set(e.src,e);return Promise.all([...r.values()].map(async({src:e,data:t,cache:r})=>({src:e,data:typeof t==`function`?await t():t,cache:r??n})))}var a=class{registerInner;byKey=new Map;byData=new WeakMap;constructor(e){this.registerInner=e}getFont(e){return typeof e==`string`?this.byKey.get(e):this.byData.get(e)}setFont(e,t){typeof e==`string`?this.byKey.set(e,t):this.byData.set(e,t)}deleteFont(e){typeof e==`string`?this.byKey.delete(e):this.byData.delete(e)}async register(i){let a=typeof i==`string`?e.n(i):i,o=r(a),s=this.getFont(o);if(s)return s;let c=n(a),l=Promise.resolve(c).then(e=>this.registerInner(t(a)?e:{...a,data:e})).catch(e=>{throw this.deleteFont(o),e});return this.setFont(o,l),l}async prepareFonts(e){if(!e)return;let t=await Promise.all(e.map(e=>this.register(e)));return[...new Set(t.flat().map(e=>e.name))]}async resolveResources(e,t,n){let r=await this.prepareFonts(e);return{images:t?await i(t):void 0,fontFamilies:n??r}}};async function o(t,n,r){let{fonts:i,fontFamilies:a,signal:o,images:s,...c}=n;o?.throwIfAborted();let l=await t.resolveResources(i&&e.i({fonts:i,source:r}),s,a);return o?.throwIfAborted(),{options:{...c,...l},signal:o}}exports.FontRegistry=a,exports.prepareRenderInput=o,exports.resolveImageLoaders=i;
@@ -1,3 +1,5 @@
1
+ import { r as Node } from "./types-xgX3CGse.cjs";
2
+
1
3
  //#region src/renderer.d.ts
2
4
  /**
3
5
  * Shared wrapper primitives for the `@takumi-rs/core` (napi) and `@takumi-rs/wasm` renderer
@@ -98,6 +100,12 @@ type RenderExtras = {
98
100
  signal?: AbortSignal;
99
101
  images?: ImagesInput;
100
102
  };
103
+ /** Public `render`/`measure` options for a backend whose binding options are {@link TInternal}. */
104
+ type BackendRenderOptions<TInternal> = Omit<TInternal, "images" | "format" | "quality" | "lossless"> & OutputFormatOptions & RenderExtras;
105
+ /** Public `renderAnimation` options for a backend whose binding options are {@link TInternal}. */
106
+ type BackendAnimationOptions<TInternal> = Omit<TInternal, "images" | "format" | "quality" | "lossless"> & AnimationOutputFormatOptions & RenderExtras;
107
+ /** Public `renderSvg` options for a backend whose binding options are {@link TInternal}. */
108
+ type BackendSvgOptions<TInternal> = Omit<TInternal, "images"> & RenderExtras;
101
109
  /** Normalize an {@link ImagesInput} into concrete, deduped {@link ImageSource} entries. */
102
110
  declare function resolveImageLoaders(images: ImagesInput): Promise<ImageSource[]>;
103
111
  /**
@@ -129,5 +137,22 @@ declare class FontRegistry<TFamily extends RegisteredFamilyLike> {
129
137
  fontFamilies?: string[];
130
138
  }>;
131
139
  }
140
+ /** The binding options {@link prepareRenderInput} yields: extras stripped, resolved resources merged in. */
141
+ type ResolvedRenderOptions<TOptions> = Omit<TOptions, keyof RenderExtras | "fontFamilies"> & {
142
+ images?: ImageSource[];
143
+ fontFamilies?: string[];
144
+ };
145
+ /**
146
+ * Shared body for every backend render entry point: subsets and registers `fonts` against `source`,
147
+ * resolves `images`/`fontFamilies`, and enforces one abort policy: `signal` is checked before and
148
+ * after the (network-bound) resource resolution. Returns the binding options plus the `signal` for
149
+ * the backend to forward into a native call when it supports cancellation.
150
+ */
151
+ declare function prepareRenderInput<TOptions extends RenderExtras & {
152
+ fontFamilies?: string[];
153
+ }, TFamily extends RegisteredFamilyLike>(registry: FontRegistry<TFamily>, options: TOptions, source: string | Node | Node[]): Promise<{
154
+ options: ResolvedRenderOptions<TOptions>;
155
+ signal: AbortSignal | undefined;
156
+ }>;
132
157
  //#endregion
133
- export { AnimationOutputFormatOptions, ByteBuf, Font, FontDetails, FontLoader, FontRegistry, ImageCacheMode, ImageLoader, ImageSource, ImagesInput, OutputFormatOptions, RegisteredFamilyLike, RenderExtras, resolveImageLoaders };
158
+ export { AnimationOutputFormatOptions, BackendAnimationOptions, BackendRenderOptions, BackendSvgOptions, ByteBuf, Font, FontDetails, FontLoader, FontRegistry, ImageCacheMode, ImageLoader, ImageSource, ImagesInput, OutputFormatOptions, RegisteredFamilyLike, RenderExtras, ResolvedRenderOptions, prepareRenderInput, resolveImageLoaders };
@@ -1,3 +1,5 @@
1
+ import { r as Node } from "./types-xgX3CGse.mjs";
2
+
1
3
  //#region src/renderer.d.ts
2
4
  /**
3
5
  * Shared wrapper primitives for the `@takumi-rs/core` (napi) and `@takumi-rs/wasm` renderer
@@ -98,6 +100,12 @@ type RenderExtras = {
98
100
  signal?: AbortSignal;
99
101
  images?: ImagesInput;
100
102
  };
103
+ /** Public `render`/`measure` options for a backend whose binding options are {@link TInternal}. */
104
+ type BackendRenderOptions<TInternal> = Omit<TInternal, "images" | "format" | "quality" | "lossless"> & OutputFormatOptions & RenderExtras;
105
+ /** Public `renderAnimation` options for a backend whose binding options are {@link TInternal}. */
106
+ type BackendAnimationOptions<TInternal> = Omit<TInternal, "images" | "format" | "quality" | "lossless"> & AnimationOutputFormatOptions & RenderExtras;
107
+ /** Public `renderSvg` options for a backend whose binding options are {@link TInternal}. */
108
+ type BackendSvgOptions<TInternal> = Omit<TInternal, "images"> & RenderExtras;
101
109
  /** Normalize an {@link ImagesInput} into concrete, deduped {@link ImageSource} entries. */
102
110
  declare function resolveImageLoaders(images: ImagesInput): Promise<ImageSource[]>;
103
111
  /**
@@ -129,5 +137,22 @@ declare class FontRegistry<TFamily extends RegisteredFamilyLike> {
129
137
  fontFamilies?: string[];
130
138
  }>;
131
139
  }
140
+ /** The binding options {@link prepareRenderInput} yields: extras stripped, resolved resources merged in. */
141
+ type ResolvedRenderOptions<TOptions> = Omit<TOptions, keyof RenderExtras | "fontFamilies"> & {
142
+ images?: ImageSource[];
143
+ fontFamilies?: string[];
144
+ };
145
+ /**
146
+ * Shared body for every backend render entry point: subsets and registers `fonts` against `source`,
147
+ * resolves `images`/`fontFamilies`, and enforces one abort policy: `signal` is checked before and
148
+ * after the (network-bound) resource resolution. Returns the binding options plus the `signal` for
149
+ * the backend to forward into a native call when it supports cancellation.
150
+ */
151
+ declare function prepareRenderInput<TOptions extends RenderExtras & {
152
+ fontFamilies?: string[];
153
+ }, TFamily extends RegisteredFamilyLike>(registry: FontRegistry<TFamily>, options: TOptions, source: string | Node | Node[]): Promise<{
154
+ options: ResolvedRenderOptions<TOptions>;
155
+ signal: AbortSignal | undefined;
156
+ }>;
132
157
  //#endregion
133
- export { AnimationOutputFormatOptions, ByteBuf, Font, FontDetails, FontLoader, FontRegistry, ImageCacheMode, ImageLoader, ImageSource, ImagesInput, OutputFormatOptions, RegisteredFamilyLike, RenderExtras, resolveImageLoaders };
158
+ export { AnimationOutputFormatOptions, BackendAnimationOptions, BackendRenderOptions, BackendSvgOptions, ByteBuf, Font, FontDetails, FontLoader, FontRegistry, ImageCacheMode, ImageLoader, ImageSource, ImagesInput, OutputFormatOptions, RegisteredFamilyLike, RenderExtras, ResolvedRenderOptions, prepareRenderInput, resolveImageLoaders };
package/dist/renderer.mjs CHANGED
@@ -1 +1 @@
1
- import{n as e}from"./fonts-CrmMlf6O.mjs";function t(e){return e instanceof Uint8Array||e instanceof ArrayBuffer||typeof Buffer<`u`&&Buffer.isBuffer(e)}function n(e){return t(e)?e:typeof e.data==`function`?e.data():e.data}function r(e){return t(e)?e:`key`in e&&e.key?e.key:typeof e.data==`function`?`${e.name??``}:${e.weight??``}:${e.style??``}`:e.data}async function i(e){let{sources:t=[],cache:n}=Array.isArray(e)?{sources:e}:e,r=new Map;for(let e of t)r.set(e.src,e);return Promise.all([...r.values()].map(async({src:e,data:t,cache:r})=>({src:e,data:typeof t==`function`?await t():t,cache:r??n})))}var a=class{registerInner;byKey=new Map;byData=new WeakMap;constructor(e){this.registerInner=e}getFont(e){return typeof e==`string`?this.byKey.get(e):this.byData.get(e)}setFont(e,t){typeof e==`string`?this.byKey.set(e,t):this.byData.set(e,t)}deleteFont(e){typeof e==`string`?this.byKey.delete(e):this.byData.delete(e)}async register(i){let a=typeof i==`string`?e(i):i,o=r(a),s=this.getFont(o);if(s)return s;let c=n(a),l=Promise.resolve(c).then(e=>this.registerInner(t(a)?e:{...a,data:e})).catch(e=>{throw this.deleteFont(o),e});return this.setFont(o,l),l}async prepareFonts(e){if(!e)return;let t=await Promise.all(e.map(e=>this.register(e)));return[...new Set(t.flat().map(e=>e.name))]}async resolveResources(e,t,n){let r=await this.prepareFonts(e);return{images:t?await i(t):void 0,fontFamilies:n??r}}};export{a as FontRegistry,i as resolveImageLoaders};
1
+ import{i as e,n as t}from"./fonts-DUzzGxwK.mjs";function n(e){return e instanceof Uint8Array||e instanceof ArrayBuffer||typeof Buffer<`u`&&Buffer.isBuffer(e)}function r(e){return n(e)?e:typeof e.data==`function`?e.data():e.data}function i(e){return n(e)?e:`key`in e&&e.key?e.key:typeof e.data==`function`?`${e.name??``}:${e.weight??``}:${e.style??``}`:e.data}async function a(e){let{sources:t=[],cache:n}=Array.isArray(e)?{sources:e}:e,r=new Map;for(let e of t)r.set(e.src,e);return Promise.all([...r.values()].map(async({src:e,data:t,cache:r})=>({src:e,data:typeof t==`function`?await t():t,cache:r??n})))}var o=class{registerInner;byKey=new Map;byData=new WeakMap;constructor(e){this.registerInner=e}getFont(e){return typeof e==`string`?this.byKey.get(e):this.byData.get(e)}setFont(e,t){typeof e==`string`?this.byKey.set(e,t):this.byData.set(e,t)}deleteFont(e){typeof e==`string`?this.byKey.delete(e):this.byData.delete(e)}async register(e){let a=typeof e==`string`?t(e):e,o=i(a),s=this.getFont(o);if(s)return s;let c=r(a),l=Promise.resolve(c).then(e=>this.registerInner(n(a)?e:{...a,data:e})).catch(e=>{throw this.deleteFont(o),e});return this.setFont(o,l),l}async prepareFonts(e){if(!e)return;let t=await Promise.all(e.map(e=>this.register(e)));return[...new Set(t.flat().map(e=>e.name))]}async resolveResources(e,t,n){let r=await this.prepareFonts(e);return{images:t?await a(t):void 0,fontFamilies:n??r}}};async function s(t,n,r){let{fonts:i,fontFamilies:a,signal:o,images:s,...c}=n;o?.throwIfAborted();let l=await t.resolveResources(i&&e({fonts:i,source:r}),s,a);return o?.throwIfAborted(),{options:{...c,...l},signal:o}}export{o as FontRegistry,s as prepareRenderInput,a as resolveImageLoaders};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@takumi-rs/helpers",
3
- "version": "2.0.0-rc.9",
3
+ "version": "2.0.1",
4
4
  "description": "Utility helpers for converting JSX/HTML to Takumi node trees, loading fonts, and processing emoji.",
5
5
  "keywords": [
6
6
  "css",
@@ -1 +0,0 @@
1
- const e=/url\(\s*(['"]?)(.*?)\1\s*\)/g;async function t(e,t={}){let n=t.fetch??globalThis.fetch,r=t.timeout===void 0?void 0:AbortSignal.timeout(t.timeout),i=[t.signal,t.init?.signal,r].filter(e=>e!==void 0),a=i.length?AbortSignal.any(i):void 0,o=await n(e,{...t.init,signal:a});if(!o.ok)throw Error(`HTTP ${o.status} ${o.statusText} fetching ${e}`);return o}function n(e){return e.startsWith(`https://`)||e.startsWith(`http://`)}function r(t,i){if(typeof t==`string`)for(let r of t.matchAll(e)){let e=r[2]?.trim();e&&n(e)&&i.add(e)}else if(Array.isArray(t))for(let e of t)r(e,i)}function i(e){let t=new Set,i=e=>{let a=e=>{e&&(r(e.backgroundImage,t),r(e.maskImage,t))};if(a(e.style),a(e.preset),r(e.tw,t),e.type===`image`){typeof e.src==`string`&&n(e.src)&&t.add(e.src);return}if(e.type===`container`)for(let t of e.children??[])i(t)};return i(e),[...t]}function a(e,n,r){let i=r?.get(e);if(i)return i;let a=t(e,n).then(e=>e.arrayBuffer()).catch(t=>{throw r?.delete(e),t});return r?.set(e,a),a}async function o({node:e,sources:t=[],fetchCache:n,fetch:r,timeout:o=5e3,signal:s,throwOnError:c=!0}){let l=Array.isArray(e)?e:[e],u=new Map;for(let e of t)u.set(e.src,e);let d=[...new Set(l.flatMap(i))].filter(e=>!u.has(e)),f={fetch:r,timeout:o,signal:s},p=d.map(async e=>({src:e,data:await a(e,f,n)})),m=c?await Promise.all(p):(await Promise.allSettled(p)).filter(e=>e.status===`fulfilled`).map(e=>e.value);return[...u.values(),...m]}function s(e,t,n,r){let i=new Map(r),a=n.includes(`italic`),o=a?n.includes(`normal`)?[0,1]:[1]:[void 0],s=[...a?[`ital`]:[],...i.keys(),`wght`].sort(),c=o.flatMap(e=>t.map(t=>s.map(n=>n===`ital`?String(e):n===`wght`?t:i.get(n)??``).join(`,`))).sort();return`${e}:${s.join(`,`)}@${c.join(`;`)}`}function c(e){let t=new URL(e.baseUrl??`https://fonts.googleapis.com/css2`);for(let n of e.families){if(typeof n==`string`){t.searchParams.append(`family`,s(n,[`400`],[`normal`],[]));continue}let e=n.weight??400,r=(Array.isArray(e)?[...e].sort((e,t)=>e-t):[e]).map(String),i=n.style??`normal`,a=(Array.isArray(i)?i:[i]).map(String),o=Object.entries(n.axes??{}).filter(([e])=>e!==`ital`&&e!==`wght`).map(([e,t])=>[e,String(t)]);t.searchParams.append(`family`,s(n.name,r,a,o))}return e.display&&t.searchParams.set(`display`,e.display),t.toString()}function l(e,n){return t(e,{...n,init:{headers:{"User-Agent":`Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36`}}}).then(e=>e.text())}async function u(e,t){let n=t.cache?.get(e);if(n!==void 0)return n;let r=await l(e,t);return t.cache?.set(e,r),r}const d=/(?:\/\*\s*([^*]+?)\s*\*\/\s*)?@font-face\s*\{([^}]*)\}/g;function f(e,n){let r=`${e.family} ${e.subset}`,i=e.ranges.map(([e,t])=>`${e}-${t}`).join(`,`);return{name:r,subsetOf:e.family,key:`${r}:${e.weight??``}:${e.style??``}:${i}`,weight:e.weight,style:e.style,ranges:e.ranges,data:()=>t(e.url,n).then(e=>e.arrayBuffer())}}function p(e){let t=[];for(let n of e.split(`,`)){let e=n.trim().replace(/^U\+/i,``);if(e)if(e.includes(`-`)){let[n,r]=e.split(`-`);n&&r&&t.push([parseInt(n,16),parseInt(r,16)])}else if(e.includes(`?`))t.push([parseInt(e.replace(/\?/g,`0`),16),parseInt(e.replace(/\?/g,`F`),16)]);else{let n=parseInt(e,16);t.push([n,n])}}return t}function m(e){let t=[],n=0;for(let r of e.matchAll(d)){let e=r[2];if(!e)continue;let i=e.match(/src:\s*url\(([^)]+)\)/)?.[1]?.replace(/['"]/g,``).trim(),a=e.match(/font-family:\s*['"]?([^'";]+)['"]?/)?.[1]?.trim();if(!i||!a)continue;let o=e.match(/unicode-range:\s*([^;]+)/)?.[1],s=e.match(/font-weight:\s*(\d+)(?:\s+(\d+))?/);t.push({family:a,subset:r[1]?.trim()||`subset-${n}`,url:i,weight:s&&!s[2]?Number(s[1]):void 0,style:e.match(/font-style:\s*([a-z]+)/i)?.[1],ranges:o?p(o):[]}),n+=1}return t}function h(e){let t=new Map;for(let n of e){let e=t.get(n.url)??new Set;e.add(n.weight),t.set(n.url,e)}let n=new Set,r=[];for(let i of e){if(n.has(i.url))continue;n.add(i.url);let e=(t.get(i.url)?.size??0)>1;r.push(e?{...i,weight:void 0}:i)}return r}function g(e){let t=new Set,n=e=>{for(let n of e)t.add(n.codePointAt(0))},r=e=>{e.type===`text`?n(e.text):e.type===`container`&&e.children?.forEach(r)};return typeof e==`string`?n(e):Array.isArray(e)?e.forEach(r):r(e),t}function _(e,t){if(e.length===0)return!0;for(let n of t)for(let[t,r]of e)if(n>=t&&n<=r)return!0;return!1}function v({fonts:e,source:t}){let n=g(t);return e.filter(e=>_(e.ranges??[],n))}function y(e){return{key:e,data:()=>t(e).then(e=>e.arrayBuffer())}}async function b(e){return e.families.length===0?[]:h(m(await u(c(e),e))).map(t=>f(t,e))}export{t as a,v as i,y as n,o,b as r,g as t};
@@ -1 +0,0 @@
1
- const e=/url\(\s*(['"]?)(.*?)\1\s*\)/g;async function t(e,t={}){let n=t.fetch??globalThis.fetch,r=t.timeout===void 0?void 0:AbortSignal.timeout(t.timeout),i=[t.signal,t.init?.signal,r].filter(e=>e!==void 0),a=i.length?AbortSignal.any(i):void 0,o=await n(e,{...t.init,signal:a});if(!o.ok)throw Error(`HTTP ${o.status} ${o.statusText} fetching ${e}`);return o}function n(e){return e.startsWith(`https://`)||e.startsWith(`http://`)}function r(t,i){if(typeof t==`string`)for(let r of t.matchAll(e)){let e=r[2]?.trim();e&&n(e)&&i.add(e)}else if(Array.isArray(t))for(let e of t)r(e,i)}function i(e){let t=new Set,i=e=>{let a=e=>{e&&(r(e.backgroundImage,t),r(e.maskImage,t))};if(a(e.style),a(e.preset),r(e.tw,t),e.type===`image`){typeof e.src==`string`&&n(e.src)&&t.add(e.src);return}if(e.type===`container`)for(let t of e.children??[])i(t)};return i(e),[...t]}function a(e,n,r){let i=r?.get(e);if(i)return i;let a=t(e,n).then(e=>e.arrayBuffer()).catch(t=>{throw r?.delete(e),t});return r?.set(e,a),a}async function o({node:e,sources:t=[],fetchCache:n,fetch:r,timeout:o=5e3,signal:s,throwOnError:c=!0}){let l=Array.isArray(e)?e:[e],u=new Map;for(let e of t)u.set(e.src,e);let d=[...new Set(l.flatMap(i))].filter(e=>!u.has(e)),f={fetch:r,timeout:o,signal:s},p=d.map(async e=>({src:e,data:await a(e,f,n)})),m=c?await Promise.all(p):(await Promise.allSettled(p)).filter(e=>e.status===`fulfilled`).map(e=>e.value);return[...u.values(),...m]}function s(e,t,n,r){let i=new Map(r),a=n.includes(`italic`),o=a?n.includes(`normal`)?[0,1]:[1]:[void 0],s=[...a?[`ital`]:[],...i.keys(),`wght`].sort(),c=o.flatMap(e=>t.map(t=>s.map(n=>n===`ital`?String(e):n===`wght`?t:i.get(n)??``).join(`,`))).sort();return`${e}:${s.join(`,`)}@${c.join(`;`)}`}function c(e){let t=new URL(e.baseUrl??`https://fonts.googleapis.com/css2`);for(let n of e.families){if(typeof n==`string`){t.searchParams.append(`family`,s(n,[`400`],[`normal`],[]));continue}let e=n.weight??400,r=(Array.isArray(e)?[...e].sort((e,t)=>e-t):[e]).map(String),i=n.style??`normal`,a=(Array.isArray(i)?i:[i]).map(String),o=Object.entries(n.axes??{}).filter(([e])=>e!==`ital`&&e!==`wght`).map(([e,t])=>[e,String(t)]);t.searchParams.append(`family`,s(n.name,r,a,o))}return e.display&&t.searchParams.set(`display`,e.display),t.toString()}function l(e,n){return t(e,{...n,init:{headers:{"User-Agent":`Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36`}}}).then(e=>e.text())}async function u(e,t){let n=t.cache?.get(e);if(n!==void 0)return n;let r=await l(e,t);return t.cache?.set(e,r),r}const d=/(?:\/\*\s*([^*]+?)\s*\*\/\s*)?@font-face\s*\{([^}]*)\}/g;function f(e,n){let r=`${e.family} ${e.subset}`,i=e.ranges.map(([e,t])=>`${e}-${t}`).join(`,`);return{name:r,subsetOf:e.family,key:`${r}:${e.weight??``}:${e.style??``}:${i}`,weight:e.weight,style:e.style,ranges:e.ranges,data:()=>t(e.url,n).then(e=>e.arrayBuffer())}}function p(e){let t=[];for(let n of e.split(`,`)){let e=n.trim().replace(/^U\+/i,``);if(e)if(e.includes(`-`)){let[n,r]=e.split(`-`);n&&r&&t.push([parseInt(n,16),parseInt(r,16)])}else if(e.includes(`?`))t.push([parseInt(e.replace(/\?/g,`0`),16),parseInt(e.replace(/\?/g,`F`),16)]);else{let n=parseInt(e,16);t.push([n,n])}}return t}function m(e){let t=[],n=0;for(let r of e.matchAll(d)){let e=r[2];if(!e)continue;let i=e.match(/src:\s*url\(([^)]+)\)/)?.[1]?.replace(/['"]/g,``).trim(),a=e.match(/font-family:\s*['"]?([^'";]+)['"]?/)?.[1]?.trim();if(!i||!a)continue;let o=e.match(/unicode-range:\s*([^;]+)/)?.[1],s=e.match(/font-weight:\s*(\d+)(?:\s+(\d+))?/);t.push({family:a,subset:r[1]?.trim()||`subset-${n}`,url:i,weight:s&&!s[2]?Number(s[1]):void 0,style:e.match(/font-style:\s*([a-z]+)/i)?.[1],ranges:o?p(o):[]}),n+=1}return t}function h(e){let t=new Map;for(let n of e){let e=t.get(n.url)??new Set;e.add(n.weight),t.set(n.url,e)}let n=new Set,r=[];for(let i of e){if(n.has(i.url))continue;n.add(i.url);let e=(t.get(i.url)?.size??0)>1;r.push(e?{...i,weight:void 0}:i)}return r}function g(e){let t=new Set,n=e=>{for(let n of e)t.add(n.codePointAt(0))},r=e=>{e.type===`text`?n(e.text):e.type===`container`&&e.children?.forEach(r)};return typeof e==`string`?n(e):Array.isArray(e)?e.forEach(r):r(e),t}function _(e,t){if(e.length===0)return!0;for(let n of t)for(let[t,r]of e)if(n>=t&&n<=r)return!0;return!1}function v({fonts:e,source:t}){let n=g(t);return e.filter(e=>_(e.ranges??[],n))}function y(e){return{key:e,data:()=>t(e).then(e=>e.arrayBuffer())}}async function b(e){return e.families.length===0?[]:h(m(await u(c(e),e))).map(t=>f(t,e))}Object.defineProperty(exports,"a",{enumerable:!0,get:function(){return t}}),Object.defineProperty(exports,"i",{enumerable:!0,get:function(){return v}}),Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return y}}),Object.defineProperty(exports,"o",{enumerable:!0,get:function(){return o}}),Object.defineProperty(exports,"r",{enumerable:!0,get:function(){return b}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return g}});