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.
- package/dist/__tests__/comics/art.test.d.ts +2 -0
- package/dist/__tests__/comics/art.test.d.ts.map +1 -0
- package/dist/__tests__/comics/art.test.js +96 -0
- package/dist/__tests__/comics/art.test.js.map +1 -0
- package/dist/__tests__/comics/build.test.d.ts +2 -0
- package/dist/__tests__/comics/build.test.d.ts.map +1 -0
- package/dist/__tests__/comics/build.test.js +215 -0
- package/dist/__tests__/comics/build.test.js.map +1 -0
- package/dist/__tests__/comics/canvas.test.d.ts +2 -0
- package/dist/__tests__/comics/canvas.test.d.ts.map +1 -0
- package/dist/__tests__/comics/canvas.test.js +161 -0
- package/dist/__tests__/comics/canvas.test.js.map +1 -0
- package/dist/__tests__/comics/config.test.d.ts +2 -0
- package/dist/__tests__/comics/config.test.d.ts.map +1 -0
- package/dist/__tests__/comics/config.test.js +97 -0
- package/dist/__tests__/comics/config.test.js.map +1 -0
- package/dist/__tests__/comics/geometry.test.d.ts +2 -0
- package/dist/__tests__/comics/geometry.test.d.ts.map +1 -0
- package/dist/__tests__/comics/geometry.test.js +118 -0
- package/dist/__tests__/comics/geometry.test.js.map +1 -0
- package/dist/__tests__/comics/html.test.d.ts +2 -0
- package/dist/__tests__/comics/html.test.d.ts.map +1 -0
- package/dist/__tests__/comics/html.test.js +253 -0
- package/dist/__tests__/comics/html.test.js.map +1 -0
- package/dist/__tests__/comics/lettering.test.d.ts +2 -0
- package/dist/__tests__/comics/lettering.test.d.ts.map +1 -0
- package/dist/__tests__/comics/lettering.test.js +241 -0
- package/dist/__tests__/comics/lettering.test.js.map +1 -0
- package/dist/__tests__/comics/script.test.d.ts +2 -0
- package/dist/__tests__/comics/script.test.d.ts.map +1 -0
- package/dist/__tests__/comics/script.test.js +147 -0
- package/dist/__tests__/comics/script.test.js.map +1 -0
- package/dist/__tests__/comics/split.test.d.ts +2 -0
- package/dist/__tests__/comics/split.test.d.ts.map +1 -0
- package/dist/__tests__/comics/split.test.js +120 -0
- package/dist/__tests__/comics/split.test.js.map +1 -0
- package/dist/__tests__/comics/spread.test.d.ts +2 -0
- package/dist/__tests__/comics/spread.test.d.ts.map +1 -0
- package/dist/__tests__/comics/spread.test.js +161 -0
- package/dist/__tests__/comics/spread.test.js.map +1 -0
- package/dist/__tests__/comics/strip.test.d.ts +2 -0
- package/dist/__tests__/comics/strip.test.d.ts.map +1 -0
- package/dist/__tests__/comics/strip.test.js +231 -0
- package/dist/__tests__/comics/strip.test.js.map +1 -0
- package/dist/__tests__/exports.test.js +89 -0
- package/dist/__tests__/exports.test.js.map +1 -1
- package/dist/__tests__/parse/containers.test.js +1 -1
- package/dist/__tests__/parse/containers.test.js.map +1 -1
- package/dist/canvas-backend/comic.d.ts +32 -0
- package/dist/canvas-backend/comic.d.ts.map +1 -0
- package/dist/canvas-backend/comic.js +216 -0
- package/dist/canvas-backend/comic.js.map +1 -0
- package/dist/canvas-backend/headerFooter.d.ts +4 -1
- package/dist/canvas-backend/headerFooter.d.ts.map +1 -1
- package/dist/canvas-backend/headerFooter.js +3 -1
- package/dist/canvas-backend/headerFooter.js.map +1 -1
- package/dist/canvas-backend/index.d.ts.map +1 -1
- package/dist/canvas-backend/index.js +7 -1
- package/dist/canvas-backend/index.js.map +1 -1
- package/dist/comics/art.d.ts +72 -0
- package/dist/comics/art.d.ts.map +1 -0
- package/dist/comics/art.js +154 -0
- package/dist/comics/art.js.map +1 -0
- package/dist/comics/fonts.d.ts +20 -0
- package/dist/comics/fonts.d.ts.map +1 -0
- package/dist/comics/fonts.js +42 -0
- package/dist/comics/fonts.js.map +1 -0
- package/dist/comics/geometry.d.ts +87 -0
- package/dist/comics/geometry.d.ts.map +1 -0
- package/dist/comics/geometry.js +272 -0
- package/dist/comics/geometry.js.map +1 -0
- package/dist/comics/index.d.ts +29 -0
- package/dist/comics/index.d.ts.map +1 -0
- package/dist/comics/index.js +18 -0
- package/dist/comics/index.js.map +1 -0
- package/dist/comics/layoutPage.d.ts +156 -0
- package/dist/comics/layoutPage.d.ts.map +1 -0
- package/dist/comics/layoutPage.js +697 -0
- package/dist/comics/layoutPage.js.map +1 -0
- package/dist/comics/lettering/__tests__/harness.test.d.ts +2 -0
- package/dist/comics/lettering/__tests__/harness.test.d.ts.map +1 -0
- package/dist/comics/lettering/__tests__/harness.test.js +273 -0
- package/dist/comics/lettering/__tests__/harness.test.js.map +1 -0
- package/dist/comics/lettering/__tests__/letterPanel.test.d.ts +2 -0
- package/dist/comics/lettering/__tests__/letterPanel.test.d.ts.map +1 -0
- package/dist/comics/lettering/__tests__/letterPanel.test.js +224 -0
- package/dist/comics/lettering/__tests__/letterPanel.test.js.map +1 -0
- package/dist/comics/lettering/__tests__/polish.test.d.ts +2 -0
- package/dist/comics/lettering/__tests__/polish.test.d.ts.map +1 -0
- package/dist/comics/lettering/__tests__/polish.test.js +357 -0
- package/dist/comics/lettering/__tests__/polish.test.js.map +1 -0
- package/dist/comics/lettering/__tests__/round2.test.d.ts +2 -0
- package/dist/comics/lettering/__tests__/round2.test.d.ts.map +1 -0
- package/dist/comics/lettering/__tests__/round2.test.js +289 -0
- package/dist/comics/lettering/__tests__/round2.test.js.map +1 -0
- package/dist/comics/lettering/__tests__/shapeText.test.d.ts +2 -0
- package/dist/comics/lettering/__tests__/shapeText.test.d.ts.map +1 -0
- package/dist/comics/lettering/__tests__/shapeText.test.js +98 -0
- package/dist/comics/lettering/__tests__/shapeText.test.js.map +1 -0
- package/dist/comics/lettering/__tests__/shapes.test.d.ts +2 -0
- package/dist/comics/lettering/__tests__/shapes.test.d.ts.map +1 -0
- package/dist/comics/lettering/__tests__/shapes.test.js +137 -0
- package/dist/comics/lettering/__tests__/shapes.test.js.map +1 -0
- package/dist/comics/lettering/__tests__/stubMeasure.d.ts +5 -0
- package/dist/comics/lettering/__tests__/stubMeasure.d.ts.map +1 -0
- package/dist/comics/lettering/__tests__/stubMeasure.js +47 -0
- package/dist/comics/lettering/__tests__/stubMeasure.js.map +1 -0
- package/dist/comics/lettering/__tests__/text.test.d.ts +2 -0
- package/dist/comics/lettering/__tests__/text.test.d.ts.map +1 -0
- package/dist/comics/lettering/__tests__/text.test.js +86 -0
- package/dist/comics/lettering/__tests__/text.test.js.map +1 -0
- package/dist/comics/lettering/geom.d.ts +78 -0
- package/dist/comics/lettering/geom.d.ts.map +1 -0
- package/dist/comics/lettering/geom.js +376 -0
- package/dist/comics/lettering/geom.js.map +1 -0
- package/dist/comics/lettering/index.d.ts +7 -0
- package/dist/comics/lettering/index.d.ts.map +1 -0
- package/dist/comics/lettering/index.js +8 -0
- package/dist/comics/lettering/index.js.map +1 -0
- package/dist/comics/lettering/letter.d.ts +7 -0
- package/dist/comics/lettering/letter.d.ts.map +1 -0
- package/dist/comics/lettering/letter.js +397 -0
- package/dist/comics/lettering/letter.js.map +1 -0
- package/dist/comics/lettering/placement.d.ts +117 -0
- package/dist/comics/lettering/placement.d.ts.map +1 -0
- package/dist/comics/lettering/placement.js +889 -0
- package/dist/comics/lettering/placement.js.map +1 -0
- package/dist/comics/lettering/presets.d.ts +15 -0
- package/dist/comics/lettering/presets.d.ts.map +1 -0
- package/dist/comics/lettering/presets.js +61 -0
- package/dist/comics/lettering/presets.js.map +1 -0
- package/dist/comics/lettering/shape-text.d.ts +72 -0
- package/dist/comics/lettering/shape-text.d.ts.map +1 -0
- package/dist/comics/lettering/shape-text.js +550 -0
- package/dist/comics/lettering/shape-text.js.map +1 -0
- package/dist/comics/lettering/shapes.d.ts +83 -0
- package/dist/comics/lettering/shapes.d.ts.map +1 -0
- package/dist/comics/lettering/shapes.js +512 -0
- package/dist/comics/lettering/shapes.js.map +1 -0
- package/dist/comics/lettering/text.d.ts +79 -0
- package/dist/comics/lettering/text.d.ts.map +1 -0
- package/dist/comics/lettering/text.js +488 -0
- package/dist/comics/lettering/text.js.map +1 -0
- package/dist/comics/lettering/types.d.ts +270 -0
- package/dist/comics/lettering/types.d.ts.map +1 -0
- package/dist/comics/lettering/types.js +9 -0
- package/dist/comics/lettering/types.js.map +1 -0
- package/dist/comics/page.d.ts +37 -0
- package/dist/comics/page.d.ts.map +1 -0
- package/dist/comics/page.js +285 -0
- package/dist/comics/page.js.map +1 -0
- package/dist/comics/paint.d.ts +65 -0
- package/dist/comics/paint.d.ts.map +1 -0
- package/dist/comics/paint.js +219 -0
- package/dist/comics/paint.js.map +1 -0
- package/dist/comics/script.d.ts +42 -0
- package/dist/comics/script.d.ts.map +1 -0
- package/dist/comics/script.js +302 -0
- package/dist/comics/script.js.map +1 -0
- package/dist/comics/split.d.ts +135 -0
- package/dist/comics/split.d.ts.map +1 -0
- package/dist/comics/split.js +514 -0
- package/dist/comics/split.js.map +1 -0
- package/dist/comics/spread.d.ts +36 -0
- package/dist/comics/spread.d.ts.map +1 -0
- package/dist/comics/spread.js +172 -0
- package/dist/comics/spread.js.map +1 -0
- package/dist/comics/strip.d.ts +77 -0
- package/dist/comics/strip.d.ts.map +1 -0
- package/dist/comics/strip.js +89 -0
- package/dist/comics/strip.js.map +1 -0
- package/dist/comics/transform.d.ts +37 -0
- package/dist/comics/transform.d.ts.map +1 -0
- package/dist/comics/transform.js +161 -0
- package/dist/comics/transform.js.map +1 -0
- package/dist/comics/types.d.ts +143 -0
- package/dist/comics/types.d.ts.map +1 -0
- package/dist/comics/types.js +13 -0
- package/dist/comics/types.js.map +1 -0
- package/dist/comics/warnings.d.ts +14 -0
- package/dist/comics/warnings.d.ts.map +1 -0
- package/dist/comics/warnings.js +94 -0
- package/dist/comics/warnings.js.map +1 -0
- package/dist/configWarnings.d.ts.map +1 -1
- package/dist/configWarnings.js +42 -0
- package/dist/configWarnings.js.map +1 -1
- package/dist/defaults/comics.d.ts +51 -0
- package/dist/defaults/comics.d.ts.map +1 -0
- package/dist/defaults/comics.js +385 -0
- package/dist/defaults/comics.js.map +1 -0
- package/dist/defaults/index.d.ts +1 -0
- package/dist/defaults/index.d.ts.map +1 -1
- package/dist/defaults/index.js +9 -0
- package/dist/defaults/index.js.map +1 -1
- package/dist/design/layout.d.ts +13 -1
- package/dist/design/layout.d.ts.map +1 -1
- package/dist/design/layout.js +17 -0
- package/dist/design/layout.js.map +1 -1
- package/dist/html-backend.d.ts +3 -0
- package/dist/html-backend.d.ts.map +1 -1
- package/dist/html-backend.js +44 -8
- package/dist/html-backend.js.map +1 -1
- package/dist/htmlComic.d.ts +69 -0
- package/dist/htmlComic.d.ts.map +1 -0
- package/dist/htmlComic.js +179 -0
- package/dist/htmlComic.js.map +1 -0
- package/dist/index.d.ts +8 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/parse/blockParser.d.ts.map +1 -1
- package/dist/parse/blockParser.js +25 -1
- package/dist/parse/blockParser.js.map +1 -1
- package/dist/parse/indexMarks.d.ts.map +1 -1
- package/dist/parse/indexMarks.js +3 -0
- package/dist/parse/indexMarks.js.map +1 -1
- package/dist/parse/types.d.ts +7 -1
- package/dist/parse/types.d.ts.map +1 -1
- package/dist/pipeline/build.d.ts.map +1 -1
- package/dist/pipeline/build.js +251 -9
- package/dist/pipeline/build.js.map +1 -1
- package/dist/pipeline/config.d.ts.map +1 -1
- package/dist/pipeline/config.js +4 -1
- package/dist/pipeline/config.js.map +1 -1
- package/dist/pipeline/contentWarnings.d.ts.map +1 -1
- package/dist/pipeline/contentWarnings.js +58 -0
- package/dist/pipeline/contentWarnings.js.map +1 -1
- package/dist/pipeline/floatSlots.js +1 -1
- package/dist/pipeline/floatSlots.js.map +1 -1
- package/dist/pipeline/headerFooter.d.ts +6 -2
- package/dist/pipeline/headerFooter.d.ts.map +1 -1
- package/dist/pipeline/headerFooter.js +11 -3
- package/dist/pipeline/headerFooter.js.map +1 -1
- package/dist/pipeline/pageRoles.d.ts +1 -0
- package/dist/pipeline/pageRoles.d.ts.map +1 -1
- package/dist/pipeline/pageRoles.js +3 -0
- package/dist/pipeline/pageRoles.js.map +1 -1
- package/dist/pipeline/placement.d.ts +3 -3
- package/dist/pipeline/placement.d.ts.map +1 -1
- package/dist/pipeline/placement.js +4 -4
- package/dist/pipeline/placement.js.map +1 -1
- package/dist/types.d.ts +338 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/vdt.d.ts +271 -2
- package/dist/vdt.d.ts.map +1 -1
- package/dist/vdt.js.map +1 -1
- package/dist/worker/fonts.d.ts +2 -1
- package/dist/worker/fonts.d.ts.map +1 -1
- package/dist/worker/fonts.js +11 -1
- package/dist/worker/fonts.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"script.js","sourceRoot":"","sources":["../../src/comics/script.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The split grammar of a comic page (`:::page{split="30 [30 | 20 | *] / *"}`,
|
|
3
|
+
* #555): how the page's frame is cut into panels.
|
|
4
|
+
*
|
|
5
|
+
* ```
|
|
6
|
+
* list := item (SEP item)* SEP is '/' (rows, stacked top to bottom)
|
|
7
|
+
* or '|' (columns, from the start side)
|
|
8
|
+
* item := size [ '[' list ']' ] a bracketed list splits that cell on the
|
|
9
|
+
* other axis
|
|
10
|
+
* size := number ['%'] ['~' number ['%']] | '*' | ''
|
|
11
|
+
* ```
|
|
12
|
+
*
|
|
13
|
+
* A size is the cell's extent along its list's axis, in percent of the
|
|
14
|
+
* parent cell; the split lines sit at the running sums. `*` takes an equal
|
|
15
|
+
* share of what is left; an empty size is a `*`. `30~40` slants the cell's
|
|
16
|
+
* far edge: 30 % at the start of the cross axis (the top, for columns; the
|
|
17
|
+
* start side, for rows), 40 % at its other end. The last cell of a list
|
|
18
|
+
* runs to 100 % whatever its size says.
|
|
19
|
+
*
|
|
20
|
+
* Everything here is pure: the parser keeps the source offsets of every
|
|
21
|
+
* size so the Sandbox can rewrite one number in place, and the editing
|
|
22
|
+
* functions (`moveComicSplitLine`, `splitComicCell`, `mergeComicCells`)
|
|
23
|
+
* take a `split` value and return the new one.
|
|
24
|
+
*/
|
|
25
|
+
/** The axis a list splits its cell along: `'rows'` stacks tiers top to
|
|
26
|
+
* bottom, `'columns'` sets cells side by side from the start side. */
|
|
27
|
+
export type ComicSplitAxis = 'rows' | 'columns';
|
|
28
|
+
/** A size as written. */
|
|
29
|
+
export interface ComicSplitSize {
|
|
30
|
+
/** `*`, or an empty size (`implicit`). */
|
|
31
|
+
star: boolean;
|
|
32
|
+
/** The size was left empty (`[*|*] / *`): a `*` that serialises as
|
|
33
|
+
* nothing. */
|
|
34
|
+
implicit?: boolean;
|
|
35
|
+
/** Percent at the start end. Unset for a star. */
|
|
36
|
+
start?: number;
|
|
37
|
+
/** Percent at the far end, when the size is slanted (`30~40`). */
|
|
38
|
+
end?: number;
|
|
39
|
+
/** Written with a `%` sign. */
|
|
40
|
+
percent?: boolean;
|
|
41
|
+
/** Offsets of the size in the source (empty at the item's start for an
|
|
42
|
+
* implicit size). */
|
|
43
|
+
sourceStart: number;
|
|
44
|
+
sourceEnd: number;
|
|
45
|
+
}
|
|
46
|
+
/** One cell of a list, with the list that splits it further. */
|
|
47
|
+
export interface ComicSplitItem {
|
|
48
|
+
size: ComicSplitSize;
|
|
49
|
+
children?: ComicSplitList;
|
|
50
|
+
sourceStart: number;
|
|
51
|
+
sourceEnd: number;
|
|
52
|
+
}
|
|
53
|
+
/** A list of cells sharing one axis. A one-item list has none. */
|
|
54
|
+
export interface ComicSplitList {
|
|
55
|
+
axis?: ComicSplitAxis;
|
|
56
|
+
items: ComicSplitItem[];
|
|
57
|
+
sourceStart: number;
|
|
58
|
+
sourceEnd: number;
|
|
59
|
+
}
|
|
60
|
+
/** A size token with where it sits in the tree: `path` is the list's path
|
|
61
|
+
* (the indices of the items walked down from the top list), `index` the
|
|
62
|
+
* item's in that list. */
|
|
63
|
+
export interface ComicSplitToken {
|
|
64
|
+
path: number[];
|
|
65
|
+
index: number;
|
|
66
|
+
size: ComicSplitSize;
|
|
67
|
+
}
|
|
68
|
+
/** Something the grammar could not read as written. */
|
|
69
|
+
export interface ComicSplitIssue {
|
|
70
|
+
kind: 'syntax' | 'overflow';
|
|
71
|
+
message: string;
|
|
72
|
+
sourceStart: number;
|
|
73
|
+
sourceEnd: number;
|
|
74
|
+
/** `overflow`: the sum of the list's sizes (percent). */
|
|
75
|
+
total?: number;
|
|
76
|
+
}
|
|
77
|
+
export interface ComicSplitParse {
|
|
78
|
+
tree: ComicSplitList;
|
|
79
|
+
tokens: ComicSplitToken[];
|
|
80
|
+
issues: ComicSplitIssue[];
|
|
81
|
+
}
|
|
82
|
+
/** The smallest share a cell keeps (percent) when the sizes of its list
|
|
83
|
+
* overflow, and the least a drag leaves a cell. */
|
|
84
|
+
export declare const COMIC_MIN_CELL_PERCENT = 5;
|
|
85
|
+
/** Parse a `split` value. Never throws: what cannot be read is reported in
|
|
86
|
+
* `issues` and the rest is kept (an empty or unreadable value is one
|
|
87
|
+
* cell, a splash page). */
|
|
88
|
+
export declare function parseComicSplit(src: string): ComicSplitParse;
|
|
89
|
+
/** The axis a list's children split on: its own, or for a one-item list
|
|
90
|
+
* the cross axis of its parent (rows at the top). */
|
|
91
|
+
export declare function crossAxis(axis: ComicSplitAxis): ComicSplitAxis;
|
|
92
|
+
/**
|
|
93
|
+
* The line positions of a list (cumulative percent of its cell) at each end
|
|
94
|
+
* of the cross axis: `lines[b]` is the line between items `b` and `b + 1`.
|
|
95
|
+
* Stars share what the fixed sizes leave; sizes past 100 are scaled down so
|
|
96
|
+
* every star keeps {@link COMIC_MIN_CELL_PERCENT}; the last item runs to
|
|
97
|
+
* 100. Lines never run backwards.
|
|
98
|
+
*/
|
|
99
|
+
export declare function comicSplitLines(list: ComicSplitList): {
|
|
100
|
+
start: number[];
|
|
101
|
+
end: number[];
|
|
102
|
+
};
|
|
103
|
+
/** The list at `path` (item indices walked down from the top list). */
|
|
104
|
+
export declare function comicSplitListAt(tree: ComicSplitList, path: readonly number[]): ComicSplitList | undefined;
|
|
105
|
+
/** Leaf cells in reading order (tree order), each with its item path. */
|
|
106
|
+
export declare function comicSplitLeaves(tree: ComicSplitList): number[][];
|
|
107
|
+
/** Write a tree back as a `split` value: ` / ` between rows, ` | ` between
|
|
108
|
+
* columns, numbers with at most one decimal. */
|
|
109
|
+
export declare function serializeComicSplit(tree: ComicSplitList): string;
|
|
110
|
+
/**
|
|
111
|
+
* Move the split line between children `boundary` and `boundary + 1` of the
|
|
112
|
+
* list at `path` to `newPercentAtStart` (cumulative percent of the parent
|
|
113
|
+
* cell). With `newPercentAtEnd` the far end goes there (a slant); without
|
|
114
|
+
* it the line keeps its slant, both ends moving by the same amount. The
|
|
115
|
+
* line is clamped so every cell keeps {@link COMIC_MIN_CELL_PERCENT}. Only
|
|
116
|
+
* the sizes that change are rewritten, in place; `*` stays where the
|
|
117
|
+
* result allows. Returns `src` unchanged when the path names no line.
|
|
118
|
+
*/
|
|
119
|
+
export declare function moveComicSplitLine(src: string, path: readonly number[], boundary: number, newPercentAtStart: number, newPercentAtEnd?: number): string;
|
|
120
|
+
/**
|
|
121
|
+
* Split the cell at `cellPath` (item indices walked down from the top list)
|
|
122
|
+
* in two along `axis` (`'rows'`: one above the other). A cell whose list
|
|
123
|
+
* runs along `axis` gets a sibling after it, the two sharing its size; any
|
|
124
|
+
* other cell is split by a bracketed list (`30` → `30 [* | *]`). Returns the
|
|
125
|
+
* new `split` value, re-serialised (`serializeComicSplit`).
|
|
126
|
+
*/
|
|
127
|
+
export declare function splitComicCell(src: string, cellPath: readonly number[], axis: ComicSplitAxis): string;
|
|
128
|
+
/**
|
|
129
|
+
* Merge children `boundary` and `boundary + 1` of the list at `path` into one
|
|
130
|
+
* cell spanning both (the split line between them goes). The merged cell
|
|
131
|
+
* keeps the first one's own split, if any. A bracketed list left with one
|
|
132
|
+
* cell loses its brackets. Returns the new `split` value, re-serialised.
|
|
133
|
+
*/
|
|
134
|
+
export declare function mergeComicCells(src: string, path: readonly number[], boundary: number): string;
|
|
135
|
+
//# sourceMappingURL=split.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"split.d.ts","sourceRoot":"","sources":["../../src/comics/split.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,514 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The split grammar of a comic page (`:::page{split="30 [30 | 20 | *] / *"}`,
|
|
3
|
+
* #555): how the page's frame is cut into panels.
|
|
4
|
+
*
|
|
5
|
+
* ```
|
|
6
|
+
* list := item (SEP item)* SEP is '/' (rows, stacked top to bottom)
|
|
7
|
+
* or '|' (columns, from the start side)
|
|
8
|
+
* item := size [ '[' list ']' ] a bracketed list splits that cell on the
|
|
9
|
+
* other axis
|
|
10
|
+
* size := number ['%'] ['~' number ['%']] | '*' | ''
|
|
11
|
+
* ```
|
|
12
|
+
*
|
|
13
|
+
* A size is the cell's extent along its list's axis, in percent of the
|
|
14
|
+
* parent cell; the split lines sit at the running sums. `*` takes an equal
|
|
15
|
+
* share of what is left; an empty size is a `*`. `30~40` slants the cell's
|
|
16
|
+
* far edge: 30 % at the start of the cross axis (the top, for columns; the
|
|
17
|
+
* start side, for rows), 40 % at its other end. The last cell of a list
|
|
18
|
+
* runs to 100 % whatever its size says.
|
|
19
|
+
*
|
|
20
|
+
* Everything here is pure: the parser keeps the source offsets of every
|
|
21
|
+
* size so the Sandbox can rewrite one number in place, and the editing
|
|
22
|
+
* functions (`moveComicSplitLine`, `splitComicCell`, `mergeComicCells`)
|
|
23
|
+
* take a `split` value and return the new one.
|
|
24
|
+
*/
|
|
25
|
+
/** The smallest share a cell keeps (percent) when the sizes of its list
|
|
26
|
+
* overflow, and the least a drag leaves a cell. */
|
|
27
|
+
export const COMIC_MIN_CELL_PERCENT = 5;
|
|
28
|
+
const NUMBER_RE = /^[0-9]+(?:\.[0-9]*)?|^\.[0-9]+/;
|
|
29
|
+
/** Parse a `split` value. Never throws: what cannot be read is reported in
|
|
30
|
+
* `issues` and the rest is kept (an empty or unreadable value is one
|
|
31
|
+
* cell, a splash page). */
|
|
32
|
+
export function parseComicSplit(src) {
|
|
33
|
+
const issues = [];
|
|
34
|
+
const tokens = [];
|
|
35
|
+
let at = 0;
|
|
36
|
+
const skip = () => {
|
|
37
|
+
while (at < src.length && /\s/.test(src[at]))
|
|
38
|
+
at++;
|
|
39
|
+
};
|
|
40
|
+
const issue = (message, start, end = start + 1) => {
|
|
41
|
+
issues.push({ kind: 'syntax', message, sourceStart: start, sourceEnd: Math.max(start, Math.min(end, src.length)) });
|
|
42
|
+
};
|
|
43
|
+
const parseNumber = () => {
|
|
44
|
+
const m = NUMBER_RE.exec(src.slice(at));
|
|
45
|
+
if (!m)
|
|
46
|
+
return undefined;
|
|
47
|
+
at += m[0].length;
|
|
48
|
+
return Number(m[0]);
|
|
49
|
+
};
|
|
50
|
+
const parseSize = () => {
|
|
51
|
+
skip();
|
|
52
|
+
const start = at;
|
|
53
|
+
if (src[at] === '*') {
|
|
54
|
+
at++;
|
|
55
|
+
return { star: true, sourceStart: start, sourceEnd: at };
|
|
56
|
+
}
|
|
57
|
+
const a = parseNumber();
|
|
58
|
+
if (a === undefined)
|
|
59
|
+
return { star: true, implicit: true, sourceStart: start, sourceEnd: start };
|
|
60
|
+
let percent = false;
|
|
61
|
+
if (src[at] === '%') {
|
|
62
|
+
at++;
|
|
63
|
+
percent = true;
|
|
64
|
+
}
|
|
65
|
+
const size = { star: false, start: a, sourceStart: start, sourceEnd: at };
|
|
66
|
+
if (src[at] === '~') {
|
|
67
|
+
at++;
|
|
68
|
+
const b = parseNumber();
|
|
69
|
+
if (b === undefined) {
|
|
70
|
+
issue('a slant needs a number after "~"', at - 1, at);
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
if (src[at] === '%') {
|
|
74
|
+
at++;
|
|
75
|
+
percent = true;
|
|
76
|
+
}
|
|
77
|
+
size.end = b;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
if (percent)
|
|
81
|
+
size.percent = true;
|
|
82
|
+
size.sourceEnd = at;
|
|
83
|
+
return size;
|
|
84
|
+
};
|
|
85
|
+
const parseList = (path, closer) => {
|
|
86
|
+
skip();
|
|
87
|
+
const list = { items: [], sourceStart: at, sourceEnd: at };
|
|
88
|
+
let sep;
|
|
89
|
+
for (;;) {
|
|
90
|
+
skip();
|
|
91
|
+
const itemStart = at;
|
|
92
|
+
const index = list.items.length;
|
|
93
|
+
const size = parseSize();
|
|
94
|
+
skip();
|
|
95
|
+
const item = { size, sourceStart: itemStart, sourceEnd: at };
|
|
96
|
+
if (src[at] === '[') {
|
|
97
|
+
const open = at;
|
|
98
|
+
at++;
|
|
99
|
+
item.children = parseList([...path, index], ']');
|
|
100
|
+
skip();
|
|
101
|
+
if (src[at] === ']')
|
|
102
|
+
at++;
|
|
103
|
+
else
|
|
104
|
+
issue('"[" is never closed', open, at);
|
|
105
|
+
}
|
|
106
|
+
item.sourceEnd = at;
|
|
107
|
+
list.items.push(item);
|
|
108
|
+
tokens.push({ path, index, size });
|
|
109
|
+
// The separator after the item, past anything unreadable.
|
|
110
|
+
let next = 'end';
|
|
111
|
+
for (;;) {
|
|
112
|
+
skip();
|
|
113
|
+
const c = src[at];
|
|
114
|
+
if (c === '/' || c === '|') {
|
|
115
|
+
if (sep === undefined)
|
|
116
|
+
sep = c;
|
|
117
|
+
else if (sep !== c)
|
|
118
|
+
issue('a list mixes "/" and "|": put one of them inside brackets', at);
|
|
119
|
+
at++;
|
|
120
|
+
next = 'sep';
|
|
121
|
+
break;
|
|
122
|
+
}
|
|
123
|
+
if (c === undefined || c === closer)
|
|
124
|
+
break;
|
|
125
|
+
// Anything else: report it and skip to the next separator or closer.
|
|
126
|
+
const bad = at;
|
|
127
|
+
at++;
|
|
128
|
+
while (at < src.length && !'/|'.includes(src[at]) && src[at] !== closer)
|
|
129
|
+
at++;
|
|
130
|
+
issue(`"${src.slice(bad, at).trim()}" is not a size`, bad, at);
|
|
131
|
+
}
|
|
132
|
+
if (next === 'end')
|
|
133
|
+
break;
|
|
134
|
+
}
|
|
135
|
+
list.sourceEnd = at;
|
|
136
|
+
if (sep !== undefined && list.items.length > 1)
|
|
137
|
+
list.axis = sep === '/' ? 'rows' : 'columns';
|
|
138
|
+
return list;
|
|
139
|
+
};
|
|
140
|
+
const tree = parseList([], undefined);
|
|
141
|
+
skip();
|
|
142
|
+
if (at < src.length)
|
|
143
|
+
issue(`"${src.slice(at)}" is left over`, at, src.length);
|
|
144
|
+
tokens.sort((x, y) => x.size.sourceStart - y.size.sourceStart);
|
|
145
|
+
checkAxes(tree, undefined, issues);
|
|
146
|
+
checkOverflow(tree, issues);
|
|
147
|
+
return { tree, tokens, issues };
|
|
148
|
+
}
|
|
149
|
+
/** A bracketed list on its parent's axis (`30 [10 / 20] / *`). */
|
|
150
|
+
function checkAxes(list, parentAxis, issues) {
|
|
151
|
+
if (parentAxis !== undefined && list.axis === parentAxis) {
|
|
152
|
+
issues.push({
|
|
153
|
+
kind: 'syntax',
|
|
154
|
+
message: `a bracketed list splits its cell on the other axis: use "${parentAxis === 'rows' ? '|' : '/'}" inside it`,
|
|
155
|
+
sourceStart: list.sourceStart,
|
|
156
|
+
sourceEnd: list.sourceEnd,
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
for (const item of list.items)
|
|
160
|
+
if (item.children)
|
|
161
|
+
checkAxes(item.children, list.axis ?? parentAxis, issues);
|
|
162
|
+
}
|
|
163
|
+
function checkOverflow(list, issues) {
|
|
164
|
+
if (list.items.length > 1) {
|
|
165
|
+
for (const end of ['start', 'end']) {
|
|
166
|
+
const total = list.items.reduce((sum, it) => sum + (it.size.star ? 0 : sizeAt(it.size, end)), 0);
|
|
167
|
+
if (total > 100 + 1e-6) {
|
|
168
|
+
issues.push({ kind: 'overflow', message: `the sizes add up to ${round1(total)} %`, total: round1(total), sourceStart: list.sourceStart, sourceEnd: list.sourceEnd });
|
|
169
|
+
break;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
for (const item of list.items)
|
|
174
|
+
if (item.children)
|
|
175
|
+
checkOverflow(item.children, issues);
|
|
176
|
+
}
|
|
177
|
+
function sizeAt(size, end) {
|
|
178
|
+
const v = end === 'end' ? size.end ?? size.start : size.start;
|
|
179
|
+
return Math.max(0, v ?? 0);
|
|
180
|
+
}
|
|
181
|
+
/** The axis a list's children split on: its own, or for a one-item list
|
|
182
|
+
* the cross axis of its parent (rows at the top). */
|
|
183
|
+
export function crossAxis(axis) {
|
|
184
|
+
return axis === 'rows' ? 'columns' : 'rows';
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* The line positions of a list (cumulative percent of its cell) at each end
|
|
188
|
+
* of the cross axis: `lines[b]` is the line between items `b` and `b + 1`.
|
|
189
|
+
* Stars share what the fixed sizes leave; sizes past 100 are scaled down so
|
|
190
|
+
* every star keeps {@link COMIC_MIN_CELL_PERCENT}; the last item runs to
|
|
191
|
+
* 100. Lines never run backwards.
|
|
192
|
+
*/
|
|
193
|
+
export function comicSplitLines(list) {
|
|
194
|
+
return { start: linesAt(list, 'start'), end: linesAt(list, 'end') };
|
|
195
|
+
}
|
|
196
|
+
function linesAt(list, end) {
|
|
197
|
+
const sizes = resolvedSizes(list, end);
|
|
198
|
+
const out = [];
|
|
199
|
+
let sum = 0;
|
|
200
|
+
for (let i = 0; i < sizes.length - 1; i++) {
|
|
201
|
+
sum += sizes[i];
|
|
202
|
+
out.push(Math.min(100, Math.max(out[i - 1] ?? 0, sum)));
|
|
203
|
+
}
|
|
204
|
+
return out;
|
|
205
|
+
}
|
|
206
|
+
/** The sizes of a list's items at one end, in percent, before the last item
|
|
207
|
+
* is stretched to 100. */
|
|
208
|
+
function resolvedSizes(list, end) {
|
|
209
|
+
const stars = list.items.filter((it) => it.size.star).length;
|
|
210
|
+
const fixed = list.items.reduce((sum, it) => sum + (it.size.star ? 0 : sizeAt(it.size, end)), 0);
|
|
211
|
+
const room = 100 - stars * (stars > 0 ? COMIC_MIN_CELL_PERCENT : 0);
|
|
212
|
+
const scale = fixed > (stars > 0 ? room : 100) && fixed > 0 ? (stars > 0 ? room : 100) / fixed : 1;
|
|
213
|
+
const left = Math.max(0, 100 - fixed * scale);
|
|
214
|
+
return list.items.map((it) => (it.size.star ? left / stars : sizeAt(it.size, end) * scale));
|
|
215
|
+
}
|
|
216
|
+
/** The list at `path` (item indices walked down from the top list). */
|
|
217
|
+
export function comicSplitListAt(tree, path) {
|
|
218
|
+
let list = tree;
|
|
219
|
+
for (const i of path) {
|
|
220
|
+
list = list?.items[i]?.children;
|
|
221
|
+
if (!list)
|
|
222
|
+
return undefined;
|
|
223
|
+
}
|
|
224
|
+
return list;
|
|
225
|
+
}
|
|
226
|
+
/** Leaf cells in reading order (tree order), each with its item path. */
|
|
227
|
+
export function comicSplitLeaves(tree) {
|
|
228
|
+
const out = [];
|
|
229
|
+
const walk = (list, path) => {
|
|
230
|
+
list.items.forEach((item, i) => {
|
|
231
|
+
if (item.children && item.children.items.length > 0)
|
|
232
|
+
walk(item.children, [...path, i]);
|
|
233
|
+
else
|
|
234
|
+
out.push([...path, i]);
|
|
235
|
+
});
|
|
236
|
+
};
|
|
237
|
+
walk(tree, []);
|
|
238
|
+
return out;
|
|
239
|
+
}
|
|
240
|
+
// ---------------------------------------------------------------------------
|
|
241
|
+
// Serialising
|
|
242
|
+
// ---------------------------------------------------------------------------
|
|
243
|
+
/** A number with at most one decimal, no trailing `.0`. */
|
|
244
|
+
function round1(n) {
|
|
245
|
+
return Math.round(n * 10) / 10;
|
|
246
|
+
}
|
|
247
|
+
function formatNumber(n) {
|
|
248
|
+
return String(round1(n));
|
|
249
|
+
}
|
|
250
|
+
function formatSize(size) {
|
|
251
|
+
if (size.star)
|
|
252
|
+
return size.implicit ? '' : '*';
|
|
253
|
+
const pct = size.percent ? '%' : '';
|
|
254
|
+
const a = `${formatNumber(size.start ?? 0)}${pct}`;
|
|
255
|
+
if (size.end === undefined || round1(size.end) === round1(size.start ?? 0))
|
|
256
|
+
return a;
|
|
257
|
+
return `${a}~${formatNumber(size.end)}${pct}`;
|
|
258
|
+
}
|
|
259
|
+
/** Write a tree back as a `split` value: ` / ` between rows, ` | ` between
|
|
260
|
+
* columns, numbers with at most one decimal. */
|
|
261
|
+
export function serializeComicSplit(tree) {
|
|
262
|
+
const list = (l) => l.items.map(item).join(l.axis === 'columns' ? ' | ' : ' / ');
|
|
263
|
+
const item = (it) => {
|
|
264
|
+
const size = formatSize(it.size);
|
|
265
|
+
if (!it.children || it.children.items.length === 0)
|
|
266
|
+
return size === '' ? '*' : size;
|
|
267
|
+
return `${size}${size === '' ? '' : ' '}[${list(it.children)}]`;
|
|
268
|
+
};
|
|
269
|
+
return list(tree);
|
|
270
|
+
}
|
|
271
|
+
// ---------------------------------------------------------------------------
|
|
272
|
+
// Editing
|
|
273
|
+
// ---------------------------------------------------------------------------
|
|
274
|
+
const EPS = 0.06;
|
|
275
|
+
/** Whether giving `edits` to the list puts its lines at the targets. */
|
|
276
|
+
function linesMatch(list, edits, start, end) {
|
|
277
|
+
const items = list.items.map((it, i) => {
|
|
278
|
+
const e = edits.find((x) => x.index === i);
|
|
279
|
+
return e ? { ...it, size: e.size } : it;
|
|
280
|
+
});
|
|
281
|
+
const lines = comicSplitLines({ ...list, items });
|
|
282
|
+
return lines.start.every((v, i) => Math.abs(v - start[i]) < EPS) && lines.end.every((v, i) => Math.abs(v - end[i]) < EPS);
|
|
283
|
+
}
|
|
284
|
+
function fixedSize(old, a, b) {
|
|
285
|
+
const size = { star: false, start: round1(Math.max(0, a)), sourceStart: old.sourceStart, sourceEnd: old.sourceEnd };
|
|
286
|
+
if (Math.abs(round1(b) - round1(a)) > 1e-9)
|
|
287
|
+
size.end = round1(Math.max(0, b));
|
|
288
|
+
if (old.percent)
|
|
289
|
+
size.percent = true;
|
|
290
|
+
return size;
|
|
291
|
+
}
|
|
292
|
+
/** The fewest size edits that put a list's lines at `start` / `end`,
|
|
293
|
+
* keeping `*` sizes where the result allows. */
|
|
294
|
+
function editsFor(list, start, end, touched) {
|
|
295
|
+
const n = list.items.length;
|
|
296
|
+
const want = (i) => [
|
|
297
|
+
(i < n - 1 ? start[i] : 100) - (i > 0 ? start[i - 1] : 0),
|
|
298
|
+
(i < n - 1 ? end[i] : 100) - (i > 0 ? end[i - 1] : 0),
|
|
299
|
+
];
|
|
300
|
+
const fixedEdit = (i) => {
|
|
301
|
+
const [a, b] = want(i);
|
|
302
|
+
return { index: i, size: fixedSize(list.items[i].size, a, b) };
|
|
303
|
+
};
|
|
304
|
+
// 1. Only the touched items that are not stars.
|
|
305
|
+
const candidates = [];
|
|
306
|
+
const nonStars = touched.filter((i) => !list.items[i].size.star).map(fixedEdit);
|
|
307
|
+
candidates.push(nonStars);
|
|
308
|
+
// 2. One touched star written out, the other kept.
|
|
309
|
+
for (const i of touched)
|
|
310
|
+
if (list.items[i].size.star)
|
|
311
|
+
candidates.push([...nonStars, fixedEdit(i)]);
|
|
312
|
+
// 3. Every touched item fixed.
|
|
313
|
+
candidates.push(touched.map(fixedEdit));
|
|
314
|
+
for (const edits of candidates)
|
|
315
|
+
if (linesMatch(list, edits, start, end))
|
|
316
|
+
return edits;
|
|
317
|
+
// 4. Every item fixed.
|
|
318
|
+
return list.items.map((_, i) => fixedEdit(i));
|
|
319
|
+
}
|
|
320
|
+
function applyEdits(src, list, edits) {
|
|
321
|
+
const sorted = [...edits].sort((x, y) => list.items[y.index].size.sourceStart - list.items[x.index].size.sourceStart);
|
|
322
|
+
let out = src;
|
|
323
|
+
for (const e of sorted) {
|
|
324
|
+
const old = list.items[e.index].size;
|
|
325
|
+
let text = formatSize(e.size);
|
|
326
|
+
// An implicit size followed by its bracket needs a space.
|
|
327
|
+
if (old.implicit && src[old.sourceEnd] === '[')
|
|
328
|
+
text += ' ';
|
|
329
|
+
out = out.slice(0, old.sourceStart) + text + out.slice(old.sourceEnd);
|
|
330
|
+
}
|
|
331
|
+
return out;
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* Move the split line between children `boundary` and `boundary + 1` of the
|
|
335
|
+
* list at `path` to `newPercentAtStart` (cumulative percent of the parent
|
|
336
|
+
* cell). With `newPercentAtEnd` the far end goes there (a slant); without
|
|
337
|
+
* it the line keeps its slant, both ends moving by the same amount. The
|
|
338
|
+
* line is clamped so every cell keeps {@link COMIC_MIN_CELL_PERCENT}. Only
|
|
339
|
+
* the sizes that change are rewritten, in place; `*` stays where the
|
|
340
|
+
* result allows. Returns `src` unchanged when the path names no line.
|
|
341
|
+
*/
|
|
342
|
+
export function moveComicSplitLine(src, path, boundary, newPercentAtStart, newPercentAtEnd) {
|
|
343
|
+
const { tree } = parseComicSplit(src);
|
|
344
|
+
const list = comicSplitListAt(tree, path);
|
|
345
|
+
if (!list || boundary < 0 || boundary >= list.items.length - 1)
|
|
346
|
+
return src;
|
|
347
|
+
const lines = comicSplitLines(list);
|
|
348
|
+
const start = [...lines.start];
|
|
349
|
+
const end = [...lines.end];
|
|
350
|
+
const lo = (arr) => (boundary > 0 ? arr[boundary - 1] : 0) + COMIC_MIN_CELL_PERCENT;
|
|
351
|
+
const hi = (arr) => (boundary < arr.length - 1 ? arr[boundary + 1] : 100) - COMIC_MIN_CELL_PERCENT;
|
|
352
|
+
const clamp = (v, arr) => Math.max(lo(arr), Math.min(hi(arr), v));
|
|
353
|
+
let s;
|
|
354
|
+
let e;
|
|
355
|
+
if (newPercentAtEnd === undefined) {
|
|
356
|
+
const delta = newPercentAtStart - start[boundary];
|
|
357
|
+
const minDelta = Math.max(lo(start) - start[boundary], lo(end) - end[boundary]);
|
|
358
|
+
const maxDelta = Math.min(hi(start) - start[boundary], hi(end) - end[boundary]);
|
|
359
|
+
const d = Math.max(minDelta, Math.min(maxDelta, delta));
|
|
360
|
+
s = start[boundary] + d;
|
|
361
|
+
e = end[boundary] + d;
|
|
362
|
+
}
|
|
363
|
+
else {
|
|
364
|
+
s = clamp(newPercentAtStart, start);
|
|
365
|
+
e = clamp(newPercentAtEnd, end);
|
|
366
|
+
}
|
|
367
|
+
start[boundary] = round1(s);
|
|
368
|
+
end[boundary] = round1(e);
|
|
369
|
+
const edits = editsFor(list, start, end, [boundary, boundary + 1]);
|
|
370
|
+
return applyEdits(src, list, edits);
|
|
371
|
+
}
|
|
372
|
+
function cloneList(list) {
|
|
373
|
+
return {
|
|
374
|
+
...list,
|
|
375
|
+
items: list.items.map((it) => ({ ...it, size: { ...it.size }, ...(it.children ? { children: cloneList(it.children) } : {}) })),
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
/** The sizes of a list rewritten as fixed numbers (each end), its lines
|
|
379
|
+
* unchanged — for edits that add or remove an item. */
|
|
380
|
+
function sizesOf(list) {
|
|
381
|
+
const lines = comicSplitLines(list);
|
|
382
|
+
const n = list.items.length;
|
|
383
|
+
return list.items.map((_, i) => ({
|
|
384
|
+
start: (i < n - 1 ? lines.start[i] : 100) - (i > 0 ? lines.start[i - 1] : 0),
|
|
385
|
+
end: (i < n - 1 ? lines.end[i] : 100) - (i > 0 ? lines.end[i - 1] : 0),
|
|
386
|
+
}));
|
|
387
|
+
}
|
|
388
|
+
function sizeFrom(a, b, like) {
|
|
389
|
+
return fixedSize({ star: false, sourceStart: 0, sourceEnd: 0, ...(like?.percent ? { percent: true } : {}) }, a, b);
|
|
390
|
+
}
|
|
391
|
+
const STAR = { star: true, sourceStart: 0, sourceEnd: 0 };
|
|
392
|
+
/**
|
|
393
|
+
* Split the cell at `cellPath` (item indices walked down from the top list)
|
|
394
|
+
* in two along `axis` (`'rows'`: one above the other). A cell whose list
|
|
395
|
+
* runs along `axis` gets a sibling after it, the two sharing its size; any
|
|
396
|
+
* other cell is split by a bracketed list (`30` → `30 [* | *]`). Returns the
|
|
397
|
+
* new `split` value, re-serialised (`serializeComicSplit`).
|
|
398
|
+
*/
|
|
399
|
+
export function splitComicCell(src, cellPath, axis) {
|
|
400
|
+
const { tree } = parseComicSplit(src);
|
|
401
|
+
const root = cloneList(tree);
|
|
402
|
+
if (cellPath.length === 0)
|
|
403
|
+
return src;
|
|
404
|
+
const parentPath = cellPath.slice(0, -1);
|
|
405
|
+
const index = cellPath[cellPath.length - 1];
|
|
406
|
+
const list = comicSplitListAt(root, parentPath);
|
|
407
|
+
const item = list?.items[index];
|
|
408
|
+
if (!list || !item)
|
|
409
|
+
return src;
|
|
410
|
+
// The axis of the list above `list` (a list may not repeat it).
|
|
411
|
+
const grand = parentPath.length > 0 ? comicSplitListAt(root, parentPath.slice(0, -1)) : undefined;
|
|
412
|
+
const grandAxis = grand?.axis;
|
|
413
|
+
const listAxis = list.axis ?? (grandAxis ? crossAxis(grandAxis) : undefined);
|
|
414
|
+
if (listAxis === undefined || listAxis === axis) {
|
|
415
|
+
// A sibling on the list's own axis.
|
|
416
|
+
const stars = list.items.filter((it) => it.size.star).length;
|
|
417
|
+
let first;
|
|
418
|
+
let second;
|
|
419
|
+
if (item.size.star && stars === 1) {
|
|
420
|
+
const s = sizesOf(list)[index];
|
|
421
|
+
first = sizeFrom(s.start / 2, s.end / 2);
|
|
422
|
+
second = { ...STAR };
|
|
423
|
+
}
|
|
424
|
+
else if (item.size.star) {
|
|
425
|
+
// Several stars: the others keep their share if this one is written
|
|
426
|
+
// out as two halves.
|
|
427
|
+
const s = sizesOf(list)[index];
|
|
428
|
+
first = sizeFrom(s.start / 2, s.end / 2);
|
|
429
|
+
second = sizeFrom(s.start / 2, s.end / 2);
|
|
430
|
+
}
|
|
431
|
+
else {
|
|
432
|
+
const a = (item.size.start ?? 0) / 2;
|
|
433
|
+
const b = (item.size.end ?? item.size.start ?? 0) / 2;
|
|
434
|
+
first = sizeFrom(a, b, item.size);
|
|
435
|
+
second = sizeFrom(a, b, item.size);
|
|
436
|
+
// The last item of a list runs to 100: keep it a star when it was
|
|
437
|
+
// stretched, so the line stays put.
|
|
438
|
+
if (index === list.items.length - 1) {
|
|
439
|
+
const s = sizesOf(list)[index];
|
|
440
|
+
first = sizeFrom(s.start / 2, s.end / 2, item.size);
|
|
441
|
+
second = { ...STAR };
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
const firstItem = { ...item, size: first };
|
|
445
|
+
const secondItem = { size: second, sourceStart: 0, sourceEnd: 0 };
|
|
446
|
+
list.items.splice(index, 1, firstItem, secondItem);
|
|
447
|
+
list.axis = axis;
|
|
448
|
+
return serializeComicSplit(root);
|
|
449
|
+
}
|
|
450
|
+
// Across the list's axis: a bracketed list inside the cell.
|
|
451
|
+
if (item.children && item.children.items.length > 1) {
|
|
452
|
+
// Already split that way: one more child at the end.
|
|
453
|
+
const kids = item.children;
|
|
454
|
+
const last = kids.items[kids.items.length - 1];
|
|
455
|
+
const s = sizesOf(kids)[kids.items.length - 1];
|
|
456
|
+
kids.items[kids.items.length - 1] = { ...last, size: sizeFrom(s.start / 2, s.end / 2, last.size.star ? undefined : last.size) };
|
|
457
|
+
kids.items.push({ size: { ...STAR }, sourceStart: 0, sourceEnd: 0 });
|
|
458
|
+
return serializeComicSplit(root);
|
|
459
|
+
}
|
|
460
|
+
item.children = {
|
|
461
|
+
axis,
|
|
462
|
+
items: [{ size: { ...STAR }, sourceStart: 0, sourceEnd: 0 }, { size: { ...STAR }, sourceStart: 0, sourceEnd: 0 }],
|
|
463
|
+
sourceStart: 0,
|
|
464
|
+
sourceEnd: 0,
|
|
465
|
+
};
|
|
466
|
+
if (item.size.implicit)
|
|
467
|
+
item.size = { ...STAR };
|
|
468
|
+
return serializeComicSplit(root);
|
|
469
|
+
}
|
|
470
|
+
/**
|
|
471
|
+
* Merge children `boundary` and `boundary + 1` of the list at `path` into one
|
|
472
|
+
* cell spanning both (the split line between them goes). The merged cell
|
|
473
|
+
* keeps the first one's own split, if any. A bracketed list left with one
|
|
474
|
+
* cell loses its brackets. Returns the new `split` value, re-serialised.
|
|
475
|
+
*/
|
|
476
|
+
export function mergeComicCells(src, path, boundary) {
|
|
477
|
+
const { tree } = parseComicSplit(src);
|
|
478
|
+
const root = cloneList(tree);
|
|
479
|
+
const list = comicSplitListAt(root, path);
|
|
480
|
+
if (!list || boundary < 0 || boundary >= list.items.length - 1)
|
|
481
|
+
return src;
|
|
482
|
+
const sizes = sizesOf(list);
|
|
483
|
+
const a = list.items[boundary];
|
|
484
|
+
const b = list.items[boundary + 1];
|
|
485
|
+
// The lines that stay, which the merged size must keep where they are.
|
|
486
|
+
const lines = comicSplitLines(list);
|
|
487
|
+
const keep = (arr) => arr.filter((_, i) => i !== boundary);
|
|
488
|
+
const fixed = sizeFrom(sizes[boundary].start + sizes[boundary + 1].start, sizes[boundary].end + sizes[boundary + 1].end, a.size.star ? (b.size.star ? undefined : b.size) : a.size);
|
|
489
|
+
const trial = (size) => {
|
|
490
|
+
const items = [...list.items];
|
|
491
|
+
items.splice(boundary, 2, { ...a, size });
|
|
492
|
+
const got = comicSplitLines({ ...list, items });
|
|
493
|
+
const start = keep(lines.start);
|
|
494
|
+
const end = keep(lines.end);
|
|
495
|
+
return got.start.every((v, i) => Math.abs(v - start[i]) < EPS) && got.end.every((v, i) => Math.abs(v - end[i]) < EPS);
|
|
496
|
+
};
|
|
497
|
+
const size = a.size.star || b.size.star ? (trial({ ...STAR }) ? { ...STAR } : fixed) : fixed;
|
|
498
|
+
const merged = { ...a, size };
|
|
499
|
+
list.items.splice(boundary, 2, merged);
|
|
500
|
+
if (list.items.length === 1) {
|
|
501
|
+
delete list.axis;
|
|
502
|
+
// A bracketed list of one cell: the brackets go.
|
|
503
|
+
if (path.length > 0) {
|
|
504
|
+
const parent = comicSplitListAt(root, path.slice(0, -1));
|
|
505
|
+
const owner = parent.items[path[path.length - 1]];
|
|
506
|
+
if (merged.children && merged.children.items.length > 1)
|
|
507
|
+
owner.children = merged.children;
|
|
508
|
+
else
|
|
509
|
+
delete owner.children;
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
return serializeComicSplit(root);
|
|
513
|
+
}
|
|
514
|
+
//# sourceMappingURL=split.js.map
|