docx_templater 0.0.7
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.
- data/lib/docx_templater.rb +114 -0
- metadata +79 -0
@@ -0,0 +1,114 @@
|
|
1
|
+
require 'zip/zipfilesystem'
|
2
|
+
require 'htmlentities'
|
3
|
+
|
4
|
+
# Use .docx as reusable templates
|
5
|
+
#
|
6
|
+
# Example:
|
7
|
+
# buffer = DocxTemplater.replace_file_with_content('path/to/mydocument.docx',
|
8
|
+
# {
|
9
|
+
# :client_email1 => 'test@example.com',
|
10
|
+
# :client_phone1 => '555-555-5555',
|
11
|
+
# })
|
12
|
+
# # In Rails you can send a word document via send_data
|
13
|
+
# send_data buffer.string, :filename => 'REPC.docx'
|
14
|
+
# # Or save the output to a word file
|
15
|
+
# File.open("path/to/mydocument.docx", "wb") {|f| f.write(buffer.string) }
|
16
|
+
class DocxTemplater
|
17
|
+
def initialize(opts = {})
|
18
|
+
@options = opts
|
19
|
+
end
|
20
|
+
|
21
|
+
def replace_file_with_content(file_path, data_provider)
|
22
|
+
# Rubyzip doesn't save it right unless saved like this: https://gist.github.com/e7d2855435654e1ebc52
|
23
|
+
zf = Zip::ZipFile.new(file_path) # Put original file name here
|
24
|
+
|
25
|
+
buffer = Zip::ZipOutputStream.write_buffer do |out|
|
26
|
+
zf.entries.each do |e|
|
27
|
+
process_entry(e, out, data_provider)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
# You can save this buffer or send it with rails via send_data
|
31
|
+
return buffer
|
32
|
+
end
|
33
|
+
|
34
|
+
def generate_tags_for(*args)
|
35
|
+
attributes = {}
|
36
|
+
args.flatten!
|
37
|
+
# Prefixes the model name or custom prefix. Makes it so we don't having naming clashes when used with records from multiple m
|
38
|
+
args.each do |arg|
|
39
|
+
if arg.is_a?(Hash) && arg.has_key?(:data) && arg.has_key?(:prefix)
|
40
|
+
template_attributes = (arg[:data].respond_to?(:template_attributes) && :template_attributes) || :attributes
|
41
|
+
arg[:data].send(template_attributes).each_key do |key|
|
42
|
+
attributes["#{arg[:prefix]}_#{key.to_s}".to_sym] = arg[:data].send(template_attributes)[key]
|
43
|
+
end
|
44
|
+
elsif arg.is_a?(Hash)
|
45
|
+
attributes.merge!(arg)
|
46
|
+
else
|
47
|
+
template_attributes = (arg.respond_to?(:template_attributes) && :template_attributes) || :attributes
|
48
|
+
arg.send(template_attributes).each_key do |key|
|
49
|
+
attributes["#{arg.class.name.underscore}_#{key.to_s}".to_sym] = arg.send(template_attributes)[key]
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
attributes
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
def all_tags_regex
|
58
|
+
/\|\|\<*.+?\>*\|\|/
|
59
|
+
end
|
60
|
+
|
61
|
+
def malformed_tag_regex
|
62
|
+
/(?<=>)\w{3,}(?=<)/
|
63
|
+
end
|
64
|
+
|
65
|
+
def well_formed_tag_regex
|
66
|
+
/(?<=\|\|)\w{3,}(?=\|\|)/
|
67
|
+
end
|
68
|
+
|
69
|
+
def just_label_regex
|
70
|
+
/(?<=>)(\w{3,})/
|
71
|
+
end
|
72
|
+
|
73
|
+
def entry_requires_replacement?(entry)
|
74
|
+
entry.ftype != :directory && entry.name =~ /document|header|footer/
|
75
|
+
end
|
76
|
+
|
77
|
+
def get_entry_content(entry, data_provider)
|
78
|
+
if entry_requires_replacement?(entry)
|
79
|
+
replace_entry_content(entry.get_input_stream.read, data_provider)
|
80
|
+
else
|
81
|
+
entry.get_input_stream.read
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def process_entry(entry, output, data_provider)
|
86
|
+
output.put_next_entry(entry.name)
|
87
|
+
output.write get_entry_content(entry, data_provider) if entry.ftype != :directory
|
88
|
+
end
|
89
|
+
|
90
|
+
def replace_entry_content(str, data_provider)
|
91
|
+
possible_tags = str.scan(all_tags_regex)
|
92
|
+
# Loops through what looks like are tags. Anything with ||name|| even if they are not in the available tags list
|
93
|
+
possible_tags.each do |tag|
|
94
|
+
#extracts just the tag name
|
95
|
+
tag_name = malformed_tag_regex.match(tag)
|
96
|
+
tag_name ||= well_formed_tag_regex.match(tag)
|
97
|
+
tag_name ||= ''
|
98
|
+
# This will handle instances where someone edits just part of a tag and Word wraps that part in more XML
|
99
|
+
words = tag.scan(just_label_regex).flatten!
|
100
|
+
if words.respond_to?(:size) && words.size > 1
|
101
|
+
#Then the tag was split by word
|
102
|
+
tag_name = words.join('')
|
103
|
+
end
|
104
|
+
tag_name = tag_name.to_s.to_sym
|
105
|
+
# if in the available tag list, replace with the new value
|
106
|
+
if data_provider.has_key?(tag_name)
|
107
|
+
encoder = HTMLEntities.new
|
108
|
+
content = encoder.encode("#{data_provider[tag_name]}")
|
109
|
+
str.gsub!(tag, content)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
str
|
113
|
+
end
|
114
|
+
end
|
metadata
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: docx_templater
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.7
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Paul Smith
|
9
|
+
- Michael Ries
|
10
|
+
autorequire:
|
11
|
+
bindir: bin
|
12
|
+
cert_chain: []
|
13
|
+
date: 2012-08-03 00:00:00.000000000 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: rubyzip
|
17
|
+
requirement: !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - ~>
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 0.9.9
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
none: false
|
27
|
+
requirements:
|
28
|
+
- - ~>
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
version: 0.9.9
|
31
|
+
- !ruby/object:Gem::Dependency
|
32
|
+
name: htmlentities
|
33
|
+
requirement: !ruby/object:Gem::Requirement
|
34
|
+
none: false
|
35
|
+
requirements:
|
36
|
+
- - ~>
|
37
|
+
- !ruby/object:Gem::Version
|
38
|
+
version: 4.3.1
|
39
|
+
type: :runtime
|
40
|
+
prerelease: false
|
41
|
+
version_requirements: !ruby/object:Gem::Requirement
|
42
|
+
none: false
|
43
|
+
requirements:
|
44
|
+
- - ~>
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: 4.3.1
|
47
|
+
description: Uses a .docx file with keyword tags within '||' as a template. This gem
|
48
|
+
will then open the .docx and replace those tags with dynamically defined content.
|
49
|
+
email: pauls@basecampops.com
|
50
|
+
executables: []
|
51
|
+
extensions: []
|
52
|
+
extra_rdoc_files: []
|
53
|
+
files:
|
54
|
+
- lib/docx_templater.rb
|
55
|
+
homepage: http://rubygems.org/gems/docx_templater
|
56
|
+
licenses: []
|
57
|
+
post_install_message:
|
58
|
+
rdoc_options: []
|
59
|
+
require_paths:
|
60
|
+
- lib
|
61
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
62
|
+
none: false
|
63
|
+
requirements:
|
64
|
+
- - ! '>='
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '0'
|
67
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
68
|
+
none: false
|
69
|
+
requirements:
|
70
|
+
- - ! '>='
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: '0'
|
73
|
+
requirements: []
|
74
|
+
rubyforge_project:
|
75
|
+
rubygems_version: 1.8.24
|
76
|
+
signing_key:
|
77
|
+
specification_version: 3
|
78
|
+
summary: Uses a .docx as a template and replaces 'tags' within || with other content
|
79
|
+
test_files: []
|