@segnavia/format 0.37.0 → 0.39.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/board-edit.d.ts +2 -1
- package/dist/board-geometry.d.ts +2 -1
- package/dist/board-section-grid.d.ts +2 -1
- package/dist/board-sections.d.ts +2 -1
- package/dist/board.d.ts +8 -8
- package/dist/board.js +15 -11
- package/dist/book-exports.d.ts +4 -0
- package/dist/book-section.d.ts +225 -3
- package/dist/book-section.js +82 -17
- package/dist/book.d.ts +878 -416
- package/dist/book.js +236 -37
- package/dist/cover.d.ts +337 -0
- package/dist/cover.js +100 -0
- package/dist/deck-from-slides.d.ts +23 -4
- package/dist/deck.d.ts +144 -42
- package/dist/deck.js +22 -24
- package/dist/dependency-policy.d.ts +12 -0
- package/dist/dependency-policy.js +42 -0
- package/dist/direction.d.ts +1 -1
- package/dist/font-collection.d.ts +8 -0
- package/dist/font-collection.js +191 -0
- package/dist/font-face.d.ts +8 -0
- package/dist/font-face.js +24 -0
- package/dist/font-refusal.d.ts +5 -0
- package/dist/font-refusal.js +9 -0
- package/dist/font-signature.d.ts +5 -0
- package/dist/font-signature.js +13 -0
- package/dist/fonts.d.ts +6 -1
- package/dist/fonts.js +3 -1
- package/dist/geometry.d.ts +20 -0
- package/dist/geometry.js +18 -0
- package/dist/image-fit.d.ts +10 -0
- package/dist/image-fit.js +10 -0
- package/dist/imposition-marks.d.ts +1 -1
- package/dist/imposition-schema.d.ts +185 -0
- package/dist/imposition-schema.js +122 -0
- package/dist/imposition.d.ts +8 -6
- package/dist/index.d.ts +29 -1797
- package/dist/index.js +30 -210
- package/dist/json-schemas.d.ts +1860 -0
- package/dist/json-schemas.js +43 -0
- package/dist/local-font-limits.d.ts +15 -0
- package/dist/local-font-limits.js +24 -0
- package/dist/media.d.ts +152 -0
- package/dist/media.js +119 -0
- package/dist/note-series.d.ts +70 -0
- package/dist/note-series.js +153 -0
- package/dist/page.d.ts +174 -0
- package/dist/page.js +37 -0
- package/dist/paper.d.ts +2 -1
- package/dist/paper.js +2 -1
- package/dist/placement-cycle.d.ts +5 -0
- package/dist/placement-cycle.js +30 -0
- package/dist/placement-refusal.d.ts +5 -0
- package/dist/placement-refusal.js +6 -0
- package/dist/placement.d.ts +76 -0
- package/dist/placement.js +100 -0
- package/dist/print.d.ts +72 -0
- package/dist/print.js +38 -0
- package/dist/printed-page-imposition.d.ts +2 -1
- package/dist/printed-pages.d.ts +14 -0
- package/dist/printed-pages.js +14 -1
- package/dist/shots-used.d.ts +0 -1
- package/dist/shots-used.js +2 -2
- package/dist/slots.d.ts +13 -13
- package/package.json +1 -1
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Media } from "./media.js";
|
|
2
|
+
import { PlacementShape } from "./placement.js";
|
|
3
|
+
import { SlotDeclaration, SlotDeclarationInput } from "./slots.js";
|
|
4
|
+
import { DeckShape, Manifest, PublishedShot } from "./deck.js";
|
|
5
|
+
import { Board } from "./board.js";
|
|
6
|
+
import { FontReference, FontReferenceInput, LocalFaceTransport, LocalFacesTransport } from "./fonts.js";
|
|
7
|
+
import { Motif, MotifInput } from "./motif.js";
|
|
8
|
+
import { PrintSetting, PrintSettingInput } from "./paper.js";
|
|
9
|
+
import { BookShape, BookView } from "./book.js";
|
|
10
|
+
import { Page } from "./page.js";
|
|
11
|
+
import { Cover } from "./cover.js";
|
|
12
|
+
import { Imposition } from "./imposition-schema.js";
|
|
13
|
+
import { Lexicon } from "./lexicon.js";
|
|
14
|
+
import { z } from "zod";
|
|
15
|
+
//#region src/json-schemas.ts
|
|
16
|
+
function jsonSchemas() {
|
|
17
|
+
return {
|
|
18
|
+
book: z.toJSONSchema(BookShape, { io: "input" }),
|
|
19
|
+
bookView: z.toJSONSchema(BookView, { io: "input" }),
|
|
20
|
+
page: z.toJSONSchema(Page, { io: "input" }),
|
|
21
|
+
lexicon: z.toJSONSchema(Lexicon, { io: "input" }),
|
|
22
|
+
imposition: z.toJSONSchema(Imposition, { io: "input" }),
|
|
23
|
+
deck: z.toJSONSchema(DeckShape, { io: "input" }),
|
|
24
|
+
manifest: z.toJSONSchema(Manifest, { io: "input" }),
|
|
25
|
+
publishedShot: z.toJSONSchema(PublishedShot, { io: "input" }),
|
|
26
|
+
board: z.toJSONSchema(Board, { io: "input" }),
|
|
27
|
+
printSetting: z.toJSONSchema(PrintSetting, { io: "input" }),
|
|
28
|
+
printSettingInput: z.toJSONSchema(PrintSettingInput, { io: "input" }),
|
|
29
|
+
slotDeclaration: z.toJSONSchema(SlotDeclaration, { io: "input" }),
|
|
30
|
+
slotDeclarationInput: z.toJSONSchema(SlotDeclarationInput, { io: "input" }),
|
|
31
|
+
fontReference: z.toJSONSchema(FontReference, { io: "input" }),
|
|
32
|
+
fontReferenceInput: z.toJSONSchema(FontReferenceInput, { io: "input" }),
|
|
33
|
+
localFaceTransport: z.toJSONSchema(LocalFaceTransport, { io: "input" }),
|
|
34
|
+
localFacesTransport: z.toJSONSchema(LocalFacesTransport, { io: "input" }),
|
|
35
|
+
motif: z.toJSONSchema(Motif, { io: "input" }),
|
|
36
|
+
motifInput: z.toJSONSchema(MotifInput, { io: "input" }),
|
|
37
|
+
media: z.toJSONSchema(Media, { io: "input" }),
|
|
38
|
+
placement: z.toJSONSchema(PlacementShape, { io: "input" }),
|
|
39
|
+
cover: z.toJSONSchema(Cover, { io: "input" })
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
//#endregion
|
|
43
|
+
export { jsonSchemas };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
//#region src/local-font-limits.d.ts
|
|
2
|
+
export interface LocalFontLimits {
|
|
3
|
+
count?: number;
|
|
4
|
+
bytes?: number;
|
|
5
|
+
}
|
|
6
|
+
export interface LocalFontLimitFace {
|
|
7
|
+
family: string;
|
|
8
|
+
bytes: number;
|
|
9
|
+
}
|
|
10
|
+
export declare const LOCAL_FONT_LIMITS: {
|
|
11
|
+
readonly count: 64;
|
|
12
|
+
readonly bytes: number;
|
|
13
|
+
};
|
|
14
|
+
export declare function localFontLimitRefusal(faces: readonly LocalFontLimitFace[], limits?: LocalFontLimits): string | undefined;
|
|
15
|
+
//#endregion
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
//#region src/local-font-limits.ts
|
|
2
|
+
const LOCAL_FONT_LIMITS = {
|
|
3
|
+
count: 64,
|
|
4
|
+
bytes: 33554432
|
|
5
|
+
};
|
|
6
|
+
function limit(value, fallback, label) {
|
|
7
|
+
const resolved = value ?? fallback;
|
|
8
|
+
if (!Number.isSafeInteger(resolved) || resolved < 0) return `The local font ${label} limit must be a non-negative safe integer; pass valid limits to clear this refusal.`;
|
|
9
|
+
return resolved;
|
|
10
|
+
}
|
|
11
|
+
function localFontLimitRefusal(faces, limits = {}) {
|
|
12
|
+
const countLimit = limit(limits.count, LOCAL_FONT_LIMITS.count, "count");
|
|
13
|
+
if (typeof countLimit === "string") return countLimit;
|
|
14
|
+
const byteLimit = limit(limits.bytes, LOCAL_FONT_LIMITS.bytes, "byte");
|
|
15
|
+
if (typeof byteLimit === "string") return byteLimit;
|
|
16
|
+
if (faces.length > countLimit) return `The local face ${JSON.stringify(faces[countLimit]?.family ?? "unknown family")} exceeds the count limit of ${countLimit}; pass higher limits or declare fewer local font families to clear this refusal.`;
|
|
17
|
+
let bytes = 0;
|
|
18
|
+
for (const face of faces) {
|
|
19
|
+
bytes += face.bytes;
|
|
20
|
+
if (bytes > byteLimit) return `The local face ${JSON.stringify(face.family)} exceeds the byte limit of ${byteLimit}; pass higher limits or declare fewer local font families to clear this refusal.`;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
//#endregion
|
|
24
|
+
export { LOCAL_FONT_LIMITS, localFontLimitRefusal };
|
package/dist/media.d.ts
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { TextDirection } from "./direction.js";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
//#region src/media.d.ts
|
|
4
|
+
export declare const MediaFormat: z.ZodEnum<{
|
|
5
|
+
png: "png";
|
|
6
|
+
jpeg: "jpeg";
|
|
7
|
+
gif: "gif";
|
|
8
|
+
webp: "webp";
|
|
9
|
+
svg: "svg";
|
|
10
|
+
pdf: "pdf";
|
|
11
|
+
ai: "ai";
|
|
12
|
+
}>;
|
|
13
|
+
export type MediaFormat = z.infer<typeof MediaFormat>;
|
|
14
|
+
export declare const MEDIA_FORMATS: Record<MediaFormat, {
|
|
15
|
+
pages: boolean;
|
|
16
|
+
raster: boolean;
|
|
17
|
+
}>;
|
|
18
|
+
export declare const MediaText: z.ZodObject<{
|
|
19
|
+
text: z.ZodString;
|
|
20
|
+
lang: z.ZodOptional<z.ZodString>;
|
|
21
|
+
dir: z.ZodOptional<z.ZodEnum<{
|
|
22
|
+
auto: "auto";
|
|
23
|
+
ltr: "ltr";
|
|
24
|
+
rtl: "rtl";
|
|
25
|
+
}>>;
|
|
26
|
+
}, z.core.$strip>;
|
|
27
|
+
export type MediaText = z.infer<typeof MediaText>;
|
|
28
|
+
export declare function mediaTextDirection(text: MediaText): TextDirection;
|
|
29
|
+
export declare const PageSelector: z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>;
|
|
30
|
+
export type PageSelector = z.infer<typeof PageSelector>;
|
|
31
|
+
export declare const MediaPage: z.ZodObject<{
|
|
32
|
+
name: z.ZodOptional<z.ZodString>;
|
|
33
|
+
boxes: z.ZodObject<{
|
|
34
|
+
media: z.ZodObject<{
|
|
35
|
+
x: z.ZodNumber;
|
|
36
|
+
y: z.ZodNumber;
|
|
37
|
+
width: z.ZodNumber;
|
|
38
|
+
height: z.ZodNumber;
|
|
39
|
+
}, z.core.$strip>;
|
|
40
|
+
crop: z.ZodOptional<z.ZodObject<{
|
|
41
|
+
x: z.ZodNumber;
|
|
42
|
+
y: z.ZodNumber;
|
|
43
|
+
width: z.ZodNumber;
|
|
44
|
+
height: z.ZodNumber;
|
|
45
|
+
}, z.core.$strip>>;
|
|
46
|
+
trim: z.ZodOptional<z.ZodObject<{
|
|
47
|
+
x: z.ZodNumber;
|
|
48
|
+
y: z.ZodNumber;
|
|
49
|
+
width: z.ZodNumber;
|
|
50
|
+
height: z.ZodNumber;
|
|
51
|
+
}, z.core.$strip>>;
|
|
52
|
+
bleed: z.ZodOptional<z.ZodObject<{
|
|
53
|
+
x: z.ZodNumber;
|
|
54
|
+
y: z.ZodNumber;
|
|
55
|
+
width: z.ZodNumber;
|
|
56
|
+
height: z.ZodNumber;
|
|
57
|
+
}, z.core.$strip>>;
|
|
58
|
+
art: z.ZodOptional<z.ZodObject<{
|
|
59
|
+
x: z.ZodNumber;
|
|
60
|
+
y: z.ZodNumber;
|
|
61
|
+
width: z.ZodNumber;
|
|
62
|
+
height: z.ZodNumber;
|
|
63
|
+
}, z.core.$strip>>;
|
|
64
|
+
}, z.core.$strip>;
|
|
65
|
+
}, z.core.$strip>;
|
|
66
|
+
export type MediaPage = z.infer<typeof MediaPage>;
|
|
67
|
+
export declare const Media: z.ZodObject<{
|
|
68
|
+
format: z.ZodEnum<{
|
|
69
|
+
png: "png";
|
|
70
|
+
jpeg: "jpeg";
|
|
71
|
+
gif: "gif";
|
|
72
|
+
webp: "webp";
|
|
73
|
+
svg: "svg";
|
|
74
|
+
pdf: "pdf";
|
|
75
|
+
ai: "ai";
|
|
76
|
+
}>;
|
|
77
|
+
size: z.ZodObject<{
|
|
78
|
+
width: z.ZodNumber;
|
|
79
|
+
height: z.ZodNumber;
|
|
80
|
+
}, z.core.$strip>;
|
|
81
|
+
pages: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
82
|
+
name: z.ZodOptional<z.ZodString>;
|
|
83
|
+
boxes: z.ZodObject<{
|
|
84
|
+
media: z.ZodObject<{
|
|
85
|
+
x: z.ZodNumber;
|
|
86
|
+
y: z.ZodNumber;
|
|
87
|
+
width: z.ZodNumber;
|
|
88
|
+
height: z.ZodNumber;
|
|
89
|
+
}, z.core.$strip>;
|
|
90
|
+
crop: z.ZodOptional<z.ZodObject<{
|
|
91
|
+
x: z.ZodNumber;
|
|
92
|
+
y: z.ZodNumber;
|
|
93
|
+
width: z.ZodNumber;
|
|
94
|
+
height: z.ZodNumber;
|
|
95
|
+
}, z.core.$strip>>;
|
|
96
|
+
trim: z.ZodOptional<z.ZodObject<{
|
|
97
|
+
x: z.ZodNumber;
|
|
98
|
+
y: z.ZodNumber;
|
|
99
|
+
width: z.ZodNumber;
|
|
100
|
+
height: z.ZodNumber;
|
|
101
|
+
}, z.core.$strip>>;
|
|
102
|
+
bleed: z.ZodOptional<z.ZodObject<{
|
|
103
|
+
x: z.ZodNumber;
|
|
104
|
+
y: z.ZodNumber;
|
|
105
|
+
width: z.ZodNumber;
|
|
106
|
+
height: z.ZodNumber;
|
|
107
|
+
}, z.core.$strip>>;
|
|
108
|
+
art: z.ZodOptional<z.ZodObject<{
|
|
109
|
+
x: z.ZodNumber;
|
|
110
|
+
y: z.ZodNumber;
|
|
111
|
+
width: z.ZodNumber;
|
|
112
|
+
height: z.ZodNumber;
|
|
113
|
+
}, z.core.$strip>>;
|
|
114
|
+
}, z.core.$strip>;
|
|
115
|
+
}, z.core.$strip>>>;
|
|
116
|
+
resolution: z.ZodOptional<z.ZodNumber>;
|
|
117
|
+
alt: z.ZodOptional<z.ZodObject<{
|
|
118
|
+
text: z.ZodString;
|
|
119
|
+
lang: z.ZodOptional<z.ZodString>;
|
|
120
|
+
dir: z.ZodOptional<z.ZodEnum<{
|
|
121
|
+
auto: "auto";
|
|
122
|
+
ltr: "ltr";
|
|
123
|
+
rtl: "rtl";
|
|
124
|
+
}>>;
|
|
125
|
+
}, z.core.$strip>>;
|
|
126
|
+
caption: z.ZodOptional<z.ZodObject<{
|
|
127
|
+
text: z.ZodString;
|
|
128
|
+
lang: z.ZodOptional<z.ZodString>;
|
|
129
|
+
dir: z.ZodOptional<z.ZodEnum<{
|
|
130
|
+
auto: "auto";
|
|
131
|
+
ltr: "ltr";
|
|
132
|
+
rtl: "rtl";
|
|
133
|
+
}>>;
|
|
134
|
+
}, z.core.$strip>>;
|
|
135
|
+
credit: z.ZodOptional<z.ZodObject<{
|
|
136
|
+
text: z.ZodString;
|
|
137
|
+
lang: z.ZodOptional<z.ZodString>;
|
|
138
|
+
dir: z.ZodOptional<z.ZodEnum<{
|
|
139
|
+
auto: "auto";
|
|
140
|
+
ltr: "ltr";
|
|
141
|
+
rtl: "rtl";
|
|
142
|
+
}>>;
|
|
143
|
+
}, z.core.$strip>>;
|
|
144
|
+
derivedFrom: z.ZodOptional<z.ZodObject<{
|
|
145
|
+
address: z.ZodString;
|
|
146
|
+
page: z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>;
|
|
147
|
+
name: z.ZodOptional<z.ZodString>;
|
|
148
|
+
}, z.core.$strip>>;
|
|
149
|
+
}, z.core.$strip>;
|
|
150
|
+
export type Media = z.infer<typeof Media>;
|
|
151
|
+
export type MediaInput = z.input<typeof Media>;
|
|
152
|
+
//#endregion
|
package/dist/media.js
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { Direction, resolveDirection } from "./direction.js";
|
|
2
|
+
import { Box } from "./geometry.js";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
//#region src/media.ts
|
|
5
|
+
const MediaFormat = z.enum([
|
|
6
|
+
"png",
|
|
7
|
+
"jpeg",
|
|
8
|
+
"gif",
|
|
9
|
+
"webp",
|
|
10
|
+
"svg",
|
|
11
|
+
"pdf",
|
|
12
|
+
"ai"
|
|
13
|
+
]);
|
|
14
|
+
const MEDIA_FORMATS = {
|
|
15
|
+
png: {
|
|
16
|
+
pages: false,
|
|
17
|
+
raster: true
|
|
18
|
+
},
|
|
19
|
+
jpeg: {
|
|
20
|
+
pages: false,
|
|
21
|
+
raster: true
|
|
22
|
+
},
|
|
23
|
+
gif: {
|
|
24
|
+
pages: false,
|
|
25
|
+
raster: true
|
|
26
|
+
},
|
|
27
|
+
webp: {
|
|
28
|
+
pages: false,
|
|
29
|
+
raster: true
|
|
30
|
+
},
|
|
31
|
+
svg: {
|
|
32
|
+
pages: false,
|
|
33
|
+
raster: false
|
|
34
|
+
},
|
|
35
|
+
pdf: {
|
|
36
|
+
pages: true,
|
|
37
|
+
raster: false
|
|
38
|
+
},
|
|
39
|
+
ai: {
|
|
40
|
+
pages: true,
|
|
41
|
+
raster: false
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
const MediaText = z.object({
|
|
45
|
+
text: z.string().min(1),
|
|
46
|
+
lang: z.string().optional(),
|
|
47
|
+
dir: Direction.optional()
|
|
48
|
+
});
|
|
49
|
+
function mediaTextDirection(text) {
|
|
50
|
+
return resolveDirection(text.dir, text.lang, text.text);
|
|
51
|
+
}
|
|
52
|
+
const PageSelector = z.union([z.string().trim().min(1), z.number().int().positive()]);
|
|
53
|
+
const PageBox = Box.superRefine((box, ctx) => {
|
|
54
|
+
if (box.width <= 0) ctx.addIssue({
|
|
55
|
+
code: "custom",
|
|
56
|
+
path: ["width"],
|
|
57
|
+
message: "box width must be positive; pass a positive width to clear this refusal"
|
|
58
|
+
});
|
|
59
|
+
if (box.height <= 0) ctx.addIssue({
|
|
60
|
+
code: "custom",
|
|
61
|
+
path: ["height"],
|
|
62
|
+
message: "box height must be positive; pass a positive height to clear this refusal"
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
const PAGE_BOXES = [
|
|
66
|
+
"media",
|
|
67
|
+
"crop",
|
|
68
|
+
"trim",
|
|
69
|
+
"bleed",
|
|
70
|
+
"art"
|
|
71
|
+
];
|
|
72
|
+
const PageBoxName = z.enum(PAGE_BOXES);
|
|
73
|
+
const MediaPageBoxesShape = {
|
|
74
|
+
media: PageBox,
|
|
75
|
+
crop: PageBox.optional(),
|
|
76
|
+
trim: PageBox.optional(),
|
|
77
|
+
bleed: PageBox.optional(),
|
|
78
|
+
art: PageBox.optional()
|
|
79
|
+
};
|
|
80
|
+
const MediaPage = z.object({
|
|
81
|
+
name: z.string().min(1).optional(),
|
|
82
|
+
boxes: z.object(MediaPageBoxesShape)
|
|
83
|
+
});
|
|
84
|
+
const Media = z.object({
|
|
85
|
+
format: MediaFormat,
|
|
86
|
+
size: z.object({
|
|
87
|
+
width: z.number().positive("size.width could not be accepted; pass a positive width to clear this refusal"),
|
|
88
|
+
height: z.number().positive("size.height could not be accepted; pass a positive height to clear this refusal")
|
|
89
|
+
}),
|
|
90
|
+
pages: z.array(MediaPage).optional(),
|
|
91
|
+
resolution: z.number().positive("resolution could not be accepted; pass a positive resolution to clear this refusal").optional(),
|
|
92
|
+
alt: MediaText.optional(),
|
|
93
|
+
caption: MediaText.optional(),
|
|
94
|
+
credit: MediaText.optional(),
|
|
95
|
+
derivedFrom: z.object({
|
|
96
|
+
address: z.string().min(1),
|
|
97
|
+
page: PageSelector,
|
|
98
|
+
name: z.string().min(1).optional()
|
|
99
|
+
}).optional()
|
|
100
|
+
}).superRefine((media, ctx) => {
|
|
101
|
+
const capabilities = MEDIA_FORMATS[media.format];
|
|
102
|
+
if (media.pages !== void 0 && !capabilities.pages) ctx.addIssue({
|
|
103
|
+
code: "custom",
|
|
104
|
+
path: ["pages"],
|
|
105
|
+
message: `pages could not be accepted for ${media.format}; remove pages or use a format with pages to clear this refusal`
|
|
106
|
+
});
|
|
107
|
+
if (media.resolution !== void 0 && !capabilities.raster) ctx.addIssue({
|
|
108
|
+
code: "custom",
|
|
109
|
+
path: ["resolution"],
|
|
110
|
+
message: `resolution could not be accepted for ${media.format}; remove resolution or use a raster format to clear this refusal`
|
|
111
|
+
});
|
|
112
|
+
if (media.derivedFrom !== void 0 && capabilities.pages) ctx.addIssue({
|
|
113
|
+
code: "custom",
|
|
114
|
+
path: ["derivedFrom"],
|
|
115
|
+
message: `derivedFrom could not be accepted for ${media.format}; remove derivedFrom or use a format without pages to clear this refusal`
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
//#endregion
|
|
119
|
+
export { MEDIA_FORMATS, Media, MediaFormat, MediaPage, MediaText, PAGE_BOXES, PageBoxName, PageSelector, mediaTextDirection };
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { NoteMarker } from "./numbering.js";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
//#region src/note-series.d.ts
|
|
4
|
+
export declare const NotePlacement: z.ZodEnum<{
|
|
5
|
+
page: "page";
|
|
6
|
+
book: "book";
|
|
7
|
+
chapter: "chapter";
|
|
8
|
+
part: "part";
|
|
9
|
+
}>;
|
|
10
|
+
export type NotePlacement = z.infer<typeof NotePlacement>;
|
|
11
|
+
export declare const NoteNumbering: z.ZodEnum<{
|
|
12
|
+
book: "book";
|
|
13
|
+
chapter: "chapter";
|
|
14
|
+
part: "part";
|
|
15
|
+
}>;
|
|
16
|
+
export type NoteNumbering = z.infer<typeof NoteNumbering>;
|
|
17
|
+
export declare const NoteSeries: z.ZodObject<{
|
|
18
|
+
name: z.ZodString;
|
|
19
|
+
placement: z.ZodOptional<z.ZodEnum<{
|
|
20
|
+
page: "page";
|
|
21
|
+
book: "book";
|
|
22
|
+
chapter: "chapter";
|
|
23
|
+
part: "part";
|
|
24
|
+
}>>;
|
|
25
|
+
numbering: z.ZodOptional<z.ZodEnum<{
|
|
26
|
+
book: "book";
|
|
27
|
+
chapter: "chapter";
|
|
28
|
+
part: "part";
|
|
29
|
+
}>>;
|
|
30
|
+
marker: z.ZodOptional<z.ZodUnion<readonly [z.ZodEnum<{
|
|
31
|
+
arabic: "arabic";
|
|
32
|
+
"roman-lower": "roman-lower";
|
|
33
|
+
"roman-upper": "roman-upper";
|
|
34
|
+
hebrew: "hebrew";
|
|
35
|
+
}>, z.ZodLiteral<"symbols">]>>;
|
|
36
|
+
title: z.ZodOptional<z.ZodString>;
|
|
37
|
+
}, z.core.$strip>;
|
|
38
|
+
export type NoteSeriesInput = z.input<typeof NoteSeries>;
|
|
39
|
+
export interface ResolvedNoteSeries {
|
|
40
|
+
name: string;
|
|
41
|
+
placement: NotePlacement;
|
|
42
|
+
numbering: NoteNumbering;
|
|
43
|
+
marker: NoteMarker;
|
|
44
|
+
title: string;
|
|
45
|
+
idStem: string;
|
|
46
|
+
idScope: 'chapter' | 'numbering';
|
|
47
|
+
blockClass: string;
|
|
48
|
+
bodyClass: string;
|
|
49
|
+
titleClass: string;
|
|
50
|
+
sectionIdPrefix: string;
|
|
51
|
+
markerLabel: string;
|
|
52
|
+
markerConflictSuffixes: Readonly<Record<string, string>>;
|
|
53
|
+
markBlockSeries: boolean;
|
|
54
|
+
}
|
|
55
|
+
interface NoteSeriesSettings {
|
|
56
|
+
lang?: string;
|
|
57
|
+
footnotes: {
|
|
58
|
+
marker?: NoteMarker;
|
|
59
|
+
restart: 'chapter' | 'book';
|
|
60
|
+
};
|
|
61
|
+
endnotes: {
|
|
62
|
+
marker?: NoteMarker;
|
|
63
|
+
placement: 'book' | 'chapter';
|
|
64
|
+
title?: string;
|
|
65
|
+
};
|
|
66
|
+
notes: NoteSeriesInput[];
|
|
67
|
+
}
|
|
68
|
+
export declare function resolveNoteSeries(settings: NoteSeriesSettings): ResolvedNoteSeries[];
|
|
69
|
+
export declare function noteMarkerIssues(series: ResolvedNoteSeries[], used: ReadonlySet<string>): string[];
|
|
70
|
+
//#endregion
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { NoteMarker, isHebrew } from "./numbering.js";
|
|
2
|
+
import { REGION_NAME } from "./book-section.js";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
//#region src/note-series.ts
|
|
5
|
+
const NotePlacement = z.enum([
|
|
6
|
+
"page",
|
|
7
|
+
"chapter",
|
|
8
|
+
"part",
|
|
9
|
+
"book"
|
|
10
|
+
]);
|
|
11
|
+
const NoteNumbering = z.enum([
|
|
12
|
+
"chapter",
|
|
13
|
+
"part",
|
|
14
|
+
"book"
|
|
15
|
+
]);
|
|
16
|
+
const NoteSeries = z.object({
|
|
17
|
+
name: z.string().regex(REGION_NAME, "a note series name must be an HTML name token"),
|
|
18
|
+
placement: NotePlacement.optional(),
|
|
19
|
+
numbering: NoteNumbering.optional(),
|
|
20
|
+
marker: NoteMarker.optional(),
|
|
21
|
+
title: z.string().optional()
|
|
22
|
+
});
|
|
23
|
+
function markerOrder(lang) {
|
|
24
|
+
return isHebrew(lang) ? [
|
|
25
|
+
"hebrew",
|
|
26
|
+
"arabic",
|
|
27
|
+
"symbols",
|
|
28
|
+
"roman-lower"
|
|
29
|
+
] : [
|
|
30
|
+
"symbols",
|
|
31
|
+
"arabic",
|
|
32
|
+
"roman-lower",
|
|
33
|
+
"hebrew"
|
|
34
|
+
];
|
|
35
|
+
}
|
|
36
|
+
function unusedMarker(lang, used) {
|
|
37
|
+
return markerOrder(lang).find((marker) => !used.has(marker)) ?? "symbols";
|
|
38
|
+
}
|
|
39
|
+
function resolveCustomSeries(series) {
|
|
40
|
+
if (series.placement === void 0 || series.numbering === void 0) throw new Error(`note series ${series.name} needs placement and numbering`);
|
|
41
|
+
return {
|
|
42
|
+
...series,
|
|
43
|
+
placement: series.placement,
|
|
44
|
+
numbering: series.numbering,
|
|
45
|
+
title: series.title ?? series.name,
|
|
46
|
+
idStem: `note-${series.name}`,
|
|
47
|
+
idScope: "numbering",
|
|
48
|
+
blockClass: `segnavia-notes-${series.name}`,
|
|
49
|
+
bodyClass: `segnavia-note-${series.name}`,
|
|
50
|
+
titleClass: "segnavia-notes-title",
|
|
51
|
+
sectionIdPrefix: `segnavia-notes-${series.name}`,
|
|
52
|
+
markerLabel: `note series ${series.name}`,
|
|
53
|
+
markerConflictSuffixes: {},
|
|
54
|
+
markBlockSeries: true
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
function resolveNoteSeries(settings) {
|
|
58
|
+
const hebrew = isHebrew(settings.lang);
|
|
59
|
+
const declared = new Map(settings.notes.map((series) => [series.name, series]));
|
|
60
|
+
const footnotePresentation = {
|
|
61
|
+
idStem: "fn",
|
|
62
|
+
idScope: "chapter",
|
|
63
|
+
blockClass: "segnavia-footnotes",
|
|
64
|
+
bodyClass: "segnavia-footnote",
|
|
65
|
+
titleClass: "segnavia-notes-title",
|
|
66
|
+
sectionIdPrefix: "segnavia-notes-footnote",
|
|
67
|
+
markerLabel: "footnote",
|
|
68
|
+
markerConflictSuffixes: { endnote: "the two must differ when both kinds are used" },
|
|
69
|
+
markBlockSeries: false
|
|
70
|
+
};
|
|
71
|
+
const endnotePresentation = {
|
|
72
|
+
idStem: "en",
|
|
73
|
+
idScope: "numbering",
|
|
74
|
+
blockClass: "segnavia-notes-endnote",
|
|
75
|
+
bodyClass: "segnavia-endnote",
|
|
76
|
+
titleClass: "segnavia-endnotes-title",
|
|
77
|
+
sectionIdPrefix: "segnavia-endnotes",
|
|
78
|
+
markerLabel: "endnote",
|
|
79
|
+
markerConflictSuffixes: {},
|
|
80
|
+
markBlockSeries: true
|
|
81
|
+
};
|
|
82
|
+
const inputs = [
|
|
83
|
+
{
|
|
84
|
+
name: "footnote",
|
|
85
|
+
placement: "page",
|
|
86
|
+
numbering: settings.footnotes.restart,
|
|
87
|
+
marker: settings.footnotes.marker ?? (hebrew ? "hebrew" : "symbols"),
|
|
88
|
+
title: hebrew ? "מקורות" : "Footnotes",
|
|
89
|
+
...footnotePresentation,
|
|
90
|
+
...declared.get("footnote")
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
name: "endnote",
|
|
94
|
+
placement: settings.endnotes.placement,
|
|
95
|
+
numbering: "book",
|
|
96
|
+
marker: settings.endnotes.marker ?? "arabic",
|
|
97
|
+
title: settings.endnotes.title ?? (hebrew ? "הערות" : "Notes"),
|
|
98
|
+
...endnotePresentation,
|
|
99
|
+
...declared.get("endnote")
|
|
100
|
+
},
|
|
101
|
+
...settings.notes.filter(({ name }) => name !== "footnote" && name !== "endnote").map(resolveCustomSeries)
|
|
102
|
+
];
|
|
103
|
+
const used = /* @__PURE__ */ new Set();
|
|
104
|
+
return inputs.map((series) => {
|
|
105
|
+
const marker = series.marker ?? unusedMarker(settings.lang, used);
|
|
106
|
+
used.add(marker);
|
|
107
|
+
return {
|
|
108
|
+
name: series.name,
|
|
109
|
+
placement: series.placement,
|
|
110
|
+
numbering: series.numbering,
|
|
111
|
+
marker,
|
|
112
|
+
title: series.title,
|
|
113
|
+
idStem: series.idStem,
|
|
114
|
+
idScope: series.idScope,
|
|
115
|
+
blockClass: series.blockClass,
|
|
116
|
+
bodyClass: series.bodyClass,
|
|
117
|
+
titleClass: series.titleClass,
|
|
118
|
+
sectionIdPrefix: series.sectionIdPrefix,
|
|
119
|
+
markerLabel: series.markerLabel,
|
|
120
|
+
markerConflictSuffixes: series.markerConflictSuffixes,
|
|
121
|
+
markBlockSeries: series.markBlockSeries
|
|
122
|
+
};
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
function noteSeriesIssues(series, mode) {
|
|
126
|
+
const issues = [];
|
|
127
|
+
series.forEach((item, index) => {
|
|
128
|
+
if (mode === "continuous" && (item.placement === "chapter" || item.placement === "part")) issues.push({
|
|
129
|
+
path: [
|
|
130
|
+
"notes",
|
|
131
|
+
index,
|
|
132
|
+
"placement"
|
|
133
|
+
],
|
|
134
|
+
message: `note series ${item.name} uses ${item.placement} placement only available in paginated mode; use page or book placement, or paginated mode`
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
return issues;
|
|
138
|
+
}
|
|
139
|
+
function noteMarkerIssues(series, used) {
|
|
140
|
+
const active = series.filter(({ name }) => used.has(name));
|
|
141
|
+
const issues = [];
|
|
142
|
+
for (let left = 0; left < active.length; left += 1) for (let right = left + 1; right < active.length; right += 1) {
|
|
143
|
+
const a = active[left];
|
|
144
|
+
const b = active[right];
|
|
145
|
+
if (!a || !b) continue;
|
|
146
|
+
if (a.marker !== b.marker) continue;
|
|
147
|
+
const suffix = a.markerConflictSuffixes[b.name] ?? b.markerConflictSuffixes[a.name] ?? "used series must have different markers";
|
|
148
|
+
issues.push(`${a.markerLabel} and ${b.markerLabel} markers are both ${a.marker}; ${suffix}`);
|
|
149
|
+
}
|
|
150
|
+
return issues;
|
|
151
|
+
}
|
|
152
|
+
//#endregion
|
|
153
|
+
export { NoteNumbering, NotePlacement, NoteSeries, noteMarkerIssues, noteSeriesIssues, resolveNoteSeries };
|