standard-procedure-consolidate 0.3.9 → 0.4.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/checksums/standard-procedure-consolidate-0.4.0.gem.sha512 +1 -0
- data/lib/consolidate/docx/image.rb +11 -3
- data/lib/consolidate/docx/image_reference_node_builder.rb +64 -62
- data/lib/consolidate/docx/merge.rb +138 -48
- data/lib/consolidate/image.rb +4 -1
- data/lib/consolidate/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 39e8b33a8f43ddb4a3bff6ccfb91ee9608d741dc9dff3759ea7c45b1c3cf3d3c
|
4
|
+
data.tar.gz: 71d357d9e60a98f199c7d67ab3f6a0b5ee8999218162fabf43a4fc4283f04a85
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e68a557b00ecb43feb93cdc9a5c9a4c09edd93f8421206be3372e617809bc9ce01cb9ad4928e6f97f49b6db64fd9a329dd2ff7360d5d7b618ce455d0f080c6b1
|
7
|
+
data.tar.gz: 94417403770d855c0df0d1927b3de00235a668503790e06388de83cadb3b3d2b533f394fab3ddcda5ace164bbe7394810c8ad6b00092eb553552f74fabaa2e5e
|
data/CHANGELOG.md
CHANGED
@@ -0,0 +1 @@
|
|
1
|
+
58d1597374e775340c60e3e49b9d65437909b482f7be3040fb9fdca5d8d4b4d3020508a9ee01e3521b2c552e1b853d0475335d1ca1c092b4172c1e9ac86df640
|
@@ -13,12 +13,20 @@ module Consolidate
|
|
13
13
|
def storage_path = "word/#{media_path}"
|
14
14
|
|
15
15
|
# Convert width from pixels to EMU
|
16
|
-
def width = super *
|
16
|
+
def width = super * emu_per_width_pixel
|
17
17
|
|
18
18
|
# Convert height from pixels to EMU
|
19
|
-
def height = super *
|
19
|
+
def height = super * emu_per_height_pixel
|
20
20
|
|
21
|
-
|
21
|
+
# Get the width of this image in EMU up to a maximum page width (also in EMU)
|
22
|
+
def clamped_width(maximum = 7_772_400) = [width, maximum].min
|
23
|
+
|
24
|
+
# Get the height of this image in EMU adjusted for a maximum page width (also in EMU)
|
25
|
+
def clamped_height(maximum = 7_772_400) = (height * clamped_width(maximum).to_f / width.to_f).to_i
|
26
|
+
|
27
|
+
def emu_per_width_pixel = 914_400 / dpi[:x]
|
28
|
+
|
29
|
+
def emu_per_height_pixel = 914_400 / dpi[:y]
|
22
30
|
end
|
23
31
|
end
|
24
32
|
end
|
@@ -5,74 +5,67 @@ require "nokogiri"
|
|
5
5
|
|
6
6
|
module Consolidate
|
7
7
|
module Docx
|
8
|
-
class ImageReferenceNodeBuilder < Data.define(:field_name, :image, :node_id, :document)
|
8
|
+
class ImageReferenceNodeBuilder < Data.define(:field_name, :image, :node_id, :image_number, :document)
|
9
9
|
def call
|
10
|
-
Nokogiri::XML::Node.new("w:
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
graphic_frame_locks["noChangeAspect"] = "1"
|
31
|
-
end
|
10
|
+
Nokogiri::XML::Node.new("w:drawing", document).tap do |drawing|
|
11
|
+
drawing["xmlns:a"] = "http://schemas.openxmlformats.org/drawingml/2006/main"
|
12
|
+
drawing << Nokogiri::XML::Node.new("wp:inline", document).tap do |inline|
|
13
|
+
inline["distT"] = "0"
|
14
|
+
inline["distB"] = "0"
|
15
|
+
inline["distL"] = "0"
|
16
|
+
inline["distR"] = "0"
|
17
|
+
inline << Nokogiri::XML::Node.new("wp:extent", document).tap do |extent|
|
18
|
+
extent["cx"] = image.clamped_width(max_width_from(document))
|
19
|
+
extent["cy"] = image.clamped_height(max_width_from(document))
|
20
|
+
end
|
21
|
+
inline << Nokogiri::XML::Node.new("wp:effectExtent", document).tap do |effect_extent|
|
22
|
+
effect_extent["l"] = "0"
|
23
|
+
effect_extent["t"] = "0"
|
24
|
+
effect_extent["r"] = "0"
|
25
|
+
effect_extent["b"] = "0"
|
26
|
+
end
|
27
|
+
inline << Nokogiri::XML::Node.new("wp:cNvGraphicFramePr", document).tap do |c_nv_graphic_frame_pr|
|
28
|
+
c_nv_graphic_frame_pr << Nokogiri::XML::Node.new("a:graphicFrameLocks", document).tap do |graphic_frame_locks|
|
29
|
+
graphic_frame_locks["noChangeAspect"] = true
|
32
30
|
end
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
end
|
48
|
-
end
|
31
|
+
end
|
32
|
+
inline << Nokogiri::XML::Node.new("a:graphic", document).tap do |graphic|
|
33
|
+
graphic["xmlns:a"] = "http://schemas.openxmlformats.org/drawingml/2006/main"
|
34
|
+
graphic << Nokogiri::XML::Node.new("a:graphicData", document).tap do |graphic_data|
|
35
|
+
graphic_data["uri"] = "http://schemas.openxmlformats.org/drawingml/2006/picture"
|
36
|
+
graphic_data << Nokogiri::XML::Node.new("pic:pic", document).tap do |pic|
|
37
|
+
pic["xmlns:pic"] = "http://schemas.openxmlformats.org/drawingml/2006/picture"
|
38
|
+
pic << Nokogiri::XML::Node.new("pic:nvPicPr", document).tap do |nv_pic_pr|
|
39
|
+
nv_pic_pr << Nokogiri::XML::Node.new("pic:cNvPr", document).tap do |c_nv_pr|
|
40
|
+
c_nv_pr["id"] = image_number
|
41
|
+
c_nv_pr["name"] = image.name
|
42
|
+
c_nv_pr["descr"] = image.name
|
43
|
+
c_nv_pr["hidden"] = false
|
44
|
+
c_nv_pr << Nokogiri::XML::Node.new("pic:cNvPicPr", document)
|
49
45
|
end
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
blip << Nokogiri::XML::Node.new("a:extLst", document)
|
55
|
-
end
|
56
|
-
blip_fill << Nokogiri::XML::Node.new("a:stretch", document).tap do |stretch|
|
57
|
-
stretch << Nokogiri::XML::Node.new("a:fillRect", document)
|
58
|
-
end
|
46
|
+
end
|
47
|
+
pic << Nokogiri::XML::Node.new("pic:blipFill", document).tap do |blip_fill|
|
48
|
+
blip_fill << Nokogiri::XML::Node.new("a:blip", document).tap do |blip|
|
49
|
+
blip["r:embed"] = node_id
|
59
50
|
end
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
end
|
51
|
+
blip_fill << Nokogiri::XML::Node.new("a:stretch", document).tap do |stretch|
|
52
|
+
stretch << Nokogiri::XML::Node.new("a:fillRect", document)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
pic << Nokogiri::XML::Node.new("pic:spPr", document).tap do |sp_pr|
|
56
|
+
sp_pr << Nokogiri::XML::Node.new("a:xfrm", document).tap do |xfrm|
|
57
|
+
xfrm << Nokogiri::XML::Node.new("a:off", document).tap do |off|
|
58
|
+
off["x"] = "0"
|
59
|
+
off["y"] = "0"
|
70
60
|
end
|
71
|
-
|
72
|
-
|
73
|
-
|
61
|
+
xfrm << Nokogiri::XML::Node.new("a:ext", document).tap do |ext|
|
62
|
+
ext["cx"] = image.clamped_width(max_width_from(document))
|
63
|
+
ext["cy"] = image.clamped_height(max_width_from(document))
|
74
64
|
end
|
75
|
-
|
65
|
+
end
|
66
|
+
sp_pr << Nokogiri::XML::Node.new("a:prstGeom", document).tap do |prst_geom|
|
67
|
+
prst_geom["prst"] = "rect"
|
68
|
+
prst_geom << Nokogiri::XML::Node.new("a:avLst", document)
|
76
69
|
end
|
77
70
|
end
|
78
71
|
end
|
@@ -81,6 +74,15 @@ module Consolidate
|
|
81
74
|
end
|
82
75
|
end
|
83
76
|
end
|
77
|
+
|
78
|
+
DEFAULT_PAGE_WIDTH = 12_240
|
79
|
+
TWENTIETHS_OF_A_POINT_TO_EMU = 635
|
80
|
+
DEFAULT_PAGE_WIDTH_IN_EMU = DEFAULT_PAGE_WIDTH * TWENTIETHS_OF_A_POINT_TO_EMU
|
81
|
+
|
82
|
+
private def max_width_from document
|
83
|
+
page_width = (document.at_xpath("//w:sectPr/w:pgSz/@w:w")&.value || DEFAULT_PAGE_WIDTH).to_i
|
84
|
+
page_width * TWENTIETHS_OF_A_POINT_TO_EMU
|
85
|
+
end
|
84
86
|
end
|
85
87
|
end
|
86
88
|
end
|
@@ -20,13 +20,16 @@ module Consolidate
|
|
20
20
|
@zip = Zip::File.open(path)
|
21
21
|
@documents = load_documents
|
22
22
|
@relations = load_relations
|
23
|
+
@contents_xml = load_and_update_contents_xml
|
23
24
|
@output = {}
|
24
25
|
@images = {}
|
26
|
+
@mapping = {}
|
25
27
|
end
|
26
28
|
|
27
29
|
# Helper method to display the contents of the document and the merge fields from the CLI
|
28
30
|
def examine
|
29
31
|
puts "Documents: #{document_names.join(", ")}"
|
32
|
+
puts "Content documents: #{content_document_names.join(", ")}"
|
30
33
|
puts "Merge fields: #{text_field_names.join(", ")}"
|
31
34
|
puts "Image fields: #{image_field_names.join(", ")}"
|
32
35
|
end
|
@@ -38,29 +41,47 @@ module Consolidate
|
|
38
41
|
def image_field_names = @image_field_names ||= tag_nodes.collect { |tag_node| image_field_names_from tag_node }.flatten.compact.uniq
|
39
42
|
|
40
43
|
# List the documents stored within this docx
|
41
|
-
def document_names = @zip.entries.
|
44
|
+
def document_names = @zip.entries.map(&:name)
|
45
|
+
|
46
|
+
# List the content within this docx
|
47
|
+
def content_document_names = @documents.keys
|
48
|
+
|
49
|
+
# List the field names that are present in the merge data
|
50
|
+
def merge_field_names = @mapping.keys
|
42
51
|
|
43
52
|
# Set the merge data and erform the substitution - creating copies of any documents that contain merge tags and replacing the tags with the supplied data
|
44
53
|
def data mapping = {}
|
45
|
-
mapping = mapping.transform_keys(&:to_s)
|
46
|
-
|
54
|
+
@mapping = mapping.transform_keys(&:to_s)
|
55
|
+
if verbose
|
56
|
+
puts "...mapping data"
|
57
|
+
puts @mapping.keys.select { |field_name| text_field_names.include?(field_name) }.map { |field_name| "... #{field_name} => #{@mapping[field_name]}" }.join("\n")
|
58
|
+
end
|
47
59
|
|
48
|
-
@images =
|
60
|
+
@images = load_images_and_link_relations
|
49
61
|
|
50
62
|
@documents.each do |name, document|
|
51
|
-
@output[name] = substitute(document.dup,
|
63
|
+
@output[name] = substitute(document.dup, document_name: name).serialize save_with: 0
|
52
64
|
end
|
53
65
|
end
|
54
66
|
|
55
67
|
def write_to path
|
56
68
|
puts "...writing to #{path}" if verbose
|
57
69
|
Zip::File.open(path, Zip::File::CREATE) do |out|
|
70
|
+
@output[contents_xml] = @contents_xml.serialize save_with: 0
|
71
|
+
|
58
72
|
@images.each do |field_name, image|
|
59
|
-
puts "... writing #{field_name} to #{image.storage_path}" if verbose
|
73
|
+
puts "... writing image #{field_name} to #{image.storage_path}" if verbose
|
60
74
|
out.get_output_stream(image.storage_path) { |o| o.write image.contents }
|
61
75
|
end
|
62
76
|
|
63
|
-
@
|
77
|
+
@relations.each do |relation_name, relations|
|
78
|
+
puts "... writing relations #{relation_name}" if verbose
|
79
|
+
out.get_output_stream(relation_name) { |o| o.write relations }
|
80
|
+
end
|
81
|
+
|
82
|
+
@zip.reject do |entry|
|
83
|
+
@relations.key? entry.name
|
84
|
+
end.each do |entry|
|
64
85
|
puts "... writing updated document to #{entry.name}" if verbose
|
65
86
|
out.get_output_stream(entry.name) { |o| o.write(@output[entry.name] || @relations[entry.name] || @zip.read(entry.name)) }
|
66
87
|
end
|
@@ -71,25 +92,7 @@ module Consolidate
|
|
71
92
|
|
72
93
|
attr_reader :verbose
|
73
94
|
|
74
|
-
def
|
75
|
-
@zip.entries.each_with_object({}) do |entry, results|
|
76
|
-
next unless entry.name.match?(/word\/(document|header|footer|footnotes|endnotes).?\.xml/)
|
77
|
-
puts "...reading document #{entry.name}" if verbose
|
78
|
-
contents = @zip.get_input_stream entry
|
79
|
-
results[entry.name] = Nokogiri::XML(contents) { |x| x.noent }
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
def load_relations
|
84
|
-
@zip.entries.each_with_object({}) do |entry, results|
|
85
|
-
next unless entry.name.match?(/word\/_rels\/.*.rels/)
|
86
|
-
puts "...reading relation #{entry.name}" if verbose
|
87
|
-
contents = @zip.get_input_stream entry
|
88
|
-
results[entry.name] = Nokogiri::XML(contents) { |x| x.noent }
|
89
|
-
end
|
90
|
-
ensure
|
91
|
-
@zip.close
|
92
|
-
end
|
95
|
+
def contents_xml = "[Content_Types].xml"
|
93
96
|
|
94
97
|
# Regex to find merge fields that contain text
|
95
98
|
def text_tag = /\{\{\s*(?!.*_image\b)(\S+)\s*\}\}/i
|
@@ -113,30 +116,59 @@ module Consolidate
|
|
113
116
|
# Extract the image field name(s) from the paragraph
|
114
117
|
def image_field_names_from(tag_node) = (matches = tag_node.content.scan(image_tag)).empty? ? nil : matches.flatten.map(&:strip)
|
115
118
|
|
119
|
+
# Unique number for each image field
|
120
|
+
def relation_number_for(field_name) = @mapping.keys.index(field_name) + 1000
|
121
|
+
|
116
122
|
# Identifier to use when linking a merge field to the actual image file contents
|
117
|
-
def relation_id_for(field_name) = "rId#{field_name}"
|
123
|
+
def relation_id_for(field_name) = "rId#{relation_number_for(field_name)}"
|
124
|
+
|
125
|
+
# Empty elations document for documents that do not already have one
|
126
|
+
def default_relations_document = %(<?xml version="1.0" encoding="UTF-8"?><Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"></Relationships>)
|
127
|
+
|
128
|
+
def load_documents
|
129
|
+
@zip.entries.each_with_object({}) do |entry, results|
|
130
|
+
next unless entry.name.match?(/word\/(document|header|footer|footnotes|endnotes).?\.xml/)
|
131
|
+
puts "...reading document #{entry.name}" if verbose
|
132
|
+
contents = @zip.get_input_stream entry
|
133
|
+
results[entry.name] = Nokogiri::XML(contents) { |x| x.noent }
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def load_relations
|
138
|
+
@zip.entries.each_with_object({}) do |entry, results|
|
139
|
+
next unless entry.name.match?(/word\/(document|header|footer|footnotes|endnotes).?\.xml/)
|
140
|
+
relation_document = entry.name.gsub("word/", "word/_rels/").gsub(".xml", ".xml.rels")
|
141
|
+
puts "...reading or building relations for #{relation_document}" if verbose
|
142
|
+
contents = @zip.find_entry(relation_document) ? @zip.get_input_stream(relation_document) : default_relations_document
|
143
|
+
results[relation_document] = Nokogiri::XML(contents) { |x| x.noent }
|
144
|
+
end
|
145
|
+
ensure
|
146
|
+
@zip.close
|
147
|
+
end
|
118
148
|
|
119
149
|
# Create relation links for each image field and store the image data
|
120
|
-
def
|
121
|
-
|
150
|
+
def load_images_and_link_relations
|
151
|
+
load_images.tap do |images|
|
122
152
|
link_relations_to images
|
123
153
|
end
|
124
154
|
end
|
125
155
|
|
126
156
|
# Build a mapping of image paths to the image data so that the image data can be stored in the output docx
|
127
|
-
def
|
157
|
+
def load_images
|
128
158
|
image_field_names.each_with_object({}) do |field_name, result|
|
129
|
-
result[field_name] = Consolidate::Docx::Image.new(mapping[field_name])
|
159
|
+
result[field_name] = Consolidate::Docx::Image.new(@mapping[field_name])
|
160
|
+
puts "... #{field_name} => #{result[field_name].media_path}" if verbose
|
130
161
|
end
|
131
162
|
end
|
132
163
|
|
133
164
|
# Update all relation documents to include a relationship for each image field and its stored image path
|
134
165
|
def link_relations_to images
|
135
166
|
@relations.each do |name, xml|
|
167
|
+
puts "... linking images in #{name}" if verbose
|
136
168
|
images.each do |field_name, image|
|
137
169
|
# Is this image already referenced in this relationship document?
|
138
|
-
next unless xml.at_xpath("//Relationship[@Target
|
139
|
-
puts "...
|
170
|
+
next unless xml.at_xpath("//Relationship[@Target=\"#{image.media_path}\"]").nil?
|
171
|
+
puts "... #{relation_id_for(field_name)} => #{image.media_path}" if verbose
|
140
172
|
xml.root << Nokogiri::XML::Node.new("Relationship", xml).tap do |relation|
|
141
173
|
relation["Id"] = relation_id_for(field_name)
|
142
174
|
relation["Type"] = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"
|
@@ -146,32 +178,38 @@ module Consolidate
|
|
146
178
|
end
|
147
179
|
end
|
148
180
|
|
181
|
+
def load_and_update_contents_xml
|
182
|
+
puts "...reading and updating #{contents_xml}" if verbose
|
183
|
+
content = @zip.get_input_stream(contents_xml)
|
184
|
+
Nokogiri::XML(content) { |x| x.noent }.tap do |document|
|
185
|
+
add_content_relations_to document
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
149
189
|
# Go through the given document, replacing any merge fields with the values provided
|
150
190
|
# and storing the results in a new document
|
151
|
-
def substitute document, document_name
|
191
|
+
def substitute document, document_name:
|
192
|
+
puts "...substituting fields in #{document_name}" if verbose && tag_nodes_for(document).any?
|
193
|
+
substitute_text document, document_name: document_name
|
194
|
+
substitute_images document, document_name: document_name
|
195
|
+
end
|
196
|
+
|
197
|
+
def substitute_text document, document_name:
|
152
198
|
tag_nodes_for(document).each do |tag_node|
|
153
|
-
|
154
|
-
image_field_names = image_field_names_from(tag_node) || []
|
199
|
+
field_names = text_field_names_from(tag_node) || []
|
155
200
|
|
156
201
|
# Extract the properties (formatting) nodes if they exist
|
157
202
|
paragraph_properties = tag_node.search ".//w:pPr"
|
158
203
|
run_properties = tag_node.at_xpath ".//w:rPr"
|
159
204
|
|
160
|
-
# Get the current contents, then substitute any text fields
|
205
|
+
# Get the current contents, then substitute any text fields
|
161
206
|
text = tag_node.content
|
162
207
|
|
163
|
-
|
164
|
-
field_value = mapping[field_name].to_s
|
165
|
-
puts "...substituting #{field_name} with #{field_value}
|
208
|
+
field_names.each do |field_name|
|
209
|
+
field_value = @mapping[field_name].to_s
|
210
|
+
puts "... substituting '#{field_name}' with '#{field_value}'" if verbose
|
166
211
|
text = text.gsub(tag_for(field_name), field_value)
|
167
212
|
end
|
168
|
-
image_nodes = image_field_names.collect do |field_name|
|
169
|
-
image = @images[field_name]
|
170
|
-
puts "...substituting #{field_name} in #{document_name}" if verbose
|
171
|
-
# Remove the merge tag and create an image reference node to be added to this node
|
172
|
-
text = text.gsub(tag_for(field_name), "")
|
173
|
-
ImageReferenceNodeBuilder.new(field_name: field_name, image: image, node_id: relation_id_for(field_name), document: document).call
|
174
|
-
end
|
175
213
|
|
176
214
|
# Create a new text node with the substituted text
|
177
215
|
text_node = Nokogiri::XML::Node.new("w:t", tag_node.document)
|
@@ -182,7 +220,39 @@ module Consolidate
|
|
182
220
|
run_node << run_properties unless run_properties.nil?
|
183
221
|
run_node << text_node
|
184
222
|
# Add the paragraph properties and the run node to the tag node
|
185
|
-
tag_node.children = Nokogiri::XML::NodeSet.new(document, paragraph_properties.to_a + [run_node]
|
223
|
+
tag_node.children = Nokogiri::XML::NodeSet.new(document, paragraph_properties.to_a + [run_node])
|
224
|
+
rescue => ex
|
225
|
+
# Have to mangle the exception message otherwise it outputs the entire document
|
226
|
+
puts ex.message.to_s[0..255]
|
227
|
+
puts ex.backtrace.first
|
228
|
+
end
|
229
|
+
document
|
230
|
+
end
|
231
|
+
|
232
|
+
# Go through the given document, replacing any merge fields with the values provided
|
233
|
+
# and storing the results in a new document
|
234
|
+
def substitute_images document, document_name:
|
235
|
+
tag_nodes_for(document).each do |tag_node|
|
236
|
+
field_names = image_field_names_from(tag_node) || []
|
237
|
+
# Extract the properties (formatting) nodes if they exist
|
238
|
+
paragraph_properties = tag_node.search ".//w:pPr"
|
239
|
+
run_properties = tag_node.at_xpath ".//w:rPr"
|
240
|
+
|
241
|
+
pieces = tag_node.content.split(image_tag)
|
242
|
+
# Split the content into pieces - either text or an image merge field
|
243
|
+
# Then replace the text with text nodes or the image merge fields with drawing nodes
|
244
|
+
replacement_nodes = pieces.collect do |piece|
|
245
|
+
field_name = piece.strip
|
246
|
+
if field_names.include? field_name
|
247
|
+
image = @images[field_name]
|
248
|
+
puts "... substituting '#{field_name}' with '<#{relation_id_for(field_name)}/>'" if verbose
|
249
|
+
ImageReferenceNodeBuilder.new(field_name: field_name, image: image, node_id: relation_id_for(field_name), image_number: relation_number_for(field_name), document: document).call
|
250
|
+
else
|
251
|
+
Nokogiri::XML::Node.new("w:t", document) { |t| t.content = piece }
|
252
|
+
end
|
253
|
+
end
|
254
|
+
run_nodes = (replacement_nodes.map { |node| Nokogiri::XML::Node.new("w:r", document) { |run_node| run_node.children = node } } + [run_properties]).compact
|
255
|
+
tag_node.children = Nokogiri::XML::NodeSet.new(document, paragraph_properties.to_a + run_nodes)
|
186
256
|
rescue => ex
|
187
257
|
# Have to mangle the exception message otherwise it outputs the entire document
|
188
258
|
puts ex.message.to_s[0..255]
|
@@ -190,6 +260,26 @@ module Consolidate
|
|
190
260
|
end
|
191
261
|
document
|
192
262
|
end
|
263
|
+
|
264
|
+
CONTENT_RELATIONS = {
|
265
|
+
jpeg: "image/jpg",
|
266
|
+
png: "image/png",
|
267
|
+
bmp: "image/bmp",
|
268
|
+
gif: "image/gif",
|
269
|
+
tif: "image/tif",
|
270
|
+
pdf: "application/pdf",
|
271
|
+
mov: "application/movie"
|
272
|
+
}.freeze
|
273
|
+
|
274
|
+
def add_content_relations_to document
|
275
|
+
CONTENT_RELATIONS.each do |file_type, content_type|
|
276
|
+
next unless document.at_xpath("//Default[@Extension=\"#{file_type}\"]").nil?
|
277
|
+
document.root << Nokogiri::XML::Node.new("Default", document).tap do |relation|
|
278
|
+
relation["Extension"] = file_type
|
279
|
+
relation["ContentType"] = content_type
|
280
|
+
end
|
281
|
+
end
|
282
|
+
end
|
193
283
|
end
|
194
284
|
end
|
195
285
|
end
|
data/lib/consolidate/image.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module Consolidate
|
4
4
|
class Image
|
5
|
-
attr_reader :name, :width, :height
|
5
|
+
attr_reader :name, :width, :height, :aspect_ratio, :dpi
|
6
6
|
|
7
7
|
def initialize name:, width:, height:, path: nil, url: nil, contents: nil
|
8
8
|
@name = name
|
@@ -11,6 +11,9 @@ module Consolidate
|
|
11
11
|
@path = path
|
12
12
|
@url = url
|
13
13
|
@contents = contents
|
14
|
+
@aspect_ratio = width.to_f / height.to_f
|
15
|
+
# TODO: Read this from the contents
|
16
|
+
@dpi = {x: 72, y: 72}
|
14
17
|
end
|
15
18
|
|
16
19
|
def to_s = name
|
data/lib/consolidate/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: standard-procedure-consolidate
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rahoul Baruah
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-12-
|
11
|
+
date: 2024-12-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rubyzip
|
@@ -64,6 +64,7 @@ files:
|
|
64
64
|
- checksums/standard-procedure-consolidate-0.3.0.gem.sha512
|
65
65
|
- checksums/standard-procedure-consolidate-0.3.1.gem.sha512
|
66
66
|
- checksums/standard-procedure-consolidate-0.3.9.gem.sha512
|
67
|
+
- checksums/standard-procedure-consolidate-0.4.0.gem.sha512
|
67
68
|
- exe/consolidate
|
68
69
|
- exe/examine
|
69
70
|
- lib/consolidate.rb
|