@segnavia/html 0.26.0 → 0.28.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/base64.d.ts +4 -0
- package/dist/base64.js +51 -0
- package/dist/bindings.d.ts +4 -1
- package/dist/bindings.js +19 -2
- package/dist/book/book-document.js +146 -65
- package/dist/book/book-held.js +182 -0
- package/dist/book/book-view.d.ts +5 -0
- package/dist/book/book-view.js +26 -0
- package/dist/book/furniture.d.ts +14 -0
- package/dist/book/furniture.js +36 -0
- package/dist/book/notes.js +18 -9
- package/dist/book/paginate-book.d.ts +11 -0
- package/dist/book/paginate-book.js +195 -0
- package/dist/book/paginate-columns.d.ts +8 -0
- package/dist/book/paginate-columns.js +119 -0
- package/dist/book/paginate-keeps.d.ts +4 -0
- package/dist/book/paginate-keeps.js +80 -0
- package/dist/book/paginate-marks.d.ts +7 -0
- package/dist/book/paginate-marks.js +34 -0
- package/dist/book/paginate-notes.d.ts +21 -0
- package/dist/book/paginate-notes.js +105 -0
- package/dist/book/paginate-sequence.d.ts +4 -0
- package/dist/book/paginate-sequence.js +267 -0
- package/dist/book/paginate-target.d.ts +13 -0
- package/dist/book/paginate-target.js +36 -0
- package/dist/book/paginate-types.d.ts +170 -0
- package/dist/book/types.d.ts +1 -1
- package/dist/book-css.d.ts +5 -0
- package/dist/book-css.js +14 -0
- package/dist/control-char.js +10 -0
- package/dist/css-tokens.js +189 -0
- package/dist/font-css.d.ts +11 -0
- package/dist/font-css.js +75 -0
- package/dist/font-format.d.ts +4 -0
- package/dist/font-format.js +11 -0
- package/dist/font-references.d.ts +4 -0
- package/dist/font-references.js +192 -0
- package/dist/index.d.ts +15 -2
- package/dist/index.js +14 -2
- package/dist/motifs.d.ts +32 -0
- package/dist/motifs.js +245 -0
- package/dist/printed-pages.d.ts +42 -0
- package/dist/printed-pages.js +97 -0
- package/dist/sanitize-css.d.ts +6 -0
- package/dist/sanitize-css.js +308 -0
- package/dist/sanitize.d.ts +1 -0
- package/dist/sanitize.js +37 -15
- package/dist/unicode-range.d.ts +11 -0
- package/dist/unicode-range.js +86 -0
- package/package.json +2 -2
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { PaginateBookInput, PaginateBookResult, PaginatePageFill, PaginatePageNote, PaginateUnit } from "./paginate-types.js";
|
|
2
|
+
//#region src/book/paginate-sequence.d.ts
|
|
3
|
+
export declare function paginateSequence(input: PaginateBookInput, fillPage: (units: PaginateUnit[], index: number, pending: PaginatePageNote[]) => PaginatePageFill): PaginateBookResult;
|
|
4
|
+
//#endregion
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
import { paginateColumns } from "./paginate-columns.js";
|
|
2
|
+
import { paginateMarks } from "./paginate-marks.js";
|
|
3
|
+
//#region src/book/paginate-sequence.ts
|
|
4
|
+
function paginateSequence(input, fillPage) {
|
|
5
|
+
function emptyMarks() {
|
|
6
|
+
return Object.create(null);
|
|
7
|
+
}
|
|
8
|
+
function columnRefusal(block) {
|
|
9
|
+
const ceiling = 12;
|
|
10
|
+
const count = block.columns;
|
|
11
|
+
if (count === void 0) return void 0;
|
|
12
|
+
if (Number.isInteger(count) && count >= 1 && count <= ceiling) return void 0;
|
|
13
|
+
const position = `chapter ${block.position.chapter} block ${block.position.block}`;
|
|
14
|
+
return {
|
|
15
|
+
tag: block.tag,
|
|
16
|
+
position: block.position,
|
|
17
|
+
message: `The ${block.tag} at ${position} could not establish a column count; use an integer from 1 to 12 to clear this refusal.`
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
function pagesRefusal(flow) {
|
|
21
|
+
if (flow.kind !== "fixed") return void 0;
|
|
22
|
+
if (Number.isSafeInteger(flow.pages) && flow.pages >= 0) return void 0;
|
|
23
|
+
return {
|
|
24
|
+
flow: flow.id,
|
|
25
|
+
message: `The ${flow.id} flow could not establish a page count; use a safe integer of 0 or more to clear this refusal.`
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
function boundsRefusal() {
|
|
29
|
+
for (const flow of input.flows) {
|
|
30
|
+
const pages = pagesRefusal(flow);
|
|
31
|
+
if (pages) return pages;
|
|
32
|
+
if (flow.kind === "fixed") continue;
|
|
33
|
+
for (const block of flow.blocks) {
|
|
34
|
+
const columns = columnRefusal(block);
|
|
35
|
+
if (columns) return columns;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
function isFront(flow) {
|
|
40
|
+
if (flow.kind === "fixed") return flow.sequence === "front";
|
|
41
|
+
return flow.kind === "front" || flow.kind === "contents";
|
|
42
|
+
}
|
|
43
|
+
function unitsOf(flow) {
|
|
44
|
+
if (flow.kind === "fixed") return [];
|
|
45
|
+
const units = [];
|
|
46
|
+
for (const block of flow.blocks) for (const [index, line] of block.lines.entries()) {
|
|
47
|
+
const previous = units[units.length - 1];
|
|
48
|
+
const refs = (block.footnoteRefs ?? []).filter((ref) => ref.line === index).map((ref) => ref.note);
|
|
49
|
+
const unit = {
|
|
50
|
+
flowId: flow.id,
|
|
51
|
+
block,
|
|
52
|
+
index,
|
|
53
|
+
top: line.top,
|
|
54
|
+
bottom: line.bottom,
|
|
55
|
+
refs
|
|
56
|
+
};
|
|
57
|
+
if (previous) {
|
|
58
|
+
unit.prevBottom = previous.bottom;
|
|
59
|
+
previous.nextTop = line.top;
|
|
60
|
+
}
|
|
61
|
+
units.push(unit);
|
|
62
|
+
}
|
|
63
|
+
return units;
|
|
64
|
+
}
|
|
65
|
+
function flowParents(flow) {
|
|
66
|
+
return flow.parents === void 0 ? {} : { parents: flow.parents };
|
|
67
|
+
}
|
|
68
|
+
function openingOf(flow) {
|
|
69
|
+
if (flow.opens === "recto" || flow.opens === "verso" || flow.opens === "any") return flow.opens;
|
|
70
|
+
return input.settings.rectoOpenings ? "recto" : "any";
|
|
71
|
+
}
|
|
72
|
+
function needsOpeningBlank(opens, count) {
|
|
73
|
+
const nextIsRecto = count % 2 === 0;
|
|
74
|
+
if (opens === "recto") return !nextIsRecto;
|
|
75
|
+
if (opens === "verso") return nextIsRecto;
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
function makeBlank(number, sequence, flow) {
|
|
79
|
+
return {
|
|
80
|
+
kind: "blank",
|
|
81
|
+
number,
|
|
82
|
+
sequence,
|
|
83
|
+
flow: flow.id,
|
|
84
|
+
role: "blank",
|
|
85
|
+
windows: [],
|
|
86
|
+
notes: [],
|
|
87
|
+
blank: true,
|
|
88
|
+
sectionOpening: false,
|
|
89
|
+
...flowParents(flow)
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
function makeContent(part, number, flow, opener, placed, fragments, marks) {
|
|
93
|
+
const layout = paginateColumns(placed);
|
|
94
|
+
return {
|
|
95
|
+
kind: part,
|
|
96
|
+
number,
|
|
97
|
+
sequence: part,
|
|
98
|
+
flow: flow.id,
|
|
99
|
+
role: opener ? "opener" : "body",
|
|
100
|
+
windows: layout.windows,
|
|
101
|
+
notes: fragments,
|
|
102
|
+
...layout.headerRepeat ? { headerRepeat: layout.headerRepeat } : {},
|
|
103
|
+
blank: false,
|
|
104
|
+
sectionOpening: opener,
|
|
105
|
+
...opener || flow.runningHead === void 0 ? {} : { runningHead: flow.runningHead },
|
|
106
|
+
marks,
|
|
107
|
+
...flowParents(flow)
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
function makeFixed(part, number, flow, opener, marks) {
|
|
111
|
+
const templated = flow.kind === "fixed" && flow.role === "body";
|
|
112
|
+
return {
|
|
113
|
+
kind: part,
|
|
114
|
+
number,
|
|
115
|
+
sequence: part,
|
|
116
|
+
flow: flow.id,
|
|
117
|
+
role: templated ? "body" : "fixed",
|
|
118
|
+
windows: [],
|
|
119
|
+
notes: [],
|
|
120
|
+
blank: false,
|
|
121
|
+
sectionOpening: opener,
|
|
122
|
+
...opener && !templated || flow.runningHead === void 0 ? {} : { runningHead: flow.runningHead },
|
|
123
|
+
marks,
|
|
124
|
+
...flowParents(flow)
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
function emitMarked(part, flow, opener, placed, fragments, pages, carried) {
|
|
128
|
+
const marked = paginateMarks(placed, carried);
|
|
129
|
+
pages.push(makeContent(part, pages.length + 1, flow, opener, placed, fragments, marked.marks));
|
|
130
|
+
return marked.carried;
|
|
131
|
+
}
|
|
132
|
+
function appendFixed(flow, part, pages, continued, carried) {
|
|
133
|
+
const count = flow.kind === "fixed" ? flow.pages : 0;
|
|
134
|
+
let next = carried;
|
|
135
|
+
for (let index = 0; index < count; index += 1) {
|
|
136
|
+
const opener = index === 0;
|
|
137
|
+
const marked = paginateMarks([], next);
|
|
138
|
+
next = marked.carried;
|
|
139
|
+
pages.push(makeFixed(part, pages.length + 1, flow, opener, marked.marks));
|
|
140
|
+
}
|
|
141
|
+
return {
|
|
142
|
+
pending: continued,
|
|
143
|
+
carried: next
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
function paginateFlow(flow, part, pages, continued, carried) {
|
|
147
|
+
if (flow.kind === "fixed") return appendFixed(flow, part, pages, continued, carried);
|
|
148
|
+
const units = unitsOf(flow);
|
|
149
|
+
let index = 0;
|
|
150
|
+
let pending = continued;
|
|
151
|
+
let opener = true;
|
|
152
|
+
let nextCarried = carried;
|
|
153
|
+
while (index < units.length || pending.length > 0) {
|
|
154
|
+
const page = fillPage(units, index, pending);
|
|
155
|
+
if (page.refusal) return {
|
|
156
|
+
refusal: page.refusal,
|
|
157
|
+
pending,
|
|
158
|
+
carried: nextCarried
|
|
159
|
+
};
|
|
160
|
+
if (page.done || page.placed.length === 0 && page.fragments.length === 0) return {
|
|
161
|
+
pending,
|
|
162
|
+
carried: nextCarried
|
|
163
|
+
};
|
|
164
|
+
nextCarried = emitMarked(part, flow, opener && page.placed.length > 0, page.placed, page.fragments, pages, nextCarried);
|
|
165
|
+
opener = opener && page.placed.length === 0;
|
|
166
|
+
index = page.index;
|
|
167
|
+
pending = page.pending;
|
|
168
|
+
}
|
|
169
|
+
return {
|
|
170
|
+
pending,
|
|
171
|
+
carried: nextCarried
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
function flushNotes(continued, flow, part, pages, carried) {
|
|
175
|
+
let pending = continued;
|
|
176
|
+
let nextCarried = carried;
|
|
177
|
+
while (pending.length > 0) {
|
|
178
|
+
const page = fillPage([], 0, pending);
|
|
179
|
+
if (page.refusal) return {
|
|
180
|
+
refusal: page.refusal,
|
|
181
|
+
carried: nextCarried
|
|
182
|
+
};
|
|
183
|
+
if (page.done || page.placed.length === 0 && page.fragments.length === 0) return { carried: nextCarried };
|
|
184
|
+
nextCarried = emitMarked(part, flow, false, page.placed, page.fragments, pages, nextCarried);
|
|
185
|
+
pending = page.pending;
|
|
186
|
+
}
|
|
187
|
+
return { carried: nextCarried };
|
|
188
|
+
}
|
|
189
|
+
function flushBeforeFixed(flow, previous, continued, carried, part, pages) {
|
|
190
|
+
if (flow.kind !== "fixed" || continued.length === 0 || !previous) return {
|
|
191
|
+
continued,
|
|
192
|
+
carried
|
|
193
|
+
};
|
|
194
|
+
const flushed = flushNotes(continued, previous, part, pages, carried);
|
|
195
|
+
if ("refusal" in flushed && flushed.refusal) return { refusal: flushed.refusal };
|
|
196
|
+
return {
|
|
197
|
+
continued: [],
|
|
198
|
+
carried: flushed.carried
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
function emitFlow(flow, previous, continued, carried, part, pages, physicalOffset) {
|
|
202
|
+
const held = flushBeforeFixed(flow, previous, continued, carried, part, pages);
|
|
203
|
+
if ("refusal" in held && held.refusal) return { refusal: held.refusal };
|
|
204
|
+
if (needsOpeningBlank(openingOf(flow), physicalOffset + pages.length)) pages.push(makeBlank(pages.length + 1, part, flow));
|
|
205
|
+
const result = paginateFlow(flow, part, pages, held.continued, held.carried);
|
|
206
|
+
if ("refusal" in result && result.refusal) return { refusal: result.refusal };
|
|
207
|
+
return {
|
|
208
|
+
continued: result.pending,
|
|
209
|
+
carried: result.carried
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
function paginatePart(flows, part, physicalOffset = 0) {
|
|
213
|
+
const pages = [];
|
|
214
|
+
let continued = [];
|
|
215
|
+
let carried = emptyMarks();
|
|
216
|
+
let previous;
|
|
217
|
+
for (const flow of flows) {
|
|
218
|
+
const result = emitFlow(flow, previous, continued, carried, part, pages, physicalOffset);
|
|
219
|
+
if ("refusal" in result && result.refusal) return {
|
|
220
|
+
pages,
|
|
221
|
+
refusals: [result.refusal]
|
|
222
|
+
};
|
|
223
|
+
continued = result.continued;
|
|
224
|
+
carried = result.carried;
|
|
225
|
+
previous = flow;
|
|
226
|
+
}
|
|
227
|
+
const last = flows[flows.length - 1];
|
|
228
|
+
if (last) {
|
|
229
|
+
const flushed = flushNotes(continued, last, part, pages, carried);
|
|
230
|
+
if ("refusal" in flushed && flushed.refusal) return {
|
|
231
|
+
pages,
|
|
232
|
+
refusals: [flushed.refusal]
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
return {
|
|
236
|
+
pages,
|
|
237
|
+
refusals: []
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
const bounded = boundsRefusal();
|
|
241
|
+
if (bounded) return {
|
|
242
|
+
pages: [],
|
|
243
|
+
refusals: [bounded]
|
|
244
|
+
};
|
|
245
|
+
const frontFlows = input.flows.filter(isFront);
|
|
246
|
+
const bodyFlows = input.flows.filter((flow) => !isFront(flow));
|
|
247
|
+
const front = paginatePart(frontFlows, "front");
|
|
248
|
+
const firstBody = bodyFlows[0];
|
|
249
|
+
const lastFront = frontFlows[frontFlows.length - 1];
|
|
250
|
+
const padFront = input.settings.rectoOpenings ? front.pages.length % 2 === 1 : firstBody !== void 0 && needsOpeningBlank(openingOf(firstBody), front.pages.length);
|
|
251
|
+
if (front.pages.length > 0 && lastFront && padFront) front.pages.push(makeBlank(front.pages.length + 1, "front", lastFront));
|
|
252
|
+
const body = paginatePart(bodyFlows, "body", front.pages.length);
|
|
253
|
+
if (body.refusals.length > 0) return {
|
|
254
|
+
pages: [...front.pages, ...body.pages],
|
|
255
|
+
refusals: body.refusals
|
|
256
|
+
};
|
|
257
|
+
if (front.refusals.length > 0) return {
|
|
258
|
+
pages: [...front.pages, ...body.pages],
|
|
259
|
+
refusals: front.refusals
|
|
260
|
+
};
|
|
261
|
+
return {
|
|
262
|
+
pages: [...front.pages, ...body.pages],
|
|
263
|
+
refusals: []
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
//#endregion
|
|
267
|
+
export { paginateSequence };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { PaginateBookPage } from "./paginate-types.js";
|
|
2
|
+
//#region src/book/paginate-target.d.ts
|
|
3
|
+
export type PaginateTargetPage = Pick<PaginateBookPage, 'blank' | 'flow' | 'role' | 'sectionOpening' | 'windows'>;
|
|
4
|
+
export interface PaginateTarget {
|
|
5
|
+
flow: string;
|
|
6
|
+
heldPage?: number;
|
|
7
|
+
top?: number;
|
|
8
|
+
}
|
|
9
|
+
export declare function heldPageNumber(pages: PaginateTargetPage[], index: number): number;
|
|
10
|
+
export declare function windowPageIndex(pages: PaginateTargetPage[], flow: string, top: number): number | undefined;
|
|
11
|
+
export declare function openerPageIndex(pages: PaginateTargetPage[], flow: string): number | undefined;
|
|
12
|
+
export declare function pageIndexForTarget(pages: PaginateTargetPage[], target: PaginateTarget): number | undefined;
|
|
13
|
+
//#endregion
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
//#region src/book/paginate-target.ts
|
|
2
|
+
function heldPageNumber(pages, index) {
|
|
3
|
+
const page = pages[index];
|
|
4
|
+
if (!page) return 0;
|
|
5
|
+
let seen = 0;
|
|
6
|
+
for (let i = 0; i <= index; i++) {
|
|
7
|
+
const held = pages[i];
|
|
8
|
+
if (!held || held.flow !== page.flow || held.blank) continue;
|
|
9
|
+
if (held.role !== "fixed" && !(held.role === "body" && held.windows.length === 0)) continue;
|
|
10
|
+
seen += 1;
|
|
11
|
+
}
|
|
12
|
+
return seen;
|
|
13
|
+
}
|
|
14
|
+
function windowPageIndex(pages, flow, top) {
|
|
15
|
+
for (const [index, page] of pages.entries()) {
|
|
16
|
+
if (page.blank) continue;
|
|
17
|
+
for (const win of page.windows) if (win.flow === flow && top >= win.start && top < win.end) return index;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
function openerPageIndex(pages, flow) {
|
|
21
|
+
for (const [index, page] of pages.entries()) if (!page.blank && page.flow === flow && page.sectionOpening) return index;
|
|
22
|
+
}
|
|
23
|
+
function pageIndexForTarget(pages, target) {
|
|
24
|
+
const held = target.heldPage;
|
|
25
|
+
if (held !== void 0 && Number.isSafeInteger(held) && held > 0) {
|
|
26
|
+
for (let index = 0; index < pages.length; index++) if (pages[index]?.flow === target.flow && heldPageNumber(pages, index) === held) return index;
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
if (target.top !== void 0) {
|
|
30
|
+
const windowed = windowPageIndex(pages, target.flow, target.top);
|
|
31
|
+
if (windowed !== void 0) return windowed;
|
|
32
|
+
}
|
|
33
|
+
return openerPageIndex(pages, target.flow);
|
|
34
|
+
}
|
|
35
|
+
//#endregion
|
|
36
|
+
export { heldPageNumber, openerPageIndex, pageIndexForTarget, windowPageIndex };
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { BookOpens, BookSectionParents } from "@segnavia/format";
|
|
2
|
+
//#region src/book/paginate-types.d.ts
|
|
3
|
+
export type PaginateSequence = 'front' | 'body';
|
|
4
|
+
export type PaginatePageRole = 'opener' | 'body' | 'blank' | 'fixed';
|
|
5
|
+
export interface PaginateLine {
|
|
6
|
+
top: number;
|
|
7
|
+
bottom: number;
|
|
8
|
+
}
|
|
9
|
+
export interface PaginateNoteRef {
|
|
10
|
+
note: string;
|
|
11
|
+
line: number;
|
|
12
|
+
}
|
|
13
|
+
export interface PaginateMark {
|
|
14
|
+
name: string;
|
|
15
|
+
value: string;
|
|
16
|
+
line: number;
|
|
17
|
+
}
|
|
18
|
+
export interface PaginateBlock {
|
|
19
|
+
kind: 'heading' | 'figure' | 'table' | 'text';
|
|
20
|
+
tag: string;
|
|
21
|
+
position: {
|
|
22
|
+
chapter: number;
|
|
23
|
+
block: number;
|
|
24
|
+
};
|
|
25
|
+
lines: PaginateLine[];
|
|
26
|
+
columns?: number;
|
|
27
|
+
orphans?: number;
|
|
28
|
+
widows?: number;
|
|
29
|
+
keepWithNext?: boolean;
|
|
30
|
+
keepTogether?: boolean;
|
|
31
|
+
headerHeight?: number;
|
|
32
|
+
footnoteRefs?: PaginateNoteRef[];
|
|
33
|
+
marks?: PaginateMark[];
|
|
34
|
+
}
|
|
35
|
+
export type PaginateFlowParents = BookSectionParents;
|
|
36
|
+
export type PaginateOpens = BookOpens;
|
|
37
|
+
interface PaginateFlowBase {
|
|
38
|
+
id: string;
|
|
39
|
+
runningHead?: string;
|
|
40
|
+
opens?: PaginateOpens;
|
|
41
|
+
parents?: PaginateFlowParents;
|
|
42
|
+
}
|
|
43
|
+
export type PaginateFlow = (PaginateFlowBase & {
|
|
44
|
+
kind: 'front' | 'contents' | 'chapter' | 'endnotes';
|
|
45
|
+
blocks: PaginateBlock[];
|
|
46
|
+
}) | (PaginateFlowBase & {
|
|
47
|
+
kind: 'fixed';
|
|
48
|
+
pages: number;
|
|
49
|
+
sequence?: PaginateSequence;
|
|
50
|
+
role?: 'fixed' | 'body';
|
|
51
|
+
});
|
|
52
|
+
export interface PaginateNote {
|
|
53
|
+
id: string;
|
|
54
|
+
lines: PaginateLine[];
|
|
55
|
+
}
|
|
56
|
+
export interface PaginateBookInput {
|
|
57
|
+
flows: PaginateFlow[];
|
|
58
|
+
notes: PaginateNote[];
|
|
59
|
+
geometry: {
|
|
60
|
+
textHeight: number;
|
|
61
|
+
notesGap: number;
|
|
62
|
+
};
|
|
63
|
+
settings: {
|
|
64
|
+
orphans?: number;
|
|
65
|
+
widows?: number;
|
|
66
|
+
rectoOpenings: boolean;
|
|
67
|
+
direction: 'ltr' | 'rtl';
|
|
68
|
+
endnotePlacement: 'chapter' | 'book';
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
export interface PaginateWindow {
|
|
72
|
+
flow: string;
|
|
73
|
+
start: number;
|
|
74
|
+
end: number;
|
|
75
|
+
top: number;
|
|
76
|
+
column: number;
|
|
77
|
+
columns: number;
|
|
78
|
+
}
|
|
79
|
+
export interface PaginatePageNote {
|
|
80
|
+
id: string;
|
|
81
|
+
whole: boolean;
|
|
82
|
+
start: number;
|
|
83
|
+
end: number;
|
|
84
|
+
}
|
|
85
|
+
export type PaginatePageMarks = Record<string, {
|
|
86
|
+
first: string;
|
|
87
|
+
last: string;
|
|
88
|
+
}>;
|
|
89
|
+
export interface PaginateBookPage {
|
|
90
|
+
kind: 'front' | 'body' | 'blank';
|
|
91
|
+
number: number;
|
|
92
|
+
sequence: PaginateSequence;
|
|
93
|
+
flow: string;
|
|
94
|
+
role: PaginatePageRole;
|
|
95
|
+
windows: PaginateWindow[];
|
|
96
|
+
notes: PaginatePageNote[];
|
|
97
|
+
headerRepeat?: number;
|
|
98
|
+
blank: boolean;
|
|
99
|
+
sectionOpening: boolean;
|
|
100
|
+
runningHead?: string;
|
|
101
|
+
marks?: PaginatePageMarks;
|
|
102
|
+
parents?: PaginateFlowParents;
|
|
103
|
+
}
|
|
104
|
+
export type PaginateBookRefusal = {
|
|
105
|
+
tag: string;
|
|
106
|
+
position: {
|
|
107
|
+
chapter: number;
|
|
108
|
+
block: number;
|
|
109
|
+
};
|
|
110
|
+
message: string;
|
|
111
|
+
} | {
|
|
112
|
+
flow: string;
|
|
113
|
+
message: string;
|
|
114
|
+
} | {
|
|
115
|
+
note: string;
|
|
116
|
+
message: string;
|
|
117
|
+
};
|
|
118
|
+
export interface PaginateBookResult {
|
|
119
|
+
pages: PaginateBookPage[];
|
|
120
|
+
refusals: PaginateBookRefusal[];
|
|
121
|
+
}
|
|
122
|
+
export interface PaginateUnit {
|
|
123
|
+
flowId: string;
|
|
124
|
+
block: PaginateBlock;
|
|
125
|
+
index: number;
|
|
126
|
+
top: number;
|
|
127
|
+
bottom: number;
|
|
128
|
+
refs: string[];
|
|
129
|
+
prevBottom?: number;
|
|
130
|
+
nextTop?: number;
|
|
131
|
+
}
|
|
132
|
+
export interface PaginatePageFill {
|
|
133
|
+
placed: PaginateUnit[];
|
|
134
|
+
fragments: PaginatePageNote[];
|
|
135
|
+
index: number;
|
|
136
|
+
pending: PaginatePageNote[];
|
|
137
|
+
refusal?: PaginateBookRefusal;
|
|
138
|
+
done?: boolean;
|
|
139
|
+
}
|
|
140
|
+
export type PaginateNotesUsed = (placed: PaginateUnit[], fragments: PaginatePageNote[]) => number;
|
|
141
|
+
interface PaginateNotesBase {
|
|
142
|
+
notes: PaginateNote[];
|
|
143
|
+
geometry: {
|
|
144
|
+
textHeight: number;
|
|
145
|
+
notesGap: number;
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
export type PaginateNotesOp = (PaginateNotesBase & {
|
|
149
|
+
op: 'space';
|
|
150
|
+
fragments: PaginatePageNote[];
|
|
151
|
+
}) | (PaginateNotesBase & {
|
|
152
|
+
op: 'continue';
|
|
153
|
+
pending: PaginatePageNote[];
|
|
154
|
+
used: PaginateNotesUsed;
|
|
155
|
+
}) | (PaginateNotesBase & {
|
|
156
|
+
op: 'allocate';
|
|
157
|
+
placed: PaginateUnit[];
|
|
158
|
+
fragments: PaginatePageNote[];
|
|
159
|
+
unit: PaginateUnit;
|
|
160
|
+
used: PaginateNotesUsed;
|
|
161
|
+
}) | (PaginateNotesBase & {
|
|
162
|
+
op: 'recompute';
|
|
163
|
+
placed: PaginateUnit[];
|
|
164
|
+
seed: PaginatePageNote[];
|
|
165
|
+
used: PaginateNotesUsed;
|
|
166
|
+
}) | (PaginateNotesBase & {
|
|
167
|
+
op: 'leftover';
|
|
168
|
+
fragments: PaginatePageNote[];
|
|
169
|
+
});
|
|
170
|
+
//#endregion
|
package/dist/book/types.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ export interface BookDocumentOptions {
|
|
|
8
8
|
}
|
|
9
9
|
export interface BookSectionInfo {
|
|
10
10
|
id: string;
|
|
11
|
-
kind: 'front' | 'contents' | 'chapter' | 'endnotes';
|
|
11
|
+
kind: 'front' | 'contents' | 'chapter' | 'endnotes' | 'designed' | 'templated';
|
|
12
12
|
title?: string;
|
|
13
13
|
runningHead?: string;
|
|
14
14
|
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { CssSanitizeResult } from "./sanitize-css.js";
|
|
2
|
+
//#region src/book-css.d.ts
|
|
3
|
+
export declare function sanitizeBookCss(css: string | undefined): CssSanitizeResult;
|
|
4
|
+
export declare function bookStylesheet(fontCss: string | undefined, bookCss: string | undefined, hostCss: string | undefined): string;
|
|
5
|
+
//#endregion
|
package/dist/book-css.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { sanitizeCss } from "./sanitize-css.js";
|
|
2
|
+
//#region src/book-css.ts
|
|
3
|
+
function sanitizeBookCss(css) {
|
|
4
|
+
const sanitized = sanitizeCss(css ?? "", false, false);
|
|
5
|
+
return {
|
|
6
|
+
css: sanitized.css.replaceAll("<", "\\3c "),
|
|
7
|
+
removed: sanitized.removed
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
function bookStylesheet(fontCss, bookCss, hostCss) {
|
|
11
|
+
return `${fontCss ?? ""}${sanitizeBookCss(bookCss).css}${hostCss ?? ""}`;
|
|
12
|
+
}
|
|
13
|
+
//#endregion
|
|
14
|
+
export { bookStylesheet, sanitizeBookCss };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
//#region src/control-char.ts
|
|
2
|
+
function hasControlChar(value) {
|
|
3
|
+
for (let i = 0; i < value.length; i += 1) {
|
|
4
|
+
const code = value.charCodeAt(i);
|
|
5
|
+
if (code <= 31 || code === 127) return true;
|
|
6
|
+
}
|
|
7
|
+
return false;
|
|
8
|
+
}
|
|
9
|
+
//#endregion
|
|
10
|
+
export { hasControlChar };
|