vitae 0.0.2 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.autotest +10 -0
- data/.gitignore +2 -0
- data/Gemfile.lock +29 -0
- data/README.rdoc +59 -2
- data/bin/vitae +67 -0
- data/config.ru +4 -0
- data/lib/vitae.rb +2 -3
- data/lib/vitae/cv.rb +40 -0
- data/lib/vitae/server/.gitignore +4 -0
- data/lib/vitae/server/helpers.rb +37 -0
- data/lib/vitae/server/server.rb +31 -0
- data/lib/vitae/server/views/index.haml +3 -0
- data/lib/vitae/server/views/layout.haml +10 -0
- data/lib/vitae/server/views/show.haml +1 -0
- data/lib/vitae/templates/cvs/arthur_gunn.yaml +5 -0
- data/lib/vitae/templates/cvs/default.yaml.tt +5 -0
- data/lib/vitae/templates/themes/default/application.css +226 -0
- data/lib/vitae/templates/themes/default/application.js +1 -0
- data/lib/vitae/version.rb +1 -1
- data/test/active_server_test.rb +36 -0
- data/test/basic_server_test.rb +10 -0
- data/test/tag_helpers_test.rb +24 -0
- data/test/test_helper.rb +78 -0
- data/test/vitae_executable_test.rb +52 -0
- data/vitae.gemspec +6 -0
- metadata +88 -9
data/.autotest
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
vitae (0.0.2)
|
5
|
+
haml
|
6
|
+
sinatra
|
7
|
+
thor
|
8
|
+
|
9
|
+
GEM
|
10
|
+
remote: http://rubygems.org/
|
11
|
+
specs:
|
12
|
+
haml (3.0.24)
|
13
|
+
nokogiri (1.4.4)
|
14
|
+
rack (1.2.1)
|
15
|
+
sinatra (1.1.0)
|
16
|
+
rack (~> 1.1)
|
17
|
+
tilt (~> 1.1)
|
18
|
+
thor (0.14.6)
|
19
|
+
tilt (1.1)
|
20
|
+
|
21
|
+
PLATFORMS
|
22
|
+
ruby
|
23
|
+
|
24
|
+
DEPENDENCIES
|
25
|
+
haml
|
26
|
+
nokogiri
|
27
|
+
sinatra
|
28
|
+
thor
|
29
|
+
vitae!
|
data/README.rdoc
CHANGED
@@ -1,5 +1,62 @@
|
|
1
|
-
|
1
|
+
= Vitae
|
2
2
|
|
3
3
|
Vitae is to CVs what rubygems is to ruby code.
|
4
4
|
|
5
|
-
|
5
|
+
It's also very under development right now, and not very useful yet. Come back soon!
|
6
|
+
|
7
|
+
|
8
|
+
=== Usage
|
9
|
+
First install the vitae gem:
|
10
|
+
$: sudo gem i vitae
|
11
|
+
|
12
|
+
Now lets create a new project called my_cv_project, with some named CVs:
|
13
|
+
$: vitae create my_cv_project arthur_gunn sajal_shah
|
14
|
+
creating my_cv_project...
|
15
|
+
create cvs/arthur_gunn.yaml
|
16
|
+
create cvs/sajal_shah.yaml
|
17
|
+
create themes/default/application.js
|
18
|
+
create themes/default/application.css
|
19
|
+
|
20
|
+
Great, it's created our two named CVs in the my_cv_project/cvs directory from a basic yaml template. Edit these yaml files with your own info (note: currently data is not actually read from these, that will change soon).
|
21
|
+
|
22
|
+
Once your done editing, start up the server:
|
23
|
+
$: cd my_cv_project
|
24
|
+
$: vitae server
|
25
|
+
Serving CVs at 0.0.0.0:3141
|
26
|
+
|
27
|
+
Enjoy!
|
28
|
+
|
29
|
+
=== Future plans
|
30
|
+
1. Data should actually be read from the yaml files.
|
31
|
+
2. Vitae should com bundled with better default templates - CSS, JS and YAML.
|
32
|
+
3. Support for multiple themes.
|
33
|
+
4. The clever stuff
|
34
|
+
|
35
|
+
=== The clever stuff
|
36
|
+
Much like rubygems or git
|
37
|
+
|
38
|
+
Push a CV:
|
39
|
+
$: vitae push vitae.gunn.co.nz arthur_gunn
|
40
|
+
pushing...
|
41
|
+
1 CV pushed
|
42
|
+
CV available at http://vitae.gunn.co.nz/arthur_gunn
|
43
|
+
|
44
|
+
Pull a CV:
|
45
|
+
$: vitae pull vitae.gunn.co.nz sajal_shah
|
46
|
+
pulling...
|
47
|
+
1 CV pulled
|
48
|
+
2 themes pulled
|
49
|
+
CV pulled to cvs/sajal_shah
|
50
|
+
Theme pulled to themes/darkness
|
51
|
+
Theme pulled to themes/espresso
|
52
|
+
|
53
|
+
=== Want to help?
|
54
|
+
Just the github usual for development - fork, commit, pull request, bonus points for tests.
|
55
|
+
Have a play and report bugs, request features via the issue tracker.
|
56
|
+
|
57
|
+
Feel free to email me at arthur@gunn.co.nz
|
58
|
+
|
59
|
+
=== Credits
|
60
|
+
Development by Arthur Gunn.
|
61
|
+
|
62
|
+
Thanks to Maxim Chernyak and Juriy Zaytsev for CSS used in the default theme.
|
data/bin/vitae
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require "rubygems"
|
3
|
+
require "thor"
|
4
|
+
|
5
|
+
require File.expand_path('../../lib/vitae', __FILE__)
|
6
|
+
|
7
|
+
module Vitae
|
8
|
+
class CLI < Thor
|
9
|
+
include Thor::Actions
|
10
|
+
|
11
|
+
def self.source_root
|
12
|
+
File.expand_path('../../lib/vitae/templates', __FILE__)
|
13
|
+
end
|
14
|
+
|
15
|
+
|
16
|
+
default_task :create
|
17
|
+
|
18
|
+
desc "create [project_name]", "Create a new vitae project"
|
19
|
+
def create(name, *cv_names)
|
20
|
+
self.destination_root = name
|
21
|
+
puts "creating #{name}..."
|
22
|
+
|
23
|
+
if cv_names.size > 0
|
24
|
+
cv_names.each do |cv_name|
|
25
|
+
@name = cv_name
|
26
|
+
template "cvs/default.yaml.tt", "cvs/#{cv_name}.yaml"
|
27
|
+
end
|
28
|
+
else
|
29
|
+
templates = Dir.glob(File.join(CLI.source_root, "cvs/*.yaml*")).
|
30
|
+
map{|f| File.basename(f)} -["default.yaml.tt"]
|
31
|
+
|
32
|
+
templates.each do |template_name|
|
33
|
+
template "cvs/#{template_name}", "cvs/#{template_name.sub(/\.tt$/, '')}"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
themes = Dir.glob(File.join(CLI.source_root, "themes/*")).map{|f| File.basename(f)}
|
38
|
+
themes.each do |theme_name|
|
39
|
+
copy_file "themes/#{theme_name}/application.js"
|
40
|
+
copy_file "themes/#{theme_name}/application.css"
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
desc "server [-p 3000]", "Start the vitae server."
|
46
|
+
def server
|
47
|
+
require "rack"
|
48
|
+
|
49
|
+
just_pretend = ARGV.delete "--pretend"
|
50
|
+
port_set_by_user = ARGV.any? { |a| %w[-p --port].include?( a ) }
|
51
|
+
|
52
|
+
server = Rack::Server.new.tap do |s|
|
53
|
+
s.options[:config] = File.join(File.dirname(__FILE__), "../config.ru")
|
54
|
+
s.options[:Port] = 3141 unless port_set_by_user
|
55
|
+
end
|
56
|
+
|
57
|
+
require "vitae/server/server"
|
58
|
+
Server.project_root = Dir.pwd
|
59
|
+
|
60
|
+
say "Serving CVs at #{server.options[:Host]}:#{server.options[:Port]}", :green
|
61
|
+
server.start unless just_pretend
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
Vitae::CLI.start
|
data/config.ru
ADDED
data/lib/vitae.rb
CHANGED
@@ -1,3 +1,2 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
end
|
1
|
+
$:.unshift File.dirname(File.expand_path(__FILE__))
|
2
|
+
require "vitae/cv"
|
data/lib/vitae/cv.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
class CV
|
2
|
+
|
3
|
+
def self.all
|
4
|
+
cvs = Dir.glob(File.join(Server.project_root, "cvs/*.yaml"))
|
5
|
+
cvs.map do |cv|
|
6
|
+
CV.new(cv)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.find name
|
11
|
+
all.find do |cv|
|
12
|
+
cv.name == name
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize yaml_file
|
17
|
+
@name = File.basename(yaml_file, '.yaml')
|
18
|
+
end
|
19
|
+
|
20
|
+
def name
|
21
|
+
@name
|
22
|
+
end
|
23
|
+
|
24
|
+
def human_name
|
25
|
+
name.split("_").map{|w|w.capitalize}.join(" ")
|
26
|
+
end
|
27
|
+
|
28
|
+
def to_s
|
29
|
+
human_name
|
30
|
+
end
|
31
|
+
|
32
|
+
def link
|
33
|
+
"/#{name}"
|
34
|
+
end
|
35
|
+
|
36
|
+
def theme
|
37
|
+
"default"
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Helpers
|
2
|
+
def current_theme
|
3
|
+
@cv && @cv.theme || "default"
|
4
|
+
end
|
5
|
+
|
6
|
+
def include_theme_assets
|
7
|
+
html = content_tag(:script, nil, :type => "text/javascript", :src => "/#{current_theme}/application.js")
|
8
|
+
html << "\n"+tag(:link, nil, :type => "text/css", :media => "screen", :rel => "stylesheet", :href => "/#{current_theme}/application.css")
|
9
|
+
html
|
10
|
+
end
|
11
|
+
|
12
|
+
def link_to(text, link=nil, options={})
|
13
|
+
link ||= text.split(/\s+/).join('_').downcase
|
14
|
+
content_tag :a, text, options.merge({:href => link})
|
15
|
+
end
|
16
|
+
|
17
|
+
def content_tag(*args, &block)
|
18
|
+
args.last[:double_tag] = true if args.last.is_a?(Hash)
|
19
|
+
tag(*args, &block)
|
20
|
+
end
|
21
|
+
|
22
|
+
def tag(*args, &block)
|
23
|
+
name = args.first
|
24
|
+
|
25
|
+
options = args.last.is_a?(Hash) ? args.pop : {}
|
26
|
+
double_tag = options.delete(:double_tag)
|
27
|
+
|
28
|
+
attrs = if options.size>0
|
29
|
+
" "+options.map { |k,v| "#{k}='#{v}'" }.join(" ")
|
30
|
+
else
|
31
|
+
""
|
32
|
+
end
|
33
|
+
tag_html = block_given? ? capture_html(&block) : args[1]
|
34
|
+
|
35
|
+
"<#{name}#{attrs}"+(tag_html||double_tag ? ">#{tag_html}</#{name}>" : "/>")
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'sinatra/base'
|
2
|
+
require 'haml'
|
3
|
+
require "vitae/server/helpers"
|
4
|
+
|
5
|
+
class Server < Sinatra::Base
|
6
|
+
helpers Helpers
|
7
|
+
set :views, File.dirname(__FILE__) + '/views'
|
8
|
+
|
9
|
+
get '/' do
|
10
|
+
@cvs = CV.all
|
11
|
+
haml :index
|
12
|
+
end
|
13
|
+
|
14
|
+
get '/:name' do
|
15
|
+
@cv = CV.find( params[:name] )
|
16
|
+
haml :show
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
|
21
|
+
@@project_root = nil
|
22
|
+
def self.project_root
|
23
|
+
@@project_root
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.project_root= root
|
27
|
+
set :public, File.join(root, "themes")
|
28
|
+
@@project_root = root
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
=link_to "Vitae Home", "/"
|
@@ -0,0 +1,226 @@
|
|
1
|
+
/* CSS by Maxim Chernyak and Juriy Zaytsev - https://github.com/maxim/maxim.github.com */
|
2
|
+
body {
|
3
|
+
font-family: Garamond, "Hoefler Text", "Times New Roman", Times, serif;
|
4
|
+
font-size: 1.1em;
|
5
|
+
line-height: 1.3;
|
6
|
+
}
|
7
|
+
|
8
|
+
abbr { border: none; cursor: help; }
|
9
|
+
|
10
|
+
h1, h2, h3, h4 {
|
11
|
+
font-family: Garamond, "Hoefler Text", Palatino, "Palatino Linotype", serif;
|
12
|
+
}
|
13
|
+
|
14
|
+
h1 { font-size: 2em; }
|
15
|
+
h2 { font-size: 1.8em; }
|
16
|
+
|
17
|
+
h3 {
|
18
|
+
margin-bottom: 0;
|
19
|
+
font-size: 1.2em;
|
20
|
+
font-weight: normal;
|
21
|
+
}
|
22
|
+
|
23
|
+
img {
|
24
|
+
border: 0;
|
25
|
+
}
|
26
|
+
|
27
|
+
#left-ribbon {
|
28
|
+
position: absolute;
|
29
|
+
top: 0;
|
30
|
+
left: 0;
|
31
|
+
border: 0;
|
32
|
+
}
|
33
|
+
|
34
|
+
#download-links {
|
35
|
+
position: absolute;
|
36
|
+
top: 160px;
|
37
|
+
right: 0;
|
38
|
+
padding: 5px;
|
39
|
+
padding-top: 15px;
|
40
|
+
background-color: #ffd;
|
41
|
+
}
|
42
|
+
|
43
|
+
#download-links a {
|
44
|
+
display: block;
|
45
|
+
}
|
46
|
+
|
47
|
+
ul {
|
48
|
+
list-style-type: none;
|
49
|
+
padding-left: 0;
|
50
|
+
}
|
51
|
+
|
52
|
+
.tags-header {
|
53
|
+
margin-bottom: 0.5em;
|
54
|
+
}
|
55
|
+
|
56
|
+
.tags {
|
57
|
+
font-size: 0.85em;
|
58
|
+
font-family: "Courier New", Courier, monospace;
|
59
|
+
margin-top: 0;
|
60
|
+
margin-bottom: 2em;
|
61
|
+
}
|
62
|
+
|
63
|
+
.tags li {
|
64
|
+
display: inline;
|
65
|
+
margin-right: 0.5em;
|
66
|
+
vertical-align: middle;
|
67
|
+
}
|
68
|
+
|
69
|
+
.tags li {
|
70
|
+
-moz-box-shadow: 0px 1px 2px #777;
|
71
|
+
-webkit-box-shadow: 1px 1px 2px #777;
|
72
|
+
box-shadow: 0px 1px 2px #777;
|
73
|
+
|
74
|
+
-moz-border-radius: 0.25em;
|
75
|
+
-webkit-border-radius: 0.25em;
|
76
|
+
border-radius: 0.25em;
|
77
|
+
|
78
|
+
border: 1px solid #eee;
|
79
|
+
background-color: #efefef;
|
80
|
+
padding: 0.40em;
|
81
|
+
line-height: 2.8em;
|
82
|
+
}
|
83
|
+
|
84
|
+
.tags .weak {
|
85
|
+
color: #333;
|
86
|
+
font-size: 0.9em;
|
87
|
+
}
|
88
|
+
|
89
|
+
.tags .strong {
|
90
|
+
font-weight: normal;
|
91
|
+
font-size: 1.2em;
|
92
|
+
}
|
93
|
+
|
94
|
+
.tags .prefer {
|
95
|
+
font-size: 1.4em;
|
96
|
+
font-weight: bold;
|
97
|
+
}
|
98
|
+
|
99
|
+
.tags .dislike {
|
100
|
+
font-size: 0.9em;
|
101
|
+
}
|
102
|
+
|
103
|
+
#title, #title-clone {
|
104
|
+
text-align: center;
|
105
|
+
font-size: 4em;
|
106
|
+
color: #777;
|
107
|
+
margin-top: 0;
|
108
|
+
}
|
109
|
+
|
110
|
+
#quick-links {
|
111
|
+
list-style-type: none;
|
112
|
+
padding-left: 0.5em;
|
113
|
+
width: 25em;
|
114
|
+
margin: 2em auto;
|
115
|
+
color: #666;
|
116
|
+
font-size: 0.9em;
|
117
|
+
}
|
118
|
+
|
119
|
+
#quick-links li a {
|
120
|
+
text-decoration: none;
|
121
|
+
font-size: 1.1em;
|
122
|
+
}
|
123
|
+
|
124
|
+
.label {
|
125
|
+
color: #888;
|
126
|
+
display: inline-block;
|
127
|
+
width: 6em;
|
128
|
+
padding-right: 1em;
|
129
|
+
text-align: right;
|
130
|
+
}
|
131
|
+
|
132
|
+
#quick-links li a:hover, #quick-links li a:focus {
|
133
|
+
text-decoration: underline;
|
134
|
+
}
|
135
|
+
|
136
|
+
#content {
|
137
|
+
width: 960px;
|
138
|
+
margin: 3em auto;
|
139
|
+
}
|
140
|
+
|
141
|
+
.spaced-out {
|
142
|
+
line-height: 1.5;
|
143
|
+
}
|
144
|
+
|
145
|
+
.column-wrapper {
|
146
|
+
overflow: hidden;
|
147
|
+
width: 100%;
|
148
|
+
margin-bottom: 2em;
|
149
|
+
}
|
150
|
+
|
151
|
+
.column {
|
152
|
+
float: left;
|
153
|
+
width: 30%;
|
154
|
+
padding-right: 30px;
|
155
|
+
}
|
156
|
+
|
157
|
+
em {
|
158
|
+
font-style: inherit;
|
159
|
+
background-color: #ffd;
|
160
|
+
padding: 2px 5px 2px 5px;
|
161
|
+
color: #444;
|
162
|
+
}
|
163
|
+
|
164
|
+
.dtrange {
|
165
|
+
text-shadow: none;
|
166
|
+
font-weight: normal;
|
167
|
+
font-size: 15px;
|
168
|
+
margin-left: 0.5em;
|
169
|
+
color: #777;
|
170
|
+
}
|
171
|
+
|
172
|
+
#printio-experience-intro {
|
173
|
+
margin-top: -1em;
|
174
|
+
margin-bottom: 2em;
|
175
|
+
}
|
176
|
+
|
177
|
+
#bitsonnet-experience-intro {
|
178
|
+
margin-top: -1em;
|
179
|
+
margin-bottom: 2em;
|
180
|
+
}
|
181
|
+
|
182
|
+
.jobs-list li {
|
183
|
+
padding: 0.75em 0.5em 0.75em 1em;
|
184
|
+
margin-bottom: 1em;
|
185
|
+
}
|
186
|
+
|
187
|
+
.jobs-list li h3 {
|
188
|
+
margin-top: 0;
|
189
|
+
}
|
190
|
+
|
191
|
+
.job-description {
|
192
|
+
margin: 0.25em 0 0 1em;
|
193
|
+
color: #333;
|
194
|
+
}
|
195
|
+
|
196
|
+
#summarize { color: #555; position: absolute; top: 1em; right: 1em; width: 10em; }
|
197
|
+
|
198
|
+
#projects-contributed-to { margin-left: 1em; }
|
199
|
+
#projects-contributed-to li { display: inline; margin-right: 0.5em; line-height: 1.5; }
|
200
|
+
#projects-contributed-to li a { margin-right: 0.5em; }
|
201
|
+
|
202
|
+
/* PRINT MEDIA */
|
203
|
+
|
204
|
+
@media print {
|
205
|
+
body { color: #000; font-family: Cambria, Georgia, Times, "Times New Roman", serif; font-size: 1.3em; }
|
206
|
+
em { font-weight: bold; }
|
207
|
+
a:link, a:visited { color: #007; text-decoration: none; }
|
208
|
+
.tags li { color: #000; }
|
209
|
+
#title { margin-top: -0.5em; font-size: 3em; }
|
210
|
+
#left-ribbon { display: none; }
|
211
|
+
#summarize { display: none; }
|
212
|
+
#download-links { display: none; }
|
213
|
+
}
|
214
|
+
|
215
|
+
/* SMALL SCREEN DEVICES */
|
216
|
+
|
217
|
+
@media only screen and (max-device-width: 480px) {
|
218
|
+
body { margin: 0; }
|
219
|
+
.column { width: auto; padding-right: 0; }
|
220
|
+
#title, #title-clone { font-size: 3em; margin-top: 0; }
|
221
|
+
#content { width: auto; padding: 0 0.5em 0.5em 0.5em; }
|
222
|
+
#left-ribbon { display: none; }
|
223
|
+
#quick-links { width: auto; }
|
224
|
+
#quick-links li { margin-bottom: 0.25em; padding: 0.25em; }
|
225
|
+
#quick-links .label { width: 5em; }
|
226
|
+
}
|
@@ -0,0 +1 @@
|
|
1
|
+
// I'm javascript!
|
data/lib/vitae/version.rb
CHANGED
@@ -0,0 +1,36 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
require "nokogiri"
|
3
|
+
|
4
|
+
class ActiveServerTest < VitaeServerTestCase
|
5
|
+
|
6
|
+
test "the homepage contains lists the cvs we're hosting" do
|
7
|
+
clear_test_dir
|
8
|
+
vitae_create "resumes derek arthur sajal"
|
9
|
+
|
10
|
+
get '/'
|
11
|
+
assert last_response.ok?
|
12
|
+
assert_matches %w[Derek Arthur Sajal]
|
13
|
+
assert_select "a[href='/sajal']", "Sajal"
|
14
|
+
|
15
|
+
check_includes_standard_assets
|
16
|
+
end
|
17
|
+
|
18
|
+
test "a CV gets its own show page" do
|
19
|
+
clear_test_dir
|
20
|
+
vitae_create "resumes arthur_gunn"
|
21
|
+
|
22
|
+
get '/arthur_gunn'
|
23
|
+
assert last_response.ok?
|
24
|
+
|
25
|
+
assert_select "h1", "Arthur Gunn"
|
26
|
+
assert_select "a[href='/']"
|
27
|
+
|
28
|
+
check_includes_standard_assets
|
29
|
+
end
|
30
|
+
|
31
|
+
def check_includes_standard_assets theme="default"
|
32
|
+
assert_select "script[src='/#{theme}/application.js'][type='text/javascript']"
|
33
|
+
assert_select "link[href='/#{theme}/application.css'][rel='stylesheet'][type='text/css']"
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
require 'vitae/server/helpers'
|
3
|
+
|
4
|
+
class VitaeExecutableTest < VitaeTestCase
|
5
|
+
module Help
|
6
|
+
extend Helpers
|
7
|
+
end
|
8
|
+
|
9
|
+
test "link_to helper produces well formed links" do
|
10
|
+
assert_equal "<a href='about_us'>About Us</a>", Help.link_to("About Us")
|
11
|
+
assert_equal "<a href='http://google.com'>Search Time!</a>", Help.link_to("Search Time!", "http://google.com")
|
12
|
+
end
|
13
|
+
|
14
|
+
test "content_tag helper produces well formed tags" do
|
15
|
+
assert_equal "<h1>Title!</h1>", Help.content_tag(:h1, "Title!")
|
16
|
+
assert_equal "<script src='/fast.js'></script>", Help.content_tag(:script, :src => "/fast.js")
|
17
|
+
end
|
18
|
+
|
19
|
+
test "tag helper produces well formed tags" do
|
20
|
+
assert_equal "<br/>", Help.tag(:br)
|
21
|
+
assert_equal "<link href='/pretty.css'/>", Help.tag(:link, :href => "/pretty.css")
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'test/unit'
|
3
|
+
|
4
|
+
require File.expand_path('../../lib/vitae', __FILE__)
|
5
|
+
require 'vitae/server/server'
|
6
|
+
require 'rack/test'
|
7
|
+
|
8
|
+
VITAE_TEST_DIR = ::File.expand_path('../../tmp', __FILE__)
|
9
|
+
VITAE_EXECUTABLE = ::File.expand_path('../../bin/vitae', __FILE__)
|
10
|
+
|
11
|
+
class VitaeTestCase < Test::Unit::TestCase
|
12
|
+
def self.test name, &block
|
13
|
+
name = "test #{name}"#.split(/[^a-z1-9]+/).compact.join("_")
|
14
|
+
define_method name, &block
|
15
|
+
end
|
16
|
+
|
17
|
+
test "tests working here" do
|
18
|
+
# assert(true, "Just to keep t/u happy.")
|
19
|
+
end
|
20
|
+
|
21
|
+
def vitae_test_dir
|
22
|
+
FileUtils.mkdir_p VITAE_TEST_DIR
|
23
|
+
end
|
24
|
+
|
25
|
+
def vitae_executable
|
26
|
+
VITAE_EXECUTABLE
|
27
|
+
end
|
28
|
+
|
29
|
+
%w[server].each do |command|
|
30
|
+
define_method "vitae_#{command}" do |*args|
|
31
|
+
args = args.first
|
32
|
+
FileUtils.cd vitae_test_dir
|
33
|
+
`#{vitae_executable} #{command} #{args} 2>&1`
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def vitae_create args=""
|
38
|
+
FileUtils.cd vitae_test_dir
|
39
|
+
project_name = args.split(/\s+/).first || ""
|
40
|
+
Server.project_root = File.join(vitae_test_dir, project_name)
|
41
|
+
`#{vitae_executable} create #{args} 2>&1`
|
42
|
+
end
|
43
|
+
|
44
|
+
def clear_test_dir
|
45
|
+
FileUtils.rm_r vitae_test_dir
|
46
|
+
end
|
47
|
+
|
48
|
+
def vitae_file? path
|
49
|
+
File.exist? ::File.expand_path(path, vitae_test_dir)
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
class VitaeServerTestCase < VitaeTestCase
|
55
|
+
include Rack::Test::Methods
|
56
|
+
|
57
|
+
def app
|
58
|
+
Server
|
59
|
+
end
|
60
|
+
|
61
|
+
def assert_matches matches, actual=last_response.body
|
62
|
+
matches.each do |match|
|
63
|
+
assert_match match, actual
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def assert_select selector, content=nil, text=last_response.body
|
68
|
+
matches = Nokogiri::HTML.parse(text).css(selector)
|
69
|
+
assert(matches.size>0, "No matches for the selector '#{selector}'.")
|
70
|
+
if content
|
71
|
+
matches.each do |el|
|
72
|
+
return assert(true) if el.content.match content
|
73
|
+
end
|
74
|
+
assert(false, "No matches for '#{content}' with the selector '#{selector}'.")
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class VitaeExecutableTest < VitaeTestCase
|
4
|
+
|
5
|
+
test "create gives help when called without args" do
|
6
|
+
output = vitae_create
|
7
|
+
assert_match('"create" was called incorrectly', output)
|
8
|
+
end
|
9
|
+
|
10
|
+
test "create generates a project" do
|
11
|
+
clear_test_dir
|
12
|
+
output = vitae_create("my_cvs")
|
13
|
+
|
14
|
+
files = %w[my_cvs/cvs/arthur_gunn.yaml
|
15
|
+
my_cvs/themes/default/application.js
|
16
|
+
my_cvs/themes/default/application.css]
|
17
|
+
|
18
|
+
files.each do |file|
|
19
|
+
assert(vitae_file?( file ), "#{file} should exist in #{vitae_test_dir}")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
test "create generates a project with provided names" do
|
24
|
+
clear_test_dir
|
25
|
+
output = vitae_create("resume arthur_gunn derek sajal")
|
26
|
+
|
27
|
+
files = %w[resume/cvs/arthur_gunn.yaml
|
28
|
+
resume/cvs/derek.yaml
|
29
|
+
resume/cvs/sajal.yaml
|
30
|
+
resume/themes/default/application.js
|
31
|
+
resume/themes/default/application.css]
|
32
|
+
|
33
|
+
files.each do |file|
|
34
|
+
assert(vitae_file?( file ), "#{file} should exist in #{vitae_test_dir}")
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
test "the server responds well" do
|
39
|
+
assert_match("Serving CVs", vitae_server("--pretend"))
|
40
|
+
end
|
41
|
+
|
42
|
+
test "the server accepts a custom port" do
|
43
|
+
assert_match(":3141", vitae_server("--pretend"))
|
44
|
+
assert_match(":9292", vitae_server("--pretend -p 9292"))
|
45
|
+
assert_match(":1121", vitae_server("--pretend -p 1121"))
|
46
|
+
end
|
47
|
+
|
48
|
+
test "the server gives rackup help" do
|
49
|
+
assert_match("Usage: rackup", vitae_server("-h"))
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
data/vitae.gemspec
CHANGED
@@ -11,6 +11,12 @@ Gem::Specification.new do |s|
|
|
11
11
|
s.homepage = "https://github.com/gunn/vitae"
|
12
12
|
s.summary = %q{A structured CV publishing system.}
|
13
13
|
s.description = %q{Vitae is to CVs what rubygems is to ruby code. Now I just need to program it.}
|
14
|
+
|
15
|
+
s.add_dependency "sinatra"
|
16
|
+
s.add_dependency "haml"
|
17
|
+
s.add_dependency "thor"
|
18
|
+
|
19
|
+
s.add_development_dependency "nokogiri"
|
14
20
|
|
15
21
|
s.files = `git ls-files`.split("\n")
|
16
22
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
metadata
CHANGED
@@ -5,9 +5,9 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
+
- 1
|
8
9
|
- 0
|
9
|
-
|
10
|
-
version: 0.0.2
|
10
|
+
version: 0.1.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Arthur Gunn
|
@@ -15,26 +15,101 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-12-
|
18
|
+
date: 2010-12-04 00:00:00 +13:00
|
19
19
|
default_executable:
|
20
|
-
dependencies:
|
21
|
-
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: sinatra
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
version: "0"
|
33
|
+
type: :runtime
|
34
|
+
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: haml
|
37
|
+
prerelease: false
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
hash: 3
|
44
|
+
segments:
|
45
|
+
- 0
|
46
|
+
version: "0"
|
47
|
+
type: :runtime
|
48
|
+
version_requirements: *id002
|
49
|
+
- !ruby/object:Gem::Dependency
|
50
|
+
name: thor
|
51
|
+
prerelease: false
|
52
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
53
|
+
none: false
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
hash: 3
|
58
|
+
segments:
|
59
|
+
- 0
|
60
|
+
version: "0"
|
61
|
+
type: :runtime
|
62
|
+
version_requirements: *id003
|
63
|
+
- !ruby/object:Gem::Dependency
|
64
|
+
name: nokogiri
|
65
|
+
prerelease: false
|
66
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
67
|
+
none: false
|
68
|
+
requirements:
|
69
|
+
- - ">="
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
hash: 3
|
72
|
+
segments:
|
73
|
+
- 0
|
74
|
+
version: "0"
|
75
|
+
type: :development
|
76
|
+
version_requirements: *id004
|
22
77
|
description: Vitae is to CVs what rubygems is to ruby code. Now I just need to program it.
|
23
78
|
email:
|
24
79
|
- arthur@gunn.co.nz
|
25
|
-
executables:
|
26
|
-
|
80
|
+
executables:
|
81
|
+
- vitae
|
27
82
|
extensions: []
|
28
83
|
|
29
84
|
extra_rdoc_files: []
|
30
85
|
|
31
86
|
files:
|
87
|
+
- .autotest
|
32
88
|
- .gitignore
|
33
89
|
- Gemfile
|
90
|
+
- Gemfile.lock
|
34
91
|
- README.rdoc
|
35
92
|
- Rakefile
|
93
|
+
- bin/vitae
|
94
|
+
- config.ru
|
36
95
|
- lib/vitae.rb
|
96
|
+
- lib/vitae/cv.rb
|
97
|
+
- lib/vitae/server/.gitignore
|
98
|
+
- lib/vitae/server/helpers.rb
|
99
|
+
- lib/vitae/server/server.rb
|
100
|
+
- lib/vitae/server/views/index.haml
|
101
|
+
- lib/vitae/server/views/layout.haml
|
102
|
+
- lib/vitae/server/views/show.haml
|
103
|
+
- lib/vitae/templates/cvs/arthur_gunn.yaml
|
104
|
+
- lib/vitae/templates/cvs/default.yaml.tt
|
105
|
+
- lib/vitae/templates/themes/default/application.css
|
106
|
+
- lib/vitae/templates/themes/default/application.js
|
37
107
|
- lib/vitae/version.rb
|
108
|
+
- test/active_server_test.rb
|
109
|
+
- test/basic_server_test.rb
|
110
|
+
- test/tag_helpers_test.rb
|
111
|
+
- test/test_helper.rb
|
112
|
+
- test/vitae_executable_test.rb
|
38
113
|
- vitae.gemspec
|
39
114
|
has_rdoc: true
|
40
115
|
homepage: https://github.com/gunn/vitae
|
@@ -70,5 +145,9 @@ rubygems_version: 1.3.7
|
|
70
145
|
signing_key:
|
71
146
|
specification_version: 3
|
72
147
|
summary: A structured CV publishing system.
|
73
|
-
test_files:
|
74
|
-
|
148
|
+
test_files:
|
149
|
+
- test/active_server_test.rb
|
150
|
+
- test/basic_server_test.rb
|
151
|
+
- test/tag_helpers_test.rb
|
152
|
+
- test/test_helper.rb
|
153
|
+
- test/vitae_executable_test.rb
|