postext 1.19.2 → 1.20.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 (251) 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 +697 -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__/shapeText.test.d.ts +2 -0
  97. package/dist/comics/lettering/__tests__/shapeText.test.d.ts.map +1 -0
  98. package/dist/comics/lettering/__tests__/shapeText.test.js +98 -0
  99. package/dist/comics/lettering/__tests__/shapeText.test.js.map +1 -0
  100. package/dist/comics/lettering/__tests__/shapes.test.d.ts +2 -0
  101. package/dist/comics/lettering/__tests__/shapes.test.d.ts.map +1 -0
  102. package/dist/comics/lettering/__tests__/shapes.test.js +137 -0
  103. package/dist/comics/lettering/__tests__/shapes.test.js.map +1 -0
  104. package/dist/comics/lettering/__tests__/stubMeasure.d.ts +5 -0
  105. package/dist/comics/lettering/__tests__/stubMeasure.d.ts.map +1 -0
  106. package/dist/comics/lettering/__tests__/stubMeasure.js +47 -0
  107. package/dist/comics/lettering/__tests__/stubMeasure.js.map +1 -0
  108. package/dist/comics/lettering/__tests__/text.test.d.ts +2 -0
  109. package/dist/comics/lettering/__tests__/text.test.d.ts.map +1 -0
  110. package/dist/comics/lettering/__tests__/text.test.js +86 -0
  111. package/dist/comics/lettering/__tests__/text.test.js.map +1 -0
  112. package/dist/comics/lettering/geom.d.ts +78 -0
  113. package/dist/comics/lettering/geom.d.ts.map +1 -0
  114. package/dist/comics/lettering/geom.js +376 -0
  115. package/dist/comics/lettering/geom.js.map +1 -0
  116. package/dist/comics/lettering/index.d.ts +7 -0
  117. package/dist/comics/lettering/index.d.ts.map +1 -0
  118. package/dist/comics/lettering/index.js +8 -0
  119. package/dist/comics/lettering/index.js.map +1 -0
  120. package/dist/comics/lettering/letter.d.ts +7 -0
  121. package/dist/comics/lettering/letter.d.ts.map +1 -0
  122. package/dist/comics/lettering/letter.js +397 -0
  123. package/dist/comics/lettering/letter.js.map +1 -0
  124. package/dist/comics/lettering/placement.d.ts +117 -0
  125. package/dist/comics/lettering/placement.d.ts.map +1 -0
  126. package/dist/comics/lettering/placement.js +889 -0
  127. package/dist/comics/lettering/placement.js.map +1 -0
  128. package/dist/comics/lettering/presets.d.ts +15 -0
  129. package/dist/comics/lettering/presets.d.ts.map +1 -0
  130. package/dist/comics/lettering/presets.js +61 -0
  131. package/dist/comics/lettering/presets.js.map +1 -0
  132. package/dist/comics/lettering/shape-text.d.ts +72 -0
  133. package/dist/comics/lettering/shape-text.d.ts.map +1 -0
  134. package/dist/comics/lettering/shape-text.js +550 -0
  135. package/dist/comics/lettering/shape-text.js.map +1 -0
  136. package/dist/comics/lettering/shapes.d.ts +83 -0
  137. package/dist/comics/lettering/shapes.d.ts.map +1 -0
  138. package/dist/comics/lettering/shapes.js +512 -0
  139. package/dist/comics/lettering/shapes.js.map +1 -0
  140. package/dist/comics/lettering/text.d.ts +79 -0
  141. package/dist/comics/lettering/text.d.ts.map +1 -0
  142. package/dist/comics/lettering/text.js +488 -0
  143. package/dist/comics/lettering/text.js.map +1 -0
  144. package/dist/comics/lettering/types.d.ts +270 -0
  145. package/dist/comics/lettering/types.d.ts.map +1 -0
  146. package/dist/comics/lettering/types.js +9 -0
  147. package/dist/comics/lettering/types.js.map +1 -0
  148. package/dist/comics/page.d.ts +37 -0
  149. package/dist/comics/page.d.ts.map +1 -0
  150. package/dist/comics/page.js +285 -0
  151. package/dist/comics/page.js.map +1 -0
  152. package/dist/comics/paint.d.ts +65 -0
  153. package/dist/comics/paint.d.ts.map +1 -0
  154. package/dist/comics/paint.js +219 -0
  155. package/dist/comics/paint.js.map +1 -0
  156. package/dist/comics/script.d.ts +42 -0
  157. package/dist/comics/script.d.ts.map +1 -0
  158. package/dist/comics/script.js +302 -0
  159. package/dist/comics/script.js.map +1 -0
  160. package/dist/comics/split.d.ts +135 -0
  161. package/dist/comics/split.d.ts.map +1 -0
  162. package/dist/comics/split.js +514 -0
  163. package/dist/comics/split.js.map +1 -0
  164. package/dist/comics/spread.d.ts +36 -0
  165. package/dist/comics/spread.d.ts.map +1 -0
  166. package/dist/comics/spread.js +172 -0
  167. package/dist/comics/spread.js.map +1 -0
  168. package/dist/comics/strip.d.ts +77 -0
  169. package/dist/comics/strip.d.ts.map +1 -0
  170. package/dist/comics/strip.js +89 -0
  171. package/dist/comics/strip.js.map +1 -0
  172. package/dist/comics/transform.d.ts +37 -0
  173. package/dist/comics/transform.d.ts.map +1 -0
  174. package/dist/comics/transform.js +161 -0
  175. package/dist/comics/transform.js.map +1 -0
  176. package/dist/comics/types.d.ts +143 -0
  177. package/dist/comics/types.d.ts.map +1 -0
  178. package/dist/comics/types.js +13 -0
  179. package/dist/comics/types.js.map +1 -0
  180. package/dist/comics/warnings.d.ts +14 -0
  181. package/dist/comics/warnings.d.ts.map +1 -0
  182. package/dist/comics/warnings.js +94 -0
  183. package/dist/comics/warnings.js.map +1 -0
  184. package/dist/configWarnings.d.ts.map +1 -1
  185. package/dist/configWarnings.js +42 -0
  186. package/dist/configWarnings.js.map +1 -1
  187. package/dist/defaults/comics.d.ts +51 -0
  188. package/dist/defaults/comics.d.ts.map +1 -0
  189. package/dist/defaults/comics.js +385 -0
  190. package/dist/defaults/comics.js.map +1 -0
  191. package/dist/defaults/index.d.ts +1 -0
  192. package/dist/defaults/index.d.ts.map +1 -1
  193. package/dist/defaults/index.js +9 -0
  194. package/dist/defaults/index.js.map +1 -1
  195. package/dist/design/layout.d.ts +13 -1
  196. package/dist/design/layout.d.ts.map +1 -1
  197. package/dist/design/layout.js +17 -0
  198. package/dist/design/layout.js.map +1 -1
  199. package/dist/html-backend.d.ts +3 -0
  200. package/dist/html-backend.d.ts.map +1 -1
  201. package/dist/html-backend.js +44 -8
  202. package/dist/html-backend.js.map +1 -1
  203. package/dist/htmlComic.d.ts +69 -0
  204. package/dist/htmlComic.d.ts.map +1 -0
  205. package/dist/htmlComic.js +179 -0
  206. package/dist/htmlComic.js.map +1 -0
  207. package/dist/index.d.ts +8 -2
  208. package/dist/index.d.ts.map +1 -1
  209. package/dist/index.js +4 -0
  210. package/dist/index.js.map +1 -1
  211. package/dist/parse/blockParser.d.ts.map +1 -1
  212. package/dist/parse/blockParser.js +25 -1
  213. package/dist/parse/blockParser.js.map +1 -1
  214. package/dist/parse/indexMarks.d.ts.map +1 -1
  215. package/dist/parse/indexMarks.js +3 -0
  216. package/dist/parse/indexMarks.js.map +1 -1
  217. package/dist/parse/types.d.ts +7 -1
  218. package/dist/parse/types.d.ts.map +1 -1
  219. package/dist/pipeline/build.d.ts.map +1 -1
  220. package/dist/pipeline/build.js +251 -9
  221. package/dist/pipeline/build.js.map +1 -1
  222. package/dist/pipeline/config.d.ts.map +1 -1
  223. package/dist/pipeline/config.js +4 -1
  224. package/dist/pipeline/config.js.map +1 -1
  225. package/dist/pipeline/contentWarnings.d.ts.map +1 -1
  226. package/dist/pipeline/contentWarnings.js +58 -0
  227. package/dist/pipeline/contentWarnings.js.map +1 -1
  228. package/dist/pipeline/floatSlots.js +1 -1
  229. package/dist/pipeline/floatSlots.js.map +1 -1
  230. package/dist/pipeline/headerFooter.d.ts +6 -2
  231. package/dist/pipeline/headerFooter.d.ts.map +1 -1
  232. package/dist/pipeline/headerFooter.js +11 -3
  233. package/dist/pipeline/headerFooter.js.map +1 -1
  234. package/dist/pipeline/pageRoles.d.ts +1 -0
  235. package/dist/pipeline/pageRoles.d.ts.map +1 -1
  236. package/dist/pipeline/pageRoles.js +3 -0
  237. package/dist/pipeline/pageRoles.js.map +1 -1
  238. package/dist/pipeline/placement.d.ts +3 -3
  239. package/dist/pipeline/placement.d.ts.map +1 -1
  240. package/dist/pipeline/placement.js +4 -4
  241. package/dist/pipeline/placement.js.map +1 -1
  242. package/dist/types.d.ts +338 -1
  243. package/dist/types.d.ts.map +1 -1
  244. package/dist/vdt.d.ts +271 -2
  245. package/dist/vdt.d.ts.map +1 -1
  246. package/dist/vdt.js.map +1 -1
  247. package/dist/worker/fonts.d.ts +2 -1
  248. package/dist/worker/fonts.d.ts.map +1 -1
  249. package/dist/worker/fonts.js +11 -1
  250. package/dist/worker/fonts.js.map +1 -1
  251. package/package.json +1 -1
