@kensio/colophon 2.2.0 → 2.3.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 (350) hide show
  1. package/README.md +560 -24
  2. package/dist/cli/args.d.ts +14 -0
  3. package/dist/cli/args.d.ts.map +1 -0
  4. package/dist/cli/args.js +67 -0
  5. package/dist/cli/args.js.map +1 -0
  6. package/dist/cli/config.d.ts +12 -0
  7. package/dist/cli/config.d.ts.map +1 -0
  8. package/dist/cli/config.js +43 -0
  9. package/dist/cli/config.js.map +1 -0
  10. package/dist/cli/index.d.ts +3 -0
  11. package/dist/cli/index.d.ts.map +1 -0
  12. package/dist/cli/index.js +35 -0
  13. package/dist/cli/index.js.map +1 -0
  14. package/dist/cli.js +34 -6
  15. package/dist/cli.js.map +1 -1
  16. package/dist/config/defaults.d.ts +64 -0
  17. package/dist/config/defaults.d.ts.map +1 -0
  18. package/dist/config/defaults.js +64 -0
  19. package/dist/config/defaults.js.map +1 -0
  20. package/dist/config/index.d.ts +22 -0
  21. package/dist/config/index.d.ts.map +1 -0
  22. package/dist/config/index.js +52 -0
  23. package/dist/config/index.js.map +1 -0
  24. package/dist/config/resolve.d.ts +24 -0
  25. package/dist/config/resolve.d.ts.map +1 -0
  26. package/dist/config/resolve.js +66 -0
  27. package/dist/config/resolve.js.map +1 -0
  28. package/dist/config/size.d.ts +20 -0
  29. package/dist/config/size.d.ts.map +1 -0
  30. package/dist/config/size.js +46 -0
  31. package/dist/config/size.js.map +1 -0
  32. package/dist/config.d.ts +27 -1
  33. package/dist/config.d.ts.map +1 -1
  34. package/dist/config.js +78 -2
  35. package/dist/config.js.map +1 -1
  36. package/dist/content/index.d.ts +5 -51
  37. package/dist/content/index.d.ts.map +1 -1
  38. package/dist/content/index.js +3 -115
  39. package/dist/content/index.js.map +1 -1
  40. package/dist/content/props.d.ts +15 -0
  41. package/dist/content/props.d.ts.map +1 -0
  42. package/dist/content/props.js +71 -0
  43. package/dist/content/props.js.map +1 -0
  44. package/dist/content/slug.d.ts +23 -0
  45. package/dist/content/slug.d.ts.map +1 -0
  46. package/dist/content/slug.js +52 -0
  47. package/dist/content/slug.js.map +1 -0
  48. package/dist/content/walk.d.ts +17 -0
  49. package/dist/content/walk.d.ts.map +1 -0
  50. package/dist/content/walk.js +57 -0
  51. package/dist/content/walk.js.map +1 -0
  52. package/dist/fonts/index.d.ts +10 -0
  53. package/dist/fonts/index.d.ts.map +1 -0
  54. package/dist/fonts/index.js +11 -0
  55. package/dist/fonts/index.js.map +1 -0
  56. package/dist/fonts/materialise.d.ts +7 -0
  57. package/dist/fonts/materialise.d.ts.map +1 -0
  58. package/dist/fonts/materialise.js +47 -0
  59. package/dist/fonts/materialise.js.map +1 -0
  60. package/dist/fonts/resolve.d.ts +7 -0
  61. package/dist/fonts/resolve.d.ts.map +1 -0
  62. package/dist/fonts/resolve.js +50 -0
  63. package/dist/fonts/resolve.js.map +1 -0
  64. package/dist/fonts.d.ts +18 -0
  65. package/dist/fonts.d.ts.map +1 -0
  66. package/dist/fonts.js +102 -0
  67. package/dist/fonts.js.map +1 -0
  68. package/dist/generate/extra.d.ts +16 -0
  69. package/dist/generate/extra.d.ts.map +1 -0
  70. package/dist/generate/extra.js +60 -0
  71. package/dist/generate/extra.js.map +1 -0
  72. package/dist/generate/index.d.ts +19 -0
  73. package/dist/generate/index.d.ts.map +1 -0
  74. package/dist/generate/index.js +46 -0
  75. package/dist/generate/index.js.map +1 -0
  76. package/dist/generate/job.d.ts +35 -0
  77. package/dist/generate/job.d.ts.map +1 -0
  78. package/dist/generate/job.js +2 -0
  79. package/dist/generate/job.js.map +1 -0
  80. package/dist/generate/options.d.ts +56 -0
  81. package/dist/generate/options.d.ts.map +1 -0
  82. package/dist/generate/options.js +17 -0
  83. package/dist/generate/options.js.map +1 -0
  84. package/dist/generate/output-path.d.ts +12 -0
  85. package/dist/generate/output-path.d.ts.map +1 -0
  86. package/dist/generate/output-path.js +18 -0
  87. package/dist/generate/output-path.js.map +1 -0
  88. package/dist/generate/outputs.d.ts +28 -0
  89. package/dist/generate/outputs.d.ts.map +1 -0
  90. package/dist/generate/outputs.js +71 -0
  91. package/dist/generate/outputs.js.map +1 -0
  92. package/dist/generate/plan.d.ts +21 -0
  93. package/dist/generate/plan.d.ts.map +1 -0
  94. package/dist/generate/plan.js +72 -0
  95. package/dist/generate/plan.js.map +1 -0
  96. package/dist/generate/render-image.d.ts +11 -0
  97. package/dist/generate/render-image.d.ts.map +1 -0
  98. package/dist/generate/render-image.js +27 -0
  99. package/dist/generate/render-image.js.map +1 -0
  100. package/dist/generate.d.ts +27 -6
  101. package/dist/generate.d.ts.map +1 -1
  102. package/dist/generate.js +69 -15
  103. package/dist/generate.js.map +1 -1
  104. package/dist/highlight/color.d.ts +9 -0
  105. package/dist/highlight/color.d.ts.map +1 -0
  106. package/dist/highlight/color.js +15 -0
  107. package/dist/highlight/color.js.map +1 -0
  108. package/dist/highlight/grid.d.ts +14 -0
  109. package/dist/highlight/grid.d.ts.map +1 -0
  110. package/dist/highlight/grid.js +36 -0
  111. package/dist/highlight/grid.js.map +1 -0
  112. package/dist/highlight/index.d.ts +12 -0
  113. package/dist/highlight/index.d.ts.map +1 -0
  114. package/dist/highlight/index.js +31 -0
  115. package/dist/highlight/index.js.map +1 -0
  116. package/dist/highlight/language.d.ts +14 -0
  117. package/dist/highlight/language.d.ts.map +1 -0
  118. package/dist/highlight/language.js +42 -0
  119. package/dist/highlight/language.js.map +1 -0
  120. package/dist/highlight/normalise.d.ts +17 -0
  121. package/dist/highlight/normalise.d.ts.map +1 -0
  122. package/dist/highlight/normalise.js +37 -0
  123. package/dist/highlight/normalise.js.map +1 -0
  124. package/dist/highlight/types.d.ts +40 -0
  125. package/dist/highlight/types.d.ts.map +1 -0
  126. package/dist/highlight/types.js +2 -0
  127. package/dist/highlight/types.js.map +1 -0
  128. package/dist/index.d.ts +15 -9
  129. package/dist/index.d.ts.map +1 -1
  130. package/dist/index.js +9 -5
  131. package/dist/index.js.map +1 -1
  132. package/dist/manifest/build.d.ts +14 -0
  133. package/dist/manifest/build.d.ts.map +1 -0
  134. package/dist/manifest/build.js +43 -0
  135. package/dist/manifest/build.js.map +1 -0
  136. package/dist/manifest/index.d.ts +27 -0
  137. package/dist/manifest/index.d.ts.map +1 -0
  138. package/dist/manifest/index.js +31 -0
  139. package/dist/manifest/index.js.map +1 -0
  140. package/dist/manifest/order.d.ts +12 -0
  141. package/dist/manifest/order.d.ts.map +1 -0
  142. package/dist/manifest/order.js +17 -0
  143. package/dist/manifest/order.js.map +1 -0
  144. package/dist/manifest/page.d.ts +24 -0
  145. package/dist/manifest/page.d.ts.map +1 -0
  146. package/dist/manifest/page.js +55 -0
  147. package/dist/manifest/page.js.map +1 -0
  148. package/dist/meta/html.d.ts +14 -0
  149. package/dist/meta/html.d.ts.map +1 -0
  150. package/dist/meta/html.js +24 -0
  151. package/dist/meta/html.js.map +1 -0
  152. package/dist/meta/index.d.ts +11 -0
  153. package/dist/meta/index.d.ts.map +1 -0
  154. package/dist/meta/index.js +11 -0
  155. package/dist/meta/index.js.map +1 -0
  156. package/dist/meta/tags.d.ts +21 -0
  157. package/dist/meta/tags.d.ts.map +1 -0
  158. package/dist/meta/tags.js +72 -0
  159. package/dist/meta/tags.js.map +1 -0
  160. package/dist/meta/url.d.ts +15 -0
  161. package/dist/meta/url.d.ts.map +1 -0
  162. package/dist/meta/url.js +34 -0
  163. package/dist/meta/url.js.map +1 -0
  164. package/dist/placement/check.d.ts +16 -0
  165. package/dist/placement/check.d.ts.map +1 -0
  166. package/dist/placement/check.js +40 -0
  167. package/dist/placement/check.js.map +1 -0
  168. package/dist/placement/index.d.ts +29 -0
  169. package/dist/placement/index.d.ts.map +1 -0
  170. package/dist/placement/index.js +61 -0
  171. package/dist/placement/index.js.map +1 -0
  172. package/dist/placement/relative.d.ts +31 -0
  173. package/dist/placement/relative.d.ts.map +1 -0
  174. package/dist/placement/relative.js +53 -0
  175. package/dist/placement/relative.js.map +1 -0
  176. package/dist/pool.d.ts +18 -0
  177. package/dist/pool.d.ts.map +1 -0
  178. package/dist/pool.js +56 -0
  179. package/dist/pool.js.map +1 -0
  180. package/dist/render/index.d.ts +10 -0
  181. package/dist/render/index.d.ts.map +1 -0
  182. package/dist/render/index.js +27 -0
  183. package/dist/render/index.js.map +1 -0
  184. package/dist/render/png.d.ts +10 -0
  185. package/dist/render/png.d.ts.map +1 -0
  186. package/dist/render/png.js +30 -0
  187. package/dist/render/png.js.map +1 -0
  188. package/dist/render/svg.d.ts +10 -0
  189. package/dist/render/svg.d.ts.map +1 -0
  190. package/dist/render/svg.js +20 -0
  191. package/dist/render/svg.js.map +1 -0
  192. package/dist/render/template.d.ts +9 -0
  193. package/dist/render/template.d.ts.map +1 -0
  194. package/dist/render/template.js +17 -0
  195. package/dist/render/template.js.map +1 -0
  196. package/dist/render.d.ts +6 -2
  197. package/dist/render.d.ts.map +1 -1
  198. package/dist/render.js +31 -10
  199. package/dist/render.js.map +1 -1
  200. package/dist/stamp/chunk.d.ts +16 -0
  201. package/dist/stamp/chunk.d.ts.map +1 -0
  202. package/dist/stamp/chunk.js +46 -0
  203. package/dist/stamp/chunk.js.map +1 -0
  204. package/dist/stamp/config-digest.d.ts +11 -0
  205. package/dist/stamp/config-digest.d.ts.map +1 -0
  206. package/dist/stamp/config-digest.js +43 -0
  207. package/dist/stamp/config-digest.js.map +1 -0
  208. package/dist/stamp/digest.d.ts +8 -0
  209. package/dist/stamp/digest.d.ts.map +1 -0
  210. package/dist/stamp/digest.js +20 -0
  211. package/dist/stamp/digest.js.map +1 -0
  212. package/dist/stamp/index.d.ts +20 -0
  213. package/dist/stamp/index.d.ts.map +1 -0
  214. package/dist/stamp/index.js +40 -0
  215. package/dist/stamp/index.js.map +1 -0
  216. package/dist/stamp/read.d.ts +7 -0
  217. package/dist/stamp/read.d.ts.map +1 -0
  218. package/dist/stamp/read.js +62 -0
  219. package/dist/stamp/read.js.map +1 -0
  220. package/dist/stamp.d.ts +29 -0
  221. package/dist/stamp.d.ts.map +1 -0
  222. package/dist/stamp.js +198 -0
  223. package/dist/stamp.js.map +1 -0
  224. package/dist/templates/banner/badge.d.ts +7 -0
  225. package/dist/templates/banner/badge.d.ts.map +1 -0
  226. package/dist/templates/banner/badge.js +24 -0
  227. package/dist/templates/banner/badge.js.map +1 -0
  228. package/dist/templates/banner/index.d.ts +9 -0
  229. package/dist/templates/banner/index.d.ts.map +1 -0
  230. package/dist/templates/banner/index.js +66 -0
  231. package/dist/templates/banner/index.js.map +1 -0
  232. package/dist/templates/banner/lines.d.ts +27 -0
  233. package/dist/templates/banner/lines.d.ts.map +1 -0
  234. package/dist/templates/banner/lines.js +46 -0
  235. package/dist/templates/banner/lines.js.map +1 -0
  236. package/dist/templates/card/index.d.ts +7 -0
  237. package/dist/templates/card/index.d.ts.map +1 -0
  238. package/dist/templates/card/index.js +43 -0
  239. package/dist/templates/card/index.js.map +1 -0
  240. package/dist/templates/card/lines.d.ts +17 -0
  241. package/dist/templates/card/lines.d.ts.map +1 -0
  242. package/dist/templates/card/lines.js +32 -0
  243. package/dist/templates/card/lines.js.map +1 -0
  244. package/dist/templates/code/chrome.d.ts +9 -0
  245. package/dist/templates/code/chrome.d.ts.map +1 -0
  246. package/dist/templates/code/chrome.js +32 -0
  247. package/dist/templates/code/chrome.js.map +1 -0
  248. package/dist/templates/code/clip.d.ts +18 -0
  249. package/dist/templates/code/clip.d.ts.map +1 -0
  250. package/dist/templates/code/clip.js +44 -0
  251. package/dist/templates/code/clip.js.map +1 -0
  252. package/dist/templates/code/ellipsis.d.ts +3 -0
  253. package/dist/templates/code/ellipsis.d.ts.map +1 -0
  254. package/dist/templates/code/ellipsis.js +3 -0
  255. package/dist/templates/code/ellipsis.js.map +1 -0
  256. package/dist/templates/code/fit.d.ts +27 -0
  257. package/dist/templates/code/fit.d.ts.map +1 -0
  258. package/dist/templates/code/fit.js +59 -0
  259. package/dist/templates/code/fit.js.map +1 -0
  260. package/dist/templates/code/index.d.ts +12 -0
  261. package/dist/templates/code/index.d.ts.map +1 -0
  262. package/dist/templates/code/index.js +64 -0
  263. package/dist/templates/code/index.js.map +1 -0
  264. package/dist/templates/code/layout.d.ts +21 -0
  265. package/dist/templates/code/layout.d.ts.map +1 -0
  266. package/dist/templates/code/layout.js +21 -0
  267. package/dist/templates/code/layout.js.map +1 -0
  268. package/dist/templates/code/panel.d.ts +17 -0
  269. package/dist/templates/code/panel.d.ts.map +1 -0
  270. package/dist/templates/code/panel.js +20 -0
  271. package/dist/templates/code/panel.js.map +1 -0
  272. package/dist/templates/code/plate.d.ts +15 -0
  273. package/dist/templates/code/plate.d.ts.map +1 -0
  274. package/dist/templates/code/plate.js +32 -0
  275. package/dist/templates/code/plate.js.map +1 -0
  276. package/dist/templates/code/spans.d.ts +19 -0
  277. package/dist/templates/code/spans.d.ts.map +1 -0
  278. package/dist/templates/code/spans.js +36 -0
  279. package/dist/templates/code/spans.js.map +1 -0
  280. package/dist/templates/code/warn.d.ts +11 -0
  281. package/dist/templates/code/warn.d.ts.map +1 -0
  282. package/dist/templates/code/warn.js +24 -0
  283. package/dist/templates/code/warn.js.map +1 -0
  284. package/dist/templates/footer.d.ts +21 -0
  285. package/dist/templates/footer.d.ts.map +1 -0
  286. package/dist/templates/footer.js +25 -0
  287. package/dist/templates/footer.js.map +1 -0
  288. package/dist/templates/index.d.ts +3 -3
  289. package/dist/templates/index.d.ts.map +1 -1
  290. package/dist/templates/index.js +6 -6
  291. package/dist/templates/index.js.map +1 -1
  292. package/dist/text/element.d.ts +18 -0
  293. package/dist/text/element.d.ts.map +1 -0
  294. package/dist/text/element.js +19 -0
  295. package/dist/text/element.js.map +1 -0
  296. package/dist/text/escape.d.ts +5 -0
  297. package/dist/text/escape.d.ts.map +1 -0
  298. package/dist/text/escape.js +12 -0
  299. package/dist/text/escape.js.map +1 -0
  300. package/dist/text/index.d.ts +7 -0
  301. package/dist/text/index.d.ts.map +1 -0
  302. package/dist/text/index.js +5 -0
  303. package/dist/text/index.js.map +1 -0
  304. package/dist/text/stack.d.ts +24 -0
  305. package/dist/text/stack.d.ts.map +1 -0
  306. package/dist/text/stack.js +18 -0
  307. package/dist/text/stack.js.map +1 -0
  308. package/dist/text/wrap.d.ts +12 -0
  309. package/dist/text/wrap.d.ts.map +1 -0
  310. package/dist/text/wrap.js +33 -0
  311. package/dist/text/wrap.js.map +1 -0
  312. package/dist/types.d.ts +326 -2
  313. package/dist/types.d.ts.map +1 -1
  314. package/dist/validate/check.d.ts +13 -0
  315. package/dist/validate/check.d.ts.map +1 -0
  316. package/dist/validate/check.js +34 -0
  317. package/dist/validate/check.js.map +1 -0
  318. package/dist/validate/index.d.ts +15 -0
  319. package/dist/validate/index.d.ts.map +1 -0
  320. package/dist/validate/index.js +41 -0
  321. package/dist/validate/index.js.map +1 -0
  322. package/dist/validate/keys.d.ts +58 -0
  323. package/dist/validate/keys.d.ts.map +1 -0
  324. package/dist/validate/keys.js +166 -0
  325. package/dist/validate/keys.js.map +1 -0
  326. package/dist/validate/overrides.d.ts +5 -0
  327. package/dist/validate/overrides.d.ts.map +1 -0
  328. package/dist/validate/overrides.js +43 -0
  329. package/dist/validate/overrides.js.map +1 -0
  330. package/dist/validate/placement.d.ts +10 -0
  331. package/dist/validate/placement.d.ts.map +1 -0
  332. package/dist/validate/placement.js +38 -0
  333. package/dist/validate/placement.js.map +1 -0
  334. package/dist/validate/sizes.d.ts +9 -0
  335. package/dist/validate/sizes.d.ts.map +1 -0
  336. package/dist/validate/sizes.js +27 -0
  337. package/dist/validate/sizes.js.map +1 -0
  338. package/dist/validate/suggest.d.ts +10 -0
  339. package/dist/validate/suggest.d.ts.map +1 -0
  340. package/dist/validate/suggest.js +55 -0
  341. package/dist/validate/suggest.js.map +1 -0
  342. package/dist/validate/values.d.ts +21 -0
  343. package/dist/validate/values.d.ts.map +1 -0
  344. package/dist/validate/values.js +57 -0
  345. package/dist/validate/values.js.map +1 -0
  346. package/dist/validate.d.ts +15 -0
  347. package/dist/validate.d.ts.map +1 -0
  348. package/dist/validate.js +300 -0
  349. package/dist/validate.js.map +1 -0
  350. package/package.json +13 -6
