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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1e32cdd0e7cb785ccb74285d2df67556c6ae24184a49511dd08fa6aa523e845c
4
- data.tar.gz: d5872f502d4e95d4135dfcf3014826c76fa3968db8be301e4cc52d73d04b9951
3
+ metadata.gz: 65f3c502d4e4982f2361991d6b43b4d22460ab4e25d9db7fd60eb6b9f14d4a1f
4
+ data.tar.gz: 779810f481adebb853e62ea708df571ab355fb96cc9fde3c83d86ff7ad214714
5
5
  SHA512:
6
- metadata.gz: 65852b8af255a23a06064bc91eee802005f31cdff3e3fc3258cbb03fbec9ba07e2f0c5cbd0af37f25324db2df774070280596a87fb49e2332d28a368514ca837
7
- data.tar.gz: 85ebb2d3d2af5a0a3c7e3787a8ba98688193e220e56aceba5b37aa3ac500a39fc3914f6d14251d4f4007a317e677d41cf6b8fd7a98e4d51960e441abac40a59a
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
@@ -2,6 +2,7 @@ require 'nokogiri'
2
2
  require 'zip'
3
3
  require "lm_docstache/version"
4
4
  require "lm_docstache/document"
5
+ require 'lm_docstache/hide_custom_tags'
5
6
  require "lm_docstache/parser"
6
7
  require "lm_docstache/condition"
7
8
  require "lm_docstache/conditional_block"
@@ -93,8 +93,8 @@ module LMDocstache
93
93
  buffer.sysread
94
94
  end
95
95
 
96
- def render_xml(data = {})
97
- render_documents(data)
96
+ def render_xml(data = {}, render_options = {})
97
+ render_documents(data, nil, render_options)
98
98
  end
99
99
 
100
100
  private
@@ -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
@@ -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
@@ -1,3 +1,3 @@
1
1
  module LMDocstache
2
- VERSION = "2.0.2"
2
+ VERSION = "2.1.0"
3
3
  end
@@ -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
@@ -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
@@ -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.2
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-09 00:00:00.000000000 Z
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