lm_docstache 2.1.0 → 3.0.2

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 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