lm_docstache 2.1.0 → 3.0.2

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: 65f3c502d4e4982f2361991d6b43b4d22460ab4e25d9db7fd60eb6b9f14d4a1f
4
- data.tar.gz: 779810f481adebb853e62ea708df571ab355fb96cc9fde3c83d86ff7ad214714
3
+ metadata.gz: e8db9e1f7f1a534059ed080bfd89005372b334cc203b66cfbb45323b8116b980
4
+ data.tar.gz: 4af011e633d34a62fcc0ed24fa639e04ce88937423b8570ae4f3a8fd4ff8fe70
5
5
  SHA512:
6
- metadata.gz: 44994ae953e0a0b42acfc1ef0a6ac8722c17be1582c227ecdac3c6cd572ae91031e85e71671628bc3eacc0981904968c15f079824b42b4f95bddefd2b417939e
7
- data.tar.gz: f94f9e419671854f22031c232a7df41f8c52e1e95cb1db57e94aa5ab1f1229e387aee42a407fcadef7b09a78a114d1d2e6d642a8db0c68c1ff977b0757db9d04
6
+ metadata.gz: e3c0630c4472b5d5b8f2a479a7b201411a817069221026778f86581146f4ef797dd586d2a0b299df4281394edf7878f1536ceda0d59f766a737255960a07d450
7
+ data.tar.gz: df59e4c7c9750e75f976d47ee6d8d632c795702863cdb332627497f88026efa70a2eac2b01520c615a8faf042f677e547d3fec8ae09dc470d50383e1e5ed5548
data/CHANGELOG.md CHANGED
@@ -1,5 +1,40 @@
1
1
  # Changelog
2
2
 
3
+ ## 3.0.2
4
+
5
+ ### Bugfix
6
+
7
+ * Fix replacing tags related to hidden custom tags regexp formats. E.g. tab characters.
8
+
9
+
10
+ ## 3.0.1
11
+
12
+ ### Bugfix
13
+
14
+ * Fix Hide Custom Tag feature when document there is no text inside a w|r we
15
+ can't split content.
16
+
17
+ ## 3.0.0
18
+
19
+ ## Breaking Changes
20
+ * Replaced Renderer `hide_custom_tags` options to be a `Hash` instead of `Array`.
21
+ There are are edge cases which we want to replace the content on hide custom tags.
22
+ All documentations can be followed on `Renderer` and `HideCustomTag` classes.
23
+
24
+ ## 2.1.2
25
+
26
+ ### Bugfix
27
+
28
+ * Giving a document there is no *rPr* tag we should add new *rPr* tag before
29
+ *t* tag.
30
+
31
+ ## 2.1.1
32
+
33
+ ### Improvements
34
+
35
+ * Hidden custom tags now follow your document background color. If there is no background defined
36
+ we assume white font color.
37
+
3
38
  ## 2.1.0
4
39
 
5
40
  #### Improvements
@@ -1,41 +1,52 @@
1
1
  module LMDocstache
2
2
  class HideCustomTags
3
- HIDDEN_FONT_COLOR = 'FFFFFF'
4
-
5
3
  attr_reader :document, :hide_custom_tags
6
4
 
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.
5
+ # The +hide_custom_tags+ options is a +Hash+ of +Regexp+ or +String+ keys representing
6
+ # the pattern you expect to keep at the document but replacing the content to use
7
+ # font color equal to document background color or white.
8
+ # For the +Hash+ values we can have:
9
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: [])
10
+ # * +false+ -> In this case we don't change the text content.
11
+ # * +Proc+ -> When a +Proc+ instance is provided, it's expected it to be
12
+ # able to receive the matched string and to return the string that will be
13
+ # used as replacement.
14
+ # * any other value that will be turned into a string -> in this case, this
15
+ # will be the value that will replace the matched string
16
+ def initialize(document:, hide_custom_tags: {})
14
17
  @document = document
15
18
  @hide_custom_tags = hide_custom_tags
16
19
  end
17
20
 
