@tonguetoquill/collection 0.2.5 → 0.2.6

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tonguetoquill/collection",
3
- "version": "0.2.5",
3
+ "version": "0.2.6",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/nibsbin/tonguetoquill-collection.git"
@@ -1,6 +1,46 @@
1
1
  // Formalizer Engine – rendering engine
2
2
  // Renders pixel-perfect PDF form replicas from a PyMuPDF-extracted schema.
3
3
 
4
+ /// Global configuration for text rendering.
5
+ /// Adjust these to change the overall form text appearance.
6
+ #let FORM_MAX_TEXT_SIZE = 14pt
7
+ #let FORM_MIN_TEXT_SIZE = 6pt
8
+ #let FORM_MIN_CHARS_PER_LINE = 7
9
+
10
+ /// Render a text-like field with word-wrapping and shrink-to-fit.
11
+ #let render-text-field(display, width, height, x-inset, y-inset) = {
12
+ set par(leading: 0.25em)
13
+ context {
14
+ let final-size = FORM_MIN_TEXT_SIZE
15
+ let current = FORM_MAX_TEXT_SIZE
16
+ let step = 0.5pt
17
+
18
+ // Find the largest font size that fits both horizontally and vertically
19
+ // and optionally leaves enough room for a minimum number of characters
20
+ while current >= FORM_MIN_TEXT_SIZE {
21
+ let m = measure(block(width: width - 2 * x-inset, text(size: current, display)))
22
+ let char-m = measure(text(size: current, "0" * FORM_MIN_CHARS_PER_LINE))
23
+
24
+ if m.height <= height - 2 * y-inset and char-m.width <= width - 2 * x-inset {
25
+ final-size = current
26
+ break
27
+ }
28
+ current = current - step
29
+ }
30
+ // Alignment: center vertically if it's a short box (likely single line),
31
+ // otherwise top-align for multi-line paragraphs.
32
+ let vert-align = if height < 24pt { horizon } else { top }
33
+
34
+ box(
35
+ width: width,
36
+ height: height,
37
+ clip: true,
38
+ inset: (x: x-inset, y: y-inset),
39
+ align(left + vert-align, text(size: final-size, display)),
40
+ )
41
+ }
42
+ }
43
+
4
44
  /// Render a single field's content overlay.
5
45
  ///
6
46
  /// - field-type (str): normalised lowercase type
@@ -11,21 +51,7 @@
11
51
  #let render-field(field-type, value, width, height, field) = {
12
52
  if field-type == "text" {
13
53
  if value != none and str(value) != "" {
14
- context {
15
- let default-size = height * 0.6
16
- let min-size = 6pt
17
- let x-inset = 1.5pt
18
- let m = measure(text(size: default-size, str(value)))
19
- let scale = calc.min(1.0, (width - 2 * x-inset) / m.width)
20
- let final-size = calc.max(min-size, default-size * scale)
21
- box(
22
- width: width,
23
- height: height,
24
- clip: true,
25
- inset: (x: x-inset),
26
- align(left + horizon, text(size: final-size, str(value))),
27
- )
28
- }
54
+ render-text-field(str(value), width, height, 1.5pt, 1pt)
29
55
  }
30
56
  } else if field-type == "checkbox" {
31
57
  if value == true {
@@ -57,21 +83,7 @@
57
83
  }
58
84
  }
59
85
  if display != "" {
60
- context {
61
- let default-size = height * 0.6
62
- let min-size = 6pt
63
- let x-inset = 2pt
64
- let m = measure(text(size: default-size, display))
65
- let scale = calc.min(1.0, (width - 2 * x-inset) / m.width)
66
- let final-size = calc.max(min-size, default-size * scale)
67
- box(
68
- width: width,
69
- height: height,
70
- clip: true,
71
- inset: (x: x-inset),
72
- align(left + horizon, text(size: final-size, display)),
73
- )
74
- }
86
+ render-text-field(display, width, height, 2pt, 1pt)
75
87
  }
76
88
  }
77
89
  }