ruby_docx 0.0.4
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/.gitignore +19 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +29 -0
- data/Rakefile +1 -0
- data/lib/ruby_docx.rb +24 -0
- data/lib/ruby_docx/convertors/elements/html/base.rb +44 -0
- data/lib/ruby_docx/convertors/elements/html/br.rb +6 -0
- data/lib/ruby_docx/convertors/elements/html/header.rb +15 -0
- data/lib/ruby_docx/convertors/elements/html/hyperlink.rb +6 -0
- data/lib/ruby_docx/convertors/elements/html/paragraph.rb +15 -0
- data/lib/ruby_docx/convertors/elements/html/span.rb +11 -0
- data/lib/ruby_docx/convertors/elements/html/table.rb +19 -0
- data/lib/ruby_docx/convertors/elements/html/td.rb +27 -0
- data/lib/ruby_docx/convertors/elements/html/th.rb +3 -0
- data/lib/ruby_docx/convertors/elements/html/tr.rb +10 -0
- data/lib/ruby_docx/convertors/html.rb +52 -0
- data/lib/ruby_docx/elements/block.rb +72 -0
- data/lib/ruby_docx/elements/br.rb +3 -0
- data/lib/ruby_docx/elements/document.rb +60 -0
- data/lib/ruby_docx/elements/hyperlink.rb +9 -0
- data/lib/ruby_docx/elements/inextensible_block.rb +24 -0
- data/lib/ruby_docx/elements/paragraph.rb +59 -0
- data/lib/ruby_docx/elements/row.rb +13 -0
- data/lib/ruby_docx/elements/table.rb +33 -0
- data/lib/ruby_docx/elements/table_column.rb +9 -0
- data/lib/ruby_docx/elements/table_row.rb +3 -0
- data/lib/ruby_docx/styles/default.css +11 -0
- data/lib/ruby_docx/template.docx +0 -0
- data/lib/ruby_docx/templates/br.xml +1 -0
- data/lib/ruby_docx/templates/document.xml +2 -0
- data/lib/ruby_docx/templates/hyperlink.xml +1 -0
- data/lib/ruby_docx/templates/paragraph.xml +1 -0
- data/lib/ruby_docx/templates/row.xml +1 -0
- data/lib/ruby_docx/templates/table.xml +1 -0
- data/lib/ruby_docx/templates/table_column.xml +1 -0
- data/lib/ruby_docx/templates/table_row.xml +1 -0
- data/lib/ruby_docx/version.rb +3 -0
- data/ruby_docx.gemspec +22 -0
- metadata +132 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 HoJSim
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# RubyDocx
|
2
|
+
|
3
|
+
TODO: Write a gem description
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'ruby_docx'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install ruby_docx
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
TODO: Write usage instructions here
|
22
|
+
|
23
|
+
## Contributing
|
24
|
+
|
25
|
+
1. Fork it
|
26
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
28
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
29
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/lib/ruby_docx.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require "nokogiri"
|
3
|
+
require "css_parser"
|
4
|
+
require "zip/zip"
|
5
|
+
require "ruby_docx/version"
|
6
|
+
|
7
|
+
module RubyDocx
|
8
|
+
class InvalidOperation < StandardError; end
|
9
|
+
|
10
|
+
require 'ruby_docx/elements/document'
|
11
|
+
require 'ruby_docx/elements/inextensible_block'
|
12
|
+
require 'ruby_docx/elements/block'
|
13
|
+
require 'ruby_docx/elements/paragraph'
|
14
|
+
require 'ruby_docx/elements/row'
|
15
|
+
require 'ruby_docx/elements/br'
|
16
|
+
require 'ruby_docx/elements/table'
|
17
|
+
require 'ruby_docx/elements/table_row'
|
18
|
+
require 'ruby_docx/elements/table_column'
|
19
|
+
require 'ruby_docx/elements/hyperlink'
|
20
|
+
|
21
|
+
module Convertor
|
22
|
+
require 'ruby_docx/convertors/html'
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
class RubyDocx::Convertor::Html::Base
|
3
|
+
attr_reader :tag, :css
|
4
|
+
def initialize(tag, css)
|
5
|
+
@tag = tag
|
6
|
+
@css = css
|
7
|
+
end
|
8
|
+
|
9
|
+
def build
|
10
|
+
node = convert
|
11
|
+
node.add_styles(styles) if styles.present?
|
12
|
+
node
|
13
|
+
end
|
14
|
+
|
15
|
+
def convert
|
16
|
+
RubyDocx::InextensibleBlock.new
|
17
|
+
end
|
18
|
+
|
19
|
+
def styles
|
20
|
+
@styles = {}
|
21
|
+
eval_styles.reverse.each do |row|
|
22
|
+
prop, val = row.split(':', 2).map(&:strip)
|
23
|
+
unless @styles.has_key? prop
|
24
|
+
@styles[prop] = val.sub /;$/, ''
|
25
|
+
end
|
26
|
+
end
|
27
|
+
@styles
|
28
|
+
end
|
29
|
+
|
30
|
+
protected
|
31
|
+
def eval_styles
|
32
|
+
styles = css[tag.name]
|
33
|
+
tag.attributes.each do |_, attr|
|
34
|
+
if attr.name == 'class'
|
35
|
+
attr.value.split(' ').map(&:strip).each do |tag_class|
|
36
|
+
styles += css[".#{tag_class}"]
|
37
|
+
end
|
38
|
+
elsif attr.name == 'id'
|
39
|
+
styles += css["##{attr.value}"]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
styles.uniq.map { |row| row.split(';').map(&:strip) }.flatten
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class RubyDocx::Convertor::Html::Header < RubyDocx::Convertor::Html::Base
|
2
|
+
def convert
|
3
|
+
default_styles = {
|
4
|
+
'font-weight' => 'bold',
|
5
|
+
'font-size' => (20 - tag.name.gsub(/\D/, '').to_i)
|
6
|
+
}
|
7
|
+
node = RubyDocx::Paragraph.new(nil, default_styles)
|
8
|
+
tag.children.each do |child|
|
9
|
+
if child.is_a?(Nokogiri::XML::Text) && child.content.present?
|
10
|
+
node.append(RubyDocx::Row.new(child.content, default_styles))
|
11
|
+
end
|
12
|
+
end
|
13
|
+
node
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
class RubyDocx::Convertor::Html::Paragraph < RubyDocx::Convertor::Html::Base
|
3
|
+
def convert
|
4
|
+
node = RubyDocx::Paragraph.new
|
5
|
+
tag.children.each do |child|
|
6
|
+
child_node = if child.is_a?(Nokogiri::XML::Text)
|
7
|
+
RubyDocx::Row.new(child.content) if child.content.present?
|
8
|
+
else
|
9
|
+
RubyDocx::Convertor::Html.create_node(child, css)
|
10
|
+
end
|
11
|
+
node.append(child_node) if child_node
|
12
|
+
end
|
13
|
+
node
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
class RubyDocx::Convertor::Html::Span < RubyDocx::Convertor::Html::Base
|
3
|
+
def convert
|
4
|
+
RubyDocx::Row.new(
|
5
|
+
tag.children.select{|child| child.is_a? Nokogiri::XML::Text }.map(&:content).join(' '),
|
6
|
+
{
|
7
|
+
'white-space' => 'pre'
|
8
|
+
}
|
9
|
+
)
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
class RubyDocx::Convertor::Html::Table < RubyDocx::Convertor::Html::Base
|
3
|
+
def convert
|
4
|
+
node = RubyDocx::Table.new
|
5
|
+
tag.children.each do |child|
|
6
|
+
rows = if %w[thead tbody tfoot].include? child.name
|
7
|
+
child.children
|
8
|
+
elsif !child.is_a?(Nokogiri::XML::Text)
|
9
|
+
[child]
|
10
|
+
else
|
11
|
+
[]
|
12
|
+
end
|
13
|
+
rows.each do |row|
|
14
|
+
node.append RubyDocx::Convertor::Html.create_node(row, css)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
node
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
class RubyDocx::Convertor::Html::Td < RubyDocx::Convertor::Html::Base
|
3
|
+
def convert
|
4
|
+
node = RubyDocx::Paragraph.new
|
5
|
+
tag.children.each do |child|
|
6
|
+
child_node = if child.is_a?(Nokogiri::XML::Text)
|
7
|
+
RubyDocx::Row.new(child.content) if child.content.present?
|
8
|
+
else
|
9
|
+
RubyDocx::Convertor::Html.create_node(child, css)
|
10
|
+
end
|
11
|
+
node.append(child_node) if child_node
|
12
|
+
end
|
13
|
+
RubyDocx::TableColumn.new(nil, [], [node])
|
14
|
+
end
|
15
|
+
|
16
|
+
protected
|
17
|
+
def apply_style(properties_node, key, style)
|
18
|
+
super
|
19
|
+
case key
|
20
|
+
when 'vertical-align'
|
21
|
+
property_node = Nokogiri::XML::Node.new 'vAlign', node.document
|
22
|
+
property_node['w:val'] = style
|
23
|
+
properties_node.add_child property_node
|
24
|
+
end
|
25
|
+
properties_node
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
class RubyDocx::Convertor::Html::Tr < RubyDocx::Convertor::Html::Base
|
3
|
+
def convert
|
4
|
+
node = RubyDocx::TableRow.new
|
5
|
+
tag.children.each do |child|
|
6
|
+
node.append(RubyDocx::Convertor::Html.create_node(child, css)) unless child.is_a?(Nokogiri::XML::Text)
|
7
|
+
end
|
8
|
+
node
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module RubyDocx::Convertor::Html
|
3
|
+
require_relative 'elements/html/base'
|
4
|
+
require_relative 'elements/html/paragraph'
|
5
|
+
require_relative 'elements/html/header'
|
6
|
+
require_relative 'elements/html/br'
|
7
|
+
require_relative 'elements/html/span'
|
8
|
+
require_relative 'elements/html/table'
|
9
|
+
require_relative 'elements/html/tr'
|
10
|
+
require_relative 'elements/html/td'
|
11
|
+
require_relative 'elements/html/th'
|
12
|
+
require_relative 'elements/html/hyperlink'
|
13
|
+
|
14
|
+
ROUTES = {
|
15
|
+
default: 'Paragraph',
|
16
|
+
h1: 'Header',
|
17
|
+
h2: 'Header',
|
18
|
+
h3: 'Header',
|
19
|
+
h4: 'Header',
|
20
|
+
h5: 'Header',
|
21
|
+
h6: 'Header',
|
22
|
+
a: 'Hyperlink'
|
23
|
+
}
|
24
|
+
|
25
|
+
def self.convert(template, css_path = nil)
|
26
|
+
css = self.load_styles(css_path)
|
27
|
+
doc = RubyDocx::Document.new
|
28
|
+
body = Nokogiri::HTML(template).xpath('//body').first
|
29
|
+
body.children.each { |child| doc.append self.create_node(child, css) }
|
30
|
+
doc
|
31
|
+
end
|
32
|
+
|
33
|
+
protected
|
34
|
+
def self.create_node(tag, css)
|
35
|
+
tag_name = tag.name.capitalize
|
36
|
+
unless RubyDocx::Convertor::Html.const_defined? tag_name
|
37
|
+
tag_name = ROUTES[tag.name.to_sym] || ROUTES[:default]
|
38
|
+
end
|
39
|
+
RubyDocx::Convertor::Html.const_get(tag_name).new(tag, css).build
|
40
|
+
end
|
41
|
+
|
42
|
+
##
|
43
|
+
# returns CssParser
|
44
|
+
def self.load_styles(css_path = nil)
|
45
|
+
default_css_path = File.expand_path("../../styles/default.css", __FILE__)
|
46
|
+
css = CssParser::Parser.new
|
47
|
+
css_block = File.read( default_css_path )
|
48
|
+
css_block += File.read( css_path ) if css_path
|
49
|
+
css.add_block!(css_block)
|
50
|
+
css
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
class RubyDocx::Block < RubyDocx::InextensibleBlock
|
3
|
+
attr_accessor :content, :children, :styles
|
4
|
+
|
5
|
+
def initialize(content = nil, styles = {}, children = [])
|
6
|
+
@content = content
|
7
|
+
@children = children
|
8
|
+
@styles = styles
|
9
|
+
|
10
|
+
@template = 'block.xml'
|
11
|
+
end
|
12
|
+
|
13
|
+
def append(block)
|
14
|
+
@children << block
|
15
|
+
end
|
16
|
+
|
17
|
+
def prepend(block)
|
18
|
+
@children.unshift block
|
19
|
+
end
|
20
|
+
|
21
|
+
def build
|
22
|
+
node = super
|
23
|
+
apply_styles(node)
|
24
|
+
@children.each { |child| node.add_child child.build }
|
25
|
+
node
|
26
|
+
end
|
27
|
+
|
28
|
+
protected
|
29
|
+
def apply_styles(node)
|
30
|
+
if styles.present?
|
31
|
+
properties_node = get_properties_node(node)
|
32
|
+
styles.each do |key, style|
|
33
|
+
apply_style(properties_node, key, style)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
node
|
37
|
+
end
|
38
|
+
|
39
|
+
def apply_style(properties_node, key, style)
|
40
|
+
case key
|
41
|
+
when 'text-align'
|
42
|
+
property_node = Nokogiri::XML::Node.new 'jc', properties_node.document
|
43
|
+
property_node['w:val'] = style
|
44
|
+
properties_node.add_child property_node
|
45
|
+
when 'font-weight'
|
46
|
+
if style == 'bold' || (style =~ /^\d+$/ && style.to_i > 500 )
|
47
|
+
properties_node.add_child Nokogiri::XML::Node.new 'b', properties_node.document
|
48
|
+
end
|
49
|
+
when 'font-size'
|
50
|
+
property_node = Nokogiri::XML::Node.new 'sz', properties_node.document
|
51
|
+
property_node['w:val'] = style.to_i * 2
|
52
|
+
properties_node.add_child property_node
|
53
|
+
|
54
|
+
property_node = Nokogiri::XML::Node.new 'szCs', properties_node.document
|
55
|
+
property_node['w:val'] = style.to_i * 2
|
56
|
+
properties_node.add_child property_node
|
57
|
+
end
|
58
|
+
properties_node
|
59
|
+
end
|
60
|
+
|
61
|
+
def get_properties_node(node)
|
62
|
+
properties_node_name = "#{node.name}Pr"
|
63
|
+
properties_node = node.children.find { |child| child.name == properties_node_name }
|
64
|
+
return properties_node if properties_node
|
65
|
+
properties_node = Nokogiri::XML::Node.new properties_node_name, node.document
|
66
|
+
if node.children.empty?
|
67
|
+
node.add_child(properties_node)
|
68
|
+
else
|
69
|
+
node.children.first.add_previous_sibling(properties_node)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
class RubyDocx::Document
|
3
|
+
TEMPLATE = 'document.xml'
|
4
|
+
|
5
|
+
attr_accessor :children
|
6
|
+
|
7
|
+
def initialize(children = [])
|
8
|
+
@children = children
|
9
|
+
end
|
10
|
+
|
11
|
+
def append(block)
|
12
|
+
@children << block
|
13
|
+
end
|
14
|
+
|
15
|
+
def prepend(block)
|
16
|
+
@children.unshift block
|
17
|
+
end
|
18
|
+
|
19
|
+
def build
|
20
|
+
doc = Nokogiri::XML(File.read( File.expand_path("../../templates/#{TEMPLATE}", __FILE__) ))
|
21
|
+
body = doc.at '/w:document/w:body'
|
22
|
+
@children.each { |child| body.add_child child.build }
|
23
|
+
doc
|
24
|
+
end
|
25
|
+
|
26
|
+
def render
|
27
|
+
build.to_s
|
28
|
+
end
|
29
|
+
|
30
|
+
def file
|
31
|
+
file = Tempfile.new('order_preview')
|
32
|
+
write_file(file)
|
33
|
+
end
|
34
|
+
|
35
|
+
def save(path)
|
36
|
+
file = File.open(path, 'w')
|
37
|
+
write_file(file).close
|
38
|
+
end
|
39
|
+
|
40
|
+
protected
|
41
|
+
def write_file(file)
|
42
|
+
zf = Zip::ZipFile.new File.expand_path("../../template.docx", __FILE__)
|
43
|
+
buffer = Zip::ZipOutputStream.write_buffer do |out|
|
44
|
+
zf.entries.each do |e|
|
45
|
+
if e.ftype == :directory
|
46
|
+
out.put_next_entry(e.name)
|
47
|
+
else
|
48
|
+
out.put_next_entry(e.name)
|
49
|
+
if e.name == "word/document.xml"
|
50
|
+
out.write render
|
51
|
+
else
|
52
|
+
out.write e.get_input_stream.read
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
file.write(buffer.string)
|
58
|
+
file
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
class RubyDocx::InextensibleBlock
|
3
|
+
attr_accessor :document, :styles
|
4
|
+
def build
|
5
|
+
build_node
|
6
|
+
end
|
7
|
+
|
8
|
+
def add_styles(adding_styles)
|
9
|
+
self.styles = ( styles.present? ? styles : {} ).merge(adding_styles)
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.create(*args)
|
13
|
+
new(*args).build
|
14
|
+
end
|
15
|
+
|
16
|
+
protected
|
17
|
+
def template
|
18
|
+
"#{self.class.to_s.split('::').last.underscore}.xml"
|
19
|
+
end
|
20
|
+
|
21
|
+
def build_node
|
22
|
+
Nokogiri::XML(File.read( File.expand_path("../../templates/#{template}", __FILE__) )).children.last
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
class RubyDocx::Paragraph < RubyDocx::Block
|
3
|
+
def build
|
4
|
+
# doc = RubyDocx::Convertor::Html.convert(nil); puts doc.render
|
5
|
+
# doc = RubyDocx::Convertor::Html.convert(nil); doc.save('/Users/Homer/Temp/creating.docx')
|
6
|
+
set = []
|
7
|
+
node = build_node
|
8
|
+
apply_styles node
|
9
|
+
set << node
|
10
|
+
@children.each do |child|
|
11
|
+
if child.is_a?(self.class)
|
12
|
+
child_set = child.build
|
13
|
+
unless child_set.all? { |cnode| cnode.name == 'p' && cnode.children.empty? }
|
14
|
+
child_set.each { |item| set << item }
|
15
|
+
end
|
16
|
+
elsif child.is_a?(RubyDocx::Table)
|
17
|
+
set << child.build
|
18
|
+
elsif (child.is_a?(RubyDocx::Row) || child.is_a?(RubyDocx::Br) || child.is_a?(RubyDocx::Hyperlink)) && set.size > 1
|
19
|
+
RubyDocx::Paragraph.new(nil, styles, [child]).build.each { |item| set << item }
|
20
|
+
else
|
21
|
+
node.add_child child.build
|
22
|
+
end
|
23
|
+
end
|
24
|
+
delete_empty_nodes set
|
25
|
+
node_set = Nokogiri::XML::NodeSet.new( document || Nokogiri::XML::Document.new )
|
26
|
+
set.each { |item| node_set << item }
|
27
|
+
node_set
|
28
|
+
end
|
29
|
+
|
30
|
+
protected
|
31
|
+
##
|
32
|
+
# removes empty node (<p/>) and convert <p><r><cr/></r></p> to <p><r/></p> that excess break lines are exluded
|
33
|
+
def delete_empty_nodes(set)
|
34
|
+
set.reject! { |node| node.name == 'p' && node.children.empty? }
|
35
|
+
set.select do |node|
|
36
|
+
node.name == 'p' &&
|
37
|
+
node.children.size == 1 &&
|
38
|
+
node.children.first.name == 'r' &&
|
39
|
+
node.children.first.children.size == 1 &&
|
40
|
+
node.children.first.children.first.name == 'cr'
|
41
|
+
end.each do |node|
|
42
|
+
node.children.first.children.remove
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def build_node
|
47
|
+
node = super
|
48
|
+
if content
|
49
|
+
rows = content.split("\n")
|
50
|
+
rows.each_with_index do |row, row_number|
|
51
|
+
node.add_child RubyDocx::Row.create(row)
|
52
|
+
if row_number != rows.size - 1
|
53
|
+
node.add_child RubyDocx::Br.create
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
node
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
class RubyDocx::Row < RubyDocx::Block
|
3
|
+
protected
|
4
|
+
def build_node
|
5
|
+
node = super
|
6
|
+
t_node = node.at('/r/t')
|
7
|
+
t_node.content = content
|
8
|
+
if styles['white-space'] == 'pre'
|
9
|
+
t_node['xml:space'] = 'preserve'
|
10
|
+
end
|
11
|
+
node
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
class RubyDocx::Table < RubyDocx::Block
|
3
|
+
protected
|
4
|
+
def apply_style(properties_node, key, style)
|
5
|
+
super
|
6
|
+
case key
|
7
|
+
when 'width'
|
8
|
+
if style =~ /^(\d+)%$/
|
9
|
+
property_node = Nokogiri::XML::Node.new 'tblW', properties_node.document
|
10
|
+
property_node['w:w'] = $1.to_i * 50 # 1% == 50 pct
|
11
|
+
property_node['w:type'] = 'pct'
|
12
|
+
properties_node.add_child property_node
|
13
|
+
end
|
14
|
+
when 'border'
|
15
|
+
border_size = style.split(' ').map(&:strip).find { |prop| prop =~ /^\d+(px)%/ }.to_i * 4
|
16
|
+
border_style = 'single'
|
17
|
+
border_color = 'auto'
|
18
|
+
if border_size
|
19
|
+
property_node = Nokogiri::XML::Node.new 'tblBorders', properties_node.document
|
20
|
+
%w[top left bottom right insideH insideV].each do |border|
|
21
|
+
border_node = Nokogiri::XML::Node.new border, properties_node.document
|
22
|
+
border_node['w:val'] = border_style
|
23
|
+
border_node['w:sz'] = border_size
|
24
|
+
border_node['w:color'] = border_color
|
25
|
+
border_node['w:space'] = 0
|
26
|
+
property_node.add_child border_node
|
27
|
+
end
|
28
|
+
properties_node.add_child property_node
|
29
|
+
end
|
30
|
+
end
|
31
|
+
properties_node
|
32
|
+
end
|
33
|
+
end
|
Binary file
|
@@ -0,0 +1 @@
|
|
1
|
+
<r><cr/></r>
|
@@ -0,0 +1,2 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
2
|
+
<w:document xmlns:wpc="http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas" xmlns:mo="http://schemas.microsoft.com/office/mac/office/2008/main" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mv="urn:schemas-microsoft-com:mac:vml" 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"><w:body/></w:document>
|
@@ -0,0 +1 @@
|
|
1
|
+
<hyperlink><r><t/></r></hyperlink>
|
@@ -0,0 +1 @@
|
|
1
|
+
<p/>
|
@@ -0,0 +1 @@
|
|
1
|
+
<r><t/></r>
|
@@ -0,0 +1 @@
|
|
1
|
+
<tbl/>
|
@@ -0,0 +1 @@
|
|
1
|
+
<tc/>
|
@@ -0,0 +1 @@
|
|
1
|
+
<tr/>
|
data/ruby_docx.gemspec
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'ruby_docx/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "ruby_docx"
|
8
|
+
gem.version = RubyDocx::VERSION
|
9
|
+
gem.authors = ["Dmitriy Mokrushin"]
|
10
|
+
gem.email = ["dimokr@ya.ru"]
|
11
|
+
gem.description = %q{Simple html to docx convertor}
|
12
|
+
gem.summary = %q{Simple html to docx convertor}
|
13
|
+
gem.homepage = "https://github.com/HoJSim/ruby_docx"
|
14
|
+
|
15
|
+
gem.files = `git ls-files`.split($/)
|
16
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
+
gem.require_paths = ["lib"]
|
19
|
+
gem.add_dependency 'nokogiri', '>= 1.5.5'
|
20
|
+
gem.add_dependency 'css_parser'
|
21
|
+
gem.add_dependency 'rubyzip'
|
22
|
+
end
|
metadata
ADDED
@@ -0,0 +1,132 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ruby_docx
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 0.0.4
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Dmitriy Mokrushin
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-03-14 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: nokogiri
|
16
|
+
version_requirements: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 1.5.5
|
22
|
+
requirement: !ruby/object:Gem::Requirement
|
23
|
+
none: false
|
24
|
+
requirements:
|
25
|
+
- - ! '>='
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: 1.5.5
|
28
|
+
type: :runtime
|
29
|
+
prerelease: false
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: css_parser
|
32
|
+
version_requirements: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
requirement: !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
type: :runtime
|
45
|
+
prerelease: false
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: rubyzip
|
48
|
+
version_requirements: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
requirement: !ruby/object:Gem::Requirement
|
55
|
+
none: false
|
56
|
+
requirements:
|
57
|
+
- - ! '>='
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '0'
|
60
|
+
type: :runtime
|
61
|
+
prerelease: false
|
62
|
+
description: Simple html to docx convertor
|
63
|
+
email:
|
64
|
+
- dimokr@ya.ru
|
65
|
+
executables: []
|
66
|
+
extensions: []
|
67
|
+
extra_rdoc_files: []
|
68
|
+
files:
|
69
|
+
- .gitignore
|
70
|
+
- Gemfile
|
71
|
+
- LICENSE.txt
|
72
|
+
- README.md
|
73
|
+
- Rakefile
|
74
|
+
- lib/ruby_docx.rb
|
75
|
+
- lib/ruby_docx/convertors/elements/html/base.rb
|
76
|
+
- lib/ruby_docx/convertors/elements/html/br.rb
|
77
|
+
- lib/ruby_docx/convertors/elements/html/header.rb
|
78
|
+
- lib/ruby_docx/convertors/elements/html/hyperlink.rb
|
79
|
+
- lib/ruby_docx/convertors/elements/html/paragraph.rb
|
80
|
+
- lib/ruby_docx/convertors/elements/html/span.rb
|
81
|
+
- lib/ruby_docx/convertors/elements/html/table.rb
|
82
|
+
- lib/ruby_docx/convertors/elements/html/td.rb
|
83
|
+
- lib/ruby_docx/convertors/elements/html/th.rb
|
84
|
+
- lib/ruby_docx/convertors/elements/html/tr.rb
|
85
|
+
- lib/ruby_docx/convertors/html.rb
|
86
|
+
- lib/ruby_docx/elements/block.rb
|
87
|
+
- lib/ruby_docx/elements/br.rb
|
88
|
+
- lib/ruby_docx/elements/document.rb
|
89
|
+
- lib/ruby_docx/elements/hyperlink.rb
|
90
|
+
- lib/ruby_docx/elements/inextensible_block.rb
|
91
|
+
- lib/ruby_docx/elements/paragraph.rb
|
92
|
+
- lib/ruby_docx/elements/row.rb
|
93
|
+
- lib/ruby_docx/elements/table.rb
|
94
|
+
- lib/ruby_docx/elements/table_column.rb
|
95
|
+
- lib/ruby_docx/elements/table_row.rb
|
96
|
+
- lib/ruby_docx/styles/default.css
|
97
|
+
- lib/ruby_docx/template.docx
|
98
|
+
- lib/ruby_docx/templates/br.xml
|
99
|
+
- lib/ruby_docx/templates/document.xml
|
100
|
+
- lib/ruby_docx/templates/hyperlink.xml
|
101
|
+
- lib/ruby_docx/templates/paragraph.xml
|
102
|
+
- lib/ruby_docx/templates/row.xml
|
103
|
+
- lib/ruby_docx/templates/table.xml
|
104
|
+
- lib/ruby_docx/templates/table_column.xml
|
105
|
+
- lib/ruby_docx/templates/table_row.xml
|
106
|
+
- lib/ruby_docx/version.rb
|
107
|
+
- ruby_docx.gemspec
|
108
|
+
homepage: https://github.com/HoJSim/ruby_docx
|
109
|
+
licenses: []
|
110
|
+
post_install_message:
|
111
|
+
rdoc_options: []
|
112
|
+
require_paths:
|
113
|
+
- lib
|
114
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
115
|
+
none: false
|
116
|
+
requirements:
|
117
|
+
- - ! '>='
|
118
|
+
- !ruby/object:Gem::Version
|
119
|
+
version: '0'
|
120
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
122
|
+
requirements:
|
123
|
+
- - ! '>='
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '0'
|
126
|
+
requirements: []
|
127
|
+
rubyforge_project:
|
128
|
+
rubygems_version: 1.8.25
|
129
|
+
signing_key:
|
130
|
+
specification_version: 3
|
131
|
+
summary: Simple html to docx convertor
|
132
|
+
test_files: []
|