avv2word 1.1.18 → 1.1.20
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/lib/avv2word/document.rb +79 -8
- data/lib/avv2word/templates/default.docx +0 -0
- data/lib/avv2word/version.rb +1 -1
- data/lib/avv2word/xslt/base.xslt +1 -0
- data/lib/avv2word/xslt/footnote.xslt +29 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8c2007bdd078951c37ebd73c35daf9a6a6022b23b366e28335c1f482a6da18b0
|
4
|
+
data.tar.gz: 42af443d0dce033451ebd545115fe2db68438b338287cb8b6713f91a8de87fb2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6bedab9f56d9134974c78f20ab3b500102c281bae9d69c8f0c0c0c56e28be74b650421f7ed3730e13a5c32ed293d99cd415681346964dc0cbe72171a9d37a5f5
|
7
|
+
data.tar.gz: ac2849c81b0dfd36a327b6b86673c936aa2d035777477093f9bd178a3a9375fa5a4d977ff3bd14e2d172109925c29b3ee19e6c50da0218ba71207d8ef243ffac
|
data/lib/avv2word/document.rb
CHANGED
@@ -11,13 +11,15 @@ module Avv2word
|
|
11
11
|
|
12
12
|
# create working dir
|
13
13
|
FileUtils.mkdir_p("tmp_imgs")
|
14
|
-
resize = 1 #
|
14
|
+
resize = 1 # future feature; half size: 0.5
|
15
15
|
|
16
16
|
doc = Nokogiri::HTML.fragment(html)
|
17
17
|
doc.css("img").each_with_index do |img_elm,i|
|
18
18
|
mime_type, img_data = img_elm.attributes["src"].value.split(",")
|
19
19
|
# ^--data:image/jpeg;base64
|
20
|
-
|
20
|
+
ext = mime_type.match(/image\/(\w+?);base64/)[1]
|
21
|
+
ext = "jpg" if ext == "jpeg"
|
22
|
+
img_path = "tmp_imgs/image#{i+1}.#{ext}"
|
21
23
|
File.open(img_path,"wb"){|f| f.write Base64.decode64(img_data)}
|
22
24
|
img_elm.attributes["src"].value = img_path
|
23
25
|
match_dimensions = %x( file #{img_path} ).match(/, (?<x>\d+) ?x ?(?<y>\d+),/)
|
@@ -29,8 +31,20 @@ module Avv2word
|
|
29
31
|
doc.to_html
|
30
32
|
end
|
31
33
|
|
34
|
+
def escape_footnotes(html)
|
35
|
+
doc = Nokogiri::HTML.fragment(html)
|
36
|
+
nodes_with_footnotes = doc.css("footnote")
|
37
|
+
nodes_with_footnotes.each do |node|
|
38
|
+
node.name = "footnote"
|
39
|
+
node.content = node.attributes["data-value"]
|
40
|
+
node.attributes.map{|k,v| node.attributes[k].remove }
|
41
|
+
end
|
42
|
+
doc.to_html
|
43
|
+
end
|
44
|
+
|
32
45
|
def create(content, template_name = nil, extras = false)
|
33
46
|
content = extract_images_html(content)
|
47
|
+
content = escape_footnotes(content)
|
34
48
|
template_name += extension if template_name && !template_name.end_with?(extension)
|
35
49
|
document = new(template_file(template_name))
|
36
50
|
document.replace_files(content, extras)
|
@@ -44,6 +58,7 @@ module Avv2word
|
|
44
58
|
end
|
45
59
|
|
46
60
|
def create_with_content(template, content, extras = false)
|
61
|
+
content = extract_images_html(content)
|
47
62
|
template += extension unless template.end_with?(extension)
|
48
63
|
document = new(template_file(template))
|
49
64
|
document.replace_files(content, extras)
|
@@ -109,7 +124,6 @@ module Avv2word
|
|
109
124
|
elsif entry.name == Document.content_types_xml_file
|
110
125
|
raw_file = entry.get_input_stream.read
|
111
126
|
content_types = @image_files.empty? ? raw_file : inject_image_content_types(raw_file)
|
112
|
-
|
113
127
|
out.write(content_types)
|
114
128
|
else
|
115
129
|
out.write(template_zip.read(entry.name))
|
@@ -124,6 +138,18 @@ module Avv2word
|
|
124
138
|
end
|
125
139
|
end
|
126
140
|
end
|
141
|
+
|
142
|
+
%w( word/_rels/header.xml.rels
|
143
|
+
word/_rels/footer.xml.rels
|
144
|
+
word/footnotes.xml
|
145
|
+
word/endnotes.xml
|
146
|
+
).each do |f|
|
147
|
+
if @replaceable_files[f]
|
148
|
+
out.put_next_entry f
|
149
|
+
out.write(@replaceable_files[f])
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
127
153
|
end
|
128
154
|
buffer.string
|
129
155
|
end
|
@@ -143,9 +169,15 @@ module Avv2word
|
|
143
169
|
transform_and_replace(footer, xslt_path('footer'), Document.footer_xml_file)
|
144
170
|
transform_and_replace(original_source, xslt_path('relations'), Document.relations_xml_file)
|
145
171
|
source = xslt(stylesheet_name: 'cleanup').transform(original_source)
|
172
|
+
|
173
|
+
add_footnotes(source.css("footnote").map{ |footnote| footnote.text })
|
174
|
+
|
146
175
|
transform_and_replace(source, xslt_path('numbering'), Document.numbering_xml_file)
|
147
176
|
transform_doc_xml(source, extras)
|
177
|
+
|
148
178
|
local_images(source)
|
179
|
+
local_images(footer, :footer) if @footer
|
180
|
+
local_images(header, :header) if @header
|
149
181
|
end
|
150
182
|
|
151
183
|
def transform_doc_xml(source, extras = false)
|
@@ -156,13 +188,40 @@ module Avv2word
|
|
156
188
|
|
157
189
|
private
|
158
190
|
|
191
|
+
def add_footnotes(footnotes)
|
192
|
+
if footnotes.empty?
|
193
|
+
@replaceable_files["word/footnotes.xml"] = ""
|
194
|
+
return
|
195
|
+
end
|
196
|
+
doc = Nokogiri::XML.parse(File.read("templates/default/word/footnotes.xml"))
|
197
|
+
fn_node = doc.xpath("//w:footnote").last
|
198
|
+
footnotes.each_with_index do |footnote,i|
|
199
|
+
fn_node2 = fn_node.clone
|
200
|
+
fn_node2.parent = fn_node.parent
|
201
|
+
fn_node2["w:id"] = (fn_node["w:id"].to_i + i).to_s
|
202
|
+
fn_node2.xpath("w:p/w:r/w:t").first.content = " " + footnote
|
203
|
+
end
|
204
|
+
fn_node.remove
|
205
|
+
|
206
|
+
@replaceable_files["word/footnotes.xml"] = doc.to_xml
|
207
|
+
# add relation
|
208
|
+
rels = Nokogiri::XML(@replaceable_files["word/_rels/document.xml.rels"])
|
209
|
+
new_rel = '<Relationship Id="rIdXXXXX" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/footnotes" Target="footnotes.xml"/>'
|
210
|
+
new_rel.sub!(/XXXXX/, (rels.xpath("//xmlns:Relationship").size+1).to_s )
|
211
|
+
new_rel = Nokogiri::XML.parse(new_rel).child
|
212
|
+
rels.children.first << new_rel
|
213
|
+
@replaceable_files["word/_rels/document.xml.rels"] = rels.to_xml
|
214
|
+
end
|
215
|
+
|
159
216
|
def inject_image_relations(relations, noko_html_source)
|
160
217
|
rel_doc = Nokogiri::XML(relations)
|
161
218
|
relations_root = rel_doc.css("Relationships").first
|
162
219
|
|
220
|
+
relations_size = relations_root.css("Relationship").size
|
221
|
+
|
163
222
|
noko_html_source.css("img").each_with_index do |img,i|
|
164
223
|
new_relation = relations_root.css("Relationship").last.clone
|
165
|
-
new_relation["Id"] = "rId#{i+10}"
|
224
|
+
new_relation["Id"] = "rId#{i + 10}" # use relations_size for dynamic relations create, todo
|
166
225
|
new_relation["Type"] = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"
|
167
226
|
new_relation["Target"] = "media/image#{i+1}#{File.extname(img[:src])}"
|
168
227
|
relations_root.add_child new_relation
|
@@ -176,18 +235,30 @@ module Avv2word
|
|
176
235
|
content.gsub!(/\s*xmlns:(\w+)="(.*?)\s*"/, '') if remove_ns
|
177
236
|
if ( file =~ /document\.xml\.rels/ ) && ( source.css("img").size > 0 )
|
178
237
|
content = inject_image_relations(content, source)
|
238
|
+
elsif file =~ /header/i
|
239
|
+
@replaceable_files["word/_rels/header.xml.rels"] = %(<?xml version="1.0" encoding="UTF-8"?>\n<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">\n</Relationships>)
|
240
|
+
source.css("img").each_with_index do |noko_img,i|
|
241
|
+
# <Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="media/image3.png"/>
|
242
|
+
new_head_rel = %Q(<Relationship Id="rId#{i+10}" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="media/#{File.basename(noko_img["src"])}"/>)
|
243
|
+
@replaceable_files["word/_rels/header.xml.rels"].sub!(/<\/Relationships>/, new_head_rel + "</Relationships>")
|
244
|
+
end
|
245
|
+
elsif file =~ /footer/i
|
246
|
+
@replaceable_files["word/_rels/footer.xml.rels"] = %(<?xml version="1.0" encoding="UTF-8"?>\n<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">\n</Relationships>)
|
247
|
+
source.css("img").each_with_index do |noko_img,i|
|
248
|
+
new_foot_rel = %Q(<Relationship Id="rId#{i+10}" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="media/#{File.basename(noko_img["src"])}"/>)
|
249
|
+
@replaceable_files["word/_rels/footer.xml.rels"].sub!(/<\/Relationships>/, new_foot_rel + "</Relationships>")
|
250
|
+
end
|
179
251
|
end
|
180
252
|
@replaceable_files[file] = content
|
181
253
|
end
|
182
254
|
|
183
255
|
#generates an array of hashes with filename and full url
|
184
256
|
#for all images to be embeded in the word document
|
185
|
-
def local_images(source)
|
186
|
-
source.css('img').each_with_index do |image,i|
|
257
|
+
def local_images(source, type = nil)
|
258
|
+
source.css('img').sort_by{|e| e.attributes['src'].value}.each_with_index do |image,i|
|
187
259
|
filename = image['data-filename'] ? image['data-filename'] : image['src'].split("/").last
|
188
260
|
ext = File.extname(filename).delete(".").downcase
|
189
|
-
|
190
|
-
@image_files << { filename: "image#{i+1}.#{ext}", url: image['src'], ext: ext }
|
261
|
+
@image_files << { filename: "image#{@image_files.size+1}.#{ext}", url: image['src'], ext: ext }
|
191
262
|
end
|
192
263
|
end
|
193
264
|
|
Binary file
|
data/lib/avv2word/version.rb
CHANGED
data/lib/avv2word/xslt/base.xslt
CHANGED
@@ -0,0 +1,29 @@
|
|
1
|
+
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
2
|
+
xmlns:wpc="http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas"
|
3
|
+
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
4
|
+
xmlns:o="urn:schemas-microsoft-com:office:office"
|
5
|
+
xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
|
6
|
+
xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math"
|
7
|
+
xmlns:v="urn:schemas-microsoft-com:vml"
|
8
|
+
xmlns:wp14="http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing"
|
9
|
+
xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing"
|
10
|
+
xmlns:w10="urn:schemas-microsoft-com:office:word"
|
11
|
+
xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
|
12
|
+
xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml"
|
13
|
+
xmlns:wpg="http://schemas.microsoft.com/office/word/2010/wordprocessingGroup"
|
14
|
+
xmlns:wpi="http://schemas.microsoft.com/office/word/2010/wordprocessingInk"
|
15
|
+
xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml"
|
16
|
+
xmlns:wps="http://schemas.microsoft.com/office/word/2010/wordprocessingShape"
|
17
|
+
mc:Ignorable="w14 wp14">
|
18
|
+
|
19
|
+
<xsl:template match="footnote">
|
20
|
+
<xsl:number level="any" count="footnote" format="1"/>
|
21
|
+
<w:r>
|
22
|
+
<w:rPr>
|
23
|
+
<w:rStyle w:val="FootnoteReference"/>
|
24
|
+
</w:rPr>
|
25
|
+
<w:footnoteReference w:id="{format-number(count(preceding::footnote)+1,'0')}"/>
|
26
|
+
<xsl:apply-templates select="@*|node()"/>
|
27
|
+
</w:r>
|
28
|
+
</xsl:template>
|
29
|
+
</xsl:stylesheet>
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: avv2word
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.20
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Marián Bilas
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-07-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: actionpack
|
@@ -146,6 +146,7 @@ files:
|
|
146
146
|
- lib/avv2word/xslt/cleanup.xslt
|
147
147
|
- lib/avv2word/xslt/extras.xslt
|
148
148
|
- lib/avv2word/xslt/footer.xslt
|
149
|
+
- lib/avv2word/xslt/footnote.xslt
|
149
150
|
- lib/avv2word/xslt/functions.xslt
|
150
151
|
- lib/avv2word/xslt/header.xslt
|
151
152
|
- lib/avv2word/xslt/htmltoword.xslt
|