standard-procedure-consolidate 0.2.0 → 0.3.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/.devcontainer/devcontainer.json +20 -4
- data/.ruby-version +1 -1
- data/.standard.yml +1 -1
- data/CHANGELOG.md +4 -0
- data/README.md +1 -1
- data/Rakefile +1 -1
- data/checksums/standard-procedure-consolidate-0.3.0.gem.sha512 +1 -0
- data/lib/consolidate/docx/merge.rb +70 -43
- data/lib/consolidate/version.rb +1 -1
- metadata +7 -7
- data/.nova/Configuration.json +0 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1bd2015cc0f88bc4b16bae7d8ecd335fb7b28c2bc940f81b1479e4a58ecce647
|
4
|
+
data.tar.gz: 44905254b9536f40f839d64d0448c4fb40b1a3720fb4d9ba3e2251468175eb9b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 36dee64a5f21766e06e7b5eb213e5a5b4dee9ca04da8bde4b429c4d93c5bd49275226975c7e9887214ea5a3b5975c4f955b245ab45e0103656b928ab59854789
|
7
|
+
data.tar.gz: 687bba668eb1f137b67c82819561ec2e8c2c3bc9a54f03aa4b6ac76958ae3a15988af8db5f78e7e95adb59968b5764b32c37e71d257b7885d1eb0e10d6e3f56a
|
@@ -1,7 +1,23 @@
|
|
1
1
|
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
|
2
2
|
// README at: https://github.com/devcontainers/templates/tree/main/src/ruby
|
3
3
|
{
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
4
|
+
"name": "Ruby",
|
5
|
+
"image": "mcr.microsoft.com/devcontainers/ruby:1-3.2-bullseye",
|
6
|
+
"postCreateCommand": "bundle install",
|
7
|
+
"customizations": {
|
8
|
+
"vscode": {
|
9
|
+
"extensions": [
|
10
|
+
"Shopify.ruby-extensions-pack",
|
11
|
+
"testdouble.vscode-standard-ruby",
|
12
|
+
"manuelpuyol.erb-linter",
|
13
|
+
"Shopify.ruby-lsp",
|
14
|
+
"aki77.rails-db-schema",
|
15
|
+
"miguel-savignano.ruby-symbols",
|
16
|
+
"sibiraj-s.vscode-scss-formatter",
|
17
|
+
"Thadeu.vscode-run-rspec-file",
|
18
|
+
"Cronos87.yaml-symbols",
|
19
|
+
"aliariff.vscode-erb-beautify"
|
20
|
+
]
|
21
|
+
}
|
22
|
+
}
|
23
|
+
}
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
3.2.
|
1
|
+
3.2.5
|
data/.standard.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
## [0.3.0] - 2024-11-21
|
2
|
+
|
3
|
+
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.
|
4
|
+
|
1
5
|
## [0.2.0] - 2023-09-13
|
2
6
|
|
3
7
|
Thrown away the mail-merge implementation and replaced it with a simple search/replace.
|
data/README.md
CHANGED
@@ -78,7 +78,7 @@ Consolidate looks for word/document.xml files, plus any files that match word/he
|
|
78
78
|
|
79
79
|
## Development
|
80
80
|
|
81
|
-
The repo contains a .devcontainer folder - this contains instructions for a development container that has everything needed to build the project. Once the container has started, you can use `bin/setup` to install dependencies. Then, run `rake
|
81
|
+
The repo contains a .devcontainer folder - this contains instructions for a development container that has everything needed to build the project. Once the container has started, you can use `bin/setup` to install dependencies. Then, run `bundle exec rake` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
82
82
|
|
83
83
|
`bundle exec rake install` will install the gem on your local machine (obviously not from within the devcontainer though). To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
84
84
|
|
data/Rakefile
CHANGED
@@ -0,0 +1 @@
|
|
1
|
+
098078b13e3bb4e3370cbc6bdb0195300489dfb33a5c27a201a4c5f1f0184bba73557264e674f49da41dbc62ad991e8ae99bef1debf417a5b1a363b1d56829f1
|
@@ -11,6 +11,15 @@ module Consolidate
|
|
11
11
|
path
|
12
12
|
end
|
13
13
|
|
14
|
+
def initialize(path, verbose: false, &block)
|
15
|
+
@verbose = verbose
|
16
|
+
@output = {}
|
17
|
+
@zip = Zip::File.open(path)
|
18
|
+
@documents = load_documents
|
19
|
+
block&.call self
|
20
|
+
end
|
21
|
+
|
22
|
+
# Helper method to display the contents of the document and the merge fields from the CLI
|
14
23
|
def examine
|
15
24
|
documents = document_names.join(", ")
|
16
25
|
fields = field_names.join(", ")
|
@@ -18,23 +27,21 @@ module Consolidate
|
|
18
27
|
puts "Merge fields: #{fields}"
|
19
28
|
end
|
20
29
|
|
30
|
+
# Read all documents within the docx and extract any merge fields
|
21
31
|
def field_names
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
field_name = matches[1].strip
|
26
|
-
puts "...field #{field_name} found in #{name}" if verbose
|
27
|
-
field_name
|
28
|
-
end.compact
|
29
|
-
end.flatten
|
32
|
+
tag_nodes.collect do |tag_node|
|
33
|
+
field_name_from tag_node
|
34
|
+
end.compact.uniq
|
30
35
|
end
|
31
36
|
|
37
|
+
# List the documents stored within this docx
|
32
38
|
def document_names
|
33
39
|
@zip.entries.collect { |entry| entry.name }
|
34
40
|
end
|
35
41
|
|
36
|
-
|
37
|
-
|
42
|
+
# Substitute the data from the merge fields with the values provided
|
43
|
+
def data mapping = {}
|
44
|
+
mapping = mapping.transform_keys(&:to_s)
|
38
45
|
|
39
46
|
if verbose
|
40
47
|
puts "...substitutions..."
|
@@ -44,13 +51,13 @@ module Consolidate
|
|
44
51
|
end
|
45
52
|
|
46
53
|
@documents.each do |name, document|
|
47
|
-
|
48
|
-
result = substitute result, fields, name
|
54
|
+
output_document = substitute document.dup, mapping: mapping, document_name: name
|
49
55
|
|
50
|
-
@output[name] =
|
56
|
+
@output[name] = output_document.serialize save_with: 0
|
51
57
|
end
|
52
58
|
end
|
53
59
|
|
60
|
+
# Write the new document to the given path
|
54
61
|
def write_to path
|
55
62
|
puts "...writing to #{path}" if verbose
|
56
63
|
Zip::File.open(path, Zip::File::CREATE) do |out|
|
@@ -62,7 +69,7 @@ module Consolidate
|
|
62
69
|
end
|
63
70
|
end
|
64
71
|
|
65
|
-
|
72
|
+
private
|
66
73
|
|
67
74
|
attr_reader :verbose
|
68
75
|
attr_reader :zip
|
@@ -70,42 +77,62 @@ module Consolidate
|
|
70
77
|
attr_reader :documents
|
71
78
|
attr_accessor :output
|
72
79
|
|
73
|
-
def
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
@zip = Zip::File.open(path)
|
80
|
-
@zip.entries.each do |entry|
|
81
|
-
next unless entry.name.match?(/word\/(document|header|footer|footnotes|endnotes).?\.xml/)
|
82
|
-
puts "...reading #{entry.name}" if verbose
|
83
|
-
xml = @zip.get_input_stream entry
|
84
|
-
@documents[entry.name] = Nokogiri::XML(xml) { |x| x.noent }
|
85
|
-
end
|
86
|
-
yield self
|
87
|
-
ensure
|
88
|
-
@zip.close
|
80
|
+
def load_documents
|
81
|
+
@zip.entries.each_with_object({}) do |entry, documents|
|
82
|
+
next unless entry.name.match?(/word\/(document|header|footer|footnotes|endnotes).?\.xml/)
|
83
|
+
puts "...reading #{entry.name}" if verbose
|
84
|
+
xml = @zip.get_input_stream entry
|
85
|
+
documents[entry.name] = Nokogiri::XML(xml) { |x| x.noent }
|
89
86
|
end
|
87
|
+
ensure
|
88
|
+
@zip.close
|
90
89
|
end
|
91
90
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
91
|
+
# Collect all the nodes that contain merge fields
|
92
|
+
def tag_nodes
|
93
|
+
documents.collect do |name, document|
|
94
|
+
tag_nodes_for document
|
95
|
+
end.flatten
|
96
|
+
end
|
97
|
+
|
98
|
+
# go through all w:t (Word Text???) nodes of the document
|
99
|
+
# find any nodes that contain "{{"
|
100
|
+
# then find the ancestor node that also includes the ending "}}"
|
101
|
+
# This collection of nodes contains all the merge fields for this document
|
102
|
+
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
|
106
|
+
end
|
107
|
+
|
108
|
+
# 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
|
114
|
+
end
|
115
|
+
|
116
|
+
# Go through the given document, replacing any merge fields with the values provided
|
117
|
+
# and storing the results in a new document
|
118
|
+
def substitute document, document_name:, mapping: {}
|
119
|
+
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*}}/, "")
|
125
|
+
rescue => ex
|
126
|
+
# Have to mangle the exception message otherwise it outputs the entire document
|
127
|
+
puts ex.message.to_s[0..255]
|
103
128
|
end
|
104
129
|
document
|
105
130
|
end
|
106
131
|
|
107
|
-
|
108
|
-
|
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)
|
109
136
|
end
|
110
137
|
end
|
111
138
|
end
|
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.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rahoul Baruah
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-11-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rubyzip
|
@@ -48,7 +48,6 @@ extensions: []
|
|
48
48
|
extra_rdoc_files: []
|
49
49
|
files:
|
50
50
|
- ".devcontainer/devcontainer.json"
|
51
|
-
- ".nova/Configuration.json"
|
52
51
|
- ".rspec"
|
53
52
|
- ".ruby-version"
|
54
53
|
- ".standard.yml"
|
@@ -62,6 +61,7 @@ files:
|
|
62
61
|
- checksums/standard-procedure-consolidate-0.1.3.gem.sha512
|
63
62
|
- checksums/standard-procedure-consolidate-0.1.4.gem.sha512
|
64
63
|
- checksums/standard-procedure-consolidate-0.2.0.gem.sha512
|
64
|
+
- checksums/standard-procedure-consolidate-0.3.0.gem.sha512
|
65
65
|
- exe/consolidate
|
66
66
|
- exe/examine
|
67
67
|
- lib/consolidate.rb
|
@@ -77,7 +77,7 @@ metadata:
|
|
77
77
|
homepage_uri: https://github.com/standard-procedure/standard-procedure-consolidate
|
78
78
|
source_code_uri: https://github.com/standard-procedure/standard-procedure-consolidate
|
79
79
|
changelog_uri: https://github.com/standard-procedure/standard-procedure-consolidate/blob/main/CHANGELOG.md
|
80
|
-
post_install_message:
|
80
|
+
post_install_message:
|
81
81
|
rdoc_options: []
|
82
82
|
require_paths:
|
83
83
|
- lib
|
@@ -92,8 +92,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
92
92
|
- !ruby/object:Gem::Version
|
93
93
|
version: '0'
|
94
94
|
requirements: []
|
95
|
-
rubygems_version: 3.4.
|
96
|
-
signing_key:
|
95
|
+
rubygems_version: 3.4.19
|
96
|
+
signing_key:
|
97
97
|
specification_version: 4
|
98
98
|
summary: Simple ruby mailmerge for Microsoft Word .docx files.
|
99
99
|
test_files: []
|
data/.nova/Configuration.json
DELETED