standard-procedure-consolidate 0.3.0 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1bd2015cc0f88bc4b16bae7d8ecd335fb7b28c2bc940f81b1479e4a58ecce647
4
- data.tar.gz: 44905254b9536f40f839d64d0448c4fb40b1a3720fb4d9ba3e2251468175eb9b
3
+ metadata.gz: e7a086625fa1f07169c2f9eba544538df266fbd83702efeedd13998d1a9e83b3
4
+ data.tar.gz: f80f0c11aa839c9dba9c4dc41758471ccfc31d7d38159e902e11d48cc8016c82
5
5
  SHA512:
6
- metadata.gz: 36dee64a5f21766e06e7b5eb213e5a5b4dee9ca04da8bde4b429c4d93c5bd49275226975c7e9887214ea5a3b5975c4f955b245ab45e0103656b928ab59854789
7
- data.tar.gz: 687bba668eb1f137b67c82819561ec2e8c2c3bc9a54f03aa4b6ac76958ae3a15988af8db5f78e7e95adb59968b5764b32c37e71d257b7885d1eb0e10d6e3f56a
6
+ metadata.gz: 72b26cbc5f54cc481ad49cbb604338591e27f1a503330372ab41920a05f3cbde4b1d6b6aa4b607b1189fbd8fd5ed30102d9741b8b6cf762c0cb39c900ac19327
7
+ data.tar.gz: 33ab5fbe36794cf24ca73ce70ec6da8f91cfe5430a438d5794da54bd668e72dd956331401ac983f5d15b7f77d60ef8ac6a3d438e4a0fb6279736c6dd79342931
data/CHANGELOG.md CHANGED
@@ -1,3 +1,8 @@
1
+ ## [0.3.1] - 2024-11-22
2
+
3
+ Ensure that the substituted nodes are reinserted correctly into the output document, attempting to restore formatting at the paragraph level (although it does lose formatting at lower levels than this - so-called "run" nodes which represent arbitrary spans of characters within the paragraph).
4
+
5
+
1
6
  ## [0.3.0] - 2024-11-21
2
7
 
3
8
  Updated the code that examines the docx file for merge fields to deal with Word formatting tags being inserted in the middle of the merge fields.
@@ -0,0 +1 @@
1
+ ac1393002b538b8f000c1e4f1f7f4514f689434dad0889a77a0470bd839c58cb49d6218daafd4a8ca48675e220ab9c42147de78a40ec0fd59d5a19371b699eb0
@@ -30,8 +30,8 @@ module Consolidate
30
30
  # Read all documents within the docx and extract any merge fields
31
31
  def field_names
32
32
  tag_nodes.collect do |tag_node|
33
- field_name_from tag_node
34
- end.compact.uniq
33
+ field_names_from tag_node
34
+ end.flatten.compact.uniq
35
35
  end
36
36
 
37
37
  # List the documents stored within this docx
@@ -45,7 +45,7 @@ module Consolidate
45
45
 
46
46
  if verbose
47
47
  puts "...substitutions..."
48
- fields.each do |key, value|
48
+ mapping.each do |key, value|
49
49
  puts " #{key} => #{value}"
50
50
  end
51
51
  end
@@ -76,6 +76,7 @@ module Consolidate
76
76
  attr_reader :xml
77
77
  attr_reader :documents
78
78
  attr_accessor :output
79
+ TAG = /\{\{\s*(\S+)\s*\}\}/
79
80
 
80
81
  def load_documents
81
82
  @zip.entries.each_with_object({}) do |entry, documents|
@@ -100,40 +101,52 @@ module Consolidate
100
101
  # then find the ancestor node that also includes the ending "}}"
101
102
  # This collection of nodes contains all the merge fields for this document
102
103
  def tag_nodes_for document
103
- (document / "//w:t").collect do |node|
104
- (node.children.any? { |child| child.content.include? "{{" }) ? enclosing_node_for_start_tag(node) : nil
105
- end.compact
104
+ (document / "//w:p").select do |paragraph|
105
+ paragraph.content.match(TAG)
106
+ end
106
107
  end
