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 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
@@ -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: []