@@ -0,0 +1,241 @@
1
+ import { describe, it, expect, beforeAll } from 'vitest';
2
+ import { buildDocument } from '../../pipeline';
3
+ import { installStubMeasure } from '../../comics/lettering/__tests__/stubMeasure';
4
+ import { comicArtPointToPage, pointInPolygon } from '../../comics';
5
+ // The lettering of comic pages in the build (#559–#561): balloons set from
6
+ // each panel's script around the speakers the pictures mark, in four
7
+ // languages.
8
+ beforeAll(() => installStubMeasure());
9
+ const picture = (id, width, height, extra = {}) => ({
10
+ id,
11
+ typeId: 'figure',
12
+ kind: 'bitmap',
13
+ createdAt: 0,
14
+ updatedAt: 0,
15
+ bitmap: { fileId: `file-${id}`, format: 'png', width, height },
16
+ ...extra,
17
+ });
18
+ // Two characters facing each other, mouths at a third and two thirds of
19
+ // the width, faces marked; a lamp to keep clear.
20
+ const resources = [
21
+ picture('room', 1600, 1000, {
22
+ anchors: [
23
+ { id: 'ana', x: 0.3, y: 0.62, head: { x: 0.3, y: 0.52 }, face: { x: 0.24, y: 0.5, width: 0.12, height: 0.18 } },
24
+ { id: 'ben', x: 0.7, y: 0.64, head: { x: 0.7, y: 0.54 }, face: { x: 0.64, y: 0.52, width: 0.12, height: 0.18 } },
25
+ ],
26
+ avoid: [{ x: 0.46, y: 0.3, width: 0.08, height: 0.5 }],
27
+ }),
28
+ picture('door', 1000, 1000, { anchors: [{ id: 'sfx', x: 0.5, y: 0.4 }, { id: 'ben', x: 0.8, y: 0.7 }] }),
29
+ ];
30
+ const scripts = {
31
+ en: { a1: 'Did you hear that?', b1: 'It is nothing. Go back to sleep.', a2: 'Nothing, he says…', cap: 'Lyon, 1943.', sfx: 'KRAK' },
32
+ es: { a1: '¿Has oído eso?', b1: 'No es nada. Vuelve a dormir.', a2: 'Nada, dice…', cap: 'Lyon, 1943.', sfx: 'CRAC' },
33
+ ja: { a1: '今の聞こえた?', b1: '何でもないよ。もう寝なさい。', a2: '何でもない、だって……', cap: '一九四三年、リヨン。', sfx: 'バキッ' },
34
+ ar: { a1: 'هل سمعت ذلك؟', b1: 'لا شيء. عودي إلى النوم.', a2: 'لا شيء، يقول…', cap: 'ليون، ١٩٤٣.', sfx: 'طاخ' },
35
+ };
36
+ const markdown = (s) => `:::page{split="60 / *"}
37
+ ::panel{art=room}
38
+ caption: ${s.cap}
39
+ ana: ${s.a1}
40
+ ben: ${s.b1}
41
+ ::panel{art=door}
42
+ sfx: ${s.sfx}
43
+ ben{whisper}: ${s.a2}
44
+ :::
45
+ `;
46
+ const config = (locale) => ({ page: { sizePreset: '17x24' }, locale });
47
+ function comicOf(doc) {
48
+ return doc.pages.find((p) => p.comic).comic;
49
+ }
50
+ const centre = (b) => ({ x: b.bbox.x + b.bbox.width / 2, y: b.bbox.y + b.bbox.height / 2 });
51
+ const dist = (a, b) => Math.hypot(a.x - b.x, a.y - b.y);
52
+ describe('comic lettering in the build', () => {
53
+ for (const locale of ['en', 'es', 'ja', 'ar']) {
54
+ describe(locale, () => {
55
+ const doc = () => buildDocument({ markdown: markdown(scripts[locale]), resources }, config(locale));
56
+ it('letters every script line once, in reading order, inside its panel', () => {
57
+ const comic = comicOf(doc());
58
+ expect(comic.balloons.map((b) => [b.panelIndex, b.kind, b.style])).toEqual([
59
+ [0, 'caption', 'caption'],
60
+ [0, 'balloon', 'speech'],
61
+ [0, 'balloon', 'speech'],
62
+ [1, 'sfx', 'sfx'],
63
+ [1, 'balloon', 'whisper'],
64
+ ]);
65
+ for (const b of comic.balloons) {
66
+ const panel = comic.panels[b.panelIndex];
67
+ expect(pointInPolygon(panel.polygon, centre(b))).toBe(true);
68
+ expect(b.bbox.x).toBeGreaterThanOrEqual(panel.bbox.x - 1);
69
+ expect(b.bbox.y).toBeGreaterThanOrEqual(panel.bbox.y - 1);
70
+ expect(b.bbox.x + b.bbox.width).toBeLessThanOrEqual(panel.bbox.x + panel.bbox.width + 1);
71
+ expect(b.bbox.y + b.bbox.height).toBeLessThanOrEqual(panel.bbox.y + panel.bbox.height + 1);
72
+ expect(b.text.length).toBeGreaterThan(0);
73
+ }
74
+ // Speech balloons stay off the two faces.
75
+ const room = comic.panels[0];
76
+ const faces = resources[0].anchors.map((a) => a.face).map((f) => ({
77
+ a: comicArtPointToPage(room.art, f.x, f.y),
78
+ b: comicArtPointToPage(room.art, f.x + f.width, f.y + f.height),
79
+ }));
80
+ for (const b of comic.balloons.filter((x) => x.panelIndex === 0)) {
81
+ for (const f of faces) {
82
+ const apart = b.bbox.x + b.bbox.width <= Math.min(f.a.x, f.b.x) + 1 || b.bbox.x >= Math.max(f.a.x, f.b.x) - 1
83
+ || b.bbox.y + b.bbox.height <= f.a.y + 1 || b.bbox.y >= f.b.y - 1;
84
+ expect(apart).toBe(true);
85
+ }
86
+ }
87
+ });
88
+ it('points each tail toward its speaker', () => {
89
+ const comic = comicOf(doc());
90
+ const room = comic.panels[0];
91
+ for (const b of comic.balloons.filter((x) => x.panelIndex === 0 && x.kind === 'balloon')) {
92
+ const a = resources[0].anchors.find((x) => x.id === b.speaker);
93
+ const mouth = comicArtPointToPage(room.art, a.x, a.y);
94
+ expect(b.tailTip).toBeDefined();
95
+ expect(b.shape).toBeDefined();
96
+ expect(dist(b.tailTip, mouth)).toBeLessThan(dist(centre(b), mouth));
97
+ }
98
+ // The sound effect: no outline, no tail, a halo.
99
+ const sfx = comic.balloons.find((b) => b.kind === 'sfx');
100
+ expect(sfx.shape).toBeUndefined();
101
+ expect(sfx.tailTip).toBeUndefined();
102
+ expect(sfx.halo?.width).toBeGreaterThan(0);
103
+ });
104
+ it('is deterministic', () => {
105
+ expect(JSON.stringify(comicOf(doc()))).toBe(JSON.stringify(comicOf(doc())));
106
+ });
107
+ });
108
+ }
109
+ it('sets Japanese balloons in columns and Arabic ones right to left', () => {
110
+ const ja = comicOf(buildDocument({ markdown: markdown(scripts.ja), resources }, config('ja')));
111
+ for (const b of ja.balloons)
112
+ expect(b.text[0].vertical).toBeDefined();
113
+ const en = comicOf(buildDocument({ markdown: markdown(scripts.en), resources }, config('en')));
114
+ for (const b of en.balloons)
115
+ expect(b.text[0].vertical).toBeUndefined();
116
+ const ar = comicOf(buildDocument({ markdown: markdown(scripts.ar), resources }, config('ar')));
117
+ expect(ar.direction).toBe('rtl');
118
+ for (const b of ar.balloons)
119
+ expect(b.text[0].direction).toBe('rtl');
120
+ // Read from the right: the caption takes the top right corner, and the
121
+ // first speech balloon is not after the second one in reading order
122
+ // (higher, or level and to its right).
123
+ const cap = ar.balloons[0];
124
+ const room = ar.panels[0];
125
+ // (Butted against the inner edge of the panel's border.)
126
+ expect(cap.bbox.x + cap.bbox.width).toBeGreaterThan(room.bbox.x + room.bbox.width - room.border.width / 2 - 2);
127
+ const [b1, b2] = ar.balloons.filter((b) => b.kind === 'balloon' && b.panelIndex === 0);
128
+ expect(b1.bbox.y < b2.bbox.y + 1 || centre(b1).x > centre(b2).x).toBe(true);
129
+ });
130
+ it('keeps the source ranges of every line (click to source)', () => {
131
+ const md = markdown(scripts.en);
132
+ const comic = comicOf(buildDocument({ markdown: md, resources }, config('en')));
133
+ for (const b of comic.balloons) {
134
+ const line = md.slice(b.sourceStart, b.sourceEnd);
135
+ expect(line).toMatch(/^(caption|ana|ben|sfx)(\{[^}]*\})?:/);
136
+ for (const t of b.text)
137
+ if (t.sourceMap)
138
+ for (const o of t.sourceMap)
139
+ expect(o).toBeGreaterThanOrEqual(b.sourceStart);
140
+ }
141
+ });
142
+ it('warns when a balloon cannot be placed cleanly, without shrinking it', () => {
143
+ const long = 'This is a very long line of dialogue that will never fit inside such a small panel, however hard the lettering tries to place it somewhere.';
144
+ const md = `:::page{split="8 [12 | *] / *"}\n::panel{art=room}\nana: ${long}\nben: ${long}\n::panel\n::panel\n:::\n`;
145
+ const doc = buildDocument({ markdown: md, resources }, config('en'));
146
+ const w = (doc.contentWarnings ?? []).filter((x) => x.kind === 'comicBalloonOverflow');
147
+ expect(w.length).toBeGreaterThan(0);
148
+ const first = w[0];
149
+ expect(md.slice(first.sourceStart, first.sourceEnd)).toMatch(/^(ana|ben): This is/);
150
+ expect(first.pageIndex).toBe(doc.pages.find((p) => p.comic).index);
151
+ // One lettering size: the text keeps the size of a roomy page.
152
+ const roomy = comicOf(buildDocument({ markdown: markdown(scripts.en), resources }, config('en')));
153
+ const crowded = comicOf(doc);
154
+ expect(crowded.balloons[0].text[0].fontString).toBe(roomy.balloons[1].text[0].fontString);
155
+ });
156
+ it('reports speakers no picture of the page marks (only on pages that mark some)', () => {
157
+ const md = ':::page\n::panel{art=room}\nana: Hello.\nzed: Who is there?\n:::\n\n:::page\n::panel\nbob: Hi.\n:::\n';
158
+ const doc = buildDocument({ markdown: md, resources }, config('en'));
159
+ const unknown = (doc.contentWarnings ?? []).filter((w) => w.kind === 'comicUnknownSpeaker');
160
+ expect(unknown.map((w) => w.speaker)).toEqual(['zed']);
161
+ // A cast entry makes the speaker known; its tail points off the panel.
162
+ const cast = buildDocument({ markdown: md, resources }, { ...config('en'), comics: { cast: [{ id: 'zed', fill: { hex: '#eeeeee', model: 'hex' } }] } });
163
+ expect((cast.contentWarnings ?? []).some((w) => w.kind === 'comicUnknownSpeaker')).toBe(false);
164
+ const zed = comicOf(cast).balloons.find((b) => b.speaker === 'zed');
165
+ expect(zed.shape?.fill).toBe('#eeeeee');
166
+ const panel = comicOf(cast).panels[0];
167
+ const tip = zed.tailTip;
168
+ const onBorder = Math.min(Math.abs(tip.x - panel.bbox.x), Math.abs(tip.x - panel.bbox.x - panel.bbox.width), Math.abs(tip.y - panel.bbox.y), Math.abs(tip.y - panel.bbox.y - panel.bbox.height));
169
+ expect(onBorder).toBeLessThan(2);
170
+ });
171
+ it('honours pins in picture fractions and per-line tail and join attributes', () => {
172
+ const md = ':::page\n::panel{art=room}\nana{at="45% 20%"}: Pinned here.\nben: One.\nben: Two.\nben{join=false}: Three.\n:::\n';
173
+ const comic = comicOf(buildDocument({ markdown: md, resources }, config('en')));
174
+ const room = comic.panels[0];
175
+ const pin = comicArtPointToPage(room.art, 0.45, 0.2);
176
+ expect(pointInPolygon(room.polygon, pin)).toBe(true);
177
+ const ana = comic.balloons[0];
178
+ expect(dist(centre(ana), pin)).toBeLessThan(ana.bbox.height);
179
+ const bens = comic.balloons.filter((b) => b.speaker === 'ben');
180
+ // The first two join (one outline, carried by the first); the third
181
+ // stands alone.
182
+ expect(bens[0].group).toBe(bens[1].group);
183
+ expect(bens[1].shape).toBeUndefined();
184
+ expect(bens[2].group).not.toBe(bens[0].group);
185
+ expect(bens[2].shape).toBeDefined();
186
+ });
187
+ it('keeps a joined group whole when its first line is pinned, that balloon on the pin (#571)', () => {
188
+ const md = ':::page\n::panel{art=room}\nben{at="62% 22%"}: Listen to me.\nben: We leave tonight. Pack only what you can carry.\n:::\n';
189
+ const comic = comicOf(buildDocument({ markdown: md, resources }, config('en')));
190
+ const [first, second] = comic.balloons;
191
+ expect(first.group).toBe(second.group);
192
+ expect(first.shape).toBeDefined();
193
+ expect(second.shape).toBeUndefined();
194
+ const pin = comicArtPointToPage(comic.panels[0].art, 0.62, 0.22);
195
+ expect(dist(centre(first), pin)).toBeLessThan(1);
196
+ });
197
+ it('keeps balloons off a hat: the face grown upward, and a head guard from mouth and head', () => {
198
+ // A tall hat over a marked face; a second speaker marked by mouth and
199
+ // head only (no face): neither head is covered.
200
+ const hats = [picture('hats', 1600, 1000, {
201
+ anchors: [
202
+ { id: 'ana', x: 0.3, y: 0.7, face: { x: 0.24, y: 0.55, width: 0.12, height: 0.2 } },
203
+ { id: 'ben', x: 0.72, y: 0.72, head: { x: 0.72, y: 0.6 } },
204
+ ],
205
+ })];
206
+ const md = ':::page\n::panel{art=hats}\nana: The tallest hat in the whole valley, and it is mine.\nben: It suits you, I suppose.\n:::\n';
207
+ const comic = comicOf(buildDocument({ markdown: md, resources: hats }, config('en')));
208
+ const art = comic.panels[0].art;
209
+ const a = comicArtPointToPage(art, 0.24, 0.55);
210
+ const a2 = comicArtPointToPage(art, 0.36, 0.75);
211
+ // The hat: 0.4 of the face's height above it.
212
+ const hat = { x: a.x, y: a.y - 0.4 * (a2.y - a.y), width: a2.x - a.x, height: 0.4 * (a2.y - a.y) };
213
+ const head = comicArtPointToPage(art, 0.72, 0.6);
214
+ const em = (7.5 / 72) * 300;
215
+ const benHead = { x: head.x - 1.2 * em, y: head.y - 2 * em, width: 2.4 * em, height: 2 * em };
216
+ const hits = (r, b) => Math.min(r.x + r.width, b.bbox.x + 0.9 * b.bbox.width) > Math.max(r.x, b.bbox.x + 0.1 * b.bbox.width)
217
+ && Math.min(r.y + r.height, b.bbox.y + 0.9 * b.bbox.height) > Math.max(r.y, b.bbox.y + 0.1 * b.bbox.height);
218
+ for (const b of comic.balloons) {
219
+ expect(hits(hat, b)).toBe(false);
220
+ expect(hits(benHead, b)).toBe(false);
221
+ }
222
+ });
223
+ it('gives text set on the art with no balloon a halo, and butted captions the border\'s weight', () => {
224
+ const md = ':::page\n::panel{art=room}\ncaption{at=top-start}: Lyon, 1943.\nsfx{writing at="50% 20%"}: Invitation\n:::\n';
225
+ const cfg = { ...config('en'), comics: { balloonStyles: [{ id: 'writing', shape: 'none', tail: 'none', color: { hex: '#3b2a1e', model: 'hex' } }] } };
226
+ const comic = comicOf(buildDocument({ markdown: md, resources }, cfg));
227
+ const writing = comic.balloons.find((b) => b.style === 'writing');
228
+ expect(writing.halo?.color).toBe('#ffffff');
229
+ expect(writing.halo.width).toBeGreaterThan(0);
230
+ const cap = comic.balloons.find((b) => b.kind === 'caption');
231
+ expect(cap.shape.strokeWidth).toBeCloseTo(comic.panels[0].border.width, 6);
232
+ // A style with an explicit halo of 0 keeps none.
233
+ const none = comicOf(buildDocument({ markdown: md, resources }, { ...cfg, comics: { balloonStyles: [{ id: 'writing', shape: 'none', tail: 'none', halo: { value: 0, unit: 'pt' } }] } }));
234
+ expect(none.balloons.find((b) => b.style === 'writing').halo).toBeUndefined();
235
+ });
236
+ it('lays out documents without comics exactly as before (no balloons anywhere)', () => {
237
+ const doc = buildDocument({ markdown: '# Title\n\nSome text.\n' }, config('en'));
238
+ expect(doc.pages.every((p) => p.comic === undefined)).toBe(true);
239
+ });
240
+ });
241
+ //# sourceMappingURL=lettering.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lettering.test.js","sourceRoot":"","sources":["../../../src/__tests__/comics/lettering.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=script.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"script.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/comics/script.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,147 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { parseMarkdown } from '../../parse/blockParser';
3
+ import { parseComicPoint } from '../../comics/script';
4
+ import { BREAK_PLACEHOLDER } from '../../parse/inlineFormatting';
5
+ function comicOf(md) {
6
+ const block = parseMarkdown(md).find((b) => b.comic);
7
+ if (!block?.comic)
8
+ throw new Error('no comic block');
9
+ return block.comic;
10
+ }
11
+ const SPEC_PAGE = `:::page{split="30 [30 | 20 | *] / *" gutter=4mm style=clean}
12
+ ::panel{art=p1-wide}
13
+ caption: Lyon, 1943.
14
+ ana: Did you hear that?
15
+ ben{whisper}: It's nothing. Go back to sleep.
16
+ ben: Really.
17
+ ::panel{art=p1-door focus="70% 40%"}
18
+ sfx{at="62% 40%" rotate=-8}: KRAK
19
+ ::panel{art=p1-ana}
20
+ ana{thought}: Nothing, he says…
21
+ ::panel{art=p1-street bleed}
22
+ caption{at=bottom-end}: Three streets away.
23
+ :::`;
24
+ describe(':::page block', () => {
25
+ it('reads the SPEC example into one directive block with four panels', () => {
26
+ const md = `Before.\n\n${SPEC_PAGE}\n\nAfter.`;
27
+ const blocks = parseMarkdown(md);
28
+ expect(blocks.map((b) => b.type)).toEqual(['paragraph', 'directive', 'paragraph']);
29
+ const page = blocks[1];
30
+ expect(page.directiveName).toBe('page');
31
+ const c = page.comic;
32
+ expect(md.slice(c.sourceStart, c.sourceEnd)).toBe(SPEC_PAGE);
33
+ expect(c.closed).toBe(true);
34
+ expect(c.attrs).toMatchObject({ gutter: '4mm', style: 'clean' });
35
+ expect(md.slice(c.attrSources.split.start, c.attrSources.split.end)).toBe('30 [30 | 20 | *] / *');
36
+ expect(c.panels.map((p) => p.attrs.art)).toEqual(['p1-wide', 'p1-door', 'p1-ana', 'p1-street']);
37
+ expect(c.panels[3].attrs.bleed).toBe('');
38
+ expect(md.slice(c.panels[1].lineStart, c.panels[1].lineEnd)).toBe('::panel{art=p1-door focus="70% 40%"}');
39
+ expect(md.slice(c.panels[0].sourceStart, c.panels[0].sourceEnd)).toBe(SPEC_PAGE.split('\n').slice(1, 6).join('\n'));
40
+ const items = c.panels[0].items;
41
+ expect(items.map((i) => [i.key, i.role, i.style, i.text])).toEqual([
42
+ ['caption', 'caption', undefined, 'Lyon, 1943.'],
43
+ ['ana', 'speech', undefined, 'Did you hear that?'],
44
+ ['ben', 'speech', 'whisper', "It's nothing. Go back to sleep."],
45
+ ['ben', 'speech', undefined, 'Really.'],
46
+ ]);
47
+ expect(items[2].speaker).toBe('ben');
48
+ expect(md.slice(items[2].sourceStart, items[2].sourceEnd)).toBe("ben{whisper}: It's nothing. Go back to sleep.");
49
+ const sfx = c.panels[1].items[0];
50
+ expect(sfx).toMatchObject({ role: 'sfx', at: { x: 0.62, y: 0.4 }, rotate: -8, text: 'KRAK' });
51
+ expect(md.slice(sfx.attrSources.at.start, sfx.attrSources.at.end)).toBe('62% 40%');
52
+ expect(c.panels[2].items[0]).toMatchObject({ style: 'thought', text: 'Nothing, he says…' });
53
+ expect(c.panels[3].items[0]).toMatchObject({ role: 'caption', atKeyword: 'bottom-end' });
54
+ });
55
+ it('maps every balloon character back to its source', () => {
56
+ const md = `:::page\n::panel\nana: Hello *there*.\n:::`;
57
+ const item = comicOf(md).panels[0].items[0];
58
+ expect(item.text).toBe('Hello there.');
59
+ expect(item.sourceMap.map((o) => md[o]).join('')).toBe('Hello there.');
60
+ expect(item.spans.find((s) => s.italic)?.text).toBe('there');
61
+ });
62
+ it('joins continuation lines and keeps forced breaks', () => {
63
+ const md = [
64
+ ':::page',
65
+ '::panel',
66
+ 'ben: It is nothing.',
67
+ ' Go back to sleep.\\',
68
+ '\tReally.',
69
+ 'ana: Fine.',
70
+ ':::',
71
+ ].join('\n');
72
+ const items = comicOf(md).panels[0].items;
73
+ expect(items).toHaveLength(2);
74
+ expect(items[0].text).toBe(`It is nothing. Go back to sleep.${BREAK_PLACEHOLDER}Really.`);
75
+ expect(md.slice(items[0].textStart, items[0].textEnd)).toBe('It is nothing.\n Go back to sleep.\\\n\tReally.');
76
+ });
77
+ it('reads Japanese lines: the fullwidth colon, no space between CJK lines, ruby and tcy', () => {
78
+ const md = [
79
+ ':::page',
80
+ '::panel',
81
+ 'アナ{thought}:何でもない',
82
+ ' と彼は言う。',
83
+ 'ben::ruby[漢字]{rt="かんじ"}を:tcy[12]回',
84
+ ':::',
85
+ ].join('\n');
86
+ const items = comicOf(md).panels[0].items;
87
+ expect(items[0]).toMatchObject({ key: 'アナ', speaker: 'アナ', style: 'thought', text: '何でもないと彼は言う。' });
88
+ expect(items[1].text).toBe('漢字を12回');
89
+ expect(items[1].spans.some((s) => s.ruby)).toBe(true);
90
+ expect(items[1].spans.some((s) => s.combineUpright)).toBe(true);
91
+ });
92
+ it('reads Arabic lines and direction marks', () => {
93
+ const md = ':::page{direction=rtl}\n::panel\nليلى: مرحبا :ltr[OK] يا صديقي\n:::';
94
+ const c = comicOf(md);
95
+ expect(c.attrs.direction).toBe('rtl');
96
+ const item = c.panels[0].items[0];
97
+ expect(item).toMatchObject({ key: 'ليلى', role: 'speech' });
98
+ expect(item.text).toBe('مرحبا OK يا صديقي');
99
+ expect(item.spans.some((s) => s.direction?.dir === 'ltr')).toBe(true);
100
+ });
101
+ it('skips comments and blank lines; flags stray text and keeps unknown flags', () => {
102
+ const md = [
103
+ ':::page{split="*"}',
104
+ 'Text before any panel.',
105
+ '::panel{#first}',
106
+ '<!-- a note',
107
+ 'over two lines -->',
108
+ '',
109
+ 'ana{wisper join=false break}: Hi',
110
+ 'Just text.',
111
+ ':::',
112
+ ].join('\n');
113
+ const c = comicOf(md);
114
+ expect(c.stray).toHaveLength(1);
115
+ const items = c.panels[0].items;
116
+ expect(c.panels[0].attrs.id).toBe('first');
117
+ expect(items.map((i) => [i.key, i.text, i.stray ?? false])).toEqual([
118
+ ['caption', 'Text before any panel.', true],
119
+ ['ana', 'Hi', false],
120
+ ['caption', 'Just text.', true],
121
+ ]);
122
+ expect(items[1]).toMatchObject({ style: 'wisper', styleFlags: ['wisper'], join: false, break: true });
123
+ });
124
+ it('runs an unclosed page to the end of the text', () => {
125
+ const md = ':::page\n::panel\nana: Hi';
126
+ const c = comicOf(md);
127
+ expect(c.closed).toBe(false);
128
+ expect(c.sourceEnd).toBe(md.length);
129
+ });
130
+ it('maps offsets back when the text holds index marks', () => {
131
+ const md = 'A :index[term] word.\n\n:::page{split="50 / *"}\n::panel\nana: Hi\n:::';
132
+ const c = comicOf(md);
133
+ expect(md.slice(c.attrSources.split.start, c.attrSources.split.end)).toBe('50 / *');
134
+ const item = c.panels[0].items[0];
135
+ expect(md.slice(item.sourceStart, item.sourceEnd)).toBe('ana: Hi');
136
+ expect(c.splitParse.tokens.map((t) => md.slice(t.size.sourceStart, t.size.sourceEnd))).toEqual(['50', '*']);
137
+ });
138
+ });
139
+ describe('parseComicPoint', () => {
140
+ it('reads percentages and fractions', () => {
141
+ expect(parseComicPoint('62% 40%')).toEqual({ x: 0.62, y: 0.4 });
142
+ expect(parseComicPoint('50 25')).toEqual({ x: 0.5, y: 0.25 });
143
+ expect(parseComicPoint('0.5 0.25')).toEqual({ x: 0.5, y: 0.25 });
144
+ expect(parseComicPoint('top')).toBeUndefined();
145
+ });
146
+ });
147
+ //# sourceMappingURL=script.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"script.test.js","sourceRoot":"","sources":["../../../src/__tests__/comics/script.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=split.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"split.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/comics/split.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,120 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { comicSplitLeaves, comicSplitLines, comicSplitListAt, mergeComicCells, moveComicSplitLine, parseComicSplit, serializeComicSplit, splitComicCell, } from '../../comics/split';
3
+ describe('parseComicSplit', () => {
4
+ it("reads the owner's example: a top tier of three, a bottom tier", () => {
5
+ const src = '30 [30 | 20 | *] / *';
6
+ const { tree, tokens, issues } = parseComicSplit(src);
7
+ expect(issues).toEqual([]);
8
+ expect(tree.axis).toBe('rows');
9
+ expect(tree.items).toHaveLength(2);
10
+ expect(tree.items[0].children.axis).toBe('columns');
11
+ expect(comicSplitLines(tree)).toEqual({ start: [30], end: [30] });
12
+ expect(comicSplitLines(tree.items[0].children)).toEqual({ start: [30, 50], end: [30, 50] });
13
+ expect(comicSplitLeaves(tree)).toEqual([[0, 0], [0, 1], [0, 2], [1]]);
14
+ // Every size with its source range, in source order.
15
+ expect(tokens.map((t) => [t.path, t.index, src.slice(t.size.sourceStart, t.size.sourceEnd)])).toEqual([
16
+ [[], 0, '30'],
17
+ [[0], 0, '30'],
18
+ [[0], 1, '20'],
19
+ [[0], 2, '*'],
20
+ [[], 1, '*'],
21
+ ]);
22
+ });
23
+ it('reads a splash, tiers, and stars sharing what is left', () => {
24
+ expect(comicSplitLeaves(parseComicSplit('*').tree)).toEqual([[0]]);
25
+ expect(comicSplitLeaves(parseComicSplit('').tree)).toEqual([[0]]);
26
+ expect(comicSplitLines(parseComicSplit('33/33/*').tree).start).toEqual([33, 66]);
27
+ expect(comicSplitLines(parseComicSplit('20 / * / *').tree).start).toEqual([20, 60]);
28
+ const nested = parseComicSplit('50 [*|*] / 50 [*|*|*]').tree;
29
+ expect(comicSplitLeaves(nested)).toHaveLength(5);
30
+ expect(comicSplitLines(nested.items[1].children).start.map((v) => Math.round(v * 10) / 10)).toEqual([33.3, 66.7]);
31
+ });
32
+ it('reads slanted sizes, each end on its own', () => {
33
+ const { tree, issues } = parseComicSplit('* [40~55 | *] / 35');
34
+ expect(issues).toEqual([]);
35
+ expect(comicSplitLines(tree)).toEqual({ start: [65], end: [65] });
36
+ expect(comicSplitLines(tree.items[0].children)).toEqual({ start: [40], end: [55] });
37
+ expect(tree.items[0].children.items[0].size).toMatchObject({ start: 40, end: 55 });
38
+ });
39
+ it('reads a column list on top, the right column split in two', () => {
40
+ const { tree } = parseComicSplit('60 | * [50 / *]');
41
+ expect(tree.axis).toBe('columns');
42
+ expect(tree.items[1].children.axis).toBe('rows');
43
+ expect(comicSplitLeaves(tree)).toEqual([[0], [1, 0], [1, 1]]);
44
+ });
45
+ it('keeps percent signs and the last cell runs to 100', () => {
46
+ const { tree } = parseComicSplit('30% / 40%');
47
+ expect(comicSplitLines(tree).start).toEqual([30]);
48
+ expect(serializeComicSplit(tree)).toBe('30% / 40%');
49
+ });
50
+ it('reports mixed separators, stray characters, unclosed brackets and overflow', () => {
51
+ expect(parseComicSplit('30 / 40 | 2').issues.map((i) => i.kind)).toEqual(['syntax']);
52
+ expect(parseComicSplit('30 [a] / *').issues[0].message).toContain('"a"');
53
+ expect(parseComicSplit('30 [10 | 20 / *').issues.some((i) => i.message.includes('never closed'))).toBe(true);
54
+ expect(parseComicSplit('30 [10 / 20] / *').issues[0].message).toContain('other axis');
55
+ const over = parseComicSplit('80/80');
56
+ expect(over.issues).toMatchObject([{ kind: 'overflow', total: 160 }]);
57
+ // Scaled down to fit.
58
+ expect(comicSplitLines(over.tree).start).toEqual([50]);
59
+ // A star keeps 5 %.
60
+ expect(comicSplitLines(parseComicSplit('80 / 80 / *').tree).start).toEqual([47.5, 95]);
61
+ });
62
+ it('serialises a parsed tree back', () => {
63
+ for (const src of ['30 [30 | 20 | *] / *', '* [40~55 | *] / 35', '60 | * [50 / *]', '*', '33 / 33 / *']) {
64
+ expect(serializeComicSplit(parseComicSplit(src).tree)).toBe(src);
65
+ }
66
+ expect(serializeComicSplit(parseComicSplit('30[30|20|*]/*').tree)).toBe('30 [30 | 20 | *] / *');
67
+ expect(serializeComicSplit(parseComicSplit('33.333/*').tree)).toBe('33.3 / *');
68
+ });
69
+ });
70
+ describe('moveComicSplitLine', () => {
71
+ const src = '30 [30 | 20 | *] / *';
72
+ it('rewrites the sizes next to the line, in place, keeping stars', () => {
73
+ expect(moveComicSplitLine(src, [], 0, 42)).toBe('42 [30 | 20 | *] / *');
74
+ expect(moveComicSplitLine(src, [0], 0, 40)).toBe('30 [40 | 10 | *] / *');
75
+ expect(moveComicSplitLine(src, [0], 1, 70)).toBe('30 [30 | 40 | *] / *');
76
+ // Formatting outside the edited sizes is kept.
77
+ expect(moveComicSplitLine('30[30|20|*]/*', [0], 0, 25.25)).toBe('30[25.3|24.7|*]/*');
78
+ });
79
+ it('moves a slanted line by its start, the slant kept, or one end alone', () => {
80
+ expect(moveComicSplitLine('* [40~55 | *] / 35', [0], 0, 50)).toBe('* [50~65 | *] / 35');
81
+ expect(moveComicSplitLine(src, [0], 1, 70, 60)).toBe('30 [30 | 40~30 | *] / *');
82
+ const lines = comicSplitLines(comicSplitListAt(parseComicSplit(moveComicSplitLine(src, [0], 1, 70, 60)).tree, [0]));
83
+ expect(lines).toEqual({ start: [30, 70], end: [30, 60] });
84
+ });
85
+ it('keeps every cell at least 5 % and ignores a line that does not exist', () => {
86
+ expect(moveComicSplitLine(src, [], 0, 99)).toBe('95 [30 | 20 | *] / *');
87
+ expect(moveComicSplitLine(src, [0], 0, 0)).toBe('30 [5 | 45 | *] / *');
88
+ expect(moveComicSplitLine(src, [], 3, 50)).toBe(src);
89
+ expect(moveComicSplitLine(src, [7], 0, 50)).toBe(src);
90
+ });
91
+ it('writes stars out only when they would move', () => {
92
+ // Two stars sharing a tier: the first becomes a number, the second stays.
93
+ expect(moveComicSplitLine('* | *', [], 0, 30)).toBe('30 | *');
94
+ // A line between fixed sizes leaves the star elsewhere untouched.
95
+ expect(moveComicSplitLine('20 | 20 | *', [], 0, 30)).toBe('30 | 10 | *');
96
+ });
97
+ });
98
+ describe('splitComicCell and mergeComicCells', () => {
99
+ const src = '30 [30 | 20 | *] / *';
100
+ it('splits a cell along its own list or across it', () => {
101
+ expect(splitComicCell(src, [1], 'rows')).toBe('30 [30 | 20 | *] / 35 / *');
102
+ expect(splitComicCell(src, [1], 'columns')).toBe('30 [30 | 20 | *] / * [* | *]');
103
+ expect(splitComicCell(src, [0, 1], 'columns')).toBe('30 [30 | 10 | 10 | *] / *');
104
+ expect(splitComicCell(src, [0, 0], 'rows')).toBe('30 [30 [* / *] | 20 | *] / *');
105
+ expect(splitComicCell('*', [0], 'rows')).toBe('50 / *');
106
+ });
107
+ it('merges two cells, keeping the lines around them', () => {
108
+ expect(mergeComicCells(src, [0], 0)).toBe('30 [50 | *] / *');
109
+ expect(mergeComicCells(src, [0], 1)).toBe('30 [30 | *] / *');
110
+ expect(mergeComicCells(src, [], 0)).toBe('* [30 | 20 | *]');
111
+ // A bracketed list left with one cell loses its brackets.
112
+ expect(mergeComicCells('30 [* | *] / *', [0], 0)).toBe('30 / *');
113
+ });
114
+ it('round-trips: a split then a merge gives the lines back', () => {
115
+ const split = splitComicCell(src, [0, 2], 'columns');
116
+ const merged = mergeComicCells(split, [0], 2);
117
+ expect(comicSplitLines(comicSplitListAt(parseComicSplit(merged).tree, [0]))).toEqual(comicSplitLines(comicSplitListAt(parseComicSplit(src).tree, [0])));
118
+ });
119
+ });
120
+ //# sourceMappingURL=split.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"split.test.js","sourceRoot":"","sources":["../../../src/__tests__/comics/split.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=spread.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spread.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/comics/spread.test.ts"],"names":[],"mappings":""}