rubyword 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +10 -0
- data/.rspec +1 -0
- data/CHANGELOG.txt +10 -0
- data/Gemfile +6 -0
- data/LICENSE +22 -0
- data/README.md +125 -0
- data/Rakefile +4 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/doc/README.md +1 -0
- data/doc/text.md +1 -0
- data/lib/rubyword/configuration.rb +5 -0
- data/lib/rubyword/document.rb +81 -0
- data/lib/rubyword/element/base.rb +12 -0
- data/lib/rubyword/element/image.rb +45 -0
- data/lib/rubyword/element/link.rb +35 -0
- data/lib/rubyword/element/list.rb +35 -0
- data/lib/rubyword/element/page_break.rb +26 -0
- data/lib/rubyword/element/section.rb +67 -0
- data/lib/rubyword/element/text.rb +137 -0
- data/lib/rubyword/element/text_break.rb +20 -0
- data/lib/rubyword/version.rb +3 -0
- data/lib/rubyword/writer/part/base.rb +13 -0
- data/lib/rubyword/writer/part/content_types.rb +39 -0
- data/lib/rubyword/writer/part/doc_props_app.rb +20 -0
- data/lib/rubyword/writer/part/doc_props_core.rb +32 -0
- data/lib/rubyword/writer/part/doc_props_custom.rb +16 -0
- data/lib/rubyword/writer/part/document.rb +56 -0
- data/lib/rubyword/writer/part/font_table.rb +12 -0
- data/lib/rubyword/writer/part/footer.rb +50 -0
- data/lib/rubyword/writer/part/header.rb +40 -0
- data/lib/rubyword/writer/part/numbering.rb +51 -0
- data/lib/rubyword/writer/part/rels.rb +26 -0
- data/lib/rubyword/writer/part/rels_document.rb +31 -0
- data/lib/rubyword/writer/part/settings.rb +93 -0
- data/lib/rubyword/writer/part/styles.rb +91 -0
- data/lib/rubyword/writer/part/theme.rb +12 -0
- data/lib/rubyword/writer/part/toc.rb +89 -0
- data/lib/rubyword/writer/part/web_settings.rb +21 -0
- data/lib/rubyword/writer/style/base.rb +16 -0
- data/lib/rubyword/writer/style/section.rb +65 -0
- data/lib/rubyword/writer.rb +87 -0
- data/lib/rubyword.rb +9 -0
- data/rubyword.gemspec +27 -0
- data/sample/test.rb +78 -0
- data/spec/rubyword/document_spec.rb +11 -0
- data/spec/spec_helper.rb +32 -0
- data/template/fontTable.xml +54 -0
- data/template/theme.xml +284 -0
- metadata +197 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 94a411b43cd5b8e055aa0d391332d91e29b5a9eb
|
4
|
+
data.tar.gz: 3253a4e9f289ba99b9e62a0ab73b1cb43c223d58
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d67230b2cb422a7a5631c9844a1fa44b77a0739b683dfcecd86b9e090989ade5d625d7dfb8a1d17aef10c9a8290a59799a95fd092507b0bd40554aea31a28557
|
7
|
+
data.tar.gz: 82ebc3d3424424abc1293896448472dc53d76f41fbbb921e6eeb158793172c017992458c07819c011674d29737e4f7dff8e78c115c3181379a79bd9f389778b1
|
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--require spec_helper
|
data/CHANGELOG.txt
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
CHANGELOG
|
2
|
+
Version 0.1.0:
|
3
|
+
* Support for setting the properties of the document, such as: title, subject, author and other information
|
4
|
+
* Support for generated TOC for the title
|
5
|
+
* Support for setting header and footer
|
6
|
+
* Support for insert title which is different attributes, such as: title, sub title, etc.
|
7
|
+
* Support for insert blank lines and blank page
|
8
|
+
* Support for insert multiple images
|
9
|
+
* Support for insert multiple lists
|
10
|
+
* Support for insert hyperlink
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Nicholas Frandsen
|
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,125 @@
|
|
1
|
+
# RubyWord: Microsoft Word Generation For Ruby
|
2
|
+
> RubyWord is a simple, efficient Word document generation gem and easy to generate docx file.
|
3
|
+
|
4
|
+
# Please Read Before Use
|
5
|
+
This project is under developing, and develop by myself until now, so the progress may be slow and there may be a lot of problems, but i will try my best to improve it and welcome everyone to join the development. Thanks for supporting.
|
6
|
+
|
7
|
+
# Installing RubyWord
|
8
|
+
```
|
9
|
+
gem install rubyword
|
10
|
+
```
|
11
|
+
or put this line in your Gemfile
|
12
|
+
```
|
13
|
+
gem 'rubyword'
|
14
|
+
```
|
15
|
+
# Features
|
16
|
+
+ Support for setting the properties of the document, such as: title, subject, author and other information
|
17
|
+
+ Support for generated TOC for the title
|
18
|
+
+ Support for setting header and footer
|
19
|
+
+ Support for insert title which is different attributes, such as: title, sub title, etc.
|
20
|
+
+ Support for insert blank lines and blank page
|
21
|
+
+ Support for insert multiple images
|
22
|
+
+ Support for insert multiple lists
|
23
|
+
+ Support for insert hyperlink
|
24
|
+
|
25
|
+
# Usage
|
26
|
+
```
|
27
|
+
require "rubyword"
|
28
|
+
Rubyword::Document::generate('hello.docx') {
|
29
|
+
# write the doc infomation
|
30
|
+
information({
|
31
|
+
company: 'ruby word',
|
32
|
+
creator: 'young',
|
33
|
+
title: 'example word file',
|
34
|
+
description: 'this is a example docx',
|
35
|
+
subject: 'how to create doc info',
|
36
|
+
keywords: 'remark',
|
37
|
+
category: 'category'
|
38
|
+
})
|
39
|
+
|
40
|
+
# Generate the directory structure
|
41
|
+
title_directory font_size: 24
|
42
|
+
|
43
|
+
# insert header
|
44
|
+
add_header 'rubyword'
|
45
|
+
|
46
|
+
# insert footer with number
|
47
|
+
add_footer nil, text_align: 'center', nums_type: 'number'
|
48
|
+
# insert text
|
49
|
+
# add_footer 'hello', text_align: 'center'
|
50
|
+
# initialize section and insert something in the section
|
51
|
+
section {
|
52
|
+
# insert title
|
53
|
+
title_1 "It's a title", ignore_dir: true
|
54
|
+
# insert subtitle
|
55
|
+
title_2 "It's a subtitle"
|
56
|
+
# insert title
|
57
|
+
title_1 'Database'
|
58
|
+
# insert subtitle
|
59
|
+
title_2 'MySQL'
|
60
|
+
# insert No.3 title
|
61
|
+
title_3 'NoSQL'
|
62
|
+
# text break
|
63
|
+
text_break 3
|
64
|
+
# insert text
|
65
|
+
text 'hello word', bgcolor: 'yellow', text_align: 'center'
|
66
|
+
# page break
|
67
|
+
page_break 2
|
68
|
+
# insert text
|
69
|
+
text 'hello word', indent_between: '1440-1440'
|
70
|
+
text 'title', { font_size: 62, color: '996699', blod: true, text_align: 'center' }
|
71
|
+
|
72
|
+
# insert title
|
73
|
+
title_1 'section2 title'
|
74
|
+
title_2 'section2 title'
|
75
|
+
title_3 'section2 title'
|
76
|
+
|
77
|
+
# add a link
|
78
|
+
link 'baidu', 'http://www.baidu.com', text_align: 'center'
|
79
|
+
}
|
80
|
+
|
81
|
+
section {
|
82
|
+
# insert a text
|
83
|
+
text 'another Section', bgcolor: 'yellow', text_align: 'center'
|
84
|
+
|
85
|
+
# insert a text
|
86
|
+
text 'hello word', indent_between: '1440-1440'
|
87
|
+
text 'title', { font_size: 62, color: '996699', blod: true, text_align: 'center' }
|
88
|
+
}
|
89
|
+
|
90
|
+
section {
|
91
|
+
list 'test1', 1
|
92
|
+
list 'test1', 2
|
93
|
+
list 'test3', 2
|
94
|
+
list 'test2', 1
|
95
|
+
list 'test2', 1
|
96
|
+
}
|
97
|
+
|
98
|
+
section {
|
99
|
+
# add a link
|
100
|
+
link 'baidu', 'http://www.baidu.com', text_align: 'center'
|
101
|
+
image 'http://www.baidu.com/img/bd_logo1.png'
|
102
|
+
}
|
103
|
+
}
|
104
|
+
```
|
105
|
+
|
106
|
+
# TODO
|
107
|
+
+ Support table
|
108
|
+
+ Support paragraph
|
109
|
+
+ Support more style
|
110
|
+
+ Support Markdown/HTML to docx
|
111
|
+
|
112
|
+
# Contributing
|
113
|
+
RubyWord is use my spare time to write, so it may has a lot of Bugs and welcome everyone to create Pull Request or Issue to improve this project together.
|
114
|
+
1. fork this project
|
115
|
+
2. git clone your fork project
|
116
|
+
3. git checkout -b fixed-something
|
117
|
+
4. git commit fixed some bug.
|
118
|
+
5. git push to your fork project
|
119
|
+
6. create a new pr to request merge
|
120
|
+
|
121
|
+
# Inspiration
|
122
|
+
Thanks [PHPWord](https://github.com/PHPOffice/PHPWord), I was very surprised when I saw the PHPWord project which is a very powerful project and provide a lot of features. But I can't find such as ruby project when i search in google and I decided to write and design by myself.
|
123
|
+
|
124
|
+
# License
|
125
|
+
RubyWord is licensed under [The MIT License](LICENSE)
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "rubyword"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
data/doc/README.md
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
# keep
|
data/doc/text.md
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
# keep
|
@@ -0,0 +1,81 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
require_relative "element/section"
|
3
|
+
require_relative "writer"
|
4
|
+
module Rubyword
|
5
|
+
class Document
|
6
|
+
attr_accessor :sections, :init_rid
|
7
|
+
attr_accessor :relation_rids, :content_types, :rels_documents, :images
|
8
|
+
attr_accessor :header, :footer
|
9
|
+
attr_accessor :doc_info, :toc
|
10
|
+
include Writer
|
11
|
+
|
12
|
+
def self.generate(filename, options = {}, &block)
|
13
|
+
rubyword = new(options, &block)
|
14
|
+
rubyword.save(filename)
|
15
|
+
end
|
16
|
+
|
17
|
+
def initialize(options={}, &block)
|
18
|
+
@sections, @toc, @init_rid, @doc_info = [], {}, 7, {}
|
19
|
+
@relation_rids = []
|
20
|
+
@content_types = []
|
21
|
+
@rels_documents = []
|
22
|
+
@images = []
|
23
|
+
instance_eval(&block) if block_given?
|
24
|
+
end
|
25
|
+
|
26
|
+
def section(style=nil, &block)
|
27
|
+
@section = Element::Section.new(@sections.count + 1, style, self)
|
28
|
+
self.sections << @section
|
29
|
+
@section.instance_eval(&block) if block_given?
|
30
|
+
end
|
31
|
+
|
32
|
+
def title_directory(option= {})
|
33
|
+
@toc.merge!(open: true)
|
34
|
+
@toc.merge!(option)
|
35
|
+
end
|
36
|
+
|
37
|
+
def add_header(text, options={})
|
38
|
+
@header = {
|
39
|
+
id: 1,
|
40
|
+
text: text,
|
41
|
+
rid: self.init_rid,
|
42
|
+
text_align: options[:align] || 'center',
|
43
|
+
type: 'header'
|
44
|
+
}
|
45
|
+
self.content_types << {
|
46
|
+
"/word/header1.xml" => "application/vnd.openxmlformats-officedocument.wordprocessingml.header+xml"
|
47
|
+
}
|
48
|
+
self.rels_documents << {
|
49
|
+
Id: "rId#{self.init_rid}",
|
50
|
+
Type: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/header",
|
51
|
+
Target: "header1.xml"
|
52
|
+
}
|
53
|
+
self.init_rid = self.init_rid + 1
|
54
|
+
end
|
55
|
+
|
56
|
+
def add_footer(text=nil, options={})
|
57
|
+
@footer = {
|
58
|
+
id: 1,
|
59
|
+
text: text,
|
60
|
+
rid: self.init_rid,
|
61
|
+
text_align: options[:align] || 'center',
|
62
|
+
nums_type: options[:nums_type],
|
63
|
+
type: 'footer'
|
64
|
+
}
|
65
|
+
self.content_types << {
|
66
|
+
"/word/footer1.xml" => "application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml"
|
67
|
+
}
|
68
|
+
self.rels_documents << {
|
69
|
+
Id: "rId#{self.init_rid}",
|
70
|
+
Type: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/footer",
|
71
|
+
Target: "footer1.xml"
|
72
|
+
}
|
73
|
+
self.init_rid = self.init_rid + 1
|
74
|
+
end
|
75
|
+
|
76
|
+
def information(options={})
|
77
|
+
@doc_info = options
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
module Rubyword
|
3
|
+
module Element
|
4
|
+
class Image < Base
|
5
|
+
attr_accessor :images
|
6
|
+
def save(url, style=nil)
|
7
|
+
@images ||= Queue.new
|
8
|
+
filename = url.split('/').last
|
9
|
+
width, height = FastImage.size(url)
|
10
|
+
image_params = {
|
11
|
+
rid: @rubyword.init_rid,
|
12
|
+
path: url,
|
13
|
+
width: width,
|
14
|
+
height: height,
|
15
|
+
filename: filename
|
16
|
+
}
|
17
|
+
@images << image_params
|
18
|
+
@rubyword.images << image_params
|
19
|
+
@rubyword.rels_documents << {
|
20
|
+
Id: "rId#{@rubyword.init_rid}",
|
21
|
+
Type: 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image',
|
22
|
+
Target: "media/#{filename}"
|
23
|
+
}
|
24
|
+
@rubyword.init_rid = @rubyword.init_rid + 1
|
25
|
+
end
|
26
|
+
|
27
|
+
def write(section=nil, xml=nil)
|
28
|
+
@xml = xml
|
29
|
+
image = self.images.pop
|
30
|
+
@xml.send('w:p') {
|
31
|
+
@xml.send('w:pPr')
|
32
|
+
@xml.send('w:r') {
|
33
|
+
@xml.send('w:pict') {
|
34
|
+
@xml.send('v:shape', 'type' => '#_x0000_t75', 'style' => "width:#{image[:width]}px; height:#{image[:height]}px; margin-left:0px; margin-top:0px; mso-position-horizontal:left; mso-position-vertical:top; mso-position-horizontal-relative:char; mso-position-vertical-relative:line;") {
|
35
|
+
@xml.send('w10:wrap', 'type' => 'inline', 'anchorx' => 'page', 'anchory' => 'page')
|
36
|
+
@xml.send('v:imagedata', 'r:id' => "rId#{image[:rid]}", 'o:title' => '')
|
37
|
+
}
|
38
|
+
}
|
39
|
+
}
|
40
|
+
}
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
module Rubyword
|
3
|
+
module Element
|
4
|
+
class Link < Base
|
5
|
+
attr_accessor :links
|
6
|
+
def save(text, link, style)
|
7
|
+
@links ||= Queue.new
|
8
|
+
return if text.nil?
|
9
|
+
@rubyword.rels_documents << {
|
10
|
+
Id: "rId#{@rubyword.init_rid}",
|
11
|
+
Type: 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink',
|
12
|
+
Target: link,
|
13
|
+
TargetMode: 'External'
|
14
|
+
}
|
15
|
+
@links << { rId: @rubyword.init_rid, text: text, link: link }
|
16
|
+
@rubyword.init_rid = @rubyword.init_rid + 1
|
17
|
+
end
|
18
|
+
|
19
|
+
def write(section=nil, xml=nil)
|
20
|
+
@xml = xml
|
21
|
+
link = self.links.pop
|
22
|
+
@xml.send('w:p') {
|
23
|
+
@xml.send('hyperlink', 'r:id' => "rId#{link[:rId]}", 'w:history' => '1') {
|
24
|
+
@xml.send('w:r') {
|
25
|
+
# TODO: add style
|
26
|
+
@xml.send('w:rPr')
|
27
|
+
@xml.send('w:t', {'xml:space' => 'preserve'}, link[:text])
|
28
|
+
}
|
29
|
+
}
|
30
|
+
}
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
module Rubyword
|
3
|
+
module Element
|
4
|
+
class List < Base
|
5
|
+
attr_accessor :lists
|
6
|
+
|
7
|
+
# write document and numbering
|
8
|
+
def save(text, level, style)
|
9
|
+
@lists ||= Queue.new
|
10
|
+
@lists << {
|
11
|
+
level: level.to_i - 1,
|
12
|
+
text: text
|
13
|
+
}
|
14
|
+
end
|
15
|
+
|
16
|
+
def write(section=nil, xml=nil)
|
17
|
+
@xml = xml
|
18
|
+
list = self.lists.pop
|
19
|
+
@xml.send('w:p') {
|
20
|
+
@xml.send('w:pPr') {
|
21
|
+
@xml.send('w:numPr') {
|
22
|
+
@xml.send('w:ilvl', 'w:val' => list[:level])
|
23
|
+
@xml.send('w:numId', 'w:val' => 3)
|
24
|
+
}
|
25
|
+
}
|
26
|
+
@xml.send('w:r') {
|
27
|
+
@xml.send('w:rPr')
|
28
|
+
@xml.send('w:t', {'xml:space' => 'preserve'}, list[:text])
|
29
|
+
}
|
30
|
+
}
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
module Rubyword
|
3
|
+
module Element
|
4
|
+
class PageBreak < Base
|
5
|
+
attr_accessor :numbers
|
6
|
+
|
7
|
+
def save(numbers)
|
8
|
+
@numbers ||= Queue.new
|
9
|
+
@numbers << numbers.to_i
|
10
|
+
end
|
11
|
+
|
12
|
+
def write(section=nil, xml=nil)
|
13
|
+
@xml = xml
|
14
|
+
page_break = self.numbers.pop
|
15
|
+
page_break.to_i.times.each do |i|
|
16
|
+
@xml.send('w:p') {
|
17
|
+
@xml.send('w:r') {
|
18
|
+
@xml.send('w:br', 'w:type' => 'page')
|
19
|
+
}
|
20
|
+
}
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require_relative 'base'
|
3
|
+
require_relative 'text'
|
4
|
+
require_relative 'link'
|
5
|
+
require_relative 'list'
|
6
|
+
require_relative 'image'
|
7
|
+
require_relative 'page_break'
|
8
|
+
require_relative 'text_break'
|
9
|
+
module Rubyword
|
10
|
+
module Element
|
11
|
+
class Section
|
12
|
+
attr_accessor :section_id, :style, :rubyword, :section_objects, :objects, :titles
|
13
|
+
def initialize(section_count, style = nil, rubyword=nil)
|
14
|
+
@section_id = section_count
|
15
|
+
@style = style
|
16
|
+
@rubyword = rubyword
|
17
|
+
@section_objects = []
|
18
|
+
@objects = []
|
19
|
+
end
|
20
|
+
|
21
|
+
def generate(&block)
|
22
|
+
!block.nil? && block.arity < 1 ? instance_eval(&block) : block[self]
|
23
|
+
end
|
24
|
+
|
25
|
+
def text(text, style=nil)
|
26
|
+
object ||= Text.new(@rubyword, self)
|
27
|
+
object.save(text, __callee__.to_s, style)
|
28
|
+
@objects << object
|
29
|
+
end
|
30
|
+
alias :title_1 :text
|
31
|
+
alias :title_2 :text
|
32
|
+
alias :title_3 :text
|
33
|
+
alias :title_4 :text
|
34
|
+
|
35
|
+
def list(text, level, style=nil)
|
36
|
+
object ||= List.new(@rubyword)
|
37
|
+
object.save(text, level, style)
|
38
|
+
@objects << object
|
39
|
+
end
|
40
|
+
|
41
|
+
def image(url)
|
42
|
+
object ||= Image.new(@rubyword)
|
43
|
+
object.save(url)
|
44
|
+
@objects << object
|
45
|
+
end
|
46
|
+
|
47
|
+
def link(text, link, style=nil)
|
48
|
+
object ||= Link.new(@rubyword)
|
49
|
+
object.save(text, link, style)
|
50
|
+
@objects << object
|
51
|
+
end
|
52
|
+
|
53
|
+
def page_break(break_num=1)
|
54
|
+
object ||= PageBreak.new(@rubyword)
|
55
|
+
object.save(break_num)
|
56
|
+
@objects << object
|
57
|
+
end
|
58
|
+
|
59
|
+
def text_break(break_num=1)
|
60
|
+
object ||= TextBreak.new(@rubyword)
|
61
|
+
object.save(break_num)
|
62
|
+
@objects << object
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,137 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
module Rubyword
|
3
|
+
module Element
|
4
|
+
class Text < Base
|
5
|
+
attr_accessor :texts
|
6
|
+
|
7
|
+
IndentSize = 200
|
8
|
+
WordStyleList = {
|
9
|
+
font_size: 'w:sz',
|
10
|
+
color: 'w:color',
|
11
|
+
underline: 'w:u',
|
12
|
+
blod: 'w:b',
|
13
|
+
all_caps: 'w:caps',
|
14
|
+
italic: 'w:i',
|
15
|
+
bgcolor: 'w:highlight'
|
16
|
+
}.freeze
|
17
|
+
ParagraphStyleList = {
|
18
|
+
text_align: 'w:jc',
|
19
|
+
spacing: 'w:spacing',
|
20
|
+
indent_left: 'w:ind',
|
21
|
+
indent_right: 'w:ind',
|
22
|
+
indent_between: 'w:ind'
|
23
|
+
}.freeze
|
24
|
+
|
25
|
+
def save(text, type, style)
|
26
|
+
@texts ||= Queue.new
|
27
|
+
@section.titles ||= []
|
28
|
+
return if text.nil?
|
29
|
+
if type == 'text'
|
30
|
+
text(text, style)
|
31
|
+
else
|
32
|
+
self.send(type.to_sym, text, style)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def text(text, style)
|
37
|
+
@texts << { size: 'normal', text: text.to_s, style: style }
|
38
|
+
end
|
39
|
+
|
40
|
+
(1..4).each do |num|
|
41
|
+
define_method "title_#{num}" do |text, style|
|
42
|
+
@rubyword.relation_rids << {rid: @rubyword.init_rid, type: "title_#{num}"}
|
43
|
+
title_hs = {
|
44
|
+
indent: (num - 1) * IndentSize,
|
45
|
+
size: "title_#{num}",
|
46
|
+
text: text.to_s,
|
47
|
+
rid: @rubyword.init_rid,
|
48
|
+
style: style
|
49
|
+
}
|
50
|
+
@section.titles << title_hs if (style && !style[:ignore_dir]) || style.nil?
|
51
|
+
@texts << title_hs
|
52
|
+
@rubyword.init_rid = @rubyword.init_rid + 1
|
53
|
+
end
|
54
|
+
|
55
|
+
define_method "write_title_#{num}" do |args|
|
56
|
+
@xml.send('w:p') do
|
57
|
+
@xml.send('w:pPr') {
|
58
|
+
@xml.send('w:pStyle', 'w:val' => "Heading#{num}")
|
59
|
+
}
|
60
|
+
@xml.send('bookmarkStart', 'w:id' => args[:rid], 'w:name' => "_Toc#{args[:rid]}")
|
61
|
+
@xml.send('w:r') {
|
62
|
+
@xml.send('w:t', args[:text])
|
63
|
+
}
|
64
|
+
@xml.send('bookmarkEnd', 'w:id' => args[:rid])
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def write(section=nil, xml=nil)
|
70
|
+
@xml = xml
|
71
|
+
text = self.texts.pop
|
72
|
+
eval "write_#{text[:size]}(text)"
|
73
|
+
end
|
74
|
+
|
75
|
+
def write_normal(text)
|
76
|
+
@xml.send('w:p') do
|
77
|
+
write_paragraph_style(text[:style])
|
78
|
+
@xml.send('w:r') do
|
79
|
+
write_word_style(text[:style])
|
80
|
+
@xml.send('w:t', {'xml:space' => 'preserve'}, text[:text])
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def write_word_style(style)
|
86
|
+
if style.is_a?(Hash)
|
87
|
+
@xml.send('w:rPr') {
|
88
|
+
style.keys.each do |style_name|
|
89
|
+
style_name = style_name.to_sym
|
90
|
+
if WordStyleList.keys.include?(style_name)
|
91
|
+
value =style[style_name]
|
92
|
+
attribute = if !!value != value # not a bool type
|
93
|
+
{'w:val' => value}
|
94
|
+
else
|
95
|
+
nil
|
96
|
+
end
|
97
|
+
doc_style = WordStyleList[style_name]
|
98
|
+
@xml.send(doc_style, attribute)
|
99
|
+
@xml.send('w:szCs', attribute) if style_name == :font_size
|
100
|
+
end
|
101
|
+
end
|
102
|
+
}
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def write_paragraph_style(style)
|
107
|
+
return unless style.is_a?(Hash)
|
108
|
+
@xml.send('w:pPr') {
|
109
|
+
style.keys.each do |style_name|
|
110
|
+
style_name = style_name.to_sym
|
111
|
+
next unless ParagraphStyleList.keys.include?(style_name)
|
112
|
+
value =style[style_name]
|
113
|
+
attribute = case style_name.to_s
|
114
|
+
when 'spacing'
|
115
|
+
{'w:after' => value}
|
116
|
+
when 'indent_left'
|
117
|
+
{'w:left' => value}
|
118
|
+
when 'indent_right'
|
119
|
+
{'w:right' => value}
|
120
|
+
when 'indent_between'
|
121
|
+
v = value.split '-'
|
122
|
+
next unless v.is_a?(Array)
|
123
|
+
{ 'w:left' => v[0].to_i, 'w:right' => v[1].to_i }
|
124
|
+
when !!value == value
|
125
|
+
nil
|
126
|
+
else
|
127
|
+
{'w:val' => value}
|
128
|
+
end
|
129
|
+
doc_style = ParagraphStyleList[style_name]
|
130
|
+
@xml.send(doc_style, attribute)
|
131
|
+
end
|
132
|
+
}
|
133
|
+
end
|
134
|
+
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|