indesign-cli 0.2.0__py3-none-any.whl
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.
- cli_anything/indesign/README.md +32 -0
- cli_anything/indesign/__init__.py +1 -0
- cli_anything/indesign/__main__.py +5 -0
- cli_anything/indesign/core/artifacts.py +57 -0
- cli_anything/indesign/core/catalog.py +405 -0
- cli_anything/indesign/core/domains.py +178 -0
- cli_anything/indesign/core/envelope.py +65 -0
- cli_anything/indesign/core/errors.py +30 -0
- cli_anything/indesign/core/health.py +46 -0
- cli_anything/indesign/core/hidden_backend.py +116 -0
- cli_anything/indesign/core/hidden_handler_schemas.py +223 -0
- cli_anything/indesign/core/mcp_backend.py +152 -0
- cli_anything/indesign/core/node_setup.py +35 -0
- cli_anything/indesign/core/paths.py +41 -0
- cli_anything/indesign/core/plugins/__init__.py +2 -0
- cli_anything/indesign/core/plugins/backend.py +90 -0
- cli_anything/indesign/core/plugins/discovery.py +69 -0
- cli_anything/indesign/core/plugins/host_actions.py +76 -0
- cli_anything/indesign/core/plugins/install.py +38 -0
- cli_anything/indesign/core/plugins/manifest.py +279 -0
- cli_anything/indesign/core/plugins/validate.py +181 -0
- cli_anything/indesign/core/router.py +217 -0
- cli_anything/indesign/core/runtime.py +59 -0
- cli_anything/indesign/core/scripts.py +44 -0
- cli_anything/indesign/core/session.py +68 -0
- cli_anything/indesign/indesign_cli.py +320 -0
- cli_anything/indesign/node/hidden_handler_bridge.mjs +111 -0
- cli_anything/indesign/server/package-lock.json +168 -0
- cli_anything/indesign/server/package.json +45 -0
- cli_anything/indesign/server/src/advanced/index.js +76 -0
- cli_anything/indesign/server/src/core/InDesignMCPServer.js +273 -0
- cli_anything/indesign/server/src/core/scriptExecutor.js +271 -0
- cli_anything/indesign/server/src/core/sessionManager.js +545 -0
- cli_anything/indesign/server/src/handlers/advancedTemplateHandlers.js +1072 -0
- cli_anything/indesign/server/src/handlers/bookHandlers.js +490 -0
- cli_anything/indesign/server/src/handlers/documentHandlers.js +1472 -0
- cli_anything/indesign/server/src/handlers/exportHandlers.js +208 -0
- cli_anything/indesign/server/src/handlers/graphicsHandlers.js +605 -0
- cli_anything/indesign/server/src/handlers/groupHandlers.js +358 -0
- cli_anything/indesign/server/src/handlers/helpHandlers.js +347 -0
- cli_anything/indesign/server/src/handlers/index.js +77 -0
- cli_anything/indesign/server/src/handlers/layerHandlers.js +75 -0
- cli_anything/indesign/server/src/handlers/masterSpreadHandlers.js +451 -0
- cli_anything/indesign/server/src/handlers/pageHandlers.js +698 -0
- cli_anything/indesign/server/src/handlers/pageItemHandlers.js +704 -0
- cli_anything/indesign/server/src/handlers/presentationHandlers.js +220 -0
- cli_anything/indesign/server/src/handlers/spreadHandlers.js +348 -0
- cli_anything/indesign/server/src/handlers/styleHandlers.js +458 -0
- cli_anything/indesign/server/src/handlers/textHandlers.js +431 -0
- cli_anything/indesign/server/src/handlers/utilityHandlers.js +83 -0
- cli_anything/indesign/server/src/index.js +17 -0
- cli_anything/indesign/server/src/types/index.js +106 -0
- cli_anything/indesign/server/src/types/toolDefinitionsAdvancedTemplates.js +144 -0
- cli_anything/indesign/server/src/types/toolDefinitionsBook.js +224 -0
- cli_anything/indesign/server/src/types/toolDefinitionsContent.js +353 -0
- cli_anything/indesign/server/src/types/toolDefinitionsDocument.js +409 -0
- cli_anything/indesign/server/src/types/toolDefinitionsExport.js +65 -0
- cli_anything/indesign/server/src/types/toolDefinitionsLayer.js +40 -0
- cli_anything/indesign/server/src/types/toolDefinitionsMasterSpread.js +160 -0
- cli_anything/indesign/server/src/types/toolDefinitionsPage.js +271 -0
- cli_anything/indesign/server/src/types/toolDefinitionsPageItemGroup.js +437 -0
- cli_anything/indesign/server/src/types/toolDefinitionsPresentation.js +83 -0
- cli_anything/indesign/server/src/types/toolDefinitionsSpread.js +158 -0
- cli_anything/indesign/server/src/types/toolDefinitionsUtility.js +40 -0
- cli_anything/indesign/server/src/utils/stringUtils.js +107 -0
- cli_anything/indesign/skills/SKILL.md +198 -0
- indesign_cli-0.2.0.dist-info/METADATA +267 -0
- indesign_cli-0.2.0.dist-info/RECORD +72 -0
- indesign_cli-0.2.0.dist-info/WHEEL +5 -0
- indesign_cli-0.2.0.dist-info/entry_points.txt +3 -0
- indesign_cli-0.2.0.dist-info/licenses/LICENSE +21 -0
- indesign_cli-0.2.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,545 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enhanced Session management for InDesign MCP Server
|
|
3
|
+
* Stores page dimensions and other session-specific data with improved validation and error handling
|
|
4
|
+
*/
|
|
5
|
+
if (typeof globalThis.CustomEvent !== 'function') {
|
|
6
|
+
const BaseEvent = typeof globalThis.Event === 'function' ? globalThis.Event : null;
|
|
7
|
+
if (BaseEvent) {
|
|
8
|
+
class NodeCustomEvent extends BaseEvent {
|
|
9
|
+
constructor(type, params = {}) {
|
|
10
|
+
super(type, params);
|
|
11
|
+
this.detail = params?.detail ?? null;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
globalThis.CustomEvent = NodeCustomEvent;
|
|
15
|
+
} else {
|
|
16
|
+
class MinimalCustomEvent {
|
|
17
|
+
constructor(type, params = {}) {
|
|
18
|
+
this.type = type;
|
|
19
|
+
this.detail = params?.detail ?? null;
|
|
20
|
+
this.bubbles = Boolean(params?.bubbles);
|
|
21
|
+
this.cancelable = Boolean(params?.cancelable);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
globalThis.CustomEvent = MinimalCustomEvent;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export class SessionManager extends EventTarget {
|
|
29
|
+
constructor(config = {}) {
|
|
30
|
+
super();
|
|
31
|
+
|
|
32
|
+
this.config = {
|
|
33
|
+
defaultMargin: config.defaultMargin || 20,
|
|
34
|
+
minMargin: config.minMargin || 5,
|
|
35
|
+
minDimension: config.minDimension || 10,
|
|
36
|
+
maxDimension: config.maxDimension || 10000,
|
|
37
|
+
precision: config.precision || 2,
|
|
38
|
+
...config
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
this.sessionData = {
|
|
42
|
+
pageDimensions: null,
|
|
43
|
+
activeDocument: null,
|
|
44
|
+
activePage: null,
|
|
45
|
+
lastCreatedItem: null,
|
|
46
|
+
createdAt: new Date().toISOString(),
|
|
47
|
+
lastModified: null
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Set page dimensions for the current session
|
|
53
|
+
* @param {Object} dimensions - Page dimensions object
|
|
54
|
+
* @param {number} dimensions.width - Page width in mm
|
|
55
|
+
* @param {number} dimensions.height - Page height in mm
|
|
56
|
+
*/
|
|
57
|
+
setPageDimensions(dimensions) {
|
|
58
|
+
this._validateDimensions(dimensions);
|
|
59
|
+
|
|
60
|
+
const old = this.sessionData.pageDimensions;
|
|
61
|
+
this.sessionData.pageDimensions = { ...dimensions };
|
|
62
|
+
this._updateLastModified();
|
|
63
|
+
|
|
64
|
+
this.dispatchEvent(new CustomEvent('dimensionsChanged', {
|
|
65
|
+
detail: { old, new: dimensions }
|
|
66
|
+
}));
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Get page dimensions for the current session (returns copy to prevent mutations)
|
|
71
|
+
*/
|
|
72
|
+
getPageDimensions() {
|
|
73
|
+
return this.sessionData.pageDimensions ? { ...this.sessionData.pageDimensions } : null;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Set active document info
|
|
78
|
+
*/
|
|
79
|
+
setActiveDocument(documentInfo) {
|
|
80
|
+
this._validateDocumentInfo(documentInfo);
|
|
81
|
+
|
|
82
|
+
const old = this.sessionData.activeDocument;
|
|
83
|
+
this.sessionData.activeDocument = documentInfo ? { ...documentInfo } : null;
|
|
84
|
+
this._updateLastModified();
|
|
85
|
+
|
|
86
|
+
this.dispatchEvent(new CustomEvent('documentChanged', {
|
|
87
|
+
detail: { old, new: documentInfo }
|
|
88
|
+
}));
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Get active document info (returns copy)
|
|
93
|
+
*/
|
|
94
|
+
getActiveDocument() {
|
|
95
|
+
return this.sessionData.activeDocument ? { ...this.sessionData.activeDocument } : null;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Set active page info
|
|
100
|
+
*/
|
|
101
|
+
setActivePage(pageInfo) {
|
|
102
|
+
this._validatePageInfo(pageInfo);
|
|
103
|
+
|
|
104
|
+
const old = this.sessionData.activePage;
|
|
105
|
+
this.sessionData.activePage = pageInfo ? { ...pageInfo } : null;
|
|
106
|
+
this._updateLastModified();
|
|
107
|
+
|
|
108
|
+
this.dispatchEvent(new CustomEvent('pageChanged', {
|
|
109
|
+
detail: { old, new: pageInfo }
|
|
110
|
+
}));
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Get active page info (returns copy)
|
|
115
|
+
*/
|
|
116
|
+
getActivePage() {
|
|
117
|
+
return this.sessionData.activePage ? { ...this.sessionData.activePage } : null;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Set last created item info
|
|
122
|
+
*/
|
|
123
|
+
setLastCreatedItem(itemInfo) {
|
|
124
|
+
this.sessionData.lastCreatedItem = itemInfo ? { ...itemInfo, createdAt: new Date().toISOString() } : null;
|
|
125
|
+
this._updateLastModified();
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Get last created item info (returns copy)
|
|
130
|
+
*/
|
|
131
|
+
getLastCreatedItem() {
|
|
132
|
+
return this.sessionData.lastCreatedItem ? { ...this.sessionData.lastCreatedItem } : null;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Get calculated positioning based on page dimensions with enhanced bounds checking
|
|
137
|
+
*/
|
|
138
|
+
getCalculatedPositioning(options = {}) {
|
|
139
|
+
const dimensions = this.getPageDimensions();
|
|
140
|
+
if (!dimensions) {
|
|
141
|
+
return this._getDefaultPositioning(options);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const config = this._getPositioningConfig(options);
|
|
145
|
+
const bounds = this._calculateBounds(dimensions, config);
|
|
146
|
+
const position = this._adjustPositionToBounds(options, bounds, config);
|
|
147
|
+
|
|
148
|
+
return this._roundPositioning(position, bounds);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Enhanced validation with detailed feedback
|
|
153
|
+
*/
|
|
154
|
+
validatePositioning(x, y, width, height) {
|
|
155
|
+
// Input validation
|
|
156
|
+
const inputValidation = this._validatePositioningInputs(x, y, width, height);
|
|
157
|
+
if (!inputValidation.valid) return inputValidation;
|
|
158
|
+
|
|
159
|
+
const dimensions = this.getPageDimensions();
|
|
160
|
+
if (!dimensions) {
|
|
161
|
+
return {
|
|
162
|
+
valid: true,
|
|
163
|
+
reason: 'No page dimensions available for validation',
|
|
164
|
+
warning: 'Consider setting page dimensions for better validation'
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
return this._validateAgainstPageBounds(x, y, width, height, dimensions);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Get available space at given position
|
|
173
|
+
*/
|
|
174
|
+
getAvailableSpace(x, y) {
|
|
175
|
+
const bounds = this.getPageBounds();
|
|
176
|
+
if (!bounds) return null;
|
|
177
|
+
|
|
178
|
+
return {
|
|
179
|
+
width: Math.max(0, bounds.pageWidth - x - bounds.minMargin),
|
|
180
|
+
height: Math.max(0, bounds.pageHeight - y - bounds.minMargin),
|
|
181
|
+
maxWidth: bounds.pageWidth - bounds.minMargin * 2,
|
|
182
|
+
maxHeight: bounds.pageHeight - bounds.minMargin * 2
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Find optimal position for given dimensions
|
|
188
|
+
*/
|
|
189
|
+
findOptimalPosition(width, height, preferences = {}) {
|
|
190
|
+
const bounds = this.getPageBounds();
|
|
191
|
+
if (!bounds) return null;
|
|
192
|
+
|
|
193
|
+
const { align = 'top-left', margin = this.config.defaultMargin } = preferences;
|
|
194
|
+
|
|
195
|
+
const positions = {
|
|
196
|
+
'top-left': { x: margin, y: margin },
|
|
197
|
+
'top-center': { x: (bounds.pageWidth - width) / 2, y: margin },
|
|
198
|
+
'top-right': { x: bounds.pageWidth - width - margin, y: margin },
|
|
199
|
+
'center-left': { x: margin, y: (bounds.pageHeight - height) / 2 },
|
|
200
|
+
'center': { x: (bounds.pageWidth - width) / 2, y: (bounds.pageHeight - height) / 2 },
|
|
201
|
+
'center-right': { x: bounds.pageWidth - width - margin, y: (bounds.pageHeight - height) / 2 },
|
|
202
|
+
'bottom-left': { x: margin, y: bounds.pageHeight - height - margin },
|
|
203
|
+
'bottom-center': { x: (bounds.pageWidth - width) / 2, y: bounds.pageHeight - height - margin },
|
|
204
|
+
'bottom-right': { x: bounds.pageWidth - width - margin, y: bounds.pageHeight - height - margin }
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
const position = positions[align] || positions['top-left'];
|
|
208
|
+
const validation = this.validatePositioning(position.x, position.y, width, height);
|
|
209
|
+
|
|
210
|
+
return {
|
|
211
|
+
...position,
|
|
212
|
+
validation,
|
|
213
|
+
align
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Get enhanced page bounds information
|
|
219
|
+
*/
|
|
220
|
+
getPageBounds() {
|
|
221
|
+
const dimensions = this.getPageDimensions();
|
|
222
|
+
if (!dimensions) return null;
|
|
223
|
+
|
|
224
|
+
const { width: pageWidth, height: pageHeight } = dimensions;
|
|
225
|
+
const margin = this.config.defaultMargin;
|
|
226
|
+
const minMargin = this.config.minMargin;
|
|
227
|
+
|
|
228
|
+
return {
|
|
229
|
+
pageWidth,
|
|
230
|
+
pageHeight,
|
|
231
|
+
margin,
|
|
232
|
+
minMargin,
|
|
233
|
+
safeArea: {
|
|
234
|
+
x: margin,
|
|
235
|
+
y: margin,
|
|
236
|
+
width: Math.max(0, pageWidth - (margin * 2)),
|
|
237
|
+
height: Math.max(0, pageHeight - (margin * 2))
|
|
238
|
+
},
|
|
239
|
+
absoluteBounds: {
|
|
240
|
+
x: minMargin,
|
|
241
|
+
y: minMargin,
|
|
242
|
+
width: Math.max(0, pageWidth - (minMargin * 2)),
|
|
243
|
+
height: Math.max(0, pageHeight - (minMargin * 2))
|
|
244
|
+
},
|
|
245
|
+
center: {
|
|
246
|
+
x: pageWidth / 2,
|
|
247
|
+
y: pageHeight / 2
|
|
248
|
+
}
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* Clear session data with optional preservation
|
|
254
|
+
*/
|
|
255
|
+
clearSession(preserve = []) {
|
|
256
|
+
const preserveSet = new Set(preserve);
|
|
257
|
+
const oldData = { ...this.sessionData };
|
|
258
|
+
|
|
259
|
+
this.sessionData = {
|
|
260
|
+
pageDimensions: preserveSet.has('pageDimensions') ? this.sessionData.pageDimensions : null,
|
|
261
|
+
activeDocument: preserveSet.has('activeDocument') ? this.sessionData.activeDocument : null,
|
|
262
|
+
activePage: preserveSet.has('activePage') ? this.sessionData.activePage : null,
|
|
263
|
+
lastCreatedItem: preserveSet.has('lastCreatedItem') ? this.sessionData.lastCreatedItem : null,
|
|
264
|
+
createdAt: new Date().toISOString(),
|
|
265
|
+
lastModified: null
|
|
266
|
+
};
|
|
267
|
+
|
|
268
|
+
this.dispatchEvent(new CustomEvent('sessionCleared', {
|
|
269
|
+
detail: { old: oldData, preserved: preserve }
|
|
270
|
+
}));
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* Get comprehensive session summary
|
|
275
|
+
*/
|
|
276
|
+
getSessionSummary() {
|
|
277
|
+
const bounds = this.getPageBounds();
|
|
278
|
+
|
|
279
|
+
return {
|
|
280
|
+
hasPageDimensions: !!this.sessionData.pageDimensions,
|
|
281
|
+
hasActiveDocument: !!this.sessionData.activeDocument,
|
|
282
|
+
hasActivePage: !!this.sessionData.activePage,
|
|
283
|
+
hasLastCreatedItem: !!this.sessionData.lastCreatedItem,
|
|
284
|
+
pageDimensions: this.getPageDimensions(),
|
|
285
|
+
activeDocument: this.getActiveDocument(),
|
|
286
|
+
activePage: this.getActivePage(),
|
|
287
|
+
lastCreatedItem: this.getLastCreatedItem(),
|
|
288
|
+
bounds: bounds,
|
|
289
|
+
timestamps: {
|
|
290
|
+
createdAt: this.sessionData.createdAt,
|
|
291
|
+
lastModified: this.sessionData.lastModified
|
|
292
|
+
},
|
|
293
|
+
config: { ...this.config }
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* Export session data for persistence
|
|
299
|
+
*/
|
|
300
|
+
exportSession() {
|
|
301
|
+
return JSON.stringify({
|
|
302
|
+
sessionData: this.sessionData,
|
|
303
|
+
config: this.config,
|
|
304
|
+
version: '2.0'
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Import session data from persistence
|
|
310
|
+
*/
|
|
311
|
+
importSession(sessionString) {
|
|
312
|
+
try {
|
|
313
|
+
const imported = JSON.parse(sessionString);
|
|
314
|
+
if (imported.version && imported.sessionData) {
|
|
315
|
+
this.sessionData = { ...imported.sessionData };
|
|
316
|
+
if (imported.config) {
|
|
317
|
+
this.config = { ...this.config, ...imported.config };
|
|
318
|
+
}
|
|
319
|
+
this.dispatchEvent(new CustomEvent('sessionImported', {
|
|
320
|
+
detail: { version: imported.version }
|
|
321
|
+
}));
|
|
322
|
+
return true;
|
|
323
|
+
}
|
|
324
|
+
} catch (error) {
|
|
325
|
+
console.error('Failed to import session:', error);
|
|
326
|
+
}
|
|
327
|
+
return false;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
// Private helper methods
|
|
331
|
+
_validateDimensions(dimensions) {
|
|
332
|
+
if (!dimensions || typeof dimensions !== 'object') {
|
|
333
|
+
throw new Error('Dimensions must be an object');
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
const { width, height } = dimensions;
|
|
337
|
+
if (typeof width !== 'number' || typeof height !== 'number') {
|
|
338
|
+
throw new Error('Width and height must be numbers');
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
if (width <= 0 || height <= 0) {
|
|
342
|
+
throw new Error('Width and height must be positive');
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
if (width > this.config.maxDimension || height > this.config.maxDimension) {
|
|
346
|
+
throw new Error(`Dimensions exceed maximum allowed size of ${this.config.maxDimension}mm`);
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
_validateDocumentInfo(documentInfo) {
|
|
351
|
+
if (documentInfo && typeof documentInfo !== 'object') {
|
|
352
|
+
throw new Error('Document info must be an object');
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
_validatePageInfo(pageInfo) {
|
|
357
|
+
if (pageInfo && typeof pageInfo !== 'object') {
|
|
358
|
+
throw new Error('Page info must be an object');
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
_validatePositioningInputs(x, y, width, height) {
|
|
363
|
+
const inputs = { x, y, width, height };
|
|
364
|
+
|
|
365
|
+
for (const [key, value] of Object.entries(inputs)) {
|
|
366
|
+
if (typeof value !== 'number' || isNaN(value)) {
|
|
367
|
+
return {
|
|
368
|
+
valid: false,
|
|
369
|
+
reason: `${key} must be a valid number`,
|
|
370
|
+
input: key
|
|
371
|
+
};
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
if (width <= 0 || height <= 0) {
|
|
376
|
+
return {
|
|
377
|
+
valid: false,
|
|
378
|
+
reason: 'Width and height must be positive',
|
|
379
|
+
suggested: {
|
|
380
|
+
width: Math.max(width, this.config.minDimension),
|
|
381
|
+
height: Math.max(height, this.config.minDimension)
|
|
382
|
+
}
|
|
383
|
+
};
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
return { valid: true };
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
_validateAgainstPageBounds(x, y, width, height, dimensions) {
|
|
390
|
+
const { width: pageWidth, height: pageHeight } = dimensions;
|
|
391
|
+
const minMargin = this.config.minMargin;
|
|
392
|
+
|
|
393
|
+
if (x < minMargin) {
|
|
394
|
+
return {
|
|
395
|
+
valid: false,
|
|
396
|
+
reason: `X position (${x}mm) is too close to left edge`,
|
|
397
|
+
suggested: { x: minMargin },
|
|
398
|
+
bounds: { minX: minMargin }
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
if (y < minMargin) {
|
|
403
|
+
return {
|
|
404
|
+
valid: false,
|
|
405
|
+
reason: `Y position (${y}mm) is too close to top edge`,
|
|
406
|
+
suggested: { y: minMargin },
|
|
407
|
+
bounds: { minY: minMargin }
|
|
408
|
+
};
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
if (x + width > pageWidth - minMargin) {
|
|
412
|
+
return {
|
|
413
|
+
valid: false,
|
|
414
|
+
reason: `Content extends beyond right edge (${x + width}mm > ${pageWidth - minMargin}mm)`,
|
|
415
|
+
suggested: {
|
|
416
|
+
width: Math.max(pageWidth - x - minMargin, this.config.minDimension),
|
|
417
|
+
x: Math.max(pageWidth - width - minMargin, minMargin)
|
|
418
|
+
},
|
|
419
|
+
bounds: { maxX: pageWidth - minMargin }
|
|
420
|
+
};
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
if (y + height > pageHeight - minMargin) {
|
|
424
|
+
return {
|
|
425
|
+
valid: false,
|
|
426
|
+
reason: `Content extends beyond bottom edge (${y + height}mm > ${pageHeight - minMargin}mm)`,
|
|
427
|
+
suggested: {
|
|
428
|
+
height: Math.max(pageHeight - y - minMargin, this.config.minDimension),
|
|
429
|
+
y: Math.max(pageHeight - height - minMargin, minMargin)
|
|
430
|
+
},
|
|
431
|
+
bounds: { maxY: pageHeight - minMargin }
|
|
432
|
+
};
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
return {
|
|
436
|
+
valid: true,
|
|
437
|
+
reason: 'Positioning is within page bounds'
|
|
438
|
+
};
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
_getDefaultPositioning(options) {
|
|
442
|
+
return {
|
|
443
|
+
x: options.x || 10,
|
|
444
|
+
y: options.y || 10,
|
|
445
|
+
width: options.width || 100,
|
|
446
|
+
height: options.height || 50,
|
|
447
|
+
note: 'No page dimensions available - using default positioning'
|
|
448
|
+
};
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
_getPositioningConfig(options) {
|
|
452
|
+
return {
|
|
453
|
+
margin: options.margin ?? this.config.defaultMargin,
|
|
454
|
+
minMargin: this.config.minMargin,
|
|
455
|
+
minDimension: this.config.minDimension
|
|
456
|
+
};
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
_calculateBounds(dimensions, config) {
|
|
460
|
+
const { width: pageWidth, height: pageHeight } = dimensions;
|
|
461
|
+
|
|
462
|
+
return {
|
|
463
|
+
pageWidth,
|
|
464
|
+
pageHeight,
|
|
465
|
+
safeWidth: pageWidth - (config.margin * 2),
|
|
466
|
+
safeHeight: pageHeight - (config.margin * 2),
|
|
467
|
+
margin: config.margin,
|
|
468
|
+
minMargin: config.minMargin
|
|
469
|
+
};
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
_adjustPositionToBounds(options, bounds, config) {
|
|
473
|
+
let x = options.x !== undefined ? options.x : bounds.margin;
|
|
474
|
+
let y = options.y !== undefined ? options.y : bounds.margin;
|
|
475
|
+
let width = options.width !== undefined ? options.width : Math.min(bounds.safeWidth, 100);
|
|
476
|
+
let height = options.height !== undefined ? options.height : Math.min(bounds.safeHeight, 50);
|
|
477
|
+
|
|
478
|
+
// Ensure content stays within page bounds
|
|
479
|
+
if (x + width > bounds.pageWidth - config.minMargin) {
|
|
480
|
+
if (options.x !== undefined) {
|
|
481
|
+
width = Math.max(bounds.pageWidth - x - config.minMargin, config.minDimension);
|
|
482
|
+
} else {
|
|
483
|
+
x = Math.max(bounds.pageWidth - width - config.minMargin, bounds.margin);
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
if (y + height > bounds.pageHeight - config.minMargin) {
|
|
488
|
+
if (options.y !== undefined) {
|
|
489
|
+
height = Math.max(bounds.pageHeight - y - config.minMargin, config.minDimension);
|
|
490
|
+
} else {
|
|
491
|
+
y = Math.max(bounds.pageHeight - height - config.minMargin, bounds.margin);
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
// Ensure minimum dimensions and positions
|
|
496
|
+
width = Math.max(width, config.minDimension);
|
|
497
|
+
height = Math.max(height, config.minDimension);
|
|
498
|
+
x = Math.max(x, config.minMargin);
|
|
499
|
+
y = Math.max(y, config.minMargin);
|
|
500
|
+
|
|
501
|
+
return { x, y, width, height };
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
_roundPositioning(position, bounds = null) {
|
|
505
|
+
const precision = this.config.precision;
|
|
506
|
+
const factor = Math.pow(10, precision);
|
|
507
|
+
|
|
508
|
+
const result = {
|
|
509
|
+
x: Math.round(position.x * factor) / factor,
|
|
510
|
+
y: Math.round(position.y * factor) / factor,
|
|
511
|
+
width: Math.round(position.width * factor) / factor,
|
|
512
|
+
height: Math.round(position.height * factor) / factor
|
|
513
|
+
};
|
|
514
|
+
|
|
515
|
+
if (bounds) {
|
|
516
|
+
result.pageWidth = bounds.pageWidth;
|
|
517
|
+
result.pageHeight = bounds.pageHeight;
|
|
518
|
+
result.safeArea = {
|
|
519
|
+
width: bounds.safeWidth,
|
|
520
|
+
height: bounds.safeHeight,
|
|
521
|
+
margin: bounds.margin
|
|
522
|
+
};
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
return result;
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
_updateLastModified() {
|
|
529
|
+
this.sessionData.lastModified = new Date().toISOString();
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
// Alias for compatibility
|
|
533
|
+
getSessionInfo() {
|
|
534
|
+
return this.getSessionSummary();
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
// Create a singleton instance with default configuration
|
|
539
|
+
export const sessionManager = new SessionManager({
|
|
540
|
+
defaultMargin: 20,
|
|
541
|
+
minMargin: 5,
|
|
542
|
+
minDimension: 10,
|
|
543
|
+
maxDimension: 10000,
|
|
544
|
+
precision: 2
|
|
545
|
+
});
|