postext 1.19.3 → 1.20.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (255) hide show
  1. package/dist/__tests__/comics/art.test.d.ts +2 -0
  2. package/dist/__tests__/comics/art.test.d.ts.map +1 -0
  3. package/dist/__tests__/comics/art.test.js +96 -0
  4. package/dist/__tests__/comics/art.test.js.map +1 -0
  5. package/dist/__tests__/comics/build.test.d.ts +2 -0
  6. package/dist/__tests__/comics/build.test.d.ts.map +1 -0
  7. package/dist/__tests__/comics/build.test.js +215 -0
  8. package/dist/__tests__/comics/build.test.js.map +1 -0
  9. package/dist/__tests__/comics/canvas.test.d.ts +2 -0
  10. package/dist/__tests__/comics/canvas.test.d.ts.map +1 -0
  11. package/dist/__tests__/comics/canvas.test.js +161 -0
  12. package/dist/__tests__/comics/canvas.test.js.map +1 -0
  13. package/dist/__tests__/comics/config.test.d.ts +2 -0
  14. package/dist/__tests__/comics/config.test.d.ts.map +1 -0
  15. package/dist/__tests__/comics/config.test.js +97 -0
  16. package/dist/__tests__/comics/config.test.js.map +1 -0
  17. package/dist/__tests__/comics/geometry.test.d.ts +2 -0
  18. package/dist/__tests__/comics/geometry.test.d.ts.map +1 -0
  19. package/dist/__tests__/comics/geometry.test.js +118 -0
  20. package/dist/__tests__/comics/geometry.test.js.map +1 -0
  21. package/dist/__tests__/comics/html.test.d.ts +2 -0
  22. package/dist/__tests__/comics/html.test.d.ts.map +1 -0
  23. package/dist/__tests__/comics/html.test.js +253 -0
  24. package/dist/__tests__/comics/html.test.js.map +1 -0
  25. package/dist/__tests__/comics/lettering.test.d.ts +2 -0
  26. package/dist/__tests__/comics/lettering.test.d.ts.map +1 -0
  27. package/dist/__tests__/comics/lettering.test.js +241 -0
  28. package/dist/__tests__/comics/lettering.test.js.map +1 -0
  29. package/dist/__tests__/comics/script.test.d.ts +2 -0
  30. package/dist/__tests__/comics/script.test.d.ts.map +1 -0
  31. package/dist/__tests__/comics/script.test.js +147 -0
  32. package/dist/__tests__/comics/script.test.js.map +1 -0
  33. package/dist/__tests__/comics/split.test.d.ts +2 -0
  34. package/dist/__tests__/comics/split.test.d.ts.map +1 -0
  35. package/dist/__tests__/comics/split.test.js +120 -0
  36. package/dist/__tests__/comics/split.test.js.map +1 -0
  37. package/dist/__tests__/comics/spread.test.d.ts +2 -0
  38. package/dist/__tests__/comics/spread.test.d.ts.map +1 -0
  39. package/dist/__tests__/comics/spread.test.js +161 -0
  40. package/dist/__tests__/comics/spread.test.js.map +1 -0
  41. package/dist/__tests__/comics/strip.test.d.ts +2 -0
  42. package/dist/__tests__/comics/strip.test.d.ts.map +1 -0
  43. package/dist/__tests__/comics/strip.test.js +231 -0
  44. package/dist/__tests__/comics/strip.test.js.map +1 -0
  45. package/dist/__tests__/exports.test.js +89 -0
  46. package/dist/__tests__/exports.test.js.map +1 -1
  47. package/dist/__tests__/parse/containers.test.js +1 -1
  48. package/dist/__tests__/parse/containers.test.js.map +1 -1
  49. package/dist/canvas-backend/comic.d.ts +32 -0
  50. package/dist/canvas-backend/comic.d.ts.map +1 -0
  51. package/dist/canvas-backend/comic.js +216 -0
  52. package/dist/canvas-backend/comic.js.map +1 -0
  53. package/dist/canvas-backend/headerFooter.d.ts +4 -1
  54. package/dist/canvas-backend/headerFooter.d.ts.map +1 -1
  55. package/dist/canvas-backend/headerFooter.js +3 -1
  56. package/dist/canvas-backend/headerFooter.js.map +1 -1
  57. package/dist/canvas-backend/index.d.ts.map +1 -1
  58. package/dist/canvas-backend/index.js +7 -1
  59. package/dist/canvas-backend/index.js.map +1 -1
  60. package/dist/comics/art.d.ts +72 -0
  61. package/dist/comics/art.d.ts.map +1 -0
  62. package/dist/comics/art.js +154 -0
  63. package/dist/comics/art.js.map +1 -0
  64. package/dist/comics/fonts.d.ts +20 -0
  65. package/dist/comics/fonts.d.ts.map +1 -0
  66. package/dist/comics/fonts.js +42 -0
  67. package/dist/comics/fonts.js.map +1 -0
  68. package/dist/comics/geometry.d.ts +87 -0
  69. package/dist/comics/geometry.d.ts.map +1 -0
  70. package/dist/comics/geometry.js +272 -0
  71. package/dist/comics/geometry.js.map +1 -0
  72. package/dist/comics/index.d.ts +29 -0
  73. package/dist/comics/index.d.ts.map +1 -0
  74. package/dist/comics/index.js +18 -0
  75. package/dist/comics/index.js.map +1 -0
  76. package/dist/comics/layoutPage.d.ts +156 -0
  77. package/dist/comics/layoutPage.d.ts.map +1 -0
  78. package/dist/comics/layoutPage.js +698 -0
  79. package/dist/comics/layoutPage.js.map +1 -0
  80. package/dist/comics/lettering/__tests__/harness.test.d.ts +2 -0
  81. package/dist/comics/lettering/__tests__/harness.test.d.ts.map +1 -0
  82. package/dist/comics/lettering/__tests__/harness.test.js +273 -0
  83. package/dist/comics/lettering/__tests__/harness.test.js.map +1 -0
  84. package/dist/comics/lettering/__tests__/letterPanel.test.d.ts +2 -0
  85. package/dist/comics/lettering/__tests__/letterPanel.test.d.ts.map +1 -0
  86. package/dist/comics/lettering/__tests__/letterPanel.test.js +224 -0
  87. package/dist/comics/lettering/__tests__/letterPanel.test.js.map +1 -0
  88. package/dist/comics/lettering/__tests__/polish.test.d.ts +2 -0
  89. package/dist/comics/lettering/__tests__/polish.test.d.ts.map +1 -0
  90. package/dist/comics/lettering/__tests__/polish.test.js +357 -0
  91. package/dist/comics/lettering/__tests__/polish.test.js.map +1 -0
  92. package/dist/comics/lettering/__tests__/round2.test.d.ts +2 -0
  93. package/dist/comics/lettering/__tests__/round2.test.d.ts.map +1 -0
  94. package/dist/comics/lettering/__tests__/round2.test.js +289 -0
  95. package/dist/comics/lettering/__tests__/round2.test.js.map +1 -0
  96. package/dist/comics/lettering/__tests__/round3.test.d.ts +2 -0
  97. package/dist/comics/lettering/__tests__/round3.test.d.ts.map +1 -0
  98. package/dist/comics/lettering/__tests__/round3.test.js +240 -0
  99. package/dist/comics/lettering/__tests__/round3.test.js.map +1 -0
  100. package/dist/comics/lettering/__tests__/shapeText.test.d.ts +2 -0
  101. package/dist/comics/lettering/__tests__/shapeText.test.d.ts.map +1 -0
  102. package/dist/comics/lettering/__tests__/shapeText.test.js +98 -0
  103. package/dist/comics/lettering/__tests__/shapeText.test.js.map +1 -0
  104. package/dist/comics/lettering/__tests__/shapes.test.d.ts +2 -0
  105. package/dist/comics/lettering/__tests__/shapes.test.d.ts.map +1 -0
  106. package/dist/comics/lettering/__tests__/shapes.test.js +137 -0
  107. package/dist/comics/lettering/__tests__/shapes.test.js.map +1 -0
  108. package/dist/comics/lettering/__tests__/stubMeasure.d.ts +5 -0
  109. package/dist/comics/lettering/__tests__/stubMeasure.d.ts.map +1 -0
  110. package/dist/comics/lettering/__tests__/stubMeasure.js +47 -0
  111. package/dist/comics/lettering/__tests__/stubMeasure.js.map +1 -0
  112. package/dist/comics/lettering/__tests__/text.test.d.ts +2 -0
  113. package/dist/comics/lettering/__tests__/text.test.d.ts.map +1 -0
  114. package/dist/comics/lettering/__tests__/text.test.js +86 -0
  115. package/dist/comics/lettering/__tests__/text.test.js.map +1 -0
  116. package/dist/comics/lettering/geom.d.ts +78 -0
  117. package/dist/comics/lettering/geom.d.ts.map +1 -0
  118. package/dist/comics/lettering/geom.js +376 -0
  119. package/dist/comics/lettering/geom.js.map +1 -0
  120. package/dist/comics/lettering/index.d.ts +7 -0
  121. package/dist/comics/lettering/index.d.ts.map +1 -0
  122. package/dist/comics/lettering/index.js +8 -0
  123. package/dist/comics/lettering/index.js.map +1 -0
  124. package/dist/comics/lettering/letter.d.ts +7 -0
  125. package/dist/comics/lettering/letter.d.ts.map +1 -0
  126. package/dist/comics/lettering/letter.js +496 -0
  127. package/dist/comics/lettering/letter.js.map +1 -0
  128. package/dist/comics/lettering/placement.d.ts +133 -0
  129. package/dist/comics/lettering/placement.d.ts.map +1 -0
  130. package/dist/comics/lettering/placement.js +1095 -0
  131. package/dist/comics/lettering/placement.js.map +1 -0
  132. package/dist/comics/lettering/presets.d.ts +15 -0
  133. package/dist/comics/lettering/presets.d.ts.map +1 -0
  134. package/dist/comics/lettering/presets.js +61 -0
  135. package/dist/comics/lettering/presets.js.map +1 -0
  136. package/dist/comics/lettering/shape-text.d.ts +72 -0
  137. package/dist/comics/lettering/shape-text.d.ts.map +1 -0
  138. package/dist/comics/lettering/shape-text.js +550 -0
  139. package/dist/comics/lettering/shape-text.js.map +1 -0
  140. package/dist/comics/lettering/shapes.d.ts +83 -0
  141. package/dist/comics/lettering/shapes.d.ts.map +1 -0
  142. package/dist/comics/lettering/shapes.js +512 -0
  143. package/dist/comics/lettering/shapes.js.map +1 -0
  144. package/dist/comics/lettering/text.d.ts +79 -0
  145. package/dist/comics/lettering/text.d.ts.map +1 -0
  146. package/dist/comics/lettering/text.js +488 -0
  147. package/dist/comics/lettering/text.js.map +1 -0
  148. package/dist/comics/lettering/types.d.ts +279 -0
  149. package/dist/comics/lettering/types.d.ts.map +1 -0
  150. package/dist/comics/lettering/types.js +9 -0
  151. package/dist/comics/lettering/types.js.map +1 -0
  152. package/dist/comics/page.d.ts +37 -0
  153. package/dist/comics/page.d.ts.map +1 -0
  154. package/dist/comics/page.js +285 -0
  155. package/dist/comics/page.js.map +1 -0
  156. package/dist/comics/paint.d.ts +65 -0
  157. package/dist/comics/paint.d.ts.map +1 -0
  158. package/dist/comics/paint.js +219 -0
  159. package/dist/comics/paint.js.map +1 -0
  160. package/dist/comics/script.d.ts +42 -0
  161. package/dist/comics/script.d.ts.map +1 -0
  162. package/dist/comics/script.js +302 -0
  163. package/dist/comics/script.js.map +1 -0
  164. package/dist/comics/split.d.ts +135 -0
  165. package/dist/comics/split.d.ts.map +1 -0
  166. package/dist/comics/split.js +514 -0
  167. package/dist/comics/split.js.map +1 -0
  168. package/dist/comics/spread.d.ts +36 -0
  169. package/dist/comics/spread.d.ts.map +1 -0
  170. package/dist/comics/spread.js +172 -0
  171. package/dist/comics/spread.js.map +1 -0
  172. package/dist/comics/strip.d.ts +77 -0
  173. package/dist/comics/strip.d.ts.map +1 -0
  174. package/dist/comics/strip.js +89 -0
  175. package/dist/comics/strip.js.map +1 -0
  176. package/dist/comics/transform.d.ts +37 -0
  177. package/dist/comics/transform.d.ts.map +1 -0
  178. package/dist/comics/transform.js +161 -0
  179. package/dist/comics/transform.js.map +1 -0
  180. package/dist/comics/types.d.ts +143 -0
  181. package/dist/comics/types.d.ts.map +1 -0
  182. package/dist/comics/types.js +13 -0
  183. package/dist/comics/types.js.map +1 -0
  184. package/dist/comics/warnings.d.ts +14 -0
  185. package/dist/comics/warnings.d.ts.map +1 -0
  186. package/dist/comics/warnings.js +94 -0
  187. package/dist/comics/warnings.js.map +1 -0
  188. package/dist/configWarnings.d.ts.map +1 -1
  189. package/dist/configWarnings.js +42 -0
  190. package/dist/configWarnings.js.map +1 -1
  191. package/dist/defaults/comics.d.ts +51 -0
  192. package/dist/defaults/comics.d.ts.map +1 -0
  193. package/dist/defaults/comics.js +385 -0
  194. package/dist/defaults/comics.js.map +1 -0
  195. package/dist/defaults/index.d.ts +1 -0
  196. package/dist/defaults/index.d.ts.map +1 -1
  197. package/dist/defaults/index.js +9 -0
  198. package/dist/defaults/index.js.map +1 -1
  199. package/dist/design/layout.d.ts +13 -1
  200. package/dist/design/layout.d.ts.map +1 -1
  201. package/dist/design/layout.js +17 -0
  202. package/dist/design/layout.js.map +1 -1
  203. package/dist/html-backend.d.ts +3 -0
  204. package/dist/html-backend.d.ts.map +1 -1
  205. package/dist/html-backend.js +44 -8
  206. package/dist/html-backend.js.map +1 -1
  207. package/dist/htmlComic.d.ts +69 -0
  208. package/dist/htmlComic.d.ts.map +1 -0
  209. package/dist/htmlComic.js +179 -0
  210. package/dist/htmlComic.js.map +1 -0
  211. package/dist/index.d.ts +8 -2
  212. package/dist/index.d.ts.map +1 -1
  213. package/dist/index.js +4 -0
  214. package/dist/index.js.map +1 -1
  215. package/dist/parse/blockParser.d.ts.map +1 -1
  216. package/dist/parse/blockParser.js +25 -1
  217. package/dist/parse/blockParser.js.map +1 -1
  218. package/dist/parse/indexMarks.d.ts.map +1 -1
  219. package/dist/parse/indexMarks.js +3 -0
  220. package/dist/parse/indexMarks.js.map +1 -1
  221. package/dist/parse/types.d.ts +7 -1
  222. package/dist/parse/types.d.ts.map +1 -1
  223. package/dist/pipeline/build.d.ts.map +1 -1
  224. package/dist/pipeline/build.js +251 -9
  225. package/dist/pipeline/build.js.map +1 -1
  226. package/dist/pipeline/config.d.ts.map +1 -1
  227. package/dist/pipeline/config.js +4 -1
  228. package/dist/pipeline/config.js.map +1 -1
  229. package/dist/pipeline/contentWarnings.d.ts.map +1 -1
  230. package/dist/pipeline/contentWarnings.js +58 -0
  231. package/dist/pipeline/contentWarnings.js.map +1 -1
  232. package/dist/pipeline/floatSlots.js +1 -1
  233. package/dist/pipeline/floatSlots.js.map +1 -1
  234. package/dist/pipeline/headerFooter.d.ts +6 -2
  235. package/dist/pipeline/headerFooter.d.ts.map +1 -1
  236. package/dist/pipeline/headerFooter.js +11 -3
  237. package/dist/pipeline/headerFooter.js.map +1 -1
  238. package/dist/pipeline/pageRoles.d.ts +1 -0
  239. package/dist/pipeline/pageRoles.d.ts.map +1 -1
  240. package/dist/pipeline/pageRoles.js +3 -0
  241. package/dist/pipeline/pageRoles.js.map +1 -1
  242. package/dist/pipeline/placement.d.ts +3 -3
  243. package/dist/pipeline/placement.d.ts.map +1 -1
  244. package/dist/pipeline/placement.js +4 -4
  245. package/dist/pipeline/placement.js.map +1 -1
  246. package/dist/types.d.ts +338 -1
  247. package/dist/types.d.ts.map +1 -1
  248. package/dist/vdt.d.ts +271 -2
  249. package/dist/vdt.d.ts.map +1 -1
  250. package/dist/vdt.js.map +1 -1
  251. package/dist/worker/fonts.d.ts +2 -1
  252. package/dist/worker/fonts.d.ts.map +1 -1
  253. package/dist/worker/fonts.js +11 -1
  254. package/dist/worker/fonts.js.map +1 -1
  255. package/package.json +1 -1
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=art.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"art.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/comics/art.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,96 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { anchorsOutsideSafeArea, comicArtCrop, comicArtPointToPage, comicCropFeasibleRange } from '../../comics/art';
3
+ import { pointInPolygon } from '../../comics/geometry';
4
+ const r = (n) => Math.round(n * 1000) / 1000;
5
+ const cellRect = (cell) => [
6
+ { x: cell.x, y: cell.y },
7
+ { x: cell.x + cell.width, y: cell.y },
8
+ { x: cell.x + cell.width, y: cell.y + cell.height },
9
+ { x: cell.x, y: cell.y + cell.height },
10
+ ];
11
+ describe('comicArtCrop', () => {
12
+ // A 3:1 panorama, its subject left of centre.
13
+ const wide = { width: 3000, height: 1000, safeArea: { x: 0.2, y: 0, width: 0.4, height: 1 } };
14
+ it('covers the cell and keeps the safe area, the margins cropped in proportion', () => {
15
+ const cell = { x: 0, y: 0, width: 600, height: 400 };
16
+ const crop = comicArtCrop({ ...wide, cell, fit: 'cover' });
17
+ expect(crop.letterbox).toBe(false);
18
+ expect(crop.fallback).toBe(false);
19
+ // The window is 1.5 / 3 = half the width, the whole height.
20
+ expect(r(crop.source.width)).toBe(0.5);
21
+ expect(r(crop.source.height)).toBe(1);
22
+ // Safe area [0.2, 0.6] inside, margins 0.2 and 0.4 cut in proportion.
23
+ expect(crop.source.x).toBeLessThanOrEqual(0.2);
24
+ expect(crop.source.x + crop.source.width).toBeGreaterThanOrEqual(0.6);
25
+ expect(r(crop.source.x)).toBe(r((0.2 * 0.5) / 0.6));
26
+ // The whole picture is drawn twice the cell's width.
27
+ expect(r(crop.box.width)).toBe(1200);
28
+ expect(r(crop.box.height)).toBe(400);
29
+ expect(r(crop.box.x)).toBe(r(-crop.source.x * 1200));
30
+ });
31
+ it('centres the window on the focus while the safe area allows', () => {
32
+ const cell = { x: 0, y: 0, width: 600, height: 400 };
33
+ const centred = comicArtCrop({ width: 3000, height: 1000, cell, fit: 'cover', focus: { x: 0.7, y: 0.5 } });
34
+ expect(r(centred.source.x)).toBe(0.45);
35
+ // The safe area wins over the focus.
36
+ const kept = comicArtCrop({ ...wide, cell, fit: 'cover', focus: { x: 0.9, y: 0.5 } });
37
+ expect(kept.source.x).toBeLessThanOrEqual(0.2 + 1e-9);
38
+ // No safe area and no focus: centred.
39
+ expect(r(comicArtCrop({ width: 3000, height: 1000, cell, fit: 'cover' }).source.x)).toBe(0.25);
40
+ });
41
+ it('letterboxes when the cell cannot hold the safe area under a cover crop', () => {
42
+ // A tall cell: a cover window would be 0.1 of the width, the safe area
43
+ // needs 0.4 of it.
44
+ const cell = { x: 0, y: 0, width: 100, height: 333.3333 };
45
+ const crop = comicArtCrop({ ...wide, cell, fit: 'cover' });
46
+ expect(crop.fallback).toBe(true);
47
+ expect(crop.letterbox).toBe(true);
48
+ expect(r(crop.source.x)).toBe(0.2);
49
+ expect(r(crop.source.width)).toBe(0.4);
50
+ expect(r(crop.source.height)).toBe(1);
51
+ // The picture is drawn narrower than the cell is tall: bands above and
52
+ // below, the safe area spanning the cell's width.
53
+ expect(r(crop.box.width)).toBe(250);
54
+ expect(crop.box.height).toBeLessThan(cell.height);
55
+ expect(r(crop.box.y + crop.box.height / 2)).toBe(r(cell.height / 2));
56
+ // Feasible ratios: 0.4·3 = 1.2 down to … 3/1.
57
+ expect(comicCropFeasibleRange(3000, 1000, wide.safeArea)).toEqual({ min: 1.2000000000000002, max: 3 });
58
+ });
59
+ it('contains: the whole picture, always letterboxed', () => {
60
+ const cell = { x: 10, y: 20, width: 400, height: 400 };
61
+ const crop = comicArtCrop({ width: 2000, height: 1000, cell, fit: 'contain' });
62
+ expect(crop.source).toEqual({ x: 0, y: 0, width: 1, height: 1 });
63
+ expect(crop.letterbox).toBe(true);
64
+ expect(crop.fallback).toBe(false);
65
+ expect([crop.box.x, crop.box.y, crop.box.width, crop.box.height].map(r)).toEqual([10, 120, 400, 200]);
66
+ });
67
+ it('reads the safe area flipped for mirrored art, and reports the source unflipped', () => {
68
+ const cell = { x: 0, y: 0, width: 600, height: 400 };
69
+ const plain = comicArtCrop({ ...wide, cell, fit: 'cover' });
70
+ const mirrored = comicArtCrop({ ...wide, cell, fit: 'cover', mirrored: true });
71
+ // The same part of the stored picture shows.
72
+ expect(r(mirrored.source.x)).toBe(r(plain.source.x));
73
+ expect(r(mirrored.source.width)).toBe(r(plain.source.width));
74
+ // On the page the subject is on the other side.
75
+ expect(r(mirrored.box.x)).toBe(r(600 - (plain.box.x + plain.box.width)));
76
+ });
77
+ });
78
+ describe('anchors', () => {
79
+ it('maps a picture point to the page, flipped for mirrored art, and tests visibility', () => {
80
+ const cell = { x: 100, y: 100, width: 600, height: 400 };
81
+ const crop = comicArtCrop({ width: 3000, height: 1000, cell, fit: 'cover' });
82
+ const art = { box: crop.box, mirrored: false };
83
+ const centre = comicArtPointToPage(art, 0.5, 0.5);
84
+ expect([r(centre.x), r(centre.y)]).toEqual([400, 300]);
85
+ const edge = comicArtPointToPage(art, 0.05, 0.5);
86
+ expect(pointInPolygon(cellRect(cell), edge)).toBe(false);
87
+ const flipped = comicArtPointToPage({ box: crop.box, mirrored: true }, 0.3, 0.5);
88
+ expect(r(flipped.x)).toBe(r(crop.box.x + 0.7 * crop.box.width));
89
+ });
90
+ it('lists the anchors outside the safe area', () => {
91
+ const anchors = [{ id: 'ana', x: 0.1, y: 0.5 }, { id: 'ben', x: 0.5, y: 0.5 }];
92
+ expect(anchorsOutsideSafeArea(anchors, { x: 0.2, y: 0, width: 0.6, height: 1 }).map((a) => a.id)).toEqual(['ana']);
93
+ expect(anchorsOutsideSafeArea(anchors, undefined)).toEqual([]);
94
+ });
95
+ });
96
+ //# sourceMappingURL=art.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"art.test.js","sourceRoot":"","sources":["../../../src/__tests__/comics/art.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,sBAAsB,EAAE,YAAY,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AACrH,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD,MAAM,CAAC,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;AACrD,MAAM,QAAQ,GAAG,CAAC,IAA6D,EAAE,EAAE,CAAC;IAClF,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE;IACxB,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE;IACrC,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE;IACnD,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE;CACvC,CAAC;AAEF,QAAQ,CAAC,cAAc,EAAE,GAAG,EAAE;IAC5B,8CAA8C;IAC9C,MAAM,IAAI,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;IAE9F,EAAE,CAAC,4EAA4E,EAAE,GAAG,EAAE;QACpF,MAAM,IAAI,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;QACrD,MAAM,IAAI,GAAG,YAAY,CAAC,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC;QAC3D,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACnC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAClC,4DAA4D;QAC5D,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACvC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACtC,sEAAsE;QACtE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,mBAAmB,CAAC,GAAG,CAAC,CAAC;QAC/C,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,sBAAsB,CAAC,GAAG,CAAC,CAAC;QACtE,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;QACpD,qDAAqD;QACrD,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACrC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4DAA4D,EAAE,GAAG,EAAE;QACpE,MAAM,IAAI,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;QACrD,MAAM,OAAO,GAAG,YAAY,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;QAC3G,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACvC,qCAAqC;QACrC,MAAM,IAAI,GAAG,YAAY,CAAC,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;QACtF,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,mBAAmB,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC;QACtD,sCAAsC;QACtC,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACjG,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wEAAwE,EAAE,GAAG,EAAE;QAChF,uEAAuE;QACvE,mBAAmB;QACnB,MAAM,IAAI,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;QAC1D,MAAM,IAAI,GAAG,YAAY,CAAC,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC;QAC3D,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACnC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACvC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACtC,uEAAuE;QACvE,kDAAkD;QAClD,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACpC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAClD,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;QACrE,8CAA8C;QAC9C,MAAM,CAAC,sBAAsB,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,kBAAkB,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;IACzG,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iDAAiD,EAAE,GAAG,EAAE;QACzD,MAAM,IAAI,GAAG,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;QACvD,MAAM,IAAI,GAAG,YAAY,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC;QAC/E,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC;QACjE,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAClC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;IACxG,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gFAAgF,EAAE,GAAG,EAAE;QACxF,MAAM,IAAI,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;QACrD,MAAM,KAAK,GAAG,YAAY,CAAC,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC;QAC5D,MAAM,QAAQ,GAAG,YAAY,CAAC,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;QAC/E,6CAA6C;QAC7C,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QACrD,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QAC7D,gDAAgD;QAChD,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC3E,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,SAAS,EAAE,GAAG,EAAE;IACvB,EAAE,CAAC,kFAAkF,EAAE,GAAG,EAAE;QAC1F,MAAM,IAAI,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;QACzD,MAAM,IAAI,GAAG,YAAY,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC;QAC7E,MAAM,GAAG,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;QAC/C,MAAM,MAAM,GAAG,mBAAmB,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;QAClD,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;QACvD,MAAM,IAAI,GAAG,mBAAmB,CAAC,GAAG,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;QACjD,MAAM,CAAC,cAAc,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACzD,MAAM,OAAO,GAAG,mBAAmB,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;QACjF,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;IAClE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;QACjD,MAAM,OAAO,GAAG,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;QAC/E,MAAM,CAAC,sBAAsB,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;QACnH,MAAM,CAAC,sBAAsB,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACjE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=build.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/comics/build.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,215 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { buildDocument } from '../../pipeline';
3
+ // Deterministic text measurement stub (no DOM in the node test env).
4
+ class StubCtx {
5
+ font = '';
6
+ measureText(s) {
7
+ return { width: s.length * 7 };
8
+ }
9
+ }
10
+ globalThis.OffscreenCanvas = class {
11
+ getContext() {
12
+ return new StubCtx();
13
+ }
14
+ };
15
+ const picture = (id, width, height, extra = {}) => ({
16
+ id,
17
+ typeId: 'figure',
18
+ kind: 'bitmap',
19
+ createdAt: 0,
20
+ updatedAt: 0,
21
+ bitmap: { fileId: `file-${id}`, format: 'png', width, height },
22
+ ...extra,
23
+ });
24
+ const resources = [
25
+ picture('p1-wide', 3000, 1000, { safeArea: { x: 0.3, y: 0, width: 0.4, height: 1 } }),
26
+ picture('p1-door', 1000, 1500),
27
+ picture('p1-ana', 1000, 1000, { anchors: [{ id: 'ana', x: 0.05, y: 0.5 }], safeArea: { x: 0.2, y: 0.2, width: 0.6, height: 0.6 } }),
28
+ picture('p1-street', 2000, 1000),
29
+ ];
30
+ const markdown = `---
31
+ title: Comic
32
+ ---
33
+ # Chapter
34
+
35
+ Some text before the comic.
36
+
37
+ :::page{split="30 [30 | 20 | *] / *" gutter=4mm}
38
+ ::panel{art=p1-wide}
39
+ caption: Lyon, 1943.
40
+ ana: Did you hear that?
41
+ ::panel{art=p1-door focus="70% 40%"}
42
+ sfx{at="62% 40%" rotate=-8}: KRAK
43
+ ::panel{art=p1-ana}
44
+ ana{thought}: Nothing, he says…
45
+ ::panel{art=p1-street bleed}
46
+ caption{at=bottom-end}: Three streets away.
47
+ :::
48
+
49
+ :::page{split="* [40~55 | *] / 35"}
50
+ ::panel{art=p1-door}
51
+ ben: Run!
52
+ ::panel{art=missing}
53
+ ::panel{art=p1-street}
54
+ :::
55
+
56
+ Text after the comic pages.
57
+ `;
58
+ describe('comic pages in the build', () => {
59
+ const config = { page: { sizePreset: '17x24' } };
60
+ it('gives each :::page a page of its own, with its panels and split lines', () => {
61
+ const doc = buildDocument({ markdown, resources }, config);
62
+ const comics = doc.pages.filter((p) => p.comic);
63
+ expect(comics).toHaveLength(2);
64
+ const [a, b] = comics;
65
+ expect(b.index).toBe(a.index + 1);
66
+ // Text before and after: on pages of their own.
67
+ expect(a.index).toBeGreaterThan(0);
68
+ expect(doc.pages.length).toBe(b.index + 2);
69
+ expect(doc.pages[b.index + 1].columns.some((c) => c.blocks.length > 0)).toBe(true);
70
+ for (const p of comics) {
71
+ expect(p.role).toBe('comic');
72
+ expect(p.columns.every((c) => c.blocks.length === 0)).toBe(true);
73
+ expect(p.header).toBeUndefined();
74
+ expect(p.footer).toBeUndefined();
75
+ }
76
+ expect(a.comic.panels.map((p) => p.art?.resourceId)).toEqual(['p1-wide', 'p1-door', 'p1-ana', 'p1-street']);
77
+ expect(a.comic.splitters).toHaveLength(3);
78
+ expect(a.comic.splitters.map((s) => [s.path, s.boundary, s.axis])).toEqual([
79
+ [[], 0, 'rows'],
80
+ [[0], 0, 'columns'],
81
+ [[0], 1, 'columns'],
82
+ ]);
83
+ // The split value's source range, in the whole markdown.
84
+ const s0 = a.comic.splitters[0];
85
+ expect(markdown.slice(s0.sourceStart, s0.sourceEnd)).toBe('30 [30 | 20 | *] / *');
86
+ expect(markdown.slice(a.comic.sourceStart, a.comic.sourceStart + 7)).toBe(':::page');
87
+ // Lettered: one balloon per script line, in reading order.
88
+ expect(a.comic.balloons.map((b) => b.style)).toEqual(['caption', 'speech', 'sfx', 'thought', 'caption']);
89
+ // The last panel bleeds: past the frame to the trim (no cut lines).
90
+ const last = a.comic.panels[3];
91
+ expect(last.bbox.y + last.bbox.height).toBeCloseTo(doc.pages[0].height, 3);
92
+ expect(last.bbox.x).toBeCloseTo(0, 3);
93
+ // Second page: slanted line, missing art set empty.
94
+ expect(b.comic.panels).toHaveLength(3);
95
+ expect(b.comic.panels[1].art).toBeUndefined();
96
+ expect(b.comic.panels[0].polygon.length).toBe(4);
97
+ expect(b.comic.panels[0].radius).toBe(0);
98
+ });
99
+ it('reports the comic warnings on their page', () => {
100
+ const doc = buildDocument({ markdown, resources }, config);
101
+ const kinds = (doc.contentWarnings ?? []).map((w) => w.kind);
102
+ expect(kinds).toContain('comicUnknownArt');
103
+ expect(kinds).toContain('comicAnchorOutsideSafeArea');
104
+ const unknown = doc.contentWarnings.find((w) => w.kind === 'comicUnknownArt');
105
+ expect(unknown.pageIndex).toBe(doc.pages.findIndex((p) => p.comic) + 1);
106
+ });
107
+ it('keeps running heads on comic pages when the config asks', () => {
108
+ // The default footer prints the folio on every other page.
109
+ const before = buildDocument({ markdown, resources }, config);
110
+ expect(before.pages.find((p) => !p.comic).footer).toBeDefined();
111
+ const doc = buildDocument({ markdown, resources }, { ...config, comics: { runningHeads: true } });
112
+ const page = doc.pages.find((p) => p.comic);
113
+ expect(page.footer).toBeDefined();
114
+ // Comic pages count in the numbering either way.
115
+ expect(page.pageLabel).toBe(String(page.index + 1));
116
+ });
117
+ it('leaves no empty page after a comic page that ends the document', () => {
118
+ const md = 'Text.\n\n:::page\n::panel\nana: Hi\n:::\n';
119
+ const doc = buildDocument({ markdown: md, resources }, config);
120
+ expect(doc.pages).toHaveLength(2);
121
+ expect(doc.pages[1].comic).toBeDefined();
122
+ // A comic page first: it takes page 1.
123
+ const first = buildDocument({ markdown: ':::page\n::panel\n:::\n\nText.', resources }, config);
124
+ expect(first.pages[0].comic).toBeDefined();
125
+ expect(first.pages).toHaveLength(2);
126
+ // A page break between two comic pages opens no blank page.
127
+ const two = buildDocument({ markdown: ':::page\n::panel\n:::\n\n:::pagebreak\n\n:::page\n::panel\n:::', resources }, config);
128
+ expect(two.pages.map((p) => p.role)).toEqual(['comic', 'comic']);
129
+ });
130
+ it('stacks the panels of a page without a split in equal tiers', () => {
131
+ const doc = buildDocument({ markdown: ':::page{gutter=0}\n::panel\n::panel\n::panel\n:::', resources }, config);
132
+ const comic = doc.pages[0].comic;
133
+ expect(comic.panels).toHaveLength(3);
134
+ const h = comic.frame.height / 3;
135
+ comic.panels.forEach((p, i) => expect(p.bbox.y).toBeCloseTo(comic.frame.y + i * h, 3));
136
+ // The splitters point at where a split attribute would go.
137
+ expect(comic.splitters).toHaveLength(2);
138
+ expect(comic.splitters[0].sourceStart).toBe(comic.splitters[0].sourceEnd);
139
+ });
140
+ it('reads the panels from the right in a right-to-left document, and mirrors art when asked', () => {
141
+ const md = ':::page{split="* [30 | *]"}\n::panel{art=p1-door}\n::panel{art=p1-ana mirror=false}\n:::';
142
+ const ltr = buildDocument({ markdown: md, resources }, config).pages[0].comic;
143
+ const rtl = buildDocument({ markdown: md, resources }, { ...config, locale: 'ar', comics: { mirrorArt: true } }).pages[0].comic;
144
+ expect(ltr.direction).toBe('ltr');
145
+ expect(rtl.direction).toBe('rtl');
146
+ expect(rtl.panels[0].bbox.x).toBeGreaterThan(rtl.panels[1].bbox.x);
147
+ expect(ltr.panels[0].bbox.x).toBeLessThan(ltr.panels[1].bbox.x);
148
+ expect(rtl.panels[0].art.mirrored).toBe(true);
149
+ expect(rtl.panels[1].art.mirrored).toBe(false);
150
+ expect(ltr.panels[0].art.mirrored).toBe(false);
151
+ });
152
+ it('pads a panel inside its cell and lays an inset panel over the one before', () => {
153
+ const md = ':::page{split="* [* | *]" gutter=0}\n::panel{pad="0 10%"}\n::panel\n::panel{inset="50% 50% 40% 40%"}\n:::';
154
+ const comic = buildDocument({ markdown: md, resources }, config).pages[0].comic;
155
+ expect(comic.panels).toHaveLength(3);
156
+ const half = comic.frame.width / 2;
157
+ expect(comic.panels[0].bbox.x).toBeCloseTo(comic.frame.x + half * 0.1, 3);
158
+ expect(comic.panels[0].bbox.width).toBeCloseTo(half * 0.8, 3);
159
+ const second = comic.panels[1];
160
+ const inset = comic.panels[2];
161
+ expect(inset.bbox.x).toBeCloseTo(second.bbox.x + second.bbox.width * 0.5, 3);
162
+ expect(inset.bbox.width).toBeCloseTo(second.bbox.width * 0.4, 3);
163
+ });
164
+ it('warns about the split, the panel count, stray text, styles and letterboxed panels', () => {
165
+ const md = [
166
+ 'Text.',
167
+ '',
168
+ ':::page{split="30 / 40 | *"}',
169
+ 'Stray.',
170
+ '::panel{art=p1-wide}',
171
+ 'ana{wisper}: Hi',
172
+ '::panel',
173
+ '::panel',
174
+ '::panel',
175
+ ':::',
176
+ '',
177
+ ':::page{split="* [10 | *]"}',
178
+ '::panel{art=p1-wide}',
179
+ '::panel',
180
+ ':::',
181
+ ].join('\n');
182
+ const doc = buildDocument({ markdown: md, resources }, config);
183
+ const warnings = doc.contentWarnings ?? [];
184
+ const kinds = warnings.map((w) => w.kind);
185
+ expect(kinds).toEqual(expect.arrayContaining(['comicSplitSyntax', 'comicPanelCount', 'comicStrayText', 'comicUnknownBalloonStyle', 'comicPanelLetterbox']));
186
+ const comicPages = doc.pages.filter((p) => p.comic).map((p) => p.index);
187
+ for (const w of warnings)
188
+ expect(comicPages).toContain(w.pageIndex);
189
+ const letterbox = warnings.find((w) => w.kind === 'comicPanelLetterbox');
190
+ expect(letterbox.pageIndex).toBe(comicPages[1]);
191
+ const stray = warnings.find((w) => w.kind === 'comicStrayText');
192
+ expect(md.slice(stray.sourceStart, stray.sourceEnd)).toBe('Stray.');
193
+ });
194
+ it('lays a comic page out on the sheet in a vertical document', () => {
195
+ const md = '本文。\n\n:::page{split="* [* | *]"}\n::panel\n::panel\nアナ:はい\n:::';
196
+ const doc = buildDocument({ markdown: md, resources }, { ...config, locale: 'ja', layout: { writingMode: 'vertical-rl' } });
197
+ const page = doc.pages.find((p) => p.comic);
198
+ const { frame } = page.comic;
199
+ // Inside the sheet, portrait like the page.
200
+ expect(frame.x).toBeGreaterThan(0);
201
+ expect(frame.x + frame.width).toBeLessThan(page.width);
202
+ expect(frame.y + frame.height).toBeLessThan(page.height);
203
+ expect(frame.height).toBeGreaterThan(frame.width);
204
+ // A Western comic in Japanese still reads left to right.
205
+ expect(page.comic.direction).toBe('ltr');
206
+ expect(page.comic.panels[0].bbox.x).toBeLessThan(page.comic.panels[1].bbox.x);
207
+ });
208
+ it('lays out a document without comics as before', () => {
209
+ const plain = '# Title\n\nOne paragraph.\n\n:::pagebreak\n\nAnother.\n';
210
+ const doc = buildDocument({ markdown: plain }, config);
211
+ expect(doc.pages.every((p) => p.comic === undefined && p.role !== 'comic')).toBe(true);
212
+ expect(doc.config.comics).toBeUndefined();
213
+ });
214
+ });
215
+ //# sourceMappingURL=build.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build.test.js","sourceRoot":"","sources":["../../../src/__tests__/comics/build.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=canvas.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canvas.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/comics/canvas.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,161 @@
1
+ import { describe, it, expect, afterEach } from 'vitest';
2
+ import { buildDocument, renderPageToCanvas, registerResourceImage, clearResourceImages, pageComics } from '../../index';
3
+ class StubCtx {
4
+ font = '';
5
+ measureText(s) {
6
+ return { width: s.length * 7 };
7
+ }
8
+ }
9
+ globalThis.OffscreenCanvas = class {
10
+ getContext() {
11
+ return new StubCtx();
12
+ }
13
+ };
14
+ /** A 2D context that logs the calls the panel painter makes. */
15
+ function recordingCanvas() {
16
+ const calls = [];
17
+ const logged = new Set(['clip', 'stroke', 'fill', 'fillText', 'strokeText', 'bezierCurveTo', 'rotate', 'drawImage', 'fillRect', 'scale', 'translate', 'arcTo', 'setLineDash']);
18
+ const ctx = new Proxy({}, {
19
+ get(target, key) {
20
+ if (typeof key === 'string' && logged.has(key)) {
21
+ return (...args) => {
22
+ calls.push(`${key}(${args.filter((a) => typeof a === 'number').map((a) => Math.round(a)).join(',')})`);
23
+ };
24
+ }
25
+ if (key === 'measureText')
26
+ return (s) => ({ width: s.length * 7 });
27
+ if (key in target)
28
+ return target[key];
29
+ return () => undefined;
30
+ },
31
+ set(target, key, value) {
32
+ if (key === 'lineWidth')
33
+ calls.push(`lineWidth=${Math.round(Number(value) * 100) / 100}`);
34
+ if (key === 'strokeStyle' || key === 'fillStyle')
35
+ calls.push(`${String(key)}=${String(value)}`);
36
+ target[key] = value;
37
+ return true;
38
+ },
39
+ });
40
+ const canvas = { width: 0, height: 0, getContext: () => ctx };
41
+ return { canvas, calls };
42
+ }
43
+ const resources = [
44
+ { id: 'pic', typeId: 'figure', kind: 'bitmap', createdAt: 0, updatedAt: 0, bitmap: { fileId: 'pic-file', format: 'png', width: 1000, height: 1000 } },
45
+ ];
46
+ afterEach(() => clearResourceImages());
47
+ describe('canvas painting of comic panels', () => {
48
+ it('fills, clips, draws the art and strokes the border of every panel, flipped when mirrored', () => {
49
+ registerResourceImage('pic-file', { width: 1000, height: 1000 });
50
+ const md = ':::page{split="50 / *"}\n::panel{art=pic bg="#ff0000"}\n::panel{art=pic mirror border=none}\n:::';
51
+ const doc = buildDocument({ markdown: md, resources }, {});
52
+ const page = doc.pages.find((p) => p.comic);
53
+ expect(page.comic.panels[1].art.mirrored).toBe(true);
54
+ const { canvas, calls } = recordingCanvas();
55
+ renderPageToCanvas(page, doc, canvas);
56
+ const at = (s, from = 0) => calls.findIndex((c, i) => i >= from && c.startsWith(s));
57
+ const red = at('fillStyle=#ff0000');
58
+ expect(red).toBeGreaterThan(-1);
59
+ const firstDraw = at('drawImage', red);
60
+ expect(firstDraw).toBeGreaterThan(red);
61
+ expect(at('stroke', firstDraw)).toBeGreaterThan(firstDraw);
62
+ // The second panel: a horizontal flip before its picture, no border.
63
+ const flip = calls.indexOf('scale(-1,1)');
64
+ expect(flip).toBeGreaterThan(firstDraw);
65
+ expect(at('drawImage', flip)).toBeGreaterThan(flip);
66
+ expect(calls.filter((c) => c === 'stroke()')).toHaveLength(1);
67
+ });
68
+ it('paints a strip set in the flow on the sheet, where its block sits', () => {
69
+ registerResourceImage('pic-file', { width: 1000, height: 1000 });
70
+ const md = 'Some text.\n\n:::strip{split="* | *"}\n::panel{art=pic bg="#00ff00"}\n::panel{art=pic}\n:::\n\nMore text.';
71
+ const doc = buildDocument({ markdown: md, resources }, {});
72
+ const page = doc.pages[0];
73
+ const block = page.columns[0].blocks.find((b) => b.comic);
74
+ const onSheet = pageComics(page)[0];
75
+ const { canvas, calls } = recordingCanvas();
76
+ renderPageToCanvas(page, doc, canvas);
77
+ const green = calls.indexOf('fillStyle=#00ff00');
78
+ expect(green).toBeGreaterThan(-1);
79
+ // Both pictures drawn at their box on the sheet (the block's place
80
+ // added to the strip's own coordinates).
81
+ const draws = calls.filter((c) => c.startsWith('drawImage'));
82
+ expect(draws).toHaveLength(2);
83
+ const box = onSheet.panels[0].art.box;
84
+ expect(box.y).toBeCloseTo(block.comic.panels[0].art.box.y + block.bbox.y, 3);
85
+ expect(draws[0]).toContain(`${Math.round(box.x)},${Math.round(box.y)}`);
86
+ expect(calls.filter((c) => c === 'stroke()')).toHaveLength(2);
87
+ });
88
+ it('paints each page of a spread with its half, a panel across the spine on both', () => {
89
+ registerResourceImage('pic-file', { width: 1000, height: 1000 });
90
+ const md = ':::page{spread split="*"}\n::panel{art=pic}\n:::';
91
+ const doc = buildDocument({ markdown: md, resources }, {});
92
+ const [left, right] = doc.pages.filter((p) => p.comic);
93
+ for (const page of [left, right]) {
94
+ const { canvas, calls } = recordingCanvas();
95
+ renderPageToCanvas(page, doc, canvas);
96
+ expect(calls.filter((c) => c.startsWith('clip'))).not.toHaveLength(0);
97
+ expect(calls.filter((c) => c.startsWith('drawImage'))).toHaveLength(1);
98
+ expect(calls.filter((c) => c === 'stroke()')).toHaveLength(1);
99
+ }
100
+ // The right page draws the same picture a page's width to the left.
101
+ const l = left.comic.panels[0].art.box;
102
+ const r = right.comic.panels[0].art.box;
103
+ expect(l.x - r.x).toBeCloseTo(left.width - 2 * doc.trimOffset, 3);
104
+ });
105
+ it('draws rough borders and rounded corners', () => {
106
+ const md = ':::page{split="*"}\n::panel{style=sketch}\n:::';
107
+ const config = { comics: { panelStyles: [{ id: 'sketch', borderStyle: 'rough', borderRadius: { value: 3, unit: 'mm' } }] } };
108
+ const doc = buildDocument({ markdown: md, resources }, config);
109
+ const page = doc.pages.find((p) => p.comic);
110
+ expect(page.comic.panels[0].radius).toBeGreaterThan(0);
111
+ expect(page.comic.panels[0].border.style).toBe('rough');
112
+ const { canvas, calls } = recordingCanvas();
113
+ renderPageToCanvas(page, doc, canvas);
114
+ expect(calls.some((c) => c.startsWith('arcTo'))).toBe(true);
115
+ expect(calls.filter((c) => c === 'stroke()')).toHaveLength(1);
116
+ });
117
+ it('draws a whisper\'s dashes over a band of the balloon\'s ground', () => {
118
+ const md = ':::page\n::panel{art=pic}\nana{whisper}: Psst.\n:::';
119
+ const doc = buildDocument({ markdown: md, resources }, { comics: { balloonStyles: [{ id: 'whisper', stroke: { hex: '#123456', model: 'hex' }, fill: { hex: '#fefefe', model: 'hex' } }] } });
120
+ const page = doc.pages.find((p) => p.comic);
121
+ const w = page.comic.balloons[0].shape.strokeWidth;
122
+ const { canvas, calls } = recordingCanvas();
123
+ renderPageToCanvas(page, doc, canvas);
124
+ const band = calls.indexOf(`lineWidth=${Math.round(3 * w * 100) / 100}`);
125
+ // (The recorder logs number arguments only: the pattern shows as ().)
126
+ const dash = calls.indexOf('setLineDash()', band);
127
+ expect(band).toBeGreaterThan(-1);
128
+ expect(calls.lastIndexOf('strokeStyle=#fefefe', band)).toBeGreaterThan(-1);
129
+ expect(dash).toBeGreaterThan(band);
130
+ });
131
+ it('paints the lettering after the panels: each outline stroked at twice its width, then filled, then its text; sound effects last, turned', () => {
132
+ const md = ':::page\n::panel{art=pic}\nsfx{rotate=-10}: BAM\nana: Hello there.\nana: And again.\n:::';
133
+ const doc = buildDocument({ markdown: md, resources }, { comics: { balloonStyles: [{ id: 'speech', stroke: { hex: '#123456', model: 'hex' }, fill: { hex: '#fefefe', model: 'hex' } }] } });
134
+ const page = doc.pages.find((p) => p.comic);
135
+ const balloons = page.comic.balloons;
136
+ expect(balloons.map((b) => b.kind)).toEqual(['sfx', 'balloon', 'balloon']);
137
+ const { canvas, calls } = recordingCanvas();
138
+ renderPageToCanvas(page, doc, canvas);
139
+ const width = balloons[1].shape.strokeWidth;
140
+ const outline = calls.indexOf('strokeStyle=#123456');
141
+ // After the panel (clipped to its outline).
142
+ expect(outline).toBeGreaterThan(calls.findIndex((c) => c.startsWith('clip')));
143
+ const doubled = calls.indexOf(`lineWidth=${Math.round(2 * width * 100) / 100}`, outline);
144
+ const stroke = calls.indexOf('stroke()', outline);
145
+ const fill = calls.indexOf('fillStyle=#fefefe', stroke);
146
+ const fillCall = calls.indexOf('fill()', fill);
147
+ const text = calls.findIndex((c, i) => i > fillCall && c.startsWith('fillText'));
148
+ expect(doubled).toBeGreaterThan(outline);
149
+ expect(stroke).toBeGreaterThan(doubled);
150
+ expect(fillCall).toBeGreaterThan(fill);
151
+ expect(text).toBeGreaterThan(fillCall);
152
+ // One outline for the joined pair: a single doubled stroke in that colour.
153
+ expect(calls.filter((c) => c === 'strokeStyle=#123456')).toHaveLength(1);
154
+ // The sound effect after the balloons, turned about its centre, its
155
+ // halo stroked under its letters.
156
+ const turn = calls.findIndex((c) => c.startsWith('rotate'));
157
+ expect(turn).toBeGreaterThan(text);
158
+ expect(calls.findIndex((c, i) => i > turn && c.startsWith('strokeText'))).toBeGreaterThan(turn);
159
+ });
160
+ });
161
+ //# sourceMappingURL=canvas.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canvas.test.js","sourceRoot":"","sources":["../../../src/__tests__/comics/canvas.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=config.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/comics/config.test.ts"],"names":[],"mappings":""}