json_resume 1.0.3 → 1.0.4
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/.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
|