cvdl-ts 1.0.9 → 1.0.10

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/README.md ADDED
@@ -0,0 +1,5 @@
1
+
2
+ # Todos
3
+
4
+ - Right elements should not become double columns when there is available space.
5
+ - Margins should affect the width of the element.
package/dist/Layout.d.ts CHANGED
@@ -18,6 +18,7 @@ export declare class SectionLayout {
18
18
  toJson(): any;
19
19
  width(): Width;
20
20
  is_container(): boolean;
21
+ is_fill(): boolean;
21
22
  is_ref(): boolean;
22
23
  type_(): "Stack" | "Row" | "Elem";
23
24
  tag_(): "Stack" | "FlexRow" | "FrozenRow" | "Ref" | "Text";
@@ -25,6 +26,7 @@ export declare class SectionLayout {
25
26
  with_margin(margin: Margin): SectionLayout;
26
27
  with_alignment(alignment: Alignment): SectionLayout;
27
28
  with_width(width: Width): SectionLayout;
29
+ total_elements_width(): number;
28
30
  is_instantiated(): boolean;
29
31
  instantiate(section: Map<string, ItemContent>): SectionLayout;
30
32
  static instantiate_ref_element(element: Elem, section: Map<string, ItemContent>): SectionLayout;
@@ -42,8 +44,9 @@ export declare class Stack {
42
44
  margin: Margin;
43
45
  alignment: Alignment;
44
46
  width: Width;
45
- constructor(elements: SectionLayout[], margin?: Margin, alignment?: Alignment, width?: Width);
46
- static stack(elements: SectionLayout[], margin?: Margin, alignment?: Alignment, width?: Width): SectionLayout;
47
+ is_fill: boolean;
48
+ constructor(elements: SectionLayout[], margin?: Margin, alignment?: Alignment, width?: Width, is_fill?: boolean);
49
+ static stack(elements: SectionLayout[], margin?: Margin, alignment?: Alignment, width?: Width, is_fill?: boolean): SectionLayout;
47
50
  copy(): Stack;
48
51
  static default_(): Stack;
49
52
  instantiate(section: Map<string, ItemContent>): Stack;
@@ -61,8 +64,9 @@ export declare class Row {
61
64
  alignment: Alignment;
62
65
  width: Width;
63
66
  is_frozen: boolean;
64
- constructor(elements: SectionLayout[], is_frozen?: boolean, margin?: Margin, alignment?: Alignment, width?: Width);
65
- static row(elements: SectionLayout[], is_frozen?: boolean, margin?: Margin, alignment?: Alignment, width?: Width): SectionLayout;
67
+ is_fill: boolean;
68
+ constructor(elements: SectionLayout[], is_frozen?: boolean, margin?: Margin, alignment?: Alignment, width?: Width, is_fill?: boolean);
69
+ static row(elements: SectionLayout[], is_frozen?: boolean, margin?: Margin, alignment?: Alignment, width?: Width, is_fill?: boolean): SectionLayout;
66
70
  copy(): Row;
67
71
  static default_(): Row;
68
72
  instantiate(section: Map<string, ItemContent>): Row;
package/dist/Layout.js CHANGED
@@ -105,6 +105,16 @@ class SectionLayout {
105
105
  is_container() {
106
106
  return this.inner.tag === "Stack" || this.inner.tag === "Row";
107
107
  }
108
+ is_fill() {
109
+ switch (this.type_()) {
110
+ case "Stack":
111
+ return this.inner.is_fill && this.inner.elements.map(e => e.is_fill()).reduce((a, b) => a && b, true);
112
+ case "Row":
113
+ return this.inner.is_fill && this.inner.elements.map(e => e.is_fill()).reduce((a, b) => a && b, true);
114
+ case "Elem":
115
+ return this.inner.is_fill;
116
+ }
117
+ }
108
118
  is_ref() {
109
119
  return this.inner.tag === "Elem" && this.inner.is_ref;
110
120
  }
@@ -143,6 +153,14 @@ class SectionLayout {
143
153
  this.inner = this.inner.with_width(width);
144
154
  return this;
145
155
  }
156
+ total_elements_width() {
157
+ if (this.is_container()) {
158
+ return this.inner.elements.map(e => e.total_elements_width()).reduce((a, b) => a + b, 0.0);
159
+ }
160
+ else {
161
+ return Width_1.Width.get_fixed_unchecked(this.width());
162
+ }
163
+ }
146
164
  is_instantiated() {
147
165
  if (this.is_container()) {
148
166
  return this.inner.elements.map(e => e.is_instantiated()).reduce((a, b) => a && b, true);
@@ -189,7 +207,7 @@ class SectionLayout {
189
207
  if (this.inner.tag === "Elem" && this.inner.is_ref) {
190
208
  throw new Error("Cannot propagate widths of uninstantiated layout");
191
209
  }
192
- this.inner = this.inner.bound_width(bound);
210
+ this.inner = this.inner.bound_width(bound - this.inner.margin.left - this.inner.margin.right);
193
211
  return this;
194
212
  }
195
213
  scale_width(document_width) {
@@ -222,6 +240,17 @@ class SectionLayout {
222
240
  case "Stack":
223
241
  case "Row":
224
242
  this.inner.elements = this.inner.elements.map(e => e.fill_fonts(font_dict));
243
+ console.error(this, this.is_fill());
244
+ if (this.is_fill()) {
245
+ const total_width = this.total_elements_width();
246
+ console.error(this);
247
+ console.error(total_width);
248
+ console.error(this.inner.elements);
249
+ if (total_width <= Width_1.Width.get_fixed_unchecked(this.width())) {
250
+ // throw `Cannot fill fonts of row with width ${JSON.stringify(this.width())} and total width ${total_width}`
251
+ this.inner = this.inner.with_width(Width_1.Width.absolute(total_width));
252
+ }
253
+ }
225
254
  break;
226
255
  case "Elem":
227
256
  this.inner = this.inner.fill_fonts(font_dict);
@@ -262,6 +291,11 @@ class SectionLayout {
262
291
  }
263
292
  const elem = this.inner;
264
293
  const lines = elem.break_lines(font_dict).map(l => new SectionLayout(l));
294
+ // Make last line left if it's justified
295
+ if (lines[lines.length - 1].inner.alignment === "Justified") {
296
+ console.error(lines[lines.length - 1]);
297
+ lines[lines.length - 1] = lines[lines.length - 1].with_alignment("Left");
298
+ }
265
299
  return new SectionLayout(new Stack(lines, elem.margin, elem.alignment, elem.width));
266
300
  }
267
301
  }
@@ -278,6 +312,7 @@ class SectionLayout {
278
312
  switch (this.type_()) {
279
313
  case "Stack": {
280
314
  const stack = this.inner;
315
+ top_left = top_left.move_y_by(stack.margin.top).move_x_by(stack.margin.left);
281
316
  for (const element of stack.elements) {
282
317
  depth = element.compute_textbox_positions(textbox_positions, top_left, font_dict);
283
318
  top_left = top_left.move_y_to(depth);
@@ -286,6 +321,7 @@ class SectionLayout {
286
321
  }
287
322
  case "Row": {
288
323
  const row = this.inner;
324
+ top_left = top_left.move_y_by(row.margin.top).move_x_by(row.margin.left);
289
325
  let per_elem_space = 0.0;
290
326
  switch (row.alignment) {
291
327
  case "Center":
@@ -315,6 +351,7 @@ class SectionLayout {
315
351
  }
316
352
  const height = elem.font.get_height(font_dict);
317
353
  const width = Width_1.Width.get_fixed_unchecked(elem.text_width);
354
+ top_left = top_left.move_y_by(elem.margin.top).move_x_by(elem.margin.left);
318
355
  switch (elem.alignment) {
319
356
  case "Center":
320
357
  top_left = top_left.move_x_by((Width_1.Width.get_fixed_unchecked(elem.width) - width) / 2.0);
@@ -322,11 +359,25 @@ class SectionLayout {
322
359
  case "Right":
323
360
  top_left = top_left.move_x_by(Width_1.Width.get_fixed_unchecked(elem.width) - width);
324
361
  break;
325
- case "Justified":
326
- throw new Error("Cannot compute textbox positions of justified element");
327
362
  }
328
- const textbox = new Box_1.Box(top_left, top_left.move_x_by(width).move_y_by(height));
329
- textbox_positions.push([textbox, elem]);
363
+ if (elem.alignment === "Justified") {
364
+ const words = elem.item.split(/\s+/);
365
+ const word_elems = words.map((word) => {
366
+ const word_width = elem.font.get_width(word, font_dict);
367
+ const word_elem = new Elem(word, null, false, false, Width_1.Width.absolute(word_width), elem.font, Margin_1.Margin.default_(), Alignment_1.Alignment.default_(), Width_1.Width.absolute(word_width), elem.background_color);
368
+ return word_elem;
369
+ });
370
+ const per_elem_space = (Width_1.Width.get_fixed_unchecked(elem.width) - (word_elems.reduce((w, elem) => w + Width_1.Width.get_fixed_unchecked(elem.width), 0.0))) / (words.length);
371
+ for (const word_elem of word_elems) {
372
+ const textbox = new Box_1.Box(top_left, top_left.move_x_by(width).move_y_by(height));
373
+ textbox_positions.push([textbox, word_elem]);
374
+ top_left = top_left.move_x_by(Width_1.Width.get_fixed_unchecked(word_elem.width) + per_elem_space);
375
+ }
376
+ }
377
+ else {
378
+ const textbox = new Box_1.Box(top_left, top_left.move_x_by(width).move_y_by(height));
379
+ textbox_positions.push([textbox, elem]);
380
+ }
330
381
  return top_left.y + height;
331
382
  }
332
383
  }
@@ -334,15 +385,16 @@ class SectionLayout {
334
385
  }
335
386
  exports.SectionLayout = SectionLayout;
336
387
  class Stack {
337
- constructor(elements, margin, alignment, width) {
388
+ constructor(elements, margin, alignment, width, is_fill) {
338
389
  this.tag = "Stack";
339
390
  this.elements = elements;
340
391
  this.margin = margin !== null && margin !== void 0 ? margin : Margin_1.Margin.default_();
341
392
  this.alignment = alignment !== null && alignment !== void 0 ? alignment : Alignment_1.Alignment.default_();
342
393
  this.width = width !== null && width !== void 0 ? width : Width_1.Width.default_();
394
+ this.is_fill = is_fill !== null && is_fill !== void 0 ? is_fill : false;
343
395
  }
344
- static stack(elements, margin, alignment, width) {
345
- return new SectionLayout(new Stack(elements, margin, alignment, width));
396
+ static stack(elements, margin, alignment, width, is_fill) {
397
+ return new SectionLayout(new Stack(elements, margin, alignment, width, is_fill));
346
398
  }
347
399
  copy() {
348
400
  return new Stack(this.elements.map((e) => e.copy()), this.margin.copy(), this.alignment, Width_1.Width.copy(this.width));
@@ -351,19 +403,19 @@ class Stack {
351
403
  return new Stack([]);
352
404
  }
353
405
  instantiate(section) {
354
- return new Stack(this.elements.map(e => e.instantiate(section)), this.margin, this.alignment, this.width);
406
+ return new Stack(this.elements.map(e => e.instantiate(section)), this.margin, this.alignment, this.width, this.is_fill);
355
407
  }
356
408
  with_elements(elements) {
357
- return new Stack(elements, this.margin, this.alignment, this.width);
409
+ return new Stack(elements, this.margin, this.alignment, this.width, this.is_fill);
358
410
  }
359
411
  with_margin(margin) {
360
- return new Stack(this.elements, margin, this.alignment, this.width);
412
+ return new Stack(this.elements, margin, this.alignment, this.width, this.is_fill);
361
413
  }
362
414
  with_alignment(alignment) {
363
- return new Stack(this.elements, this.margin, alignment, this.width);
415
+ return new Stack(this.elements, this.margin, alignment, this.width, this.is_fill);
364
416
  }
365
417
  with_width(width) {
366
- return new Stack(this.elements, this.margin, this.alignment, width);
418
+ return new Stack(this.elements, this.margin, this.alignment, width, this.is_fill);
367
419
  }
368
420
  bound_width(width) {
369
421
  const bound = this.width.tag === "Absolute" ? Math.min(this.width.value, width)
@@ -372,7 +424,7 @@ class Stack {
372
424
  if (bound === null) {
373
425
  throw new Error("Cannot bound width of non-unitized widths!");
374
426
  }
375
- return new Stack(this.elements.map(e => e.bound_width(bound)), this.margin, this.alignment, Width_1.Width.absolute(bound));
427
+ return new Stack(this.elements.map(e => e.bound_width(bound)), this.margin, this.alignment, Width_1.Width.absolute(bound), Width_1.Width.is_fill(this.width));
376
428
  }
377
429
  scale_width(w) {
378
430
  return this.with_elements(this.elements.map(e => e.scale_width(w))).with_width(Width_1.Width.scale(this.width, w));
@@ -380,37 +432,38 @@ class Stack {
380
432
  }
381
433
  exports.Stack = Stack;
382
434
  class Row {
383
- constructor(elements, is_frozen, margin, alignment, width) {
435
+ constructor(elements, is_frozen, margin, alignment, width, is_fill) {
384
436
  this.tag = "Row";
385
437
  this.elements = elements;
386
438
  this.is_frozen = is_frozen !== null && is_frozen !== void 0 ? is_frozen : false;
387
439
  this.margin = margin !== null && margin !== void 0 ? margin : Margin_1.Margin.default_();
388
440
  this.alignment = alignment !== null && alignment !== void 0 ? alignment : Alignment_1.Alignment.default_();
389
441
  this.width = width !== null && width !== void 0 ? width : Width_1.Width.default_();
442
+ this.is_fill = is_fill !== null && is_fill !== void 0 ? is_fill : false;
390
443
  }
391
- static row(elements, is_frozen, margin, alignment, width) {
392
- return new SectionLayout(new Row(elements, is_frozen, margin, alignment, width));
444
+ static row(elements, is_frozen, margin, alignment, width, is_fill) {
445
+ return new SectionLayout(new Row(elements, is_frozen, margin, alignment, width, is_fill));
393
446
  }
394
447
  copy() {
395
- return new Row(this.elements.map((e) => e.copy()), this.is_frozen, this.margin.copy(), this.alignment, Width_1.Width.copy(this.width));
448
+ return new Row(this.elements.map((e) => e.copy()), this.is_frozen, this.margin.copy(), this.alignment, Width_1.Width.copy(this.width), this.is_fill);
396
449
  }
397
450
  static default_() {
398
451
  return new Row([]);
399
452
  }
400
453
  instantiate(section) {
401
- return new Row(this.elements.map(e => e.instantiate(section)), this.is_frozen, this.margin, this.alignment, this.width);
454
+ return new Row(this.elements.map(e => e.instantiate(section)), this.is_frozen, this.margin, this.alignment, this.width, this.is_fill);
402
455
  }
403
456
  with_elements(elements) {
404
- return new Row(elements, this.is_frozen, this.margin, this.alignment, this.width);
457
+ return new Row(elements, this.is_frozen, this.margin, this.alignment, this.width, this.is_fill);
405
458
  }
406
459
  with_margin(margin) {
407
- return new Row(this.elements, this.is_frozen, margin, this.alignment, this.width);
460
+ return new Row(this.elements, this.is_frozen, margin, this.alignment, this.width, this.is_fill);
408
461
  }
409
462
  with_alignment(alignment) {
410
- return new Row(this.elements, this.is_frozen, this.margin, alignment, this.width);
463
+ return new Row(this.elements, this.is_frozen, this.margin, alignment, this.width, this.is_fill);
411
464
  }
412
465
  with_width(width) {
413
- return new Row(this.elements, this.is_frozen, this.margin, this.alignment, width);
466
+ return new Row(this.elements, this.is_frozen, this.margin, this.alignment, width, this.is_fill);
414
467
  }
415
468
  elements_width() {
416
469
  return this.elements.map(e => Width_1.Width.get_fixed_unchecked(e.width())).reduce((a, b) => a + b, 0.0);
@@ -422,7 +475,7 @@ class Row {
422
475
  if (bound === null) {
423
476
  throw new Error("Cannot bound width of non-unitized widths!");
424
477
  }
425
- return new Row(this.elements.map(e => e.bound_width(bound)), this.is_frozen, this.margin, this.alignment, Width_1.Width.absolute(bound));
478
+ return new Row(this.elements.map(e => e.bound_width(bound)), this.is_frozen, this.margin, this.alignment, Width_1.Width.absolute(bound), Width_1.Width.is_fill(this.width));
426
479
  }
427
480
  scale_width(w) {
428
481
  return this.with_elements(this.elements.map(e => e.scale_width(w))).with_width(Width_1.Width.scale(this.width, w));
@@ -526,7 +579,7 @@ class Elem {
526
579
  }
527
580
  justified_lines(lines, font_dict) {
528
581
  const rowLines = [];
529
- for (const line of lines) {
582
+ for (const line of lines.slice(0, -1)) {
530
583
  const words = line.item.split(/\s+/);
531
584
  const row = new Row([], false, line.margin, line.alignment, line.width);
532
585
  words.forEach(word => {
@@ -535,6 +588,7 @@ class Elem {
535
588
  });
536
589
  rowLines.push(row);
537
590
  }
591
+ rowLines.push(new Row([new SectionLayout(lines[lines.length - 1]).with_alignment("Left")], false, lines[0].margin, "Left", lines[0].width));
538
592
  return rowLines;
539
593
  }
540
594
  break_lines(font_dict) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cvdl-ts",
3
- "version": "1.0.9",
3
+ "version": "1.0.10",
4
4
  "description": "Typescript Implementation of CVDL Compiler",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",