18
21
  # 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.
22
+ # in multiple runs and replace font color to document background color or white in the matching tag run node.
23
+ # Replace content if you have defined any replacement value.
20
24
  def hide_custom_tags!
21
- hide_custom_tags.each do |full_pattern|
25
+ hide_custom_tags.each do |full_pattern, value|
22
26
  paragraphs = document.css('w|p')
23
27
  while paragraph = paragraphs.shift do
24
28
  next unless paragraph.text =~ full_pattern
25
29
  run_nodes = paragraph.css('w|r')
26
30
  while run_node = run_nodes.shift
27
- next if run_node.text.to_s.strip.size == 0
31
+ next unless run_node.at_css('w|t')
32
+ next unless run_node.text =~ full_pattern
28
33
  remainder_run_node = run_node.clone
29
34
  run_node.unlink
30
35
  tag_contents = split_tag_content(remainder_run_node.text, full_pattern)
31
36
  tag_contents[:content_list].each_with_index do |content, idx|
32
37
  replace_content(remainder_run_node, content)
33
- run_node_with_match = remainder_run_node.dup
34
38
  matched_tag = tag_contents[:matched_tags][idx]
35
39
  nodes_list = [remainder_run_node]
36
40
  if matched_tag
41
+ run_node_with_match = remainder_run_node.dup
37
42
  replace_style(run_node_with_match)
38
- replace_content(run_node_with_match, matched_tag)
43
+ matched_content = matched_tag
44
+ if value
45
+ matched_content = value.is_a?(Proc) ?
46
+ value.call(matched_tag) :
47
+ value.to_s
48
+ end
49
+ replace_content(run_node_with_match, matched_content)
39
50
  nodes_list << run_node_with_match
40
51
  end
41
52
  paragraph << Nokogiri::XML::NodeSet.new(document, nodes_list)
@@ -47,6 +58,11 @@ module LMDocstache
47
58
  end
48
59
 
49
60
  private
61
+
62
+ def font_color
63
+ @font_color ||= document.at_css('w|background')&.attr('w:color') || 'FFFFFF'
64
+ end
65
+
50
66
  def split_tag_content(text, full_pattern)
51
67
  content_list = text.split(full_pattern)
52
68
  content_list = content_list.empty? ? [''] : content_list
@@ -59,9 +75,9 @@ module LMDocstache
59
75
  if style
60
76
  w_color = style.at_css('w|color')
61
77
  w_color.unlink if w_color
62
- style << "<w:color w:val=\"#{HIDDEN_FONT_COLOR}\"/>"
78
+ style << "<w:color w:val=\"#{font_color}\"/>"
63
79
  else
64
- run_node << "<w:rPr><w:color w:val=\"#{HIDDEN_FONT_COLOR}\"/></w:rPr>"
80
+ run_node.prepend_child("<w:rPr><w:color w:val=\"#{font_color}\"/></w:rPr>")
65
81
  end
66
82
  end
67
83
 
@@ -34,22 +34,30 @@ 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.
37
+ # The +hide_custom_tags+ options is a +Hash+ of +Regexp+ or +String+ keys representing
38
+ # the pattern you expect to keep at the document but replacing the content to use
39
+ # font color equal to document background color or white.
40
+ # For the +Hash+ values we can have:
39
41
  #
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.
42
+ # * +false+ -> In this case we don't change the text content.
43
+ # * +Proc+ -> When a +Proc+ instance is provided, it's expected it to be
44
+ # able to receive the matched string and to return the string that will be
45
+ # used as replacement.
46
+ # * any other value that will be turned into a string -> in this case, this
47
+ # will be the value that will replace the matched string
43
48
  def initialize(document, data, options = {})
44
49
  @document = document
45
50
  @data = data.transform_keys(&:to_s)
46
- @special_variable_replacements = options.fetch(:special_variable_replacements, {})
47
- @hide_custom_tags = load_hide_custom_tags(options)
51
+ @special_variable_replacements = add_blocks_to_regexp(options.fetch(:special_variable_replacements, {}))
52
+ @hide_custom_tags = add_blocks_to_regexp(options.fetch(:hide_custom_tags, {}))
48
53
  end
