@altano/satori-fit-text 2.0.2 → 3.1.0
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/TextMeasurer/BrowserTextMeasurer.js.map +1 -1
- package/dist/TextMeasurer/HeadlessTextMeasurer.js.map +1 -1
- package/dist/TextMeasurer/TextMeasurer.js +8 -2
- package/dist/TextMeasurer/TextMeasurer.js.map +1 -1
- package/dist/TextMeasurer/getTextMeasurer.js.map +1 -1
- package/dist/fitText.d.ts +23 -34
- package/dist/fitText.js.map +1 -1
- package/dist/log.d.ts +0 -1
- package/dist/log.js.map +1 -1
- package/dist/types.d.ts +2 -4
- package/package.json +27 -27
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BrowserTextMeasurer.js","names":[
|
|
1
|
+
{"version":3,"file":"BrowserTextMeasurer.js","names":[],"sources":["../../src/TextMeasurer/BrowserTextMeasurer.ts"],"sourcesContent":["/// <reference lib=\"dom\" />\n\n// TODO Factor this out to a separate project so it doesn't infect the whole\n// project with the dom lib\n\n/* v8 ignore start */\nimport log from \"../log.js\";\nimport { TextMeasurer } from \"./TextMeasurer.js\";\nimport type { Dimensions } from \"../types.js\";\n\nexport default class BrowserTextMeasurer extends TextMeasurer {\n #createSvgElement(svgXML: string): SVGSVGElement {\n const wrapper = document.createElement(\"div\");\n wrapper.innerHTML = svgXML;\n const svg = wrapper.firstElementChild;\n if (svg == null || !(svg instanceof SVGSVGElement)) {\n throw new Error(`Child should be svg element`);\n }\n return svg;\n }\n\n async getDimensions(fontSize: number): Promise<Dimensions> {\n const svgXML = await this.createSvgXmlString(fontSize);\n const svg = this.#createSvgElement(svgXML);\n\n try {\n document.body.appendChild(svg);\n const dimensions = svg.getBBox();\n const width = dimensions.width + Math.min(dimensions.x, 0);\n const height = dimensions.height + Math.min(dimensions.y, 0);\n\n log({\n fontSize,\n width: `${width}px`,\n height: `${height}px`,\n widthFits: `${width}px ${width <= this.maxWidth ? \"DOES\" : \"does NOT\"} fit in ${this.maxWidth}`,\n heightFits: `${height}px ${height <= this.maxHeight ? \"DOES\" : \"does NOT\"} fit in ${this.maxHeight}`,\n });\n\n return { width, height };\n } finally {\n svg.parentElement?.removeChild?.(svg);\n }\n }\n}\n/* v8 ignore stop */\n"],"mappings":";;;;;AAUA,IAAqB,sBAArB,cAAiD,aAAa;CAC5D,kBAAkB,QAA+B;EAC/C,MAAM,UAAU,SAAS,cAAc,KAAK;EAC5C,QAAQ,YAAY;EACpB,MAAM,MAAM,QAAQ;EACpB,IAAI,OAAO,QAAQ,EAAE,eAAe,gBAClC,MAAM,IAAI,MAAM,6BAA6B;EAE/C,OAAO;CACT;CAEA,MAAM,cAAc,UAAuC;EACzD,MAAM,SAAS,MAAM,KAAK,mBAAmB,QAAQ;EACrD,MAAM,MAAM,KAAK,kBAAkB,MAAM;EAEzC,IAAI;GACF,SAAS,KAAK,YAAY,GAAG;GAC7B,MAAM,aAAa,IAAI,QAAQ;GAC/B,MAAM,QAAQ,WAAW,QAAQ,KAAK,IAAI,WAAW,GAAG,CAAC;GACzD,MAAM,SAAS,WAAW,SAAS,KAAK,IAAI,WAAW,GAAG,CAAC;GAE3D,IAAI;IACF;IACA,OAAO,GAAG,MAAM;IAChB,QAAQ,GAAG,OAAO;IAClB,WAAW,GAAG,MAAM,KAAK,SAAS,KAAK,WAAW,SAAS,WAAW,UAAU,KAAK;IACrF,YAAY,GAAG,OAAO,KAAK,UAAU,KAAK,YAAY,SAAS,WAAW,UAAU,KAAK;GAC3F,CAAC;GAED,OAAO;IAAE;IAAO;GAAO;EACzB,UAAU;GACR,IAAI,eAAe,cAAc,GAAG;EACtC;CACF;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HeadlessTextMeasurer.js","names":[
|
|
1
|
+
{"version":3,"file":"HeadlessTextMeasurer.js","names":[],"sources":["../../src/TextMeasurer/HeadlessTextMeasurer.ts"],"sourcesContent":["/// <reference no-default-lib=\"true\"/>\n\nimport { SVG, registerWindow, type Svg } from \"@svgdotjs/svg.js\";\nimport { createSVGWindow } from \"svgdom\";\nimport log from \"../log.js\";\nimport type { Dimensions, Font } from \"../types.js\";\nimport { TextMeasurer } from \"./TextMeasurer.js\";\n\nexport default class HeadlessTextMeasurer extends TextMeasurer {\n #canvas: Svg;\n\n constructor(\n text: string,\n font: Font,\n maxWidth: number,\n maxHeight: number,\n lineHeight: number | \"normal\",\n ) {\n super(text, font, maxWidth, maxHeight, lineHeight);\n\n // register window and document\n const window = createSVGWindow();\n const document = window.document;\n registerWindow(window, document);\n\n // create canvas\n this.#canvas = SVG<SVGSVGElement>(document.documentElement);\n }\n\n async getDimensions(fontSize: number): Promise<Dimensions> {\n await this.#setFontSize(fontSize);\n const dimensions = this.#canvas.bbox();\n const width = dimensions.width + Math.min(dimensions.x, 0);\n const height = dimensions.height + Math.min(dimensions.y, 0);\n\n log({\n fontSize,\n width: `${width}px`,\n height: `${height}px`,\n widthFits: `${width}px ${\n width <= this.maxWidth ? \"DOES\" : \"does NOT\"\n } fit in ${this.maxWidth}`,\n heightFits: `${height}px ${\n height <= this.maxHeight ? \"DOES\" : \"does NOT\"\n } fit in ${this.maxHeight}`,\n });\n\n return { width, height };\n }\n\n async #setFontSize(fontSize: number): Promise<void> {\n const svgXML = await this.createSvgXmlString(fontSize);\n this.#canvas.clear();\n this.#canvas.svg(svgXML);\n }\n}\n"],"mappings":";;;;;;AAQA,IAAqB,uBAArB,cAAkD,aAAa;CAC7D;CAEA,YACE,MACA,MACA,UACA,WACA,YACA;EACA,MAAM,MAAM,MAAM,UAAU,WAAW,UAAU;EAGjD,MAAM,SAAS,gBAAgB;EAC/B,MAAM,WAAW,OAAO;EACxB,eAAe,QAAQ,QAAQ;EAG/B,KAAK,UAAU,IAAmB,SAAS,eAAe;CAC5D;CAEA,MAAM,cAAc,UAAuC;EACzD,MAAM,KAAK,aAAa,QAAQ;EAChC,MAAM,aAAa,KAAK,QAAQ,KAAK;EACrC,MAAM,QAAQ,WAAW,QAAQ,KAAK,IAAI,WAAW,GAAG,CAAC;EACzD,MAAM,SAAS,WAAW,SAAS,KAAK,IAAI,WAAW,GAAG,CAAC;EAE3D,IAAI;GACF;GACA,OAAO,GAAG,MAAM;GAChB,QAAQ,GAAG,OAAO;GAClB,WAAW,GAAG,MAAM,KAClB,SAAS,KAAK,WAAW,SAAS,WACnC,UAAU,KAAK;GAChB,YAAY,GAAG,OAAO,KACpB,UAAU,KAAK,YAAY,SAAS,WACrC,UAAU,KAAK;EAClB,CAAC;EAED,OAAO;GAAE;GAAO;EAAO;CACzB;CAEA,MAAM,aAAa,UAAiC;EAClD,MAAM,SAAS,MAAM,KAAK,mBAAmB,QAAQ;EACrD,KAAK,QAAQ,MAAM;EACnB,KAAK,QAAQ,IAAI,MAAM;CACzB;AACF"}
|
|
@@ -3,6 +3,11 @@ import satori from "satori";
|
|
|
3
3
|
//#region src/TextMeasurer/TextMeasurer.ts
|
|
4
4
|
const epsilon = 1e-4;
|
|
5
5
|
var TextMeasurer = class {
|
|
6
|
+
text;
|
|
7
|
+
font;
|
|
8
|
+
maxWidth;
|
|
9
|
+
maxHeight;
|
|
10
|
+
lineHeight;
|
|
6
11
|
#fonts;
|
|
7
12
|
constructor(text, font, maxWidth, maxHeight, lineHeight) {
|
|
8
13
|
this.text = text;
|
|
@@ -17,7 +22,7 @@ var TextMeasurer = class {
|
|
|
17
22
|
return width - epsilon <= this.maxWidth && height - epsilon <= this.maxHeight;
|
|
18
23
|
}
|
|
19
24
|
async createSvgXmlString(fontSize) {
|
|
20
|
-
|
|
25
|
+
const node = {
|
|
21
26
|
type: "div",
|
|
22
27
|
key: "satori-fit-text-measure-node",
|
|
23
28
|
props: {
|
|
@@ -36,7 +41,8 @@ var TextMeasurer = class {
|
|
|
36
41
|
},
|
|
37
42
|
children: this.text
|
|
38
43
|
}
|
|
39
|
-
}
|
|
44
|
+
};
|
|
45
|
+
return satori(node, {
|
|
40
46
|
fonts: this.#fonts,
|
|
41
47
|
width: this.maxWidth * 2,
|
|
42
48
|
height: this.maxHeight * 2
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TextMeasurer.js","names":[
|
|
1
|
+
{"version":3,"file":"TextMeasurer.js","names":[],"sources":["../../src/TextMeasurer/TextMeasurer.ts"],"sourcesContent":["import satori from \"satori\";\n\nimport type React from \"react\";\nimport type { Dimensions, Font } from \"../types.js\";\n\n// getBBox seems to be off by a very tiny fraction with certain versions of\n// Inter. Maybe that makes sense... maybe there's a better way of measuring\n// things. But for now, fudge it...\nconst epsilon = 0.0001;\n\nexport abstract class TextMeasurer {\n protected text: string;\n protected font: Font;\n protected maxWidth: number;\n protected maxHeight: number;\n protected lineHeight: number | \"normal\";\n\n #fonts: Font[];\n\n constructor(\n text: string,\n font: Font,\n maxWidth: number,\n maxHeight: number,\n lineHeight: number | \"normal\",\n ) {\n this.text = text;\n this.font = font;\n this.maxWidth = maxWidth;\n this.maxHeight = maxHeight;\n this.lineHeight = lineHeight;\n\n // Satori keeps a WeakMap of fonts arrays. Adding a new font is very\n // expensive, so let's make sure we always return the (referentially) same\n // array if the font is the same, to improve performance.\n this.#fonts = [this.font];\n }\n\n abstract getDimensions(fontSize: number): Promise<Dimensions>;\n\n async doesSizeFit(fontSize: number): Promise<boolean> {\n const { width, height } = await this.getDimensions(fontSize);\n return (\n width - epsilon <= this.maxWidth && height - epsilon <= this.maxHeight\n );\n }\n\n protected async createSvgXmlString(fontSize: number): Promise<string> {\n const node: React.ReactElement = {\n type: \"div\",\n key: \"satori-fit-text-measure-node\",\n props: {\n style: {\n // Static styles\n background: \"white\",\n color: \"black\",\n display: \"flex\",\n flex: 1,\n boxSizing: \"border-box\",\n margin: 0,\n padding: 0,\n\n // Dynamic styles based on input\n fontSize,\n fontFamily: this.font.name,\n maxWidth: this.maxWidth,\n lineHeight: this.lineHeight,\n },\n children: this.text,\n },\n } as const;\n\n // vnode => svg\n return satori(node, {\n fonts: this.#fonts,\n width: this.maxWidth * 2,\n height: this.maxHeight * 2,\n });\n }\n}\n"],"mappings":";;;AAQA,MAAM,UAAU;AAEhB,IAAsB,eAAtB,MAAmC;CACjC,AAAU;CACV,AAAU;CACV,AAAU;CACV,AAAU;CACV,AAAU;CAEV;CAEA,YACE,MACA,MACA,UACA,WACA,YACA;EACA,KAAK,OAAO;EACZ,KAAK,OAAO;EACZ,KAAK,WAAW;EAChB,KAAK,YAAY;EACjB,KAAK,aAAa;EAKlB,KAAK,SAAS,CAAC,KAAK,IAAI;CAC1B;CAIA,MAAM,YAAY,UAAoC;EACpD,MAAM,EAAE,OAAO,WAAW,MAAM,KAAK,cAAc,QAAQ;EAC3D,OACE,QAAQ,WAAW,KAAK,YAAY,SAAS,WAAW,KAAK;CAEjE;CAEA,MAAgB,mBAAmB,UAAmC;EACpE,MAAM,OAA2B;GAC/B,MAAM;GACN,KAAK;GACL,OAAO;IACL,OAAO;KAEL,YAAY;KACZ,OAAO;KACP,SAAS;KACT,MAAM;KACN,WAAW;KACX,QAAQ;KACR,SAAS;KAGT;KACA,YAAY,KAAK,KAAK;KACtB,UAAU,KAAK;KACf,YAAY,KAAK;IACnB;IACA,UAAU,KAAK;GACjB;EACF;EAGA,OAAO,OAAO,MAAM;GAClB,OAAO,KAAK;GACZ,OAAO,KAAK,WAAW;GACvB,QAAQ,KAAK,YAAY;EAC3B,CAAC;CACH;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getTextMeasurer.js","names":[],"sources":["../../src/TextMeasurer/getTextMeasurer.ts"],"sourcesContent":["import type { TextMeasurer } from \"./TextMeasurer.js\";\n\nexport async function getTextMeasurer(\n ...args: ConstructorParameters<typeof TextMeasurer>\n): Promise<TextMeasurer> {\n // TODO Get browser testing working\n /* v8 ignore next 3 */\n if (typeof window !== \"undefined\") {\n const Measurer = await import(\"./BrowserTextMeasurer.js\");\n return new Measurer.default(...args);\n } else {\n const Measurer = await import(\"./HeadlessTextMeasurer.js\");\n return new Measurer.default(...args);\n }\n}\n"],"mappings":";AAEA,eAAsB,gBACpB,GAAG,MACoB;;
|
|
1
|
+
{"version":3,"file":"getTextMeasurer.js","names":[],"sources":["../../src/TextMeasurer/getTextMeasurer.ts"],"sourcesContent":["import type { TextMeasurer } from \"./TextMeasurer.js\";\n\nexport async function getTextMeasurer(\n ...args: ConstructorParameters<typeof TextMeasurer>\n): Promise<TextMeasurer> {\n // TODO Get browser testing working\n /* v8 ignore next 3 */\n if (typeof window !== \"undefined\") {\n const Measurer = await import(\"./BrowserTextMeasurer.js\");\n return new Measurer.default(...args);\n } else {\n const Measurer = await import(\"./HeadlessTextMeasurer.js\");\n return new Measurer.default(...args);\n }\n}\n"],"mappings":";AAEA,eAAsB,gBACpB,GAAG,MACoB;;CAGvB,IAAI,OAAO,WAAW,aAEpB,OAAO,KAAI,OADY,OAAO,6BACX,CAAC,QAAQ,GAAG,IAAI;MAGnC,OAAO,KAAI,OADY,OAAO,8BACX,CAAC,QAAQ,GAAG,IAAI;AAEvC"}
|
package/dist/fitText.d.ts
CHANGED
|
@@ -1,56 +1,45 @@
|
|
|
1
1
|
import { Font } from "./types.js";
|
|
2
|
-
|
|
3
2
|
//#region src/fitText.d.ts
|
|
4
|
-
type FindOptions = {
|
|
3
|
+
export type FindOptions = {
|
|
5
4
|
/**
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
* The text you want to fit
|
|
6
|
+
*/
|
|
8
7
|
text: string;
|
|
9
8
|
/**
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
9
|
+
* The font of your text. Options are the same as [those taken by
|
|
10
|
+
* Satori](https://github.com/vercel/satori#fonts), but only one font and not
|
|
11
|
+
* an array of fonts is accepted here.
|
|
12
|
+
*/
|
|
14
13
|
font: Font;
|
|
15
14
|
/**
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
* The max width the text must be contained in
|
|
16
|
+
*/
|
|
18
17
|
maxWidth: number;
|
|
19
18
|
/**
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
* The max height the text must be contained in
|
|
20
|
+
*/
|
|
22
21
|
maxHeight: number;
|
|
23
22
|
/**
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
* Optional: the CSS line height factor to use, e.g. 1.1
|
|
24
|
+
*/
|
|
26
25
|
lineHeight?: number | "normal";
|
|
27
26
|
/**
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
* The minimum font size that should be returned, even if smaller fonts fit
|
|
28
|
+
*/
|
|
30
29
|
minFontSize?: number;
|
|
31
30
|
/**
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
* The maximum font size that should be returned, even if larger fonts fit
|
|
32
|
+
*/
|
|
34
33
|
maxFontSize?: number;
|
|
35
34
|
/**
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
* The maximum number of font sizes to try before giving up. Defaults to 1000.
|
|
36
|
+
*/
|
|
38
37
|
maxTries?: number;
|
|
39
38
|
};
|
|
40
39
|
/**
|
|
41
|
-
* Given text, dimensions, and some options, returns the largest font size that
|
|
42
|
-
* would keep the text contained within the dimensions.
|
|
43
|
-
*/
|
|
44
|
-
declare function findLargestUsableFontSize({
|
|
45
|
-
text,
|
|
46
|
-
font,
|
|
47
|
-
maxWidth,
|
|
48
|
-
maxHeight,
|
|
49
|
-
lineHeight,
|
|
50
|
-
minFontSize,
|
|
51
|
-
maxFontSize,
|
|
52
|
-
maxTries
|
|
53
|
-
}: FindOptions): Promise<number>;
|
|
40
|
+
* Given text, dimensions, and some options, returns the largest font size that
|
|
41
|
+
* would keep the text contained within the dimensions.
|
|
42
|
+
*/
|
|
43
|
+
export declare function findLargestUsableFontSize({ text, font, maxWidth, maxHeight, lineHeight, minFontSize, maxFontSize, maxTries }: FindOptions): Promise<number>;
|
|
54
44
|
//#endregion
|
|
55
|
-
export { FindOptions, findLargestUsableFontSize };
|
|
56
45
|
//# sourceMappingURL=fitText.d.ts.map
|
package/dist/fitText.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fitText.js","names":[],"sources":["../src/fitText.ts"],"sourcesContent":["import { getTextMeasurer } from \"./TextMeasurer/getTextMeasurer.js\";\n\nimport type { Font } from \"./types.js\";\n\nexport type FindOptions = {\n /**\n * The text you want to fit\n */\n text: string;\n /**\n * The font of your text. Options are the same as [those taken by\n * Satori](https://github.com/vercel/satori#fonts), but only one font and not\n * an array of fonts is accepted here.\n */\n font: Font;\n /**\n * The max width the text must be contained in\n */\n maxWidth: number;\n /**\n * The max height the text must be contained in\n */\n maxHeight: number;\n /**\n * Optional: the CSS line height factor to use, e.g. 1.1\n */\n lineHeight?: number | \"normal\";\n /**\n * The minimum font size that should be returned, even if smaller fonts fit\n */\n minFontSize?: number;\n /**\n * The maximum font size that should be returned, even if larger fonts fit\n */\n maxFontSize?: number;\n /**\n * The maximum number of font sizes to try before giving up. Defaults to 1000.\n */\n maxTries?: number;\n};\n\n/**\n * Given text, dimensions, and some options, returns the largest font size that\n * would keep the text contained within the dimensions.\n */\nexport async function findLargestUsableFontSize({\n text,\n font,\n maxWidth,\n maxHeight,\n lineHeight = \"normal\",\n minFontSize = 1,\n maxFontSize = 1000,\n maxTries = 1000,\n}: FindOptions): Promise<number> {\n if (maxTries < 2) {\n throw new Error(\"`maxTries` must be >= 2\");\n }\n\n const textMeasurer = await getTextMeasurer(\n text,\n font,\n maxWidth,\n maxHeight,\n lineHeight,\n );\n\n for (\n let tries = 1, lower = minFontSize, upper = maxFontSize;\n tries < maxTries;\n ++tries\n ) {\n const searchCutoffThreshold = Math.min(1, lower);\n if (upper - lower <= searchCutoffThreshold) {\n return Math.floor(lower);\n }\n\n const sizeCandidate = Math.floor(lower + (upper - lower) / 2);\n const doesFit = await textMeasurer.doesSizeFit(sizeCandidate);\n\n if (doesFit) {\n lower = sizeCandidate;\n } else {\n upper = sizeCandidate;\n }\n }\n\n throw new Error(\n `Could not find a valid font size in ${\n maxTries - 1\n } attempts. Giving up. Please try again after constraining the search space, e.g. by restricting the min/max font size difference.`,\n );\n}\n"],"mappings":";;;;;;;AA6CA,eAAsB,0BAA0B,EAC9C,MACA,MACA,UACA,WACA,aAAa,UACb,cAAc,GACd,cAAc,KACd,WAAW,OACoB;
|
|
1
|
+
{"version":3,"file":"fitText.js","names":[],"sources":["../src/fitText.ts"],"sourcesContent":["import { getTextMeasurer } from \"./TextMeasurer/getTextMeasurer.js\";\n\nimport type { Font } from \"./types.js\";\n\nexport type FindOptions = {\n /**\n * The text you want to fit\n */\n text: string;\n /**\n * The font of your text. Options are the same as [those taken by\n * Satori](https://github.com/vercel/satori#fonts), but only one font and not\n * an array of fonts is accepted here.\n */\n font: Font;\n /**\n * The max width the text must be contained in\n */\n maxWidth: number;\n /**\n * The max height the text must be contained in\n */\n maxHeight: number;\n /**\n * Optional: the CSS line height factor to use, e.g. 1.1\n */\n lineHeight?: number | \"normal\";\n /**\n * The minimum font size that should be returned, even if smaller fonts fit\n */\n minFontSize?: number;\n /**\n * The maximum font size that should be returned, even if larger fonts fit\n */\n maxFontSize?: number;\n /**\n * The maximum number of font sizes to try before giving up. Defaults to 1000.\n */\n maxTries?: number;\n};\n\n/**\n * Given text, dimensions, and some options, returns the largest font size that\n * would keep the text contained within the dimensions.\n */\nexport async function findLargestUsableFontSize({\n text,\n font,\n maxWidth,\n maxHeight,\n lineHeight = \"normal\",\n minFontSize = 1,\n maxFontSize = 1000,\n maxTries = 1000,\n}: FindOptions): Promise<number> {\n if (maxTries < 2) {\n throw new Error(\"`maxTries` must be >= 2\");\n }\n\n const textMeasurer = await getTextMeasurer(\n text,\n font,\n maxWidth,\n maxHeight,\n lineHeight,\n );\n\n for (\n let tries = 1, lower = minFontSize, upper = maxFontSize;\n tries < maxTries;\n ++tries\n ) {\n const searchCutoffThreshold = Math.min(1, lower);\n if (upper - lower <= searchCutoffThreshold) {\n return Math.floor(lower);\n }\n\n const sizeCandidate = Math.floor(lower + (upper - lower) / 2);\n const doesFit = await textMeasurer.doesSizeFit(sizeCandidate);\n\n if (doesFit) {\n lower = sizeCandidate;\n } else {\n upper = sizeCandidate;\n }\n }\n\n throw new Error(\n `Could not find a valid font size in ${\n maxTries - 1\n } attempts. Giving up. Please try again after constraining the search space, e.g. by restricting the min/max font size difference.`,\n );\n}\n"],"mappings":";;;;;;;AA6CA,eAAsB,0BAA0B,EAC9C,MACA,MACA,UACA,WACA,aAAa,UACb,cAAc,GACd,cAAc,KACd,WAAW,OACoB;CAC/B,IAAI,WAAW,GACb,MAAM,IAAI,MAAM,yBAAyB;CAG3C,MAAM,eAAe,MAAM,gBACzB,MACA,MACA,UACA,WACA,UACF;CAEA,KACE,IAAI,QAAQ,GAAG,QAAQ,aAAa,QAAQ,aAC5C,QAAQ,UACR,EAAE,OACF;EACA,MAAM,wBAAwB,KAAK,IAAI,GAAG,KAAK;EAC/C,IAAI,QAAQ,SAAS,uBACnB,OAAO,KAAK,MAAM,KAAK;EAGzB,MAAM,gBAAgB,KAAK,MAAM,SAAS,QAAQ,SAAS,CAAC;EAG5D,IAAI,MAFkB,aAAa,YAAY,aAAa,GAG1D,QAAQ;OAER,QAAQ;CAEZ;CAEA,MAAM,IAAI,MACR,uCACE,WAAW,EACZ,kIACH;AACF"}
|
package/dist/log.d.ts
CHANGED
package/dist/log.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"log.js","names":[],"sources":["../src/log.ts"],"sourcesContent":["import debug from \"debug\";\n\nconst log: debug.Debugger = debug(\"satori-text-fit\");\n\nexport default log;\n"],"mappings":";;;AAEA,MAAM,MAAsB,MAAM,
|
|
1
|
+
{"version":3,"file":"log.js","names":[],"sources":["../src/log.ts"],"sourcesContent":["import debug from \"debug\";\n\nconst log: debug.Debugger = debug(\"satori-text-fit\");\n\nexport default log;\n"],"mappings":";;;AAEA,MAAM,MAAsB,MAAM,iBAAiB"}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { Font as Font$1 } from "satori";
|
|
2
|
-
|
|
3
2
|
//#region src/types.d.ts
|
|
4
|
-
type Dimensions = Pick<DOMRect, "width" | "height">;
|
|
5
|
-
type Font = Font$1;
|
|
3
|
+
export type Dimensions = Pick<DOMRect, "width" | "height">;
|
|
4
|
+
export type Font = Font$1;
|
|
6
5
|
//#endregion
|
|
7
|
-
export { Dimensions, Font };
|
|
8
6
|
//# sourceMappingURL=types.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@altano/satori-fit-text",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.1.0",
|
|
4
4
|
"description": "Fit text to a bounding box in Node or the browser",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"fit-text",
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"license": "ISC",
|
|
18
18
|
"author": {
|
|
19
19
|
"name": "Alan Norbauer",
|
|
20
|
-
"email": "
|
|
20
|
+
"email": "alan@norbauer.com",
|
|
21
21
|
"url": "https://alan.norbauer.com"
|
|
22
22
|
},
|
|
23
23
|
"sideEffects": false,
|
|
@@ -31,36 +31,36 @@
|
|
|
31
31
|
"dist/**/*.d.ts"
|
|
32
32
|
],
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@svgdotjs/svg.js": "^3.2.
|
|
34
|
+
"@svgdotjs/svg.js": "^3.2.8",
|
|
35
35
|
"debug": "^4.4.3",
|
|
36
|
-
"satori": "^0.
|
|
37
|
-
"svgdom": "^0.1.
|
|
36
|
+
"satori": "^0.55.5",
|
|
37
|
+
"svgdom": "^0.1.29"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
|
-
"@arethetypeswrong/cli": "^0.18.
|
|
41
|
-
"@fontsource-variable/inter": "5.
|
|
42
|
-
"@fontsource/inter": "5.
|
|
43
|
-
"@playwright/test": "1.
|
|
40
|
+
"@arethetypeswrong/cli": "^0.18.5",
|
|
41
|
+
"@fontsource-variable/inter": "5.3.0",
|
|
42
|
+
"@fontsource/inter": "5.3.0",
|
|
43
|
+
"@playwright/test": "1.59.1",
|
|
44
44
|
"@resvg/resvg-js": "^2.6.2",
|
|
45
|
-
"@types/debug": "^4.1.
|
|
45
|
+
"@types/debug": "^4.1.13",
|
|
46
46
|
"@types/he": "^1.2.3",
|
|
47
|
-
"@types/jest-image-snapshot": "^6.4.
|
|
48
|
-
"@types/node": "^
|
|
49
|
-
"@types/react": "^19.
|
|
50
|
-
"@types/react-dom": "^19.
|
|
47
|
+
"@types/jest-image-snapshot": "^6.4.2",
|
|
48
|
+
"@types/node": "^26.6.4",
|
|
49
|
+
"@types/react": "^19.3.0",
|
|
50
|
+
"@types/react-dom": "^19.3.0",
|
|
51
51
|
"@types/svgdom": "^0.1.2",
|
|
52
|
-
"@vitest/coverage-v8": "^
|
|
52
|
+
"@vitest/coverage-v8": "^5.0.3",
|
|
53
53
|
"depcheck": "^1.4.7",
|
|
54
|
-
"jest-image-snapshot": "^6.5.
|
|
55
|
-
"prettier": "
|
|
56
|
-
"react": "^19.
|
|
57
|
-
"tsdown": "^0.
|
|
58
|
-
"typescript": "^
|
|
59
|
-
"vite": "^
|
|
60
|
-
"vitest": "^
|
|
54
|
+
"jest-image-snapshot": "^6.5.2",
|
|
55
|
+
"prettier": "3.9.9",
|
|
56
|
+
"react": "^19.3.0",
|
|
57
|
+
"tsdown": "^0.23.0",
|
|
58
|
+
"typescript": "^6.0.3",
|
|
59
|
+
"vite": "^8.3.2",
|
|
60
|
+
"vitest": "^5.0.3",
|
|
61
61
|
"@altano/assets": "0.0.1",
|
|
62
|
-
"@altano/build-config": "0.0.1",
|
|
63
62
|
"@altano/testing": "0.0.1",
|
|
63
|
+
"@altano/build-config": "0.0.1",
|
|
64
64
|
"@altano/tsconfig": "0.0.1"
|
|
65
65
|
},
|
|
66
66
|
"peerDependencies": {
|
|
@@ -70,15 +70,15 @@
|
|
|
70
70
|
"access": "public"
|
|
71
71
|
},
|
|
72
72
|
"scripts": {
|
|
73
|
-
"build": "tsdown
|
|
73
|
+
"build": "tsdown",
|
|
74
74
|
"check:exports": "attw --pack . --profile esm-only --quiet",
|
|
75
75
|
"check:types:src": "tsc --noEmit",
|
|
76
76
|
"check:types:test": "tsc --noEmit --project ./tests/tsconfig.json",
|
|
77
77
|
"check:unused-dependencies": "depcheck",
|
|
78
78
|
"clean": "rm -rf .turbo && rm -rf .tsbuildinfo && rm -rf node_modules && rm -rf dist",
|
|
79
79
|
"dev": "pnpm run build --watch",
|
|
80
|
-
"format": "prettier --check
|
|
81
|
-
"format:fix": "prettier --write
|
|
80
|
+
"format": "prettier --check .",
|
|
81
|
+
"format:fix": "prettier --write .",
|
|
82
82
|
"lint": "eslint",
|
|
83
83
|
"lint:fix": "TIMING=1 pnpm lint --fix",
|
|
84
84
|
"lint:timing": "TIMING=1 pnpm lint",
|
|
@@ -86,7 +86,7 @@
|
|
|
86
86
|
"test:e2e:server": "pnpm --dir ../../examples/satori-fit-text-playground start",
|
|
87
87
|
"test:e2e:ui": "playwright test --ui",
|
|
88
88
|
"test:unit": "vitest --run",
|
|
89
|
-
"test:unit:benchmark": "vitest --run
|
|
89
|
+
"test:unit:benchmark": "vitest bench --run",
|
|
90
90
|
"test:unit:watch": "vitest"
|
|
91
91
|
}
|
|
92
92
|
}
|