@kensio/colophon 2.12.0 → 2.13.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.
Files changed (104) hide show
  1. package/README.md +8 -4
  2. package/dist/config/defaults.d.ts +32 -4
  3. package/dist/config/defaults.d.ts.map +1 -1
  4. package/dist/config/defaults.js +32 -4
  5. package/dist/config/defaults.js.map +1 -1
  6. package/dist/config/index.d.ts.map +1 -1
  7. package/dist/config/index.js +2 -1
  8. package/dist/config/index.js.map +1 -1
  9. package/dist/config/resolve.d.ts +13 -0
  10. package/dist/config/resolve.d.ts.map +1 -1
  11. package/dist/config/resolve.js +14 -8
  12. package/dist/config/resolve.js.map +1 -1
  13. package/dist/config/size.d.ts.map +1 -1
  14. package/dist/config/size.js +3 -0
  15. package/dist/config/size.js.map +1 -1
  16. package/dist/fonts/bundled.d.ts +38 -0
  17. package/dist/fonts/bundled.d.ts.map +1 -0
  18. package/dist/fonts/bundled.js +29 -0
  19. package/dist/fonts/bundled.js.map +1 -0
  20. package/dist/fonts/index.d.ts +1 -0
  21. package/dist/fonts/index.d.ts.map +1 -1
  22. package/dist/fonts/index.js +1 -0
  23. package/dist/fonts/index.js.map +1 -1
  24. package/dist/layout/fill.d.ts +32 -0
  25. package/dist/layout/fill.d.ts.map +1 -0
  26. package/dist/layout/fill.js +34 -0
  27. package/dist/layout/fill.js.map +1 -0
  28. package/dist/layout/index.d.ts +4 -2
  29. package/dist/layout/index.d.ts.map +1 -1
  30. package/dist/layout/index.js +2 -1
  31. package/dist/layout/index.js.map +1 -1
  32. package/dist/measure/faces.d.ts.map +1 -1
  33. package/dist/measure/faces.js +29 -5
  34. package/dist/measure/faces.js.map +1 -1
  35. package/dist/measure/index.d.ts.map +1 -1
  36. package/dist/measure/index.js +0 -0
  37. package/dist/measure/index.js.map +1 -1
  38. package/dist/platform/bundled-fonts.browser.d.ts +16 -0
  39. package/dist/platform/bundled-fonts.browser.d.ts.map +1 -0
  40. package/dist/platform/bundled-fonts.browser.js +17 -0
  41. package/dist/platform/bundled-fonts.browser.js.map +1 -0
  42. package/dist/platform/bundled-fonts.node.d.ts +18 -0
  43. package/dist/platform/bundled-fonts.node.d.ts.map +1 -0
  44. package/dist/platform/bundled-fonts.node.js +49 -0
  45. package/dist/platform/bundled-fonts.node.js.map +1 -0
  46. package/dist/render/rasterise.d.ts.map +1 -1
  47. package/dist/render/rasterise.js +8 -3
  48. package/dist/render/rasterise.js.map +1 -1
  49. package/dist/render/svg.js +1 -1
  50. package/dist/render/svg.js.map +1 -1
  51. package/dist/templates/index.d.ts +1 -0
  52. package/dist/templates/index.d.ts.map +1 -1
  53. package/dist/templates/index.js +3 -0
  54. package/dist/templates/index.js.map +1 -1
  55. package/dist/templates/thumbnail/index.d.ts +21 -0
  56. package/dist/templates/thumbnail/index.d.ts.map +1 -0
  57. package/dist/templates/thumbnail/index.js +68 -0
  58. package/dist/templates/thumbnail/index.js.map +1 -0
  59. package/dist/templates/thumbnail/lines.d.ts +38 -0
  60. package/dist/templates/thumbnail/lines.d.ts.map +1 -0
  61. package/dist/templates/thumbnail/lines.js +76 -0
  62. package/dist/templates/thumbnail/lines.js.map +1 -0
  63. package/dist/text/fill.d.ts +34 -0
  64. package/dist/text/fill.d.ts.map +1 -0
  65. package/dist/text/fill.js +57 -0
  66. package/dist/text/fill.js.map +1 -0
  67. package/dist/text/fit.d.ts.map +1 -1
  68. package/dist/text/fit.js +2 -6
  69. package/dist/text/fit.js.map +1 -1
  70. package/dist/text/index.d.ts +2 -0
  71. package/dist/text/index.d.ts.map +1 -1
  72. package/dist/text/index.js +1 -0
  73. package/dist/text/index.js.map +1 -1
  74. package/dist/text/step.d.ts +13 -0
  75. package/dist/text/step.d.ts.map +1 -0
  76. package/dist/text/step.js +17 -0
  77. package/dist/text/step.js.map +1 -0
  78. package/dist/text/unbroken.d.ts +22 -0
  79. package/dist/text/unbroken.d.ts.map +1 -0
  80. package/dist/text/unbroken.js +29 -0
  81. package/dist/text/unbroken.js.map +1 -0
  82. package/dist/texture/index.d.ts +14 -2
  83. package/dist/texture/index.d.ts.map +1 -1
  84. package/dist/texture/index.js +22 -3
  85. package/dist/texture/index.js.map +1 -1
  86. package/dist/texture/resolve.d.ts +10 -0
  87. package/dist/texture/resolve.d.ts.map +1 -1
  88. package/dist/texture/resolve.js +15 -0
  89. package/dist/texture/resolve.js.map +1 -1
  90. package/dist/types.d.ts +28 -0
  91. package/dist/types.d.ts.map +1 -1
  92. package/dist/validate/keys.d.ts.map +1 -1
  93. package/dist/validate/keys.js +2 -0
  94. package/dist/validate/keys.js.map +1 -1
  95. package/fonts/JetBrainsMono-LICENSE.txt +93 -0
  96. package/fonts/JetBrainsMono_400Regular.ttf +0 -0
  97. package/fonts/JetBrainsMono_700Bold.ttf +0 -0
  98. package/fonts/Outfit-LICENSE.txt +93 -0
  99. package/fonts/Outfit_400Regular.ttf +0 -0
  100. package/fonts/Outfit_500Medium.ttf +0 -0
  101. package/fonts/Outfit_600SemiBold.ttf +0 -0
  102. package/fonts/Outfit_700Bold.ttf +0 -0
  103. package/fonts/Outfit_800ExtraBold.ttf +0 -0
  104. package/package.json +4 -2