107
108
 
108
109
  # Extract the merge field name from the node
109
- def field_name_from(tag_node)
110
- return nil unless (matches = tag_node.content.match(/{{\s*(\S+)\s*}}/))
111
- field_name = matches[1].strip
112
- puts "...field #{field_name} found in #{name}" if verbose
113
- field_name.to_s
110
+ def field_names_from(tag_node)
111
+ matches = tag_node.content.scan(TAG)
112
+ matches.empty? ? nil : matches.flatten.map(&:strip)
114
113
  end
115
114
 
116
115
  # Go through the given document, replacing any merge fields with the values provided
117
116
  # and storing the results in a new document
118
117
  def substitute document, document_name:, mapping: {}
119
118
  tag_nodes_for(document).each do |tag_node|
120
- field_name = field_name_from tag_node
121
- next unless mapping.has_key? field_name
122
- field_value = mapping[field_name]
123
- puts "...substituting #{field_name} with #{field_value} in #{document_name}" if verbose
124
- tag_node.content = tag_node.content.gsub(field_name, field_value).gsub(/{{\s*/, "").gsub(/\s*}}/, "")
119
+ field_names = field_names_from tag_node
120
+ puts "Original Node for #{field_names} is #{tag_node}" if verbose
121
+
122
+ # Extract the paragraph properties node if it exists
123
+ paragraph_properties = tag_node.search ".//w:pPr"
124
+ run_properties = tag_node.at_xpath ".//w:rPr"
125
+
126
+ text = tag_node.content
127
+ field_names.each do |field_name|
128
+ field_value = mapping[field_name].to_s
129
+ puts "...substituting #{field_name} with #{field_value} in #{document_name}" if verbose
130
+ text = text.gsub(/{{\s*#{field_name}\s*}}/, field_value)
131
+ end
132
+
133
+ # Create a new text node with the substituted text
134
+ text_node = Nokogiri::XML::Node.new("w:t", tag_node.document)
135
+ text_node.content = text
136
+
137
+ # Create a new run node to hold the substituted text and the paragraph properties
138
+ run_node = Nokogiri::XML::Node.new("w:r", tag_node.document)
139
+ run_node << run_properties if run_properties
140
+ run_node << text_node
141
+ tag_node.children = Nokogiri::XML::NodeSet.new(document, paragraph_properties.to_a + [run_node])
142
+
143
+ puts "TAG NODE FOR #{field_names} IS #{tag_node}" if verbose
125
144
  rescue => ex
126
145
  # Have to mangle the exception message otherwise it outputs the entire document
127
146
  puts ex.message.to_s[0..255]
128
147
  end
129
148
  document
130
149
  end
131
-
132
- # Find the ancestor node that contains both the start {{ text and the end }} text enclosing the merge field
133
- def enclosing_node_for_start_tag(node)
134
- return node if node.content.include? "}}"
135
- node.parent.nil? ? nil : enclosing_node_for_start_tag(node.parent)
136
- end
137
150
  end
138
151
  end
139
152
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Consolidate
4
- VERSION = "0.3.0"
4
+ VERSION = "0.3.1"
5
5
  end
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.3.0
4
+ version: 0.3.1
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-11-21 00:00:00.000000000 Z
11
+ date: 2024-11-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rubyzip
@@ -62,6 +62,7 @@ files:
62
62
  - checksums/standard-procedure-consolidate-0.1.4.gem.sha512
63
63
  - checksums/standard-procedure-consolidate-0.2.0.gem.sha512
64
64
  - checksums/standard-procedure-consolidate-0.3.0.gem.sha512
65
+ - checksums/standard-procedure-consolidate-0.3.1.gem.sha512
65
66
  - exe/consolidate
66
67
  - exe/examine
67
68
  - lib/consolidate.rb