docxify 0.0.5 → 0.0.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +19 -0
- data/README.md +18 -7
- data/lib/docxify/container.rb +7 -5
- data/lib/docxify/document.rb +25 -14
- data/lib/docxify/element/base.rb +3 -3
- data/lib/docxify/element/file.rb +4 -0
- data/lib/docxify/element/page_break.rb +0 -1
- data/lib/docxify/element/paragraph.rb +68 -20
- data/lib/docxify/element/table.rb +99 -1
- data/lib/docxify/element/table_cell.rb +66 -0
- data/lib/docxify/element/web_address.rb +20 -0
- data/lib/docxify/version.rb +1 -1
- data/lib/docxify.rb +11 -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: 9ce756578c53df736bb1a6641722c8915ccc6bfdf24ce19c21e4bd64624f8405
|
4
|
+
data.tar.gz: 62039225ee265819d72a6cd6ef64a6cd7150b89d99f93fc1a0dfcf7994cafa4c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 514adbdd7c383dc3a373f460b9c548b532e3885b16d75030e5a12e070a13d41e3addab9cbed4cd89794e2bb057e67599e44d1399981d5a6e94c9fb1c5747dc6c
|
7
|
+
data.tar.gz: d3d04f7f8ad20fcdc4478cfe07247f4dc1d687423d4df46336ffd742cbbf941846e8831b8344279db182c324e3eac515856937152162be89f84590c095d80f14
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,24 @@
|
|
1
1
|
# CHANGELOG
|
2
2
|
|
3
|
+
## 0.0.8
|
4
|
+
|
5
|
+
Features:
|
6
|
+
|
7
|
+
- Allow changing of following section's page layotu
|
8
|
+
|
9
|
+
## 0.0.7
|
10
|
+
|
11
|
+
Features:
|
12
|
+
|
13
|
+
- Table support
|
14
|
+
|
15
|
+
## 0.0.6
|
16
|
+
|
17
|
+
Features:
|
18
|
+
|
19
|
+
- Tab stops and hanging indents done
|
20
|
+
- Replacing of {CHECKBOX_EMPTY} and {CHECKBOX_CHECKED} with correct UTF-8 characters done
|
21
|
+
|
3
22
|
## 0.0.5
|
4
23
|
|
5
24
|
Features:
|
data/README.md
CHANGED
@@ -35,21 +35,32 @@ gem install docxify
|
|
35
35
|
@docx.add_paragraph "{CHECKBOX_EMPTY}\tEmpty checkbox", tab_stops_cm: [2]
|
36
36
|
@docx.add_paragraph "{CHECKBOX_CHECKED}\tChecked checkbox", tab_stops_cm: [2]
|
37
37
|
|
38
|
-
@docx.add_page_break
|
39
38
|
@docx.add_divider
|
40
39
|
|
41
40
|
@docx.add_image "file_path or data", align: :right, height_cm: 2, width_cm: 4
|
42
41
|
|
43
|
-
|
42
|
+
@docx.add_page_break
|
43
|
+
|
44
|
+
@docx.page_layout width: DocXify::A4_PORTRAIT_HEIGHT, height: DocXify::A4_PORTRAIT_WIDTH, orientation: :landscape
|
45
|
+
|
46
|
+
rows = []
|
47
|
+
rows << [
|
44
48
|
DocXify::Element::TableCell.new("<b>Header 1</b>"),
|
45
49
|
DocXify::Element::TableCell.new("<b>Header 2</b>")
|
50
|
+
DocXify::Element::TableCell.new("<b>Header 3</b>")
|
51
|
+
DocXify::Element::TableCell.new("<b>Header 4</b>", width_cm: 10)
|
52
|
+
]
|
53
|
+
rows << [
|
54
|
+
DocXify::Element::TableCell.new("Content 1", valign: :center, align: :left, nowrap: true, colspan: 3),
|
55
|
+
DocXify::Element::TableCell.new("Rowspan <b>here</b>", rowspan: true) # merges until a "nil" cell
|
46
56
|
]
|
47
|
-
|
48
|
-
DocXify::Element::TableCell.new("
|
49
|
-
DocXify::Element::TableCell.new("
|
57
|
+
rows << [
|
58
|
+
DocXify::Element::TableCell.new("Secondary 1")
|
59
|
+
DocXify::Element::TableCell.new("Secondary 2")
|
60
|
+
DocXify::Element::TableCell.new("Secondary 3")
|
61
|
+
DocXify::Element::TableCell.new(nil) # Word requires that there's an empty cell merged with the previous rowspan
|
50
62
|
]
|
51
|
-
rows
|
52
|
-
@docx.add_table headers, rows, expand: :full
|
63
|
+
container.add_table rows
|
53
64
|
|
54
65
|
docx_binary_data = @docx.render
|
55
66
|
# or
|
data/lib/docxify/container.rb
CHANGED
@@ -39,9 +39,11 @@ module DocXify
|
|
39
39
|
zip.put_next_entry "word/_rels/document.xml.rels"
|
40
40
|
zip.write document_xml_rels
|
41
41
|
|
42
|
-
@document.
|
43
|
-
|
44
|
-
|
42
|
+
@document.relationships.each do |relation|
|
43
|
+
if relation.is_a?(DocXify::Element::File)
|
44
|
+
zip.put_next_entry "word/media/#{relation.filename}"
|
45
|
+
zip.write relation.data
|
46
|
+
end
|
45
47
|
end
|
46
48
|
end
|
47
49
|
|
@@ -64,8 +66,8 @@ module DocXify
|
|
64
66
|
<Relationship Id="rId4" Target="fontTable.xml" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable"/>
|
65
67
|
XML
|
66
68
|
|
67
|
-
@document.
|
68
|
-
xml <<
|
69
|
+
@document.relationships.each do |relation|
|
70
|
+
xml << relation.to_s
|
69
71
|
end
|
70
72
|
|
71
73
|
xml << "</Relationships>"
|
data/lib/docxify/document.rb
CHANGED
@@ -1,18 +1,19 @@
|
|
1
1
|
module DocXify
|
2
2
|
class Document
|
3
|
-
attr_accessor :font, :size, :color, :background
|
4
|
-
attr_reader :content, :
|
3
|
+
attr_accessor :font, :size, :color, :background, :margins, :page_layout
|
4
|
+
attr_reader :content, :relationships, :width
|
5
5
|
|
6
6
|
def initialize(options = {})
|
7
7
|
@content = []
|
8
|
-
@
|
8
|
+
@relationships = []
|
9
9
|
@width = options[:width] || A4_PORTRAIT_WIDTH
|
10
10
|
@height = options[:height] || A4_PORTRAIT_HEIGHT
|
11
|
+
@orientation = options[:orientation] || :portrait
|
11
12
|
@font = options[:font] || "Times New Roman"
|
12
13
|
@size = options[:size] || 12
|
13
14
|
@color = options[:color] || 12
|
14
15
|
@background = options[:background] if options[:background]
|
15
|
-
@margins = { top: 2, bottom: 2, left: 2, right: 2 }
|
16
|
+
@margins = { top: 2, bottom: 2, left: 2, right: 2 }.merge(options[:margins] || {})
|
16
17
|
end
|
17
18
|
|
18
19
|
def default_styling(options = {})
|
@@ -41,17 +42,21 @@ module DocXify
|
|
41
42
|
<w:body>
|
42
43
|
XML
|
43
44
|
|
45
|
+
# See the note in DocXify::Element::PageLayout for why it's not just handled the same as any other element
|
46
|
+
@page_layout = DocXify::Element::PageLayout.new(width: @width, height: @height, orientation: @orientatation, document: self)
|
47
|
+
|
44
48
|
@content.each do |element|
|
45
|
-
|
49
|
+
if element.is_a?(DocXify::Element::PageLayout)
|
50
|
+
xml << @page_layout.to_s
|
51
|
+
@page_layout = element
|
52
|
+
else
|
53
|
+
xml << element.to_s(container)
|
54
|
+
end
|
46
55
|
end
|
47
56
|
|
57
|
+
xml << @page_layout.to_s
|
58
|
+
|
48
59
|
xml << <<~XML
|
49
|
-
<w:sectPr >
|
50
|
-
<w:pgSz w:h="#{@height}" w:w="#{@width}"/>
|
51
|
-
<w:pgMar w:bottom="#{DocXify.cm2dxa @margins[:bottom]}" w:footer="708" w:gutter="0" w:header="708" w:left="#{DocXify.cm2dxa @margins[:left]}" w:right="#{DocXify.cm2dxa @margins[:right]}" w:top="#{DocXify.cm2dxa @margins[:top]}"/>
|
52
|
-
<w:cols w:space="708"/>
|
53
|
-
<w:docGrid w:linePitch="360"/>
|
54
|
-
</w:sectPr>
|
55
60
|
</w:body>
|
56
61
|
</w:document>
|
57
62
|
XML
|
@@ -74,7 +79,7 @@ module DocXify
|
|
74
79
|
|
75
80
|
def add_file(file_path_or_data)
|
76
81
|
file = DocXify::Element::File.new(file_path_or_data)
|
77
|
-
@
|
82
|
+
@relationships << file
|
78
83
|
file
|
79
84
|
end
|
80
85
|
|
@@ -82,6 +87,11 @@ module DocXify
|
|
82
87
|
add DocXify::Element::PageBreak.new
|
83
88
|
end
|
84
89
|
|
90
|
+
def add_page_layout(options = {})
|
91
|
+
options[:document] = self
|
92
|
+
add DocXify::Element::PageLayout.new(options)
|
93
|
+
end
|
94
|
+
|
85
95
|
def add_divider
|
86
96
|
add DocXify::Element::Divider.new
|
87
97
|
end
|
@@ -91,8 +101,9 @@ module DocXify
|
|
91
101
|
add DocXify::Element::Paragraph.new(text, options)
|
92
102
|
end
|
93
103
|
|
94
|
-
def add_table(
|
95
|
-
|
104
|
+
def add_table(rows, options = {})
|
105
|
+
options[:document] = self
|
106
|
+
add DocXify::Element::Table.new(rows, options)
|
96
107
|
end
|
97
108
|
end
|
98
109
|
end
|
data/lib/docxify/element/base.rb
CHANGED
@@ -22,7 +22,7 @@ module DocXify
|
|
22
22
|
if char == "<"
|
23
23
|
state = :tag
|
24
24
|
tag = ""
|
25
|
-
result << text
|
25
|
+
result << text unless text.empty?
|
26
26
|
text = ""
|
27
27
|
else
|
28
28
|
text << char
|
@@ -61,7 +61,7 @@ module DocXify
|
|
61
61
|
when :content # With the content of an HTML tag
|
62
62
|
if char == "<"
|
63
63
|
state = :tag
|
64
|
-
result.last[:content] = content
|
64
|
+
result.last[:content] = content
|
65
65
|
content = ""
|
66
66
|
else
|
67
67
|
content << char
|
@@ -71,7 +71,7 @@ module DocXify
|
|
71
71
|
last_char = char
|
72
72
|
end
|
73
73
|
|
74
|
-
result << text
|
74
|
+
result << text unless text.empty?
|
75
75
|
result
|
76
76
|
end
|
77
77
|
end
|
data/lib/docxify/element/file.rb
CHANGED
@@ -34,6 +34,10 @@ module DocXify
|
|
34
34
|
"image-#{Digest::SHA1.hexdigest(@data)[0, 8]}"
|
35
35
|
end
|
36
36
|
|
37
|
+
def to_s
|
38
|
+
"<Relationship Id=\"#{reference}\" Target=\"media/#{filename}\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/image\"/>"
|
39
|
+
end
|
40
|
+
|
37
41
|
def contains_png_image?(data)
|
38
42
|
data[0, 8] == PNG_SIGNATURE
|
39
43
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module DocXify
|
2
2
|
module Element
|
3
3
|
class Paragraph < Base
|
4
|
-
attr_accessor :text, :font, :size, :color, :background, :align, :inline_styling, :tab_stops_cm
|
4
|
+
attr_accessor :text, :font, :size, :color, :background, :align, :inline_styling, :tab_stops_cm, :hanging_cm
|
5
5
|
|
6
6
|
def initialize(text, options = {})
|
7
7
|
super()
|
@@ -14,38 +14,86 @@ module DocXify
|
|
14
14
|
@background = options[:background] if options[:background]
|
15
15
|
@background ||= @document&.background if @document&.background
|
16
16
|
@align = options[:align] || :left
|
17
|
-
@inline_styling = options[:inline_styling]
|
17
|
+
@inline_styling = options.key?(:inline_styling) ? options[:inline_styling] : true
|
18
18
|
@tab_stops_cm = options[:tab_stops_cm] || []
|
19
|
+
@hanging_cm = options[:hanging_cm] || 0
|
19
20
|
end
|
20
21
|
|
21
22
|
def to_s(_container = nil)
|
22
23
|
nodes = if @inline_styling
|
23
24
|
parse_simple_html(@text)
|
24
25
|
else
|
25
|
-
[@text]
|
26
|
+
[@text.gsub("<", "<").gsub(">", ">")]
|
26
27
|
end
|
27
28
|
|
28
29
|
xml = "<w:p>"
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
30
|
+
|
31
|
+
xml << "<w:pPr>"
|
32
|
+
xml << "<w:jc w:val=\"#{@align}\"/>" if @align != :left
|
33
|
+
|
34
|
+
if tab_stops_cm.any?
|
35
|
+
xml << "<w:tabs>"
|
36
|
+
tab_stops_cm.each do |stop|
|
37
|
+
xml << "<w:tab w:pos=\"#{DocXify.cm2dxa(stop)}\" w:val=\"left\"/>"
|
38
|
+
end
|
39
|
+
xml << "</w:tabs>"
|
40
|
+
end
|
41
|
+
|
42
|
+
if @hanging_cm&.positive?
|
43
|
+
xml << "<w:ind w:hanging=\"#{DocXify.cm2dxa(@hanging_cm)}\" w:left=\"#{DocXify.cm2dxa(@hanging_cm)}\"/>"
|
44
|
+
end
|
45
|
+
|
46
|
+
xml << "</w:pPr>"
|
44
47
|
|
45
48
|
nodes.each do |node|
|
46
|
-
|
49
|
+
if node.is_a?(Hash) && node[:tag] == "a"
|
50
|
+
xml << "<w:hyperlink r:id=\"#{ref_for_href(node[:attributes][:href])}\">"
|
51
|
+
end
|
52
|
+
|
53
|
+
xml << "<w:r>"
|
54
|
+
xml << <<~XML
|
55
|
+
<w:rPr>
|
56
|
+
<w:rFonts w:ascii="#{@font}" w:cs="#{@font}" w:hAnsi="#{@font}"/>
|
57
|
+
<w:color w:val="#{@color.gsub("#", "")}"/>
|
58
|
+
<w:sz w:val="#{DocXify.pt2halfpt(@size)}"/>
|
59
|
+
<w:szCs w:val="#{DocXify.pt2halfpt(@size)}"/>
|
60
|
+
#{"<w:highlight w:val=\"yellow\"/>" if @highlight}
|
61
|
+
#{"<w:b/><w:bCs/>" if node.is_a?(Hash) && node[:tag] == "b"}
|
62
|
+
#{"<w:i/><w:iCs/>" if node.is_a?(Hash) && node[:tag] == "i"}
|
63
|
+
#{"<w:u w:val=\"single\"/>" if node.is_a?(Hash) && (node[:tag] == "u" || node[:tag] == "a")}
|
64
|
+
#{"<w:rStyle w:val=\"Hyperlink\"/>" if node.is_a?(Hash) && node[:tag] == "a"}
|
65
|
+
</w:rPr>
|
66
|
+
XML
|
67
|
+
|
68
|
+
content = node.is_a?(Hash) ? node[:content] : node
|
69
|
+
content = content.gsub("{CHECKBOX_EMPTY}", "☐").gsub("{CHECKBOX_CHECKED}", "☒")
|
70
|
+
xml << "<w:t xml:space=\"preserve\">#{content}</w:t>"
|
71
|
+
xml << "</w:r>"
|
72
|
+
|
73
|
+
if node.is_a?(Hash) && node[:tag] == "a"
|
74
|
+
xml << "</w:hyperlink>"
|
75
|
+
end
|
47
76
|
end
|
48
|
-
|
77
|
+
|
78
|
+
xml << "</w:p>"
|
79
|
+
end
|
80
|
+
|
81
|
+
def ref_for_href(href)
|
82
|
+
relation = nil
|
83
|
+
|
84
|
+
@document.relationships.select { |r| r.is_a?(DocXify::Element::WebAddress) }.each do |r|
|
85
|
+
if r.target == href
|
86
|
+
relation = r
|
87
|
+
break
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
if relation.nil?
|
92
|
+
relation = DocXify::Element::WebAddress.new(href)
|
93
|
+
@document.relationships << relation
|
94
|
+
end
|
95
|
+
|
96
|
+
relation.reference
|
49
97
|
end
|
50
98
|
end
|
51
99
|
end
|
@@ -1,8 +1,106 @@
|
|
1
|
+
# Structure of a table element looks something like this
|
2
|
+
# <w:tbl> - Table element
|
3
|
+
# <w:tblPr> - Table properties
|
4
|
+
# <w:tblGrid> - Table grid (column widths)
|
5
|
+
# <w:tr> - Table row
|
6
|
+
# <w:tc> - Table cell
|
7
|
+
# <w:tcPr> - Table cell properties
|
8
|
+
# <w:tcW w:type="dxa" w:w="1502"/> - Table cell width
|
9
|
+
# <w:vMerge w:val="restart"/> - Something about merging TODO - figure out
|
10
|
+
# <w:tcBorders> - Overriding table cell borders
|
11
|
+
# <w:top w:val="nil"/>
|
12
|
+
# <w:bottom w:color="auto" w:space="0" w:sz="4" w:val="single"/>
|
13
|
+
# <w:right w:val="nil"/>
|
14
|
+
# </w:tcBorders>
|
15
|
+
# <w:vAlign w:val="bottom"/>
|
16
|
+
# </w:tcPr>
|
17
|
+
# <w:p> - Paragraph element
|
18
|
+
|
1
19
|
module DocXify
|
2
20
|
module Element
|
3
21
|
class Table < Base
|
22
|
+
attr_accessor :rows, :column_widths
|
23
|
+
|
24
|
+
def initialize(rows, options = {})
|
25
|
+
super()
|
26
|
+
@document = options[:document]
|
27
|
+
@rows = rows
|
28
|
+
end
|
29
|
+
|
4
30
|
def to_s(_container = nil)
|
5
|
-
|
31
|
+
xml = ""
|
32
|
+
xml << table_element_start
|
33
|
+
xml << table_properties
|
34
|
+
xml << table_grid
|
35
|
+
@rows.each do |row|
|
36
|
+
xml << table_row(row)
|
37
|
+
end
|
38
|
+
xml << table_element_end
|
39
|
+
xml
|
40
|
+
end
|
41
|
+
|
42
|
+
def table_element_start
|
43
|
+
"<w:tbl>"
|
44
|
+
end
|
45
|
+
|
46
|
+
def table_properties
|
47
|
+
xml = ""
|
48
|
+
xml << "<w:tblPr>"
|
49
|
+
xml << '<w:tblStyle w:val="TableGrid"/>'
|
50
|
+
xml << '<w:tblW w:type="auto" w:w="0"/>'
|
51
|
+
xml << "<w:tblBorders>"
|
52
|
+
xml << '<w:top w:color="auto" w:space="0" w:sz="0" w:val="none"/>'
|
53
|
+
xml << '<w:left w:color="auto" w:space="0" w:sz="0" w:val="none"/>'
|
54
|
+
xml << '<w:bottom w:color="auto" w:space="0" w:sz="0" w:val="none"/>'
|
55
|
+
xml << '<w:right w:color="auto" w:space="0" w:sz="0" w:val="none"/>'
|
56
|
+
xml << "</w:tblBorders>"
|
57
|
+
xml << '<w:tblLook w:firstColumn="1" w:firstRow="1" w:lastColumn="0" w:lastRow="0" w:noHBand="0" w:noVBand="1" w:val="04A0"/>'
|
58
|
+
xml << "</w:tblPr>"
|
59
|
+
xml
|
60
|
+
end
|
61
|
+
|
62
|
+
def table_grid
|
63
|
+
default_equal_width = (@document.width / @rows.first.size).to_i
|
64
|
+
|
65
|
+
@column_widths = []
|
66
|
+
xml = "<w:tblGrid>"
|
67
|
+
@rows.first.each do |cell|
|
68
|
+
width = if cell.width_cm
|
69
|
+
DocXify.cm2dxa(cell.width_cm)
|
70
|
+
else
|
71
|
+
default_equal_width
|
72
|
+
end
|
73
|
+
xml << "<w:gridCol w:w=\"#{width}\"/>"
|
74
|
+
@column_widths << width
|
75
|
+
end
|
76
|
+
|
77
|
+
xml << "</w:tblGrid>"
|
78
|
+
xml
|
79
|
+
end
|
80
|
+
|
81
|
+
def table_row(row)
|
82
|
+
xml = "<w:tr>"
|
83
|
+
widths = @column_widths.dup
|
84
|
+
row.each do |cell|
|
85
|
+
if cell.nil?
|
86
|
+
cell = DocXify::Element::TableCell.new(nil)
|
87
|
+
end
|
88
|
+
|
89
|
+
if cell.width_cm.nil?
|
90
|
+
cell.width_cm = 0
|
91
|
+
(cell.colspan || 1).times do
|
92
|
+
cell.width_cm += DocXify.dxa2cm(widths.shift)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
xml << cell.to_s
|
97
|
+
end
|
98
|
+
xml << "</w:tr>"
|
99
|
+
xml
|
100
|
+
end
|
101
|
+
|
102
|
+
def table_element_end
|
103
|
+
"</w:tbl>"
|
6
104
|
end
|
7
105
|
end
|
8
106
|
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module DocXify
|
2
|
+
module Element
|
3
|
+
class TableCell < Base
|
4
|
+
attr_accessor :content, :valign, :align, :nowrap, :colspan, :width_cm, :borders, :font, :size, :colour
|
5
|
+
|
6
|
+
def initialize(content, options = {})
|
7
|
+
super()
|
8
|
+
@content = content
|
9
|
+
@valign = options[:valign] || :top
|
10
|
+
@align = options[:align] || :left
|
11
|
+
@nowrap = options[:nowrap]
|
12
|
+
@colspan = options[:colspan]
|
13
|
+
@rowspan = options[:rowspan]
|
14
|
+
@width_cm = options[:width_cm]
|
15
|
+
@font = options[:font]
|
16
|
+
@size = options[:size]
|
17
|
+
@color = options[:color]
|
18
|
+
@borders = options[:borders]&.map(&:to_sym) || []
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_s
|
22
|
+
xml = "<w:tc>"
|
23
|
+
xml << "<w:tcPr>"
|
24
|
+
xml << %Q(<w:tcW w:type="dxa" w:w="#{DocXify.cm2dxa(@width_cm)}"/>)
|
25
|
+
if !@colspan.nil? && @colspan.to_i > 1
|
26
|
+
xml << %Q(<w:gridSpan w:val="#{@colspan}"/>')
|
27
|
+
end
|
28
|
+
|
29
|
+
if borders.any?
|
30
|
+
xml << "<w:tcBorders>"
|
31
|
+
xml << (borders.include?(:top) ? '<w:top w:color="auto" w:space="0" w:sz="4" w:val="single"/>' : '<w:top w:val="nil"/>')
|
32
|
+
xml << (borders.include?(:bottom) ? '<w:bottom w:color="auto" w:space="0" w:sz="4" w:val="single"/>' : '<w:bottom w:val="nil"/>')
|
33
|
+
xml << (borders.include?(:left) ? '<w:left w:color="auto" w:space="0" w:sz="4" w:val="single"/>' : '<w:left w:val="nil"/>')
|
34
|
+
xml << (borders.include?(:right) ? '<w:right w:color="auto" w:space="0" w:sz="4" w:val="single"/>' : '<w:right w:val="nil"/>')
|
35
|
+
xml << "</w:tcBorders>"
|
36
|
+
end
|
37
|
+
|
38
|
+
if @valign != :top
|
39
|
+
xml << %Q(<w:vAlign w:val="#{@valign}"/>)
|
40
|
+
end
|
41
|
+
|
42
|
+
if @nowrap
|
43
|
+
xml << "<w:noWrap/>"
|
44
|
+
end
|
45
|
+
|
46
|
+
if @content.nil?
|
47
|
+
@content = "" # Nil is useful for rowspan, but we need to output something or Word breaks
|
48
|
+
end
|
49
|
+
|
50
|
+
if @rowspan
|
51
|
+
xml << '<w:vMerge w:val="restart"/>'
|
52
|
+
elsif @content == ""
|
53
|
+
xml << "<w:vMerge/>"
|
54
|
+
end
|
55
|
+
|
56
|
+
xml << "</w:tcPr>"
|
57
|
+
|
58
|
+
xml << DocXify::Element::Paragraph.new(@content, document: @document, font: @font, size: @size, color: @color, align: @align).to_s
|
59
|
+
|
60
|
+
xml << "</w:tc>"
|
61
|
+
|
62
|
+
xml
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module DocXify
|
2
|
+
module Element
|
3
|
+
class WebAddress < Base
|
4
|
+
attr_accessor :target
|
5
|
+
|
6
|
+
def initialize(target)
|
7
|
+
super()
|
8
|
+
@target = target
|
9
|
+
end
|
10
|
+
|
11
|
+
def reference
|
12
|
+
"url-#{Digest::SHA1.hexdigest(target)[0, 8]}"
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_s
|
16
|
+
"<Relationship Id=\"#{reference}\" Target=\"#{target}/\" TargetMode=\"External\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink\"/>"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/lib/docxify/version.rb
CHANGED
data/lib/docxify.rb
CHANGED
@@ -8,8 +8,11 @@ require_relative "docxify/element/divider"
|
|
8
8
|
require_relative "docxify/element/file"
|
9
9
|
require_relative "docxify/element/image"
|
10
10
|
require_relative "docxify/element/page_break"
|
11
|
+
require_relative "docxify/element/page_layout"
|
11
12
|
require_relative "docxify/element/paragraph"
|
12
13
|
require_relative "docxify/element/table"
|
14
|
+
require_relative "docxify/element/table_cell"
|
15
|
+
require_relative "docxify/element/web_address"
|
13
16
|
|
14
17
|
module DocXify
|
15
18
|
class Error < StandardError; end
|
@@ -28,6 +31,14 @@ module DocXify
|
|
28
31
|
(value * UNITS_PER_CM).to_i
|
29
32
|
end
|
30
33
|
|
34
|
+
# Inverse of cm2dxa
|
35
|
+
def self.dxa2cm(value)
|
36
|
+
value = value.to_f
|
37
|
+
raise ArgumentError.new("Value must be greater than or equal to 0") if value.negative?
|
38
|
+
|
39
|
+
(value / UNITS_PER_CM).to_i
|
40
|
+
end
|
41
|
+
|
31
42
|
# Used for font sizes
|
32
43
|
def self.pt2halfpt(value)
|
33
44
|
value = value.to_f
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: docxify
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andy Jeffries
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-04-
|
11
|
+
date: 2024-04-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rubyzip
|
@@ -48,6 +48,8 @@ files:
|
|
48
48
|
- lib/docxify/element/page_break.rb
|
49
49
|
- lib/docxify/element/paragraph.rb
|
50
50
|
- lib/docxify/element/table.rb
|
51
|
+
- lib/docxify/element/table_cell.rb
|
52
|
+
- lib/docxify/element/web_address.rb
|
51
53
|
- lib/docxify/template.rb
|
52
54
|
- lib/docxify/version.rb
|
53
55
|
homepage: https://github.com/foundercatalyst/docxify
|