acro_that 1.0.3 → 1.0.4
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -0
- data/Gemfile.lock +5 -1
- data/acro_that.gemspec +1 -0
- data/lib/acro_that/actions/update_field.rb +10 -10
- data/lib/acro_that/dict_scan.rb +32 -4
- data/lib/acro_that/fields/checkbox.rb +10 -10
- data/lib/acro_that/fields/radio.rb +10 -10
- data/lib/acro_that/pdf_writer.rb +4 -3
- data/lib/acro_that/version.rb +1 -1
- data/lib/acro_that.rb +1 -0
- metadata +16 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8983cb8f5bef4f8085baf807e7fea9b8efc11d0d25efc3cbcd25b54a8e938af3
|
|
4
|
+
data.tar.gz: 646674f34985529556d9b36ee91351aa7fd25a3e0ca561814fa9ae2274da7653
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f1827af100fbb441cd52015c146abc2522852c3c57f4cdcdec32b382c91db0896fef918a101bcd65ced3167ad201eed136c279baa4c59139318f41cfc6db5116
|
|
7
|
+
data.tar.gz: 877931eced47139862b7966fd9b73307532e075e218538e7fda02bd768a6a13354ed0e5fefe9481d2b1af3d756a7a81a1f129f34f42eb80b4c19031d8906e913
|
data/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,16 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [1.0.4] - 2025-11-12
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
- Fixed `Encoding::CompatibilityError` when processing field values with special characters (e.g., "María", "José"). Special characters are now automatically transliterated to ASCII equivalents (e.g., "María" → "Maria") before encoding to PDF format, ensuring compatibility with PDF string encoding requirements.
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
- Added I18n gem as a runtime dependency for transliteration support
|
|
15
|
+
- Added `DictScan.transliterate_to_ascii` method to convert special characters to ASCII equivalents
|
|
16
|
+
- Automatic transliteration for text field values and radio button field export values
|
|
17
|
+
|
|
8
18
|
## [0.1.8] - 2025-11-04
|
|
9
19
|
|
|
10
20
|
### Fixed
|
data/Gemfile.lock
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
acro_that (1.0.
|
|
4
|
+
acro_that (1.0.3)
|
|
5
5
|
chunky_png (~> 1.4)
|
|
6
|
+
i18n (~> 1.14)
|
|
6
7
|
|
|
7
8
|
GEM
|
|
8
9
|
remote: https://rubygems.org/
|
|
@@ -10,7 +11,10 @@ GEM
|
|
|
10
11
|
ast (2.4.3)
|
|
11
12
|
chunky_png (1.4.0)
|
|
12
13
|
coderay (1.1.3)
|
|
14
|
+
concurrent-ruby (1.3.5)
|
|
13
15
|
diff-lcs (1.6.2)
|
|
16
|
+
i18n (1.14.7)
|
|
17
|
+
concurrent-ruby (~> 1.0)
|
|
14
18
|
json (2.15.2)
|
|
15
19
|
language_server-protocol (3.17.0.5)
|
|
16
20
|
lint_roller (1.1.0)
|
data/acro_that.gemspec
CHANGED
|
@@ -28,6 +28,7 @@ Gem::Specification.new do |spec|
|
|
|
28
28
|
spec.require_paths = ["lib"]
|
|
29
29
|
|
|
30
30
|
spec.add_runtime_dependency "chunky_png", "~> 1.4"
|
|
31
|
+
spec.add_runtime_dependency "i18n", "~> 1.14"
|
|
31
32
|
spec.add_development_dependency "rspec", "~> 3.0"
|
|
32
33
|
spec.add_development_dependency "pry", "~> 0.14"
|
|
33
34
|
spec.add_development_dependency "rubocop", "~> 1.50"
|
|
@@ -591,23 +591,23 @@ module AcroThat
|
|
|
591
591
|
|
|
592
592
|
# Calculate scale to maximize size while maintaining aspect ratio
|
|
593
593
|
# Use the smaller dimension to ensure it fits
|
|
594
|
-
scale = [width, height].min * 0.85
|
|
595
|
-
|
|
594
|
+
scale = [width, height].min * 0.85 # Use 85% of the smaller dimension
|
|
595
|
+
|
|
596
596
|
# Calculate checkmark dimensions
|
|
597
597
|
check_width = scale
|
|
598
598
|
check_height = scale
|
|
599
|
-
|
|
599
|
+
|
|
600
600
|
# Center the checkmark in the box
|
|
601
601
|
offset_x = (width - check_width) / 2
|
|
602
602
|
offset_y = (height - check_height) / 2
|
|
603
|
-
|
|
603
|
+
|
|
604
604
|
# Calculate actual coordinates
|
|
605
|
-
check_x1 = offset_x + norm_x1 * check_width
|
|
606
|
-
check_y1 = offset_y + norm_y1 * check_height
|
|
607
|
-
check_x2 = offset_x + norm_x2 * check_width
|
|
608
|
-
check_y2 = offset_y + norm_y2 * check_height
|
|
609
|
-
check_x3 = offset_x + norm_x3 * check_width
|
|
610
|
-
check_y3 = offset_y + norm_y3 * check_height
|
|
605
|
+
check_x1 = offset_x + (norm_x1 * check_width)
|
|
606
|
+
check_y1 = offset_y + (norm_y1 * check_height)
|
|
607
|
+
check_x2 = offset_x + (norm_x2 * check_width)
|
|
608
|
+
check_y2 = offset_y + (norm_y2 * check_height)
|
|
609
|
+
check_x3 = offset_x + (norm_x3 * check_width)
|
|
610
|
+
check_y3 = offset_y + (norm_y3 * check_height)
|
|
611
611
|
|
|
612
612
|
content_stream = "q\n"
|
|
613
613
|
# Draw square border around field bounds
|
data/lib/acro_that/dict_scan.rb
CHANGED
|
@@ -4,6 +4,26 @@ module AcroThat
|
|
|
4
4
|
module DictScan
|
|
5
5
|
module_function
|
|
6
6
|
|
|
7
|
+
# Configure I18n for transliteration (disable locale enforcement)
|
|
8
|
+
I18n.config.enforce_available_locales = false
|
|
9
|
+
|
|
10
|
+
# Transliterate a string to ASCII, converting special characters to their ASCII equivalents
|
|
11
|
+
# Example: "María Valentina" -> "Maria Valentina"
|
|
12
|
+
def transliterate_to_ascii(str)
|
|
13
|
+
return str unless str.is_a?(String)
|
|
14
|
+
|
|
15
|
+
# Ensure the string is in UTF-8 encoding
|
|
16
|
+
utf8_str = str.encode("UTF-8", invalid: :replace, undef: :replace)
|
|
17
|
+
|
|
18
|
+
# Use I18n transliteration to convert to ASCII
|
|
19
|
+
begin
|
|
20
|
+
I18n.transliterate(utf8_str, locale: :en, replacement: "")
|
|
21
|
+
rescue StandardError
|
|
22
|
+
# Fallback: if transliteration fails, try to encode to ASCII with replacements
|
|
23
|
+
utf8_str.encode("ASCII", invalid: :replace, undef: :replace)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
7
27
|
# --- low-level string helpers -------------------------------------------------
|
|
8
28
|
|
|
9
29
|
def strip_stream_bodies(pdf)
|
|
@@ -118,10 +138,15 @@ module AcroThat
|
|
|
118
138
|
when Symbol
|
|
119
139
|
"/#{val}"
|
|
120
140
|
when String
|
|
121
|
-
|
|
122
|
-
|
|
141
|
+
# Transliterate special characters to ASCII to avoid encoding issues
|
|
142
|
+
ascii_val = transliterate_to_ascii(val)
|
|
143
|
+
|
|
144
|
+
if ascii_val.ascii_only?
|
|
145
|
+
"(#{ascii_val.gsub(/([\\()])/, '\\\\\\1').gsub("\n", '\\n')})"
|
|
123
146
|
else
|
|
124
|
-
|
|
147
|
+
# Ensure string is in UTF-8 before encoding to UTF-16BE
|
|
148
|
+
utf8_str = ascii_val.encode("UTF-8", invalid: :replace, undef: :replace)
|
|
149
|
+
utf16 = utf8_str.encode("UTF-16BE")
|
|
125
150
|
bytes = "\xFE\xFF#{utf16}"
|
|
126
151
|
"<#{bytes.unpack1('H*')}>"
|
|
127
152
|
end
|
|
@@ -138,8 +163,11 @@ module AcroThat
|
|
|
138
163
|
# Remove leading / if present (we'll add it back)
|
|
139
164
|
name_str = name_str[1..] if name_str.start_with?("/")
|
|
140
165
|
|
|
166
|
+
# Transliterate special characters to ASCII to avoid encoding issues
|
|
167
|
+
ascii_name = transliterate_to_ascii(name_str)
|
|
168
|
+
|
|
141
169
|
# Encode special characters as hex
|
|
142
|
-
encoded =
|
|
170
|
+
encoded = ascii_name.each_byte.map do |byte|
|
|
143
171
|
char = byte.chr
|
|
144
172
|
# PDF name special characters that need hex encoding: # ( ) < > [ ] { } / %
|
|
145
173
|
# Also encode control characters (0x00-0x1F, 0x7F) and non-ASCII (0x80-0xFF)
|
|
@@ -99,23 +99,23 @@ module AcroThat
|
|
|
99
99
|
|
|
100
100
|
# Calculate scale to maximize size while maintaining aspect ratio
|
|
101
101
|
# Use the smaller dimension to ensure it fits
|
|
102
|
-
scale = [width, height].min * 0.85
|
|
103
|
-
|
|
102
|
+
scale = [width, height].min * 0.85 # Use 85% of the smaller dimension
|
|
103
|
+
|
|
104
104
|
# Calculate checkmark dimensions
|
|
105
105
|
check_width = scale
|
|
106
106
|
check_height = scale
|
|
107
|
-
|
|
107
|
+
|
|
108
108
|
# Center the checkmark in the box
|
|
109
109
|
offset_x = (width - check_width) / 2
|
|
110
110
|
offset_y = (height - check_height) / 2
|
|
111
|
-
|
|
111
|
+
|
|
112
112
|
# Calculate actual coordinates
|
|
113
|
-
check_x1 = offset_x + norm_x1 * check_width
|
|
114
|
-
check_y1 = offset_y + norm_y1 * check_height
|
|
115
|
-
check_x2 = offset_x + norm_x2 * check_width
|
|
116
|
-
check_y2 = offset_y + norm_y2 * check_height
|
|
117
|
-
check_x3 = offset_x + norm_x3 * check_width
|
|
118
|
-
check_y3 = offset_y + norm_y3 * check_height
|
|
113
|
+
check_x1 = offset_x + (norm_x1 * check_width)
|
|
114
|
+
check_y1 = offset_y + (norm_y1 * check_height)
|
|
115
|
+
check_x2 = offset_x + (norm_x2 * check_width)
|
|
116
|
+
check_y2 = offset_y + (norm_y2 * check_height)
|
|
117
|
+
check_x3 = offset_x + (norm_x3 * check_width)
|
|
118
|
+
check_y3 = offset_y + (norm_y3 * check_height)
|
|
119
119
|
|
|
120
120
|
content_stream = "q\n"
|
|
121
121
|
# Draw square border around field bounds
|
|
@@ -176,23 +176,23 @@ module AcroThat
|
|
|
176
176
|
|
|
177
177
|
# Calculate scale to maximize size while maintaining aspect ratio
|
|
178
178
|
# Use the smaller dimension to ensure it fits
|
|
179
|
-
scale = [width, height].min * 0.85
|
|
180
|
-
|
|
179
|
+
scale = [width, height].min * 0.85 # Use 85% of the smaller dimension
|
|
180
|
+
|
|
181
181
|
# Calculate checkmark dimensions
|
|
182
182
|
check_width = scale
|
|
183
183
|
check_height = scale
|
|
184
|
-
|
|
184
|
+
|
|
185
185
|
# Center the checkmark in the box
|
|
186
186
|
offset_x = (width - check_width) / 2
|
|
187
187
|
offset_y = (height - check_height) / 2
|
|
188
|
-
|
|
188
|
+
|
|
189
189
|
# Calculate actual coordinates
|
|
190
|
-
check_x1 = offset_x + norm_x1 * check_width
|
|
191
|
-
check_y1 = offset_y + norm_y1 * check_height
|
|
192
|
-
check_x2 = offset_x + norm_x2 * check_width
|
|
193
|
-
check_y2 = offset_y + norm_y2 * check_height
|
|
194
|
-
check_x3 = offset_x + norm_x3 * check_width
|
|
195
|
-
check_y3 = offset_y + norm_y3 * check_height
|
|
190
|
+
check_x1 = offset_x + (norm_x1 * check_width)
|
|
191
|
+
check_y1 = offset_y + (norm_y1 * check_height)
|
|
192
|
+
check_x2 = offset_x + (norm_x2 * check_width)
|
|
193
|
+
check_y2 = offset_y + (norm_y2 * check_height)
|
|
194
|
+
check_x3 = offset_x + (norm_x3 * check_width)
|
|
195
|
+
check_y3 = offset_y + (norm_y3 * check_height)
|
|
196
196
|
|
|
197
197
|
content_stream = "q\n"
|
|
198
198
|
# Draw checkmark only (no border)
|
data/lib/acro_that/pdf_writer.rb
CHANGED
|
@@ -58,12 +58,12 @@ module AcroThat
|
|
|
58
58
|
while current_obj <= max_obj_num
|
|
59
59
|
# Find next existing object
|
|
60
60
|
next_existing = sorted.find { |num, _gen, _offset| num >= current_obj }
|
|
61
|
-
|
|
61
|
+
|
|
62
62
|
if next_existing && next_existing[0] == current_obj
|
|
63
63
|
# Object exists - find consecutive run of existing objects
|
|
64
64
|
first_num = current_obj
|
|
65
65
|
run_length = 1
|
|
66
|
-
|
|
66
|
+
|
|
67
67
|
while (i + run_length) < sorted.length &&
|
|
68
68
|
sorted[i + run_length][0] == first_num + run_length &&
|
|
69
69
|
sorted[i + run_length][1] == sorted[i][1]
|
|
@@ -86,12 +86,13 @@ module AcroThat
|
|
|
86
86
|
# Object doesn't exist - find consecutive run of missing objects
|
|
87
87
|
first_missing = current_obj
|
|
88
88
|
missing_count = 1
|
|
89
|
-
|
|
89
|
+
|
|
90
90
|
while current_obj + missing_count <= max_obj_num
|
|
91
91
|
check_obj = current_obj + missing_count
|
|
92
92
|
if sorted.any? { |num, _gen, _offset| num == check_obj }
|
|
93
93
|
break
|
|
94
94
|
end
|
|
95
|
+
|
|
95
96
|
missing_count += 1
|
|
96
97
|
end
|
|
97
98
|
|
data/lib/acro_that/version.rb
CHANGED
data/lib/acro_that.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: acro_that
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.0.
|
|
4
|
+
version: 1.0.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Michael Wynkoop
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2025-11-
|
|
11
|
+
date: 2025-11-12 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: chunky_png
|
|
@@ -24,6 +24,20 @@ dependencies:
|
|
|
24
24
|
- - "~>"
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
26
|
version: '1.4'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: i18n
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - "~>"
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '1.14'
|
|
34
|
+
type: :runtime
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - "~>"
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '1.14'
|
|
27
41
|
- !ruby/object:Gem::Dependency
|
|
28
42
|
name: rspec
|
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|