Skip to content

Commit 4429a0f

Browse files
committed
Merge branch 'master' of https://github.com/chrahunt/docx
2 parents bbb6a00 + 81ff9e1 commit 4429a0f

12 files changed

Lines changed: 488 additions & 227 deletions

File tree

README.md

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
# docx
22

3-
a ruby library/gem for interacting with `.docx` files. currently capabilities include reading paragraphs/bookmarks, inserting text at bookmarks, reading tables/rows/columns/cells and saving the document.
3+
A ruby library/gem for interacting with `.docx` files. currently capabilities include reading paragraphs/bookmarks, inserting text at bookmarks, reading tables/rows/columns/cells and saving the document.
44

5-
## usage
5+
## Usage
66

7-
### install
7+
### Install
88

9-
requires ruby (only tested with 1.9.3 so far)
9+
Requires ruby (tested with 2.1.1)
1010

11-
gem install docx
11+
gem 'docx', '~> 0.2.07', :require => ["docx"]
1212

13-
### reading
13+
### Reading
1414

1515
``` ruby
1616
require 'docx'
@@ -29,7 +29,18 @@ doc.bookmarks.each_pair do |bookmark_name, bookmark_object|
2929
end
3030
```
3131

32-
### reading tables
32+
### Rendering html
33+
``` ruby
34+
require 'docx'
35+
36+
# Retrieve and display paragraphs as html
37+
doc = Docx::Document.open('example.docx')
38+
doc.paragraphs.each do |p|
39+
puts p.to_html
40+
end
41+
```
42+
43+
### Reading tables
3344

3445
``` ruby
3546
require 'docx'
@@ -59,7 +70,7 @@ doc.tables.each do |table|
5970
end
6071
```
6172

62-
### writing
73+
### Writing
6374

6475
``` ruby
6576
require 'docx'
@@ -77,7 +88,7 @@ doc.bookmarks['example_bookmark_2'].insert_multiple_lines_after(['Hello', 'World
7788
doc.save('example-edited.docx')
7889
```
7990

80-
### advanced
91+
### Advanced
8192

8293
``` ruby
8394
require 'docx'
@@ -99,7 +110,6 @@ p_child = p_element.at_xpath("//child::*") # selects first child
99110

100111
### todo
101112

102-
* Add better formatting identification for specific nodes and other formatting indicators (text size, paragraph spacing)
103113
* Calculate element formatting based on values present in element properties as well as properties inherited from parents
104114
* Default formatting of inserted elements to inherited values
105115
* Implement formattable elements.

docx.gemspec

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@ Gem::Specification.new do |s|
66
s.version = Docx::VERSION
77
s.summary = 'a ruby library/gem for interacting with .docx files'
88
s.description = s.summary
9-
s.authors = ['Christopher Hunt', 'Marcus Ortiz']
9+
s.authors = ['Christopher Hunt', 'Marcus Ortiz', 'Higgins Dragon', 'Toms Mikoss', 'Sebastian Wittenkamp']
1010
s.email = ['chrahunt@gmail.com']
1111
s.homepage = 'https://github.com/chrahunt/docx'
1212
s.files = Dir["README.md", "LICENSE.md", "lib/**/*.rb"]
1313

1414
s.add_dependency 'nokogiri', '~> 1.5'
15-
s.add_dependency 'rubyzip', '~> 1.0'
15+
s.add_dependency 'rubyzip', '~> 1.1.6'
1616

1717
s.add_development_dependency 'rspec'
1818
end

lib/docx/containers/paragraph.rb

100644100755
Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,11 @@ def self.tag
1515

1616
# Child elements: pPr, r, fldSimple, hlink, subDoc
1717
# http://msdn.microsoft.com/en-us/library/office/ee364458(v=office.11).aspx
18-
def initialize(node)
18+
def initialize(node, document_properties = {})
1919
@node = node
2020
@properties_tag = 'pPr'
21+
@document_properties = document_properties
22+
@font_size = @document_properties[:font_size]
2123
end
2224

2325
# Set text of paragraph
@@ -39,17 +41,55 @@ def to_s
3941
text_runs.map(&:text).join('')
4042
end
4143

44+
# Return paragraph as a <p></p> HTML fragment with formatting based on properties.
45+
def to_html
46+
html = ''
47+
text_runs.each do |text_run|
48+
html << text_run.to_html
49+
end
50+
styles = { 'font-size' => "#{font_size}pt" }
51+
styles['text-align'] = alignment if alignment
52+
html_tag(:p, content: html, styles: styles)
53+
end
54+
55+
4256
# Array of text runs contained within paragraph
4357
def text_runs
44-
@node.xpath('w:r|w:hyperlink/w:r').map {|r_node| Containers::TextRun.new(r_node) }
58+
@node.xpath('w:r|w:hyperlink/w:r').map { |r_node| Containers::TextRun.new(r_node, @document_properties) }
4559
end
4660

4761
# Iterate over each text run within a paragraph
4862
def each_text_run
4963
text_runs.each { |tr| yield(tr) }
5064
end
65+
66+
def aligned_left?
67+
['left', nil].include?(alignment)
68+
end
69+
70+
def aligned_right?
71+
alignment == 'right'
72+
end
73+
74+
def aligned_center?
75+
alignment == 'center'
76+
end
77+
78+
def font_size
79+
size_tag = @node.xpath('w:pPr//w:sz').first
80+
size_tag ? size_tag.attributes['val'].value.to_i / 2 : @font_size
81+
end
5182

5283
alias_method :text, :to_s
84+
85+
private
86+
87+
# Returns the alignment if any, or nil if left
88+
def alignment
89+
alignment_tag = @node.xpath('.//w:jc').first
90+
alignment_tag ? alignment_tag.attributes['val'].value : nil
91+
end
92+
5393
end
5494
end
5595
end

lib/docx/containers/text_run.rb

100644100755
Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,14 @@ def self.tag
2020
attr_reader :text
2121
attr_reader :formatting
2222

23-
def initialize(node)
23+
def initialize(node, document_properties = {})
2424
@node = node
2525
@text_nodes = @node.xpath('w:t').map {|t_node| Elements::Text.new(t_node) }
2626
@properties_tag = 'rPr'
2727
@text = parse_text || ''
2828
@formatting = parse_formatting || DEFAULT_FORMATTING
29+
@document_properties = document_properties
30+
@font_size = @document_properties[:font_size]
2931
end
3032

3133
# Set text of text run
@@ -54,7 +56,20 @@ def parse_formatting
5456
def to_s
5557
@text
5658
end
57-
59+
60+
# Return text as a HTML fragment with formatting based on properties.
61+
def to_html
62+
html = @text
63+
html = html_tag(:em, content: html) if italicized?
64+
html = html_tag(:strong, content: html) if bolded?
65+
styles = {}
66+
styles['text-decoration'] = 'underline' if underlined?
67+
# No need to be granular with font size down to the span level if it doesn't vary.
68+
styles['font-size'] = "#{font_size}pt" if font_size != @font_size
69+
html = html_tag(:span, content: html, styles: styles) unless styles.empty?
70+
return html
71+
end
72+
5873
def italicized?
5974
@formatting[:italic]
6075
end
@@ -66,6 +81,11 @@ def bolded?
6681
def underlined?
6782
@formatting[:underline]
6883
end
84+
85+
def font_size
86+
size_tag = @node.xpath('w:rPr//w:sz').first
87+
size_tag ? size_tag.attributes['val'].value.to_i / 2 : @font_size
88+
end
6989
end
7090
end
7191
end

0 commit comments

Comments
 (0)