docx 0.2.03 → 0.2.07

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,16 +1,16 @@
1
1
  # docx
2
2
 
3
- a ruby library/gem for interacting with `.docx` files. currently capabilities include reading paragraphs/bookmarks, inserting text at bookmarks, 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.
4
4
 
5
- ## usage
5
+ ## Usage
6
6
 
7
- ### install
7
+ ### Install
8
8
 
9
- requires ruby (only tested with 1.9.3 so far)
9
+ Requires ruby (tested with 2.1.1)
10
10
 
11
- gem install docx
11
+ gem 'docx', '~> 0.2.07', :require => ["docx"]
12
12
 
13
- ### reading
13
+ ### Reading
14
14
 
15
15
  ``` ruby
16
16
  require 'docx'
@@ -29,7 +29,48 @@ doc.bookmarks.each_pair do |bookmark_name, bookmark_object|
29
29
  end
30
30
  ```
31
31
 
32
- ### writing
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
44
+
45
+ ``` ruby
46
+ require 'docx'
47
+
48
+ # Create a Docx::Document object for our existing docx file
49
+ doc = Docx::Document.open('tables.docx')
50
+
51
+ first_table = doc.tables[0]
52
+ puts first_table.row_count
53
+ puts first_table.column_count
54
+ puts first_table.rows[0].cells[0].text
55
+ puts first_table.columns[0].cells[0].text
56
+
57
+ # Iterate through tables
58
+ doc.tables.each do |table|
59
+ table.rows.each do |row| # Row-based iteration
60
+ row.cells.each do |cell|
61
+ puts cell.text
62
+ end
63
+ end
64
+
65
+ table.columns.each do |column| # Column-based iteration
66
+ column.cells.each do |cell|
67
+ puts cell.text
68
+ end
69
+ end
70
+ end
71
+ ```
72
+
73
+ ### Writing
33
74
 
34
75
  ``` ruby
35
76
  require 'docx'
@@ -38,7 +79,7 @@ require 'docx'
38
79
  doc = Docx::Document.open('example.docx')
39
80
 
40
81
  # Insert a single line of text after one of our bookmarks
41
- doc.bookmarks['example_bookmark'].insert_after("Hello world.")
82
+ doc.bookmarks['example_bookmark'].insert_text_after("Hello world.")
42
83
 
43
84
  # Insert multiple lines of text at our bookmark
44
85
  doc.bookmarks['example_bookmark_2'].insert_multiple_lines_after(['Hello', 'World', 'foo'])
@@ -47,7 +88,7 @@ doc.bookmarks['example_bookmark_2'].insert_multiple_lines_after(['Hello', 'World
47
88
  doc.save('example-edited.docx')
48
89
  ```
49
90
 
50
- ### advanced
91
+ ### Advanced
51
92
 