49
54
 
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}}/
55
+ # Replace +Regepx+ or +String+ keys to have the enclosing blocks
56
+ def add_blocks_to_regexp(options)
57
+ options.inject({}) do |x, (regexp_str, value)|
58
+ key = regexp_str.is_a?(String) ? Regexp.new("{{#{regexp_str}}}") : /{{#{regexp_str.source}}/
59
+ x[key] = value
60
+ x
53
61
  end
54
62
  end
55
63
 
@@ -128,15 +136,13 @@ module LMDocstache
128
136
  variable_replacement.call($1) :
129
137
  variable_replacement.to_s
130
138
  end
131
-
132
139
  text_node.content = text
133
140
  end
134
141
  end
135
142
 
136
143
  def has_skippable_variable?(text)
137
- return true if hide_custom_tags.find { |pattern| text =~ pattern }
144
+ return true if hide_custom_tags.find { |(pattern, value)| text =~ pattern }
138
145
  !!special_variable_replacements.find do |(pattern, value)|
139
- pattern = pattern.is_a?(String) ? /{{#{pattern}}}/ : /{{#{pattern.source}}}/
140
146
  text =~ pattern && value == false
141
147
  end
142
148
  end
@@ -144,7 +150,6 @@ module LMDocstache
144
150
  def special_variable_replacement(text)
145
151
  Array(
146
152
  special_variable_replacements.find do |(pattern, value)|
147
- pattern = pattern.is_a?(String) ? /{{#{pattern}}}/ : /{{#{pattern.source}}}/
148
153
  text =~ pattern && !!value
149
154
  end
150
155
  ).last
@@ -6,7 +6,8 @@ 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, :hide_custom_tags))
9
+ option_types = [:special_variable_replacements, :hide_custom_tags]
10
+ @parser = Parser.new(xml, data, options.slice(*option_types))
10
11
  end
11
12
 
12
13
  def render
@@ -1,3 +1,3 @@
1
1
  module LMDocstache
2
- VERSION = "2.1.0"
2
+ VERSION = "3.0.2"
3
3
  end
Binary file
@@ -1,10 +1,10 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe LMDocstache::HideCustomTags do
4
-
5
4
  context '#example' do
6
5
  let(:output_dir) { "#{base_path}/tmp/" }
7
6
  let(:output_file) { File.new("#{output_dir}/BlankTestOutput.docx", 'w') }
7
+
8
8
  before do
9
9
  FileUtils.rm_rf(output_dir) if File.exist?(output_dir)
10
10
  Dir.mkdir(output_dir)
@@ -15,22 +15,84 @@ describe LMDocstache::HideCustomTags do
15
15
  end
16
16
 
17
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)\|.+?}}/ }
18
+ let(:document) {
19
+ doc = LMDocstache::Document.new(input_file)
20
+ doc.fix_errors
21
+ doc.instance_variable_get(:@document)
22
+ }
23
+ let(:regexp_tag) { /(?:sig|sigfirm|date|text|initial)\|(?:req|noreq)\|.+?/ }
24
+ let(:regexp_for_replacement) { /(?:check)\|(?:req|noreq)\|.+?/ }
22
25
  let(:hide_custom_tags) {
23
- LMDocstache::HideCustomTags.new(document: document, hide_custom_tags: [ regexp_tag ])
26
+ LMDocstache::HideCustomTags.new(document: document, hide_custom_tags: {
27
+ /#{regexp_tag}/ => false,
28
+ /#{regexp_for_replacement}/ => 'replaced_content'
29
+ })
24
30
  }
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)
31
+
32
+ context "giving a document with blue background" do
33
+ let(:input_file) { "#{base_path}/sample-signature-blue.docx" }
34
+
35
+ it 'expect to have a white color on all hide custom tags matching and have first child node equal rPr tag' do
36
+ hide_custom_tags.hide_custom_tags!
37
+ d = hide_custom_tags.document
38
+ run_nodes = d.css('w|p w|r')
39
+ while run_node = run_nodes.shift
40
+ next unless run_node.text =~ regexp_tag
41
+ expect(run_node.at_css('w|rPr w|color').first[1]).to eq('4472C4')
42
+ expect(run_node.children.first.name).to eq('rPr')
43
+ end
44
+ end
45
+ end
46
+
47
+ context 'giving a document with white background' do
48
+ let(:input_file) { "#{base_path}/sample-signature.docx" }
49
+
50
+ it 'expect to have a white color on all hide custom tags matching and have first child node equal rPr tag' do
51
+ hide_custom_tags.hide_custom_tags!
52
+ d = hide_custom_tags.document
53
+ run_nodes = d.css('w|p w|r')
54
+ while run_node = run_nodes.shift
55
+ next unless run_node.text =~ regexp_tag
56
+ expect(run_node.at_css('w|rPr w|color').first[1]).to eq('FFFFFF')
57
+ expect(run_node.children.first.name).to eq('rPr')
58
+ end
59
+ end
60
+ end
61
+ context 'giving a document without rpr and block tags on the left' do
62
+ let(:input_file) { "#{base_path}/docx-no-rpr.docx" }
63
+
64
+ it 'expect to have a white color on all hide custom tags matching and have first child node equal rPr tag' do
65
+ hide_custom_tags.hide_custom_tags!
66
+ d = hide_custom_tags.document
67
+ run_nodes = d.css('w|p w|r')
68
+ while run_node = run_nodes.shift
69
+ next unless run_node.text =~ regexp_tag
70
+ expect(run_node.at_css('w|rPr w|color').first[1]).to eq('FFFFFF')
71
+ expect(run_node.children.first.name).to eq('rPr')
32
72
  end
