@takumi-rs/helpers 2.0.0-beta.6 → 2.0.0-beta.8
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.
- package/dist/index-D4LX37aN.d.cts +9816 -0
- package/dist/index-Da14nnwt.d.mts +9816 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +2 -117
- package/dist/index.d.mts +2 -117
- package/dist/index.mjs +1 -1
- package/package.json +9 -9
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;function n(e){return e.startsWith(`https://`)||e.startsWith(`http://`)}function r(e,i){if(typeof e==`string`)for(let r of e.matchAll(t)){let e=r[2]?.trim();e&&n(e)&&i.add(e)}else if(Array.isArray(e))for(let t of e)r(t,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]}async function a(e,t={}){let n=t.fetch??globalThis.fetch,r=t.timeout===void 0?t.init?.signal:AbortSignal.timeout(t.timeout),i=await n(e,{...t.init,signal:r});if(!i.ok)throw Error(`HTTP ${i.status} ${i.statusText} fetching ${e}`);return i}async function o(e,t){let n=t?.throwOnError??!0,r=t?.timeout??5e3,i=[...new Set(e)].map(async e=>{if(t?.cache?.has(e)){let n=t.cache.get(e);if(n)return{src:e,data:n}}let n=await a(e,{fetch:t?.fetch,timeout:r}).then(e=>e.arrayBuffer());return t?.cache?.set(e,n),{src:e,data:n}});return n?Promise.all(i):(await Promise.allSettled(i)).filter(e=>e.status===`fulfilled`).map(e=>e.value)}
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./helpers-4kGcvc-Q.cjs"),t=/url\(\s*(['"]?)(.*?)\1\s*\)/g;function n(e){return e.startsWith(`https://`)||e.startsWith(`http://`)}function r(e,i){if(typeof e==`string`)for(let r of e.matchAll(t)){let e=r[2]?.trim();e&&n(e)&&i.add(e)}else if(Array.isArray(e))for(let t of e)r(t,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]}async function a(e,t={}){let n=t.fetch??globalThis.fetch,r=t.timeout===void 0?t.init?.signal:AbortSignal.timeout(t.timeout),i=await n(e,{...t.init,signal:r});if(!i.ok)throw Error(`HTTP ${i.status} ${i.statusText} fetching ${e}`);return i}async function o(e,t){let n=t?.throwOnError??!0,r=t?.timeout??5e3,i=[...new Set(e)].map(async e=>{if(t?.cache?.has(e)){let n=t.cache.get(e);if(n)return{src:e,data:n}}let n=await a(e,{fetch:t?.fetch,timeout:r}).then(e=>e.arrayBuffer());return t?.cache?.set(e,n),{src:e,data:n}});return n?Promise.all(i):(await Promise.allSettled(i)).filter(e=>e.status===`fulfilled`).map(e=>e.value)}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(`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.family,r,a,o))}return e.display&&t.searchParams.set(`display`,e.display),t.toString()}function l(e,t){return a(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 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,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:()=>a(e.url,t).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({fonts:e,source:t,subset:n}){return e&&n!==!1?v({fonts:e,source:t}):e}async function b(e){return e.families.length===0?[]:h(m(await u(c(e),e))).map(t=>f(t,e))}exports.collectCodepoints=g,exports.container=e.t,exports.em=e.n,exports.extractResourceUrls=i,exports.fetchOk=a,exports.fetchResources=o,exports.fr=e.r,exports.googleFonts=b,exports.image=e.i,exports.percentage=e.a,exports.pickFonts=y,exports.rem=e.o,exports.rgba=e.s,exports.style=e.c,exports.subsetFonts=v,exports.text=e.l,exports.vh=e.u,exports.vw=e.d;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,118 +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 {
|
|
3
|
-
|
|
4
|
-
//#region src/utils.d.ts
|
|
5
|
-
declare function extractResourceUrls(node: Node): string[];
|
|
6
|
-
type FetchLike = (input: string, init?: RequestInit) => Promise<Response>;
|
|
7
|
-
type FetchOptions = {
|
|
8
|
-
/** Custom fetch implementation. @default globalThis.fetch */fetch?: FetchLike; /** Abort the request after this many milliseconds. */
|
|
9
|
-
timeout?: number;
|
|
10
|
-
};
|
|
11
|
-
/** Fetches a URL, applying a timeout signal and throwing on a non-OK status. */
|
|
12
|
-
declare function fetchOk(url: string, options?: FetchOptions & {
|
|
13
|
-
init?: RequestInit;
|
|
14
|
-
}): Promise<Response>;
|
|
15
|
-
type FetchResourcesOptions = FetchOptions & {
|
|
16
|
-
/**
|
|
17
|
-
* Whether to throw on any fetch failure. If false, returns only successful fetches.
|
|
18
|
-
* @default true
|
|
19
|
-
*/
|
|
20
|
-
throwOnError?: boolean;
|
|
21
|
-
/**
|
|
22
|
-
* Cache for fetched resources.
|
|
23
|
-
* Custom features (like LRU, TTL, etc.) can be implemented by providing an extended `Map<string, ArrayBuffer>`.
|
|
24
|
-
*/
|
|
25
|
-
cache?: Pick<Map<string, ArrayBuffer>, "has" | "get" | "set">;
|
|
26
|
-
};
|
|
27
|
-
/**
|
|
28
|
-
* Fetches multiple resources concurrently, deduplicating URLs.
|
|
29
|
-
*
|
|
30
|
-
* @param urls - URLs to fetch
|
|
31
|
-
* @param options - Fetch options; `timeout` defaults to 5000ms
|
|
32
|
-
* @returns Array of { src: string, data: ArrayBuffer }
|
|
33
|
-
*/
|
|
34
|
-
declare function fetchResources(urls: string[], options?: FetchResourcesOptions): Promise<{
|
|
35
|
-
src: string;
|
|
36
|
-
data: ArrayBuffer;
|
|
37
|
-
}[]>;
|
|
38
|
-
//#endregion
|
|
39
|
-
//#region src/fonts.d.ts
|
|
40
|
-
type FontStyle = "normal" | "italic";
|
|
41
|
-
type GoogleFontOptions = FetchOptions & {
|
|
42
|
-
/**
|
|
43
|
-
* `400` for one weight, `[400, 700]` for several, or a range like `"100..900"` to load
|
|
44
|
-
* the variable font. A range leaves the weight unset so CSS `font-weight` controls it.
|
|
45
|
-
* @default 400
|
|
46
|
-
*/
|
|
47
|
-
weight?: number | number[] | `${number}..${number}`; /** `"normal"`, `"italic"`, or both. @default "normal" */
|
|
48
|
-
style?: FontStyle | FontStyle[]; /** Limit the download to the glyphs used in this text. Recommended for OG images. */
|
|
49
|
-
text?: string; /** `font-display` strategy passed through to the CSS request. */
|
|
50
|
-
display?: "auto" | "block" | "swap" | "fallback" | "optional";
|
|
51
|
-
};
|
|
52
|
-
/**
|
|
53
|
-
* Load a Google Font as descriptors you can pass to a renderer's `fonts`. Fetches the
|
|
54
|
-
* Google Fonts CSS, reads the `woff2` URLs, and returns one loader per file. Each file
|
|
55
|
-
* downloads when the renderer first needs it; the renderer skips files it already loaded.
|
|
56
|
-
*
|
|
57
|
-
* @example
|
|
58
|
-
* fonts: await googleFont("Inter", { weight: [400, 700] })
|
|
59
|
-
* @example
|
|
60
|
-
* fonts: await googleFont("Inter", { weight: "100..900" }) // variable
|
|
61
|
-
* @example
|
|
62
|
-
* fonts: await googleFont("Inter", { weight: 700, style: "italic", text: "Hello" })
|
|
63
|
-
*/
|
|
64
|
-
declare function googleFont(family: string, options?: GoogleFontOptions): Promise<{
|
|
65
|
-
name: string;
|
|
66
|
-
key: string;
|
|
67
|
-
weight: number | undefined;
|
|
68
|
-
style: string | undefined;
|
|
69
|
-
data: () => Promise<ArrayBuffer>;
|
|
70
|
-
}[]>;
|
|
71
|
-
/** A loaded Google Font subset, ready to hand to a renderer's `fonts`. */
|
|
72
|
-
type GoogleFontSubset = {
|
|
73
|
-
/** Unique internal family name (`"{family} {subset}"`); never written in CSS. */name: string; /** Logical family authors reference in `font-family`; expands to every loaded subset. */
|
|
74
|
-
subsetOf: string; /** Subset woff2 URL, also the dedup key. */
|
|
75
|
-
key: string;
|
|
76
|
-
weight?: number;
|
|
77
|
-
style?: string; /** Fetches the subset bytes; the renderer skips files it has already loaded. */
|
|
78
|
-
data: () => Promise<ArrayBuffer>;
|
|
79
|
-
};
|
|
80
|
-
/** A Google family to load, plus how — same options as {@link googleFont} minus `text`. */
|
|
81
|
-
type GoogleFontFamily = string | ({
|
|
82
|
-
family: string;
|
|
83
|
-
} & Omit<GoogleFontOptions, "text">);
|
|
84
|
-
type GoogleFontSubsetsOptions = FetchOptions & {
|
|
85
|
-
/**
|
|
86
|
-
* Cache for the Google Fonts CSS, keyed by request URL. Reuse one across renders (e.g. a
|
|
87
|
-
* playground re-rendering on every edit) so the metadata is fetched and parsed only once.
|
|
88
|
-
*/
|
|
89
|
-
cache?: Pick<Map<string, string>, "has" | "get" | "set">;
|
|
90
|
-
};
|
|
91
|
-
/**
|
|
92
|
-
* Load only the Google Font subsets that `source` actually renders: scan its codepoints,
|
|
93
|
-
* fetch every family's metadata in ONE css2 request, and keep just the intersecting
|
|
94
|
-
* `unicode-range` subsets. Each registers uniquely-named under its `subsetOf` family, which
|
|
95
|
-
* `font-family: {family}` expands across, so every script routes to the subset that covers
|
|
96
|
-
* it. No font anxiety.
|
|
97
|
-
*
|
|
98
|
-
* @example
|
|
99
|
-
* const fonts = await googleFontSubsets(element, ["Inter", "Noto Sans JP"]);
|
|
100
|
-
* await render(element, { width, height, fonts });
|
|
101
|
-
*/
|
|
102
|
-
declare function googleFontSubsets(source: string | Node | Node[], families: GoogleFontFamily[], options?: GoogleFontSubsetsOptions): Promise<GoogleFontSubset[]>;
|
|
103
|
-
//#endregion
|
|
104
|
-
//#region src/helpers.d.ts
|
|
105
|
-
declare function container(props: Omit<ContainerNode, "type">): ContainerNode;
|
|
106
|
-
declare function text(text: string, style?: CSSProperties): TextNode;
|
|
107
|
-
declare function text(props: Omit<TextNode, "type">): TextNode;
|
|
108
|
-
declare function image(props: Omit<ImageNode, "type">): ImageNode;
|
|
109
|
-
declare function style(style: CSSProperties): CSSProperties;
|
|
110
|
-
declare function percentage(percentage: number): `${number}%`;
|
|
111
|
-
declare function vw(vw: number): `${number}vw`;
|
|
112
|
-
declare function vh(vh: number): `${number}vh`;
|
|
113
|
-
declare function em(em: number): `${number}em`;
|
|
114
|
-
declare function rem(rem: number): `${number}rem`;
|
|
115
|
-
declare function fr(fr: number): `${number}fr`;
|
|
116
|
-
declare function rgba(r: number, g: number, b: number, a?: number): `rgb(${number} ${number} ${number} / ${number})`;
|
|
117
|
-
//#endregion
|
|
118
|
-
export { ContainerNode, FetchLike, FetchOptions, FetchResourcesOptions, GoogleFontFamily, GoogleFontOptions, GoogleFontSubset, GoogleFontSubsetsOptions, ImageNode, Node, NodeAttributes, NodeMetadata, ReactElementLike, TextFit, TextNode, container, em, extractResourceUrls, fetchOk, fetchResources, fr, googleFont, googleFontSubsets, image, percentage, rem, rgba, style, text, vh, vw };
|
|
2
|
+
import { C as fetchOk, S as extractResourceUrls, _ as pickFonts, a as percentage, b as FetchOptions, c as style, d as vw, f as FontSubset, g as googleFonts, 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 fetchResources, x as FetchResourcesOptions, y as FetchLike } from "./index-D4LX37aN.cjs";
|
|
3
|
+
export { ContainerNode, FetchLike, FetchOptions, FetchResourcesOptions, FontSubset, GoogleFontFamily, GoogleFontsOptions, ImageNode, Node, NodeAttributes, NodeMetadata, ReactElementLike, TextFit, TextNode, collectCodepoints, container, em, extractResourceUrls, fetchOk, fetchResources, fr, googleFonts, image, percentage, pickFonts, rem, rgba, style, subsetFonts, text, vh, vw };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,118 +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 {
|
|
3
|
-
|
|
4
|
-
//#region src/utils.d.ts
|
|
5
|
-
declare function extractResourceUrls(node: Node): string[];
|
|
6
|
-
type FetchLike = (input: string, init?: RequestInit) => Promise<Response>;
|
|
7
|
-
type FetchOptions = {
|
|
8
|
-
/** Custom fetch implementation. @default globalThis.fetch */fetch?: FetchLike; /** Abort the request after this many milliseconds. */
|
|
9
|
-
timeout?: number;
|
|
10
|
-
};
|
|
11
|
-
/** Fetches a URL, applying a timeout signal and throwing on a non-OK status. */
|
|
12
|
-
declare function fetchOk(url: string, options?: FetchOptions & {
|
|
13
|
-
init?: RequestInit;
|
|
14
|
-
}): Promise<Response>;
|
|
15
|
-
type FetchResourcesOptions = FetchOptions & {
|
|
16
|
-
/**
|
|
17
|
-
* Whether to throw on any fetch failure. If false, returns only successful fetches.
|
|
18
|
-
* @default true
|
|
19
|
-
*/
|
|
20
|
-
throwOnError?: boolean;
|
|
21
|
-
/**
|
|
22
|
-
* Cache for fetched resources.
|
|
23
|
-
* Custom features (like LRU, TTL, etc.) can be implemented by providing an extended `Map<string, ArrayBuffer>`.
|
|
24
|
-
*/
|
|
25
|
-
cache?: Pick<Map<string, ArrayBuffer>, "has" | "get" | "set">;
|
|
26
|
-
};
|
|
27
|
-
/**
|
|
28
|
-
* Fetches multiple resources concurrently, deduplicating URLs.
|
|
29
|
-
*
|
|
30
|
-
* @param urls - URLs to fetch
|
|
31
|
-
* @param options - Fetch options; `timeout` defaults to 5000ms
|
|
32
|
-
* @returns Array of { src: string, data: ArrayBuffer }
|
|
33
|
-
*/
|
|
34
|
-
declare function fetchResources(urls: string[], options?: FetchResourcesOptions): Promise<{
|
|
35
|
-
src: string;
|
|
36
|
-
data: ArrayBuffer;
|
|
37
|
-
}[]>;
|
|
38
|
-
//#endregion
|
|
39
|
-
//#region src/fonts.d.ts
|
|
40
|
-
type FontStyle = "normal" | "italic";
|
|
41
|
-
type GoogleFontOptions = FetchOptions & {
|
|
42
|
-
/**
|
|
43
|
-
* `400` for one weight, `[400, 700]` for several, or a range like `"100..900"` to load
|
|
44
|
-
* the variable font. A range leaves the weight unset so CSS `font-weight` controls it.
|
|
45
|
-
* @default 400
|
|
46
|
-
*/
|
|
47
|
-
weight?: number | number[] | `${number}..${number}`; /** `"normal"`, `"italic"`, or both. @default "normal" */
|
|
48
|
-
style?: FontStyle | FontStyle[]; /** Limit the download to the glyphs used in this text. Recommended for OG images. */
|
|
49
|
-
text?: string; /** `font-display` strategy passed through to the CSS request. */
|
|
50
|
-
display?: "auto" | "block" | "swap" | "fallback" | "optional";
|
|
51
|
-
};
|
|
52
|
-
/**
|
|
53
|
-
* Load a Google Font as descriptors you can pass to a renderer's `fonts`. Fetches the
|
|
54
|
-
* Google Fonts CSS, reads the `woff2` URLs, and returns one loader per file. Each file
|
|
55
|
-
* downloads when the renderer first needs it; the renderer skips files it already loaded.
|
|
56
|
-
*
|
|
57
|
-
* @example
|
|
58
|
-
* fonts: await googleFont("Inter", { weight: [400, 700] })
|
|
59
|
-
* @example
|
|
60
|
-
* fonts: await googleFont("Inter", { weight: "100..900" }) // variable
|
|
61
|
-
* @example
|
|
62
|
-
* fonts: await googleFont("Inter", { weight: 700, style: "italic", text: "Hello" })
|
|
63
|
-
*/
|
|
64
|
-
declare function googleFont(family: string, options?: GoogleFontOptions): Promise<{
|
|
65
|
-
name: string;
|
|
66
|
-
key: string;
|
|
67
|
-
weight: number | undefined;
|
|
68
|
-
style: string | undefined;
|
|
69
|
-
data: () => Promise<ArrayBuffer>;
|
|
70
|
-
}[]>;
|
|
71
|
-
/** A loaded Google Font subset, ready to hand to a renderer's `fonts`. */
|
|
72
|
-
type GoogleFontSubset = {
|
|
73
|
-
/** Unique internal family name (`"{family} {subset}"`); never written in CSS. */name: string; /** Logical family authors reference in `font-family`; expands to every loaded subset. */
|
|
74
|
-
subsetOf: string; /** Subset woff2 URL, also the dedup key. */
|
|
75
|
-
key: string;
|
|
76
|
-
weight?: number;
|
|
77
|
-
style?: string; /** Fetches the subset bytes; the renderer skips files it has already loaded. */
|
|
78
|
-
data: () => Promise<ArrayBuffer>;
|
|
79
|
-
};
|
|
80
|
-
/** A Google family to load, plus how — same options as {@link googleFont} minus `text`. */
|
|
81
|
-
type GoogleFontFamily = string | ({
|
|
82
|
-
family: string;
|
|
83
|
-
} & Omit<GoogleFontOptions, "text">);
|
|
84
|
-
type GoogleFontSubsetsOptions = FetchOptions & {
|
|
85
|
-
/**
|
|
86
|
-
* Cache for the Google Fonts CSS, keyed by request URL. Reuse one across renders (e.g. a
|
|
87
|
-
* playground re-rendering on every edit) so the metadata is fetched and parsed only once.
|
|
88
|
-
*/
|
|
89
|
-
cache?: Pick<Map<string, string>, "has" | "get" | "set">;
|
|
90
|
-
};
|
|
91
|
-
/**
|
|
92
|
-
* Load only the Google Font subsets that `source` actually renders: scan its codepoints,
|
|
93
|
-
* fetch every family's metadata in ONE css2 request, and keep just the intersecting
|
|
94
|
-
* `unicode-range` subsets. Each registers uniquely-named under its `subsetOf` family, which
|
|
95
|
-
* `font-family: {family}` expands across, so every script routes to the subset that covers
|
|
96
|
-
* it. No font anxiety.
|
|
97
|
-
*
|
|
98
|
-
* @example
|
|
99
|
-
* const fonts = await googleFontSubsets(element, ["Inter", "Noto Sans JP"]);
|
|
100
|
-
* await render(element, { width, height, fonts });
|
|
101
|
-
*/
|
|
102
|
-
declare function googleFontSubsets(source: string | Node | Node[], families: GoogleFontFamily[], options?: GoogleFontSubsetsOptions): Promise<GoogleFontSubset[]>;
|
|
103
|
-
//#endregion
|
|
104
|
-
//#region src/helpers.d.ts
|
|
105
|
-
declare function container(props: Omit<ContainerNode, "type">): ContainerNode;
|
|
106
|
-
declare function text(text: string, style?: CSSProperties): TextNode;
|
|
107
|
-
declare function text(props: Omit<TextNode, "type">): TextNode;
|
|
108
|
-
declare function image(props: Omit<ImageNode, "type">): ImageNode;
|
|
109
|
-
declare function style(style: CSSProperties): CSSProperties;
|
|
110
|
-
declare function percentage(percentage: number): `${number}%`;
|
|
111
|
-
declare function vw(vw: number): `${number}vw`;
|
|
112
|
-
declare function vh(vh: number): `${number}vh`;
|
|
113
|
-
declare function em(em: number): `${number}em`;
|
|
114
|
-
declare function rem(rem: number): `${number}rem`;
|
|
115
|
-
declare function fr(fr: number): `${number}fr`;
|
|
116
|
-
declare function rgba(r: number, g: number, b: number, a?: number): `rgb(${number} ${number} ${number} / ${number})`;
|
|
117
|
-
//#endregion
|
|
118
|
-
export { ContainerNode, FetchLike, FetchOptions, FetchResourcesOptions, GoogleFontFamily, GoogleFontOptions, GoogleFontSubset, GoogleFontSubsetsOptions, ImageNode, Node, NodeAttributes, NodeMetadata, ReactElementLike, TextFit, TextNode, container, em, extractResourceUrls, fetchOk, fetchResources, fr, googleFont, googleFontSubsets, image, percentage, rem, rgba, style, text, vh, vw };
|
|
2
|
+
import { C as fetchOk, S as extractResourceUrls, _ as pickFonts, a as percentage, b as FetchOptions, c as style, d as vw, f as FontSubset, g as googleFonts, 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 fetchResources, x as FetchResourcesOptions, y as FetchLike } from "./index-Da14nnwt.mjs";
|
|
3
|
+
export { ContainerNode, FetchLike, FetchOptions, FetchResourcesOptions, FontSubset, GoogleFontFamily, GoogleFontsOptions, ImageNode, Node, NodeAttributes, NodeMetadata, ReactElementLike, TextFit, TextNode, collectCodepoints, container, em, extractResourceUrls, fetchOk, fetchResources, fr, googleFonts, image, percentage, pickFonts, rem, rgba, style, subsetFonts, text, vh, vw };
|
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;function f(e){return e.startsWith(`https://`)||e.startsWith(`http://`)}function p(e,t){if(typeof e==`string`)for(let n of e.matchAll(d)){let e=n[2]?.trim();e&&f(e)&&t.add(e)}else if(Array.isArray(e))for(let n of e)p(n,t)}function m(e){let t=new Set,n=e=>{let r=e=>{e&&(p(e.backgroundImage,t),p(e.maskImage,t))};if(r(e.style),r(e.preset),p(e.tw,t),e.type===`image`){typeof e.src==`string`&&f(e.src)&&t.add(e.src);return}if(e.type===`container`)for(let t of e.children??[])n(t)};return n(e),[...t]}async function h(e,t={}){let n=t.fetch??globalThis.fetch,r=t.timeout===void 0?t.init?.signal:AbortSignal.timeout(t.timeout),i=await n(e,{...t.init,signal:r});if(!i.ok)throw Error(`HTTP ${i.status} ${i.statusText} fetching ${e}`);return i}async function g(e,t){let n=t?.throwOnError??!0,r=t?.timeout??5e3,i=[...new Set(e)].map(async e=>{if(t?.cache?.has(e)){let n=t.cache.get(e);if(n)return{src:e,data:n}}let n=await h(e,{fetch:t?.fetch,timeout:r}).then(e=>e.arrayBuffer());return t?.cache?.set(e,n),{src:e,data:n}});return n?Promise.all(i):(await Promise.allSettled(i)).filter(e=>e.status===`fulfilled`).map(e=>e.value)}
|
|
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;function f(e){return e.startsWith(`https://`)||e.startsWith(`http://`)}function p(e,t){if(typeof e==`string`)for(let n of e.matchAll(d)){let e=n[2]?.trim();e&&f(e)&&t.add(e)}else if(Array.isArray(e))for(let n of e)p(n,t)}function m(e){let t=new Set,n=e=>{let r=e=>{e&&(p(e.backgroundImage,t),p(e.maskImage,t))};if(r(e.style),r(e.preset),p(e.tw,t),e.type===`image`){typeof e.src==`string`&&f(e.src)&&t.add(e.src);return}if(e.type===`container`)for(let t of e.children??[])n(t)};return n(e),[...t]}async function h(e,t={}){let n=t.fetch??globalThis.fetch,r=t.timeout===void 0?t.init?.signal:AbortSignal.timeout(t.timeout),i=await n(e,{...t.init,signal:r});if(!i.ok)throw Error(`HTTP ${i.status} ${i.statusText} fetching ${e}`);return i}async function g(e,t){let n=t?.throwOnError??!0,r=t?.timeout??5e3,i=[...new Set(e)].map(async e=>{if(t?.cache?.has(e)){let n=t.cache.get(e);if(n)return{src:e,data:n}}let n=await h(e,{fetch:t?.fetch,timeout:r}).then(e=>e.arrayBuffer());return t?.cache?.set(e,n),{src:e,data:n}});return n?Promise.all(i):(await Promise.allSettled(i)).filter(e=>e.status===`fulfilled`).map(e=>e.value)}function _(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 v(e){let t=new URL(`https://fonts.googleapis.com/css2`);for(let n of e.families){if(typeof n==`string`){t.searchParams.append(`family`,_(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`,_(n.family,r,a,o))}return e.display&&t.searchParams.set(`display`,e.display),t.toString()}function y(e,t){return h(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 b(e,t){let n=t.cache?.get(e);if(n!==void 0)return n;let r=await y(e,t);return t.cache?.set(e,r),r}const x=/(?:\/\*\s*([^*]+?)\s*\*\/\s*)?@font-face\s*\{([^}]*)\}/g;function S(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:()=>h(e.url,t).then(e=>e.arrayBuffer())}}function C(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 w(e){let t=[],n=0;for(let r of e.matchAll(x)){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?C(o):[]}),n+=1}return t}function T(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(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 D(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 O({fonts:e,source:t}){let n=E(t);return e.filter(e=>D(e.ranges??[],n))}function k({fonts:e,source:t,subset:n}){return e&&n!==!1?O({fonts:e,source:t}):e}async function A(e){return e.families.length===0?[]:T(w(await b(v(e),e))).map(t=>S(t,e))}export{E as collectCodepoints,l as container,a as em,m as extractResourceUrls,h as fetchOk,g as fetchResources,s as fr,A as googleFonts,r as image,e as percentage,k as pickFonts,o as rem,c as rgba,t as style,O as subsetFonts,i as text,u as vh,n as vw};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@takumi-rs/helpers",
|
|
3
|
-
"version": "2.0.0-beta.
|
|
3
|
+
"version": "2.0.0-beta.8",
|
|
4
4
|
"description": "Utility helpers for converting JSX/HTML to Takumi node trees and handling resources.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"css",
|
|
@@ -85,15 +85,15 @@
|
|
|
85
85
|
"publish-lint": "attw --pack . && publint --strict ."
|
|
86
86
|
},
|
|
87
87
|
"devDependencies": {
|
|
88
|
-
"@types/bun": "
|
|
89
|
-
"@types/react": "
|
|
90
|
-
"@types/react-dom": "
|
|
91
|
-
"lucide-react": "
|
|
92
|
-
"react": "
|
|
93
|
-
"react-dom": "
|
|
94
|
-
"tsdown": "
|
|
88
|
+
"@types/bun": "^1.3.14",
|
|
89
|
+
"@types/react": "19.2.17",
|
|
90
|
+
"@types/react-dom": "^19.2.3",
|
|
91
|
+
"lucide-react": "^1.21.0",
|
|
92
|
+
"react": "^19.2.7",
|
|
93
|
+
"react-dom": "^19.2.7",
|
|
94
|
+
"tsdown": "^0.22.3",
|
|
95
95
|
"ultrahtml": "^1.6.0",
|
|
96
|
-
"unrun": "
|
|
96
|
+
"unrun": "^0.3.1"
|
|
97
97
|
},
|
|
98
98
|
"peerDependencies": {
|
|
99
99
|
"react": "^19.2.5",
|