lm_docstache 3.0.12 → 3.0.13
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 +12 -0
- data/lib/lm_docstache/document.rb +16 -6
- data/lib/lm_docstache/version.rb +1 -1
- data/spec/document_spec.rb +52 -0
- metadata +4 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ae18b926b254131128665bfa341baff5c70c6b1a76f95dd4a82b1ee9f3481bfd
|
|
4
|
+
data.tar.gz: 621ed8204c30caa2b205651d1b05b7564e39e9d7c981e46f0175d2eee292765a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b886ea9ada5a9ecb9e370d2fb38616a19531715ab0bb7725b5f0e8357eca51bc0a4b5536da7c8acc1a176662963eaeab57009f54799ee13220ba79c5db875050
|
|
7
|
+
data.tar.gz: 583be1faad4e8b92c4eedf3ab8035f894a45dac5636a08e4cac0323b3af10e97990126d304981df2fbee9ab42897fc40ae464762291e3438bccb00414293764c
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 3.0.13
|
|
4
|
+
|
|
5
|
+
#### Performance
|
|
6
|
+
|
|
7
|
+
* `LMDocstache::Document#problem_paragraphs` now serializes each paragraph's
|
|
8
|
+
text once per call instead of once per broken tag. Locating broken tags
|
|
9
|
+
previously rescanned every paragraph in the document, its headers, and its
|
|
10
|
+
footers for each unusable tag, so a template with many merge tags split
|
|
11
|
+
across runs cost paragraphs × broken tags text serializations. Measured 13.9×
|
|
12
|
+
faster on a template with 2,022 paragraphs and 180 broken tags. The return
|
|
13
|
+
value is unchanged.
|
|
14
|
+
|
|
3
15
|
## 3.0.10
|
|
4
16
|
|
|
5
17
|
#### Bug fixes
|
|
@@ -143,12 +143,22 @@ module LMDocstache
|
|
|
143
143
|
end
|
|
144
144
|
|
|
145
145
|
def problem_paragraphs
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
146
|
+
broken_tags = unusable_tags
|
|
147
|
+
return [] if broken_tags.empty?
|
|
148
|
+
|
|
149
|
+
# Serialize each paragraph once up front. Scanning per tag instead makes a
|
|
150
|
+
# template with many split tags cost one full rescan per broken tag.
|
|
151
|
+
scanned_documents = @documents.values.map do |document|
|
|
152
|
+
document.css('w|p').map { |paragraph| [paragraph, paragraph.text] }
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
broken_tags.flat_map do |tag|
|
|
156
|
+
tag_regex = tag.is_a?(Regexp) ? tag : /#{Regexp.escape(tag)}/
|
|
157
|
+
|
|
158
|
+
scanned_documents.inject([]) do |tags, scanned_paragraphs|
|
|
159
|
+
faulty_paragraphs = scanned_paragraphs
|
|
160
|
+
.select { |_paragraph, text| text =~ tag_regex }
|
|
161
|
+
.map(&:first)
|
|
152
162
|
|
|
153
163
|
tags + faulty_paragraphs
|
|
154
164
|
end
|
data/lib/lm_docstache/version.rb
CHANGED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
# Counts how many times a `w:p` node has its text serialized. Serializing a
|
|
4
|
+
# paragraph walks and allocates its whole subtree, so it dominates the cost of
|
|
5
|
+
# scanning a document for broken tags.
|
|
6
|
+
module ParagraphTextCounter
|
|
7
|
+
class << self
|
|
8
|
+
attr_accessor :count, :enabled
|
|
9
|
+
end
|
|
10
|
+
self.count = 0
|
|
11
|
+
self.enabled = false
|
|
12
|
+
|
|
13
|
+
def text
|
|
14
|
+
ParagraphTextCounter.count += 1 if ParagraphTextCounter.enabled && name == 'p'
|
|
15
|
+
super
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
Nokogiri::XML::Node.prepend(ParagraphTextCounter)
|
|
20
|
+
|
|
21
|
+
describe LMDocstache::Document do
|
|
22
|
+
let(:input_file) { SPEC_BASE_PATH.join('example_input', 'ExampleTemplate.docx') }
|
|
23
|
+
let(:document) { LMDocstache::Document.new(input_file) }
|
|
24
|
+
|
|
25
|
+
def count_paragraph_text_serializations
|
|
26
|
+
ParagraphTextCounter.count = 0
|
|
27
|
+
ParagraphTextCounter.enabled = true
|
|
28
|
+
yield
|
|
29
|
+
ParagraphTextCounter.count
|
|
30
|
+
ensure
|
|
31
|
+
ParagraphTextCounter.enabled = false
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
describe '#problem_paragraphs' do
|
|
35
|
+
it 'serializes each paragraph text at most once, whatever the broken tag count' do
|
|
36
|
+
# Headers and footers are scanned alongside document.xml, so the bound is
|
|
37
|
+
# every paragraph in every interpolated document.
|
|
38
|
+
paragraph_count = document.instance_variable_get(:@documents)
|
|
39
|
+
.values.sum { |doc| doc.css('w|p').size }
|
|
40
|
+
broken_tag_count = document.send(:unusable_tags).size
|
|
41
|
+
|
|
42
|
+
serializations = count_paragraph_text_serializations do
|
|
43
|
+
document.send(:problem_paragraphs)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Scanning must cost one pass over the paragraphs, not one pass per broken
|
|
47
|
+
# tag: the latter is what makes a template with many split tags unrenderable.
|
|
48
|
+
expect(broken_tag_count).to be > 1 # guards the assertion below from being vacuous
|
|
49
|
+
expect(serializations).to be <= paragraph_count
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
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: 3.0.
|
|
4
|
+
version: 3.0.13
|
|
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:
|
|
15
|
+
date: 2026-07-28 00:00:00.000000000 Z
|
|
16
16
|
dependencies:
|
|
17
17
|
- !ruby/object:Gem::Dependency
|
|
18
18
|
name: nokogiri
|
|
@@ -105,6 +105,7 @@ files:
|
|
|
105
105
|
- lib/lm_docstache/version.rb
|
|
106
106
|
- lm_docstache.gemspec
|
|
107
107
|
- spec/conditional_block_spec.rb
|
|
108
|
+
- spec/document_spec.rb
|
|
108
109
|
- spec/example_input/ExampleTemplate.docx
|
|
109
110
|
- spec/example_input/blank.docx
|
|
110
111
|
- spec/example_input/docx-no-rpr.docx
|
|
@@ -140,6 +141,7 @@ specification_version: 4
|
|
|
140
141
|
summary: Merges Hash of Data into Word docx template files using mustache syntax
|
|
141
142
|
test_files:
|
|
142
143
|
- spec/conditional_block_spec.rb
|
|
144
|
+
- spec/document_spec.rb
|
|
143
145
|
- spec/example_input/ExampleTemplate.docx
|
|
144
146
|
- spec/example_input/blank.docx
|
|
145
147
|
- spec/example_input/docx-no-rpr.docx
|