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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5c2a37ce811da368c2df5af7af1e7e4088b34072
|
4
|
+
data.tar.gz: 39690709061e65e1183a938971689231a7662dc3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3f567a271f08691c337ae6141e4856107c84f30fbe98d2aecaebc9b05e0ddd0df21b5e4246179df9b0c7c67633e4e779b19b3d502c557430d8785566edb0708f
|
7
|
+
data.tar.gz: 262094ab199cc9c47d347e6dddef3e857b94719aa236cfc5ff11901602ed1e186067983957c5013d6f0ac1a485112f6c4fa5ca911b9c0ae49ac3f87b47f72492
|
data/.rubocop.yml
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
inherit_from: .rubocop_todo.yml
|
data/.rubocop_todo.yml
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
# This configuration was generated by `rubocop --auto-gen-config`
|
2
|
+
# on 2014-12-29 14:04:27 +0530 using RuboCop version 0.28.0.
|
3
|
+
# The point is for the user to remove these configuration records
|
4
|
+
# one by one as the offenses are removed from the code base.
|
5
|
+
# Note that changes in the inspected code, or installation of new
|
6
|
+
# versions of RuboCop, may require this file to be generated again.
|
7
|
+
|
8
|
+
# Offense count: 8
|
9
|
+
Metrics/AbcSize:
|
10
|
+
Max: 22
|
11
|
+
|
12
|
+
# Offense count: 1
|
13
|
+
# Configuration parameters: CountComments.
|
14
|
+
Metrics/ClassLength:
|
15
|
+
Max: 253
|
16
|
+
|
17
|
+
# Offense count: 36
|
18
|
+
# Configuration parameters: AllowURI, URISchemes.
|
19
|
+
Metrics/LineLength:
|
20
|
+
Max: 213
|
21
|
+
|
22
|
+
# Offense count: 4
|
23
|
+
# Configuration parameters: CountComments.
|
24
|
+
Metrics/MethodLength:
|
25
|
+
Max: 30
|
26
|
+
|
27
|
+
# Offense count: 1
|
28
|
+
Style/AccessorMethodName:
|
29
|
+
Enabled: true
|
30
|
+
|
31
|
+
# Offense count: 1
|
32
|
+
# Cop supports --auto-correct.
|
33
|
+
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
34
|
+
Style/AndOr:
|
35
|
+
Enabled: true
|
36
|
+
|
37
|
+
# Offense count: 1
|
38
|
+
Style/ClassVars:
|
39
|
+
Enabled: false
|
40
|
+
|
41
|
+
# Offense count: 1
|
42
|
+
# Configuration parameters: Keywords.
|
43
|
+
Style/CommentAnnotation:
|
44
|
+
Enabled: true
|
45
|
+
|
46
|
+
# Offense count: 11
|
47
|
+
Style/Documentation:
|
48
|
+
Enabled: false
|
49
|
+
|
50
|
+
# Offense count: 1
|
51
|
+
Style/EachWithObject:
|
52
|
+
Enabled: true
|
53
|
+
|
54
|
+
# Offense count: 1
|
55
|
+
Style/EvenOdd:
|
56
|
+
Enabled: true
|
57
|
+
|
58
|
+
# Offense count: 1
|
59
|
+
# Configuration parameters: MinBodyLength.
|
60
|
+
Style/GuardClause:
|
61
|
+
Enabled: true
|
62
|
+
|
63
|
+
# Offense count: 1
|
64
|
+
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
65
|
+
Style/MethodName:
|
66
|
+
Enabled: true
|
67
|
+
|
68
|
+
# Offense count: 1
|
69
|
+
# Configuration parameters: NamePrefix, NamePrefixBlacklist.
|
70
|
+
Style/PredicateName:
|
71
|
+
Enabled: true
|
72
|
+
|
73
|
+
# Offense count: 1
|
74
|
+
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
75
|
+
Style/RaiseArgs:
|
76
|
+
Enabled: true
|
77
|
+
|
78
|
+
# Offense count: 2
|
79
|
+
# Configuration parameters: MaxSlashes.
|
80
|
+
Style/RegexpLiteral:
|
81
|
+
Enabled: true
|
82
|
+
|
83
|
+
# Offense count: 2
|
84
|
+
# Cop supports --auto-correct.
|
85
|
+
# Configuration parameters: AllowAsExpressionSeparator.
|
86
|
+
Style/Semicolon:
|
87
|
+
Enabled: true
|
data/README.md
CHANGED
@@ -16,6 +16,8 @@ A [sample](https://github.com/prat0318/json_resume/blob/master/examples/prateek_
|
|
16
16
|
|
17
17
|
Modify it as per the needs, and remove or keep rest of the fields empty.
|
18
18
|
|
19
|
+
Note: YAML files are also supported. Try `$ json_resume sample --in=yaml`.
|
20
|
+
|
19
21
|
### Conversion
|
20
22
|
|
21
23
|
* Syntax
|
@@ -23,12 +25,15 @@ Modify it as per the needs, and remove or keep rest of the fields empty.
|
|
23
25
|
```
|
24
26
|
json_resume convert [--template=/path/to/custom/template]
|
25
27
|
[--out=html|html_pdf|tex|tex_pdf|md]
|
26
|
-
[--locale=es|en|pt]
|
28
|
+
[--locale=es|en|pt|zh_cn]
|
29
|
+
[--dest_dir=/path/to/put/output/files]
|
27
30
|
[--theme=default|classic] <json_input>
|
28
31
|
|
29
32
|
<json_input> can be /path/to/json OR "{'json':'string'}" OR http://raw.json
|
30
33
|
```
|
31
34
|
|
35
|
+
NEW: YAML files are also supported. Pass path/to/yaml file (must have .yaml or .yml).
|
36
|
+
|
32
37
|
* Default (HTML) version
|
33
38
|
|
34
39
|
```
|
data/Rakefile
CHANGED
@@ -1 +1 @@
|
|
1
|
-
require
|
1
|
+
require 'bundler/gem_tasks'
|
data/bin/json_resume
CHANGED
@@ -7,40 +7,52 @@ require_relative '../lib/json_resume'
|
|
7
7
|
require 'zlib'
|
8
8
|
require 'pdfkit'
|
9
9
|
require 'rest-client'
|
10
|
+
require 'json'
|
11
|
+
require 'yaml'
|
10
12
|
|
11
|
-
WL_URL =
|
13
|
+
WL_URL = 'https://www.overleaf.com/docs'
|
12
14
|
|
13
15
|
class String
|
14
|
-
|
15
|
-
|
16
|
+
def red
|
17
|
+
"\033[31m#{self}\033[0m"
|
18
|
+
end
|
19
|
+
|
20
|
+
def green
|
21
|
+
"\033[32m#{self}\033[0m"
|
22
|
+
end
|
16
23
|
end
|
17
24
|
|
18
25
|
class JsonResumeCLI < Thor
|
19
|
-
|
20
|
-
|
21
|
-
option :
|
22
|
-
option :
|
23
|
-
option :
|
24
|
-
option :
|
25
|
-
option :dest_dir, :default=>"current", :banner=>"dest_dir", :desc=>"location of dest. dir (optional)"
|
26
|
+
desc 'convert /path/to/json/file', 'converts the json to pretty resume format'
|
27
|
+
option :out, default: 'html', banner: 'output_type', desc: 'html|html_pdf|tex|tex_pdf|md'
|
28
|
+
option :template, banner: 'template_path', desc: 'path to customized template (optional)'
|
29
|
+
option :locale, default: 'en', banner: 'locale', desc: 'en|es|pt|zh_cn'
|
30
|
+
option :theme, default: 'default', banner: 'theme', desc: 'default|classic'
|
31
|
+
option :dest_dir, default: 'current', banner: 'dest_dir', desc: 'location of dest. dir (optional)'
|
26
32
|
def convert(json_input)
|
27
|
-
|
33
|
+
assign_i18n(options[:locale])
|
28
34
|
puts "Generating the #{options[:out]} type..."
|
29
|
-
dest = options[:dest_dir] == 'current'? Dir.pwd : options[:dest_dir]
|
35
|
+
dest = options[:dest_dir] == 'current' ? Dir.pwd : options[:dest_dir]
|
30
36
|
begin
|
31
|
-
puts send('convert_to_'+options[:out], json_input, get_template(options), dest)
|
37
|
+
puts send('convert_to_' + options[:out], json_input, get_template(options), dest)
|
32
38
|
rescue Encoding::InvalidByteSequenceError
|
33
39
|
puts "ERROR: You need to 'export LC_CTYPE=en_US.UTF-8' ...".green
|
34
40
|
end
|
35
41
|
end
|
36
42
|
|
37
|
-
desc
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
43
|
+
desc 'sample', 'Generates a sample json file in cwd'
|
44
|
+
option :in, default: 'json', banner: 'input_type', desc: 'json|yaml'
|
45
|
+
def sample
|
46
|
+
cwd = Dir.pwd
|
47
|
+
file_names = []
|
48
|
+
if options[:in] == 'yaml'
|
49
|
+
file_names = convert_sample_to_yaml
|
50
|
+
else
|
51
|
+
json_file_paths = Dir["#{@@orig_locn}/../examples/*.json"]
|
52
|
+
file_names = json_file_paths.map { |x| File.basename(x) }
|
53
|
+
FileUtils.cp json_file_paths, cwd
|
54
|
+
end
|
55
|
+
msg = "Generated #{file_names.join(' ')} in #{cwd}/".green
|
44
56
|
msg += "\nYou can now modify it and call: json_resume convert <file.json>"
|
45
57
|
puts msg
|
46
58
|
end
|
@@ -48,42 +60,54 @@ class JsonResumeCLI < Thor
|
|
48
60
|
no_commands do
|
49
61
|
@@orig_locn = File.expand_path(File.dirname(__FILE__))
|
50
62
|
|
63
|
+
def convert_sample_to_yaml
|
64
|
+
cwd = Dir.pwd
|
65
|
+
json_file_paths = Dir["#{@@orig_locn}/../examples/*.json"]
|
66
|
+
json_file_paths.map do |json_file_path|
|
67
|
+
dest = File.basename(json_file_path).gsub(/json$/, 'yaml')
|
68
|
+
yaml_string = (JSON.parse(File.read(json_file_path))).to_yaml
|
69
|
+
File.open("#{cwd}/#{dest}", 'w') { |f| f.write(yaml_string) }
|
70
|
+
dest
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
51
74
|
def get_template(options)
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
75
|
+
return options[:template] if options[:template]
|
76
|
+
out_type = options[:out].split('_').first # html for both html, html_pdf
|
77
|
+
out_type = 'html' if out_type == 'pdf'
|
78
|
+
theme = options[:theme]
|
79
|
+
template_path = "#{@@orig_locn}/../templates/#{theme}_#{out_type}.mustache"
|
80
|
+
if !(File.exist? template_path) && theme != 'default'
|
81
|
+
puts "Theme #{theme} doesn't exist for #{options[:out]} type yet! Using default...".red
|
82
|
+
template_path = "#{@@orig_locn}/../templates/default_#{out_type}.mustache"
|
83
|
+
end
|
84
|
+
template_path
|
62
85
|
end
|
63
86
|
|
64
|
-
def convert_to_html(json_input, template, dest=Dir.pwd, dir_name='resume')
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
87
|
+
def convert_to_html(json_input, template, dest = Dir.pwd, dir_name = 'resume')
|
88
|
+
dest_dir = "#{dest}/#{dir_name}"
|
89
|
+
FileUtils.mkdir_p dest_dir
|
90
|
+
FileUtils.cp_r(Dir["#{@@orig_locn}/../extras/resume_html/*"], dest_dir)
|
91
|
+
msg = generate_file(json_input, template, 'html', "#{dest_dir}/page.html")
|
92
|
+
msg += "\nPlace #{dest_dir}/ in /var/www/ to host."
|
93
|
+
msg
|
70
94
|
end
|
71
95
|
|
72
|
-
def convert_to_pdf(json_input, template, dest=Dir.pwd)
|
96
|
+
def convert_to_pdf(json_input, template, dest = Dir.pwd)
|
73
97
|
puts "Defaulting to 'html_pdf'..."
|
74
98
|
convert_to_html_pdf(json_input, template, dest)
|
75
99
|
end
|
76
100
|
|
77
|
-
def convert_to_html_pdf(json_input, template, dest=Dir.pwd)
|
78
|
-
tmp_dir =
|
101
|
+
def convert_to_html_pdf(json_input, template, dest = Dir.pwd)
|
102
|
+
tmp_dir = '.tmp_resume'
|
79
103
|
convert_to_html(json_input, template, dest, tmp_dir)
|
80
104
|
PDFKit.configure do |config|
|
81
105
|
wkhtmltopdf_path = `which wkhtmltopdf`.to_s.strip
|
82
106
|
config.wkhtmltopdf = wkhtmltopdf_path unless wkhtmltopdf_path.empty?
|
83
107
|
config.default_options = {
|
84
|
-
:
|
85
|
-
:
|
86
|
-
:
|
108
|
+
footer_right: "Page [page] of [toPage] .\n",
|
109
|
+
footer_font_size: 10,
|
110
|
+
footer_font_name: 'Georgia'
|
87
111
|
}
|
88
112
|
end
|
89
113
|
html_file = File.new("#{dest}/#{tmp_dir}/core-page.html")
|
@@ -91,88 +115,92 @@ class JsonResumeCLI < Thor
|
|
91
115
|
File.open("#{dest}/#{tmp_dir}/public/css/mobile.css", 'w') {}
|
92
116
|
|
93
117
|
pdf_options = {
|
94
|
-
:
|
95
|
-
:
|
96
|
-
:
|
97
|
-
:
|
98
|
-
:
|
118
|
+
margin_top: 2.0,
|
119
|
+
margin_left: 0.0,
|
120
|
+
margin_right: 0.0,
|
121
|
+
margin_bottom: 4.0,
|
122
|
+
page_size: 'Letter'
|
99
123
|
}
|
100
124
|
kit = PDFKit.new(html_file, pdf_options)
|
101
125
|
|
102
126
|
begin
|
103
|
-
kit.to_file(dest+
|
127
|
+
kit.to_file(dest + '/resume.pdf')
|
104
128
|
rescue Errno::ENOENT => e
|
105
129
|
puts "\nTry: sudo apt-get update; sudo apt-get install libxtst6 libfontconfig1".green
|
106
130
|
raise e
|
107
131
|
end
|
108
132
|
FileUtils.rm_rf "#{dest}/#{tmp_dir}"
|
109
133
|
msg = "\nGenerated resume.pdf at #{dest}.".green
|
134
|
+
msg
|
110
135
|
end
|
111
136
|
|
112
|
-
def convert_to_tex(json_input, template, dest=Dir.pwd, filename=
|
113
|
-
generate_file(json_input, template,
|
137
|
+
def convert_to_tex(json_input, template, dest = Dir.pwd, filename = 'resume.tex')
|
138
|
+
generate_file(json_input, template, 'latex', "#{dest}/#{filename}")
|
114
139
|
end
|
115
140
|
|
116
|
-
def convert_to_tex_pdf(json_input, template, dest=Dir.pwd)
|
117
|
-
file1 =
|
141
|
+
def convert_to_tex_pdf(json_input, template, dest = Dir.pwd)
|
142
|
+
file1 = 'resume'
|
143
|
+
filename = "#{file1}.tex"
|
118
144
|
convert_to_tex(json_input, template, dest, filename)
|
119
|
-
if `which pdflatex` ==
|
120
|
-
puts
|
121
|
-
puts
|
122
|
-
puts
|
145
|
+
if `which pdflatex` == ''
|
146
|
+
puts 'It looks like pdflatex is not installed...'.red
|
147
|
+
puts 'Either install it with instructions at...'
|
148
|
+
puts 'http://dods.ipsl.jussieu.fr/fast/pdflatex_install.html'
|
123
149
|
return use_write_latex(dest, filename)
|
124
150
|
end
|
125
|
-
if `kpsewhich moderncv.cls` ==
|
126
|
-
puts
|
127
|
-
puts
|
151
|
+
if `kpsewhich moderncv.cls` == ''
|
152
|
+
puts 'It looks liks moderncv package for tex is not installed'.red
|
153
|
+
puts 'Read about it here: http://ctan.org/pkg/moderncv'
|
128
154
|
return use_write_latex(dest, filename)
|
129
155
|
end
|
130
156
|
system("pdflatex -shell-escape -interaction=nonstopmode #{dest}/#{filename}")
|
131
|
-
[
|
157
|
+
['.tex', '.out', '.aux', '.log'].each do |ext|
|
132
158
|
FileUtils.rm "#{dest}/#{file1}#{ext}"
|
133
159
|
end
|
134
160
|
msg = "\nPDF is ready at #{dest}/#{file1}.pdf"
|
161
|
+
msg
|
135
162
|
end
|
136
163
|
|
137
164
|
def use_write_latex(dest, filename)
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
165
|
+
reply = ask 'Create PDF online using writeLatex/overleaf ([y]n)?'
|
166
|
+
if reply == '' || reply == 'y'
|
167
|
+
return convert_using_write_latex(dest, filename)
|
168
|
+
end
|
169
|
+
msg = "Latex file created at #{dest}/#{filename}".green
|
170
|
+
msg
|
143
171
|
end
|
144
172
|
|
145
|
-
def
|
173
|
+
def convert_using_write_latex(dest, filename)
|
146
174
|
tex_file = File.read("#{dest}/#{filename}")
|
147
|
-
|
175
|
+
msg = ''
|
176
|
+
RestClient.post(WL_URL, snip: tex_file, splash: 'none') do |response, _, _, &_|
|
148
177
|
FileUtils.rm "#{dest}/#{filename}"
|
149
178
|
msg = "\nPDF is ready at #{response.headers[:location]}".green
|
150
179
|
end
|
180
|
+
msg
|
151
181
|
end
|
152
182
|
|
153
|
-
def convert_to_md(json_input, template, dest=Dir.pwd)
|
154
|
-
generate_file(json_input, template,
|
183
|
+
def convert_to_md(json_input, template, dest = Dir.pwd)
|
184
|
+
generate_file(json_input, template, 'markdown', "#{dest}/resume.md")
|
155
185
|
end
|
156
186
|
|
157
|
-
def
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
end
|
187
|
+
def assign_i18n(locale)
|
188
|
+
I18n.load_path = Dir["#{@@orig_locn}/../locale/*.yml"]
|
189
|
+
I18n.enforce_available_locales = true
|
190
|
+
I18n.locale = locale.to_sym
|
191
|
+
end
|
162
192
|
|
163
|
-
def i18n(text)
|
164
|
-
|
165
|
-
end
|
193
|
+
def i18n(text)
|
194
|
+
text.gsub(/##(\w*?)##/) { I18n.t! Regexp.last_match[1], scope: 'headings' }
|
195
|
+
end
|
166
196
|
|
167
197
|
def generate_file(json_input, template, output_type, dest)
|
168
|
-
resume_obj = JsonResume.new(json_input,
|
198
|
+
resume_obj = JsonResume.new(json_input, 'output_type' => output_type)
|
169
199
|
mustache_obj = Mustache.render(i18n(File.read(template)), resume_obj.reader.hash)
|
170
|
-
File.open(dest,'w') {|f| f.write(mustache_obj) }
|
171
|
-
|
200
|
+
File.open(dest, 'w') { |f| f.write(mustache_obj) }
|
201
|
+
"\nGenerated files present at #{dest}".green
|
172
202
|
end
|
173
|
-
|
174
203
|
end
|
175
|
-
|
176
204
|
end
|
177
205
|
|
178
206
|
JsonResumeCLI.start(ARGV)
|
data/json_resume.gemspec
CHANGED
@@ -4,28 +4,27 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
4
|
require 'json_resume/version'
|
5
5
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
|
-
spec.name =
|
7
|
+
spec.name = 'json_resume'
|
8
8
|
spec.version = JsonResume::VERSION
|
9
|
-
spec.authors = [
|
10
|
-
spec.email = [
|
11
|
-
spec.description =
|
12
|
-
spec.summary =
|
13
|
-
spec.homepage =
|
14
|
-
spec.license =
|
9
|
+
spec.authors = ['Prateek Agarwal']
|
10
|
+
spec.email = ['prat0318@gmail.com']
|
11
|
+
spec.description = 'json_resume creates pretty resume formats from a .json input file. Currently, it can convert to html, tex, markdown and pdf. Customizing the templates to your own needs is also super easy.'
|
12
|
+
spec.summary = 'Generates pretty resume formats out of json input file'
|
13
|
+
spec.homepage = 'http://github.com/prat0318/json_resume'
|
14
|
+
spec.license = 'MIT'
|
15
15
|
|
16
|
-
spec.files = `git ls-files`.split(
|
17
|
-
spec.executables = [
|
18
|
-
spec.test_files = spec.files.grep(
|
19
|
-
spec.require_paths = [
|
16
|
+
spec.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
|
17
|
+
spec.executables = ['json_resume']
|
18
|
+
spec.test_files = spec.files.grep(/^(test|spec|features)/)
|
19
|
+
spec.require_paths = ['lib']
|
20
20
|
|
21
|
-
spec.add_development_dependency
|
22
|
-
spec.add_development_dependency
|
23
|
-
|
24
|
-
spec.add_dependency "i18n"
|
25
|
-
spec.add_dependency "mustache"
|
26
|
-
spec.add_dependency "pdfkit"
|
27
|
-
spec.add_dependency "rest-client"
|
28
|
-
spec.add_dependency "thor"
|
29
|
-
spec.add_dependency "wkhtmltopdf-binary"
|
21
|
+
spec.add_development_dependency 'bundler', '~> 1.3'
|
22
|
+
spec.add_development_dependency 'rake'
|
30
23
|
|
24
|
+
spec.add_dependency 'i18n'
|
25
|
+
spec.add_dependency 'mustache'
|
26
|
+
spec.add_dependency 'pdfkit'
|
27
|
+
spec.add_dependency 'rest-client'
|
28
|
+
spec.add_dependency 'thor'
|
29
|
+
spec.add_dependency 'wkhtmltopdf-binary'
|
31
30
|
end
|