qhandout 0.2.0
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/LICENSE.txt +21 -0
- data/VERSION +1 -0
- data/lib/qhandout.rb +195 -0
- data/lib/qwan_logo_small.png +0 -0
- data/test/assert_pdf.rb +21 -0
- data/test/test_assert_pdf.rb +64 -0
- data/test/test_qhandout.rb +70 -0
- metadata +137 -0
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
Copyright (c) 2010 QWAN - Quality Without a Name
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
|
+
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.2.0
|
data/lib/qhandout.rb
ADDED
@@ -0,0 +1,195 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
|
3
|
+
require "prawn"
|
4
|
+
require "prawn/measurement_extensions"
|
5
|
+
|
6
|
+
GRAY = 'aaaaaa'
|
7
|
+
ORCHID = '9932CD'
|
8
|
+
BLACK = '000000'
|
9
|
+
|
10
|
+
class Prawn::Document
|
11
|
+
def texts(lines, *parameters)
|
12
|
+
lines.each do |line|
|
13
|
+
text line, *parameters
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def with_shadow(parameters = {})
|
18
|
+
shadow_color = parameters[:color] || GRAY
|
19
|
+
depth = parameters[:depth] || 0.5.mm
|
20
|
+
|
21
|
+
original_cursor = cursor
|
22
|
+
original_fill_color = fill_color
|
23
|
+
|
24
|
+
fill_color shadow_color
|
25
|
+
|
26
|
+
move_down depth
|
27
|
+
indent depth do
|
28
|
+
yield
|
29
|
+
end
|
30
|
+
|
31
|
+
move_cursor_to original_cursor
|
32
|
+
fill_color original_fill_color
|
33
|
+
yield
|
34
|
+
end
|
35
|
+
|
36
|
+
def text_with_shadow(*text_args)
|
37
|
+
with_shadow do
|
38
|
+
text *text_args
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class Handout
|
44
|
+
DEFAULT_TRAINERS = [
|
45
|
+
["Rob Westgeest", "Westgeest-Consultancy",
|
46
|
+
"Gondelstraat 2", "5017 CK Tilburg, NL", "+31 6 45 776 328", "rob@qwan.it"],
|
47
|
+
["Marc Evers", "Piecemeal Growth", "Delftseschans 18",
|
48
|
+
"3432 TD Nieuwegein, NL", "+31 6 4455 0003", "marc@qwan.it"],
|
49
|
+
["Willem van den Ende", "Living Software B.V.", "Spilmanstraat 25",
|
50
|
+
"5645 JE Eindhoven, NL", "+31 6 4130 6965", "willem@qwan.it"]]
|
51
|
+
|
52
|
+
SERIF_FONT = "Times-Roman"
|
53
|
+
COMIC_SANS_FONT = "#{Prawn::BASEDIR}/data/fonts/comicsans.ttf"
|
54
|
+
|
55
|
+
|
56
|
+
def self.create(parameters)
|
57
|
+
raise "need course name" unless parameters[:course]
|
58
|
+
raise "need course dates" unless parameters[:date]
|
59
|
+
raise "need location/client" unless parameters[:location]
|
60
|
+
raise "need titles and goals for tabs" unless parameters[:tabs]
|
61
|
+
|
62
|
+
handout = Handout.new parameters
|
63
|
+
handout.create_frontpage
|
64
|
+
handout.create_toc
|
65
|
+
handout.create_tabs
|
66
|
+
end
|
67
|
+
|
68
|
+
def initialize arguments = {}
|
69
|
+
@trainers = arguments[:trainers] || DEFAULT_TRAINERS
|
70
|
+
@course = arguments[:course] || ""
|
71
|
+
@date = arguments[:date] || ""
|
72
|
+
@location = arguments[:location] || ""
|
73
|
+
@tabs = arguments[:tabs] || [[]]
|
74
|
+
end
|
75
|
+
|
76
|
+
def header(pdf)
|
77
|
+
pdf.font COMIC_SANS_FONT
|
78
|
+
pdf.fill_color GRAY
|
79
|
+
|
80
|
+
pdf.with_shadow :color => BLACK do
|
81
|
+
pdf.text @course, :size => 20, :align => :center
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def footer(pdf, text)
|
86
|
+
pdf.move_cursor_to(10.mm)
|
87
|
+
pdf.text text, :align => :center
|
88
|
+
end
|
89
|
+
|
90
|
+
def new_page(pdf_file, footer_text = "")
|
91
|
+
Prawn::Document.generate(pdf_file, :page_size => 'A4',
|
92
|
+
:left_margin => 15.mm,
|
93
|
+
:right_margin => 15.mm,
|
94
|
+
:top_margin => 20.mm,
|
95
|
+
:bottom_margin => 15.mm
|
96
|
+
) do | pdf |
|
97
|
+
yield pdf
|
98
|
+
|
99
|
+
footer(pdf, footer_text)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def add_trainer_info(pdf)
|
104
|
+
pdf.column_box([0, pdf.cursor], :columns => 3, :width => pdf.bounds.width) do
|
105
|
+
pdf.texts @trainers[0], :size => 11, :align => :left
|
106
|
+
pdf.bounds.move_past_bottom
|
107
|
+
pdf.texts @trainers[1], :size => 11, :align => :center
|
108
|
+
pdf.bounds.move_past_bottom
|
109
|
+
pdf.texts @trainers[2], :size => 11, :align => :right
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def create_frontpage
|
114
|
+
footer = "(c) 2005-2012 QWAN -Quality Without a Name\nwww.qwan.it -- news@qwan.it"
|
115
|
+
|
116
|
+
new_page("frontpage.pdf", footer) do | pdf |
|
117
|
+
pdf.image "#{File.dirname(__FILE__)}/qwan_logo_small.png", :position => :center
|
118
|
+
|
119
|
+
pdf.font "Helvetica"
|
120
|
+
pdf.text "\n\n\nCourse Handout\n\n\n\n", :size => 20, :align => :center
|
121
|
+
|
122
|
+
pdf.fill_color ORCHID
|
123
|
+
pdf.font COMIC_SANS_FONT
|
124
|
+
pdf.text_with_shadow @course, :size => 36, :align => :center
|
125
|
+
|
126
|
+
pdf.fill_color BLACK
|
127
|
+
pdf.font "Helvetica"
|
128
|
+
pdf.text "\n\n\n\n\n\n#{@date}", :size => 20, :align => :center
|
129
|
+
|
130
|
+
pdf.text "#{@location}\n\n\n\n\n\n\n\n", :align => :center
|
131
|
+
|
132
|
+
add_trainer_info(pdf)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def tab_number(pdf, tab_nr)
|
137
|
+
pdf.bounding_box [pdf.bounds.left, pdf.bounds.top], :width => 60, :height => 60 do
|
138
|
+
pdf.text_with_shadow tab_nr, :size => 42
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
def title_and_goal(pdf, goal, title)
|
143
|
+
pdf.bounding_box [pdf.bounds.left + 28, pdf.bounds.top], :width => 500, :height => 60 do
|
144
|
+
pdf.text_with_shadow title, :size => 18
|
145
|
+
pdf.fill_color BLACK
|
146
|
+
pdf.text goal, :size => 12
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
def tab_entry(pdf, title, goal, tab_nr)
|
151
|
+
pdf.bounding_box [15.mm, pdf.cursor - 5.mm], :width => 600 do
|
152
|
+
pdf.font SERIF_FONT
|
153
|
+
pdf.fill_color ORCHID
|
154
|
+
|
155
|
+
tab_number(pdf, tab_nr)
|
156
|
+
title_and_goal(pdf, goal, title)
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
def tab_footer
|
161
|
+
"#{@course} / #{@date}, #{@location}"
|
162
|
+
end
|
163
|
+
|
164
|
+
def create_toc
|
165
|
+
new_page("toc.pdf", tab_footer) do | pdf |
|
166
|
+
header(pdf)
|
167
|
+
|
168
|
+
pdf.move_down 10.mm
|
169
|
+
|
170
|
+
@tabs.each_with_index do | (title, goal), index |
|
171
|
+
tab_entry(pdf, title, goal, (index + 1).to_s)
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
def tab(title, goal, tab_nr)
|
177
|
+
new_page("tab#{tab_nr}.pdf", tab_footer) do |pdf|
|
178
|
+
pdf.move_down 40.mm
|
179
|
+
|
180
|
+
tab_entry(pdf, title, "", tab_nr)
|
181
|
+
|
182
|
+
pdf.bounding_box [30.mm, pdf.cursor - 20.mm], :width => 140.mm do
|
183
|
+
pdf.fill_color BLACK
|
184
|
+
pdf.text goal, :size => 16
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
def create_tabs
|
190
|
+
@tabs.each_with_index do | (title, goal), index |
|
191
|
+
tab title, goal, (index+1).to_s
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
Binary file
|
data/test/assert_pdf.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
|
2
|
+
module Test::Unit::Assertions
|
3
|
+
def assert_pdf(pdf, expected_argument)
|
4
|
+
raise "expected argument must be a hash" unless expected_argument.is_a?(Hash)
|
5
|
+
expected = expected_argument[:contains]
|
6
|
+
expected = [expected] if expected && expected.is_a?(String)
|
7
|
+
not_expected = expected_argument[:does_not_contain]
|
8
|
+
|
9
|
+
raise "missing expected text" unless expected or not_expected
|
10
|
+
|
11
|
+
assert File.exist?(pdf), "file '#{pdf}' not found"
|
12
|
+
|
13
|
+
text = `pdftotext #{pdf} -`
|
14
|
+
|
15
|
+
expected.each do |expected_text|
|
16
|
+
assert_match %r{#{expected_text}}, text, "pdf does not contain '#{expected_text}'"
|
17
|
+
end if expected
|
18
|
+
|
19
|
+
assert_no_match %r{#{not_expected}}, text, "pdf does contains '#{not_expected}'" if not_expected
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "test/unit"
|
3
|
+
require "test/unit/assertions"
|
4
|
+
require "prawn"
|
5
|
+
|
6
|
+
require "assert_pdf"
|
7
|
+
|
8
|
+
class AssertPDFTest < Test::Unit::TestCase
|
9
|
+
TEST_FILE = "test.pdf"
|
10
|
+
|
11
|
+
def setup
|
12
|
+
Prawn::Document.generate("test.pdf") do |pdf|
|
13
|
+
pdf.text "www.qwan.it"
|
14
|
+
pdf.text "Rob"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def teardown
|
19
|
+
File.delete "test.pdf" if File.exist? "test.pdf"
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_pdftotext_available
|
23
|
+
`pdftotext test.pdf -`
|
24
|
+
assert_equal 0, $?.to_i, "pdftotext not installed?"
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_assert_non_existing_pdf_fails_test
|
28
|
+
assert_raises MiniTest::Assertion do
|
29
|
+
assert_pdf "doesnotexist.pdf", :contains => "www.qwan.it"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_assert_existing_pdf_passes_test
|
34
|
+
assert_pdf TEST_FILE, :contains => "www.qwan.it"
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_assert_without_expected_text_raises_error
|
38
|
+
assert_raises RuntimeError do
|
39
|
+
assert_pdf TEST_FILE, "www.qwan.it"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_assert_text_not_in_pdf_fails
|
44
|
+
assert_raises MiniTest::Assertion do
|
45
|
+
assert_pdf TEST_FILE, :contains => "Agile"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_assert_multiple_texts_in_pdf_passes
|
50
|
+
assert_pdf TEST_FILE, :contains => ["www.qwan.it", "Rob"]
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_assert_multiple_texts_with_one_not_existing_in_pdf_fails
|
54
|
+
assert_raises MiniTest::Assertion do
|
55
|
+
assert_pdf TEST_FILE, :contains => ["www.qwan.it", "agile"]
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_asserting_does_non_contain_on_existing_text_fails
|
60
|
+
assert_raises MiniTest::Assertion do
|
61
|
+
assert_pdf TEST_FILE, :does_not_contain => "www.qwan.it"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require "test/unit"
|
2
|
+
require "assert_pdf"
|
3
|
+
require "qhandout"
|
4
|
+
|
5
|
+
class HandoutTest < Test::Unit::TestCase
|
6
|
+
def setup
|
7
|
+
Handout.new(:course => "TDD For Dummies", :date => "10 June 2031", :location => "Utrecht").create_frontpage
|
8
|
+
end
|
9
|
+
|
10
|
+
def teardown
|
11
|
+
File.delete "frontpage.pdf" if File.exist? "FrontPage.pdf"
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_frontpage_contains_default_trainers
|
15
|
+
assert_pdf "frontpage.pdf", :contains => ["Rob", "Tilburg", "Marc", "Willem"]
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_frontpage_contains_course_dates_location_footer
|
19
|
+
assert_pdf "frontpage.pdf", :contains => ["TDD For Dummies", "10 June 2031", "Utrecht"]
|
20
|
+
assert_pdf "frontpage.pdf", :contains => ["2005-2012", "www.qwan.it"]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class TabsTest < Test::Unit::TestCase
|
25
|
+
def setup
|
26
|
+
@handout = Handout.new :course => "TDD For Dummies", :date => "10 & 11 June 2031", :location => "Utrecht",
|
27
|
+
:tabs => [["Intro", "Get to know each other"], ["RDD", "CRC"]]
|
28
|
+
end
|
29
|
+
|
30
|
+
def delete_if_exists(files)
|
31
|
+
files.each do |file|
|
32
|
+
File.delete file if File.exist? file
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def teardown
|
37
|
+
delete_if_exists ["toc.pdf", "tab1.pdf", "tab2.pdf"]
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_create_toc
|
41
|
+
@handout.create_toc
|
42
|
+
|
43
|
+
assert_pdf "toc.pdf", :contains => ["TDD For Dummies"]
|
44
|
+
assert_pdf "toc.pdf", :contains => ["1", "Intro", "Get to know each other"]
|
45
|
+
|
46
|
+
assert_pdf "toc.pdf", :contains => ["10 & 11 June 2031", "Utrecht"]
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_create_toc_with_multiple_entries
|
50
|
+
@handout.create_toc
|
51
|
+
|
52
|
+
assert_pdf "toc.pdf", :contains => ["1", "Intro", "Get to know each other"]
|
53
|
+
assert_pdf "toc.pdf", :contains => ["2", "TDD", "CRC"]
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_create_tab_page
|
57
|
+
@handout.create_tabs
|
58
|
+
|
59
|
+
assert_pdf "tab1.pdf", :contains => ["1", "Intro", "Get to know each other"]
|
60
|
+
|
61
|
+
assert_pdf "tab1.pdf", :contains => ["10 & 11 June 2031", "Utrecht"]
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_create_multiple_tab_pages
|
65
|
+
@handout.create_tabs
|
66
|
+
|
67
|
+
assert_pdf "tab2.pdf", :contains => ["2", "RDD", "CRC"]
|
68
|
+
assert_pdf "tab2.pdf", :does_not_contain => "Intro"
|
69
|
+
end
|
70
|
+
end
|
metadata
ADDED
@@ -0,0 +1,137 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: qhandout
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Marc Evers
|
9
|
+
- Rob Westgeest
|
10
|
+
autorequire:
|
11
|
+
bindir: bin
|
12
|
+
cert_chain: []
|
13
|
+
date: 2012-03-30 00:00:00.000000000 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: rake
|
17
|
+
requirement: !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - ~>
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 0.9.2
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
none: false
|
27
|
+
requirements:
|
28
|
+
- - ~>
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
version: 0.9.2
|
31
|
+
- !ruby/object:Gem::Dependency
|
32
|
+
name: bundler
|
33
|
+
requirement: !ruby/object:Gem::Requirement
|
34
|
+
none: false
|
35
|
+
requirements:
|
36
|
+
- - ~>
|
37
|
+
- !ruby/object:Gem::Version
|
38
|
+
version: 1.1.3
|
39
|
+
type: :development
|
40
|
+
prerelease: false
|
41
|
+
version_requirements: !ruby/object:Gem::Requirement
|
42
|
+
none: false
|
43
|
+
requirements:
|
44
|
+
- - ~>
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: 1.1.3
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: jeweler
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 1.8.3
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: !ruby/object:Gem::Requirement
|
58
|
+
none: false
|
59
|
+
requirements:
|
60
|
+
- - ~>
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: 1.8.3
|
63
|
+
- !ruby/object:Gem::Dependency
|
64
|
+
name: rcov
|
65
|
+
requirement: !ruby/object:Gem::Requirement
|
66
|
+
none: false
|
67
|
+
requirements:
|
68
|
+
- - ! '>='
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: '0'
|
71
|
+
type: :development
|
72
|
+
prerelease: false
|
73
|
+
version_requirements: !ruby/object:Gem::Requirement
|
74
|
+
none: false
|
75
|
+
requirements:
|
76
|
+
- - ! '>='
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: '0'
|
79
|
+
- !ruby/object:Gem::Dependency
|
80
|
+
name: prawn
|
81
|
+
requirement: !ruby/object:Gem::Requirement
|
82
|
+
none: false
|
83
|
+
requirements:
|
84
|
+
- - ! '>='
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
version: 0.8.4
|
87
|
+
type: :development
|
88
|
+
prerelease: false
|
89
|
+
version_requirements: !ruby/object:Gem::Requirement
|
90
|
+
none: false
|
91
|
+
requirements:
|
92
|
+
- - ! '>='
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: 0.8.4
|
95
|
+
description: Generate course handout toc/tabs
|
96
|
+
email: info@qwan.it
|
97
|
+
executables: []
|
98
|
+
extensions: []
|
99
|
+
extra_rdoc_files:
|
100
|
+
- LICENSE.txt
|
101
|
+
files:
|
102
|
+
- VERSION
|
103
|
+
- lib/qhandout.rb
|
104
|
+
- lib/qwan_logo_small.png
|
105
|
+
- test/assert_pdf.rb
|
106
|
+
- test/test_assert_pdf.rb
|
107
|
+
- test/test_qhandout.rb
|
108
|
+
- LICENSE.txt
|
109
|
+
homepage: http://www.qwan.it
|
110
|
+
licenses:
|
111
|
+
- MIT
|
112
|
+
post_install_message:
|
113
|
+
rdoc_options: []
|
114
|
+
require_paths:
|
115
|
+
- lib
|
116
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
117
|
+
none: false
|
118
|
+
requirements:
|
119
|
+
- - ! '>='
|
120
|
+
- !ruby/object:Gem::Version
|
121
|
+
version: '0'
|
122
|
+
segments:
|
123
|
+
- 0
|
124
|
+
hash: -189504195
|
125
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
126
|
+
none: false
|
127
|
+
requirements:
|
128
|
+
- - ! '>='
|
129
|
+
- !ruby/object:Gem::Version
|
130
|
+
version: '0'
|
131
|
+
requirements: []
|
132
|
+
rubyforge_project:
|
133
|
+
rubygems_version: 1.8.21
|
134
|
+
signing_key:
|
135
|
+
specification_version: 3
|
136
|
+
summary: Generate course handout toc/tabs
|
137
|
+
test_files: []
|