33
73
  end
74
+ it 'expect to have a white color on all replacement tags and content following replacement' do
75
+ hide_custom_tags.hide_custom_tags!
76
+ d = hide_custom_tags.document
77
+ run_nodes = d.css('w|p w|r')
78
+ total_replacement = 0
79
+ while run_node = run_nodes.shift
80
+ next unless run_node.text =~ /replaced_content/
81
+ total_replacement+=1
82
+ expect(run_node.at_css('w|rPr w|color').first[1]).to eq('FFFFFF')
83
+ expect(run_node.children.first.name).to eq('rPr')
84
+ end
85
+ expect(total_replacement).to eq(2)
86
+ end
87
+ end
88
+
89
+ context 'giving a document with tabs spacing in the middle of replacement tags' do
90
+ let(:input_file) { "#{base_path}/sample-signature-with-tabs-spacing.docx" }
91
+ it 'expect to not replace tabs' do
92
+ hide_custom_tags.hide_custom_tags!
93
+ d = hide_custom_tags.document
94
+ expect(d.css('w|p w|tab').size).to eq(11)
95
+ end
34
96
  end
35
97
  end
36
98
  end
@@ -35,15 +35,18 @@ end
35
35
  describe 'integration test', integration: true do
36
36
  let(:base_path) { SPEC_BASE_PATH.join('example_input') }
37
37
  let(:output_dir) { "#{base_path}/tmp" }
38
+
38
39
  context 'should process that incoming docx' do
39
40
  let(:data) { LMDocstache::TestData::DATA }
40
41
  let(:input_file) { "#{base_path}/ExampleTemplate.docx" }
41
42
  let(:output_file) { "#{output_dir}/IntegrationTestOutput.docx" }
42
43
  let(:document) { LMDocstache::Document.new(input_file) }
44
+
43
45
  before do
44
46
  FileUtils.rm_rf(output_dir) if File.exist?(output_dir)
45
47
  Dir.mkdir(output_dir)
46
48
  end
49
+
47
50
  it 'loads the input file' do
48
51
  expect(document).to_not be_nil
