@takumi-rs/helpers 2.0.0-rc.5 → 2.0.0-rc.6

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={}){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};
@@ -0,0 +1 @@
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}});
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./helpers-4kGcvc-Q.cjs"),t=/url\(\s*(['"]?)(.*?)\1\s*\)/g;async function n(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 r(e){return e.startsWith(`https://`)||e.startsWith(`http://`)}function i(e,n){if(typeof e==`string`)for(let i of e.matchAll(t)){let e=i[2]?.trim();e&&r(e)&&n.add(e)}else if(Array.isArray(e))for(let t of e)i(t,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,t,r){let i=r?.get(e);if(i)return i;let a=n(e,t).then(e=>e.arrayBuffer()).catch(t=>{throw r?.delete(e),t});return r?.set(e,a),a}async function s({node:e,sources:t=[],fetchCache:n,fetch:r,timeout:i=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(a))].filter(e=>!u.has(e)),f={fetch:r,timeout:i,signal:s},p=d.map(async e=>({src:e,data:await o(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 c(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 l(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`,c(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`,c(n.name,r,a,o))}return e.display&&t.searchParams.set(`display`,e.display),t.toString()}function u(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=>e.text())}async function d(e,t){let n=t.cache?.get(e);if(n!==void 0)return n;let r=await u(e,t);return t.cache?.set(e,r),r}const f=/(?:\/\*\s*([^*]+?)\s*\*\/\s*)?@font-face\s*\{([^}]*)\}/g;function p(e,t){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:()=>n(e.url,t).then(e=>e.arrayBuffer())}}function m(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 h(e){let t=[],n=0;for(let r of e.matchAll(f)){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?m(o):[]}),n+=1}return t}function g(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 _(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 v(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 y({fonts:e,source:t}){let n=_(t);return e.filter(e=>v(e.ranges??[],n))}function b(e){return{key:e,data:()=>n(e).then(e=>e.arrayBuffer())}}async function x(e){return e.families.length===0?[]:g(h(await d(l(e),e))).map(t=>p(t,e))}exports.collectCodepoints=_,exports.container=e.t,exports.em=e.n,exports.fetchOk=n,exports.fontFromUrl=b,exports.fr=e.r,exports.googleFonts=x,exports.image=e.i,exports.percentage=e.a,exports.prepareImages=s,exports.rem=e.o,exports.rgba=e.s,exports.style=e.c,exports.subsetFonts=y,exports.text=e.l,exports.vh=e.u,exports.vw=e.d;
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;
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import{a as e,c as t,d as n,i as r,l as i,n as a,o,r as s,s as c,t as l,u}from"./helpers-CVQCT1Rh.mjs";const d=/url\(\s*(['"]?)(.*?)\1\s*\)/g;async function f(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 p(e){return e.startsWith(`https://`)||e.startsWith(`http://`)}function m(e,t){if(typeof e==`string`)for(let n of e.matchAll(d)){let e=n[2]?.trim();e&&p(e)&&t.add(e)}else if(Array.isArray(e))for(let n of e)m(n,t)}function h(e){let t=new Set,n=e=>{let r=e=>{e&&(m(e.backgroundImage,t),m(e.maskImage,t))};if(r(e.style),r(e.preset),m(e.tw,t),e.type===`image`){typeof e.src==`string`&&p(e.src)&&t.add(e.src);return}if(e.type===`container`)for(let t of e.children??[])n(t)};return n(e),[...t]}function g(e,t,n){let r=n?.get(e);if(r)return r;let i=f(e,t).then(e=>e.arrayBuffer()).catch(t=>{throw n?.delete(e),t});return n?.set(e,i),i}async function _({node:e,sources:t=[],fetchCache:n,fetch:r,timeout:i=5e3,signal:a,throwOnError:o=!0}){let s=Array.isArray(e)?e:[e],c=new Map;for(let e of t)c.set(e.src,e);let l=[...new Set(s.flatMap(h))].filter(e=>!c.has(e)),u={fetch:r,timeout:i,signal:a},d=l.map(async e=>({src:e,data:await g(e,u,n)})),f=o?await Promise.all(d):(await Promise.allSettled(d)).filter(e=>e.status===`fulfilled`).map(e=>e.value);return[...c.values(),...f]}function v(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 y(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`,v(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`,v(n.name,r,a,o))}return e.display&&t.searchParams.set(`display`,e.display),t.toString()}function b(e,t){return f(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=>e.text())}async function x(e,t){let n=t.cache?.get(e);if(n!==void 0)return n;let r=await b(e,t);return t.cache?.set(e,r),r}const S=/(?:\/\*\s*([^*]+?)\s*\*\/\s*)?@font-face\s*\{([^}]*)\}/g;function C(e,t){let n=`${e.family} ${e.subset}`,r=e.ranges.map(([e,t])=>`${e}-${t}`).join(`,`);return{name:n,subsetOf:e.family,key:`${n}:${e.weight??``}:${e.style??``}:${r}`,weight:e.weight,style:e.style,ranges:e.ranges,data:()=>f(e.url,t).then(e=>e.arrayBuffer())}}function w(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 T(e){let t=[],n=0;for(let r of e.matchAll(S)){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?w(o):[]}),n+=1}return t}function E(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 D(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 O(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 k({fonts:e,source:t}){let n=D(t);return e.filter(e=>O(e.ranges??[],n))}function A(e){return{key:e,data:()=>f(e).then(e=>e.arrayBuffer())}}async function j(e){return e.families.length===0?[]:E(T(await x(y(e),e))).map(t=>C(t,e))}export{D as collectCodepoints,l as container,a as em,f as fetchOk,A as fontFromUrl,s as fr,j as googleFonts,r as image,e as percentage,_ as prepareImages,o as rem,c as rgba,t as style,k as subsetFonts,i as text,u as vh,n as vw};
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};
@@ -0,0 +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;
@@ -0,0 +1,133 @@
1
+ //#region src/renderer.d.ts
2
+ /**
3
+ * Shared wrapper primitives for the `@takumi-rs/core` (napi) and `@takumi-rs/wasm` renderer
4
+ * bindings. Both backends compose their public `Renderer` from these so the two surfaces cannot
5
+ * drift: the font/image loader shapes, the output-format options, and the font-registration state
6
+ * machine live here once. The concrete `Font`/`ImageSource`/`ByteBuf`/`RegisteredFamily` shapes
7
+ * mirror each backend's generated types field-for-field; the register callback wiring in each
8
+ * backend fails to compile if they diverge.
9
+ */
10
+ type Awaitable<T> = T | Promise<T>;
11
+ /** Font byte payloads accepted across environments. */
12
+ type ByteBuf = Uint8Array | ArrayBuffer | Buffer;
13
+ /** A font descriptor, matching each backend's generated `FontDetails`. */
14
+ type FontDetails = {
15
+ name?: string;
16
+ data: ByteBuf;
17
+ weight?: number;
18
+ style?: "normal" | "italic" | "oblique" | `oblique ${number}deg` | (string & {});
19
+ /**
20
+ * Logical family this font is a coverage subset of. Subsets sharing a `subsetOf` are
21
+ * kept as distinct families and `font-family: {subsetOf}` expands to all of them, so each
22
+ * script routes to the subset that covers it.
23
+ */
24
+ subsetOf?: string;
25
+ };
26
+ /** A registered font, either detailed or raw bytes. */
27
+ type Font = FontDetails | ByteBuf;
28
+ /** Cache policy for a decoded image. Defaults to `"auto"`. */
29
+ type ImageCacheMode = "auto" | "none";
30
+ /** An image source with its URL and raw bytes, matching each backend's generated `ImageSource`. */
31
+ type ImageSource = {
32
+ src: string;
33
+ data: ByteBuf;
34
+ cache?: ImageCacheMode;
35
+ };
36
+ /** A font family produced by `registerFont`. Only `name` is read here; backends keep the full type. */
37
+ type RegisteredFamilyLike = {
38
+ name: string;
39
+ };
40
+ /**
41
+ * A font to register. Either a URL string (fetched on demand, with name/weight/style read from the
42
+ * file), raw bytes, or a descriptor with a lazy `data()` loader.
43
+ */
44
+ type FontLoader = string | Font | (Omit<FontDetails, "data"> & {
45
+ data: () => Promise<FontDetails["data"]> | FontDetails["data"]; /** Inclusive codepoint ranges this face covers; lets `render` skip it when unused. */
46
+ ranges?: [number, number][];
47
+ } & ({
48
+ key: string;
49
+ } | {
50
+ name: string;
51
+ }));
52
+ type ImageLoader = Omit<ImageSource, "data"> & {
53
+ data: ImageSource["data"] | (() => ImageSource["data"] | Promise<ImageSource["data"]>);
54
+ };
55
+ /** Images for a render: pre-fetched entries, or a group with a decode-cache default. */
56
+ type ImagesInput = ImageLoader[] | {
57
+ /** Pre-fetched entries, same as the array form. */sources?: ImageLoader[]; /** Decode-cache default for every image this render; a source's own `cache` wins. */
58
+ cache?: NonNullable<ImageLoader["cache"]>;
59
+ };
60
+ /**
61
+ * Output format. Format-specific options live on the variant that supports them, so `quality`
62
+ * cannot be paired with PNG/ICO/raw, and `lossless` is WebP-only. On native (`@takumi-rs/core`),
63
+ * WebP honors both — `lossless` takes precedence over `quality`, and omitting both encodes
64
+ * losslessly. On wasm (`@takumi-rs/wasm`) WebP is always lossless: `lossless` is effectively always
65
+ * on and `quality` is ignored for WebP (lossy WebP is native-only).
66
+ */
67
+ type OutputFormatOptions = {
68
+ format?: "png";
69
+ } | {
70
+ format: "jpeg";
71
+ quality?: number;
72
+ } | {
73
+ format: "webp";
74
+ quality?: number;
75
+ lossless?: boolean;
76
+ } | {
77
+ format: "ico";
78
+ } | {
79
+ format: "raw";
80
+ };
81
+ /**
82
+ * Animation output format. `quality` and `lossless` are WebP-only. On native, `lossless` takes
83
+ * precedence over `quality` and omitting both encodes losslessly; on wasm animated WebP is always
84
+ * lossless and `quality` is ignored.
85
+ */
86
+ type AnimationOutputFormatOptions = {
87
+ format?: "webp";
88
+ quality?: number;
89
+ lossless?: boolean;
90
+ } | {
91
+ format: "apng";
92
+ } | {
93
+ format: "gif";
94
+ };
95
+ /** The wrapper-managed extras every render entry point accepts on top of the binding options. */
96
+ type RenderExtras = {
97
+ fonts?: FontLoader[];
98
+ signal?: AbortSignal;
99
+ images?: ImagesInput;
100
+ };
101
+ /** Normalize an {@link ImagesInput} into concrete, deduped {@link ImageSource} entries. */
102
+ declare function resolveImageLoaders(images: ImagesInput): Promise<ImageSource[]>;
103
+ /**
104
+ * Font-registration state machine shared by both backends: dedupes registrations by a stable key
105
+ * (or by buffer identity), resolves lazy `data()` loaders once, and turns a set of {@link FontLoader}s
106
+ * plus an {@link ImagesInput} into the `fontFamilies`/`images` the binding expects.
107
+ *
108
+ * `registerInner` is the backend's raw `registerFont`; its precise `RegisteredFamily` type flows
109
+ * back out through {@link TFamily}.
110
+ */
111
+ declare class FontRegistry<TFamily extends RegisteredFamilyLike> {
112
+ private readonly registerInner;
113
+ private readonly byKey;
114
+ private readonly byData;
115
+ constructor(registerInner: (font: Font) => Awaitable<TFamily[]>);
116
+ private getFont;
117
+ private setFont;
118
+ private deleteFont;
119
+ /** Registers one font, deduped against earlier registrations. */
120
+ register(font: FontLoader): Promise<TFamily[]>;
121
+ /** Registers every font and returns the distinct family names produced. */
122
+ prepareFonts(fonts: FontLoader[] | undefined): Promise<string[] | undefined>;
123
+ /**
124
+ * Registers `fonts` and resolves lazy `images`, yielding the `images`/`fontFamilies` the binding
125
+ * expects. Explicit `fontFamilies` wins over the registered set.
126
+ */
127
+ resolveResources(fonts: FontLoader[] | undefined, images: ImagesInput | undefined, fontFamilies: string[] | undefined): Promise<{
128
+ images?: ImageSource[];
129
+ fontFamilies?: string[];
130
+ }>;
131
+ }
132
+ //#endregion
133
+ export { AnimationOutputFormatOptions, ByteBuf, Font, FontDetails, FontLoader, FontRegistry, ImageCacheMode, ImageLoader, ImageSource, ImagesInput, OutputFormatOptions, RegisteredFamilyLike, RenderExtras, resolveImageLoaders };
@@ -0,0 +1,133 @@
1
+ //#region src/renderer.d.ts
2
+ /**
3
+ * Shared wrapper primitives for the `@takumi-rs/core` (napi) and `@takumi-rs/wasm` renderer
4
+ * bindings. Both backends compose their public `Renderer` from these so the two surfaces cannot
5
+ * drift: the font/image loader shapes, the output-format options, and the font-registration state
6
+ * machine live here once. The concrete `Font`/`ImageSource`/`ByteBuf`/`RegisteredFamily` shapes
7
+ * mirror each backend's generated types field-for-field; the register callback wiring in each
8
+ * backend fails to compile if they diverge.
9
+ */
10
+ type Awaitable<T> = T | Promise<T>;
11
+ /** Font byte payloads accepted across environments. */
12
+ type ByteBuf = Uint8Array | ArrayBuffer | Buffer;
13
+ /** A font descriptor, matching each backend's generated `FontDetails`. */
14
+ type FontDetails = {
15
+ name?: string;
16
+ data: ByteBuf;
17
+ weight?: number;
18
+ style?: "normal" | "italic" | "oblique" | `oblique ${number}deg` | (string & {});
19
+ /**
20
+ * Logical family this font is a coverage subset of. Subsets sharing a `subsetOf` are
21
+ * kept as distinct families and `font-family: {subsetOf}` expands to all of them, so each
22
+ * script routes to the subset that covers it.
23
+ */
24
+ subsetOf?: string;
25
+ };
26
+ /** A registered font, either detailed or raw bytes. */
27
+ type Font = FontDetails | ByteBuf;
28
+ /** Cache policy for a decoded image. Defaults to `"auto"`. */
29
+ type ImageCacheMode = "auto" | "none";
30
+ /** An image source with its URL and raw bytes, matching each backend's generated `ImageSource`. */
31
+ type ImageSource = {
32
+ src: string;
33
+ data: ByteBuf;
34
+ cache?: ImageCacheMode;
35
+ };
36
+ /** A font family produced by `registerFont`. Only `name` is read here; backends keep the full type. */
37
+ type RegisteredFamilyLike = {
38
+ name: string;
39
+ };
40
+ /**
41
+ * A font to register. Either a URL string (fetched on demand, with name/weight/style read from the
42
+ * file), raw bytes, or a descriptor with a lazy `data()` loader.
43
+ */
44
+ type FontLoader = string | Font | (Omit<FontDetails, "data"> & {
45
+ data: () => Promise<FontDetails["data"]> | FontDetails["data"]; /** Inclusive codepoint ranges this face covers; lets `render` skip it when unused. */
46
+ ranges?: [number, number][];
47
+ } & ({
48
+ key: string;
49
+ } | {
50
+ name: string;
51
+ }));
52
+ type ImageLoader = Omit<ImageSource, "data"> & {
53
+ data: ImageSource["data"] | (() => ImageSource["data"] | Promise<ImageSource["data"]>);
54
+ };
55
+ /** Images for a render: pre-fetched entries, or a group with a decode-cache default. */
56
+ type ImagesInput = ImageLoader[] | {
57
+ /** Pre-fetched entries, same as the array form. */sources?: ImageLoader[]; /** Decode-cache default for every image this render; a source's own `cache` wins. */
58
+ cache?: NonNullable<ImageLoader["cache"]>;
59
+ };
60
+ /**
61
+ * Output format. Format-specific options live on the variant that supports them, so `quality`
62
+ * cannot be paired with PNG/ICO/raw, and `lossless` is WebP-only. On native (`@takumi-rs/core`),
63
+ * WebP honors both — `lossless` takes precedence over `quality`, and omitting both encodes
64
+ * losslessly. On wasm (`@takumi-rs/wasm`) WebP is always lossless: `lossless` is effectively always
65
+ * on and `quality` is ignored for WebP (lossy WebP is native-only).
66
+ */
67
+ type OutputFormatOptions = {
68
+ format?: "png";
69
+ } | {
70
+ format: "jpeg";
71
+ quality?: number;
72
+ } | {
73
+ format: "webp";
74
+ quality?: number;
75
+ lossless?: boolean;
76
+ } | {
77
+ format: "ico";
78
+ } | {
79
+ format: "raw";
80
+ };
81
+ /**
82
+ * Animation output format. `quality` and `lossless` are WebP-only. On native, `lossless` takes
83
+ * precedence over `quality` and omitting both encodes losslessly; on wasm animated WebP is always
84
+ * lossless and `quality` is ignored.
85
+ */
86
+ type AnimationOutputFormatOptions = {
87
+ format?: "webp";
88
+ quality?: number;
89
+ lossless?: boolean;
90
+ } | {
91
+ format: "apng";
92
+ } | {
93
+ format: "gif";
94
+ };
95
+ /** The wrapper-managed extras every render entry point accepts on top of the binding options. */
96
+ type RenderExtras = {
97
+ fonts?: FontLoader[];
98
+ signal?: AbortSignal;
99
+ images?: ImagesInput;
100
+ };
101
+ /** Normalize an {@link ImagesInput} into concrete, deduped {@link ImageSource} entries. */
102
+ declare function resolveImageLoaders(images: ImagesInput): Promise<ImageSource[]>;
103
+ /**
104
+ * Font-registration state machine shared by both backends: dedupes registrations by a stable key
105
+ * (or by buffer identity), resolves lazy `data()` loaders once, and turns a set of {@link FontLoader}s
106
+ * plus an {@link ImagesInput} into the `fontFamilies`/`images` the binding expects.
107
+ *
108
+ * `registerInner` is the backend's raw `registerFont`; its precise `RegisteredFamily` type flows
109
+ * back out through {@link TFamily}.
110
+ */
111
+ declare class FontRegistry<TFamily extends RegisteredFamilyLike> {
112
+ private readonly registerInner;
113
+ private readonly byKey;
114
+ private readonly byData;
115
+ constructor(registerInner: (font: Font) => Awaitable<TFamily[]>);
116
+ private getFont;
117
+ private setFont;
118
+ private deleteFont;
119
+ /** Registers one font, deduped against earlier registrations. */
120
+ register(font: FontLoader): Promise<TFamily[]>;
121
+ /** Registers every font and returns the distinct family names produced. */
122
+ prepareFonts(fonts: FontLoader[] | undefined): Promise<string[] | undefined>;
123
+ /**
124
+ * Registers `fonts` and resolves lazy `images`, yielding the `images`/`fontFamilies` the binding
125
+ * expects. Explicit `fontFamilies` wins over the registered set.
126
+ */
127
+ resolveResources(fonts: FontLoader[] | undefined, images: ImagesInput | undefined, fontFamilies: string[] | undefined): Promise<{
128
+ images?: ImageSource[];
129
+ fontFamilies?: string[];
130
+ }>;
131
+ }
132
+ //#endregion
133
+ export { AnimationOutputFormatOptions, ByteBuf, Font, FontDetails, FontLoader, FontRegistry, ImageCacheMode, ImageLoader, ImageSource, ImagesInput, OutputFormatOptions, RegisteredFamilyLike, RenderExtras, resolveImageLoaders };
@@ -0,0 +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};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@takumi-rs/helpers",
3
- "version": "2.0.0-rc.5",
3
+ "version": "2.0.0-rc.6",
4
4
  "description": "Utility helpers for converting JSX/HTML to Takumi node trees, loading fonts, and processing emoji.",
5
5
  "keywords": [
6
6
  "css",
@@ -74,6 +74,16 @@
74
74
  "types": "./dist/emoji.d.cts",
75
75
  "default": "./dist/emoji.cjs"
76
76
  }
77
+ },
78
+ "./renderer": {
79
+ "import": {
80
+ "types": "./dist/renderer.d.mts",
81
+ "default": "./dist/renderer.mjs"
82
+ },
83
+ "require": {
84
+ "types": "./dist/renderer.d.cts",
85
+ "default": "./dist/renderer.cjs"
86
+ }
77
87
  }
78
88
  },
79
89
  "publishConfig": {