Binary file
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/measure/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE9C,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAIzC;;;;;;;;GAQG;AACH,SAAS,OAAO,CACd,KAAsB,EACtB,KAAgB,EAChB,cAAuB;IAEvB,MAAM,MAAM,GAAG,KAAK,CAAC,UAAU,IAAI,GAAG,CAAC;IAEvC,OAAO,CACL,UAAU,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,EAAE,MAAM,CAAC;QAC3C,CAAC,cAAc,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CACxC,CAAC;AACJ,CAAC;AAED,gEAAgE;AAChE,SAAS,SAAS,CAChB,IAAY,EACZ,KAAgB,EAChB,KAAsB,EACtB,cAAuB;IAEvB,MAAM,MAAM,GAAG,KAAK,CAAC,UAAU,IAAI,GAAG,CAAC;IACvC,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,EAAE,KAAK,EAAE,cAAc,CAAC,CAAC;IAEtD,IAAI,GAAG,GAAG,CAAC,CAAC;IAEZ,KAAK,MAAM,GAAG,IAAI,YAAY,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,CAAC;QACrD,GAAG;YACD,GAAG,CAAC,IAAI,KAAK,SAAS;gBACpB,CAAC,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,aAAa,CAAC;gBACzD,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC;IAED,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,MAAsB;IAEtB,MAAM,KAAK,GAAG,MAAM,SAAS,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC;IAC9D,MAAM,KAAK,GAAG,IAAI,GAAG,EAAkB,CAAC;IAExC,OAAO,CAAC,IAAY,EAAE,KAAgB,EAAU,EAAE;QAChD,MAAM,GAAG,GAAG,GAAG,KAAK,CAAC,UAAU,IAAI,MAAM,CAAC,KAAK,CAAC,UAAU,IAAI,GAAG,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,aAAa,IAAI,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC;QAClH,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAE7B,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,OAAO,KAAK,GAAG,KAAK,CAAC,QAAQ,CAAC;QAChC,CAAC;QAED,MAAM,GAAG,GAAG,SAAS,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,WAAW,CAAC,CAAC;QAC9D,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QACpB,OAAO,GAAG,GAAG,KAAK,CAAC,QAAQ,CAAC;IAC9B,CAAC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/measure/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAEvD,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE9C,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAIzC;;;;;;;;GAQG;AACH,SAAS,OAAO,CACd,KAAsB,EACtB,KAAgB,EAChB,cAAuB;IAEvB,MAAM,MAAM,GAAG,KAAK,CAAC,UAAU,IAAI,GAAG,CAAC;IAEvC,OAAO,CACL,UAAU,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,EAAE,MAAM,CAAC;QAC3C,CAAC,cAAc,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CACxC,CAAC;AACJ,CAAC;AAED,gEAAgE;AAChE,SAAS,SAAS,CAChB,IAAY,EACZ,KAAgB,EAChB,KAAsB,EACtB,cAAuB;IAEvB,MAAM,MAAM,GAAG,KAAK,CAAC,UAAU,IAAI,GAAG,CAAC;IACvC,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,EAAE,KAAK,EAAE,cAAc,CAAC,CAAC;IAEtD,IAAI,GAAG,GAAG,CAAC,CAAC;IAEZ,KAAK,MAAM,GAAG,IAAI,YAAY,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,CAAC;QACrD,GAAG;YACD,GAAG,CAAC,IAAI,KAAK,SAAS;gBACpB,CAAC,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,aAAa,CAAC;gBACzD,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC;IAED,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,MAAsB;IAEtB,wEAAwE;IACxE,wEAAwE;IACxE,gBAAgB;IAChB,MAAM,KAAK,GAAG,MAAM,SAAS,CAC3B,gBAAgB,CAAC,MAAM,CAAC,KAAK,CAAC,EAC9B,MAAM,CAAC,SAAS,CACjB,CAAC;IACF,MAAM,KAAK,GAAG,IAAI,GAAG,EAAkB,CAAC;IAExC,OAAO,CAAC,IAAY,EAAE,KAAgB,EAAU,EAAE;QAChD,MAAM,GAAG,GAAG,GAAG,KAAK,CAAC,UAAU,IAAI,MAAM,CAAC,KAAK,CAAC,UAAU,IAAI,GAAG,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,aAAa,IAAI,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC;QAClH,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAE7B,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,OAAO,KAAK,GAAG,KAAK,CAAC,QAAQ,CAAC;QAChC,CAAC;QAED,MAAM,GAAG,GAAG,SAAS,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,WAAW,CAAC,CAAC;QAC9D,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QACpB,OAAO,GAAG,GAAG,KAAK,CAAC,QAAQ,CAAC;IAC9B,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,16 @@
1
+ import type { BundledFont } from "../fonts/bundled.js";
2
+ /**
3
+ * The bundled fonts in the browser and at the edge, which is to say none.
4
+ *
5
+ * A bundler picks this up through `package.json`'s `browser` field. The fonts
6
+ * that ship with the package are files, and a file path means nothing here, so
7
+ * offering them would be offering something `readFileBytes` is about to refuse.
8
+ * Inlining the bytes instead would put half a megabyte of font into every
9
+ * bundle that imports the core, whether or not it draws any text.
10
+ *
11
+ * So text in a browser is measured by estimate and drawn in whatever the host
12
+ * has, exactly as it was before there were bundled fonts. A page that wants
13
+ * them supplies them itself, as bytes, which is what `FontSource.data` is for.
14
+ */
15
+ export declare function bundledFonts(): readonly BundledFont[];
16
+ //# sourceMappingURL=bundled-fonts.browser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bundled-fonts.browser.d.ts","sourceRoot":"","sources":["../../src/platform/bundled-fonts.browser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAEvD;;;;;;;;;;;;GAYG;AACH,wBAAgB,YAAY,IAAI,SAAS,WAAW,EAAE,CAErD"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * The bundled fonts in the browser and at the edge, which is to say none.
3
+ *
4
+ * A bundler picks this up through `package.json`'s `browser` field. The fonts
5
+ * that ship with the package are files, and a file path means nothing here, so
6
+ * offering them would be offering something `readFileBytes` is about to refuse.
7
+ * Inlining the bytes instead would put half a megabyte of font into every
8
+ * bundle that imports the core, whether or not it draws any text.
9
+ *
10
+ * So text in a browser is measured by estimate and drawn in whatever the host
11
+ * has, exactly as it was before there were bundled fonts. A page that wants
12
+ * them supplies them itself, as bytes, which is what `FontSource.data` is for.
13
+ */
14
+ export function bundledFonts() {
15
+ return [];
16
+ }
17
+ //# sourceMappingURL=bundled-fonts.browser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bundled-fonts.browser.js","sourceRoot":"","sources":["../../src/platform/bundled-fonts.browser.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,YAAY;IAC1B,OAAO,EAAE,CAAC;AACZ,CAAC"}
@@ -0,0 +1,18 @@
1
+ import type { BundledFont } from "../fonts/bundled.js";
2
+ /**
3
+ * The bundled fonts, in the order they are loaded.
4
+ *
5
+ * The family is declared as well as being in the file, which is a fact written
6
+ * down twice and worth the duplication for one reason: `fallbackFamily` reads
7
+ * declared families and nothing else, and it is what tells resvg which family
8
+ * to draw a stack in when the stack names nothing that was loaded. Without a
9
+ * declared family here, a project setting `fontFamily` to something it has not
10
+ * supplied would have its text measured against Outfit and drawn in whatever
11
+ * resvg falls back to on its own, which is how a layout comes out wrong on one
12
+ * machine and right on another. Nothing else reads these: matching a
13
+ * `font-family` to a file is done from the file's own name table, by the
14
+ * rasteriser and by `measure/faces.ts` alike. `fonts.test.ts` checks the two
15
+ * against each other so they cannot drift.
16
+ */
17
+ export declare function bundledFonts(): readonly BundledFont[];
18
+ //# sourceMappingURL=bundled-fonts.node.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bundled-fonts.node.d.ts","sourceRoot":"","sources":["../../src/platform/bundled-fonts.node.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AA6BvD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,YAAY,IAAI,SAAS,WAAW,EAAE,CAKrD"}
@@ -0,0 +1,49 @@
1
+ import { fileURLToPath } from "node:url";
2
+ /**
3
+ * The font files that ship with the package, as absolute paths.
4
+ *
5
+ * Two families, and only the cuts the built-in templates draw: Outfit at 400
6
+ * through 800 for everything that is words, and JetBrains Mono at 400 and 700
7
+ * for the code templates. The whole of either family would be most of a
8
+ * megabyte to install for cuts nothing asks for, and a weight that is not here
9
+ * is drawn in the nearest one that is, by resvg and by `selectFace` alike.
10
+ *
11
+ * Static cuts rather than the variable fonts, because resvg draws a variable
12
+ * font at its default instance and a single file would then be one weight.
13
+ *
14
+ * They are named from `import.meta.url` rather than resolved from the working
15
+ * directory, since the working directory belongs to the project being built
16
+ * and these live wherever the package was installed. Two levels up from
17
+ * `dist/platform/` is the package root.
18
+ */
19
+ const files = [
20
+ ["Outfit", "Outfit_400Regular.ttf"],
21
+ ["Outfit", "Outfit_500Medium.ttf"],
22
+ ["Outfit", "Outfit_600SemiBold.ttf"],
23
+ ["Outfit", "Outfit_700Bold.ttf"],
24
+ ["Outfit", "Outfit_800ExtraBold.ttf"],
25
+ ["JetBrains Mono", "JetBrainsMono_400Regular.ttf"],
26
+ ["JetBrains Mono", "JetBrainsMono_700Bold.ttf"],
27
+ ];
28
+ /**
29
+ * The bundled fonts, in the order they are loaded.
30
+ *
31
+ * The family is declared as well as being in the file, which is a fact written
32
+ * down twice and worth the duplication for one reason: `fallbackFamily` reads
33
+ * declared families and nothing else, and it is what tells resvg which family
34
+ * to draw a stack in when the stack names nothing that was loaded. Without a
35
+ * declared family here, a project setting `fontFamily` to something it has not
36
+ * supplied would have its text measured against Outfit and drawn in whatever
37
+ * resvg falls back to on its own, which is how a layout comes out wrong on one
38
+ * machine and right on another. Nothing else reads these: matching a
39
+ * `font-family` to a file is done from the file's own name table, by the
40
+ * rasteriser and by `measure/faces.ts` alike. `fonts.test.ts` checks the two
41
+ * against each other so they cannot drift.
42
+ */
43
+ export function bundledFonts() {
44
+ return files.map(([family, file]) => ({
45
+ family,
46
+ path: fileURLToPath(new URL(`../../fonts/${file}`, import.meta.url)),
47
+ }));
48
+ }
49
+ //# sourceMappingURL=bundled-fonts.node.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bundled-fonts.node.js","sourceRoot":"","sources":["../../src/platform/bundled-fonts.node.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAIzC;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,KAAK,GAAyD;IAClE,CAAC,QAAQ,EAAE,uBAAuB,CAAC;IACnC,CAAC,QAAQ,EAAE,sBAAsB,CAAC;IAClC,CAAC,QAAQ,EAAE,wBAAwB,CAAC;IACpC,CAAC,QAAQ,EAAE,oBAAoB,CAAC;IAChC,CAAC,QAAQ,EAAE,yBAAyB,CAAC;IACrC,CAAC,gBAAgB,EAAE,8BAA8B,CAAC;IAClD,CAAC,gBAAgB,EAAE,2BAA2B,CAAC;CAChD,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,YAAY;IAC1B,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;QACpC,MAAM;QACN,IAAI,EAAE,aAAa,CAAC,IAAI,GAAG,CAAC,eAAe,IAAI,EAAE,EAAE,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;KACrE,CAAC,CAAC,CAAC;AACN,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"rasterise.d.ts","sourceRoot":"","sources":["../../src/render/rasterise.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAkB,MAAM,aAAa,CAAC;AAkB9D;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,eAAe,EAAE,UAO7B,CAAC"}
1
+ {"version":3,"file":"rasterise.d.ts","sourceRoot":"","sources":["../../src/render/rasterise.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,UAAU,EAAkB,MAAM,aAAa,CAAC;AAuB9D;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,eAAe,EAAE,UAO7B,CAAC"}
@@ -1,14 +1,19 @@
1
1
  import { renderAsync } from "@resvg/resvg-js";
2
- import { fallbackFamily, fontFilePaths } from "../fonts/index.js";
2
+ import { fallbackFamily, fontFilePaths, withBundledFonts, } from "../fonts/index.js";
3
3
  /**
4
4
  * Font options for resvg: the configured font files, and whether to fall back
5
5
  * to the machine's own.
6
6
  */
7
7
  async function fontOptions(config) {
8
- const fallback = fallbackFamily(config.fonts);
8
+ // The bundled fonts count here too, so that a stack naming nothing loaded
9
+ // falls back to Outfit rather than to whatever resvg would have chosen. That
10
+ // is the family the measurer will have measured against, and the two have to
11
+ // agree or the layout is right on a machine that happens to have the font
12
+ // and wrong on one that does not.
13
+ const fallback = fallbackFamily(withBundledFonts(config.fonts));
9
14
  return {
10
15
  loadSystemFonts: config.systemFonts,
11
- fontFiles: await fontFilePaths(config.fonts),
16
+ fontFiles: await fontFilePaths(withBundledFonts(config.fonts)),
12
17
  ...(fallback !== undefined && { defaultFontFamily: fallback }),
13
18
  };
14
19
  }
@@ -1 +1 @@
1
- {"version":3,"file":"rasterise.js","sourceRoot":"","sources":["../../src/render/rasterise.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAE9C,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAGlE;;;GAGG;AACH,KAAK,UAAU,WAAW,CACxB,MAAsB;IAEtB,MAAM,QAAQ,GAAG,cAAc,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAE9C,OAAO;QACL,eAAe,EAAE,MAAM,CAAC,WAAW;QACnC,SAAS,EAAE,MAAM,aAAa,CAAC,MAAM,CAAC,KAAK,CAAC;QAC5C,GAAG,CAAC,QAAQ,KAAK,SAAS,IAAI,EAAE,iBAAiB,EAAE,QAAQ,EAAE,CAAC;KAC/D,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,eAAe,GAAe,KAAK,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,EAAE,EAAE;IAC3E,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,GAAG,EAAE;QACtC,KAAK,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,CAAC,KAAK,EAAE;QACjD,IAAI,EAAE,MAAM,WAAW,CAAC,MAAM,CAAC;KAChC,CAAC,CAAC;IAEH,OAAO,QAAQ,CAAC,KAAK,EAAE,CAAC;AAC1B,CAAC,CAAC"}
1
+ {"version":3,"file":"rasterise.js","sourceRoot":"","sources":["../../src/render/rasterise.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAE9C,OAAO,EACL,cAAc,EACd,aAAa,EACb,gBAAgB,GACjB,MAAM,mBAAmB,CAAC;AAG3B;;;GAGG;AACH,KAAK,UAAU,WAAW,CACxB,MAAsB;IAEtB,0EAA0E;IAC1E,6EAA6E;IAC7E,6EAA6E;IAC7E,0EAA0E;IAC1E,kCAAkC;IAClC,MAAM,QAAQ,GAAG,cAAc,CAAC,gBAAgB,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IAEhE,OAAO;QACL,eAAe,EAAE,MAAM,CAAC,WAAW;QACnC,SAAS,EAAE,MAAM,aAAa,CAAC,gBAAgB,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC9D,GAAG,CAAC,QAAQ,KAAK,SAAS,IAAI,EAAE,iBAAiB,EAAE,QAAQ,EAAE,CAAC;KAC/D,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,eAAe,GAAe,KAAK,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,EAAE,EAAE;IAC3E,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,GAAG,EAAE;QACtC,KAAK,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,CAAC,KAAK,EAAE;QACjD,IAAI,EAAE,MAAM,WAAW,CAAC,MAAM,CAAC;KAChC,CAAC,CAAC;IAEH,OAAO,QAAQ,CAAC,KAAK,EAAE,CAAC;AAC1B,CAAC,CAAC"}
@@ -25,7 +25,7 @@ export async function buildSvg(props, config, dimensions) {
25
25
  // background some surface without ever coming between text and reader.
26
26
  const texture = config.texture === undefined
27
27
  ? ""
28
- : textureSvg(config.texture, dimensions, textureId);
28
+ : textureSvg(config.texture, dimensions, textureId, config.textureScale);
29
29
  const body = await template.render({
30
30
  props,
31
31
  config,
@@ -1 +1 @@
1
- {"version":3,"file":"svg.js","sourceRoot":"","sources":["../../src/render/svg.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEjD,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAE/C,MAAM,YAAY,GAAG,aAAa,CAAC;AACnC,MAAM,SAAS,GAAG,kBAAkB,CAAC;AAErC;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC5B,KAAqB,EACrB,MAAsB,EACtB,UAAsB;IAEtB,MAAM,QAAQ,GAAG,cAAc,CAAC,MAAM,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;IACxD,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QAC1C,cAAc,CAAC,MAAM,CAAC;QACtB,UAAU,CAAC,MAAM,EAAE,KAAK,CAAC;KAC1B,CAAC,CAAC;IAEH,MAAM,UAAU,GAAG,aAAa,CAC9B,MAAM,CAAC,UAAU,EACjB,UAAU,EACV,YAAY,EACZ,MAAM,CAAC,UAAU,CAClB,CAAC;IACF,4EAA4E;IAC5E,uEAAuE;IACvE,MAAM,OAAO,GACX,MAAM,CAAC,OAAO,KAAK,SAAS;QAC1B,CAAC,CAAC,EAAE;QACJ,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,OAAO,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC;IACxD,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC;QACjC,KAAK;QACL,MAAM;QACN,UAAU;QACV,OAAO;QACP,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,OAAO,EAAE,MAAM,CAAC,OAAO;KACxB,CAAC,CAAC;IACH,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,UAAU,CAAC;IAErC,OAAO,CACL,eAAe,MAAM,CAAC,KAAK,CAAC,aAAa,MAAM,CAAC,MAAM,CAAC,GAAG;QAC1D,iBAAiB,MAAM,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,GAAG;QACnD,uCAAuC,UAAU,GAAG,OAAO,GAAG,IAAI,QAAQ,CAC3E,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"svg.js","sourceRoot":"","sources":["../../src/render/svg.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEjD,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAE/C,MAAM,YAAY,GAAG,aAAa,CAAC;AACnC,MAAM,SAAS,GAAG,kBAAkB,CAAC;AAErC;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC5B,KAAqB,EACrB,MAAsB,EACtB,UAAsB;IAEtB,MAAM,QAAQ,GAAG,cAAc,CAAC,MAAM,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;IACxD,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QAC1C,cAAc,CAAC,MAAM,CAAC;QACtB,UAAU,CAAC,MAAM,EAAE,KAAK,CAAC;KAC1B,CAAC,CAAC;IAEH,MAAM,UAAU,GAAG,aAAa,CAC9B,MAAM,CAAC,UAAU,EACjB,UAAU,EACV,YAAY,EACZ,MAAM,CAAC,UAAU,CAClB,CAAC;IACF,4EAA4E;IAC5E,uEAAuE;IACvE,MAAM,OAAO,GACX,MAAM,CAAC,OAAO,KAAK,SAAS;QAC1B,CAAC,CAAC,EAAE;QACJ,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,CAAC,YAAY,CAAC,CAAC;IAC7E,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC;QACjC,KAAK;QACL,MAAM;QACN,UAAU;QACV,OAAO;QACP,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,OAAO,EAAE,MAAM,CAAC,OAAO;KACxB,CAAC,CAAC;IACH,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,UAAU,CAAC;IAErC,OAAO,CACL,eAAe,MAAM,CAAC,KAAK,CAAC,aAAa,MAAM,CAAC,MAAM,CAAC,GAAG;QAC1D,iBAAiB,MAAM,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,GAAG;QACnD,uCAAuC,UAAU,GAAG,OAAO,GAAG,IAAI,QAAQ,CAC3E,CAAC;AACJ,CAAC"}
@@ -15,6 +15,7 @@ export { quoteTemplate } from "./quote/index.js";
15
15
  export { releaseTemplate } from "./release/index.js";
16
16
  export { statTemplate } from "./stat/index.js";
17
17
  export { terminalTemplate } from "./terminal/index.js";
18
+ export { thumbnailTemplate } from "./thumbnail/index.js";
18
19
  export { wordmarkTemplate } from "./wordmark/index.js";
19
20
  export { optionalString } from "../props.js";
20
21
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/templates/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAc5C;;;GAGG;AACH,eAAO,MAAM,gBAAgB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAa/D,CAAC;AAEF,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/templates/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAe5C;;;GAGG;AACH,eAAO,MAAM,gBAAgB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAc/D,CAAC;AAEF,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC"}
@@ -9,6 +9,7 @@ import { quoteTemplate } from "./quote/index.js";
9
9
  import { releaseTemplate } from "./release/index.js";
10
10
  import { statTemplate } from "./stat/index.js";
11
11
  import { terminalTemplate } from "./terminal/index.js";
12
+ import { thumbnailTemplate } from "./thumbnail/index.js";
12
13
  import { wordmarkTemplate } from "./wordmark/index.js";
13
14
  /**
14
15
  * Templates registered out of the box. Projects can add to or override these
@@ -26,6 +27,7 @@ export const builtinTemplates = {
26
27
  [releaseTemplate.name]: releaseTemplate,
27
28
  [statTemplate.name]: statTemplate,
28
29
  [terminalTemplate.name]: terminalTemplate,
30
+ [thumbnailTemplate.name]: thumbnailTemplate,
29
31
  [wordmarkTemplate.name]: wordmarkTemplate,
30
32
  };
31
33
  export { articleTemplate } from "./article/index.js";
@@ -39,6 +41,7 @@ export { quoteTemplate } from "./quote/index.js";
39
41
  export { releaseTemplate } from "./release/index.js";
40
42
  export { statTemplate } from "./stat/index.js";
41
43
  export { terminalTemplate } from "./terminal/index.js";
44
+ export { thumbnailTemplate } from "./thumbnail/index.js";
42
45
  export { wordmarkTemplate } from "./wordmark/index.js";
43
46
  export { optionalString } from "../props.js";
44
47
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/templates/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAEvD;;;GAGG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAuC;IAClE,CAAC,eAAe,CAAC,IAAI,CAAC,EAAE,eAAe;IACvC,CAAC,cAAc,CAAC,IAAI,CAAC,EAAE,cAAc;IACrC,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,YAAY;IACjC,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,YAAY;IACjC,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,YAAY;IACjC,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,aAAa;IACnC,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,aAAa;IACnC,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,aAAa;IACnC,CAAC,eAAe,CAAC,IAAI,CAAC,EAAE,eAAe;IACvC,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,YAAY;IACjC,CAAC,gBAAgB,CAAC,IAAI,CAAC,EAAE,gBAAgB;IACzC,CAAC,gBAAgB,CAAC,IAAI,CAAC,EAAE,gBAAgB;CAC1C,CAAC;AAEF,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/templates/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAEvD;;;GAGG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAuC;IAClE,CAAC,eAAe,CAAC,IAAI,CAAC,EAAE,eAAe;IACvC,CAAC,cAAc,CAAC,IAAI,CAAC,EAAE,cAAc;IACrC,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,YAAY;IACjC,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,YAAY;IACjC,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,YAAY;IACjC,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,aAAa;IACnC,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,aAAa;IACnC,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,aAAa;IACnC,CAAC,eAAe,CAAC,IAAI,CAAC,EAAE,eAAe;IACvC,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,YAAY;IACjC,CAAC,gBAAgB,CAAC,IAAI,CAAC,EAAE,gBAAgB;IACzC,CAAC,iBAAiB,CAAC,IAAI,CAAC,EAAE,iBAAiB;IAC3C,CAAC,gBAAgB,CAAC,IAAI,CAAC,EAAE,gBAAgB;CAC1C,CAAC;AAEF,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,21 @@
1
+ import type { Template } from "../../types.js";
2
+ /**
3
+ * A video thumbnail: one title, set as large as it will go, with an optional
4
+ * line under it.
5
+ *
6
+ * It is meant for YouTube, whose own recommendation is 1280x720, and
7
+ * `SIZE_PRESETS.thumbnail` is that size. What makes it a template of its own
8
+ * rather than a `card` at other proportions is where it is looked at. A share
9
+ * image is seen more or less at the size it was rendered; a thumbnail is seen
10
+ * in a list, a sidebar or a phone, at something between a third and a sixth of
11
+ * it. So the title is grown to fill the frame rather than set at a fraction of
12
+ * the height, there is one text field by default rather than three, and the
13
+ * margins are tighter than elsewhere.
14
+ *
15
+ * Everything the other centred templates draw is still drawn: the logo above,
16
+ * the footer along the bottom. Both are worth having on a channel's images,
17
+ * and a size can drop the footer with `footer: ""` where the title should have
18
+ * the whole frame.
19
+ */
20
+ export declare const thumbnailTemplate: Template;
21
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/templates/thumbnail/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAmB,MAAM,gBAAgB,CAAC;AAoBhE;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,iBAAiB,EAAE,QAsD/B,CAAC"}
@@ -0,0 +1,68 @@
1
+ import { linesHeight, stack } from "../../layout/index.js";
2
+ import { drawSlot, footerLine } from "../bottom.js";
3
+ import { contentArea, imageFrame, markRoom } from "../frame.js";
4
+ import { logoElement, logoRect } from "../logo.js";
5
+ import { subtitleGap, subtitleLineHeight, subtitleRoom, thumbnailSubtitle, thumbnailTitle, titleLineHeight, } from "./lines.js";
6
+ /**
7
+ * The margin, as a fraction of the width. Tighter than any of the other
8
+ * centred layouts, because the room the margins give back is the whole point
9
+ * of this one.
10
+ */
11
+ const padScale = 0.055;
12
+ /**
13
+ * A video thumbnail: one title, set as large as it will go, with an optional
14
+ * line under it.
15
+ *
16
+ * It is meant for YouTube, whose own recommendation is 1280x720, and
17
+ * `SIZE_PRESETS.thumbnail` is that size. What makes it a template of its own
18
+ * rather than a `card` at other proportions is where it is looked at. A share
19
+ * image is seen more or less at the size it was rendered; a thumbnail is seen
20
+ * in a list, a sidebar or a phone, at something between a third and a sixth of
21
+ * it. So the title is grown to fill the frame rather than set at a fraction of
22
+ * the height, there is one text field by default rather than three, and the
23
+ * margins are tighter than elsewhere.
24
+ *
25
+ * Everything the other centred templates draw is still drawn: the logo above,
26
+ * the footer along the bottom. Both are worth having on a channel's images,
27
+ * and a size can drop the footer with `footer: ""` where the title should have
28
+ * the whole frame.
29
+ */
30
+ export const thumbnailTemplate = {
31
+ name: "thumbnail",
32
+ render({ props, config, dimensions, measure, logo, avatar, }) {
33
+ const { width, height } = dimensions;
34
+ const frame = imageFrame(dimensions, config, avatar, { padScale });
35
+ const { pad } = frame;
36
+ const mark = logoRect(logo, dimensions, pad, "middle");
37
+ const area = contentArea(frame, markRoom(mark?.height, pad / 2));
38
+ const text = {
39
+ measure,
40
+ fontFamily: config.fontFamily,
41
+ contentWidth: area.width,
42
+ contentHeight: area.height,
43
+ height,
44
+ };
45
+ const subtitle = thumbnailSubtitle(props, text);
46
+ const title = thumbnailTitle(props, text, subtitleRoom(subtitle, height));
47
+ const [titleSlot, subtitleSlot] = stack([
48
+ { size: linesHeight(title, titleLineHeight) },
49
+ {
50
+ size: linesHeight(subtitle, subtitleLineHeight),
51
+ gapBefore: subtitle.length === 0 ? 0 : subtitleGap(height),
52
+ },
53
+ ], area);
54
+ const style = {
55
+ fontFamily: config.fontFamily,
56
+ fill: config.colors.foreground,
57
+ anchor: "middle",
58
+ };
59
+ return (logoElement(logo, mark) +
60
+ drawSlot(title, titleSlot, { ...style, lineHeight: titleLineHeight }) +
61
+ drawSlot(subtitle, subtitleSlot, {
62
+ ...style,
63
+ lineHeight: subtitleLineHeight,
64
+ }) +
65
+ footerLine(config, frame, width, avatar, measure, "middle"));
66
+ },
67
+ };
68
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/templates/thumbnail/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAE3D,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAChE,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,EACL,WAAW,EACX,kBAAkB,EAClB,YAAY,EACZ,iBAAiB,EACjB,cAAc,EACd,eAAe,GAChB,MAAM,YAAY,CAAC;AAEpB;;;;GAIG;AACH,MAAM,QAAQ,GAAG,KAAK,CAAC;AAEvB;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAa;IACzC,IAAI,EAAE,WAAW;IACjB,MAAM,CAAC,EACL,KAAK,EACL,MAAM,EACN,UAAU,EACV,OAAO,EACP,IAAI,EACJ,MAAM,GACU;QAChB,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,UAAU,CAAC;QACrC,MAAM,KAAK,GAAG,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC;QACnE,MAAM,EAAE,GAAG,EAAE,GAAG,KAAK,CAAC;QACtB,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC;QAEvD,MAAM,IAAI,GAAG,WAAW,CAAC,KAAK,EAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;QACjE,MAAM,IAAI,GAAG;YACX,OAAO;YACP,UAAU,EAAE,MAAM,CAAC,UAAU;YAC7B,YAAY,EAAE,IAAI,CAAC,KAAK;YACxB,aAAa,EAAE,IAAI,CAAC,MAAM;YAC1B,MAAM;SACP,CAAC;QAEF,MAAM,QAAQ,GAAG,iBAAiB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QAChD,MAAM,KAAK,GAAG,cAAc,CAAC,KAAK,EAAE,IAAI,EAAE,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC;QAE1E,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,KAAK,CACrC;YACE,EAAE,IAAI,EAAE,WAAW,CAAC,KAAK,EAAE,eAAe,CAAC,EAAE;YAC7C;gBACE,IAAI,EAAE,WAAW,CAAC,QAAQ,EAAE,kBAAkB,CAAC;gBAC/C,SAAS,EAAE,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,MAAM,CAAC;aAC3D;SACF,EACD,IAAI,CACL,CAAC;QAEF,MAAM,KAAK,GAAG;YACZ,UAAU,EAAE,MAAM,CAAC,UAAU;YAC7B,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,UAAU;YAC9B,MAAM,EAAE,QAAiB;SAC1B,CAAC;QAEF,OAAO,CACL,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC;YACvB,QAAQ,CAAC,KAAK,EAAE,SAAS,EAAE,EAAE,GAAG,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,CAAC;YACrE,QAAQ,CAAC,QAAQ,EAAE,YAAY,EAAE;gBAC/B,GAAG,KAAK;gBACR,UAAU,EAAE,kBAAkB;aAC/B,CAAC;YACF,UAAU,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,CAAC,CAC5D,CAAC;IACJ,CAAC;CACF,CAAC"}
@@ -0,0 +1,38 @@
1
+ import type { TextLine } from "../../layout/index.js";
2
+ import type { MeasureText, MetaImageProps } from "../../types.js";
3
+ /** How tightly the title's own lines are stacked. */
4
+ export declare const titleLineHeight = 1.08;
5
+ /** And the subtitle's, which is set at a readable size rather than a large one. */
6
+ export declare const subtitleLineHeight = 1.25;
7
+ /** The space the thumbnail's text has, and how to measure text into it. */
8
+ export interface ThumbnailText {
9
+ readonly measure: MeasureText;
10
+ readonly fontFamily: string;
11
+ readonly contentWidth: number;
12
+ readonly contentHeight: number;
13
+ readonly height: number;
14
+ }
15
+ /** The gap between the title and the subtitle under it. */
16
+ export declare function subtitleGap(height: number): number;
17
+ /**
18
+ * The optional second line: a series name, a channel, the episode number.
19
+ *
20
+ * It is fitted first because the title takes whatever height it leaves, which
21
+ * is the order this layout is built in: the title is the picture, and what is
22
+ * under it is a caption on it.
23
+ */
24
+ export declare function thumbnailSubtitle(props: MetaImageProps, text: ThumbnailText): TextLine[];
25
+ /**
26
+ * The title, grown until it fills the room the subtitle left it.
27
+ *
28
+ * This is the one built-in whose text is sized by the box rather than by the
29
+ * image, and the format is the reason. Everything else here is drawn to be read
30
+ * at something near the size it was rendered at, where a heading that swelled
31
+ * to fill its space would stop looking like a heading. A video thumbnail is
32
+ * seen in a list at a fraction of that size, so the only thing on it that
33
+ * matters is that the words are as large as they can be.
34
+ */
35
+ export declare function thumbnailTitle(props: MetaImageProps, text: ThumbnailText, subtitleRoom: number): TextLine[];
36
+ /** The room the subtitle takes, including the gap above it, or none at all. */
37
+ export declare function subtitleRoom(lines: readonly TextLine[], height: number): number;
38
+ //# sourceMappingURL=lines.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lines.d.ts","sourceRoot":"","sources":["../../../src/templates/thumbnail/lines.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEtD,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAElE,qDAAqD;AACrD,eAAO,MAAM,eAAe,OAAO,CAAC;AAEpC,mFAAmF;AACnF,eAAO,MAAM,kBAAkB,OAAO,CAAC;AA6BvC,2EAA2E;AAC3E,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAC9B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,2DAA2D;AAC3D,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAElD;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,cAAc,EACrB,IAAI,EAAE,aAAa,GAClB,QAAQ,EAAE,CASZ;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,cAAc,EACrB,IAAI,EAAE,aAAa,EACnB,YAAY,EAAE,MAAM,GACnB,QAAQ,EAAE,CAUZ;AAED,+EAA+E;AAC/E,wBAAgB,YAAY,CAC1B,KAAK,EAAE,SAAS,QAAQ,EAAE,EAC1B,MAAM,EAAE,MAAM,GACb,MAAM,CAIR"}
@@ -0,0 +1,76 @@
1
+ import { blockLines, fillLines, linesHeight } from "../../layout/index.js";
2
+ /** How tightly the title's own lines are stacked. */
3
+ export const titleLineHeight = 1.08;
4
+ /** And the subtitle's, which is set at a readable size rather than a large one. */
5
+ export const subtitleLineHeight = 1.25;
6
+ const maxSubtitleLines = 2;
7
+ const subtitleFloor = 0.8;
8
+ /**
9
+ * The title's ceiling, as a fraction of the image's height.
10
+ *
11
+ * Nothing longer than a word or two ever reaches it, since the width runs out
12
+ * first: at 16:9 a two-word title settles around 0.45 of the height on its own.
13
+ * What the ceiling is for is the one-word case, where the width would allow
14
+ * something enormous, and half the height is where a single word stops reading
15
+ * as writing and starts reading as a graphic.
16
+ */
17
+ const maxTitleScale = 0.5;
18
+ /**
19
+ * And its floor, below which the title is cut instead.
20
+ *
21
+ * Around 90px at 720 tall. A thumbnail is shown at something like a third of
22
+ * the width it was rendered at, so this is roughly the smallest text a reader
23
+ * scrolling past can still take in, and a title that will not fit at it is one
24
+ * with too much in it for the format.
25
+ */
26
+ const minTitleScale = 0.125;
27
+ /** The subtitle's size, which does not change with how long the title is. */
28
+ const subtitleScale = 0.055;
29
+ /** The gap between the title and the subtitle under it. */
30
+ export function subtitleGap(height) {
31
+ return Math.round(height * 0.035);
32
+ }
33
+ /**
34
+ * The optional second line: a series name, a channel, the episode number.
35
+ *
36
+ * It is fitted first because the title takes whatever height it leaves, which
37
+ * is the order this layout is built in: the title is the picture, and what is
38
+ * under it is a caption on it.
39
+ */
40
+ export function thumbnailSubtitle(props, text) {
41
+ return blockLines(props.subtitle, text.measure, text.fontFamily, {
42
+ maxWidth: text.contentWidth,
43
+ maxLines: maxSubtitleLines,
44
+ fontSize: Math.round(text.height * subtitleScale),
45
+ floor: subtitleFloor,
46
+ fontWeight: 600,
47
+ opacity: 0.85,
48
+ });
49
+ }
50
+ /**
51
+ * The title, grown until it fills the room the subtitle left it.
52
+ *
53
+ * This is the one built-in whose text is sized by the box rather than by the
54
+ * image, and the format is the reason. Everything else here is drawn to be read
55
+ * at something near the size it was rendered at, where a heading that swelled
56
+ * to fill its space would stop looking like a heading. A video thumbnail is
57
+ * seen in a list at a fraction of that size, so the only thing on it that
58
+ * matters is that the words are as large as they can be.
59
+ */
60
+ export function thumbnailTitle(props, text, subtitleRoom) {
61
+ return fillLines(props.title, text.measure, text.fontFamily, {
62
+ maxWidth: text.contentWidth,
63
+ maxHeight: Math.max(1, text.contentHeight - subtitleRoom),
64
+ lineHeight: titleLineHeight,
65
+ maxFontSize: Math.round(text.height * maxTitleScale),
66
+ minFontSize: Math.round(text.height * minTitleScale),
67
+ fontWeight: 800,
68
+ opacity: 1,
69
+ });
70
+ }
71
+ /** The room the subtitle takes, including the gap above it, or none at all. */
72
+ export function subtitleRoom(lines, height) {
73
+ const stacked = linesHeight(lines, subtitleLineHeight);
74
+ return stacked === 0 ? 0 : stacked + subtitleGap(height);
75
+ }
76
+ //# sourceMappingURL=lines.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lines.js","sourceRoot":"","sources":["../../../src/templates/thumbnail/lines.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAG3E,qDAAqD;AACrD,MAAM,CAAC,MAAM,eAAe,GAAG,IAAI,CAAC;AAEpC,mFAAmF;AACnF,MAAM,CAAC,MAAM,kBAAkB,GAAG,IAAI,CAAC;AAEvC,MAAM,gBAAgB,GAAG,CAAC,CAAC;AAC3B,MAAM,aAAa,GAAG,GAAG,CAAC;AAE1B;;;;;;;;GAQG;AACH,MAAM,aAAa,GAAG,GAAG,CAAC;AAE1B;;;;;;;GAOG;AACH,MAAM,aAAa,GAAG,KAAK,CAAC;AAE5B,6EAA6E;AAC7E,MAAM,aAAa,GAAG,KAAK,CAAC;AAW5B,2DAA2D;AAC3D,MAAM,UAAU,WAAW,CAAC,MAAc;IACxC,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC,CAAC;AACpC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAC/B,KAAqB,EACrB,IAAmB;IAEnB,OAAO,UAAU,CAAC,KAAK,CAAC,QAAQ,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,UAAU,EAAE;QAC/D,QAAQ,EAAE,IAAI,CAAC,YAAY;QAC3B,QAAQ,EAAE,gBAAgB;QAC1B,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,aAAa,CAAC;QACjD,KAAK,EAAE,aAAa;QACpB,UAAU,EAAE,GAAG;QACf,OAAO,EAAE,IAAI;KACd,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,cAAc,CAC5B,KAAqB,EACrB,IAAmB,EACnB,YAAoB;IAEpB,OAAO,SAAS,CAAC,KAAK,CAAC,KAAK,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,UAAU,EAAE;QAC3D,QAAQ,EAAE,IAAI,CAAC,YAAY;QAC3B,SAAS,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,aAAa,GAAG,YAAY,CAAC;QACzD,UAAU,EAAE,eAAe;QAC3B,WAAW,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,aAAa,CAAC;QACpD,WAAW,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,aAAa,CAAC;QACpD,UAAU,EAAE,GAAG;QACf,OAAO,EAAE,CAAC;KACX,CAAC,CAAC;AACL,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,YAAY,CAC1B,KAA0B,EAC1B,MAAc;IAEd,MAAM,OAAO,GAAG,WAAW,CAAC,KAAK,EAAE,kBAAkB,CAAC,CAAC;IAEvD,OAAO,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;AAC3D,CAAC"}
@@ -0,0 +1,34 @@
1
+ import type { FittedText, MeasureAt } from "./fit.js";
2
+ /** The box a block of text has to fill, and the sizes it may be drawn at. */
3
+ export interface FillOptions {
4
+ readonly maxWidth: number;
5
+ readonly maxHeight: number;
6
+ /** Each line's advance down the box, as a multiple of its font size. */
7
+ readonly lineHeight: number;
8
+ /** A ceiling on the size, however much room the box turns out to have. */
9
+ readonly maxFontSize: number;
10
+ /** The size below which the text is cut rather than shrunk any further. */
11
+ readonly minFontSize: number;
12
+ }
13
+ /**
14
+ * Wrap text into a box, at the largest size the whole of it fits at.
15
+ *
16
+ * This is {@link fitText} with the question turned round. `fitText` is given a
17
+ * size and shrinks only when the words need more lines than the layout allows,
18
+ * so a short title is drawn at whatever size the template named and no larger.
19
+ * That is right where the text sits in a group with other things, since a
20
+ * heading that grew to fill the space would stop looking like a heading.
21
+ *
22
+ * It is wrong where the text is the picture. A YouTube thumbnail is looked at
23
+ * in a fraction of the space it was rendered at, so its words have to take the
24
+ * room they are given rather than sit in the middle of it, and how much room
25
+ * that is depends on how many words there are: three of them should be drawn
26
+ * much larger than twelve. So the search comes down from the largest size the
27
+ * box could hold until the wrapped block fits both the width and the height.
28
+ *
29
+ * Text that will not fit even at the floor is cut to the lines there is room
30
+ * for, which is what `fitText` does at its own floor and for the same reason:
31
+ * below a certain size the image has stopped saying anything anybody can read.
32
+ */
33
+ export declare function fillText(text: string, measure: MeasureAt, options: FillOptions): FittedText;
34
+ //# sourceMappingURL=fill.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fill.d.ts","sourceRoot":"","sources":["../../src/text/fill.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAKtD,6EAA6E;AAC7E,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,wEAAwE;IACxE,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,0EAA0E;IAC1E,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,2EAA2E;IAC3E,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAkCD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,QAAQ,CACtB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,SAAS,EAClB,OAAO,EAAE,WAAW,GACnB,UAAU,CAiBZ"}
@@ -0,0 +1,57 @@
1
+ import { nextSize } from "./step.js";
2
+ import { largestUnbroken } from "./unbroken.js";
3
+ import { wrapText } from "./wrap.js";
4
+ /**
5
+ * How many whole lines fit in the box at a given size, and never fewer than one.
6
+ *
7
+ * A box too short for a single line gets that line anyway, running over rather
8
+ * than being left empty. That is the rule `distribute` follows for a group that
9
+ * overflows: a template which has asked for the impossible wants to see it.
10
+ */
11
+ function linesInBox(maxHeight, advance) {
12
+ return Math.max(1, Math.floor(maxHeight / advance));
13
+ }
14
+ /**
15
+ * The size the search starts from, which is the largest one worth trying: no
16
+ * taller than a single line of the box, no larger than the caller's ceiling,
17
+ * and small enough that no word has to be broken to fit the width.
18
+ */
19
+ function startingSize(text, measure, options) {
20
+ const ceiling = Math.min(options.maxFontSize, Math.floor(options.maxHeight / options.lineHeight));
21
+ return Math.max(options.minFontSize, largestUnbroken(text, measure, options.maxWidth, ceiling));
22
+ }
23
+ /**
24
+ * Wrap text into a box, at the largest size the whole of it fits at.
25
+ *
26
+ * This is {@link fitText} with the question turned round. `fitText` is given a
27
+ * size and shrinks only when the words need more lines than the layout allows,
28
+ * so a short title is drawn at whatever size the template named and no larger.
29
+ * That is right where the text sits in a group with other things, since a
30
+ * heading that grew to fill the space would stop looking like a heading.
31
+ *
32
+ * It is wrong where the text is the picture. A YouTube thumbnail is looked at
33
+ * in a fraction of the space it was rendered at, so its words have to take the
34
+ * room they are given rather than sit in the middle of it, and how much room
35
+ * that is depends on how many words there are: three of them should be drawn
36
+ * much larger than twelve. So the search comes down from the largest size the
37
+ * box could hold until the wrapped block fits both the width and the height.
38
+ *
39
+ * Text that will not fit even at the floor is cut to the lines there is room
40
+ * for, which is what `fitText` does at its own floor and for the same reason:
41
+ * below a certain size the image has stopped saying anything anybody can read.
42
+ */
43
+ export function fillText(text, measure, options) {
44
+ const { maxWidth, maxHeight, lineHeight, minFontSize } = options;
45
+ let fontSize = startingSize(text, measure, options);
46
+ let lines = wrapText(text, maxWidth, (line) => measure(line, fontSize));
47
+ while (lines.length * fontSize * lineHeight > maxHeight &&
48
+ fontSize > minFontSize) {
49
+ fontSize = nextSize(fontSize, minFontSize);
50
+ lines = wrapText(text, maxWidth, (line) => measure(line, fontSize));
51
+ }
52
+ return {
53
+ lines: lines.slice(0, linesInBox(maxHeight, fontSize * lineHeight)),
54
+ fontSize,
55
+ };
56
+ }
57
+ //# sourceMappingURL=fill.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fill.js","sourceRoot":"","sources":["../../src/text/fill.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAcrC;;;;;;GAMG;AACH,SAAS,UAAU,CAAC,SAAiB,EAAE,OAAe;IACpD,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,OAAO,CAAC,CAAC,CAAC;AACtD,CAAC;AAED;;;;GAIG;AACH,SAAS,YAAY,CACnB,IAAY,EACZ,OAAkB,EAClB,OAAoB;IAEpB,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CACtB,OAAO,CAAC,WAAW,EACnB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CACnD,CAAC;IAEF,OAAO,IAAI,CAAC,GAAG,CACb,OAAO,CAAC,WAAW,EACnB,eAAe,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,CAC1D,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,QAAQ,CACtB,IAAY,EACZ,OAAkB,EAClB,OAAoB;IAEpB,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,UAAU,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC;IACjE,IAAI,QAAQ,GAAG,YAAY,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IACpD,IAAI,KAAK,GAAG,QAAQ,CAAC,IAAI,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC;IAExE,OACE,KAAK,CAAC,MAAM,GAAG,QAAQ,GAAG,UAAU,GAAG,SAAS;QAChD,QAAQ,GAAG,WAAW,EACtB,CAAC;QACD,QAAQ,GAAG,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;QAC3C,KAAK,GAAG,QAAQ,CAAC,IAAI,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC;IACtE,CAAC;IAED,OAAO;QACL,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC,SAAS,EAAE,QAAQ,GAAG,UAAU,CAAC,CAAC;QACnE,QAAQ;KACT,CAAC;AACJ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"fit.d.ts","sourceRoot":"","sources":["../../src/text/fit.ts"],"names":[],"mappings":"AAEA,uEAAuE;AACvE,MAAM,MAAM,SAAS,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,MAAM,CAAC;AAEnE,uEAAuE;AACvE,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,oDAAoD;IACpD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,6EAA6E;IAC7E,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAED,6DAA6D;AAC7D,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAKD;;;;;;;;;;;GAWG;AACH,wBAAgB,OAAO,CACrB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,SAAS,EAClB,OAAO,EAAE,UAAU,GAClB,UAAU,CAiBZ"}
1
+ {"version":3,"file":"fit.d.ts","sourceRoot":"","sources":["../../src/text/fit.ts"],"names":[],"mappings":"AAGA,uEAAuE;AACvE,MAAM,MAAM,SAAS,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,MAAM,CAAC;AAEnE,uEAAuE;AACvE,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,oDAAoD;IACpD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,6EAA6E;IAC7E,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAED,6DAA6D;AAC7D,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,OAAO,CACrB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,SAAS,EAClB,OAAO,EAAE,UAAU,GAClB,UAAU,CAWZ"}
package/dist/text/fit.js CHANGED
@@ -1,6 +1,5 @@
1
+ import { nextSize } from "./step.js";
1
2
  import { wrapText } from "./wrap.js";
2
- /** How much of the size is given up each time the text does not fit. */
3
- const shrinkStep = 0.94;
4
3
  /**
5
4
  * Wrap text into the space it has, shrinking it until it fits.
6
5
  *
@@ -18,10 +17,7 @@ export function fitText(text, measure, options) {
18
17
  let fontSize = options.fontSize;
19
18
  let lines = wrapText(text, maxWidth, (line) => measure(line, fontSize));
20
19
  while (lines.length > maxLines && fontSize > minFontSize) {
21
- // Both terms are here to guarantee progress: the proportional step is what
22
- // makes the search short, and the whole pixel is what stops it stalling
23
- // once the sizes are small enough for rounding to swallow the step.
24
- fontSize = Math.max(minFontSize, Math.min(fontSize - 1, Math.floor(fontSize * shrinkStep)));
20
+ fontSize = nextSize(fontSize, minFontSize);
25
21
  lines = wrapText(text, maxWidth, (line) => measure(line, fontSize));
26
22
  }
27
23
  return { lines: lines.slice(0, maxLines), fontSize };
@@ -1 +1 @@
1
- {"version":3,"file":"fit.js","sourceRoot":"","sources":["../../src/text/fit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAqBrC,wEAAwE;AACxE,MAAM,UAAU,GAAG,IAAI,CAAC;AAExB;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,OAAO,CACrB,IAAY,EACZ,OAAkB,EAClB,OAAmB;IAEnB,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC;IACpD,IAAI,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;IAChC,IAAI,KAAK,GAAG,QAAQ,CAAC,IAAI,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC;IAExE,OAAO,KAAK,CAAC,MAAM,GAAG,QAAQ,IAAI,QAAQ,GAAG,WAAW,EAAE,CAAC;QACzD,2EAA2E;QAC3E,wEAAwE;QACxE,oEAAoE;QACpE,QAAQ,GAAG,IAAI,CAAC,GAAG,CACjB,WAAW,EACX,IAAI,CAAC,GAAG,CAAC,QAAQ,GAAG,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,UAAU,CAAC,CAAC,CAC1D,CAAC;QACF,KAAK,GAAG,QAAQ,CAAC,IAAI,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC;IACtE,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,EAAE,QAAQ,EAAE,CAAC;AACvD,CAAC"}
1
+ {"version":3,"file":"fit.js","sourceRoot":"","sources":["../../src/text/fit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAqBrC;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,OAAO,CACrB,IAAY,EACZ,OAAkB,EAClB,OAAmB;IAEnB,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC;IACpD,IAAI,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;IAChC,IAAI,KAAK,GAAG,QAAQ,CAAC,IAAI,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC;IAExE,OAAO,KAAK,CAAC,MAAM,GAAG,QAAQ,IAAI,QAAQ,GAAG,WAAW,EAAE,CAAC;QACzD,QAAQ,GAAG,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;QAC3C,KAAK,GAAG,QAAQ,CAAC,IAAI,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC;IACtE,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,EAAE,QAAQ,EAAE,CAAC;AACvD,CAAC"}
@@ -4,6 +4,8 @@ export type { TextAttributes } from "./element.js";
4
4
  export { breakWord } from "./break.js";
5
5
  export { clampLine } from "./clamp.js";
6
6
  export { ellipsis } from "./ellipsis.js";
7
+ export { fillText } from "./fill.js";
8
+ export type { FillOptions } from "./fill.js";
7
9
  export { fitText } from "./fit.js";
8
10
  export type { FitOptions, FittedText, MeasureAt } from "./fit.js";
9
11
  export { wrapText } from "./wrap.js";