ruby-rtf 0.0.1
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 +10 -0
- data/.infinity_test +24 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +101 -0
- data/LICENSE +18 -0
- data/README +12 -0
- data/Rakefile +20 -0
- data/bin/rtf_parse +112 -0
- data/lib/ruby-rtf.rb +11 -0
- data/lib/ruby-rtf/colour.rb +50 -0
- data/lib/ruby-rtf/document.rb +36 -0
- data/lib/ruby-rtf/font.rb +83 -0
- data/lib/ruby-rtf/invalid_document.rb +4 -0
- data/lib/ruby-rtf/parser.rb +492 -0
- data/lib/ruby-rtf/ruby-rtf.rb +7 -0
- data/lib/ruby-rtf/table.rb +72 -0
- data/lib/ruby-rtf/version.rb +5 -0
- data/ruby-rtf.gemspec +30 -0
- data/spec/colour_spec.rb +12 -0
- data/spec/document_spec.rb +38 -0
- data/spec/font_spec.rb +15 -0
- data/spec/parser_spec.rb +926 -0
- data/spec/spec_helper.rb +1 -0
- metadata +130 -0
data/.gitignore
ADDED
data/.infinity_test
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
infinity_test do
|
2
|
+
notifications :growl do
|
3
|
+
show_images :mode => :hands
|
4
|
+
end
|
5
|
+
|
6
|
+
use :test_framework => :rspec
|
7
|
+
|
8
|
+
before_run { clear :terminal }
|
9
|
+
|
10
|
+
heuristics do
|
11
|
+
add('^spec/(.*)_spec.rb') do |file|
|
12
|
+
run :test_for => file
|
13
|
+
end
|
14
|
+
add('^spec/spec_helper.rb') do |file|
|
15
|
+
run :all => :tests
|
16
|
+
end
|
17
|
+
add('^lib/ruby-rtf.rb') do |file|
|
18
|
+
run :all => :tests
|
19
|
+
end
|
20
|
+
add('^lib/(.*)\.rb') do |file|
|
21
|
+
run :test_for => file[1].split('/').last
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
ruby-rtf (0.0.1)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: http://rubygems.org/
|
8
|
+
specs:
|
9
|
+
Saikuro (1.1.0)
|
10
|
+
abstract (1.0.0)
|
11
|
+
activesupport (3.0.4)
|
12
|
+
arrayfields (4.7.4)
|
13
|
+
bluecloth (2.0.11)
|
14
|
+
chronic (0.2.3)
|
15
|
+
hoe (>= 1.2.1)
|
16
|
+
churn (0.0.13)
|
17
|
+
chronic (>= 0.2.3)
|
18
|
+
hirb
|
19
|
+
json_pure
|
20
|
+
main
|
21
|
+
ruby_parser (~> 2.0.4)
|
22
|
+
sexp_processor (~> 3.0.3)
|
23
|
+
colored (1.2)
|
24
|
+
diff-lcs (1.1.2)
|
25
|
+
erubis (2.6.6)
|
26
|
+
abstract (>= 1.0.0)
|
27
|
+
fattr (2.2.0)
|
28
|
+
flay (1.4.2)
|
29
|
+
ruby_parser (~> 2.0)
|
30
|
+
sexp_processor (~> 3.0)
|
31
|
+
flog (2.5.1)
|
32
|
+
ruby_parser (~> 2.0)
|
33
|
+
sexp_processor (~> 3.0)
|
34
|
+
haml (3.0.25)
|
35
|
+
hirb (0.3.6)
|
36
|
+
hoe (2.9.1)
|
37
|
+
rake (>= 0.8.7)
|
38
|
+
i18n (0.5.0)
|
39
|
+
infinity_test (1.0.2)
|
40
|
+
notifiers (>= 1.1.0)
|
41
|
+
watchr (>= 0.7)
|
42
|
+
json_pure (1.5.1)
|
43
|
+
main (4.4.0)
|
44
|
+
arrayfields (>= 4.7.4)
|
45
|
+
fattr (>= 2.1.0)
|
46
|
+
metric_fu (2.0.1)
|
47
|
+
Saikuro (>= 1.1.0)
|
48
|
+
activesupport (>= 2.0.0)
|
49
|
+
chronic (~> 0.2.3)
|
50
|
+
churn (>= 0.0.7)
|
51
|
+
flay (>= 1.2.1)
|
52
|
+
flog (>= 2.2.0)
|
53
|
+
rails_best_practices (>= 0.3.16)
|
54
|
+
rcov (>= 0.8.3.3)
|
55
|
+
reek (>= 1.2.6)
|
56
|
+
roodi (>= 2.1.0)
|
57
|
+
notifiers (1.1.0)
|
58
|
+
rails_best_practices (0.7.0)
|
59
|
+
activesupport
|
60
|
+
colored (~> 1.2)
|
61
|
+
erubis (~> 2.6.6)
|
62
|
+
haml (~> 3.0.18)
|
63
|
+
i18n
|
64
|
+
ruby-progressbar (~> 0.0.9)
|
65
|
+
ruby_parser (~> 2.0.4)
|
66
|
+
rake (0.8.7)
|
67
|
+
rcov (0.9.9)
|
68
|
+
reek (1.2.8)
|
69
|
+
ruby2ruby (~> 1.2)
|
70
|
+
ruby_parser (~> 2.0)
|
71
|
+
sexp_processor (~> 3.0)
|
72
|
+
roodi (2.1.0)
|
73
|
+
ruby_parser
|
74
|
+
rspec (2.5.0)
|
75
|
+
rspec-core (~> 2.5.0)
|
76
|
+
rspec-expectations (~> 2.5.0)
|
77
|
+
rspec-mocks (~> 2.5.0)
|
78
|
+
rspec-core (2.5.1)
|
79
|
+
rspec-expectations (2.5.0)
|
80
|
+
diff-lcs (~> 1.1.2)
|
81
|
+
rspec-mocks (2.5.0)
|
82
|
+
ruby-progressbar (0.0.9)
|
83
|
+
ruby2ruby (1.2.5)
|
84
|
+
ruby_parser (~> 2.0)
|
85
|
+
sexp_processor (~> 3.0)
|
86
|
+
ruby_parser (2.0.6)
|
87
|
+
sexp_processor (~> 3.0)
|
88
|
+
sexp_processor (3.0.5)
|
89
|
+
watchr (0.7)
|
90
|
+
yard (0.6.4)
|
91
|
+
|
92
|
+
PLATFORMS
|
93
|
+
ruby
|
94
|
+
|
95
|
+
DEPENDENCIES
|
96
|
+
bluecloth
|
97
|
+
infinity_test
|
98
|
+
metric_fu
|
99
|
+
rspec (> 2.0)
|
100
|
+
ruby-rtf!
|
101
|
+
yard
|
data/LICENSE
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
Copyright (c) 2011 dan sinclair
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to
|
5
|
+
deal in the Software without restriction, including without limitation the
|
6
|
+
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
7
|
+
sell copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
16
|
+
THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
17
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
18
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
RubyRTF
|
2
|
+
=======
|
3
|
+
|
4
|
+
The Ruby RTF library is an attempt to parse RTF files. There is a lot still missing
|
5
|
+
but the basics are there including the beginnings of table support.
|
6
|
+
|
7
|
+
You can see an example of using the library in the bin/rtf_parse script which attempts
|
8
|
+
to convert an RTF file to an HTML file.
|
9
|
+
|
10
|
+
Issues
|
11
|
+
======
|
12
|
+
Please report any issues to the GitHub Issue tracker (https://github.com/dj2/ruby-rtf).
|
data/Rakefile
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
Bundler::GemHelper.install_tasks
|
3
|
+
|
4
|
+
require 'yard'
|
5
|
+
require 'rspec/core/rake_task'
|
6
|
+
|
7
|
+
require 'metric_fu'
|
8
|
+
|
9
|
+
task :default => [:spec]
|
10
|
+
|
11
|
+
desc "run spec tests"
|
12
|
+
RSpec::Core::RakeTask.new('spec') do |t|
|
13
|
+
t.pattern = 'spec/**/*_spec.rb'
|
14
|
+
end
|
15
|
+
|
16
|
+
desc 'Generate Documentation'
|
17
|
+
YARD::Rake::YardocTask.new do |t|
|
18
|
+
t.files = ['lib/**/*.rb', '-', 'LICENSE']
|
19
|
+
t.options = ['--main', 'README', '--no-private', '--hide-void-return']
|
20
|
+
end
|
data/bin/rtf_parse
ADDED
@@ -0,0 +1,112 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: utf-8
|
3
|
+
|
4
|
+
require 'ruby-rtf'
|
5
|
+
require 'pp'
|
6
|
+
|
7
|
+
@prefix = ''
|
8
|
+
@suffix = ''
|
9
|
+
|
10
|
+
def add(open, close = open)
|
11
|
+
@prefix << "<#{open}>"
|
12
|
+
@suffix = "</#{close}>#{@suffix}"
|
13
|
+
end
|
14
|
+
|
15
|
+
def format(str, section)
|
16
|
+
@prefix = ''
|
17
|
+
@suffix = ''
|
18
|
+
|
19
|
+
mods = section[:modifiers]
|
20
|
+
|
21
|
+
if mods[:paragraph]
|
22
|
+
if section[:text].empty?
|
23
|
+
str << "<p></p>\n"
|
24
|
+
else
|
25
|
+
add('p')
|
26
|
+
end
|
27
|
+
|
28
|
+
elsif mods[:tab]
|
29
|
+
str << " "
|
30
|
+
return
|
31
|
+
elsif mods[:newline]
|
32
|
+
str << "<br />\n"
|
33
|
+
return
|
34
|
+
elsif mods[:rquote]
|
35
|
+
str << "’"
|
36
|
+
return
|
37
|
+
elsif mods[:lquote]
|
38
|
+
str << "‘"
|
39
|
+
return
|
40
|
+
elsif mods[:ldblquote]
|
41
|
+
str << "“"
|
42
|
+
return
|
43
|
+
elsif mods[:rdblquote]
|
44
|
+
str << "”"
|
45
|
+
return
|
46
|
+
elsif mods[:emdash]
|
47
|
+
str << "—"
|
48
|
+
return
|
49
|
+
elsif mods[:endash]
|
50
|
+
str << "–"
|
51
|
+
return
|
52
|
+
elsif mods[:nbsp]
|
53
|
+
str << " "
|
54
|
+
return
|
55
|
+
end
|
56
|
+
return if section[:text].empty?
|
57
|
+
|
58
|
+
add('b') if mods[:bold]
|
59
|
+
add('i') if mods[:italic]
|
60
|
+
add('u') if mods[:underline]
|
61
|
+
add('sup') if mods[:superscript]
|
62
|
+
add('sub') if mods[:subscript]
|
63
|
+
add('del') if mods[:strikethrough]
|
64
|
+
|
65
|
+
style = ''
|
66
|
+
style << "font-variant: small-caps;" if mods[:smallcaps]
|
67
|
+
style << "font-size: #{mods[:font_size]}pt;" if mods[:font_size]
|
68
|
+
style << "font-family: \"#{mods[:font].name}\";" if mods[:font]
|
69
|
+
if mods[:foreground_colour] && !mods[:foreground_colour].use_default?
|
70
|
+
colour = mods[:foreground_colour]
|
71
|
+
style << "color: rgb(#{colour.red},#{colour.green},#{colour.blue});"
|
72
|
+
end
|
73
|
+
if mods[:background_colour] && !mods[:background_colour].use_default?
|
74
|
+
colour = mods[:background_colour]
|
75
|
+
style << "background-color: rgb(#{colour.red},#{colour.green},#{colour.blue});"
|
76
|
+
end
|
77
|
+
|
78
|
+
add("span style='#{style}'", 'span') unless style.empty?
|
79
|
+
|
80
|
+
str << @prefix + section[:text].force_encoding('UTF-8') + @suffix
|
81
|
+
end
|
82
|
+
|
83
|
+
doc = RubyRTF::Parser.new.parse(File.open(ARGV[0]).read)
|
84
|
+
|
85
|
+
STDERR.puts doc
|
86
|
+
|
87
|
+
str = '<html><body>'
|
88
|
+
doc.sections.each do |section|
|
89
|
+
mods = section[:modifiers]
|
90
|
+
|
91
|
+
if mods[:table]
|
92
|
+
str << "<table width=\"100%\">\n"
|
93
|
+
mods[:table].rows.each do |row|
|
94
|
+
str << "<tr>\n"
|
95
|
+
row.cells.each do |cell|
|
96
|
+
str << "<td width=\"#{cell.width}%\">\n"
|
97
|
+
cell.sections.each do |sect|
|
98
|
+
format(str, sect)
|
99
|
+
end
|
100
|
+
str << "</td>\n"
|
101
|
+
end
|
102
|
+
str << "</tr>\n"
|
103
|
+
end
|
104
|
+
str << "</table>\n"
|
105
|
+
next
|
106
|
+
end
|
107
|
+
|
108
|
+
format(str, section)
|
109
|
+
end
|
110
|
+
|
111
|
+
str << "</body></html>"
|
112
|
+
puts str
|
data/lib/ruby-rtf.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'ruby-rtf/version'
|
4
|
+
require 'ruby-rtf/invalid_document'
|
5
|
+
|
6
|
+
require 'ruby-rtf/ruby-rtf'
|
7
|
+
require 'ruby-rtf/font'
|
8
|
+
require 'ruby-rtf/colour'
|
9
|
+
require 'ruby-rtf/table'
|
10
|
+
require 'ruby-rtf/document'
|
11
|
+
require 'ruby-rtf/parser'
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module RubyRTF
|
2
|
+
# Holds information about a colour
|
3
|
+
class Colour
|
4
|
+
# @return [Integer] The red value
|
5
|
+
attr_accessor :red
|
6
|
+
|
7
|
+
# @return [Integer] The green value
|
8
|
+
attr_accessor :green
|
9
|
+
|
10
|
+
# @return [Integer] The blue value
|
11
|
+
attr_accessor :blue
|
12
|
+
|
13
|
+
# @return [Integer] The shade value
|
14
|
+
attr_accessor :shade
|
15
|
+
|
16
|
+
# @return [Integer] The tint value
|
17
|
+
attr_accessor :tint
|
18
|
+
|
19
|
+
# @return [Symbol] The theme information
|
20
|
+
attr_accessor :theme
|
21
|
+
|
22
|
+
# @return [Boolean] True if reader should use it's default colour
|
23
|
+
attr_accessor :use_default
|
24
|
+
alias :use_default? :use_default
|
25
|
+
|
26
|
+
# Create a new colour
|
27
|
+
#
|
28
|
+
# @param red [Integer] Red value between 0 and 255 (default: 0)
|
29
|
+
# @param green [Integer] Green value between 0 and 255 (default: 0)
|
30
|
+
# @param blue [Integer] Blue value between 0 and 255 (default: 0)
|
31
|
+
# @return [RubyRTF::Colour] New colour object
|
32
|
+
def initialize(red = 0, green = 0, blue = 0)
|
33
|
+
@red = red
|
34
|
+
@green = green
|
35
|
+
@blue = blue
|
36
|
+
@use_default = false
|
37
|
+
end
|
38
|
+
|
39
|
+
# Convert the colour to a string
|
40
|
+
#
|
41
|
+
# @return [String] The string representation of the colour
|
42
|
+
def to_s
|
43
|
+
return "default" if use_default?
|
44
|
+
"[#{red}, #{green}, #{blue}]"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Alias the Colour class as Color
|
49
|
+
Color = Colour
|
50
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module RubyRTF
|
2
|
+
# Represents the entire RTF document
|
3
|
+
class Document
|
4
|
+
# @return [Array] The font table
|
5
|
+
attr_reader :font_table
|
6
|
+
|
7
|
+
# @return [Array] The colour table
|
8
|
+
attr_reader :colour_table
|
9
|
+
alias :color_table :colour_table
|
10
|
+
|
11
|
+
# @return [Integer] The default font number for the document
|
12
|
+
attr_accessor :default_font
|
13
|
+
|
14
|
+
# @return [String] The characgter set for the document (:ansi, :pc, :pca, :mac)
|
15
|
+
attr_accessor :character_set
|
16
|
+
|
17
|
+
# @return [Array] The different formatted sections of the document
|
18
|
+
attr_reader :sections
|
19
|
+
|
20
|
+
# Creates a new document
|
21
|
+
#
|
22
|
+
# @return [RubyRTF::Document] The new document
|
23
|
+
def initialize
|
24
|
+
@font_table = []
|
25
|
+
@colour_table = []
|
26
|
+
@character_set = :ansi
|
27
|
+
@default_font = 0
|
28
|
+
|
29
|
+
@sections = []
|
30
|
+
end
|
31
|
+
|
32
|
+
def <<(obj)
|
33
|
+
@sections << obj
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
module RubyRTF
|
2
|
+
# Holds the information for a given font
|
3
|
+
class Font
|
4
|
+
# @return [Integer] The font numberb
|
5
|
+
attr_accessor :number
|
6
|
+
|
7
|
+
# @return [String] The font name
|
8
|
+
attr_accessor :name
|
9
|
+
|
10
|
+
# @return [String] The alternate name for this font
|
11
|
+
attr_accessor :alternate_name
|
12
|
+
|
13
|
+
# @return [String] The panose number for the font
|
14
|
+
attr_accessor :panose
|
15
|
+
|
16
|
+
# @return [Symbol] The theme for this font
|
17
|
+
attr_accessor :theme
|
18
|
+
|
19
|
+
# @return [Symbol] The pitch information for this font
|
20
|
+
attr_accessor :pitch
|
21
|
+
|
22
|
+
# @return [Integer] The character set number for the font
|
23
|
+
attr_accessor :character_set
|
24
|
+
|
25
|
+
# @return [String] The non-tagged name for the font
|
26
|
+
attr_accessor :non_tagged_name
|
27
|
+
|
28
|
+
# @return [Symbol] The font family command
|
29
|
+
attr_accessor :family_command
|
30
|
+
|
31
|
+
# The font families
|
32
|
+
FAMILIES = [:nil, :roman, :swiss, :modern, :script, :decor, :tech, :bldl]
|
33
|
+
|
34
|
+
# The font pitch values
|
35
|
+
PITCHES = [:default, :fixed, :variable]
|
36
|
+
|
37
|
+
# Creates a new font
|
38
|
+
#
|
39
|
+
# @param name [String] The font name to set (default: '')
|
40
|
+
# @return [RubyRTF::Font] The new font
|
41
|
+
def initialize(name = '')
|
42
|
+
@family_command = :nil
|
43
|
+
@name = name
|
44
|
+
@alternate_name = ''
|
45
|
+
@non_tagged_name = ''
|
46
|
+
@panose = ''
|
47
|
+
end
|
48
|
+
|
49
|
+
# Set the pitch value for the font
|
50
|
+
#
|
51
|
+
# @param val [Integer] The pitch value to set (0, 1, or 2)
|
52
|
+
# @return [Nil]
|
53
|
+
def pitch=(val)
|
54
|
+
@pitch = PITCHES[val]
|
55
|
+
end
|
56
|
+
|
57
|
+
# Cleans up the various font names
|
58
|
+
#
|
59
|
+
# @return [Nil]
|
60
|
+
def cleanup_names
|
61
|
+
@name = cleanup_name(@name)
|
62
|
+
@alternate_name = cleanup_name(@alternate_name)
|
63
|
+
@non_tagged_name = cleanup_name(@non_tagged_name)
|
64
|
+
end
|
65
|
+
|
66
|
+
# Convert to string format
|
67
|
+
#
|
68
|
+
# @return [String] The string representation
|
69
|
+
def to_s
|
70
|
+
"#{number}: #{name}"
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
# Cleanups up a given font name
|
76
|
+
#
|
77
|
+
# @param str [String] The font name to cleanup
|
78
|
+
# @return [String] The cleaned font name
|
79
|
+
def cleanup_name(str)
|
80
|
+
str.gsub(/;$/, '')
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|