@@ -0,0 +1,44 @@
1
+ import { ellipsis } from "./ellipsis.js";
2
+ /**
3
+ * Clip a line to the columns that fit, ending it with an ellipsis. The font
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.
6
+ *
7
+ * Returns the line unchanged when it already fits, so the caller can count the
8
+ * clipped lines by identity.
9
+ */
10
+ export function clipLine(tokens, maxColumns) {
11
+ const last = tokens.at(-1);
12
+ if (last === undefined || last.column + last.text.length <= maxColumns) {
13
+ return tokens;
14
+ }
15
+ const clipped = [];
16
+ for (const token of tokens) {
17
+ if (token.column >= maxColumns) {
18
+ break;
19
+ }
20
+ const room = maxColumns - token.column;
21
+ if (token.text.length <= room) {
22
+ clipped.push(token);
23
+ continue;
24
+ }
25
+ clipped.push({ ...token, text: token.text.slice(0, room - 1) + ellipsis });
26
+ break;
27
+ }
28
+ return clipped;
29
+ }
30
+ /**
31
+ * Clip every line to the panel width, and count how many had to give ground.
32
+ */
33
+ export function clipLines(lines, maxColumns) {
34
+ let clipped = 0;
35
+ const fitted = lines.map((tokens) => {
36
+ const line = clipLine(tokens, maxColumns);
37
+ if (line !== tokens) {
38
+ clipped += 1;
39
+ }
40
+ return line;
41
+ });
42
+ return { lines: fitted, clipped };
43
+ }
44
+ //# sourceMappingURL=clip.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clip.js","sourceRoot":"","sources":["../../../src/templates/code/clip.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC;;;;;;;GAOG;AACH,MAAM,UAAU,QAAQ,CACtB,MAA4B,EAC5B,UAAkB;IAElB,MAAM,IAAI,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAE3B,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,IAAI,UAAU,EAAE,CAAC;QACvE,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,MAAM,OAAO,GAAgB,EAAE,CAAC;IAEhC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,IAAI,KAAK,CAAC,MAAM,IAAI,UAAU,EAAE,CAAC;YAC/B,MAAM;QACR,CAAC;QAED,MAAM,IAAI,GAAG,UAAU,GAAG,KAAK,CAAC,MAAM,CAAC;QAEvC,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,IAAI,IAAI,EAAE,CAAC;YAC9B,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACpB,SAAS;QACX,CAAC;QAED,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,KAAK,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,GAAG,CAAC,CAAC,GAAG,QAAQ,EAAE,CAAC,CAAC;QAC3E,MAAM;IACR,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,SAAS,CACvB,KAAwC,EACxC,UAAkB;IAElB,IAAI,OAAO,GAAG,CAAC,CAAC;IAEhB,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE;QAClC,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;QAE1C,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;YACpB,OAAO,IAAI,CAAC,CAAC;QACf,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;IAEH,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;AACpC,CAAC"}
@@ -0,0 +1,3 @@
1
+ /** The mark a truncated line or block ends with. */
2
+ export declare const ellipsis = "\u2026";
3
+ //# sourceMappingURL=ellipsis.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ellipsis.d.ts","sourceRoot":"","sources":["../../../src/templates/code/ellipsis.ts"],"names":[],"mappings":"AAAA,oDAAoD;AACpD,eAAO,MAAM,QAAQ,WAAM,CAAC"}
@@ -0,0 +1,3 @@
1
+ /** The mark a truncated line or block ends with. */
2
+ export const ellipsis = "…";
3
+ //# sourceMappingURL=ellipsis.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ellipsis.js","sourceRoot":"","sources":["../../../src/templates/code/ellipsis.ts"],"names":[],"mappings":"AAAA,oDAAoD;AACpD,MAAM,CAAC,MAAM,QAAQ,GAAG,GAAG,CAAC"}
@@ -0,0 +1,27 @@
1
+ import type { CodeToken, HighlightedCode } from "../../highlight/index.js";
2
+ import type { ResolvedConfig } from "../../types.js";
3
+ /**
4
+ * Pick the largest font size that fits the snippet in the panel on both axes,
5
+ * clamped to the configured bounds.
6
+ *
7
+ * The bounds are fractions of the image *width*, not its height: a share image
8
+ * is scaled to fit the width of whatever feed shows it, so width is what
9
+ * decides whether the code ends up legible. Keying the floor to height would
10
+ * let a landscape image render the same snippet at half the size of its square
11
+ * counterpart.
12
+ */
13
+ export declare function fitFontSize(highlighted: HighlightedCode, codeWidth: number, codeHeight: number, imageWidth: number, config: ResolvedConfig): number;
14
+ /**
15
+ * Width of the laid-out block in characters, measured from the lines actually
16
+ * being drawn. Narrower than the snippet's longest line whenever that line was
17
+ * dropped or clipped, which keeps the panel hugged tight to what is visible.
18
+ */
19
+ export declare function blockColumns(lines: readonly (readonly CodeToken[])[]): number;
20
+ /**
21
+ * Drop lines that cannot fit at the chosen font size, marking the truncation
22
+ * with an ellipsis line so the image never silently misrepresents the snippet.
23
+ * The marker takes the indentation of the first dropped line, so it reads as
24
+ * part of the block rather than as a stray mark in the left margin.
25
+ */
26
+ export declare function fitLines(lines: readonly (readonly CodeToken[])[], codeHeight: number, step: number): readonly (readonly CodeToken[])[];
27
+ //# sourceMappingURL=fit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fit.d.ts","sourceRoot":"","sources":["../../../src/templates/code/fit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC3E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAGrD;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CACzB,WAAW,EAAE,eAAe,EAC5B,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,cAAc,GACrB,MAAM,CAWR;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,SAAS,CAAC,SAAS,SAAS,EAAE,CAAC,EAAE,GAAG,MAAM,CAY7E;AAaD;;;;;GAKG;AACH,wBAAgB,QAAQ,CACtB,KAAK,EAAE,SAAS,CAAC,SAAS,SAAS,EAAE,CAAC,EAAE,EACxC,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,GACX,SAAS,CAAC,SAAS,SAAS,EAAE,CAAC,EAAE,CAWnC"}
@@ -0,0 +1,59 @@
1
+ import { ellipsis } from "./ellipsis.js";
2
+ /**
3
+ * Pick the largest font size that fits the snippet in the panel on both axes,
4
+ * clamped to the configured bounds.
5
+ *
6
+ * The bounds are fractions of the image *width*, not its height: a share image
7
+ * is scaled to fit the width of whatever feed shows it, so width is what
8
+ * decides whether the code ends up legible. Keying the floor to height would
9
+ * let a landscape image render the same snippet at half the size of its square
10
+ * counterpart.
11
+ */
12
+ export function fitFontSize(highlighted, codeWidth, codeHeight, imageWidth, config) {
13
+ const { charWidthRatio, lineHeight, maxFontScale, minFontScale } = config.code;
14
+ const byWidth = codeWidth / (Math.max(1, highlighted.longestLine) * charWidthRatio);
15
+ const byHeight = codeHeight / (Math.max(1, highlighted.lines.length) * lineHeight);
16
+ const fitted = Math.min(byWidth, byHeight, imageWidth * maxFontScale);
17
+ return Math.max(1, Math.floor(Math.max(fitted, imageWidth * minFontScale)));
18
+ }
19
+ /**
20
+ * Width of the laid-out block in characters, measured from the lines actually
21
+ * being drawn. Narrower than the snippet's longest line whenever that line was
22
+ * dropped or clipped, which keeps the panel hugged tight to what is visible.
23
+ */
24
+ export function blockColumns(lines) {
25
+ let columns = 0;
26
+ for (const tokens of lines) {
27
+ const last = tokens.at(-1);
28
+ if (last !== undefined) {
29
+ columns = Math.max(columns, last.column + last.text.length);
30
+ }
31
+ }
32
+ return columns;
33
+ }
34
+ function ellipsisToken(column) {
35
+ return {
36
+ text: ellipsis,
37
+ column,
38
+ color: undefined,
39
+ opacity: 0.6,
40
+ bold: false,
41
+ italic: false,
42
+ };
43
+ }
44
+ /**
45
+ * Drop lines that cannot fit at the chosen font size, marking the truncation
46
+ * with an ellipsis line so the image never silently misrepresents the snippet.
47
+ * The marker takes the indentation of the first dropped line, so it reads as
48
+ * part of the block rather than as a stray mark in the left margin.
49
+ */
50
+ export function fitLines(lines, codeHeight, step) {
51
+ const maxLines = Math.max(1, Math.floor(codeHeight / step));
52
+ if (lines.length <= maxLines) {
53
+ return lines;
54
+ }
55
+ const kept = lines.slice(0, maxLines - 1);
56
+ const dropped = lines.slice(maxLines - 1).find((line) => line.length > 0);
57
+ return [...kept, [ellipsisToken(dropped?.[0]?.column ?? 0)]];
58
+ }
59
+ //# sourceMappingURL=fit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fit.js","sourceRoot":"","sources":["../../../src/templates/code/fit.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC;;;;;;;;;GASG;AACH,MAAM,UAAU,WAAW,CACzB,WAA4B,EAC5B,SAAiB,EACjB,UAAkB,EAClB,UAAkB,EAClB,MAAsB;IAEtB,MAAM,EAAE,cAAc,EAAE,UAAU,EAAE,YAAY,EAAE,YAAY,EAAE,GAC9D,MAAM,CAAC,IAAI,CAAC;IAEd,MAAM,OAAO,GACX,SAAS,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,WAAW,CAAC,WAAW,CAAC,GAAG,cAAc,CAAC,CAAC;IACtE,MAAM,QAAQ,GACZ,UAAU,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,UAAU,CAAC,CAAC;IAEpE,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,QAAQ,EAAE,UAAU,GAAG,YAAY,CAAC,CAAC;IACtE,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,UAAU,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;AAC9E,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,KAAwC;IACnE,IAAI,OAAO,GAAG,CAAC,CAAC;IAEhB,KAAK,MAAM,MAAM,IAAI,KAAK,EAAE,CAAC;QAC3B,MAAM,IAAI,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAE3B,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YACvB,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC9D,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,aAAa,CAAC,MAAc;IACnC,OAAO;QACL,IAAI,EAAE,QAAQ;QACd,MAAM;QACN,KAAK,EAAE,SAAS;QAChB,OAAO,EAAE,GAAG;QACZ,IAAI,EAAE,KAAK;QACX,MAAM,EAAE,KAAK;KACd,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,QAAQ,CACtB,KAAwC,EACxC,UAAkB,EAClB,IAAY;IAEZ,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC,CAAC;IAE5D,IAAI,KAAK,CAAC,MAAM,IAAI,QAAQ,EAAE,CAAC;QAC7B,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,GAAG,CAAC,CAAC,CAAC;IAC1C,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAE1E,OAAO,CAAC,GAAG,IAAI,EAAE,CAAC,aAAa,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;AAC/D,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { Template } from "../../types.js";
2
+ /**
3
+ * Syntax-highlighted code snippet on a rounded panel over the configured
4
+ * background. Reads `code` and `language` from the props (as the original
5
+ * `image_text` / `image_lexer` frontmatter did), with an optional `title`
6
+ * above the panel and the configured footer below it.
7
+ *
8
+ * Highlighting uses Shiki, so token colours come from a real VS Code theme
9
+ * rather than being approximated.
10
+ */
11
+ export declare const codeTemplate: Template;
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/templates/code/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAW/C;;;;;;;;GAQG;AACH,eAAO,MAAM,YAAY,EAAE,QAuE1B,CAAC"}
@@ -0,0 +1,64 @@
1
+ import { highlightCode } from "../../highlight/index.js";
2
+ import { hasFooter } from "../footer.js";
3
+ import { optionalString } from "../props.js";
4
+ import { codeFooter, codeHeading } from "./chrome.js";
5
+ import { blockColumns } from "./fit.js";
6
+ import { fitSnippet } from "./layout.js";
7
+ import { layoutPanel } from "./panel.js";
8
+ import { hugPanel, panelSvg } from "./plate.js";
9
+ import { codeBody } from "./spans.js";
10
+ import { warnIfTruncated } from "./warn.js";
11
+ /**
12
+ * Syntax-highlighted code snippet on a rounded panel over the configured
13
+ * background. Reads `code` and `language` from the props (as the original
14
+ * `image_text` / `image_lexer` frontmatter did), with an optional `title`
15
+ * above the panel and the configured footer below it.
16
+ *
17
+ * Highlighting uses Shiki, so token colours come from a real VS Code theme
18
+ * rather than being approximated.
19
+ */
20
+ export const codeTemplate = {
21
+ name: "code",
22
+ async render({ props, config, dimensions }) {
23
+ const { width, height } = dimensions;
24
+ const title = optionalString(props.title);
25
+ const titleFs = Math.round(height * 0.045);
26
+ const footerFs = Math.round(height * 0.032);
27
+ const highlighted = await highlightCode(optionalString(props["code"]) ?? "", {
28
+ language: optionalString(props["language"]) ?? "text",
29
+ theme: optionalString(props["theme"]) ?? config.code.theme,
30
+ tabSize: config.code.tabSize,
31
+ });
32
+ const available = layoutPanel(dimensions, config, titleFs, footerFs, title !== undefined && title !== "", hasFooter(config));
33
+ const fitted = fitSnippet(highlighted, available, width, config);
34
+ warnIfTruncated(config, dimensions, {
35
+ dropped: highlighted.lines.length - fitted.lines.length,
36
+ clipped: fitted.clipped,
37
+ }, highlighted.lines.length);
38
+ // Shrink the panel down onto the snippet so it isn't left floating in dead
39
+ // space — on a landscape image especially, a wide panel holding a narrow
40
+ // block leaves the code marooned off to one side.
41
+ const panel = hugPanel(available, {
42
+ width: blockColumns(fitted.lines) * fitted.charWidth + fitted.padding * 2,
43
+ height: fitted.lines.length * fitted.step + fitted.padding * 2,
44
+ });
45
+ const body = codeBody(fitted.lines, {
46
+ // Code reads from the left edge, as it does in an editor. Indentation is
47
+ // carried by each token's column, so the snippet keeps its shape.
48
+ originX: panel.x + fitted.padding,
49
+ originY: panel.y + (panel.height - fitted.lines.length * fitted.step) / 2,
50
+ fontSize: fitted.fontSize,
51
+ charWidth: fitted.charWidth,
52
+ step: fitted.step,
53
+ fontFamily: config.code.fontFamily,
54
+ foreground: highlighted.foreground,
55
+ });
56
+ const shadowOffset = Math.round(Math.min(width, height) * 0.01);
57
+ const plate = panelSvg(panel, highlighted.background, Math.max(1, shadowOffset));
58
+ return (codeHeading(title, panel, titleFs, width, config) +
59
+ plate +
60
+ body +
61
+ codeFooter(dimensions, footerFs, config));
62
+ },
63
+ };
64
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/templates/code/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import type { CodeToken, HighlightedCode } from "../../highlight/index.js";
2
+ import type { ResolvedConfig } from "../../types.js";
3
+ import type { Panel } from "./panel.js";
4
+ /**
5
+ * A snippet sized to the space it has: the lines that survived, the grid they
6
+ * are drawn on, and how many of them had to be clipped to get there.
7
+ */
8
+ export interface FittedCode {
9
+ readonly lines: readonly (readonly CodeToken[])[];
10
+ readonly clipped: number;
11
+ readonly fontSize: number;
12
+ readonly charWidth: number;
13
+ readonly step: number;
14
+ readonly padding: number;
15
+ }
16
+ /**
17
+ * Fit a highlighted snippet into the panel it has been allotted: choose the
18
+ * font size, then drop and clip whatever still does not fit.
19
+ */
20
+ export declare function fitSnippet(highlighted: HighlightedCode, available: Panel, imageWidth: number, config: ResolvedConfig): FittedCode;
21
+ //# sourceMappingURL=layout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layout.d.ts","sourceRoot":"","sources":["../../../src/templates/code/layout.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC3E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAGrD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAExC;;;GAGG;AACH,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC,SAAS,SAAS,EAAE,CAAC,EAAE,CAAC;IAClD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED;;;GAGG;AACH,wBAAgB,UAAU,CACxB,WAAW,EAAE,eAAe,EAC5B,SAAS,EAAE,KAAK,EAChB,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,cAAc,GACrB,UAAU,CA6BZ"}
@@ -0,0 +1,21 @@
1
+ import { clipLines } from "./clip.js";
2
+ import { fitFontSize, fitLines } from "./fit.js";
3
+ /**
4
+ * Fit a highlighted snippet into the panel it has been allotted: choose the
5
+ * font size, then drop and clip whatever still does not fit.
6
+ */
7
+ export function fitSnippet(highlighted, available, imageWidth, config) {
8
+ const inner = Math.round(Math.min(available.width, available.height) * 0.07);
9
+ const codeWidth = Math.max(1, available.width - inner * 2);
10
+ const codeHeight = Math.max(1, available.height - inner * 2);
11
+ const fontSize = fitFontSize(highlighted, codeWidth, codeHeight, imageWidth, config);
12
+ const charWidth = fontSize * config.code.charWidthRatio;
13
+ const step = fontSize * config.code.lineHeight;
14
+ const { lines, clipped } = clipLines(fitLines(highlighted.lines, codeHeight, step), Math.max(1, Math.floor(codeWidth / charWidth)));
15
+ // Padding reads best proportional to the text, not the panel — a snippet
16
+ // fitted down to a small size wants tighter margins. Only ever shrink, so
17
+ // the code area the font was fitted against stays valid.
18
+ const padding = Math.max(Math.min(inner, Math.round(fontSize * 1.6)), Math.round(inner * 0.35));
19
+ return { lines, clipped, fontSize, charWidth, step, padding };
20
+ }
21
+ //# sourceMappingURL=layout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layout.js","sourceRoot":"","sources":["../../../src/templates/code/layout.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAgBjD;;;GAGG;AACH,MAAM,UAAU,UAAU,CACxB,WAA4B,EAC5B,SAAgB,EAChB,UAAkB,EAClB,MAAsB;IAEtB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,EAAE,SAAS,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC;IAC7E,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,CAAC,KAAK,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC;IAC3D,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,CAAC,MAAM,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC;IAE7D,MAAM,QAAQ,GAAG,WAAW,CAC1B,WAAW,EACX,SAAS,EACT,UAAU,EACV,UAAU,EACV,MAAM,CACP,CAAC;IACF,MAAM,SAAS,GAAG,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC;IACxD,MAAM,IAAI,GAAG,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC;IAE/C,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,SAAS,CAClC,QAAQ,CAAC,WAAW,CAAC,KAAK,EAAE,UAAU,EAAE,IAAI,CAAC,EAC7C,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,SAAS,CAAC,CAAC,CAC/C,CAAC;IAEF,yEAAyE;IACzE,0EAA0E;IAC1E,yDAAyD;IACzD,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CACtB,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,GAAG,CAAC,CAAC,EAC3C,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC,CACzB,CAAC;IAEF,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;AAChE,CAAC"}
@@ -0,0 +1,17 @@
1
+ import type { Dimensions, ResolvedConfig } from "../../types.js";
2
+ /**
3
+ * The rounded plate the snippet is drawn on.
4
+ */
5
+ export interface Panel {
6
+ readonly x: number;
7
+ readonly y: number;
8
+ readonly width: number;
9
+ readonly height: number;
10
+ readonly radius: number;
11
+ }
12
+ /**
13
+ * Place the code panel within the image, leaving room above for a title and
14
+ * below for a footer when either is present.
15
+ */
16
+ export declare function layoutPanel(dimensions: Dimensions, config: ResolvedConfig, titleFontSize: number, footerFontSize: number, hasTitle: boolean, hasFooter: boolean): Panel;
17
+ //# sourceMappingURL=panel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"panel.d.ts","sourceRoot":"","sources":["../../../src/templates/code/panel.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAEjE;;GAEG;AACH,MAAM,WAAW,KAAK;IACpB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED;;;GAGG;AACH,wBAAgB,WAAW,CACzB,UAAU,EAAE,UAAU,EACtB,MAAM,EAAE,cAAc,EACtB,aAAa,EAAE,MAAM,EACrB,cAAc,EAAE,MAAM,EACtB,QAAQ,EAAE,OAAO,EACjB,SAAS,EAAE,OAAO,GACjB,KAAK,CAgBP"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Place the code panel within the image, leaving room above for a title and
3
+ * below for a footer when either is present.
4
+ */
5
+ export function layoutPanel(dimensions, config, titleFontSize, footerFontSize, hasTitle, hasFooter) {
6
+ const { width, height } = dimensions;
7
+ const shorter = Math.min(width, height);
8
+ const pad = Math.round(shorter * 0.05);
9
+ const gap = Math.round(shorter * 0.028);
10
+ const top = pad + (hasTitle ? titleFontSize + gap : 0);
11
+ const bottom = height - pad - (hasFooter ? footerFontSize + gap : 0);
12
+ return {
13
+ x: pad,
14
+ y: top,
15
+ width: width - pad * 2,
16
+ height: Math.max(1, bottom - top),
17
+ radius: Math.round(shorter * config.code.cornerScale),
18
+ };
19
+ }
20
+ //# sourceMappingURL=panel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"panel.js","sourceRoot":"","sources":["../../../src/templates/code/panel.ts"],"names":[],"mappings":"AAaA;;;GAGG;AACH,MAAM,UAAU,WAAW,CACzB,UAAsB,EACtB,MAAsB,EACtB,aAAqB,EACrB,cAAsB,EACtB,QAAiB,EACjB,SAAkB;IAElB,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,UAAU,CAAC;IACrC,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IACxC,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;IACvC,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,KAAK,CAAC,CAAC;IAExC,MAAM,GAAG,GAAG,GAAG,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,aAAa,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACvD,MAAM,MAAM,GAAG,MAAM,GAAG,GAAG,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,cAAc,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAErE,OAAO;QACL,CAAC,EAAE,GAAG;QACN,CAAC,EAAE,GAAG;QACN,KAAK,EAAE,KAAK,GAAG,GAAG,GAAG,CAAC;QACtB,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,GAAG,GAAG,CAAC;QACjC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC;KACtD,CAAC;AACJ,CAAC"}
@@ -0,0 +1,15 @@
1
+ import type { Panel } from "./panel.js";
2
+ /**
3
+ * Shrink a panel onto its content, keeping it centred in the space it was
4
+ * allotted. Both axes are floored so a small snippet still gets a panel with
5
+ * presence rather than a letterbox slot or a narrow strip.
6
+ */
7
+ export declare function hugPanel(available: Panel, wanted: {
8
+ readonly width: number;
9
+ readonly height: number;
10
+ }): Panel;
11
+ /**
12
+ * The panel itself: a drop shadow, then the theme-coloured surface it sits on.
13
+ */
14
+ export declare function panelSvg(panel: Panel, background: string, shadowOffset: number): string;
15
+ //# sourceMappingURL=plate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plate.d.ts","sourceRoot":"","sources":["../../../src/templates/code/plate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAExC;;;;GAIG;AACH,wBAAgB,QAAQ,CACtB,SAAS,EAAE,KAAK,EAChB,MAAM,EAAE;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC1D,KAAK,CAmBP;AAED;;GAEG;AACH,wBAAgB,QAAQ,CACtB,KAAK,EAAE,KAAK,EACZ,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM,GACnB,MAAM,CAaR"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Shrink a panel onto its content, keeping it centred in the space it was
3
+ * allotted. Both axes are floored so a small snippet still gets a panel with
4
+ * presence rather than a letterbox slot or a narrow strip.
5
+ */
6
+ export function hugPanel(available, wanted) {
7
+ const width = Math.min(available.width, Math.max(Math.round(wanted.width), Math.round(available.width * 0.55)));
8
+ // Floor relative to the panel's own width, so shrinking never leaves a
9
+ // sliver, and never taller than the space the font was fitted against.
10
+ const height = Math.min(available.height, Math.max(Math.round(wanted.height), Math.round(width * 0.25)));
11
+ return {
12
+ ...available,
13
+ x: available.x + Math.round((available.width - width) / 2),
14
+ y: available.y + Math.round((available.height - height) / 2),
15
+ width,
16
+ height,
17
+ };
18
+ }
19
+ /**
20
+ * The panel itself: a drop shadow, then the theme-coloured surface it sits on.
21
+ */
22
+ export function panelSvg(panel, background, shadowOffset) {
23
+ const shadow = `<rect x="${String(panel.x)}" y="${String(panel.y + shadowOffset)}"` +
24
+ ` width="${String(panel.width)}" height="${String(panel.height)}"` +
25
+ ` rx="${String(panel.radius)}" fill="#000000" fill-opacity="0.22"/>`;
26
+ const surface = `<rect x="${String(panel.x)}" y="${String(panel.y)}"` +
27
+ ` width="${String(panel.width)}" height="${String(panel.height)}"` +
28
+ ` rx="${String(panel.radius)}" fill="${background}"` +
29
+ ` stroke="#ffffff" stroke-opacity="0.12"/>`;
30
+ return shadow + surface;
31
+ }
32
+ //# sourceMappingURL=plate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plate.js","sourceRoot":"","sources":["../../../src/templates/code/plate.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,UAAU,QAAQ,CACtB,SAAgB,EAChB,MAA2D;IAE3D,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CACpB,SAAS,CAAC,KAAK,EACf,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,CACvE,CAAC;IACF,uEAAuE;IACvE,uEAAuE;IACvE,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CACrB,SAAS,CAAC,MAAM,EAChB,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,CAC9D,CAAC;IAEF,OAAO;QACL,GAAG,SAAS;QACZ,CAAC,EAAE,SAAS,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC;QAC1D,CAAC,EAAE,SAAS,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;QAC5D,KAAK;QACL,MAAM;KACP,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,QAAQ,CACtB,KAAY,EACZ,UAAkB,EAClB,YAAoB;IAEpB,MAAM,MAAM,GACV,YAAY,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,MAAM,CAAC,KAAK,CAAC,CAAC,GAAG,YAAY,CAAC,GAAG;QACpE,WAAW,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,aAAa,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG;QAClE,QAAQ,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,wCAAwC,CAAC;IAEvE,MAAM,OAAO,GACX,YAAY,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG;QACrD,WAAW,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,aAAa,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG;QAClE,QAAQ,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,WAAW,UAAU,GAAG;QACpD,2CAA2C,CAAC;IAE9C,OAAO,MAAM,GAAG,OAAO,CAAC;AAC1B,CAAC"}
@@ -0,0 +1,19 @@
1
+ import type { CodeToken } from "../../highlight/index.js";
2
+ /**
3
+ * Where and how the snippet's character grid is drawn.
4
+ */
5
+ export interface GridMetrics {
6
+ readonly originX: number;
7
+ readonly originY: number;
8
+ readonly fontSize: number;
9
+ readonly charWidth: number;
10
+ readonly step: number;
11
+ readonly fontFamily: string;
12
+ readonly foreground: string;
13
+ }
14
+ /**
15
+ * The snippet as one `<text>` element per line, each token positioned
16
+ * absolutely from its character column so indentation survives SVG text flow.
17
+ */
18
+ export declare function codeBody(lines: readonly (readonly CodeToken[])[], metrics: GridMetrics): string;
19
+ //# sourceMappingURL=spans.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spans.d.ts","sourceRoot":"","sources":["../../../src/templates/code/spans.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AA2B1D;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CACtB,KAAK,EAAE,SAAS,CAAC,SAAS,SAAS,EAAE,CAAC,EAAE,EACxC,OAAO,EAAE,WAAW,GACnB,MAAM,CAyBR"}
@@ -0,0 +1,36 @@
1
+ import { escapeXml } from "../../text/index.js";
2
+ /** Fraction of the font size the baseline sits below the glyph box top. */
3
+ const ascentRatio = 0.78;
4
+ function tokenSpan(token, x, charWidth, foreground) {
5
+ const fill = token.color ?? foreground;
6
+ const opacity = token.opacity === undefined
7
+ ? ""
8
+ : ` fill-opacity="${String(token.opacity)}"`;
9
+ const weight = token.bold ? ` font-weight="700"` : "";
10
+ const style = token.italic ? ` font-style="italic"` : "";
11
+ return (`<tspan x="${String(Math.round(x + token.column * charWidth))}"` +
12
+ ` fill="${fill}"${opacity}${weight}${style}>` +
13
+ `${escapeXml(token.text)}</tspan>`);
14
+ }
15
+ /**
16
+ * The snippet as one `<text>` element per line, each token positioned
17
+ * absolutely from its character column so indentation survives SVG text flow.
18
+ */
19
+ export function codeBody(lines, metrics) {
20
+ const { originX, originY, fontSize, charWidth, step } = metrics;
21
+ return lines
22
+ .map((tokens, index) => {
23
+ if (tokens.length === 0) {
24
+ return "";
25
+ }
26
+ const baseline = Math.round(originY + index * step + (step - fontSize) / 2 + fontSize * ascentRatio);
27
+ const spans = tokens
28
+ .map((token) => tokenSpan(token, originX, charWidth, metrics.foreground))
29
+ .join("");
30
+ return (`<text y="${String(baseline)}" xml:space="preserve"` +
31
+ ` font-family="${escapeXml(metrics.fontFamily)}"` +
32
+ ` font-size="${String(fontSize)}">${spans}</text>`);
33
+ })
34
+ .join("");
35
+ }
36
+ //# sourceMappingURL=spans.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spans.js","sourceRoot":"","sources":["../../../src/templates/code/spans.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAEhD,2EAA2E;AAC3E,MAAM,WAAW,GAAG,IAAI,CAAC;AAEzB,SAAS,SAAS,CAChB,KAAgB,EAChB,CAAS,EACT,SAAiB,EACjB,UAAkB;IAElB,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,IAAI,UAAU,CAAC;IACvC,MAAM,OAAO,GACX,KAAK,CAAC,OAAO,KAAK,SAAS;QACzB,CAAC,CAAC,EAAE;QACJ,CAAC,CAAC,kBAAkB,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC;IACjD,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,EAAE,CAAC;IACtD,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,EAAE,CAAC;IAEzD,OAAO,CACL,aAAa,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,KAAK,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC,GAAG;QAChE,UAAU,IAAI,IAAI,OAAO,GAAG,MAAM,GAAG,KAAK,GAAG;QAC7C,GAAG,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CACnC,CAAC;AACJ,CAAC;AAeD;;;GAGG;AACH,MAAM,UAAU,QAAQ,CACtB,KAAwC,EACxC,OAAoB;IAEpB,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC;IAEhE,OAAO,KAAK;SACT,GAAG,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE;QACrB,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxB,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CACzB,OAAO,GAAG,KAAK,GAAG,IAAI,GAAG,CAAC,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,GAAG,QAAQ,GAAG,WAAW,CACxE,CAAC;QACF,MAAM,KAAK,GAAG,MAAM;aACjB,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CACb,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,CAAC,UAAU,CAAC,CACzD;aACA,IAAI,CAAC,EAAE,CAAC,CAAC;QAEZ,OAAO,CACL,YAAY,MAAM,CAAC,QAAQ,CAAC,wBAAwB;YACpD,iBAAiB,SAAS,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG;YACjD,eAAe,MAAM,CAAC,QAAQ,CAAC,KAAK,KAAK,SAAS,CACnD,CAAC;IACJ,CAAC,CAAC;SACD,IAAI,CAAC,EAAE,CAAC,CAAC;AACd,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type { Dimensions, ResolvedConfig } from "../../types.js";
2
+ /**
3
+ * Tell the author when the snippet did not fit. Nothing in a finished image
4
+ * says the sample continued, so silent truncation is how a half-a-function
5
+ * share card ends up on someone else's timeline.
6
+ */
7
+ export declare function warnIfTruncated(config: ResolvedConfig, dimensions: Dimensions, counts: {
8
+ readonly dropped: number;
9
+ readonly clipped: number;
10
+ }, total: number): void;
11
+ //# sourceMappingURL=warn.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"warn.d.ts","sourceRoot":"","sources":["../../../src/templates/code/warn.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAMjE;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,cAAc,EACtB,UAAU,EAAE,UAAU,EACtB,MAAM,EAAE;IAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE,EAC9D,KAAK,EAAE,MAAM,GACZ,IAAI,CAoBN"}
@@ -0,0 +1,24 @@
1
+ function plural(count, noun) {
2
+ return `${String(count)} ${noun}${count === 1 ? "" : "s"}`;
3
+ }
4
+ /**
5
+ * Tell the author when the snippet did not fit. Nothing in a finished image
6
+ * says the sample continued, so silent truncation is how a half-a-function
7
+ * share card ends up on someone else's timeline.
8
+ */
9
+ export function warnIfTruncated(config, dimensions, counts, total) {
10
+ const parts = [];
11
+ if (counts.dropped > 0) {
12
+ parts.push(`${String(counts.dropped)} of ${plural(total, "line")} dropped`);
13
+ }
14
+ if (counts.clipped > 0) {
15
+ parts.push(`${plural(counts.clipped, "line")} clipped to the panel width`);
16
+ }
17
+ if (parts.length === 0) {
18
+ return;
19
+ }
20
+ config.onWarning(`code snippet does not fit the ${String(dimensions.width)}x${String(dimensions.height)}` +
21
+ ` image at a legible size: ${parts.join(", ")}.` +
22
+ ` Shorten the sample, or lower code.minFontScale to fit it in smaller.`);
23
+ }
24
+ //# sourceMappingURL=warn.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"warn.js","sourceRoot":"","sources":["../../../src/templates/code/warn.ts"],"names":[],"mappings":"AAEA,SAAS,MAAM,CAAC,KAAa,EAAE,IAAY;IACzC,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,IAAI,GAAG,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC;AAC7D,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAC7B,MAAsB,EACtB,UAAsB,EACtB,MAA8D,EAC9D,KAAa;IAEb,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,IAAI,MAAM,CAAC,OAAO,GAAG,CAAC,EAAE,CAAC;QACvB,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC;IAC9E,CAAC;IAED,IAAI,MAAM,CAAC,OAAO,GAAG,CAAC,EAAE,CAAC;QACvB,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,6BAA6B,CAAC,CAAC;IAC7E,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO;IACT,CAAC;IAED,MAAM,CAAC,SAAS,CACd,iCAAiC,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE;QACtF,6BAA6B,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;QAChD,uEAAuE,CAC1E,CAAC;AACJ,CAAC"}
@@ -0,0 +1,21 @@
1
+ import type { ResolvedConfig } from "../types.js";
2
+ /**
3
+ * Where and how a template wants its footer drawn. Every template places the
4
+ * footer differently; what they share is that a config with no footer, or an
5
+ * empty one, draws nothing at all.
6
+ */
7
+ export interface FooterPlacement {
8
+ readonly x: number;
9
+ readonly y: number;
10
+ readonly fontSize: number;
11
+ readonly opacity: number;
12
+ readonly anchor?: "start" | "middle" | "end";
13
+ }
14
+ /** Whether the config carries a footer worth drawing. */
15
+ export declare function hasFooter(config: ResolvedConfig): boolean;
16
+ /**
17
+ * The configured footer as a `<text>` element, or an empty string when there
18
+ * is none. Templates call this unconditionally and let it decide.
19
+ */
20
+ export declare function footerElement(config: ResolvedConfig, placement: FooterPlacement): string;
21
+ //# sourceMappingURL=footer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"footer.d.ts","sourceRoot":"","sources":["../../src/templates/footer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAC;CAC9C;AAED,yDAAyD;AACzD,wBAAgB,SAAS,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAEzD;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,cAAc,EACtB,SAAS,EAAE,eAAe,GACzB,MAAM,CAeR"}
@@ -0,0 +1,25 @@
1
+ import { textElement } from "../text/index.js";
2
+ /** Whether the config carries a footer worth drawing. */
3
+ export function hasFooter(config) {
4
+ return config.footer !== undefined && config.footer !== "";
5
+ }
6
+ /**
7
+ * The configured footer as a `<text>` element, or an empty string when there
8
+ * is none. Templates call this unconditionally and let it decide.
9
+ */
10
+ export function footerElement(config, placement) {
11
+ if (!hasFooter(config)) {
12
+ return "";
13
+ }
14
+ return textElement(config.footer ?? "", {
15
+ x: placement.x,
16
+ y: placement.y,
17
+ fontFamily: config.fontFamily,
18
+ fontSize: placement.fontSize,
19
+ fontWeight: 500,
20
+ fill: config.colors.foreground,
21
+ fillOpacity: placement.opacity,
22
+ ...(placement.anchor !== undefined && { anchor: placement.anchor }),
23
+ });
24
+ }
25
+ //# sourceMappingURL=footer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"footer.js","sourceRoot":"","sources":["../../src/templates/footer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAgB/C,yDAAyD;AACzD,MAAM,UAAU,SAAS,CAAC,MAAsB;IAC9C,OAAO,MAAM,CAAC,MAAM,KAAK,SAAS,IAAI,MAAM,CAAC,MAAM,KAAK,EAAE,CAAC;AAC7D,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa,CAC3B,MAAsB,EACtB,SAA0B;IAE1B,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;QACvB,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,OAAO,WAAW,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,EAAE;QACtC,CAAC,EAAE,SAAS,CAAC,CAAC;QACd,CAAC,EAAE,SAAS,CAAC,CAAC;QACd,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,QAAQ,EAAE,SAAS,CAAC,QAAQ;QAC5B,UAAU,EAAE,GAAG;QACf,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,UAAU;QAC9B,WAAW,EAAE,SAAS,CAAC,OAAO;QAC9B,GAAG,CAAC,SAAS,CAAC,MAAM,KAAK,SAAS,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC,MAAM,EAAE,CAAC;KACpE,CAAC,CAAC;AACL,CAAC"}
@@ -4,8 +4,8 @@ import type { Template } from "../types.js";
4
4
  * via `config.templates`.
5
5
  */
6
6
  export declare const builtinTemplates: Readonly<Record<string, Template>>;
7
- export { bannerTemplate } from "./banner.js";
8
- export { cardTemplate } from "./card.js";
9
- export { codeTemplate } from "./code.js";
7
+ export { bannerTemplate } from "./banner/index.js";
8
+ export { cardTemplate } from "./card/index.js";
9
+ export { codeTemplate } from "./code/index.js";
10
10
  export { optionalString } from "./props.js";
11
11
  //# 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;AAK5C;;;GAGG;AACH,eAAO,MAAM,gBAAgB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAI/D,CAAC;AAEF,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,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;AAK5C;;;GAGG;AACH,eAAO,MAAM,gBAAgB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAI/D,CAAC;AAEF,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,cAAc,EAAE,MAAM,YAAY,CAAC"}