json_resume 1.0.3 → 1.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -0
- data/.rubocop_todo.yml +87 -0
- data/README.md +6 -1
- data/Rakefile +1 -1
- data/bin/json_resume +110 -82
- data/json_resume.gemspec +19 -20
- data/lib/json_resume.rb +2 -2
- data/lib/json_resume/formatter.rb +122 -125
- data/lib/json_resume/formatter_html.rb +9 -10
- data/lib/json_resume/formatter_latex.rb +13 -14
- data/lib/json_resume/formatter_md.rb +6 -7
- data/lib/json_resume/json_resume.rb +13 -13
- data/lib/json_resume/reader.rb +21 -19
- data/lib/json_resume/version.rb +1 -1
- data/locale/pt.yml +3 -3
- data/locale/zh_cn.yml +45 -0
- data/spec/json_resume/formatter_html_spec.rb +20 -20
- data/spec/json_resume/formatter_latex_spec.rb +7 -7
- data/spec/json_resume/formatter_spec.rb +19 -19
- data/spec/json_resume/reader_spec.rb +11 -11
- metadata +5 -2
data/lib/json_resume.rb
CHANGED
@@ -1,130 +1,127 @@
|
|
1
|
-
#Hack to generalise call empty? on
|
2
|
-
#objects, arrays and hashes
|
1
|
+
# Hack to generalise call empty? on
|
2
|
+
# objects, arrays and hashes
|
3
3
|
class Object
|
4
|
-
|
5
|
-
|
6
|
-
|
4
|
+
def empty?
|
5
|
+
false
|
6
|
+
end
|
7
7
|
end
|
8
8
|
|
9
9
|
module JsonResume
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
end
|
10
|
+
class Formatter
|
11
|
+
attr_reader :hash
|
12
|
+
|
13
|
+
def initialize(hash)
|
14
|
+
@hash = hash
|
15
|
+
|
16
|
+
# recursively defined proc
|
17
|
+
@hash_proc = proc do |k, v|
|
18
|
+
v = k if v.nil? # HACK: to make it common for hash and array
|
19
|
+
v.delete_if(&@hash_proc) if [Hash, Array].any? { |x| v.instance_of? x }
|
20
|
+
v.empty?
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def add_linkedin_github_url
|
25
|
+
@hash['raw_website'] = @hash['bio_data']['website'].sub(%r{^https?://}, '') if @hash['bio_data'] && @hash['bio_data']['website']
|
26
|
+
@hash['linkedin_url'] = 'http://linkedin.com/in/' + @hash['linkedin_id'] if @hash['linkedin_id']
|
27
|
+
@hash['github_url'] = 'http://github.com/' + @hash['github_id'] if @hash['github_id']
|
28
|
+
end
|
29
|
+
|
30
|
+
def add_last_marker_on_stars
|
31
|
+
return if @hash['bio_data']['stars'].nil?
|
32
|
+
@hash['bio_data']['stars'] = {
|
33
|
+
'items' => @hash['bio_data']['stars'].map { |i| { 'name' => i } }
|
34
|
+
}
|
35
|
+
@hash['bio_data']['stars']['items'][-1]['last'] = true
|
36
|
+
end
|
37
|
+
|
38
|
+
def add_last_marker_on_skills
|
39
|
+
return if @hash['bio_data']['skills'].nil?
|
40
|
+
@hash['bio_data']['skills']['details'].each do |item|
|
41
|
+
item['items'].map! { |x| { 'name' => x } }
|
42
|
+
item['items'][-1]['last'] = true
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def add_last_marker_on_tools
|
47
|
+
return if @hash['bio_data']['other_projects'].nil?
|
48
|
+
@hash['bio_data']['other_projects']['items'].each do |item|
|
49
|
+
next if item['technology_used'].nil?
|
50
|
+
item['technology_used']['tools'].map! { |x| { 'name' => x } }
|
51
|
+
item['technology_used']['tools'][-1]['last'] = true
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def add_last_marker_on_field(field_name)
|
56
|
+
return if @hash['bio_data'][field_name].nil?
|
57
|
+
@hash['bio_data'][field_name]['items'].each do |item|
|
58
|
+
next if item['technology_used'].nil?
|
59
|
+
item['technology_used']['tools'].map! { |x| { 'name' => x } }
|
60
|
+
item['technology_used']['tools'][-1]['last'] = true
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def cleanse
|
65
|
+
@hash.delete_if(&@hash_proc)
|
66
|
+
self
|
67
|
+
end
|
68
|
+
|
69
|
+
def format_to_output_type
|
70
|
+
format_proc = proc do |k, v|
|
71
|
+
v = k if v.nil?
|
72
|
+
v.each { |x| format_proc.call(x) } if [Hash, Array].any? { |x| v.instance_of? x }
|
73
|
+
format_string v if v.instance_of? String
|
74
|
+
end
|
75
|
+
@hash.each { |x| format_proc.call(x) }
|
76
|
+
self
|
77
|
+
end
|
78
|
+
|
79
|
+
def format_string(_)
|
80
|
+
fail(NotImplementedError.new('format_string not impl in formatter'), '')
|
81
|
+
end
|
82
|
+
|
83
|
+
def item_false?(item)
|
84
|
+
item == false || item == 'false'
|
85
|
+
end
|
86
|
+
|
87
|
+
def purge_gpa
|
88
|
+
return if @hash['bio_data']['education'].nil?
|
89
|
+
@hash['bio_data']['education'].delete('show_gpa') if item_false?(@hash['bio_data']['education']['show_gpa']) || @hash['bio_data']['education']['schools'].all? { |sch| sch['gpa'].nil? || sch['gpa'].empty? }
|
90
|
+
end
|
91
|
+
|
92
|
+
def add_padding(course)
|
93
|
+
return if @hash['bio_data'].nil? || @hash['bio_data'][course].nil?
|
94
|
+
course_hash = @hash['bio_data'][course]
|
95
|
+
course_hash << {} if course_hash.size.odd?
|
96
|
+
@hash['bio_data'][course] = {
|
97
|
+
'rows' => course_hash.each_slice(2).to_a.map { |i| { 'columns' => i } }
|
98
|
+
}
|
99
|
+
end
|
100
|
+
|
101
|
+
def format
|
102
|
+
return if @hash['bio_data'].nil?
|
103
|
+
|
104
|
+
cleanse
|
105
|
+
|
106
|
+
format_to_output_type
|
107
|
+
|
108
|
+
add_last_marker_on_stars
|
109
|
+
|
110
|
+
add_last_marker_on_skills
|
111
|
+
|
112
|
+
add_last_marker_on_field 'experience'
|
113
|
+
add_last_marker_on_field 'other_projects'
|
114
|
+
|
115
|
+
purge_gpa
|
116
|
+
|
117
|
+
add_linkedin_github_url
|
118
|
+
|
119
|
+
# make odd listed courses to even
|
120
|
+
%w(grad_courses undergrad_courses).each do |course|
|
121
|
+
add_padding(course)
|
122
|
+
end
|
123
|
+
|
124
|
+
self
|
125
|
+
end
|
126
|
+
end
|
130
127
|
end
|
@@ -1,21 +1,21 @@
|
|
1
1
|
require_relative 'formatter'
|
2
2
|
|
3
3
|
module JsonResume
|
4
|
-
|
5
|
-
def format_link
|
6
|
-
|
4
|
+
class FormatterHtml < Formatter
|
5
|
+
def format_link(str)
|
6
|
+
str.gsub!(/\[(.*?)\]\((.*?)\)/, '<a href="\2">\1</a>')
|
7
7
|
end
|
8
8
|
|
9
|
-
def format_autolink
|
10
|
-
|
9
|
+
def format_autolink(str)
|
10
|
+
str.gsub!(/<<(\S*?)>>/, '<a href="\1">\1</a>')
|
11
11
|
end
|
12
12
|
|
13
|
-
def format_emphasis
|
13
|
+
def format_emphasis(str)
|
14
14
|
str.gsub!(/\b_(.+?)_\b/, '<i>\1</i>')
|
15
15
|
str.gsub!(/\*\*(.+?)\*\*/, '<b>\1</b>')
|
16
16
|
end
|
17
17
|
|
18
|
-
def format_string
|
18
|
+
def format_string(str)
|
19
19
|
format_link str
|
20
20
|
format_autolink str
|
21
21
|
format_emphasis str
|
@@ -24,8 +24,7 @@ module JsonResume
|
|
24
24
|
def format
|
25
25
|
super
|
26
26
|
|
27
|
-
|
27
|
+
self
|
28
28
|
end
|
29
|
-
|
30
|
-
end
|
29
|
+
end
|
31
30
|
end
|
@@ -2,32 +2,31 @@ require_relative 'formatter'
|
|
2
2
|
|
3
3
|
module JsonResume
|
4
4
|
class FormatterLatex < Formatter
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
str.gsub!(/\}/, '\}')
|
5
|
+
def format_slashes(str)
|
6
|
+
str.gsub!(/\\/, '\textbackslash')
|
7
|
+
str.gsub!(/\{/, '\{')
|
8
|
+
str.gsub!(/\}/, '\}')
|
10
9
|
end
|
11
10
|
|
12
|
-
def format_link
|
13
|
-
|
11
|
+
def format_link(str)
|
12
|
+
str.gsub!(/\[(.*?)\]\((.*?)\)/, '{\color{see} \href{\2}{\1}}')
|
14
13
|
end
|
15
14
|
|
16
|
-
def format_autolink
|
17
|
-
|
15
|
+
def format_autolink(str)
|
16
|
+
str.gsub!(/<<(\S*?)>>/, '{\color{see} \url{\1}}')
|
18
17
|
end
|
19
18
|
|
20
|
-
def format_emphasis
|
19
|
+
def format_emphasis(str)
|
21
20
|
str.gsub!(/\b_(.+?)_\b/, '\textit{\1}')
|
22
21
|
str.gsub!(/\*\*(.+?)\*\*/, '\textbf{\1}')
|
23
22
|
end
|
24
23
|
|
25
|
-
def format_superscripts
|
24
|
+
def format_superscripts(str)
|
26
25
|
str.gsub!(/<sup>(.*?)<\/sup>/, '$^{\1}$')
|
27
26
|
str.gsub!(/<sub>(.*?)<\/sub>/, '$_{\1}$')
|
28
27
|
end
|
29
28
|
|
30
|
-
def format_symbols
|
29
|
+
def format_symbols(str)
|
31
30
|
str.gsub!(/#/, '\#')
|
32
31
|
str.gsub!(/\$/, '\$')
|
33
32
|
str.gsub!(/&/, '\\\\&')
|
@@ -36,7 +35,7 @@ module JsonResume
|
|
36
35
|
str.gsub!(/_/, '\_')
|
37
36
|
end
|
38
37
|
|
39
|
-
def format_string
|
38
|
+
def format_string(str)
|
40
39
|
format_slashes str
|
41
40
|
format_link str
|
42
41
|
format_autolink str
|
@@ -48,7 +47,7 @@ module JsonResume
|
|
48
47
|
def format
|
49
48
|
super
|
50
49
|
|
51
|
-
|
50
|
+
self
|
52
51
|
end
|
53
52
|
end
|
54
53
|
end
|
@@ -1,20 +1,19 @@
|
|
1
1
|
require_relative 'formatter'
|
2
2
|
|
3
3
|
module JsonResume
|
4
|
-
|
5
|
-
def format_autolink
|
6
|
-
|
4
|
+
class FormatterMd < Formatter
|
5
|
+
def format_autolink(str)
|
6
|
+
str.gsub!(/<<(\S*?)>>/, '[\1](\1)')
|
7
7
|
end
|
8
8
|
|
9
|
-
def format_string
|
9
|
+
def format_string(str)
|
10
10
|
format_autolink str
|
11
11
|
end
|
12
12
|
|
13
13
|
def format
|
14
14
|
super
|
15
15
|
|
16
|
-
|
16
|
+
self
|
17
17
|
end
|
18
|
-
|
19
|
-
end
|
18
|
+
end
|
20
19
|
end
|
@@ -1,19 +1,19 @@
|
|
1
1
|
require_relative 'reader'
|
2
2
|
|
3
3
|
module JsonResume
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
4
|
+
class << self
|
5
|
+
def new(json_input, options = {})
|
6
|
+
options = options.each_with_object({}) { |(k, v), memo| memo[k.to_sym] = v }
|
7
|
+
JsonResume::Core.new(json_input, options)
|
8
|
+
end
|
9
|
+
end
|
10
10
|
|
11
|
-
|
12
|
-
|
11
|
+
class Core
|
12
|
+
attr_accessor :reader
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
14
|
+
def initialize(json_input, options)
|
15
|
+
@reader = Reader.new(json_input, options)
|
16
|
+
@reader.format!
|
17
|
+
end
|
18
|
+
end
|
19
19
|
end
|
data/lib/json_resume/reader.rb
CHANGED
@@ -3,34 +3,36 @@ require_relative 'formatter_latex'
|
|
3
3
|
require_relative 'formatter_md'
|
4
4
|
require 'rest-client'
|
5
5
|
require 'json'
|
6
|
+
require 'yaml'
|
6
7
|
|
7
8
|
module JsonResume
|
8
|
-
|
9
|
-
|
9
|
+
class Reader
|
10
|
+
attr_accessor :hash
|
10
11
|
|
11
|
-
|
12
|
-
output_type = options[:output_type] ||
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
12
|
+
def initialize(json_input, options)
|
13
|
+
output_type = options[:output_type] || 'html' # default html, others latex, md
|
14
|
+
@json_string = case json_input
|
15
|
+
when /^(http|https|www)/ then RestClient.get(json_input)
|
16
|
+
when /\.json$/i then File.read(json_input)
|
17
|
+
when /\.ya?ml$/i then JSON.dump(YAML.load_file(json_input))
|
18
|
+
else json_input
|
19
|
+
end
|
18
20
|
@output_type = output_type
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
21
|
+
begin
|
22
|
+
@hash = JSON.parse(@json_string)
|
23
|
+
rescue JSON::ParserError => e
|
24
|
+
raise Exception, 'Either you entered a file without .json extension or JSON string is wrong: ' + e.message
|
25
|
+
end
|
26
|
+
end
|
25
27
|
|
26
28
|
def format!
|
27
29
|
formatters = {
|
28
|
-
:
|
29
|
-
:
|
30
|
-
:
|
30
|
+
latex: JsonResume::FormatterLatex,
|
31
|
+
html: JsonResume::FormatterHtml,
|
32
|
+
markdown: JsonResume::FormatterMd
|
31
33
|
}
|
32
34
|
type = @output_type.to_sym
|
33
35
|
@hash = formatters[type].new(@hash).format.hash
|
34
36
|
end
|
35
|
-
|
37
|
+
end
|
36
38
|
end
|