lm_docstache 2.0.2 → 2.1.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 +10 -0
- data/lib/lm_docstache.rb +1 -0
- data/lib/lm_docstache/document.rb +2 -2
- data/lib/lm_docstache/hide_custom_tags.rb +74 -0
- data/lib/lm_docstache/parser.rb +21 -1
- data/lib/lm_docstache/renderer.rb +1 -1
- data/lib/lm_docstache/version.rb +1 -1
- data/spec/conditional_block_spec.rb +1 -3
- data/spec/example_input/sample-signature.docx +0 -0
- data/spec/hide_custom_tags_spec.rb +36 -0
- data/spec/integration_spec.rb +37 -9
- metadata +7 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 65f3c502d4e4982f2361991d6b43b4d22460ab4e25d9db7fd60eb6b9f14d4a1f
|
4
|
+
data.tar.gz: 779810f481adebb853e62ea708df571ab355fb96cc9fde3c83d86ff7ad214714
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 44994ae953e0a0b42acfc1ef0a6ac8722c17be1582c227ecdac3c6cd572ae91031e85e71671628bc3eacc0981904968c15f079824b42b4f95bddefd2b417939e
|
7
|
+
data.tar.gz: f94f9e419671854f22031c232a7df41f8c52e1e95cb1db57e94aa5ab1f1229e387aee42a407fcadef7b09a78a114d1d2e6d642a8db0c68c1ff977b0757db9d04
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,15 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 2.1.0
|
4
|
+
|
5
|
+
#### Improvements
|
6
|
+
|
7
|
+
* Add new feature which you're able to "hide" matching RegExp rule with white font color.
|
8
|
+
This change allows you to keep your content and don't loose locations of hidden tags.
|
9
|
+
You can use it just adding `hide_custom_tags` list of RegExp options to `Document#render_file`.
|
10
|
+
* Added `Document#render_xml` options parameter so you can call it with more documents
|
11
|
+
formatting possibilities.
|
12
|
+
|
3
13
|
## 2.0.2
|
4
14
|
|
5
15
|
### Improvements and bugfixes
|
data/lib/lm_docstache.rb
CHANGED
@@ -0,0 +1,74 @@
|
|
1
|
+
module LMDocstache
|
2
|
+
class HideCustomTags
|
3
|
+
HIDDEN_FONT_COLOR = 'FFFFFF'
|
4
|
+
|
5
|
+
attr_reader :document, :hide_custom_tags
|
6
|
+
|
7
|
+
# The +hide_custom_tags+ options is an +Array+ of +Regexp+ or +String+ representing
|
8
|
+
# the pattern you expect to keep at the document but with white font color.
|
9
|
+
#
|
10
|
+
# You have to remember is not acceptable to have capture groups in your +Regexp's+.
|
11
|
+
# We don't accept because we need to find all parts of your text, split it in multiple runs
|
12
|
+
# and add a white font color to matching custom tags.
|
13
|
+
def initialize(document:, hide_custom_tags: [])
|
14
|
+
@document = document
|
15
|
+
@hide_custom_tags = hide_custom_tags
|
16
|
+
end
|
17
|
+
|
18
|
+
# Find all run nodes matching hide custom tags +Regexp's+ options you defined, split it
|
19
|
+
# in multiple runs and replace font color to white in the matching tag run node.
|
20
|
+
def hide_custom_tags!
|
21
|
+
hide_custom_tags.each do |full_pattern|
|
22
|
+
paragraphs = document.css('w|p')
|
23
|
+
while paragraph = paragraphs.shift do
|
24
|
+
next unless paragraph.text =~ full_pattern
|
25
|
+
run_nodes = paragraph.css('w|r')
|
26
|
+
while run_node = run_nodes.shift
|
27
|
+
next if run_node.text.to_s.strip.size == 0
|
28
|
+
remainder_run_node = run_node.clone
|
29
|
+
run_node.unlink
|
30
|
+
tag_contents = split_tag_content(remainder_run_node.text, full_pattern)
|
31
|
+
tag_contents[:content_list].each_with_index do |content, idx|
|
32
|
+
replace_content(remainder_run_node, content)
|
33
|
+
run_node_with_match = remainder_run_node.dup
|
34
|
+
matched_tag = tag_contents[:matched_tags][idx]
|
35
|
+
nodes_list = [remainder_run_node]
|
36
|
+
if matched_tag
|
37
|
+
replace_style(run_node_with_match)
|
38
|
+
replace_content(run_node_with_match, matched_tag)
|
39
|
+
nodes_list << run_node_with_match
|
40
|
+
end
|
41
|
+
paragraph << Nokogiri::XML::NodeSet.new(document, nodes_list)
|
42
|
+
remainder_run_node = remainder_run_node.clone
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
def split_tag_content(text, full_pattern)
|
51
|
+
content_list = text.split(full_pattern)
|
52
|
+
content_list = content_list.empty? ? [''] : content_list
|
53
|
+
matched_tags = text.scan(full_pattern)
|
54
|
+
{ content_list: content_list, matched_tags: matched_tags}
|
55
|
+
end
|
56
|
+
|
57
|
+
def replace_style(run_node)
|
58
|
+
style = run_node.at_css('w|rPr')
|
59
|
+
if style
|
60
|
+
w_color = style.at_css('w|color')
|
61
|
+
w_color.unlink if w_color
|
62
|
+
style << "<w:color w:val=\"#{HIDDEN_FONT_COLOR}\"/>"
|
63
|
+
else
|
64
|
+
run_node << "<w:rPr><w:color w:val=\"#{HIDDEN_FONT_COLOR}\"/></w:rPr>"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def replace_content(run_node, content)
|
69
|
+
run_text = run_node.at_css('w|t')
|
70
|
+
run_text['xml:space'] = 'preserve'
|
71
|
+
run_text.content = content
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
data/lib/lm_docstache/parser.rb
CHANGED
@@ -17,7 +17,7 @@ module LMDocstache
|
|
17
17
|
BLOCK_MATCHER = /#{BLOCK_PATTERN}/
|
18
18
|
VARIABLE_MATCHER = /{{([^#\^\/].*?)}}/
|
19
19
|
|
20
|
-
attr_reader :document, :data, :blocks, :special_variable_replacements
|
20
|
+
attr_reader :document, :data, :blocks, :special_variable_replacements, :hide_custom_tags
|
21
21
|
|
22
22
|
# The +special_variable_replacements+ option is a +Hash+ where the key is
|
23
23
|
# expected to be either a +Regexp+ or a +String+ representing the pattern
|
@@ -34,13 +34,27 @@ module LMDocstache
|
|
34
34
|
# * any other value that will be turned into a string -> in this case, this
|
35
35
|
# will be the value that will replace the matched string
|
36
36
|
#
|
37
|
+
# The +hide_custom_tags+ options is an +Array+ of +Regexp+ or +String+ representing
|
38
|
+
# the pattern you expect to keep at the document but with white font color.
|
39
|
+
#
|
40
|
+
# You have to remember is not acceptable to have capture groups in your +Regexp's+.
|
41
|
+
# We don't accept because we need to find all parts of your text, split it in multiple runs
|
42
|
+
# and add a white font color to matching custom tags.
|
37
43
|
def initialize(document, data, options = {})
|
38
44
|
@document = document
|
39
45
|
@data = data.transform_keys(&:to_s)
|
40
46
|
@special_variable_replacements = options.fetch(:special_variable_replacements, {})
|
47
|
+
@hide_custom_tags = load_hide_custom_tags(options)
|
48
|
+
end
|
49
|
+
|
50
|
+
def load_hide_custom_tags(options)
|
51
|
+
options.fetch(:hide_custom_tags, []).map do |regexp_str|
|
52
|
+
regexp_str.is_a?(String) ? Regexp.new("{{#{regexp_str}}}") : /{{#{regexp_str.source}}/
|
53
|
+
end
|
41
54
|
end
|
42
55
|
|
43
56
|
def parse_and_update_document!
|
57
|
+
hide_custom_tags!
|
44
58
|
find_blocks
|
45
59
|
replace_conditional_blocks_in_document!
|
46
60
|
replace_variables_in_document!
|
@@ -81,6 +95,11 @@ module LMDocstache
|
|
81
95
|
@blocks
|
82
96
|
end
|
83
97
|
|
98
|
+
def hide_custom_tags!
|
99
|
+
custom_tags = HideCustomTags.new(document: document, hide_custom_tags: hide_custom_tags)
|
100
|
+
custom_tags.hide_custom_tags!
|
101
|
+
end
|
102
|
+
|
84
103
|
# Evaluates all conditional blocks inside the given XML document and keep or
|
85
104
|
# remove their content inside the document, depending on the truthiness of
|
86
105
|
# the condition on each given conditional block.
|
@@ -115,6 +134,7 @@ module LMDocstache
|
|
115
134
|
end
|
116
135
|
|
117
136
|
def has_skippable_variable?(text)
|
137
|
+
return true if hide_custom_tags.find { |pattern| text =~ pattern }
|
118
138
|
!!special_variable_replacements.find do |(pattern, value)|
|
119
139
|
pattern = pattern.is_a?(String) ? /{{#{pattern}}}/ : /{{#{pattern.source}}}/
|
120
140
|
text =~ pattern && value == false
|
@@ -6,7 +6,7 @@ module LMDocstache
|
|
6
6
|
|
7
7
|
def initialize(xml, data, options = {})
|
8
8
|
@content = xml
|
9
|
-
@parser = Parser.new(xml, data, options.slice(:special_variable_replacements))
|
9
|
+
@parser = Parser.new(xml, data, options.slice(:special_variable_replacements, :hide_custom_tags))
|
10
10
|
end
|
11
11
|
|
12
12
|
def render
|
data/lib/lm_docstache/version.rb
CHANGED
@@ -24,9 +24,7 @@ describe LMDocstache::Renderer do
|
|
24
24
|
def render_docx(doc_text)
|
25
25
|
# create doc from blank
|
26
26
|
blank_doc.render_replace(temp_file, doc_text)
|
27
|
-
|
28
|
-
doc = LMDocstache::Document.new(temp_file).render_file(result_file, data)
|
29
|
-
|
27
|
+
LMDocstache::Document.new(temp_file).render_file(result_file, data)
|
30
28
|
result_doc = LMDocstache::Document.new(result_file).render_xml(data)
|
31
29
|
result_doc["word/document.xml"].text
|
32
30
|
end
|
Binary file
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe LMDocstache::HideCustomTags do
|
4
|
+
|
5
|
+
context '#example' do
|
6
|
+
let(:output_dir) { "#{base_path}/tmp/" }
|
7
|
+
let(:output_file) { File.new("#{output_dir}/BlankTestOutput.docx", 'w') }
|
8
|
+
before do
|
9
|
+
FileUtils.rm_rf(output_dir) if File.exist?(output_dir)
|
10
|
+
Dir.mkdir(output_dir)
|
11
|
+
end
|
12
|
+
|
13
|
+
after do
|
14
|
+
File.delete(output_file.path)
|
15
|
+
end
|
16
|
+
|
17
|
+
let(:base_path) { SPEC_BASE_PATH.join('example_input') }
|
18
|
+
let(:input_file) { "#{base_path}/sample-signature.docx" }
|
19
|
+
|
20
|
+
let(:document) { LMDocstache::Document.new(input_file).instance_variable_get(:@document) }
|
21
|
+
let(:regexp_tag) { /{{(?:sig|sigfirm|date|check|text|initial)\|(?:req|noreq)\|.+?}}/ }
|
22
|
+
let(:hide_custom_tags) {
|
23
|
+
LMDocstache::HideCustomTags.new(document: document, hide_custom_tags: [ regexp_tag ])
|
24
|
+
}
|
25
|
+
it 'expect to have a white background on all hide custom tags matching' do
|
26
|
+
hide_custom_tags.hide_custom_tags!
|
27
|
+
d = hide_custom_tags.document
|
28
|
+
run_nodes = d.css('w|p w|r')
|
29
|
+
while run_node = run_nodes.shift
|
30
|
+
if run_node.text =~ regexp_tag
|
31
|
+
expect(run_node.at_css('w|rPr w|color').first[1]).to eq(LMDocstache::HideCustomTags::HIDDEN_FONT_COLOR)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/spec/integration_spec.rb
CHANGED
@@ -33,18 +33,17 @@ module LMDocstache
|
|
33
33
|
end
|
34
34
|
|
35
35
|
describe 'integration test', integration: true do
|
36
|
-
let(:data) { LMDocstache::TestData::DATA }
|
37
36
|
let(:base_path) { SPEC_BASE_PATH.join('example_input') }
|
38
|
-
let(:input_file) { "#{base_path}/ExampleTemplate.docx" }
|
39
37
|
let(:output_dir) { "#{base_path}/tmp" }
|
40
|
-
let(:output_file) { "#{output_dir}/IntegrationTestOutput.docx" }
|
41
|
-
let(:document) { LMDocstache::Document.new(input_file) }
|
42
|
-
before do
|
43
|
-
FileUtils.rm_rf(output_dir) if File.exist?(output_dir)
|
44
|
-
Dir.mkdir(output_dir)
|
45
|
-
end
|
46
|
-
|
47
38
|
context 'should process that incoming docx' do
|
39
|
+
let(:data) { LMDocstache::TestData::DATA }
|
40
|
+
let(:input_file) { "#{base_path}/ExampleTemplate.docx" }
|
41
|
+
let(:output_file) { "#{output_dir}/IntegrationTestOutput.docx" }
|
42
|
+
let(:document) { LMDocstache::Document.new(input_file) }
|
43
|
+
before do
|
44
|
+
FileUtils.rm_rf(output_dir) if File.exist?(output_dir)
|
45
|
+
Dir.mkdir(output_dir)
|
46
|
+
end
|
48
47
|
it 'loads the input file' do
|
49
48
|
expect(document).to_not be_nil
|
50
49
|
end
|
@@ -84,4 +83,33 @@ describe 'integration test', integration: true do
|
|
84
83
|
document.render_file(output_file, data)
|
85
84
|
end
|
86
85
|
end
|
86
|
+
context "testing hide custom tags" do
|
87
|
+
before do
|
88
|
+
FileUtils.rm_rf(output_dir) if File.exist?(output_dir)
|
89
|
+
Dir.mkdir(output_dir)
|
90
|
+
end
|
91
|
+
|
92
|
+
let(:input_file) { "#{base_path}/sample-signature.docx" }
|
93
|
+
let(:render_options) {
|
94
|
+
{
|
95
|
+
hide_custom_tags: ['(?:sig|sigfirm|date|check|text|initial)\|(?:req|noreq)\\|.+?']
|
96
|
+
}
|
97
|
+
}
|
98
|
+
let(:document) { LMDocstache::Document.new(input_file) }
|
99
|
+
it 'should have content replacement aligned with hide custom tags' do
|
100
|
+
doc = document
|
101
|
+
doc.fix_errors
|
102
|
+
noko = doc.render_xml({}, render_options)
|
103
|
+
output = noko['word/document.xml'].to_xml
|
104
|
+
expect(output).to include('<w:r>
|
105
|
+
<w:rPr>
|
106
|
+
<w:rFonts w:cstheme="minorHAnsi"/>
|
107
|
+
<w:lang w:val="en-US"/>
|
108
|
+
<w:color w:val="FFFFFF"/>
|
109
|
+
</w:rPr>
|
110
|
+
<w:t xml:space="preserve">{{sig|req|client}}</w:t>
|
111
|
+
</w:r>')
|
112
|
+
expect(output).to include('<w:t xml:space="preserve">Test Multiple text in the same line </w:t>')
|
113
|
+
end
|
114
|
+
end
|
87
115
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lm_docstache
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0
|
4
|
+
version: 2.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Roey Chasman
|
@@ -12,7 +12,7 @@ authors:
|
|
12
12
|
autorequire:
|
13
13
|
bindir: bin
|
14
14
|
cert_chain: []
|
15
|
-
date: 2021-03-
|
15
|
+
date: 2021-03-17 00:00:00.000000000 Z
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
18
18
|
name: nokogiri
|
@@ -113,6 +113,7 @@ files:
|
|
113
113
|
- lib/lm_docstache/condition.rb
|
114
114
|
- lib/lm_docstache/conditional_block.rb
|
115
115
|
- lib/lm_docstache/document.rb
|
116
|
+
- lib/lm_docstache/hide_custom_tags.rb
|
116
117
|
- lib/lm_docstache/parser.rb
|
117
118
|
- lib/lm_docstache/renderer.rb
|
118
119
|
- lib/lm_docstache/version.rb
|
@@ -120,6 +121,8 @@ files:
|
|
120
121
|
- spec/conditional_block_spec.rb
|
121
122
|
- spec/example_input/ExampleTemplate.docx
|
122
123
|
- spec/example_input/blank.docx
|
124
|
+
- spec/example_input/sample-signature.docx
|
125
|
+
- spec/hide_custom_tags_spec.rb
|
123
126
|
- spec/integration_spec.rb
|
124
127
|
- spec/spec_helper.rb
|
125
128
|
- spec/template_processor_spec.rb
|
@@ -150,6 +153,8 @@ test_files:
|
|
150
153
|
- spec/conditional_block_spec.rb
|
151
154
|
- spec/example_input/ExampleTemplate.docx
|
152
155
|
- spec/example_input/blank.docx
|
156
|
+
- spec/example_input/sample-signature.docx
|
157
|
+
- spec/hide_custom_tags_spec.rb
|
153
158
|
- spec/integration_spec.rb
|
154
159
|
- spec/spec_helper.rb
|
155
160
|
- spec/template_processor_spec.rb
|