docxi 0.0.2 → 0.0.6
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/README.md +45 -4
- data/lib/docxi/content_types.rb +5 -0
- data/lib/docxi/document.rb +4 -4
- data/lib/docxi/version.rb +1 -1
- data/lib/docxi/word/contents/frame.rb +84 -0
- data/lib/docxi/word/contents/image.rb +74 -10
- data/lib/docxi/word/contents/paragraph.rb +68 -1
- data/lib/docxi/word/contents/tab.rb +33 -0
- data/lib/docxi/word/contents/table.rb +80 -0
- data/lib/docxi/word/contents/text.rb +7 -1
- data/lib/docxi/word/document.rb +44 -4
- data/lib/docxi/word/footers/footer.rb +22 -2
- data/lib/docxi/word/headers/header.rb +55 -9
- data/lib/docxi/word/helpers.rb +12 -0
- data/lib/docxi/word/hyperlinks.rb +30 -0
- data/lib/docxi/word/hyperlinks/hyperlink.rb +96 -0
- data/lib/docxi/word/medias.rb +7 -1
- data/lib/docxi/word/relationships.rb +4 -4
- data/lib/docxi/word/relationships/relationship.rb +8 -3
- data/lib/docxi/word/styles.rb +5 -4
- metadata +5 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5076084e490ded4f975883817964681a11cb0020
|
4
|
+
data.tar.gz: 8e6c401e687f6eaad1c5a1c23060481f0e552576
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2b1f94d68e5d454c5703c9c26ab851bd4a886a2c7c7c27f8162d7fa2ef3599dd0eb179e02f18a1bef9065b4df27c31bff15f3383d0e99e0e95279f184b152a52
|
7
|
+
data.tar.gz: 7e714bdd0ccbfb487180beb5ef57f3fbb84c3ff6661d929d0750d9bc2f336cbf6af9b5b8ff4a14b962cd299ec7942cf181664e8feef9f3bcd6318bc30086f396
|
data/README.md
CHANGED
@@ -11,11 +11,16 @@ Docxi gem provides ability to create docx documents using Ruby.
|
|
11
11
|
7. Page Numbering
|
12
12
|
|
13
13
|
At the moment, the gem supports a limited number of functions, but the development of the gem is still in progress, and perhaps functionality will be expanded in the future. First of all, try to add documentation for the code and tests.
|
14
|
-
|
14
|
+
## NOTE
|
15
|
+
Use Latest version of Gem. Old Version has bugs.
|
15
16
|
## Usage
|
16
17
|
|
17
18
|
```ruby
|
18
|
-
|
19
|
+
# default attributes (top: 720,right: 1440,left: 1440,bottom: 720,footer: 200, header: 190)
|
20
|
+
word = Docxi::Document.new
|
21
|
+
# or change margins
|
22
|
+
# word = Docxi::Document.new(top: 0,right: 0,left: 0,bottom: 0)
|
23
|
+
|
19
24
|
document = word.document
|
20
25
|
|
21
26
|
# Creates Header
|
@@ -39,8 +44,8 @@ end
|
|
39
44
|
document.add_footer(footer)
|
40
45
|
|
41
46
|
# Creates paragraph
|
42
|
-
document.p(size:
|
43
|
-
p.text "Title"
|
47
|
+
document.p(size: 12, bold: true, align: "center", color: "000000", fill: "AAAAAA") do |p|
|
48
|
+
p.text "Title", size: 12, bold: true, align: "center", color: "000000"
|
44
49
|
# Adds 3 break lines
|
45
50
|
p.br times: 3
|
46
51
|
end
|
@@ -103,14 +108,50 @@ document.table( columns_width: [ 316, 160, 135 ] ) do |table|
|
|
103
108
|
end
|
104
109
|
end
|
105
110
|
|
111
|
+
# Adds table with row height and column indentation
|
112
|
+
document.table( columns_width: [ 316, 160, 135 ], height: 268, iwidth: 108) do |table|
|
113
|
+
# Adds row with specific styles
|
114
|
+
table.tr(fill: "FBD4B4", bold: true, align: 'center' ) do |tr|
|
115
|
+
# Adds cells
|
116
|
+
tr.tc(borders: { top: 1, right: nil, bottom: 1, left: 1 }) do |tc|
|
117
|
+
tc.text "Header 1"
|
118
|
+
end
|
119
|
+
tr.tc(borders: { top: 1, right: nil, bottom: 1, left: nil }) do |tc|
|
120
|
+
tc.text "Header 2"
|
121
|
+
end
|
122
|
+
tr.tc(borders: { top: 1, right: 1, bottom: 1, left: nil }) do |tc|
|
123
|
+
tc.text "Header 3"
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
|
106
129
|
# Adds image
|
107
130
|
document.p do |p|
|
108
131
|
p.text "Image Example", size: 16, bold: true, italic: true, underline: true, br: true
|
109
132
|
|
110
133
|
# Adds image to container
|
111
134
|
media = document.add_media File.open('image.png')
|
135
|
+
# Or add image URL
|
136
|
+
media = document.add_media image_url
|
112
137
|
# Insert media into paragraph
|
113
138
|
p.image media, style: { width: '200pt', height: '200pt' }
|
139
|
+
|
140
|
+
# Add Hyperlink
|
141
|
+
hyper = document.add_hyperlink("http://google.com")
|
142
|
+
p.hyperlink "Go to Google", "http://google.com", hyper
|
143
|
+
|
144
|
+
end
|
145
|
+
|
146
|
+
# Add Underline
|
147
|
+
document.p(bottom: true) do |p|
|
148
|
+
p.text "Example text"
|
149
|
+
end
|
150
|
+
|
151
|
+
# Set position of Paragraph
|
152
|
+
document.p(fill: "d7d7d7",align: "center", right: -1000, left: -1000) do |p|
|
153
|
+
p.text "Example Text 2"
|
154
|
+
p.br
|
114
155
|
end
|
115
156
|
|
116
157
|
# Creates Word Document
|
data/lib/docxi/content_types.rb
CHANGED
@@ -11,6 +11,7 @@ module Docxi
|
|
11
11
|
add(:default, "rels", "application/vnd.openxmlformats-package.relationships+xml")
|
12
12
|
add(:default, "xml", "application/xml")
|
13
13
|
add(:default, "png", "image/png")
|
14
|
+
add(:override, "/_rels/.rels","application/vnd.openxmlformats-package.relationships+xml")
|
14
15
|
add(:override, "/word/document.xml", "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml")
|
15
16
|
add(:override, "/word/styles.xml", "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml")
|
16
17
|
add(:override, "/word/stylesWithEffects.xml", "application/vnd.ms-word.stylesWithEffects+xml")
|
@@ -24,7 +25,11 @@ module Docxi
|
|
24
25
|
add(:override, "/word/footnotes.xml", "application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml")
|
25
26
|
add(:override, "/word/endnotes.xml", "application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml")
|
26
27
|
add(:override, "/word/footer1.xml", "application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml")
|
28
|
+
add(:override, "/word/footer2.xml", "application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml")
|
27
29
|
add(:override, "/word/header1.xml", "application/vnd.openxmlformats-officedocument.wordprocessingml.header+xml")
|
30
|
+
add(:override, "/word/header2.xml", "application/vnd.openxmlformats-officedocument.wordprocessingml.header+xml")
|
31
|
+
add(:override, "/word/_rels/header2.xml.rels", "application/vnd.openxmlformats-package.relationships+xml")
|
32
|
+
add(:override, "/word/_rels/document.xml.rels", "application/vnd.openxmlformats-package.relationships+xml")
|
28
33
|
end
|
29
34
|
|
30
35
|
def add(type, attr, content)
|
data/lib/docxi/document.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
module Docxi
|
2
2
|
class Document
|
3
3
|
|
4
|
-
attr_accessor :document, :properties, :relationships, :content_types
|
4
|
+
attr_accessor :document, :properties, :relationships, :content_types, :options
|
5
5
|
|
6
|
-
def initialize
|
7
|
-
|
6
|
+
def initialize(options = {top: 720,right: 1440,left: 1440,bottom: 720,footer: 200, header: 190})
|
7
|
+
@options = options
|
8
8
|
end
|
9
9
|
|
10
10
|
def relationships
|
@@ -20,7 +20,7 @@ module Docxi
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def document
|
23
|
-
@document ||= Word::Document.new(
|
23
|
+
@document ||= Word::Document.new(options)
|
24
24
|
end
|
25
25
|
|
26
26
|
def render
|
data/lib/docxi/version.rb
CHANGED
@@ -0,0 +1,84 @@
|
|
1
|
+
module Docxi
|
2
|
+
module Word
|
3
|
+
module Contents
|
4
|
+
|
5
|
+
class Frame
|
6
|
+
|
7
|
+
attr_accessor :content, :options
|
8
|
+
def initialize(options={})
|
9
|
+
@content = []
|
10
|
+
@options = options
|
11
|
+
if block_given?
|
12
|
+
yield self
|
13
|
+
else
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def render(xml)
|
19
|
+
xml['w'].r do
|
20
|
+
xml['w'].pict do
|
21
|
+
xml['v'].rect("fillcolor"=>"#bfbfbf[2412]", "strokecolor"=>"000000","strokeweight"=>"0pt", "style"=> @options[:style]) do
|
22
|
+
xml['v'].fill("opacity" =>"52429f")
|
23
|
+
xml['v'].textbox("inset" => "0in,0in,0in,0in") do
|
24
|
+
xml['w'].txbxContent do
|
25
|
+
xml['w'].p do
|
26
|
+
xml['w'].pPr do
|
27
|
+
xml['w'].pStyle('w:val'=>"Normal")
|
28
|
+
xml['w'].pBdr do
|
29
|
+
xml['w'].top('w:val'=>"nil")
|
30
|
+
xml['w'].left('w:val'=>"nil")
|
31
|
+
xml['w'].bottom('w:val'=>"nil")
|
32
|
+
xml['w'].right('w:val'=>"nil")
|
33
|
+
end
|
34
|
+
if @options[:spacing]
|
35
|
+
xml['w'].spacing('w:before'=>"240")
|
36
|
+
end
|
37
|
+
end
|
38
|
+
@content.each do |element|
|
39
|
+
element.render(xml)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
xml['w10'].wrap('type'=>"topAndBottom")
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def br(options={})
|
51
|
+
br = Docxi::Word::Contents::Break.new(options)
|
52
|
+
@content << br
|
53
|
+
br
|
54
|
+
end
|
55
|
+
|
56
|
+
def tab(options={})
|
57
|
+
tab = Docxi::Word::Contents::Tab.new(options)
|
58
|
+
@content << tab
|
59
|
+
tab
|
60
|
+
end
|
61
|
+
|
62
|
+
def frame(options={}, &block)
|
63
|
+
element = Docxi::Word::Contents::Frame.new(options, &block)
|
64
|
+
@content << element
|
65
|
+
element
|
66
|
+
end
|
67
|
+
|
68
|
+
def text(text, options={})
|
69
|
+
options = @options.merge(options)
|
70
|
+
text = Docxi::Word::Contents::Text.new(text, options)
|
71
|
+
@content << text
|
72
|
+
text
|
73
|
+
end
|
74
|
+
|
75
|
+
def image(image, options={})
|
76
|
+
img = Docxi::Word::Contents::Image.new(image, options)
|
77
|
+
@content << img
|
78
|
+
img
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -7,7 +7,7 @@ module Docxi
|
|
7
7
|
attr_accessor :media, :options
|
8
8
|
def initialize(media, options={})
|
9
9
|
@media = media
|
10
|
-
@media.file.rewind
|
10
|
+
# @media.file.rewind
|
11
11
|
@options = options
|
12
12
|
end
|
13
13
|
|
@@ -19,16 +19,80 @@ module Docxi
|
|
19
19
|
|
20
20
|
def render(xml)
|
21
21
|
xml['w'].r do
|
22
|
-
|
23
|
-
xml['w'].
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
22
|
+
if options[:pH] and options[:pV] and options[:wrap]
|
23
|
+
xml['w'].drawing do
|
24
|
+
xml['wp'].anchor( "behindDoc" => 1 ,"distT" => 0,"distB" => 0, "distL" => 0, "distR" => 0 ,"simplePos" => 0 ,"locked" => 0, "layoutInCell" => 1, "allowOverlap" => 1, "relativeHeight" => 3) do
|
25
|
+
xml['wp'].simplePos('x'=> 0 , 'y' => 0 )
|
26
|
+
xml['wp'].positionH("relativeFrom" => "column") do
|
27
|
+
xml['wp'].posOffset options[:pH]
|
28
|
+
end
|
29
|
+
xml['wp'].positionV("relativeFrom" => "paragraph") do
|
30
|
+
xml['wp'].posOffset options[:pV]
|
31
|
+
end
|
32
|
+
xml['wp'].extent( 'cx' => ( options[:width] * options[:height] * 14.92 ).to_i, 'cy' => ( options[:width] * options[:height] * 14.92 ).to_i ) if options[:width] && options[:height]
|
33
|
+
xml['wp'].effectExtent( 'l' => 0, 't' => 0, 'r' => 0, 'b' => 0 )
|
34
|
+
xml['wp'].wrapNone
|
35
|
+
xml['wp'].docPr( 'id' => 1, 'name'=> "Image", 'descr' => "image")
|
36
|
+
xml['wp'].cNvGraphicFramePr do
|
37
|
+
xml.graphicFrameLocks( 'xmlns:a' => "http://schemas.openxmlformats.org/drawingml/2006/main", 'noChangeAspect' => "1" ) do
|
38
|
+
xml.parent.namespace = xml.parent.namespace_definitions.find{|ns| ns.prefix == "a" }
|
39
|
+
end
|
40
|
+
end
|
41
|
+
xml.graphic( 'xmlns:a' => "http://schemas.openxmlformats.org/drawingml/2006/main" ) do
|
42
|
+
xml.parent.namespace = xml.parent.namespace_definitions.find{|ns| ns.prefix == "a" }
|
43
|
+
xml['a'].graphicData( 'uri' => "http://schemas.openxmlformats.org/drawingml/2006/picture") do
|
44
|
+
xml.pic( 'xmlns:pic' => "http://schemas.openxmlformats.org/drawingml/2006/picture") do
|
45
|
+
xml.parent.namespace = xml.parent.namespace_definitions.find{|ns| ns.prefix == "pic" }
|
46
|
+
xml['pic'].nvPicPr do
|
47
|
+
xml['pic'].cNvPr( 'id' => 0, 'name' => "Image" )
|
48
|
+
xml['pic'].cNvPicPr do
|
49
|
+
xml['a'].picLocks( 'noChangeAspect' => "1", 'noChangeArrowheads' => "1" )
|
50
|
+
end
|
51
|
+
end
|
52
|
+
xml['pic'].blipFill do
|
53
|
+
xml['a'].blip( 'r:embed' => @media.sequence )
|
54
|
+
xml['a'].stretch do
|
55
|
+
xml['a'].fillRect
|
56
|
+
end
|
57
|
+
end
|
58
|
+
xml['pic'].spPr( 'bwMode' => "auto" ) do
|
59
|
+
xml['a'].xfrm do
|
60
|
+
xml['a'].off( 'x' => 0, 'y' => 0 )
|
61
|
+
xml['a'].ext( 'cx' => ( options[:width] * options[:height] * 14.92 ).to_i, 'cy' => ( options[:width] * options[:height] * 14.92).to_i ) if options[:width] && options[:height]
|
62
|
+
end
|
63
|
+
xml['a'].prstGeom( 'prst' => "rect" ) do
|
64
|
+
xml['a'].avLst
|
65
|
+
end
|
66
|
+
xml['a'].noFill
|
67
|
+
xml['a'].ln('w' => "9525") do
|
68
|
+
xml['a'].noFill
|
69
|
+
xml['a'].miter('lim'=>"800000")
|
70
|
+
xml['a'].headEnd
|
71
|
+
xml['a'].tailEnd
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
else
|
80
|
+
xml['w'].pict do
|
81
|
+
unless options[:fill_color]
|
82
|
+
xml['v'].rect( 'id' => @media.uniq_id, 'type' => @media.type, 'style' => styles, :stroked => "f" ) do
|
83
|
+
xml['v'].imagedata( 'r:id' => @media.sequence, 'o:title' => @options[:title] )
|
84
|
+
xml['v'].wrap('v:type' => 'none') if options[:wrap]
|
85
|
+
end
|
86
|
+
else
|
87
|
+
xml['v'].rect("fillcolor"=> options[:fill_color], 'id' => @media.uniq_id, 'type' => @media.type, 'style' => styles, :stroked => "f" ) do
|
88
|
+
if options[:opacity].present?
|
89
|
+
xml['v'].fill("opacity" => options[:opacity])
|
90
|
+
end
|
91
|
+
xml['v'].imagedata( 'r:id' => @media.sequence, 'o:title' => @options[:title] )
|
92
|
+
xml['v'].wrap('v:type' => 'none') if options[:wrap]
|
93
|
+
end
|
94
|
+
end
|
28
95
|
end
|
29
|
-
end
|
30
|
-
xml['w'].rPr do
|
31
|
-
xml['w'].noProof
|
32
96
|
end
|
33
97
|
end
|
34
98
|
end
|
@@ -4,10 +4,11 @@ module Docxi
|
|
4
4
|
|
5
5
|
class Paragraph
|
6
6
|
|
7
|
-
attr_accessor :content, :options
|
7
|
+
attr_accessor :content, :options, :relationships, :id
|
8
8
|
def initialize(options={})
|
9
9
|
@content = []
|
10
10
|
@options = options
|
11
|
+
@relationships = []
|
11
12
|
|
12
13
|
if block_given?
|
13
14
|
yield self
|
@@ -16,16 +17,70 @@ module Docxi
|
|
16
17
|
end
|
17
18
|
end
|
18
19
|
|
20
|
+
def content_type
|
21
|
+
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink"
|
22
|
+
end
|
23
|
+
|
24
|
+
def target
|
25
|
+
"document.xml"
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
def hyperlink(text,link,id)
|
30
|
+
text = Hyperlink.new(text, link, id)
|
31
|
+
@content << text
|
32
|
+
end
|
33
|
+
|
34
|
+
class Hyperlink
|
35
|
+
attr_accessor :text, :link, :id
|
36
|
+
def initialize(text, link, id )
|
37
|
+
@text = text
|
38
|
+
@link = link
|
39
|
+
@id = id
|
40
|
+
end
|
41
|
+
|
42
|
+
def content_type
|
43
|
+
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink"
|
44
|
+
end
|
45
|
+
|
46
|
+
def render(xml)
|
47
|
+
xml['w'].pPr do
|
48
|
+
xml['w'].pStyle('w:val' => "Normal")
|
49
|
+
xml['w'].rPr do
|
50
|
+
xml['w'].rStyle('w:val' => "InternetLink")
|
51
|
+
end
|
52
|
+
end
|
53
|
+
xml['w'].hyperlink('r:id' => @id) do
|
54
|
+
xml['w'].r do
|
55
|
+
xml['w'].rPr do
|
56
|
+
xml['w'].rStyle( 'w:val' => "InternetLink")
|
57
|
+
end
|
58
|
+
xml['w'].t @text
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
19
64
|
def render(xml)
|
20
65
|
xml['w'].p do
|
21
66
|
xml['w'].pPr do
|
22
67
|
xml['w'].jc( 'w:val' => @options[:align]) if @options[:align]
|
68
|
+
xml['w'].shd( 'w:val' => 'clear','w:fill' => @options[:fill] ) if @options[:fill]
|
69
|
+
xml['w'].ind( 'w:left' => @options[:left], 'w:right' => @options[:right] ) if @options[:left] and @options[:right]
|
23
70
|
if options[:ul]
|
24
71
|
xml['w'].numPr do
|
25
72
|
xml['w'].ilvl( 'w:val' => 0 )
|
26
73
|
xml['w'].numId( 'w:val' => 1 )
|
27
74
|
end
|
28
75
|
end
|
76
|
+
if options[:bottom]
|
77
|
+
xml['w'].pBdr do
|
78
|
+
xml['w'].top( 'w:val' => "nil")
|
79
|
+
xml['w'].left('w:val' => "nil")
|
80
|
+
xml['w'].bottom('w:val'=>"single", 'w:sz'=>"4", 'w:space'=>"1", 'w:color'=>"000000")
|
81
|
+
xml['w'].right('w:val'=>"nil")
|
82
|
+
end
|
83
|
+
end
|
29
84
|
end
|
30
85
|
@content.each do |element|
|
31
86
|
element.render(xml)
|
@@ -40,12 +95,24 @@ module Docxi
|
|
40
95
|
text
|
41
96
|
end
|
42
97
|
|
98
|
+
def frame(options={}, &block)
|
99
|
+
element = Docxi::Word::Contents::Frame.new(options, &block)
|
100
|
+
@content << element
|
101
|
+
element
|
102
|
+
end
|
103
|
+
|
43
104
|
def br(options={})
|
44
105
|
br = Docxi::Word::Contents::Break.new(options)
|
45
106
|
@content << br
|
46
107
|
br
|
47
108
|
end
|
48
109
|
|
110
|
+
def tab(options={})
|
111
|
+
tab = Docxi::Word::Contents::Tab.new(options)
|
112
|
+
@content << tab
|
113
|
+
tab
|
114
|
+
end
|
115
|
+
|
49
116
|
def image(image, options={})
|
50
117
|
img = Docxi::Word::Contents::Image.new(image, options)
|
51
118
|
@content << img
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Docxi
|
2
|
+
module Word
|
3
|
+
module Contents
|
4
|
+
|
5
|
+
class Tab
|
6
|
+
|
7
|
+
attr_accessor :options
|
8
|
+
def initialize(options={})
|
9
|
+
@options = options
|
10
|
+
@options[:times] ||= 1
|
11
|
+
end
|
12
|
+
|
13
|
+
def render(xml)
|
14
|
+
if @options[:page]
|
15
|
+
xml['w'].p do
|
16
|
+
xml['w'].r do
|
17
|
+
xml['w'].tab
|
18
|
+
end
|
19
|
+
end
|
20
|
+
else
|
21
|
+
@options[:times].times do
|
22
|
+
xml['w'].r do
|
23
|
+
xml['w'].tab
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -28,6 +28,8 @@ module Docxi
|
|
28
28
|
xml['w'].tblPr do
|
29
29
|
xml['w'].tblStyle( 'w:val' => options[:style] ) if options[:style]
|
30
30
|
xml['w'].tblW( 'w:w' => options[:width], 'w:type' => "auto" ) if options[:width]
|
31
|
+
xml['w'].jc( 'w:val' => options[:align] ) if options[:align]
|
32
|
+
xml['w'].tblInd( 'w:w' => options[:iwidth], 'w:type' => "dxa" ) if options[:iwidth]
|
31
33
|
xml['w'].tblLook( 'w:val' => "04A0", 'w:firstRow' => 1, 'w:lastRow' => 0, 'w:firstColumn' => 1, 'w:lastColumn' => 0, 'w:noHBand' => 0, 'w:noVBand' => 1 )
|
32
34
|
if @options[:borders]
|
33
35
|
xml['w'].tblBorders do
|
@@ -40,6 +42,15 @@ module Docxi
|
|
40
42
|
end
|
41
43
|
end
|
42
44
|
end
|
45
|
+
if @options[:padding]
|
46
|
+
xml['w'].tblCellMar do
|
47
|
+
xml['w'].top( 'w:w' => "288", 'w:type' => "dxa" )
|
48
|
+
xml['w'].left( 'w:w' => "573", 'w:type' => "dxa" )
|
49
|
+
xml['w'].bottom( 'w:w' => "288", 'w:type' => "dxa" )
|
50
|
+
xml['w'].right( 'w:w' => "573", 'w:type' => "dxa" )
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
43
54
|
end
|
44
55
|
xml['w'].tblGrid do
|
45
56
|
if options[:columns_width]
|
@@ -81,6 +92,12 @@ module Docxi
|
|
81
92
|
|
82
93
|
def render(xml)
|
83
94
|
xml['w'].tr do
|
95
|
+
if options[:height].present?
|
96
|
+
xml['w'].trPr do
|
97
|
+
xml['w'].trHeight('w:val' => options[:height], 'w:hRule' => 'atLeast')
|
98
|
+
xml['w'].cantSplit('w:val' => 'false')
|
99
|
+
end
|
100
|
+
end
|
84
101
|
@cells.each do |cell|
|
85
102
|
cell.render(xml)
|
86
103
|
end
|
@@ -102,6 +119,9 @@ module Docxi
|
|
102
119
|
end
|
103
120
|
|
104
121
|
def render(xml)
|
122
|
+
if options[:fill].blank?
|
123
|
+
options[:fill] = 'FFFFFF'
|
124
|
+
end
|
105
125
|
xml['w'].tc do
|
106
126
|
xml['w'].tcPr do
|
107
127
|
xml['w'].tcW( 'w:w' => ( options[:width].to_i * 14.92 ).to_i, 'w:type' => "dxa" ) if options[:width]
|
@@ -150,6 +170,18 @@ module Docxi
|
|
150
170
|
img
|
151
171
|
end
|
152
172
|
|
173
|
+
def page_numbers
|
174
|
+
numbers = PageNumbers.new
|
175
|
+
@content << numbers
|
176
|
+
numbers
|
177
|
+
end
|
178
|
+
|
179
|
+
def p(options={}, &block)
|
180
|
+
element = Docxi::Word::Contents::Paragraph.new(options, &block)
|
181
|
+
@content << element
|
182
|
+
element
|
183
|
+
end
|
184
|
+
|
153
185
|
class Image
|
154
186
|
attr_accessor :media, :options
|
155
187
|
def initialize(media, options={})
|
@@ -215,6 +247,54 @@ module Docxi
|
|
215
247
|
end
|
216
248
|
end
|
217
249
|
end
|
250
|
+
|
251
|
+
class PageNumbers
|
252
|
+
|
253
|
+
attr_accessor :options
|
254
|
+
def initialize(options={})
|
255
|
+
@options = options
|
256
|
+
end
|
257
|
+
|
258
|
+
def render(xml)
|
259
|
+
xml['w'].sdt do
|
260
|
+
xml['w'].sdtPr do
|
261
|
+
xml['w'].id( 'w:val' => "-472213903" )
|
262
|
+
xml['w'].docPartObj do
|
263
|
+
xml['w'].docPartGallery( 'w:val' => "Page Numbers (Bottom of Page)" )
|
264
|
+
xml['w'].docPartUnique
|
265
|
+
end
|
266
|
+
end
|
267
|
+
xml['w'].sdtContent do
|
268
|
+
xml['w'].p do
|
269
|
+
xml['w'].pPr do
|
270
|
+
xml['w'].jc( 'w:val' => @options[:align] || 'right' )
|
271
|
+
end
|
272
|
+
xml['w'].r do
|
273
|
+
xml['w'].rPr do
|
274
|
+
xml['w'].rFonts( 'w:cs'=> 'Arial', 'w:ascii'=> 'Arial', 'w:hAnsi' => 'Arial' )
|
275
|
+
xml['w'].color( 'w:val' => '404040')
|
276
|
+
xml['w'].sz( 'w:val' => '20' )
|
277
|
+
end
|
278
|
+
xml['w'].t 'GlobalOptions '
|
279
|
+
end
|
280
|
+
xml['w'].r do
|
281
|
+
xml['w'].fldChar( 'w:fldCharType' => "begin" )
|
282
|
+
end
|
283
|
+
xml['w'].r do
|
284
|
+
xml['w'].instrText "PAGE \* MERGEFORMAT"
|
285
|
+
end
|
286
|
+
xml['w'].r do
|
287
|
+
xml['w'].fldChar( 'w:fldCharType' => "separate" )
|
288
|
+
end
|
289
|
+
xml['w'].r do
|
290
|
+
xml['w'].fldChar( 'w:fldCharType' => "end" )
|
291
|
+
end
|
292
|
+
end
|
293
|
+
end
|
294
|
+
end
|
295
|
+
end
|
296
|
+
end
|
297
|
+
|
218
298
|
end
|
219
299
|
end
|
220
300
|
end
|
@@ -14,13 +14,19 @@ module Docxi
|
|
14
14
|
if !@text.nil?
|
15
15
|
xml['w'].r do
|
16
16
|
xml['w'].rPr do
|
17
|
+
xml['w'].rFonts( 'w:cs'=> @options[:font], 'w:ascii'=> @options[:font], 'w:hAnsi' => @options[:font] ) if @options[:font]
|
17
18
|
xml['w'].b if @options[:bold]
|
18
19
|
xml['w'].i if @options[:italic]
|
19
20
|
xml['w'].u( 'w:val' => "single" ) if options[:underline]
|
20
21
|
xml['w'].color( 'w:val' => @options[:color] ) if @options[:color]
|
21
22
|
xml['w'].sz( 'w:val' => @options[:size].to_i * 2 ) if @options[:size]
|
23
|
+
xml['w'].shd( 'w:val' => 'clear','w:fill' => @options[:fill] ) if @options[:fill]
|
24
|
+
end
|
25
|
+
if @options[:space]
|
26
|
+
xml['w'].t( @text, 'xml:space' => "preserve" )
|
27
|
+
else
|
28
|
+
xml['w'].t @text
|
22
29
|
end
|
23
|
-
xml['w'].t @text
|
24
30
|
end
|
25
31
|
if options[:br]
|
26
32
|
br = Docxi::Word::Contents::Break.new
|
data/lib/docxi/word/document.rb
CHANGED
@@ -1,10 +1,12 @@
|
|
1
|
+
require_relative 'hyperlinks/hyperlink.rb'
|
2
|
+
require_relative 'hyperlinks.rb'
|
1
3
|
module Docxi
|
2
4
|
module Word
|
3
5
|
class Document
|
4
6
|
|
5
7
|
include Helpers
|
6
8
|
|
7
|
-
attr_accessor :options, :fonts, :setings, :styles, :numbering, :effects, :web_settings, :themes, :relationships, :footnotes, :endnotes, :footers, :headers
|
9
|
+
attr_accessor :options, :fonts, :setings, :styles, :numbering, :effects, :web_settings, :themes, :relationships, :footnotes, :endnotes, :footers, :headers, :hyperlinks
|
8
10
|
|
9
11
|
def initialize(options)
|
10
12
|
@options = options
|
@@ -26,6 +28,22 @@ module Docxi
|
|
26
28
|
@footer = footer
|
27
29
|
end
|
28
30
|
|
31
|
+
def add_first_footer(footer, options={})
|
32
|
+
footer.id = footers.sequence
|
33
|
+
rel = relationships.add(footer.content_type, footer.target)
|
34
|
+
footer.sequence = rel.id
|
35
|
+
footers.add(footer)
|
36
|
+
@first_footer = footer
|
37
|
+
end
|
38
|
+
|
39
|
+
def add_first_header(header, options={})
|
40
|
+
header.id = headers.sequence
|
41
|
+
rel = relationships.add(header.content_type, header.target)
|
42
|
+
header.sequence = rel.id
|
43
|
+
headers.add(header)
|
44
|
+
@first_header = header
|
45
|
+
end
|
46
|
+
|
29
47
|
def add_header(header, options={})
|
30
48
|
header.id = headers.sequence
|
31
49
|
rel = relationships.add(header.content_type, header.target)
|
@@ -34,6 +52,14 @@ module Docxi
|
|
34
52
|
@header = header
|
35
53
|
end
|
36
54
|
|
55
|
+
def add_hyperlink(link, options={})
|
56
|
+
hyperlink = Hyperlinks::Hyperlink.new(hyperlinks.sequence, options)
|
57
|
+
rel = relationships.add(hyperlink.content_type, link, 'External')
|
58
|
+
hyperlink.set_sequence(rel.id)
|
59
|
+
hyperlinks.add(hyperlink)
|
60
|
+
return rel.id
|
61
|
+
end
|
62
|
+
|
37
63
|
def fonts
|
38
64
|
@fonts ||= Fonts.new
|
39
65
|
end
|
@@ -82,10 +108,22 @@ module Docxi
|
|
82
108
|
@footers ||= Footers.new
|
83
109
|
end
|
84
110
|
|
111
|
+
def first_footer
|
112
|
+
@first_footer ||= Footers.new
|
113
|
+
end
|
114
|
+
|
115
|
+
def first_header
|
116
|
+
@first_header ||= Headers.new
|
117
|
+
end
|
118
|
+
|
85
119
|
def headers
|
86
120
|
@headers ||= Headers.new
|
87
121
|
end
|
88
122
|
|
123
|
+
def hyperlinks
|
124
|
+
@hyperlinks ||= Hyperlinks.new
|
125
|
+
end
|
126
|
+
|
89
127
|
def render(zip)
|
90
128
|
zip.put_next_entry('word/document.xml')
|
91
129
|
zip.write(Docxi.to_xml(document))
|
@@ -108,7 +146,7 @@ module Docxi
|
|
108
146
|
private
|
109
147
|
def document
|
110
148
|
Nokogiri::XML::Builder.with(Nokogiri::XML('<?xml version="1.0" encoding="UTF-8" standalone="yes"?>')) do |xml|
|
111
|
-
xml.document('xmlns:
|
149
|
+
xml.document('xmlns:o' => 'urn:schemas-microsoft-com:office:office', 'xmlns:r' => 'http://schemas.openxmlformats.org/officeDocument/2006/relationships' ,'xmlns:v' => 'urn:schemas-microsoft-com:vml', 'xmlns:w' => 'http://schemas.openxmlformats.org/wordprocessingml/2006/main', 'xmlns:w10' =>'urn:schemas-microsoft-com:office:word', 'xmlns:wp' =>'http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing') do
|
112
150
|
xml.parent.namespace = xml.parent.namespace_definitions.find{|ns| ns.prefix == "w" }
|
113
151
|
|
114
152
|
xml['w'].body do
|
@@ -122,11 +160,13 @@ module Docxi
|
|
122
160
|
xml['w'].bookmarkEnd('w:id' => "0")
|
123
161
|
end
|
124
162
|
xml['w'].sectPr do
|
125
|
-
xml['w'].footerReference( 'w:type' => "default", 'r:id' => @footer.sequence ) if @footer
|
126
163
|
xml['w'].headerReference( 'w:type' => "default", 'r:id' => @header.sequence ) if @header
|
164
|
+
xml['w'].headerReference( 'w:type' => "first", 'r:id' => @first_header.sequence ) if @first_header
|
165
|
+
xml['w'].footerReference( 'w:type' => "default", 'r:id' => @footer.sequence ) if @footer
|
166
|
+
xml['w'].footerReference( 'w:type' => "first", 'r:id' => @first_footer.sequence ) if @first_footer
|
127
167
|
xml['w'].titlePg
|
128
168
|
xml['w'].pgSz( 'w:w' => 12240, 'w:h' => 15840 )
|
129
|
-
xml['w'].pgMar( 'w:top' =>
|
169
|
+
xml['w'].pgMar( 'w:top' => @options[:top], 'w:right' => @options[:right], 'w:bottom' => @options[:bottom], 'w:left' => @options[:left], 'w:header' => @options[:header].present? ? @options[:header] : 190, 'w:footer' => @options[:footer].present? ? @options[:footer] : 200 , 'w:gutter' => 0)
|
130
170
|
xml['w'].cols( 'w:space' => 720)
|
131
171
|
xml['w'].docGrid( 'w:linePitch' => "360")
|
132
172
|
end
|
@@ -18,6 +18,12 @@ module Docxi
|
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
21
|
+
def br(options={})
|
22
|
+
br = Docxi::Word::Contents::Break.new(options)
|
23
|
+
@content << br
|
24
|
+
br
|
25
|
+
end
|
26
|
+
|
21
27
|
def content_type
|
22
28
|
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/footer"
|
23
29
|
end
|
@@ -45,12 +51,18 @@ module Docxi
|
|
45
51
|
element
|
46
52
|
end
|
47
53
|
|
48
|
-
def page_numbers
|
49
|
-
numbers = PageNumbers.new
|
54
|
+
def page_numbers(options={})
|
55
|
+
numbers = PageNumbers.new(options)
|
50
56
|
@content << numbers
|
51
57
|
numbers
|
52
58
|
end
|
53
59
|
|
60
|
+
def table(options={}, &block)
|
61
|
+
table = Docxi::Word::Contents::Table.new(options, &block)
|
62
|
+
@content << table
|
63
|
+
table
|
64
|
+
end
|
65
|
+
|
54
66
|
class PageNumbers
|
55
67
|
|
56
68
|
attr_accessor :options
|
@@ -72,6 +84,14 @@ module Docxi
|
|
72
84
|
xml['w'].pPr do
|
73
85
|
xml['w'].jc( 'w:val' => @options[:align] || 'right' )
|
74
86
|
end
|
87
|
+
xml['w'].r do
|
88
|
+
xml['w'].rPr do
|
89
|
+
xml['w'].rFonts( 'w:cs'=> 'Arial', 'w:ascii'=> 'Arial', 'w:hAnsi' => 'Arial' )
|
90
|
+
xml['w'].color( 'w:val' => '404040')
|
91
|
+
xml['w'].sz( 'w:val' => '20' )
|
92
|
+
end
|
93
|
+
xml['w'].t @options[:name].to_s+' '
|
94
|
+
end
|
75
95
|
xml['w'].r do
|
76
96
|
xml['w'].fldChar( 'w:fldCharType' => "begin" )
|
77
97
|
end
|
@@ -43,11 +43,38 @@ module Docxi
|
|
43
43
|
img
|
44
44
|
end
|
45
45
|
|
46
|
+
def text(text, options={})
|
47
|
+
options = @options.merge(options)
|
48
|
+
element = Docxi::Word::Contents::Paragraph.new(options) do |p|
|
49
|
+
p.text(text)
|
50
|
+
end
|
51
|
+
@content << element
|
52
|
+
element
|
53
|
+
end
|
54
|
+
|
55
|
+
def page_numbers
|
56
|
+
numbers = PageNumbers.new
|
57
|
+
@content << numbers
|
58
|
+
numbers
|
59
|
+
end
|
60
|
+
|
61
|
+
def br(options={})
|
62
|
+
br = Docxi::Word::Contents::Break.new(options)
|
63
|
+
@content << br
|
64
|
+
br
|
65
|
+
end
|
66
|
+
|
67
|
+
def table(options={}, &block)
|
68
|
+
table = Docxi::Word::Contents::Table.new(options, &block)
|
69
|
+
@content << table
|
70
|
+
table
|
71
|
+
end
|
72
|
+
|
46
73
|
class Image
|
47
74
|
attr_accessor :media, :options
|
48
75
|
def initialize(media, options={})
|
49
76
|
@media = media
|
50
|
-
@media.file.rewind
|
77
|
+
# @media.file.rewind
|
51
78
|
@options = options
|
52
79
|
end
|
53
80
|
|
@@ -69,23 +96,35 @@ module Docxi
|
|
69
96
|
xml['w'].noProof
|
70
97
|
end
|
71
98
|
xml['w'].drawing do
|
72
|
-
xml['wp'].
|
73
|
-
xml['wp'].
|
74
|
-
xml['wp'].
|
99
|
+
xml['wp'].anchor( "behindDoc" => options[:behind] ,"distT" => 0,"distB" => 0, "distL" => 0, "distR" => 0 ,"simplePos" => 0 ,"locked" => 0, "layoutInCell" => 1, "allowOverlap" => 1, "relativeHeight" => 4) do
|
100
|
+
xml['wp'].simplePos('x'=> 0 , 'y' => 0 )
|
101
|
+
xml['wp'].positionH("relativeFrom" => "column") do
|
102
|
+
xml['wp'].posOffset options[:pH]
|
103
|
+
end
|
104
|
+
xml['wp'].positionV("relativeFrom" => "paragraph") do
|
105
|
+
xml['wp'].posOffset options[:pV]
|
106
|
+
end
|
107
|
+
xml['wp'].extent( 'cx' => ( options[:width] * options[:height] * 14.92 ).to_i, 'cy' => ( options[:width] * options[:height] * 14.92 ).to_i ) if options[:width] && options[:height]
|
108
|
+
xml['wp'].effectExtent( 'l' => 0, 't' => 0, 'r' => 0, 'b' => 0 )
|
109
|
+
if options[:wrap] == "none"
|
110
|
+
xml['wp'].wrapNone
|
111
|
+
else
|
112
|
+
xml['wp'].wrapSquare("wrapText"=> "bothSides")
|
113
|
+
end
|
75
114
|
xml['wp'].docPr( 'id' => 1, 'name'=> "Image", 'descr' => "image")
|
76
115
|
xml['wp'].cNvGraphicFramePr do
|
77
|
-
xml.graphicFrameLocks( 'xmlns:a' => "http://schemas.openxmlformats.org/drawingml/2006/main", 'noChangeAspect' => 1 ) do
|
116
|
+
xml.graphicFrameLocks( 'xmlns:a' => "http://schemas.openxmlformats.org/drawingml/2006/main", 'noChangeAspect' => "1" ) do
|
78
117
|
xml.parent.namespace = xml.parent.namespace_definitions.find{|ns| ns.prefix == "a" }
|
79
118
|
end
|
80
119
|
end
|
81
120
|
xml.graphic( 'xmlns:a' => "http://schemas.openxmlformats.org/drawingml/2006/main" ) do
|
82
121
|
xml.parent.namespace = xml.parent.namespace_definitions.find{|ns| ns.prefix == "a" }
|
83
122
|
xml['a'].graphicData( 'uri' => "http://schemas.openxmlformats.org/drawingml/2006/picture") do
|
84
|
-
xml.pic( 'xmlns:pic' => "http://schemas.openxmlformats.org/drawingml/2006/picture"
|
123
|
+
xml.pic( 'xmlns:pic' => "http://schemas.openxmlformats.org/drawingml/2006/picture") do
|
85
124
|
xml.parent.namespace = xml.parent.namespace_definitions.find{|ns| ns.prefix == "pic" }
|
86
125
|
xml['pic'].nvPicPr do
|
87
126
|
xml['pic'].cNvPr( 'id' => 0, 'name' => "Image" )
|
88
|
-
xml['pic'].cNvPicPr
|
127
|
+
xml['pic'].cNvPicPr
|
89
128
|
end
|
90
129
|
xml['pic'].blipFill do
|
91
130
|
xml['a'].blip( 'r:embed' => @media.sequence ) do
|
@@ -95,14 +134,21 @@ module Docxi
|
|
95
134
|
xml['a'].fillRect
|
96
135
|
end
|
97
136
|
end
|
98
|
-
xml['pic'].spPr do
|
137
|
+
xml['pic'].spPr( 'bwMode' => "auto" ) do
|
99
138
|
xml['a'].xfrm do
|
100
139
|
xml['a'].off( 'x' => 0, 'y' => 0 )
|
101
|
-
xml['a'].ext( 'cx' => ( width *
|
140
|
+
xml['a'].ext( 'cx' => ( options[:width] * options[:height] * 14.92 ).to_i, 'cy' => ( options[:width] * options[:height] * 14.92).to_i ) if options[:width] && options[:height]
|
102
141
|
end
|
103
142
|
xml['a'].prstGeom( 'prst' => "rect" ) do
|
104
143
|
xml['a'].avLst
|
105
144
|
end
|
145
|
+
# xml['a'].noFill
|
146
|
+
# xml['a'].ln('w' => "9525") do
|
147
|
+
# xml['a'].noFill
|
148
|
+
# xml['a'].miter('lim'=>"800000")
|
149
|
+
# xml['a'].headEnd
|
150
|
+
# xml['a'].tailEnd
|
151
|
+
# end
|
106
152
|
end
|
107
153
|
end
|
108
154
|
end
|
data/lib/docxi/word/helpers.rb
CHANGED
@@ -8,12 +8,24 @@ module Docxi
|
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
11
|
+
def frame(text, options={})
|
12
|
+
p(options) do |p|
|
13
|
+
p.frame text
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
11
17
|
def br(options={})
|
12
18
|
element = Docxi::Word::Contents::Break.new(options)
|
13
19
|
@content << element
|
14
20
|
element
|
15
21
|
end
|
16
22
|
|
23
|
+
def tab(options={})
|
24
|
+
element = Docxi::Word::Contents::Tab.new(options)
|
25
|
+
@content << element
|
26
|
+
element
|
27
|
+
end
|
28
|
+
|
17
29
|
def p(options={}, &block)
|
18
30
|
element = Docxi::Word::Contents::Paragraph.new(options, &block)
|
19
31
|
@content << element
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'docxi/word/hyperlinks/hyperlink'
|
2
|
+
|
3
|
+
module Docxi
|
4
|
+
module Word
|
5
|
+
class Hyperlinks
|
6
|
+
|
7
|
+
attr_accessor :hyperlinks, :counter
|
8
|
+
def initialize
|
9
|
+
@hyperlinks = []
|
10
|
+
@counter = 0
|
11
|
+
end
|
12
|
+
|
13
|
+
def add(hyperlink)
|
14
|
+
@hyperlinks << hyperlink
|
15
|
+
hyperlink
|
16
|
+
end
|
17
|
+
|
18
|
+
def sequence
|
19
|
+
@counter += 1
|
20
|
+
end
|
21
|
+
|
22
|
+
def render(zip)
|
23
|
+
@hyperlinks.each do |hyperlink|
|
24
|
+
hyperlink.render(zip)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
#encoding: utf-8
|
2
|
+
|
3
|
+
module Docxi
|
4
|
+
module Word
|
5
|
+
class Hyperlinks
|
6
|
+
class Hyperlink
|
7
|
+
|
8
|
+
attr_accessor :id, :sequence
|
9
|
+
def initialize(id,options={})
|
10
|
+
@options = options
|
11
|
+
@id = id
|
12
|
+
|
13
|
+
if block_given?
|
14
|
+
yield self
|
15
|
+
else
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def set_sequence(sequence)
|
21
|
+
@sequence = sequence
|
22
|
+
self
|
23
|
+
end
|
24
|
+
|
25
|
+
def content_type
|
26
|
+
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink"
|
27
|
+
end
|
28
|
+
|
29
|
+
def target
|
30
|
+
"document.xml"
|
31
|
+
end
|
32
|
+
|
33
|
+
def render(zip)
|
34
|
+
zip.put_next_entry("word/#{target}")
|
35
|
+
zip.write(Docxi.to_xml(document))
|
36
|
+
if !@relationships.empty?
|
37
|
+
zip.put_next_entry("word/_rels/#{target}.rels")
|
38
|
+
zip.write(Docxi.to_xml(relationships))
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def hyperlink(text,link)
|
43
|
+
text = Hyperlink.new(text, link, id)
|
44
|
+
@content << text
|
45
|
+
end
|
46
|
+
|
47
|
+
class Hyperlink
|
48
|
+
attr_accessor :text, :link
|
49
|
+
def initialize(text, link )
|
50
|
+
@text = text
|
51
|
+
@link = link
|
52
|
+
end
|
53
|
+
|
54
|
+
def content_type
|
55
|
+
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink"
|
56
|
+
end
|
57
|
+
|
58
|
+
def render(xml)
|
59
|
+
xml['w'].hyperlink('w:id' => '1') do
|
60
|
+
xml['w'].r do
|
61
|
+
xml['w'].pPr do
|
62
|
+
xml['w'].rStyle( 'w:val' => "InternetLink")
|
63
|
+
end
|
64
|
+
xml['w'].t @text
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
|
71
|
+
private
|
72
|
+
def document
|
73
|
+
Nokogiri::XML::Builder.with(Nokogiri::XML('<?xml version="1.0" encoding="UTF-8" standalone="yes"?>')) do |xml|
|
74
|
+
xml.hdr( 'xmlns:wpc' => "http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas", 'xmlns:mc' => "http://schemas.openxmlformats.org/markup-compatibility/2006", 'xmlns:o' => "urn:schemas-microsoft-com:office:office", 'xmlns:r' => "http://schemas.openxmlformats.org/officeDocument/2006/relationships", 'xmlns:m' => "http://schemas.openxmlformats.org/officeDocument/2006/math", 'xmlns:v' => "urn:schemas-microsoft-com:vml", 'xmlns:wp14' => "http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing", 'xmlns:wp' => "http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing", 'xmlns:w10' => "urn:schemas-microsoft-com:office:word", 'xmlns:w' => "http://schemas.openxmlformats.org/wordprocessingml/2006/main", 'xmlns:w14' => "http://schemas.microsoft.com/office/word/2010/wordml", 'xmlns:wpg' => "http://schemas.microsoft.com/office/word/2010/wordprocessingGroup", 'xmlns:wpi' => "http://schemas.microsoft.com/office/word/2010/wordprocessingInk", 'xmlns:wne' => "http://schemas.microsoft.com/office/word/2006/wordml", 'xmlns:wps' => "http://schemas.microsoft.com/office/word/2010/wordprocessingShape", 'mc:Ignorable' => "w14 wp14" ) do
|
75
|
+
xml.parent.namespace = xml.parent.namespace_definitions.find{|ns| ns.prefix == "w" }
|
76
|
+
@content.each do |element|
|
77
|
+
element.render(xml)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def relationships
|
84
|
+
Nokogiri::XML::Builder.with(Nokogiri::XML('<?xml version="1.0" encoding="UTF-8" standalone="yes"?>')) do |xml|
|
85
|
+
xml.Relationships(xmlns: 'http://schemas.openxmlformats.org/package/2006/relationships') do
|
86
|
+
@relationships.each do |relationship|
|
87
|
+
xml.Relationship('Id' => relationship.sequence, 'Type' => relationship.content_type, 'Target' => relationship.target)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
data/lib/docxi/word/medias.rb
CHANGED
@@ -22,7 +22,13 @@ module Docxi
|
|
22
22
|
def render(zip)
|
23
23
|
@medias.each do |media|
|
24
24
|
zip.put_next_entry("word/#{media.target}")
|
25
|
-
|
25
|
+
if media.file.class == String
|
26
|
+
file = open(media.file)
|
27
|
+
zip.write(file.read)
|
28
|
+
file.close
|
29
|
+
else
|
30
|
+
zip.write(media.file.read)
|
31
|
+
end
|
26
32
|
end
|
27
33
|
end
|
28
34
|
|
@@ -21,8 +21,8 @@ module Docxi
|
|
21
21
|
add("http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering", "numbering.xml")
|
22
22
|
end
|
23
23
|
|
24
|
-
def add(type, target)
|
25
|
-
relationship = create_relationship(sequence, type, target)
|
24
|
+
def add(type, target, tm = '')
|
25
|
+
relationship = create_relationship(sequence, type, target,tm)
|
26
26
|
@relationships << relationship if relationship
|
27
27
|
relationship
|
28
28
|
end
|
@@ -43,8 +43,8 @@ module Docxi
|
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
46
|
-
def create_relationship(id, type, target)
|
47
|
-
Relationship.new(id, type, target)
|
46
|
+
def create_relationship(id, type, target, tm = '')
|
47
|
+
Relationship.new(id, type, target, tm)
|
48
48
|
end
|
49
49
|
|
50
50
|
def sequence
|
@@ -3,16 +3,21 @@ module Docxi
|
|
3
3
|
class Relationships
|
4
4
|
class Relationship
|
5
5
|
|
6
|
-
attr_accessor :id, :type, :target
|
6
|
+
attr_accessor :id, :type, :target, :tm
|
7
7
|
|
8
|
-
def initialize(id, type, target)
|
8
|
+
def initialize(id, type, target, tm = '')
|
9
9
|
@id = id
|
10
10
|
@type = type
|
11
11
|
@target = target
|
12
|
+
@tm = tm
|
12
13
|
end
|
13
14
|
|
14
15
|
def build(xml)
|
15
|
-
|
16
|
+
if @tm.blank?
|
17
|
+
xml.Relationship('Id' => @id, 'Type' => @type, 'Target' => @target)
|
18
|
+
else
|
19
|
+
xml.Relationship('Id' => @id, 'Type' => @type, 'Target' => @target, 'TargetMode' => @tm)
|
20
|
+
end
|
16
21
|
end
|
17
22
|
|
18
23
|
end
|
data/lib/docxi/word/styles.rb
CHANGED
@@ -20,15 +20,16 @@ module Docxi
|
|
20
20
|
xml['w'].docDefaults do
|
21
21
|
xml['w'].rPrDefault do
|
22
22
|
xml['w'].rPr do
|
23
|
-
xml['w'].rFonts('w:asciiTheme' => "minorHAnsi", 'w:eastAsiaTheme' => "minorHAnsi", 'w:hAnsiTheme' => "minorHAnsi", 'w:cstheme' => "minorBidi")
|
24
|
-
xml['w'].
|
25
|
-
xml['w'].
|
23
|
+
# xml['w'].rFonts('w:asciiTheme' => "minorHAnsi", 'w:eastAsiaTheme' => "minorHAnsi", 'w:hAnsiTheme' => "minorHAnsi", 'w:cstheme' => "minorBidi")
|
24
|
+
xml['w'].rFonts( 'w:cs'=> 'Arial', 'w:ascii'=> 'Arial', 'w:hAnsi' => 'Arial' )
|
25
|
+
xml['w'].sz('w:val' => 24)
|
26
|
+
xml['w'].szCs('w:val' => 24)
|
26
27
|
xml['w'].lang('w:val' => "en-US", 'w:eastAsia' => "en-US", 'w:bidi' => "ar-SA")
|
27
28
|
end
|
28
29
|
end
|
29
30
|
xml['w'].pPrDefault do
|
30
31
|
xml['w'].pPr do
|
31
|
-
xml['w'].spacing(
|
32
|
+
xml['w'].spacing("w:lineRule"=>"atLeast", "w:line"=>"240")
|
32
33
|
end
|
33
34
|
end
|
34
35
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: docxi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Irfan Babar
|
@@ -67,8 +67,10 @@ files:
|
|
67
67
|
- lib/docxi/word.rb
|
68
68
|
- lib/docxi/word/contents.rb
|
69
69
|
- lib/docxi/word/contents/break.rb
|
70
|
+
- lib/docxi/word/contents/frame.rb
|
70
71
|
- lib/docxi/word/contents/image.rb
|
71
72
|
- lib/docxi/word/contents/paragraph.rb
|
73
|
+
- lib/docxi/word/contents/tab.rb
|
72
74
|
- lib/docxi/word/contents/table.rb
|
73
75
|
- lib/docxi/word/contents/table_of_content.rb
|
74
76
|
- lib/docxi/word/contents/text.rb
|
@@ -83,6 +85,8 @@ files:
|
|
83
85
|
- lib/docxi/word/headers.rb
|
84
86
|
- lib/docxi/word/headers/header.rb
|
85
87
|
- lib/docxi/word/helpers.rb
|
88
|
+
- lib/docxi/word/hyperlinks.rb
|
89
|
+
- lib/docxi/word/hyperlinks/hyperlink.rb
|
86
90
|
- lib/docxi/word/medias.rb
|
87
91
|
- lib/docxi/word/medias/media.rb
|
88
92
|
- lib/docxi/word/numbering.rb
|