52
93
  ``` ruby
53
94
  require 'docx'
@@ -69,9 +110,8 @@ p_child = p_element.at_xpath("//child::*") # selects first child
69
110
 
70
111
  ### todo
71
112
 
72
- * Add better formatting identification for specific nodes and other formatting indicators (text size, paragraph spacing)
73
113
  * Calculate element formatting based on values present in element properties as well as properties inherited from parents
74
114
  * Default formatting of inserted elements to inherited values
75
115
  * Implement formattable elements.
76
116
  * Implement styles.
77
- * Easier multi-line text insertion at a single bookmark (inserting paragraph nodes after the one containing the bookmark)
117
+ * Easier multi-line text insertion at a single bookmark (inserting paragraph nodes after the one containing the bookmark)
@@ -1,3 +1,4 @@
1
1
  require 'docx/containers/container'
2
2
  require 'docx/containers/text_run'
3
- require 'docx/containers/paragraph'
3
+ require 'docx/containers/paragraph'
4
+ require 'docx/containers/table'
@@ -8,13 +8,18 @@ module Docx
8
8
  include Container
9
9
  include Elements::Element
10
10
 
11
- TAG = 'p'
11
+ def self.tag
12
+ 'p'
13
+ end
14
+
12
15
 
13
16
  # Child elements: pPr, r, fldSimple, hlink, subDoc
14
17
  # http://msdn.microsoft.com/en-us/library/office/ee364458(v=office.11).aspx
15
- def initialize(node)
18
+ def initialize(node, document_properties = {})
16
19
  @node = node
17
20
  @properties_tag = 'pPr'
21
+ @document_properties = document_properties
22
+ @font_size = @document_properties[:font_size]
18
23
  end
19
24
 
20
25
  # Set text of paragraph
@@ -36,17 +41,55 @@ module Docx
36
41
  text_runs.map(&:text).join('')
37
42
  end
38
43
 
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
+
39
56
  # Array of text runs contained within paragraph
40
57
  def text_runs
41
- @node.xpath('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) }
42
59
  end
43
60
 
44
61
  # Iterate over each text run within a paragraph
45
62
  def each_text_run
46
63
  text_runs.each { |tr| yield(tr) }
47
64
  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
48
82
 
49
83
  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
+
50
93
  end
51
94
  end
52
95
  end
@@ -0,0 +1,51 @@
1
+ require 'docx/containers/table_row'
2
+ require 'docx/containers/table_column'
3
+ require 'docx/containers/container'
4
+
5
+ module Docx
6
+ module Elements
7
+ module Containers
8
+ class Table
9
+ include Container
10
+ include Elements::Element
11
+
12
+ def self.tag
13
+ 'tbl'
14
+ end
15
+
16
+ def initialize(node)
17
+ @node = node
18
+ @properties_tag = 'tblGrid'
19
+ end
20
+
21
+ # Array of row
22
+ def rows
23
+ @node.xpath('w:tr').map {|r_node| Containers::TableRow.new(r_node) }
24
+ end
25
+
26
+ def row_count
27
+ @node.xpath('w:tr').count
28
+ end
29
+
30
+ # Array of column
31
+ def columns
32
+ columns_containers = []
33
+ (0..(column_count-1)).each do |i|
34
+ columns_containers[i] = Containers::TableColumn.new @node.xpath("w:tr//w:tc[#{i+1}]")
35
+ end
36
+ columns_containers
37
+ end
38
+
39
+ def column_count
40
+ @node.xpath('w:tblGrid/w:gridCol').count
41
+ end
42
+
43
+ # Iterate over each row within a table
44
+ def each_rows
45
+ rows.each { |r| yield(r) }
46
+ end
47
+
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,39 @@
1
+ require 'docx/containers/text_run'
2
+ require 'docx/containers/container'
3
+
4
+ module Docx
5
+ module Elements
6
+ module Containers
7
+ class TableCell
8
+ include Container
9
+ include Elements::Element
10
+
11
+ def self.tag
12
+ 'tc'
13
+ end
14
+
15
+ def initialize(node)
16
+ @node = node
17
+ @properties_tag = 'tcPr'
18
+ end
19
+
20
+ # Return text of paragraph's cell
21
+ def to_s
22
+ paragraphs.map(&:text).join('')
23
+ end
24
+
25
+ # Array of paragraphs contained within cell
26
+ def paragraphs
27
+ @node.xpath('w:p').map {|p_node| Containers::Paragraph.new(p_node) }
28
+ end
29
+
30
+ # Iterate over each text run within a paragraph's cell
31
+ def each_paragraph
32
+ paragraphs.each { |tr| yield(tr) }
33
+ end
34
+
35
+ alias_method :text, :to_s
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,29 @@
1
+ require 'docx/containers/table_cell'
2
+ require 'docx/containers/container'
3
+
4
+ module Docx
5
+ module Elements
6
+ module Containers
7
+ class TableColumn
8
+ include Container
9
+ include Elements::Element
10
+
11
+ def self.tag
12
+ 'w:gridCol'
13
+ end
14
+
15
+ def initialize(cell_nodes)
16
+ @node = ''
17
+ @properties_tag = ''
18
+ @cells = cell_nodes.map { |c_node| Containers::TableCell.new(c_node) }
19
+ end
20
+
21
+ # Array of cells contained within row
22
+ def cells
23
+ @cells
24
+ end
25
+
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,28 @@
1
+ require 'docx/containers/table_cell'
2
+ require 'docx/containers/container'
3
+
4
+ module Docx
5
+ module Elements
6
+ module Containers
7
+ class TableRow
8
+ include Container
9
+ include Elements::Element
10
+
11
+ def self.tag
12
+ 'tr'
13
+ end
14
+
15
+ def initialize(node)
16
+ @node = node
17
+ @properties_tag = ''
18
+ end
19
+
20
+ # Array of cells contained within row
21
+ def cells
22
+ @node.xpath('w:tc').map {|c_node| Containers::TableCell.new(c_node) }
23
+ end
24
+
25
+ end
26
+ end
27
+ end
28
+ end
@@ -13,17 +13,21 @@ module Docx
13
13
  underline: false
14
14
  }
15
15
 
16
- TAG = 'r'
16
+ def self.tag
17
+ 'r'
18
+ end
17
19
 
18
20
  attr_reader :text
19
21
  attr_reader :formatting
20
22
 
21
- def initialize(node)
23
+ def initialize(node, document_properties = {})
22
24
  @node = node
23
25
  @text_nodes = @node.xpath('w:t').map {|t_node| Elements::Text.new(t_node) }
24
26
  @properties_tag = 'rPr'
25
27
  @text = parse_text || ''
26
28
  @formatting = parse_formatting || DEFAULT_FORMATTING
29
+ @document_properties = document_properties
30
+ @font_size = @document_properties[:font_size]
27
31
  end
28
32
 
29
33
  # Set text of text run
@@ -52,7 +56,20 @@ module Docx
52
56
  def to_s
53
57
  @text
54
58
  end
55
-
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
+
56
73
  def italicized?
57
74
  @formatting[:italic]
58
75
  end
@@ -64,6 +81,11 @@ module Docx
64
81
  def underlined?
65
82
  @formatting[:underline]
66
83
  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
67
89
  end
68
90
  end
69
91
  end
@@ -1,32 +1,47 @@
1
- require 'docx/parser'
2
- require 'zip/zip'
1
+ require 'docx/containers'
2
+ require 'docx/elements'
3
+ require 'nokogiri'
4
+ require 'zip'
3
5
 
4
6
  module Docx
5
7
  # The Document class wraps around a docx file and provides methods to
6
8
  # interface with it.
7
- #
9
+ #
8
10
  # # get a Docx::Document for a docx file in the local directory
9
11
  # doc = Docx::Document.open("test.docx")
10
- #
12
+ #
11
13
  # # get the text from the document
12
14
  # puts doc.text
13
- #
15
+ #
14
16
  # # do the same thing in a block
15
17
  # Docx::Document.open("test.docx") do |d|
16
18
  # puts d.text
17
19
  # end
18
20
  class Document
19
- delegate :paragraphs, :bookmarks, :to => :@parser
20
- delegate :doc, :xml, :zip, :to => :@parser
21
+ attr_reader :xml, :doc, :zip, :styles
22
+
21
23
  def initialize(path, &block)
22
24
  @replace = {}
25
+ @zip = Zip::File.open(path)
26
+ @document_xml = @zip.read('word/document.xml')
27
+ @doc = Nokogiri::XML(@document_xml)
28
+ @styles_xml = @zip.read('word/styles.xml')
29
+ @styles = Nokogiri::XML(@styles_xml)
23
30
  if block_given?
24
- @parser = Parser.new(File.expand_path(path), &block)
25
- else
26
- @parser = Parser.new(File.expand_path(path))
31
+ yield self
32
+ @zip.close
27
33
  end
28
34
  end
29
-
35
+
36
+
37
+ # This stores the current global document properties, for now
38
+ def document_properties
39
+ {
40
+ font_size: font_size
41
+ }
42
+ end
43
+
44
+
30
45
  # With no associated block, Docx::Document.open is a synonym for Docx::Document.new. If the optional code block is given, it will be passed the opened +docx+ file as an argument and the Docx::Document oject will automatically be closed when the block terminates. The values of the block will be returned from Docx::Document.open.
31
46
  # call-seq:
32
47
  # open(filepath) => file
@@ -35,28 +50,57 @@ module Docx
35
50
  self.new(path, &block)
36
51
  end
37
52
 
53
+ def paragraphs
54
+ @doc.xpath('//w:document//w:body//w:p').map { |p_node| parse_paragraph_from p_node }
55
+ end
56
+
57
+ def bookmarks
58
+ bkmrks_hsh = Hash.new
59
+ bkmrks_ary = @doc.xpath('//w:bookmarkStart').map { |b_node| parse_bookmark_from b_node }
60
+ # auto-generated by office 2010
61
+ bkmrks_ary.reject! {|b| b.name == "_GoBack" }
62
+ bkmrks_ary.each {|b| bkmrks_hsh[b.name] = b }
63
+ bkmrks_hsh
64
+ end
65
+
66
+ def tables
67
+ @doc.xpath('//w:document//w:body//w:tbl').map { |t_node| parse_table_from t_node }
68
+ end
69
+
70
+ # Some documents have this set, others don't.
71
+ # Values are returned as half-points, so to get points, that's why it's divided by 2.
72
+ def font_size
73
+ size_tag = @styles.xpath('//w:docDefaults//w:rPrDefault//w:rPr//w:sz').first
74
+ size_tag ? size_tag.attributes['val'].value.to_i / 2 : nil
75
+ end
76
+
38
77
  ##
39
78
  # *Deprecated*
40
- #
79
+ #
41
80
  # Iterates over paragraphs within document
42
81
  # call-seq:
43
82
  # each_paragraph => Enumerator
44
83
  def each_paragraph
45
84
  paragraphs.each { |p| yield(p) }
46
85
  end
47
-
86
+
48
87
  # call-seq:
49
88
  # to_s -> string
50
89
  def to_s
51
90
  paragraphs.map(&:to_s).join("\n")
52
91
  end
53
92
 
93
+ # Output entire document as a String HTML fragment
94
+ def to_html
95
+ paragraphs.map(&:to_html).join('\n')
96
+ end
97
+
54
98
  # Save document to provided path
55
99
  # call-seq:
56
100
  # save(filepath) => void
57
101
  def save(path)
58
102
  update
59
- Zip::ZipOutputStream.open(path) do |out|
103
+ Zip::OutputStream.open(path) do |out|
60
104
  zip.each do |entry|
61
105
  out.put_next_entry(entry.name)
62
106
 
@@ -69,19 +113,36 @@ module Docx
69
113
  end
70
114
  zip.close
71
115
  end
72
-
116
+
73
117
  alias_method :text, :to_s
74
118
 
119
+ def replace_entry(entry_path, file_contents)
120
+ @replace[entry_path] = file_contents
121
+ end
122
+
75
123
  private
76
124
 
77
125
  #--
78
126
  # TODO: Flesh this out to be compatible with other files
79
- # TODO: Method to set flag on files that have been edited, probably by inserting something at the
127
+ # TODO: Method to set flag on files that have been edited, probably by inserting something at the
80
128
  # end of methods that make edits?
81
129
  #++
82
130
  def update
83
- @replace["word/document.xml"] = doc.serialize :save_with => 0
131
+ replace_entry "word/document.xml", doc.serialize(:save_with => 0)
132
+ end
133
+
134
+ # generate Elements::Containers::Paragraph from paragraph XML node
135
+ def parse_paragraph_from(p_node)
136
+ Elements::Containers::Paragraph.new(p_node, document_properties)
84
137
  end
85
138
 
139
+ # generate Elements::Bookmark from bookmark XML node
140
+ def parse_bookmark_from(b_node)
141
+ Elements::Bookmark.new(b_node)
142
+ end
143
+
144
+ def parse_table_from(t_node)
145
+ Elements::Containers::Table.new(t_node)
146
+ end
86
147
  end
87
148
  end
@@ -6,7 +6,9 @@ module Docx
6
6
  include Element
7
7
  attr_accessor :name
8
8
 
9
- TAG = 'bookmarkStart'
9
+ def self.tag
10
+ 'bookmarkStart'
11
+ end
10
12
 
11
13
  def initialize(node)
12
14
  @node = node
@@ -55,10 +55,34 @@ module Docx
55
55
  self.class.new(@node.dup)
56
56
  end
57
57
 
58
+ # A method to wrap content in an HTML tag.
59
+ # Currently used in paragraph and text_run for the to_html methods
60
+ #
61
+ # content:: The base text content for the tag.
62
+ # styles:: Hash of the inline CSS styles to be applied. e.g.
63
+ # { 'font-size' => '12pt', 'text-decoration' => 'underline' }
64
+ #
65
+ def html_tag(name, options = {})
66
+ content = options[:content]
67
+ styles = options[:styles]
68
+
69
+ html = "<#{name.to_s}"
70
+ unless styles.nil? || styles.empty?
71
+ styles_array = []
72
+ styles.each do |property, value|
73
+ styles_array << "#{property.to_s}:#{value};"
74
+ end
75
+ html << " style=\"#{styles_array.join('')}\""
76
+ end
77
+ html << ">"
78
+ html << content if content
79
+ html << "</#{name.to_s}>"
80
+ end
81
+
58
82
  module ClassMethods
59
83
  def create_with(element)
60
84
  # Need to somehow get the xml document accessible here by default, but this is alright in the interim
61
- self.new(Nokogiri::XML::Node.new("w:#{self.const_get(:TAG)}", element.node))
85
+ self.new(Nokogiri::XML::Node.new("w:#{self.tag}", element.node))
62
86
  end
63
87
 
64
88
  def create_within(element)
@@ -3,7 +3,11 @@ module Docx
3
3
  class Text
4
4
  include Element
5
5
  delegate :content, :content=, :to => :@node
6
- TAG = 't'
6
+
7
+ def self.tag
8
+ 't'
9
+ end
10
+
7
11
 
8
12
  def initialize(node)
9
13
  @node = node
@@ -1,3 +1,3 @@
1
1
  module Docx #:nodoc:
2
- VERSION = '0.2.03'
2
+ VERSION = '0.2.07'
3
3
  end
metadata CHANGED
@@ -1,48 +1,24 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: docx
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.03
4
+ version: 0.2.07
5
+ prerelease:
5
6
  platform: ruby
6
7
  authors:
7
8
  - Christopher Hunt
8
9
  - Marcus Ortiz
10
+ - Higgins Dragon
11
+ - Toms Mikoss
12
+ - Sebastian Wittenkamp
9
13
  autorequire:
10
14
  bindir: bin
11
- cert_chain:
12
- - !binary |-
13
- LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURjRENDQWxpZ0F3SUJB
14
- Z0lCQVRBTkJna3Foa2lHOXcwQkFRVUZBREEvTVJFd0R3WURWUVFEREFoamFI
15
- SmgKYUhWdWRERVZNQk1HQ2dtU0pvbVQ4aXhrQVJrV0JXZHRZV2xzTVJNd0VR
16
- WUtDWkltaVpQeUxHUUJHUllEWTI5dApNQjRYRFRFek1EUXhOVEl3TURFeU4x
17
- b1hEVEUwTURReE5USXdNREV5TjFvd1B6RVJNQThHQTFVRUF3d0lZMmh5CllX
18
- aDFiblF4RlRBVEJnb0praWFKay9Jc1pBRVpGZ1ZuYldGcGJERVRNQkVHQ2dt
19
- U0pvbVQ4aXhrQVJrV0EyTnYKYlRDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFB
20
- RGdnRVBBRENDQVFvQ2dnRUJBTFhycTdlWHRQaTYrUDJuZ3BYOQpSbmdXWUJz
21
- alhMZ0dhTnIxbDBieFBVUGpJN3pxaVF2N3JWOGkvNUdzNVZ4MFZSbTVtMU14
22
- OHNtK1c3akl0MExrClJVVGlvcG9TMHdlRUdJekRDZzc4Ukp4TEhBZ1g0Z2NU
23
- Vis2dGZvTzV2Qzc5WGJ5VFpZVExRbXFrWWYwSDE1RnYKVmRPd2dJS3hPaW42
24
- bThWSGdUdFhWcjhzeGxNRDlsN1Uzb3M3YmNrSDV3Lzk1SGcrNzI2NkRKdHl2
25
- eEpPUG5RLwpuOUJwblBhMEN0bXlacEY3WStmdWMzRE1LVUprY2hRdmx2OE5o
26
- cWpmNTF4T2hTQ1hVTXpFbHJlMVZvNXBON2VaClFsNERsaTFJeGNZY0R1NVpQ
27
- ck4rcEVMelYvS3QrV0JZaW1Sa3Era0ZxOGhYSzY1ODZGNGM3ZmMrSStTUkc4
28
- L2YKWTJVQ0F3RUFBYU4zTUhVd0NRWURWUjBUQkFJd0FEQUxCZ05WSFE4RUJB
29
- TUNCTEF3SFFZRFZSME9CQllFRkVlNQorZmRySFZCb1F6cnlWNEVYMmdiTGVQ
30
- clVNQjBHQTFVZEVRUVdNQlNCRW1Ob2NtRm9kVzUwUUdkdFlXbHNMbU52CmJU
31
- QWRCZ05WSFJJRUZqQVVnUkpqYUhKaGFIVnVkRUJuYldGcGJDNWpiMjB3RFFZ
32
- SktvWklodmNOQVFFRkJRQUQKZ2dFQkFMSzl1V25oMWliTUZzT2c3WGlKWWdV
33
- dlVoNUt4aWxhTHdMSHRHTDFHd3U2ZlRBMU9DSU5CeDJiMUxMbgpRNTdYQWhv
34
- dkxlOGN3Qko0RnV6RXV1aUpMTlhlOU5FTDU2L1ZpbjloMTFlVktpOHA2YTEv
35
- MC9XeTlsWEVVSHFBCkFUR0JMTHM0MXFXN2JuV3dSK09TZ2dySitJQkYzTGYr
36
- VjNzSHhiNkxHV0h4ekNNMHpIdU5OWEJsQTdnRWQyNFAKQ0llcEtTdnlwQUdP
37
- ckhRbGdpOTNPbkxEWjdKa3pCMk1wcDA0em5NSllQOGZIdGJCTkE2bFUxL2tK
38
- NEV0UFhmRQpLdFE1SGpuNFVDNTg0R0pyR01haFVnbXhMbmZleXVZWXVZTlFF
39
- M1VzVlVQYXl6eGtQVW9DOFZzT0orV1ZmMnMrCkcxL1VkNGRVYkVtOGdRL2J4
40
- bDM1TzBBdkhCcz0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
41
- date: 2013-06-08 00:00:00.000000000 Z
15
+ cert_chain: []
16
+ date: 2014-10-29 00:00:00.000000000 Z
42
17
  dependencies:
43
18
  - !ruby/object:Gem::Dependency
44
19
  name: nokogiri
45
20
  requirement: !ruby/object:Gem::Requirement
21
+ none: false
46
22
  requirements:
47
23
  - - ~>
48
24
  - !ruby/object:Gem::Version
@@ -50,6 +26,7 @@ dependencies:
50
26
  type: :runtime
51
27
  prerelease: false
52
28
  version_requirements: !ruby/object:Gem::Requirement
29
+ none: false
53
30
  requirements:
54
31
  - - ~>
55
32
  - !ruby/object:Gem::Version
@@ -57,17 +34,35 @@ dependencies:
57
34
  - !ruby/object:Gem::Dependency
58
35
  name: rubyzip
59
36
  requirement: !ruby/object:Gem::Requirement
37
+ none: false
60
38
  requirements:
61
39
  - - ~>
62
40
  - !ruby/object:Gem::Version
63
- version: '0.9'
41
+ version: 1.1.6
64
42
  type: :runtime
65
43
  prerelease: false
66
44
  version_requirements: !ruby/object:Gem::Requirement
45
+ none: false
67
46
  requirements:
68
47
  - - ~>
69
48
  - !ruby/object:Gem::Version
70
- version: '0.9'
49
+ version: 1.1.6
50
+ - !ruby/object:Gem::Dependency
51
+ name: rspec
52
+ requirement: !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ! '>='
56
+ - !ruby/object:Gem::Version
57
+ version: '0'
58
+ type: :development
59
+ prerelease: false
60
+ version_requirements: !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
71
66
  description: a ruby library/gem for interacting with .docx files
72
67
  email:
73
68
  - chrahunt@gmail.com
@@ -79,6 +74,10 @@ files:
79
74
  - LICENSE.md
80
75
  - lib/docx/containers/container.rb
81
76
  - lib/docx/containers/paragraph.rb
77
+ - lib/docx/containers/table.rb
78
+ - lib/docx/containers/table_cell.rb
79
+ - lib/docx/containers/table_column.rb
80
+ - lib/docx/containers/table_row.rb
82
81
  - lib/docx/containers/text_run.rb
83
82
  - lib/docx/containers.rb
84
83
  - lib/docx/core_ext/module.rb
@@ -87,31 +86,31 @@ files:
87
86
  - lib/docx/elements/element.rb
88
87
  - lib/docx/elements/text.rb
89
88
  - lib/docx/elements.rb
90
- - lib/docx/parser.rb
91
89
  - lib/docx/version.rb
92
90
  - lib/docx.rb
93
91
  homepage: https://github.com/chrahunt/docx
94
92
  licenses: []
95
- metadata: {}
96
93
  post_install_message:
97
94
  rdoc_options: []
98
95
  require_paths:
99
96
  - lib
100
97
  required_ruby_version: !ruby/object:Gem::Requirement
98
+ none: false
101
99
  requirements:
102
100
  - - ! '>='
103
101
  - !ruby/object:Gem::Version
104
102
  version: '0'
105
103
  required_rubygems_version: !ruby/object:Gem::Requirement
104
+ none: false
106
105
  requirements:
107
106
  - - ! '>='
108
107
  - !ruby/object:Gem::Version
109
108
  version: '0'
110
109
  requirements: []
111
110
  rubyforge_project:
112
- rubygems_version: 2.0.3
111
+ rubygems_version: 1.8.28
113
112
  signing_key:
114
- specification_version: 4
113
+ specification_version: 3
115
114
  summary: a ruby library/gem for interacting with .docx files
116
115
  test_files: []
117
116
  has_rdoc:
checksums.yaml DELETED
@@ -1,15 +0,0 @@
1
- ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- YzIyMTI3NGE3YWNhMjYyMjUzMTZjYWZjMmJkYjU0OGI4ZDg2OTM3MQ==
5
- data.tar.gz: !binary |-
6
- ZmJjNWZjMzc2OTM4NDFmMTkwNzI2Y2JhM2IwZDE5Mzc0MjY3M2I1Mw==
7
- !binary "U0hBNTEy":
8
- metadata.gz: !binary |-
9
- MmIyZWM4MDJjMjY3NGYzZDUzNjBiYmE2YjllZmNiZTA4NjkyYzE3ODg3ZmFi
10
- OTA4YTQ5ZTY2MzA4Mjc5YWI0YjIyYmIyNzFjZjk3ZWZmODQxNWUwMTNlZjNl
11
- N2ZiOTUxYzg5ZmYzNzc5MmI3ZjlhZTNiMDY0ZjNmYTE5NzVjOWE=
12
- data.tar.gz: !binary |-
13
- MTRhMjAxMmJlODRhOTJhMzM4OGExZGI5NGFiZTdmZDczZmI0N2QyYjQ0ZDhk
14
- OGQ0MjlkYWEyNWJlMzhmMGY2ZTFlODVjYmY5MThjM2Q1NzdiOTRkYzlhYjdk
15
- OWIxNGJkOWM5MzkzNTFlNzNkN2VkOWEzNmRjOWJhOTMxZWY1OTA=
Binary file
data.tar.gz.sig DELETED
Binary file
@@ -1,46 +0,0 @@
1
- require 'docx/containers'
2
- require 'docx/elements'
3
- require 'nokogiri'
4
- require 'zip/zip'
5
-
6
- module Docx
7
- class Parser
8
- attr_reader :xml, :doc, :zip
9
-
10
- def initialize(path)
11
- @zip = Zip::ZipFile.open(path)
12
- @xml = @zip.read('word/document.xml')
13
- @doc = Nokogiri::XML(@xml)
14
- if block_given?
15
- yield self
16
- @zip.close
17
- end
18
- end
19
-
20
- def paragraphs
21
- @doc.xpath('//w:document//w:body//w:p').map { |p_node| parse_paragraph_from p_node }
22
- end
23
-
24
- # Returns hash of bookmarks
25
- def bookmarks
26
- bkmrks_hsh = Hash.new
27
- bkmrks_ary = @doc.xpath('//w:bookmarkStart').map { |b_node| parse_bookmark_from b_node }
28
- # auto-generated by office 2010
29
- bkmrks_ary.reject! {|b| b.name == "_GoBack" }
30
- bkmrks_ary.each {|b| bkmrks_hsh[b.name] = b }
31
- bkmrks_hsh
32
- end
33
-
34
- private
35
-
36
- # generate Elements::Containers::Paragraph from paragraph XML node
37
- def parse_paragraph_from(p_node)
38
- Elements::Containers::Paragraph.new(p_node)
39
- end
40
-
41
- # generate Elements::Bookmark from bookmark XML node
42
- def parse_bookmark_from(b_node)
43
- Elements::Bookmark.new(b_node)
44
- end
45
- end
46
- end
metadata.gz.sig DELETED
@@ -1,3 +0,0 @@
1
- ����G��`ۼ/�W$���ѣ=�J'��H�1�gS�� ���ޭ�h!PK�A)d����x󼂷{%��YMo8���%��iRtc��fJs���^U8E\����f�`��Hf⇒8:Z�c�� \|68L��&��
2
- w�{Pږ�n�9��௨�4�!�\.�{k' �UD�5i�ߛ �إ hL�ĵ� �M�����{4��8�Ğ�(ͣ��%c��X��v�|���[�
3
- `fj)Xux��H�;XE:Q]�"@���