@kensio/colophon 2.3.0 → 2.5.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.
Files changed (361) hide show
  1. package/README.md +107 -798
  2. package/dist/background/gradient.d.ts +12 -0
  3. package/dist/background/gradient.d.ts.map +1 -0
  4. package/dist/background/gradient.js +21 -0
  5. package/dist/background/gradient.js.map +1 -0
  6. package/dist/background/image.d.ts +14 -0
  7. package/dist/background/image.d.ts.map +1 -0
  8. package/dist/background/image.js +36 -0
  9. package/dist/background/image.js.map +1 -0
  10. package/dist/background/index.d.ts +13 -0
  11. package/dist/background/index.d.ts.map +1 -0
  12. package/dist/background/index.js +27 -0
  13. package/dist/background/index.js.map +1 -0
  14. package/dist/background/mesh.d.ts +12 -0
  15. package/dist/background/mesh.d.ts.map +1 -0
  16. package/dist/background/mesh.js +43 -0
  17. package/dist/background/mesh.js.map +1 -0
  18. package/dist/background.d.ts +7 -2
  19. package/dist/background.d.ts.map +1 -1
  20. package/dist/background.js +44 -1
  21. package/dist/background.js.map +1 -1
  22. package/dist/cli/args.d.ts +1 -1
  23. package/dist/cli/args.d.ts.map +1 -1
  24. package/dist/cli/args.js +1 -1
  25. package/dist/cli/config.d.ts +1 -1
  26. package/dist/cli/config.js +1 -1
  27. package/dist/config/defaults.d.ts +8 -7
  28. package/dist/config/defaults.d.ts.map +1 -1
  29. package/dist/config/defaults.js +8 -8
  30. package/dist/config/defaults.js.map +1 -1
  31. package/dist/config/index.d.ts +1 -1
  32. package/dist/config/index.d.ts.map +1 -1
  33. package/dist/config/index.js +14 -5
  34. package/dist/config/index.js.map +1 -1
  35. package/dist/config/resolve.d.ts +7 -0
  36. package/dist/config/resolve.d.ts.map +1 -1
  37. package/dist/config/resolve.js +16 -0
  38. package/dist/config/resolve.js.map +1 -1
  39. package/dist/config/size.d.ts +7 -1
  40. package/dist/config/size.d.ts.map +1 -1
  41. package/dist/config/size.js +22 -9
  42. package/dist/config/size.js.map +1 -1
  43. package/dist/content/props.d.ts +2 -2
  44. package/dist/content/props.js +2 -2
  45. package/dist/content/slug.d.ts +5 -5
  46. package/dist/content/slug.js +6 -6
  47. package/dist/content/slug.js.map +1 -1
  48. package/dist/content/walk.d.ts +1 -1
  49. package/dist/content/walk.js +1 -1
  50. package/dist/fonts/index.d.ts +3 -2
  51. package/dist/fonts/index.d.ts.map +1 -1
  52. package/dist/fonts/index.js +3 -2
  53. package/dist/fonts/index.js.map +1 -1
  54. package/dist/fonts/resolve.js +1 -1
  55. package/dist/generate/extra.js +4 -4
  56. package/dist/generate/extra.js.map +1 -1
  57. package/dist/generate/options.d.ts +1 -1
  58. package/dist/generate/outputs.d.ts +4 -4
  59. package/dist/generate/outputs.js +4 -4
  60. package/dist/highlight/language.d.ts +2 -3
  61. package/dist/highlight/language.d.ts.map +1 -1
  62. package/dist/highlight/language.js +3 -4
  63. package/dist/highlight/language.js.map +1 -1
  64. package/dist/highlight/normalise.d.ts +2 -2
  65. package/dist/highlight/normalise.js +2 -2
  66. package/dist/image/index.d.ts +18 -0
  67. package/dist/image/index.d.ts.map +1 -0
  68. package/dist/image/index.js +42 -0
  69. package/dist/image/index.js.map +1 -0
  70. package/dist/image/jpeg.d.ts +10 -0
  71. package/dist/image/jpeg.d.ts.map +1 -0
  72. package/dist/image/jpeg.js +57 -0
  73. package/dist/image/jpeg.js.map +1 -0
  74. package/dist/image/load.d.ts +4 -0
  75. package/dist/image/load.d.ts.map +1 -0
  76. package/dist/image/load.js +60 -0
  77. package/dist/image/load.js.map +1 -0
  78. package/dist/image/media.d.ts +10 -0
  79. package/dist/image/media.d.ts.map +1 -0
  80. package/dist/image/media.js +37 -0
  81. package/dist/image/media.js.map +1 -0
  82. package/dist/image/resolve.d.ts +13 -0
  83. package/dist/image/resolve.d.ts.map +1 -0
  84. package/dist/image/resolve.js +38 -0
  85. package/dist/image/resolve.js.map +1 -0
  86. package/dist/image/size.d.ts +22 -0
  87. package/dist/image/size.d.ts.map +1 -0
  88. package/dist/image/size.js +60 -0
  89. package/dist/image/size.js.map +1 -0
  90. package/dist/image/svg.d.ts +12 -0
  91. package/dist/image/svg.d.ts.map +1 -0
  92. package/dist/image/svg.js +61 -0
  93. package/dist/image/svg.js.map +1 -0
  94. package/dist/image/uri.d.ts +9 -0
  95. package/dist/image/uri.d.ts.map +1 -0
  96. package/dist/image/uri.js +22 -0
  97. package/dist/image/uri.js.map +1 -0
  98. package/dist/index.d.ts +8 -3
  99. package/dist/index.d.ts.map +1 -1
  100. package/dist/index.js +7 -2
  101. package/dist/index.js.map +1 -1
  102. package/dist/layout/block.d.ts +37 -0
  103. package/dist/layout/block.d.ts.map +1 -0
  104. package/dist/layout/block.js +26 -0
  105. package/dist/layout/block.js.map +1 -0
  106. package/dist/layout/box.d.ts +20 -0
  107. package/dist/layout/box.d.ts.map +1 -0
  108. package/dist/layout/box.js +61 -0
  109. package/dist/layout/box.js.map +1 -0
  110. package/dist/layout/distribute.d.ts +15 -0
  111. package/dist/layout/distribute.d.ts.map +1 -0
  112. package/dist/layout/distribute.js +30 -0
  113. package/dist/layout/distribute.js.map +1 -0
  114. package/dist/layout/image.d.ts +42 -0
  115. package/dist/layout/image.d.ts.map +1 -0
  116. package/dist/layout/image.js +34 -0
  117. package/dist/layout/image.js.map +1 -0
  118. package/dist/layout/index.d.ts +40 -0
  119. package/dist/layout/index.d.ts.map +1 -0
  120. package/dist/layout/index.js +30 -0
  121. package/dist/layout/index.js.map +1 -0
  122. package/dist/layout/lines.d.ts +45 -0
  123. package/dist/layout/lines.d.ts.map +1 -0
  124. package/dist/layout/lines.js +71 -0
  125. package/dist/layout/lines.js.map +1 -0
  126. package/dist/layout/measure.d.ts +11 -0
  127. package/dist/layout/measure.d.ts.map +1 -0
  128. package/dist/layout/measure.js +11 -0
  129. package/dist/layout/measure.js.map +1 -0
  130. package/dist/layout/panel.d.ts +20 -0
  131. package/dist/layout/panel.d.ts.map +1 -0
  132. package/dist/layout/panel.js +22 -0
  133. package/dist/layout/panel.js.map +1 -0
  134. package/dist/layout/row.d.ts +15 -0
  135. package/dist/layout/row.d.ts.map +1 -0
  136. package/dist/layout/row.js +20 -0
  137. package/dist/layout/row.js.map +1 -0
  138. package/dist/layout/scrim.d.ts +23 -0
  139. package/dist/layout/scrim.d.ts.map +1 -0
  140. package/dist/layout/scrim.js +38 -0
  141. package/dist/layout/scrim.js.map +1 -0
  142. package/dist/layout/stack.d.ts +14 -0
  143. package/dist/layout/stack.d.ts.map +1 -0
  144. package/dist/layout/stack.js +19 -0
  145. package/dist/layout/stack.js.map +1 -0
  146. package/dist/layout/types.d.ts +49 -0
  147. package/dist/layout/types.d.ts.map +1 -0
  148. package/dist/layout/types.js +2 -0
  149. package/dist/layout/types.js.map +1 -0
  150. package/dist/manifest/build.d.ts +1 -1
  151. package/dist/manifest/build.js +1 -1
  152. package/dist/manifest/index.d.ts +1 -1
  153. package/dist/manifest/index.js +1 -1
  154. package/dist/manifest/order.d.ts +1 -1
  155. package/dist/manifest/order.js +1 -1
  156. package/dist/manifest/page.d.ts +2 -2
  157. package/dist/manifest/page.js +3 -3
  158. package/dist/measure/estimate.d.ts +10 -0
  159. package/dist/measure/estimate.d.ts.map +1 -0
  160. package/dist/measure/estimate.js +58 -0
  161. package/dist/measure/estimate.js.map +1 -0
  162. package/dist/measure/faces.d.ts +15 -0
  163. package/dist/measure/faces.d.ts.map +1 -0
  164. package/dist/measure/faces.js +70 -0
  165. package/dist/measure/faces.js.map +1 -0
  166. package/dist/measure/index.d.ts +16 -0
  167. package/dist/measure/index.d.ts.map +1 -0
  168. package/dist/measure/index.js +0 -0
  169. package/dist/measure/index.js.map +1 -0
  170. package/dist/measure/runs.d.ts +17 -0
  171. package/dist/measure/runs.d.ts.map +1 -0
  172. package/dist/measure/runs.js +39 -0
  173. package/dist/measure/runs.js.map +1 -0
  174. package/dist/measure/select.d.ts +13 -0
  175. package/dist/measure/select.d.ts.map +1 -0
  176. package/dist/measure/select.js +47 -0
  177. package/dist/measure/select.js.map +1 -0
  178. package/dist/meta/tags.d.ts +6 -6
  179. package/dist/meta/tags.js +6 -6
  180. package/dist/meta/url.d.ts +4 -4
  181. package/dist/meta/url.js +4 -4
  182. package/dist/placement/check.d.ts +1 -1
  183. package/dist/placement/check.js +1 -1
  184. package/dist/placement/index.js +1 -1
  185. package/dist/placement/relative.d.ts +3 -3
  186. package/dist/placement/relative.js +3 -3
  187. package/dist/pool.d.ts +2 -2
  188. package/dist/pool.js +3 -3
  189. package/dist/pool.js.map +1 -1
  190. package/dist/props.d.ts +7 -0
  191. package/dist/props.d.ts.map +1 -0
  192. package/dist/props.js +17 -0
  193. package/dist/props.js.map +1 -0
  194. package/dist/render/svg.d.ts +4 -2
  195. package/dist/render/svg.d.ts.map +1 -1
  196. package/dist/render/svg.js +28 -6
  197. package/dist/render/svg.js.map +1 -1
  198. package/dist/stamp/config-digest.d.ts.map +1 -1
  199. package/dist/stamp/config-digest.js +21 -1
  200. package/dist/stamp/config-digest.js.map +1 -1
  201. package/dist/stamp/index.js +2 -2
  202. package/dist/stamp/index.js.map +1 -1
  203. package/dist/stamp/read.d.ts +1 -1
  204. package/dist/stamp/read.js +4 -4
  205. package/dist/templates/attribution.d.ts +17 -0
  206. package/dist/templates/attribution.d.ts.map +1 -0
  207. package/dist/templates/attribution.js +39 -0
  208. package/dist/templates/attribution.js.map +1 -0
  209. package/dist/templates/banner/badge-props.d.ts +16 -0
  210. package/dist/templates/banner/badge-props.d.ts.map +1 -0
  211. package/dist/templates/banner/badge-props.js +58 -0
  212. package/dist/templates/banner/badge-props.js.map +1 -0
  213. package/dist/templates/banner/badge.d.ts.map +1 -1
  214. package/dist/templates/banner/badge.js +3 -6
  215. package/dist/templates/banner/badge.js.map +1 -1
  216. package/dist/templates/banner/index.d.ts +3 -0
  217. package/dist/templates/banner/index.d.ts.map +1 -1
  218. package/dist/templates/banner/index.js +41 -37
  219. package/dist/templates/banner/index.js.map +1 -1
  220. package/dist/templates/banner/lines.d.ts +7 -12
  221. package/dist/templates/banner/lines.d.ts.map +1 -1
  222. package/dist/templates/banner/lines.js +23 -34
  223. package/dist/templates/banner/lines.js.map +1 -1
  224. package/dist/templates/banner/version.d.ts +9 -0
  225. package/dist/templates/banner/version.d.ts.map +1 -0
  226. package/dist/templates/banner/version.js +21 -0
  227. package/dist/templates/banner/version.js.map +1 -0
  228. package/dist/templates/card/index.d.ts +4 -1
  229. package/dist/templates/card/index.d.ts.map +1 -1
  230. package/dist/templates/card/index.js +37 -25
  231. package/dist/templates/card/index.js.map +1 -1
  232. package/dist/templates/card/lines.d.ts +17 -13
  233. package/dist/templates/card/lines.d.ts.map +1 -1
  234. package/dist/templates/card/lines.js +24 -20
  235. package/dist/templates/card/lines.js.map +1 -1
  236. package/dist/templates/code/chrome.d.ts +7 -3
  237. package/dist/templates/code/chrome.d.ts.map +1 -1
  238. package/dist/templates/code/chrome.js +12 -11
  239. package/dist/templates/code/chrome.js.map +1 -1
  240. package/dist/templates/code/clip.d.ts +1 -1
  241. package/dist/templates/code/clip.js +1 -1
  242. package/dist/templates/code/fit.d.ts +2 -2
  243. package/dist/templates/code/fit.d.ts.map +1 -1
  244. package/dist/templates/code/fit.js +4 -4
  245. package/dist/templates/code/fit.js.map +1 -1
  246. package/dist/templates/code/index.d.ts.map +1 -1
  247. package/dist/templates/code/index.js +7 -6
  248. package/dist/templates/code/index.js.map +1 -1
  249. package/dist/templates/code/layout.d.ts +1 -1
  250. package/dist/templates/code/layout.d.ts.map +1 -1
  251. package/dist/templates/code/layout.js +6 -6
  252. package/dist/templates/code/layout.js.map +1 -1
  253. package/dist/templates/code/panel.d.ts +13 -0
  254. package/dist/templates/code/panel.d.ts.map +1 -1
  255. package/dist/templates/code/panel.js +34 -2
  256. package/dist/templates/code/panel.js.map +1 -1
  257. package/dist/templates/code/plate.d.ts +3 -1
  258. package/dist/templates/code/plate.d.ts.map +1 -1
  259. package/dist/templates/code/plate.js +11 -9
  260. package/dist/templates/code/plate.js.map +1 -1
  261. package/dist/templates/code/spans.js +1 -1
  262. package/dist/templates/code/spans.js.map +1 -1
  263. package/dist/templates/code/width.d.ts +10 -0
  264. package/dist/templates/code/width.d.ts.map +1 -0
  265. package/dist/templates/code/width.js +26 -0
  266. package/dist/templates/code/width.js.map +1 -0
  267. package/dist/templates/footer.d.ts +8 -0
  268. package/dist/templates/footer.d.ts.map +1 -1
  269. package/dist/templates/footer.js +11 -1
  270. package/dist/templates/footer.js.map +1 -1
  271. package/dist/templates/index.d.ts +1 -1
  272. package/dist/templates/index.d.ts.map +1 -1
  273. package/dist/templates/index.js +1 -1
  274. package/dist/templates/index.js.map +1 -1
  275. package/dist/templates/logo.d.ts +15 -0
  276. package/dist/templates/logo.d.ts.map +1 -0
  277. package/dist/templates/logo.js +30 -0
  278. package/dist/templates/logo.js.map +1 -0
  279. package/dist/templates/measure.d.ts +11 -0
  280. package/dist/templates/measure.d.ts.map +1 -0
  281. package/dist/templates/measure.js +11 -0
  282. package/dist/templates/measure.js.map +1 -0
  283. package/dist/templates/props.d.ts +2 -2
  284. package/dist/templates/props.js +2 -2
  285. package/dist/templates/text.d.ts +37 -0
  286. package/dist/templates/text.d.ts.map +1 -0
  287. package/dist/templates/text.js +26 -0
  288. package/dist/templates/text.js.map +1 -0
  289. package/dist/text/break.d.ts +11 -0
  290. package/dist/text/break.d.ts.map +1 -0
  291. package/dist/text/break.js +30 -0
  292. package/dist/text/break.js.map +1 -0
  293. package/dist/text/fit.d.ts +30 -0
  294. package/dist/text/fit.d.ts.map +1 -0
  295. package/dist/text/fit.js +29 -0
  296. package/dist/text/fit.js.map +1 -0
  297. package/dist/text/index.d.ts +5 -3
  298. package/dist/text/index.d.ts.map +1 -1
  299. package/dist/text/index.js +3 -2
  300. package/dist/text/index.js.map +1 -1
  301. package/dist/text/wrap.d.ts +17 -7
  302. package/dist/text/wrap.d.ts.map +1 -1
  303. package/dist/text/wrap.js +25 -17
  304. package/dist/text/wrap.js.map +1 -1
  305. package/dist/texture/grain.d.ts +17 -0
  306. package/dist/texture/grain.d.ts.map +1 -0
  307. package/dist/texture/grain.js +29 -0
  308. package/dist/texture/grain.js.map +1 -0
  309. package/dist/texture/index.d.ts +11 -0
  310. package/dist/texture/index.d.ts.map +1 -0
  311. package/dist/texture/index.js +20 -0
  312. package/dist/texture/index.js.map +1 -0
  313. package/dist/texture/pattern.d.ts +17 -0
  314. package/dist/texture/pattern.d.ts.map +1 -0
  315. package/dist/texture/pattern.js +45 -0
  316. package/dist/texture/pattern.js.map +1 -0
  317. package/dist/texture/resolve.d.ts +16 -0
  318. package/dist/texture/resolve.d.ts.map +1 -0
  319. package/dist/texture/resolve.js +20 -0
  320. package/dist/texture/resolve.js.map +1 -0
  321. package/dist/theme/index.d.ts +27 -0
  322. package/dist/theme/index.d.ts.map +1 -0
  323. package/dist/theme/index.js +41 -0
  324. package/dist/theme/index.js.map +1 -0
  325. package/dist/theme/presets.d.ts +38 -0
  326. package/dist/theme/presets.d.ts.map +1 -0
  327. package/dist/theme/presets.js +150 -0
  328. package/dist/theme/presets.js.map +1 -0
  329. package/dist/types.d.ts +281 -46
  330. package/dist/types.d.ts.map +1 -1
  331. package/dist/validate/background.d.ts +12 -0
  332. package/dist/validate/background.d.ts.map +1 -0
  333. package/dist/validate/background.js +53 -0
  334. package/dist/validate/background.js.map +1 -0
  335. package/dist/validate/collect.d.ts +9 -0
  336. package/dist/validate/collect.d.ts.map +1 -0
  337. package/dist/validate/collect.js +34 -0
  338. package/dist/validate/collect.js.map +1 -0
  339. package/dist/validate/index.d.ts +1 -1
  340. package/dist/validate/index.d.ts.map +1 -1
  341. package/dist/validate/index.js +3 -20
  342. package/dist/validate/index.js.map +1 -1
  343. package/dist/validate/keys.d.ts +35 -2
  344. package/dist/validate/keys.d.ts.map +1 -1
  345. package/dist/validate/keys.js +92 -3
  346. package/dist/validate/keys.js.map +1 -1
  347. package/dist/validate/overrides.d.ts.map +1 -1
  348. package/dist/validate/overrides.js +5 -1
  349. package/dist/validate/overrides.js.map +1 -1
  350. package/dist/validate/suggest.d.ts.map +1 -1
  351. package/dist/validate/suggest.js +21 -3
  352. package/dist/validate/suggest.js.map +1 -1
  353. package/dist/validate/texture.d.ts +11 -0
  354. package/dist/validate/texture.d.ts.map +1 -0
  355. package/dist/validate/texture.js +34 -0
  356. package/dist/validate/texture.js.map +1 -0
  357. package/dist/validate/values.d.ts +10 -10
  358. package/dist/validate/values.d.ts.map +1 -1
  359. package/dist/validate/values.js +21 -31
  360. package/dist/validate/values.js.map +1 -1
  361. package/package.json +7 -1
