docx 0.2.03 → 0.2.07

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.
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]�"@���