49
52
  end
@@ -89,19 +92,43 @@ describe 'integration test', integration: true do
89
92
  Dir.mkdir(output_dir)
90
93
  end
91
94
 
92
- let(:input_file) { "#{base_path}/sample-signature.docx" }
93
95
  let(:render_options) {
94
96
  {
95
- hide_custom_tags: ['(?:sig|sigfirm|date|check|text|initial)\|(?:req|noreq)\\|.+?']
97
+ hide_custom_tags: ['(?:sig|sigfirm|date|check|text|initial)\|(?:req|noreq)\|.+?']
96
98
  }
97
99
  }
98
100
  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>
101
+
102
+ context "witth document with blue background" do
103
+ let(:input_file) { "#{base_path}/sample-signature-blue.docx" }
104
+
105
+ it 'should have content replacement aligned with hide custom tags' do
106
+ doc = document
107
+ doc.fix_errors
108
+ noko = doc.render_xml({}, render_options)
109
+ output = noko['word/document.xml'].to_xml
110
+ expect(output).to include('<w:r>
111
+ <w:rPr>
112
+ <w:rFonts w:cstheme="minorHAnsi"/>
113
+ <w:lang w:val="en-US"/>
114
+ <w:color w:val="4472C4"/>
115
+ </w:rPr>
116
+ <w:t xml:space="preserve">{{sig|req|client}}</w:t>
117
+ </w:r>')
118
+ expect(output).to include('<w:t xml:space="preserve">Test Multiple text in the same line </w:t>')
119
+ end
120
+ end
121
+
122
+ context "with document without backgorund" do
123
+ let(:input_file) { "#{base_path}/sample-signature.docx" }
124
+ let(:document) { LMDocstache::Document.new(input_file) }
125
+
126
+ it 'should have content replacement aligned with hide custom tags' do
127
+ doc = document
128
+ doc.fix_errors
129
+ noko = doc.render_xml({}, render_options)
130
+ output = noko['word/document.xml'].to_xml
131
+ expect(output).to include('<w:r>
105
132
  <w:rPr>
106
133
  <w:rFonts w:cstheme="minorHAnsi"/>
107
134
  <w:lang w:val="en-US"/>
@@ -109,7 +136,8 @@ describe 'integration test', integration: true do
109
136
  </w:rPr>
110
137
  <w:t xml:space="preserve">{{sig|req|client}}</w:t>
111
138
  </w:r>')
112
- expect(output).to include('<w:t xml:space="preserve">Test Multiple text in the same line </w:t>')
139
+ expect(output).to include('<w:t xml:space="preserve">Test Multiple text in the same line </w:t>')
140
+ end
113
141
  end
114
142
  end
115
143
  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.1.0
4
+ version: 3.0.2
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-17 00:00:00.000000000 Z
15
+ date: 2021-04-08 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: nokogiri
@@ -121,6 +121,9 @@ files:
121
121
  - spec/conditional_block_spec.rb
122
122
  - spec/example_input/ExampleTemplate.docx
123
123
  - spec/example_input/blank.docx
124
+ - spec/example_input/docx-no-rpr.docx
125
+ - spec/example_input/sample-signature-blue.docx
126
+ - spec/example_input/sample-signature-with-tabs-spacing.docx
124
127
  - spec/example_input/sample-signature.docx
125
128
  - spec/hide_custom_tags_spec.rb
126
129
  - spec/integration_spec.rb
@@ -153,6 +156,9 @@ test_files:
153
156
  - spec/conditional_block_spec.rb
154
157
  - spec/example_input/ExampleTemplate.docx
155
158
  - spec/example_input/blank.docx
159
+ - spec/example_input/docx-no-rpr.docx
160
+ - spec/example_input/sample-signature-blue.docx
161
+ - spec/example_input/sample-signature-with-tabs-spacing.docx
156
162
  - spec/example_input/sample-signature.docx
157
163
  - spec/hide_custom_tags_spec.rb
158
164
  - spec/integration_spec.rb