resume_exporter 0.0.1 → 1.0.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.
- checksums.yaml +4 -4
- data/bin/resume_exporter +4 -2
- data/lib/exporters/html.rb +33 -0
- data/lib/exporters/pdf.rb +13 -0
- data/lib/extractors/html/linkedin.rb +145 -169
- data/lib/extractors/html/stackoverflow.rb +60 -72
- data/lib/extractors/html/xing.rb +46 -60
- data/lib/extractors/html.rb +1 -1
- data/lib/extractors/json/fresh.rb +196 -233
- data/lib/extractors/json/json_resume.rb +107 -127
- data/lib/extractors/json/prtflio.rb +20 -24
- data/lib/extractors/json.rb +7 -6
- data/lib/resume_exporter.rb +6 -0
- data/lib/templates/default.json.jbuilder +162 -229
- data/lib/templates/default.md.erb +99 -244
- data/lib/templates/default.txt.erb +99 -224
- data/lib/templates/default.xml.builder +162 -227
- data/lib/templates/fresh.json.jbuilder +149 -155
- data/lib/templates/html/_affiliation.liquid +53 -0
- data/lib/templates/html/_basics.liquid +19 -0
- data/lib/templates/html/_contact.liquid +27 -0
- data/lib/templates/html/_css.liquid +324 -0
- data/lib/templates/html/_disposition.liquid +13 -0
- data/lib/templates/html/_education.liquid +56 -0
- data/lib/templates/html/_employment.liquid +67 -0
- data/lib/templates/html/_extracurricular.liquid +53 -0
- data/lib/templates/html/_footer.liquid +1 -0
- data/lib/templates/html/_governance.liquid +52 -0
- data/lib/templates/html/_image.liquid +7 -0
- data/lib/templates/html/_interests.liquid +23 -0
- data/lib/templates/html/_languages.liquid +22 -0
- data/lib/templates/html/_open_source.liquid +53 -0
- data/lib/templates/html/_patents.liquid +50 -0
- data/lib/templates/html/_projects.liquid +53 -0
- data/lib/templates/html/_qualifications.liquid +53 -0
- data/lib/templates/html/_reading.liquid +52 -0
- data/lib/templates/html/_recognition.liquid +54 -0
- data/lib/templates/html/_references.liquid +28 -0
- data/lib/templates/html/_resume.liquid +49 -0
- data/lib/templates/html/_service.liquid +53 -0
- data/lib/templates/html/_skills.liquid +35 -0
- data/lib/templates/html/_social.liquid +25 -0
- data/lib/templates/html/_speaking.liquid +53 -0
- data/lib/templates/html/_writing.liquid +52 -0
- data/lib/templates/html/default.liquid +1 -0
- data/lib/templates/json_resume.json.jbuilder +72 -72
- metadata +119 -20
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ce4e808a61306a1ddaed6e8d6a2ec0f50ccad275
|
4
|
+
data.tar.gz: 10b654bc305eef2ba48703bc97d235f0125bf92a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2d56bb08e5b971b26924859b9de613558ee10ff013f6b764903fbae80c972db5866dfe0ca88cf6f7fc7bbb4b8afd07746bb1b7f61254ac5fd3e54c74beeb3ca5
|
7
|
+
data.tar.gz: 99cdad9c6b2239dc68038cb53b4dc444faa269805ef1709f8076b72a9523a901123d87ff6cf642f0b056fde9d58c1440474980e3c7d608fa5aed00bebf0f6d0d
|
data/bin/resume_exporter
CHANGED
@@ -1,8 +1,10 @@
|
|
1
|
+
#! ruby
|
2
|
+
|
1
3
|
require 'rubygems'
|
2
4
|
require 'commander/import'
|
3
5
|
require 'resume_exporter'
|
4
6
|
|
5
|
-
program :version, '0.0
|
7
|
+
program :version, '1.0.0'
|
6
8
|
program :description, 'ResumeExporter is a tool to export data from public profile html files.
|
7
9
|
Save your profile (e.g. from LinkedIn, Xing, or Stackoverflow) as html and export to json or xml with the help of ResumeExporter.
|
8
10
|
|
@@ -40,7 +42,7 @@ command :export do |c|
|
|
40
42
|
|
41
43
|
r = ResumeExporter.new(file)
|
42
44
|
|
43
|
-
|
45
|
+
puts r.export(format: options.format)
|
44
46
|
end
|
45
47
|
end
|
46
48
|
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'tilt'
|
2
|
+
require 'liquid'
|
3
|
+
require "safe_yaml"
|
4
|
+
require "base64"
|
5
|
+
require "open-uri"
|
6
|
+
|
7
|
+
module Base64Filter
|
8
|
+
def encode64(input)
|
9
|
+
begin
|
10
|
+
image = open(input) {|f| f.read }
|
11
|
+
base64 = Base64.encode64(image)
|
12
|
+
ext = File.extname(input).strip.downcase[1..-1]
|
13
|
+
out = "data:image/#{ext};base64,#{base64}"
|
14
|
+
rescue
|
15
|
+
input
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
module Exporter
|
21
|
+
module Html
|
22
|
+
def self.export(options = {})
|
23
|
+
template = options[:template] || "default"
|
24
|
+
template_path = File.expand_path("../templates/html/#{template}.liquid", __dir__)
|
25
|
+
template_dir = File.dirname(template_path)
|
26
|
+
|
27
|
+
@data = options[:data]
|
28
|
+
Liquid::Template.file_system = Liquid::LocalFileSystem.new(template_dir)
|
29
|
+
Liquid::Template.register_filter(Base64Filter)
|
30
|
+
Tilt.new(template_path).render(self, { "site" => { "data" => { "resume" => @data }}})
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require "exporters/html"
|
2
|
+
require "pdfkit"
|
3
|
+
|
4
|
+
module Exporter
|
5
|
+
module Pdf
|
6
|
+
def self.export(options = {})
|
7
|
+
@data = options[:data]
|
8
|
+
html = Exporter::Html.export(data: @data)
|
9
|
+
kit = PDFKit.new(html, :page_size => 'Letter', :print_media_type => true)
|
10
|
+
kit.to_pdf
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -9,13 +9,13 @@ module Extractor
|
|
9
9
|
|
10
10
|
def basics
|
11
11
|
{
|
12
|
-
name
|
13
|
-
label
|
14
|
-
image
|
15
|
-
summary
|
16
|
-
contact
|
17
|
-
website
|
18
|
-
location
|
12
|
+
"name" => name,
|
13
|
+
"label" => label,
|
14
|
+
"image" => image,
|
15
|
+
"summary" => summary,
|
16
|
+
"contact" => {
|
17
|
+
"website" => website,
|
18
|
+
"location" => location
|
19
19
|
}
|
20
20
|
}
|
21
21
|
end
|
@@ -54,203 +54,179 @@ module Extractor
|
|
54
54
|
end
|
55
55
|
|
56
56
|
def employment
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
end
|
68
|
-
}
|
57
|
+
@doc.css('#experience .position').map do |item|
|
58
|
+
experience = {}
|
59
|
+
experience["position"] = item.at_css(".item-title").text if item.at_css(".item-title")
|
60
|
+
experience["employer"] = item.at_css(".item-subtitle").text if item.at_css(".item-subtitle")
|
61
|
+
dates = item.css(".date-range time")
|
62
|
+
experience["startDate"] = dates[0].text if dates[0]
|
63
|
+
experience["endDate"] = dates[1].text if dates[1]
|
64
|
+
experience["summary"] = item.at_css(".description").text if item.at_css(".description")
|
65
|
+
experience
|
66
|
+
end
|
69
67
|
end
|
70
68
|
|
71
69
|
def education
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
education[:summary] = d.text
|
89
|
-
end
|
70
|
+
@doc.css('#education .school').map do |item|
|
71
|
+
education = {}
|
72
|
+
education["institution"] = item.at_css(".item-title").text if item.at_css(".item-title")
|
73
|
+
|
74
|
+
subtitle = item.at_css(".item-subtitle span").text.split(", ") if item.at_css(".item-subtitle span")
|
75
|
+
if subtitle && subtitle.length == 3
|
76
|
+
education["degree"] = subtitle[0]
|
77
|
+
education["fieldOfStudy"] = subtitle[1]
|
78
|
+
education["grade"] = subtitle[2]
|
79
|
+
elsif subtitle
|
80
|
+
education["fieldOfStudy"] = subtitle
|
81
|
+
end
|
82
|
+
|
83
|
+
item.css(".description p").map do |d|
|
84
|
+
if !d.text.include?("Activities and Societies: ")
|
85
|
+
education["summary"] = d.text
|
90
86
|
end
|
91
|
-
|
92
|
-
dates = item.css(".date-range time")
|
93
|
-
education[:startDate] = dates[0].text if dates[0]
|
94
|
-
education[:endDate] = dates[1].text if dates[1]
|
95
|
-
education
|
96
87
|
end
|
97
|
-
|
88
|
+
|
89
|
+
dates = item.css(".date-range time")
|
90
|
+
education["startDate"] = dates[0].text if dates[0]
|
91
|
+
education["endDate"] = dates[1].text if dates[1]
|
92
|
+
education
|
93
|
+
end
|
98
94
|
end
|
99
95
|
|
100
96
|
def projects
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
end
|
112
|
-
}
|
97
|
+
@doc.css('#projects .project').map do |item|
|
98
|
+
project = {}
|
99
|
+
project["title"] = item.at_css(".item-title").text if item.at_css(".item-title")
|
100
|
+
project["url"] = clean_up_linkedin_redirect_url(item.at_css(".item-title a")["href"]) if item.at_css(".item-title a")
|
101
|
+
dates = item.css(".date-range time")
|
102
|
+
project["startDate"] = dates[0].text if dates[0]
|
103
|
+
project["endDate"] = dates[1].text if dates[1]
|
104
|
+
project["summary"] = item.at_css(".description").text if item.at_css(".description")
|
105
|
+
project
|
106
|
+
end
|
113
107
|
end
|
114
108
|
|
115
109
|
def skills
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
end
|
120
|
-
}
|
110
|
+
@doc.css('#skills .skill a').map do |item|
|
111
|
+
{ "name" => item.text }
|
112
|
+
end
|
121
113
|
end
|
122
114
|
|
123
115
|
def qualifications
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
].flatten
|
157
|
-
}
|
116
|
+
[
|
117
|
+
@doc.css('#certifications .certification').map do |item|
|
118
|
+
certification = {}
|
119
|
+
certification["category"] = "Certification"
|
120
|
+
certification["title"] = item.at_css(".item-title").text if item.at_css(".item-title")
|
121
|
+
certification["from"] = item.at_css(".item-subtitle").text if item.at_css(".item-subtitle")
|
122
|
+
certification["url"] = clean_up_linkedin_redirect_url(item.at_css(".item-title a")["href"]) if item.at_css(".item-title a")
|
123
|
+
dates = item.css(".date-range time")
|
124
|
+
certification["startDate"] = dates[0].text if dates[0]
|
125
|
+
certification["endDate"] = dates[1].text if dates[1]
|
126
|
+
certification
|
127
|
+
end,
|
128
|
+
|
129
|
+
@doc.css('#courses .course').map do |item|
|
130
|
+
course = {}
|
131
|
+
course["category"] = "Course"
|
132
|
+
course["title"] = item.at_css("span").text
|
133
|
+
course
|
134
|
+
end,
|
135
|
+
|
136
|
+
@doc.css('#scores .score').map do |item|
|
137
|
+
score = {}
|
138
|
+
score["category"] = "Test Score"
|
139
|
+
score["title"] = item.at_css(".item-title").text if item.at_css(".item-title")
|
140
|
+
# score["score"] = item.at_css(".item-subtitle").text.gsub(/[^0-9]/, "") if item.at_css(".item-subtitle")
|
141
|
+
dates = item.css(".date-range time")
|
142
|
+
score["startDate"] = dates[0].text if dates[0]
|
143
|
+
score["endDate"] = dates[1].text if dates[1]
|
144
|
+
score["summary"] = item.at_css(".description").text if item.at_css(".description")
|
145
|
+
score
|
146
|
+
end
|
147
|
+
].flatten
|
158
148
|
end
|
159
149
|
|
160
150
|
def recognition
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
end
|
173
|
-
}
|
151
|
+
@doc.css('#awards .award').map do |item|
|
152
|
+
award = {}
|
153
|
+
award["category"] = "Award"
|
154
|
+
award["title"] = item.at_css(".item-title").text if item.at_css(".item-title")
|
155
|
+
award["from"] = item.at_css(".item-subtitle").text if item.at_css(".item-subtitle")
|
156
|
+
dates = item.css(".date-range time")
|
157
|
+
award["startDate"] = dates[0].text if dates[0]
|
158
|
+
award["endDate"] = dates[1].text if dates[1]
|
159
|
+
award["summary"] = item.at_css(".description").text if item.at_css(".description")
|
160
|
+
award
|
161
|
+
end
|
174
162
|
end
|
175
163
|
|
176
164
|
def writing
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
end
|
188
|
-
}
|
165
|
+
@doc.css('#publications .publication').map do |item|
|
166
|
+
publication = {}
|
167
|
+
publication["title"] = item.at_css(".item-title").text if item.at_css(".item-title")
|
168
|
+
publication["url"] = clean_up_linkedin_redirect_url(item.at_css(".item-title a")["href"]) if item.at_css(".item-title a")
|
169
|
+
publication["publisher"] = item.at_css(".item-subtitle").text if item.at_css(".item-subtitle")
|
170
|
+
publication["date"] = item.css(".date-range time").text if item.css(".date-range time")
|
171
|
+
publication["summary"] = item.at_css(".description").text if item.at_css(".description")
|
172
|
+
# publication["authors"] = item.css(".contributors .contributor").map { |c| c.text }.join("") if item.at_css(".contributors .contributor")
|
173
|
+
publication
|
174
|
+
end
|
189
175
|
end
|
190
176
|
|
191
177
|
def patents
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
end
|
202
|
-
}
|
178
|
+
@doc.css('#patents .patent').map do |item|
|
179
|
+
patent = {}
|
180
|
+
patent["title"] = item.at_css(".item-title").text if item.at_css(".item-title")
|
181
|
+
patent["url"] = clean_up_linkedin_redirect_url(item.at_css(".item-title a")["href"]) if item.at_css(".item-title a")
|
182
|
+
patent["date"] = item.at_css(".date-range time").text if item.at_css(".date-range time")
|
183
|
+
patent["status"] = item.at_css(".date-range").children.reject{|e| e.name == "time" }.map(&:text).join().strip if item.at_css(".date-range")
|
184
|
+
patent["summary"] = item.at_css(".description").text if item.at_css(".description")
|
185
|
+
patent
|
186
|
+
end
|
203
187
|
end
|
204
188
|
|
205
189
|
def languages
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
end
|
213
|
-
}
|
190
|
+
@doc.css('#languages .language').map do |item|
|
191
|
+
language = {}
|
192
|
+
language["language"] = item.at_css(".name").text if item.at_css(".name")
|
193
|
+
language["level"] = item.at_css(".proficiency").text if item.at_css(".proficiency")
|
194
|
+
language
|
195
|
+
end
|
214
196
|
end
|
215
197
|
|
216
198
|
def interests
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
end
|
221
|
-
}
|
199
|
+
@doc.css('#interests .interest span').map do |item|
|
200
|
+
{ "name" => item.text }
|
201
|
+
end
|
222
202
|
end
|
223
203
|
|
224
204
|
def affiliations
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
end
|
236
|
-
}
|
205
|
+
@doc.css('#organizations li').map do |item|
|
206
|
+
organization = {}
|
207
|
+
organization["organization"] = item.at_css(".item-title").text if item.at_css(".item-title")
|
208
|
+
organization["roles"] = [item.at_css(".item-subtitle").text] if item.at_css(".item-subtitle")
|
209
|
+
dates = item.css(".date-range time")
|
210
|
+
organization["startDate"] = dates[0].text if dates[0]
|
211
|
+
organization["endDate"] = dates[1].text if dates[1]
|
212
|
+
organization["summary"] = item.at_css(".description").text if item.at_css(".description")
|
213
|
+
organization
|
214
|
+
end
|
237
215
|
end
|
238
216
|
|
239
217
|
def service
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
end
|
253
|
-
}
|
218
|
+
@doc.css('#volunteering .position').map do |item|
|
219
|
+
volunteering = {}
|
220
|
+
volunteering["category"] = "Volunteer Work"
|
221
|
+
volunteering["roles"] = [item.at_css(".item-title").text] if item.at_css(".item-title")
|
222
|
+
volunteering["organization"] = item.at_css(".item-subtitle").text if item.at_css(".item-subtitle")
|
223
|
+
# volunteering["cause"] = item.at_css(".cause").text if item.at_css(".cause")
|
224
|
+
dates = item.css(".date-range time")
|
225
|
+
volunteering["startDate"] = dates[0].text if dates[0]
|
226
|
+
volunteering["endDate"] = dates[1].text if dates[1]
|
227
|
+
volunteering["summary"] = item.at_css(".description").text if item.at_css(".description")
|
228
|
+
volunteering
|
229
|
+
end
|
254
230
|
end
|
255
231
|
|
256
232
|
private
|
@@ -9,12 +9,12 @@ module Extractor
|
|
9
9
|
|
10
10
|
def basics
|
11
11
|
{
|
12
|
-
name
|
13
|
-
label
|
14
|
-
image
|
15
|
-
contact
|
16
|
-
website
|
17
|
-
location
|
12
|
+
"name" => name,
|
13
|
+
"label" => label,
|
14
|
+
"image" => image,
|
15
|
+
"contact" => {
|
16
|
+
"website" => website,
|
17
|
+
"location" => location
|
18
18
|
}
|
19
19
|
}
|
20
20
|
end
|
@@ -40,84 +40,72 @@ module Extractor
|
|
40
40
|
end
|
41
41
|
|
42
42
|
def employment
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
end
|
55
|
-
}
|
43
|
+
@doc.css('#cv-Experience .cv-section').map do |item|
|
44
|
+
experience = {}
|
45
|
+
experience["position"] = item.at_css(".preview h3").children.reject{|e| e.name == "span" }.map(&:text).join().gsub(/\s+/, ' ').strip if item.at_css(".preview h3")
|
46
|
+
experience["employer"] = item.at_css(".preview h3 .location").text.gsub(/\s+/, ' ').strip if item.at_css(".preview h3 .location")
|
47
|
+
dates = item.at_css('.time-frame').text.gsub(/\s+/, ' ').strip.split(" → ") if item.at_css('.time-frame')
|
48
|
+
experience["startDate"] = dates[0] if dates && dates[0]
|
49
|
+
experience["endDate"] = dates[1] if dates && dates[1]
|
50
|
+
experience["keywords"] = item.css(".timeline-item-tags .post-tag").map(&:text) if item.at_css(".timeline-item-tags .post-tag")
|
51
|
+
experience["summary"] = item.at_css(".description").text.gsub(/\s+/, ' ').strip if item.at_css(".description")
|
52
|
+
experience
|
53
|
+
end
|
56
54
|
end
|
57
55
|
|
58
56
|
def education
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
end
|
71
|
-
}
|
57
|
+
@doc.css('#cv-Education .cv-section').map do |item|
|
58
|
+
education = {}
|
59
|
+
education["institution"] = item.at_css(".preview h3 .location").text.gsub(/\s+/, ' ').strip if item.at_css(".preview h3 .location")
|
60
|
+
education["degree"] = item.at_css(".preview h3").children.reject{|e| e.name == "span" }.map(&:text).join().gsub(/\s+/, ' ').strip.gsub(/[,]?$/, '') if item.at_css(".preview h3")
|
61
|
+
education["summary"] = item.at_css(".description").text.gsub(/\s+/, ' ').strip if item.at_css(".description")
|
62
|
+
dates = item.at_css('.time-frame').text.gsub(/\s+/, ' ').strip.split(" → ") if item.at_css('.time-frame')
|
63
|
+
education["startDate"] = dates[0] if dates && dates[0]
|
64
|
+
education["endDate"] = dates[1] if dates && dates[1]
|
65
|
+
education["keywords"] = item.css(".timeline-item-tags .post-tag").map(&:text) if item.at_css(".timeline-item-tags .post-tag")
|
66
|
+
education
|
67
|
+
end
|
72
68
|
end
|
73
69
|
|
74
70
|
def projects
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
end
|
87
|
-
}
|
71
|
+
@doc.css('#cv-Apps\ \&\ Software .cv-section').map do |item|
|
72
|
+
project = {}
|
73
|
+
project["title"] = item.at_css(".preview h3").text.gsub(/\s+/, ' ').strip if item.at_css(".preview h3")
|
74
|
+
project["url"] = item.at_css(".preview h3 a")["href"] if item.at_css(".preview h3 a")
|
75
|
+
dates = item.at_css('.time-frame').text.gsub(/\s+/, ' ').strip.split(" → ") if item.at_css('.time-frame')
|
76
|
+
project["startDate"] = dates[0] if dates && dates[0]
|
77
|
+
project["endDate"] = dates[1] if dates && dates[1]
|
78
|
+
project["summary"] = item.at_css(".description").text.gsub(/\s+/, ' ').strip if item.at_css(".description")
|
79
|
+
project["keywords"] = item.css(".timeline-item-tags .post-tag").map(&:text) if item.at_css(".timeline-item-tags .post-tag")
|
80
|
+
project
|
81
|
+
end
|
88
82
|
end
|
89
83
|
|
90
84
|
def qualifications
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
certification
|
102
|
-
end
|
103
|
-
].flatten
|
104
|
-
}
|
85
|
+
@doc.css('#cv-Certifications .cv-section').map do |item|
|
86
|
+
certification = {}
|
87
|
+
certification["category"] = "Certificate"
|
88
|
+
certification["title"] = item.at_css(".preview h3").text.gsub(/\s+/, ' ').strip if item.at_css(".preview h3")
|
89
|
+
dates = item.at_css('.time-frame').text.gsub(/\s+/, ' ').strip.split(" → ") if item.at_css('.time-frame')
|
90
|
+
certification["startDate"] = dates[0] if dates && dates[0]
|
91
|
+
certification["endDate"] = dates[1] if dates && dates[1]
|
92
|
+
certification["keywords"] = item.css(".timeline-item-tags .post-tag").map(&:text) if item.at_css(".timeline-item-tags .post-tag")
|
93
|
+
certification
|
94
|
+
end
|
105
95
|
end
|
106
96
|
|
107
97
|
def openSource
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
end
|
120
|
-
}
|
98
|
+
@doc.css('#cv-Open\ Source .cv-section').map do |item|
|
99
|
+
project = {}
|
100
|
+
project["title"] = item.at_css(".preview h3").text.gsub(/\s+/, ' ').strip if item.at_css(".preview h3")
|
101
|
+
project["repo"] = item.at_css(".preview h3 a")["href"] if item.at_css(".preview h3 a")
|
102
|
+
dates = item.at_css('.time-frame').text.gsub(/\s+/, ' ').strip.split(" → ") if item.at_css('.time-frame')
|
103
|
+
project["startDate"] = dates[0] if dates && dates[0]
|
104
|
+
project["endDate"] = dates[1] if dates && dates[1]
|
105
|
+
project["summary"] = item.at_css(".description").text.gsub(/\s+/, ' ').strip if item.at_css(".description")
|
106
|
+
project["keywords"] = item.css(".timeline-item-tags .post-tag").map(&:text) if item.at_css(".timeline-item-tags .post-tag")
|
107
|
+
project
|
108
|
+
end
|
121
109
|
end
|
122
110
|
end
|
123
111
|
end
|