avv2word 1.1.18 → 1.1.20
Sign up to get free protection for your applications and to get access to all the features.
- 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
|