@@ -1,6 +1,9 @@
1
- import { layoutStack, textElement } from "../../text/index.js";
2
- import { footerElement, hasFooter } from "../footer.js";
3
- import { optionalString } from "../props.js";
1
+ import { drawLines, inset } from "../../layout/index.js";
2
+ import { optionalString } from "../../props.js";
3
+ import { attribution } from "../attribution.js";
4
+ import { footerBaseline, hasFooter } from "../footer.js";
5
+ import { logoElement, logoRect } from "../logo.js";
6
+ import { badgeFor } from "./badge-props.js";
4
7
  import { renderBadge } from "./badge.js";
5
8
  import { bannerLines } from "./lines.js";
6
9
  /**
@@ -8,59 +11,60 @@ import { bannerLines } from "./lines.js";
8
11
  * version and wrapped subtitle, an optional corner badge, and an optional
9
12
  * footer. This is the configurable descendant of the original `npm_package`
10
13
  * layout.
14
+ *
15
+ * A logo goes in the opposite corner to the badge, which is the corner the
16
+ * left-aligned text leaves free, and the avatar sits with the footer.
11
17
  */
12
18
  export const bannerTemplate = {
13
19
  name: "banner",
14
- render({ props, config, dimensions }) {
20
+ render({ props, config, dimensions, measure, logo, avatar, }) {
15
21
  const { width, height } = dimensions;
16
22
  const { fontFamily } = config;
17
23
  const pad = Math.round(width * 0.075);
18
- const contentWidth = width - pad * 2;
19
- const subtitle = optionalString(props.subtitle);
20
- const hasSubtitle = subtitle !== undefined && subtitle !== "";
21
- const titleFs = Math.round(height * (hasSubtitle ? 0.078 : 0.092));
22
24
  const footerFs = Math.round(height * 0.034);
23
25
  const badgeHeight = Math.round(height * 0.072);
26
+ const mark = logoRect(logo, dimensions, pad, "start");
27
+ const badge = badgeFor(props, config);
28
+ const subtitle = optionalString(props.subtitle);
29
+ const hasSubtitle = subtitle !== undefined && subtitle !== "";
30
+ // The text sits between whatever the marks along the top and the footer
31
+ // along the bottom leave behind.
32
+ const topMark = Math.max(badge === undefined ? 0 : badgeHeight, mark?.height ?? 0);
33
+ const area = inset({ x: 0, y: 0, width, height }, {
34
+ top: pad + (topMark === 0 ? 0 : topMark + Math.round(height * 0.03)),
35
+ right: pad,
36
+ left: pad,
37
+ bottom: pad +
38
+ (hasFooter(config) || avatar !== undefined
39
+ ? footerFs + Math.round(height * 0.02)
40
+ : 0),
41
+ });
24
42
  const lines = bannerLines(props, {
25
43
  height,
26
- contentWidth,
27
- titleFs,
44
+ contentWidth: area.width,
45
+ titleFs: Math.round(height * (hasSubtitle ? 0.078 : 0.092)),
28
46
  versionFs: Math.round(height * 0.04),
29
47
  subFs: Math.round(height * 0.05),
48
+ measure,
49
+ fontFamily,
30
50
  });
31
- const top = pad +
32
- (config.badge === undefined
33
- ? 0
34
- : badgeHeight + Math.round(height * 0.03));
35
- const bottom = height -
36
- pad -
37
- (hasFooter(config) ? footerFs + Math.round(height * 0.02) : 0);
38
- const placed = layoutStack(lines.map((line) => ({
39
- fontSize: line.fontSize,
40
- lineHeight: 1.15,
41
- ...(line.gapBefore !== undefined && { gapBefore: line.gapBefore }),
42
- })), top, bottom);
43
- const body = lines
44
- .map((line, index) => textElement(line.text, {
45
- x: pad,
46
- y: placed[index]?.y ?? top,
51
+ const body = drawLines(lines, area, {
47
52
  fontFamily,
48
- fontSize: line.fontSize,
49
- fontWeight: line.fontWeight,
50
53
  fill: config.colors.foreground,
51
- fillOpacity: line.opacity,
52
- }))
53
- .join("");
54
- const badge = config.badge === undefined
54
+ lineHeight: 1.28,
55
+ });
56
+ const badgeMark = badge === undefined
55
57
  ? ""
56
- : renderBadge(config.badge, fontFamily, config.colors.brand, pad, badgeHeight);
57
- const footer = footerElement(config, {
58
+ : renderBadge(badge, fontFamily, config.colors.brand, pad, badgeHeight);
59
+ const footer = attribution(config, {
58
60
  x: pad,
59
- y: height - pad,
61
+ y: footerBaseline(height, pad, footerFs),
60
62
  fontSize: footerFs,
61
63
  opacity: 0.78,
62
- });
63
- return badge + body + footer;
64
+ left: pad,
65
+ width: width - pad * 2,
66
+ }, avatar, measure);
67
+ return badgeMark + logoElement(logo, mark) + body + footer;
64
68
  },
65
69
  };
66
70
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/templates/banner/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/templates/banner/index.ts"],"names":[],"mappings":"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"}
@@ -1,27 +1,22 @@
1
- import type { MetaImageProps } from "../../types.js";
1
+ import type { MeasureText, MetaImageProps } from "../../types.js";
2
+ import type { TextLine } from "../../layout/index.js";
2
3
  /**
3
- * One line of the banner's text block, with the weight and opacity that say
4
- * which of the title, version and subtitle groups it belongs to.
4
+ * The font sizes the banner's text is drawn at, all keyed to image height,
5
+ * along with the space it has and how to measure text into it.
5
6
  */
6
- export interface BannerLine {
7
- readonly text: string;
8
- readonly fontSize: number;
9
- readonly fontWeight: number;
10
- readonly opacity: number;
11
- readonly gapBefore?: number;
12
- }
13
- /** The font sizes the banner's text is drawn at, all keyed to image height. */
14
7
  export interface BannerSizes {
15
8
  readonly height: number;
16
9
  readonly contentWidth: number;
17
10
  readonly titleFs: number;
18
11
  readonly versionFs: number;
19
12
  readonly subFs: number;
13
+ readonly measure: MeasureText;
14
+ readonly fontFamily: string;
20
15
  }
21
16
  /**
22
17
  * The banner's text block: the wrapped title, an optional version, and the
23
18
  * wrapped subtitle. Extra breathing room goes before the version and subtitle
24
19
  * groups so the three do not read as one squashed block.
25
20
  */
26
- export declare function bannerLines(props: MetaImageProps, sizes: BannerSizes): BannerLine[];
21
+ export declare function bannerLines(props: MetaImageProps, sizes: BannerSizes): TextLine[];
27
22
  //# sourceMappingURL=lines.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"lines.d.ts","sourceRoot":"","sources":["../../../src/templates/banner/lines.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAMrD;;;GAGG;AACH,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,+EAA+E;AAC/E,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CACzB,KAAK,EAAE,cAAc,EACrB,KAAK,EAAE,WAAW,GACjB,UAAU,EAAE,CA+Cd"}
1
+ {"version":3,"file":"lines.d.ts","sourceRoot":"","sources":["../../../src/templates/banner/lines.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAClE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAStD;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAC9B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CACzB,KAAK,EAAE,cAAc,EACrB,KAAK,EAAE,WAAW,GACjB,QAAQ,EAAE,CAuBZ"}
@@ -1,46 +1,35 @@
1
- import { estimateCharsPerLine, wrapText } from "../../text/index.js";
2
- import { optionalString } from "../props.js";
1
+ import { blockLines } from "../../layout/index.js";
2
+ import { versionLines } from "./version.js";
3
3
  const maxTitleLines = 3;
4
4
  const maxSubtitleLines = 4;
5
+ const titleFloor = 0.62;
6
+ const subtitleFloor = 0.8;
5
7
  /**
6
8
  * The banner's text block: the wrapped title, an optional version, and the
7
9
  * wrapped subtitle. Extra breathing room goes before the version and subtitle
8
10
  * groups so the three do not read as one squashed block.
9
11
  */
10
12
  export function bannerLines(props, sizes) {
11
- const { height, contentWidth, titleFs, versionFs, subFs } = sizes;
12
- const title = optionalString(props.title) ?? "";
13
- const subtitle = optionalString(props.subtitle);
14
- const version = optionalString(props.version);
15
- const lines = wrapText(title, estimateCharsPerLine(contentWidth, titleFs, 0.6))
16
- .slice(0, maxTitleLines)
17
- .map((text) => ({
18
- text,
19
- fontSize: titleFs,
20
- fontWeight: 800,
21
- opacity: 0.98,
22
- }));
23
- if (version !== undefined && version !== "") {
24
- lines.push({
25
- text: `v${version}`,
26
- fontSize: versionFs,
27
- fontWeight: 700,
28
- opacity: 0.85,
29
- gapBefore: Math.round(height * 0.03),
30
- });
31
- }
32
- const subtitleLines = subtitle === undefined || subtitle === ""
33
- ? []
34
- : wrapText(subtitle, estimateCharsPerLine(contentWidth, subFs, 0.55)).slice(0, maxSubtitleLines);
35
- for (const [index, text] of subtitleLines.entries()) {
36
- lines.push({
37
- text,
38
- fontSize: subFs,
13
+ const { height, contentWidth, measure, fontFamily } = sizes;
14
+ return [
15
+ ...blockLines(props.title, measure, fontFamily, {
16
+ maxWidth: contentWidth,
17
+ maxLines: maxTitleLines,
18
+ fontSize: sizes.titleFs,
19
+ floor: titleFloor,
20
+ fontWeight: 800,
21
+ opacity: 0.98,
22
+ }),
23
+ ...versionLines(props, sizes),
24
+ ...blockLines(props.subtitle, measure, fontFamily, {
25
+ maxWidth: contentWidth,
26
+ maxLines: maxSubtitleLines,
27
+ fontSize: sizes.subFs,
28
+ floor: subtitleFloor,
39
29
  fontWeight: 500,
40
30
  opacity: 0.86,
41
- ...(index === 0 && { gapBefore: Math.round(height * 0.045) }),
42
- });
43
- }
44
- return lines;
31
+ gapBefore: Math.round(height * 0.045),
32
+ }),
33
+ ];
45
34
  }
46
35
  //# sourceMappingURL=lines.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"lines.js","sourceRoot":"","sources":["../../../src/templates/banner/lines.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAErE,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,aAAa,GAAG,CAAC,CAAC;AACxB,MAAM,gBAAgB,GAAG,CAAC,CAAC;AAuB3B;;;;GAIG;AACH,MAAM,UAAU,WAAW,CACzB,KAAqB,EACrB,KAAkB;IAElB,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,KAAK,CAAC;IAClE,MAAM,KAAK,GAAG,cAAc,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;IAChD,MAAM,QAAQ,GAAG,cAAc,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAChD,MAAM,OAAO,GAAG,cAAc,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAE9C,MAAM,KAAK,GAAiB,QAAQ,CAClC,KAAK,EACL,oBAAoB,CAAC,YAAY,EAAE,OAAO,EAAE,GAAG,CAAC,CACjD;SACE,KAAK,CAAC,CAAC,EAAE,aAAa,CAAC;SACvB,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACd,IAAI;QACJ,QAAQ,EAAE,OAAO;QACjB,UAAU,EAAE,GAAG;QACf,OAAO,EAAE,IAAI;KACd,CAAC,CAAC,CAAC;IAEN,IAAI,OAAO,KAAK,SAAS,IAAI,OAAO,KAAK,EAAE,EAAE,CAAC;QAC5C,KAAK,CAAC,IAAI,CAAC;YACT,IAAI,EAAE,IAAI,OAAO,EAAE;YACnB,QAAQ,EAAE,SAAS;YACnB,UAAU,EAAE,GAAG;YACf,OAAO,EAAE,IAAI;YACb,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC;SACrC,CAAC,CAAC;IACL,CAAC;IAED,MAAM,aAAa,GACjB,QAAQ,KAAK,SAAS,IAAI,QAAQ,KAAK,EAAE;QACvC,CAAC,CAAC,EAAE;QACJ,CAAC,CAAC,QAAQ,CACN,QAAQ,EACR,oBAAoB,CAAC,YAAY,EAAE,KAAK,EAAE,IAAI,CAAC,CAChD,CAAC,KAAK,CAAC,CAAC,EAAE,gBAAgB,CAAC,CAAC;IAEnC,KAAK,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,aAAa,CAAC,OAAO,EAAE,EAAE,CAAC;QACpD,KAAK,CAAC,IAAI,CAAC;YACT,IAAI;YACJ,QAAQ,EAAE,KAAK;YACf,UAAU,EAAE,GAAG;YACf,OAAO,EAAE,IAAI;YACb,GAAG,CAAC,KAAK,KAAK,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC,EAAE,CAAC;SAC9D,CAAC,CAAC;IACL,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC"}
1
+ {"version":3,"file":"lines.js","sourceRoot":"","sources":["../../../src/templates/banner/lines.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,MAAM,aAAa,GAAG,CAAC,CAAC;AACxB,MAAM,gBAAgB,GAAG,CAAC,CAAC;AAC3B,MAAM,UAAU,GAAG,IAAI,CAAC;AACxB,MAAM,aAAa,GAAG,GAAG,CAAC;AAgB1B;;;;GAIG;AACH,MAAM,UAAU,WAAW,CACzB,KAAqB,EACrB,KAAkB;IAElB,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,OAAO,EAAE,UAAU,EAAE,GAAG,KAAK,CAAC;IAE5D,OAAO;QACL,GAAG,UAAU,CAAC,KAAK,CAAC,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE;YAC9C,QAAQ,EAAE,YAAY;YACtB,QAAQ,EAAE,aAAa;YACvB,QAAQ,EAAE,KAAK,CAAC,OAAO;YACvB,KAAK,EAAE,UAAU;YACjB,UAAU,EAAE,GAAG;YACf,OAAO,EAAE,IAAI;SACd,CAAC;QACF,GAAG,YAAY,CAAC,KAAK,EAAE,KAAK,CAAC;QAC7B,GAAG,UAAU,CAAC,KAAK,CAAC,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE;YACjD,QAAQ,EAAE,YAAY;YACtB,QAAQ,EAAE,gBAAgB;YAC1B,QAAQ,EAAE,KAAK,CAAC,KAAK;YACrB,KAAK,EAAE,aAAa;YACpB,UAAU,EAAE,GAAG;YACf,OAAO,EAAE,IAAI;YACb,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC;SACtC,CAAC;KACH,CAAC;AACJ,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { MetaImageProps } from "../../types.js";
2
+ import type { TextLine } from "../../layout/index.js";
3
+ import type { BannerSizes } from "./lines.js";
4
+ /**
5
+ * The version line, or nothing where there is no version. It is never wrapped
6
+ * or shrunk: a version string that needed either would not be one.
7
+ */
8
+ export declare function versionLines(props: MetaImageProps, sizes: BannerSizes): readonly TextLine[];
9
+ //# sourceMappingURL=version.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../../../src/templates/banner/version.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAErD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,cAAc,EACrB,KAAK,EAAE,WAAW,GACjB,SAAS,QAAQ,EAAE,CAgBrB"}
@@ -0,0 +1,21 @@
1
+ import { optionalString } from "../../props.js";
2
+ /**
3
+ * The version line, or nothing where there is no version. It is never wrapped
4
+ * or shrunk: a version string that needed either would not be one.
5
+ */
6
+ export function versionLines(props, sizes) {
7
+ const version = optionalString(props.version);
8
+ if (version === undefined || version === "") {
9
+ return [];
10
+ }
11
+ return [
12
+ {
13
+ text: `v${version}`,
14
+ fontSize: sizes.versionFs,
15
+ fontWeight: 700,
16
+ opacity: 0.85,
17
+ gapBefore: Math.round(sizes.height * 0.03),
18
+ },
19
+ ];
20
+ }
21
+ //# sourceMappingURL=version.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../../../src/templates/banner/version.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAIhD;;;GAGG;AACH,MAAM,UAAU,YAAY,CAC1B,KAAqB,EACrB,KAAkB;IAElB,MAAM,OAAO,GAAG,cAAc,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAE9C,IAAI,OAAO,KAAK,SAAS,IAAI,OAAO,KAAK,EAAE,EAAE,CAAC;QAC5C,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,OAAO;QACL;YACE,IAAI,EAAE,IAAI,OAAO,EAAE;YACnB,QAAQ,EAAE,KAAK,CAAC,SAAS;YACzB,UAAU,EAAE,GAAG;YACf,OAAO,EAAE,IAAI;YACb,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC;SAC3C;KACF,CAAC;AACJ,CAAC"}
@@ -1,7 +1,10 @@
1
1
  import type { Template } from "../../types.js";
2
2
  /**
3
3
  * Minimal "card" template: a centred title with an optional subtitle. No
4
- * badge or version a clean, quieter alternative to `banner`.
4
+ * badge or version, so it is a quieter alternative to `banner`.
5
+ *
6
+ * A logo goes above the title, centred like everything else here, and the
7
+ * avatar sits with the footer along the bottom.
5
8
  */
6
9
  export declare const cardTemplate: Template;
7
10
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/templates/card/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAmB,MAAM,gBAAgB,CAAC;AAIhE;;;GAGG;AACH,eAAO,MAAM,YAAY,EAAE,QAqD1B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/templates/card/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAmB,MAAM,gBAAgB,CAAC;AAMhE;;;;;;GAMG;AACH,eAAO,MAAM,YAAY,EAAE,QA8D1B,CAAC"}
@@ -1,43 +1,55 @@
1
- import { layoutStack, textElement } from "../../text/index.js";
2
- import { footerElement, hasFooter } from "../footer.js";
1
+ import { drawLines, inset } from "../../layout/index.js";
2
+ import { attribution } from "../attribution.js";
3
+ import { footerBaseline, hasFooter } from "../footer.js";
4
+ import { logoElement, logoRect } from "../logo.js";
3
5
  import { cardLines } from "./lines.js";
4
6
  /**
5
7
  * Minimal "card" template: a centred title with an optional subtitle. No
6
- * badge or version a clean, quieter alternative to `banner`.
8
+ * badge or version, so it is a quieter alternative to `banner`.
9
+ *
10
+ * A logo goes above the title, centred like everything else here, and the
11
+ * avatar sits with the footer along the bottom.
7
12
  */
8
13
  export const cardTemplate = {
9
14
  name: "card",
10
- render({ props, config, dimensions }) {
15
+ render({ props, config, dimensions, measure, logo, avatar, }) {
11
16
  const { width, height } = dimensions;
12
17
  const pad = Math.round(width * 0.09);
13
- const centreX = Math.round(width / 2);
14
- const titleFs = Math.round(height * 0.1);
15
18
  const footerFs = Math.round(height * 0.032);
16
- const lines = cardLines(props, width - pad * 2, titleFs, Math.round(height * 0.045));
17
- const bottom = height -
18
- pad -
19
- (hasFooter(config) ? footerFs + Math.round(height * 0.02) : 0);
20
- const placed = layoutStack(lines.map((line) => ({ fontSize: line.fontSize, lineHeight: 1.2 })), pad, bottom);
21
- const body = lines
22
- .map((line, index) => textElement(line.text, {
23
- x: centreX,
24
- y: placed[index]?.y ?? pad,
19
+ const mark = logoRect(logo, dimensions, pad, "middle");
20
+ const area = inset({ x: 0, y: 0, width, height }, {
21
+ top: pad + (mark === undefined ? 0 : mark.height + pad / 2),
22
+ right: pad,
23
+ left: pad,
24
+ bottom: pad +
25
+ (hasFooter(config) || avatar !== undefined
26
+ ? footerFs + Math.round(height * 0.02)
27
+ : 0),
28
+ });
29
+ const lines = cardLines(props, {
30
+ measure,
31
+ fontFamily: config.fontFamily,
32
+ contentWidth: area.width,
33
+ titleFs: Math.round(height * 0.1),
34
+ subFs: Math.round(height * 0.045),
35
+ height,
36
+ });
37
+ const body = drawLines(lines, area, {
25
38
  fontFamily: config.fontFamily,
26
- fontSize: line.fontSize,
27
- fontWeight: line.fontWeight,
28
39
  fill: config.colors.foreground,
29
- fillOpacity: line.opacity,
40
+ lineHeight: 1.28,
30
41
  anchor: "middle",
31
- }))
32
- .join("");
33
- const footer = footerElement(config, {
34
- x: centreX,
35
- y: height - pad,
42
+ });
43
+ const footer = attribution(config, {
44
+ x: Math.round(width / 2),
45
+ y: footerBaseline(height, pad, footerFs),
36
46
  fontSize: footerFs,
37
47
  opacity: 0.75,
38
48
  anchor: "middle",
39
- });
40
- return body + footer;
49
+ left: pad,
50
+ width: width - pad * 2,
51
+ }, avatar, measure);
52
+ return logoElement(logo, mark) + body + footer;
41
53
  },
42
54
  };
43
55
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/templates/card/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAE/D,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC;;;GAGG;AACH,MAAM,CAAC,MAAM,YAAY,GAAa;IACpC,IAAI,EAAE,MAAM;IACZ,MAAM,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAmB;QACnD,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,UAAU,CAAC;QACrC,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC;QACrC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;QAEtC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC;QACzC,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC,CAAC;QAE5C,MAAM,KAAK,GAAG,SAAS,CACrB,KAAK,EACL,KAAK,GAAG,GAAG,GAAG,CAAC,EACf,OAAO,EACP,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC,CAC3B,CAAC;QAEF,MAAM,MAAM,GACV,MAAM;YACN,GAAG;YACH,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAEjE,MAAM,MAAM,GAAG,WAAW,CACxB,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,CAAC,EACnE,GAAG,EACH,MAAM,CACP,CAAC;QAEF,MAAM,IAAI,GAAG,KAAK;aACf,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CACnB,WAAW,CAAC,IAAI,CAAC,IAAI,EAAE;YACrB,CAAC,EAAE,OAAO;YACV,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,GAAG;YAC1B,UAAU,EAAE,MAAM,CAAC,UAAU;YAC7B,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,UAAU;YAC9B,WAAW,EAAE,IAAI,CAAC,OAAO;YACzB,MAAM,EAAE,QAAQ;SACjB,CAAC,CACH;aACA,IAAI,CAAC,EAAE,CAAC,CAAC;QAEZ,MAAM,MAAM,GAAG,aAAa,CAAC,MAAM,EAAE;YACnC,CAAC,EAAE,OAAO;YACV,CAAC,EAAE,MAAM,GAAG,GAAG;YACf,QAAQ,EAAE,QAAQ;YAClB,OAAO,EAAE,IAAI;YACb,MAAM,EAAE,QAAQ;SACjB,CAAC,CAAC;QAEH,OAAO,IAAI,GAAG,MAAM,CAAC;IACvB,CAAC;CACF,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/templates/card/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAEzD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,YAAY,GAAa;IACpC,IAAI,EAAE,MAAM;IACZ,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,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC;QACrC,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC,CAAC;QAC5C,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC;QAEvD,MAAM,IAAI,GAAG,KAAK,CAChB,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,EAC7B;YACE,GAAG,EAAE,GAAG,GAAG,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,GAAG,GAAG,GAAG,CAAC,CAAC;YAC3D,KAAK,EAAE,GAAG;YACV,IAAI,EAAE,GAAG;YACT,MAAM,EACJ,GAAG;gBACH,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,MAAM,KAAK,SAAS;oBACxC,CAAC,CAAC,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC;oBACtC,CAAC,CAAC,CAAC,CAAC;SACT,CACF,CAAC;QAEF,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,EAAE;YAC7B,OAAO;YACP,UAAU,EAAE,MAAM,CAAC,UAAU;YAC7B,YAAY,EAAE,IAAI,CAAC,KAAK;YACxB,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,GAAG,CAAC;YACjC,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC;YACjC,MAAM;SACP,CAAC,CAAC;QAEH,MAAM,IAAI,GAAG,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE;YAClC,UAAU,EAAE,MAAM,CAAC,UAAU;YAC7B,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,UAAU;YAC9B,UAAU,EAAE,IAAI;YAChB,MAAM,EAAE,QAAQ;SACjB,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,WAAW,CACxB,MAAM,EACN;YACE,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC;YACxB,CAAC,EAAE,cAAc,CAAC,MAAM,EAAE,GAAG,EAAE,QAAQ,CAAC;YACxC,QAAQ,EAAE,QAAQ;YAClB,OAAO,EAAE,IAAI;YACb,MAAM,EAAE,QAAQ;YAChB,IAAI,EAAE,GAAG;YACT,KAAK,EAAE,KAAK,GAAG,GAAG,GAAG,CAAC;SACvB,EACD,MAAM,EACN,OAAO,CACR,CAAC;QAEF,OAAO,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,IAAI,GAAG,MAAM,CAAC;IACjD,CAAC;CACF,CAAC"}
@@ -1,17 +1,21 @@
1
- import type { MetaImageProps } from "../../types.js";
2
- /**
3
- * One line of the card's centred text block.
4
- */
5
- export interface CardLine {
6
- readonly text: string;
7
- readonly fontSize: number;
8
- readonly fontWeight: number;
9
- readonly opacity: number;
1
+ import type { MeasureText, MetaImageProps } from "../../types.js";
2
+ import type { TextLine } from "../../layout/index.js";
3
+ /** The space the card's text has, and how to measure text into it. */
4
+ export interface CardText {
5
+ readonly measure: MeasureText;
6
+ readonly fontFamily: string;
7
+ readonly contentWidth: number;
8
+ readonly titleFs: number;
9
+ readonly subFs: number;
10
+ readonly height: number;
10
11
  }
11
12
  /**
12
- * The card's text block: the wrapped title, then the wrapped subtitle. No
13
- * gaps between the groups — the card is the quieter layout, and the change of
14
- * size and weight is enough to separate them.
13
+ * The card's text block: the wrapped title, then the wrapped subtitle.
14
+ *
15
+ * The gap before the subtitle is smaller than the banner's, because the card
16
+ * has only the two groups and they belong together. It is not nothing, though:
17
+ * a title that wraps ends on a line the subtitle would otherwise sit straight
18
+ * underneath, and the change of size and weight alone does not separate them.
15
19
  */
16
- export declare function cardLines(props: MetaImageProps, contentWidth: number, titleFs: number, subFs: number): CardLine[];
20
+ export declare function cardLines(props: MetaImageProps, text: CardText): TextLine[];
17
21
  //# sourceMappingURL=lines.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"lines.d.ts","sourceRoot":"","sources":["../../../src/templates/card/lines.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAMrD;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CACvB,KAAK,EAAE,cAAc,EACrB,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,GACZ,QAAQ,EAAE,CA+BZ"}
1
+ {"version":3,"file":"lines.d.ts","sourceRoot":"","sources":["../../../src/templates/card/lines.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAClE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAQtD,sEAAsE;AACtE,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAC9B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,QAAQ,GAAG,QAAQ,EAAE,CAsB3E"}
@@ -1,32 +1,36 @@
1
- import { estimateCharsPerLine, wrapText } from "../../text/index.js";
2
- import { optionalString } from "../props.js";
1
+ import { blockLines } from "../../layout/index.js";
3
2
  const maxTitleLines = 3;
4
3
  const maxSubtitleLines = 3;
4
+ const titleFloor = 0.62;
5
+ const subtitleFloor = 0.8;
5
6
  /**
6
- * The card's text block: the wrapped title, then the wrapped subtitle. No
7
- * gaps between the groups — the card is the quieter layout, and the change of
8
- * size and weight is enough to separate them.
7
+ * The card's text block: the wrapped title, then the wrapped subtitle.
8
+ *
9
+ * The gap before the subtitle is smaller than the banner's, because the card
10
+ * has only the two groups and they belong together. It is not nothing, though:
11
+ * a title that wraps ends on a line the subtitle would otherwise sit straight
12
+ * underneath, and the change of size and weight alone does not separate them.
9
13
  */
10
- export function cardLines(props, contentWidth, titleFs, subFs) {
11
- const title = optionalString(props.title) ?? "";
12
- const subtitle = optionalString(props.subtitle);
13
- const titleLines = wrapText(title, estimateCharsPerLine(contentWidth, titleFs, 0.58)).slice(0, maxTitleLines);
14
- const subtitleLines = subtitle === undefined || subtitle === ""
15
- ? []
16
- : wrapText(subtitle, estimateCharsPerLine(contentWidth, subFs, 0.52)).slice(0, maxSubtitleLines);
14
+ export function cardLines(props, text) {
15
+ const { measure, fontFamily, contentWidth } = text;
17
16
  return [
18
- ...titleLines.map((text) => ({
19
- text,
20
- fontSize: titleFs,
17
+ ...blockLines(props.title, measure, fontFamily, {
18
+ maxWidth: contentWidth,
19
+ maxLines: maxTitleLines,
20
+ fontSize: text.titleFs,
21
+ floor: titleFloor,
21
22
  fontWeight: 800,
22
23
  opacity: 1,
23
- })),
24
- ...subtitleLines.map((text) => ({
25
- text,
26
- fontSize: subFs,
24
+ }),
25
+ ...blockLines(props.subtitle, measure, fontFamily, {
26
+ maxWidth: contentWidth,
27
+ maxLines: maxSubtitleLines,
28
+ fontSize: text.subFs,
29
+ floor: subtitleFloor,
27
30
  fontWeight: 500,
28
31
  opacity: 0.85,
29
- })),
32
+ gapBefore: Math.round(text.height * 0.025),
33
+ }),
30
34
  ];
31
35
  }
32
36
  //# sourceMappingURL=lines.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"lines.js","sourceRoot":"","sources":["../../../src/templates/card/lines.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAErE,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,aAAa,GAAG,CAAC,CAAC;AACxB,MAAM,gBAAgB,GAAG,CAAC,CAAC;AAY3B;;;;GAIG;AACH,MAAM,UAAU,SAAS,CACvB,KAAqB,EACrB,YAAoB,EACpB,OAAe,EACf,KAAa;IAEb,MAAM,KAAK,GAAG,cAAc,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;IAChD,MAAM,QAAQ,GAAG,cAAc,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAEhD,MAAM,UAAU,GAAG,QAAQ,CACzB,KAAK,EACL,oBAAoB,CAAC,YAAY,EAAE,OAAO,EAAE,IAAI,CAAC,CAClD,CAAC,KAAK,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC;IAE1B,MAAM,aAAa,GACjB,QAAQ,KAAK,SAAS,IAAI,QAAQ,KAAK,EAAE;QACvC,CAAC,CAAC,EAAE;QACJ,CAAC,CAAC,QAAQ,CACN,QAAQ,EACR,oBAAoB,CAAC,YAAY,EAAE,KAAK,EAAE,IAAI,CAAC,CAChD,CAAC,KAAK,CAAC,CAAC,EAAE,gBAAgB,CAAC,CAAC;IAEnC,OAAO;QACL,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YAC3B,IAAI;YACJ,QAAQ,EAAE,OAAO;YACjB,UAAU,EAAE,GAAG;YACf,OAAO,EAAE,CAAC;SACX,CAAC,CAAC;QACH,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YAC9B,IAAI;YACJ,QAAQ,EAAE,KAAK;YACf,UAAU,EAAE,GAAG;YACf,OAAO,EAAE,IAAI;SACd,CAAC,CAAC;KACJ,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"lines.js","sourceRoot":"","sources":["../../../src/templates/card/lines.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAEnD,MAAM,aAAa,GAAG,CAAC,CAAC;AACxB,MAAM,gBAAgB,GAAG,CAAC,CAAC;AAC3B,MAAM,UAAU,GAAG,IAAI,CAAC;AACxB,MAAM,aAAa,GAAG,GAAG,CAAC;AAY1B;;;;;;;GAOG;AACH,MAAM,UAAU,SAAS,CAAC,KAAqB,EAAE,IAAc;IAC7D,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,GAAG,IAAI,CAAC;IAEnD,OAAO;QACL,GAAG,UAAU,CAAC,KAAK,CAAC,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE;YAC9C,QAAQ,EAAE,YAAY;YACtB,QAAQ,EAAE,aAAa;YACvB,QAAQ,EAAE,IAAI,CAAC,OAAO;YACtB,KAAK,EAAE,UAAU;YACjB,UAAU,EAAE,GAAG;YACf,OAAO,EAAE,CAAC;SACX,CAAC;QACF,GAAG,UAAU,CAAC,KAAK,CAAC,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE;YACjD,QAAQ,EAAE,YAAY;YACtB,QAAQ,EAAE,gBAAgB;YAC1B,QAAQ,EAAE,IAAI,CAAC,KAAK;YACpB,KAAK,EAAE,aAAa;YACpB,UAAU,EAAE,GAAG;YACf,OAAO,EAAE,IAAI;YACb,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;SAC3C,CAAC;KACH,CAAC;AACJ,CAAC"}
@@ -1,9 +1,13 @@
1
+ import type { Rect } from "../../layout/index.js";
1
2
  import type { Dimensions, ResolvedConfig } from "../../types.js";
2
- import type { Panel } from "./panel.js";
3
3
  /**
4
- * The optional title, centred just above the panel.
4
+ * The optional title, centred in the band reserved above the panel.
5
+ *
6
+ * It is drawn as a single line at the size the band was measured with, so a
7
+ * title too long for the image runs over rather than wrapping into room that
8
+ * was never set aside for it.
5
9
  */
6
- export declare function codeHeading(title: string | undefined, panel: Panel, fontSize: number, imageWidth: number, config: ResolvedConfig): string;
10
+ export declare function codeHeading(title: string | undefined, band: Rect, fontSize: number, config: ResolvedConfig): string;
7
11
  /** The configured footer, centred along the bottom of the image. */
8
12
  export declare function codeFooter(dimensions: Dimensions, fontSize: number, config: ResolvedConfig): string;
9
13
  //# sourceMappingURL=chrome.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"chrome.d.ts","sourceRoot":"","sources":["../../../src/templates/code/chrome.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAEjE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAExC;;GAEG;AACH,wBAAgB,WAAW,CACzB,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,cAAc,GACrB,MAAM,CAeR;AAED,oEAAoE;AACpE,wBAAgB,UAAU,CACxB,UAAU,EAAE,UAAU,EACtB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,cAAc,GACrB,MAAM,CAUR"}
1
+ {"version":3,"file":"chrome.d.ts","sourceRoot":"","sources":["../../../src/templates/code/chrome.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAIjE;;;;;;GAMG;AACH,wBAAgB,WAAW,CACzB,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,IAAI,EAAE,IAAI,EACV,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,cAAc,GACrB,MAAM,CAeR;AAED,oEAAoE;AACpE,wBAAgB,UAAU,CACxB,UAAU,EAAE,UAAU,EACtB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,cAAc,GACrB,MAAM,CAUR"}
@@ -1,20 +1,21 @@
1
- import { textElement } from "../../text/index.js";
2
- import { footerElement } from "../footer.js";
1
+ import { drawLines } from "../../layout/index.js";
2
+ import { footerBaseline, footerElement } from "../footer.js";
3
+ import { imageMargin } from "./panel.js";
3
4
  /**
4
- * The optional title, centred just above the panel.
5
+ * The optional title, centred in the band reserved above the panel.
6
+ *
7
+ * It is drawn as a single line at the size the band was measured with, so a
8
+ * title too long for the image runs over rather than wrapping into room that
9
+ * was never set aside for it.
5
10
  */
6
- export function codeHeading(title, panel, fontSize, imageWidth, config) {
11
+ export function codeHeading(title, band, fontSize, config) {
7
12
  if (title === undefined || title === "") {
8
13
  return "";
9
14
  }
10
- return textElement(title, {
11
- x: Math.round(imageWidth / 2),
12
- y: panel.y - Math.round(fontSize * 0.42),
15
+ return drawLines([{ text: title, fontSize, fontWeight: 700, opacity: 0.95 }], band, {
13
16
  fontFamily: config.fontFamily,
14
- fontSize,
15
- fontWeight: 700,
16
17
  fill: config.colors.foreground,
17
- fillOpacity: 0.95,
18
+ lineHeight: 1,
18
19
  anchor: "middle",
19
20
  });
20
21
  }
@@ -23,7 +24,7 @@ export function codeFooter(dimensions, fontSize, config) {
23
24
  const { width, height } = dimensions;
24
25
  return footerElement(config, {
25
26
  x: Math.round(width / 2),
26
- y: height - Math.round(Math.min(width, height) * 0.05),
27
+ y: footerBaseline(height, imageMargin(dimensions), fontSize),
27
28
  fontSize,
28
29
  opacity: 0.78,
29
30
  anchor: "middle",
@@ -1 +1 @@
1
- {"version":3,"file":"chrome.js","sourceRoot":"","sources":["../../../src/templates/code/chrome.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAElD,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAG7C;;GAEG;AACH,MAAM,UAAU,WAAW,CACzB,KAAyB,EACzB,KAAY,EACZ,QAAgB,EAChB,UAAkB,EAClB,MAAsB;IAEtB,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,EAAE,EAAE,CAAC;QACxC,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,OAAO,WAAW,CAAC,KAAK,EAAE;QACxB,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,UAAU,GAAG,CAAC,CAAC;QAC7B,CAAC,EAAE,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC;QACxC,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,QAAQ;QACR,UAAU,EAAE,GAAG;QACf,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,UAAU;QAC9B,WAAW,EAAE,IAAI;QACjB,MAAM,EAAE,QAAQ;KACjB,CAAC,CAAC;AACL,CAAC;AAED,oEAAoE;AACpE,MAAM,UAAU,UAAU,CACxB,UAAsB,EACtB,QAAgB,EAChB,MAAsB;IAEtB,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,UAAU,CAAC;IAErC,OAAO,aAAa,CAAC,MAAM,EAAE;QAC3B,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC;QACxB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,GAAG,IAAI,CAAC;QACtD,QAAQ;QACR,OAAO,EAAE,IAAI;QACb,MAAM,EAAE,QAAQ;KACjB,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"chrome.js","sourceRoot":"","sources":["../../../src/templates/code/chrome.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAGlD,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7D,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzC;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CACzB,KAAyB,EACzB,IAAU,EACV,QAAgB,EAChB,MAAsB;IAEtB,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,EAAE,EAAE,CAAC;QACxC,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,OAAO,SAAS,CACd,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,EAC3D,IAAI,EACJ;QACE,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,UAAU;QAC9B,UAAU,EAAE,CAAC;QACb,MAAM,EAAE,QAAQ;KACjB,CACF,CAAC;AACJ,CAAC;AAED,oEAAoE;AACpE,MAAM,UAAU,UAAU,CACxB,UAAsB,EACtB,QAAgB,EAChB,MAAsB;IAEtB,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,UAAU,CAAC;IAErC,OAAO,aAAa,CAAC,MAAM,EAAE;QAC3B,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC;QACxB,CAAC,EAAE,cAAc,CAAC,MAAM,EAAE,WAAW,CAAC,UAAU,CAAC,EAAE,QAAQ,CAAC;QAC5D,QAAQ;QACR,OAAO,EAAE,IAAI;QACb,MAAM,EAAE,QAAQ;KACjB,CAAC,CAAC;AACL,CAAC"}
@@ -2,7 +2,7 @@ import type { CodeToken } from "../../highlight/index.js";
2
2
  /**
3
3
  * Clip a line to the columns that fit, ending it with an ellipsis. The font
4
4
  * size is floored for legibility, so a wide enough snippet can still overrun
5
- * the panel clipping keeps it inside instead of bleeding off the image.
5
+ * the panel, and clipping keeps it inside instead of bleeding off the image.
6
6
  *
7
7
  * Returns the line unchanged when it already fits, so the caller can count the
8
8
  * clipped lines by identity.