json_resume 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Binary file
@@ -0,0 +1,23 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'json_resume/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "json_resume"
8
+ spec.version = JsonResume::VERSION
9
+ spec.authors = ["Prateek Agarwal"]
10
+ spec.email = ["prat0318@gmail.com"]
11
+ spec.description = %q{json_resume creates pretty resume formats from a .json input file. Currently, it can cpnvert to html, tex, markdown and pdf. Customizing the template to your own need is super easy. You just need to change the mustache files for any of these formats.}
12
+ spec.summary = %q{Generates pretty resume formats out of json input file}
13
+ spec.homepage = "http://github.com/prat0318/json_resume"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = ["json_resume"]
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rake"
23
+ end
@@ -0,0 +1,6 @@
1
+ require_relative "json_resume/version"
2
+ require_relative "json_resume/json_resume"
3
+
4
+ module JsonResume
5
+ # Your code goes here...
6
+ end
@@ -0,0 +1,130 @@
1
+ #Hack to generalise call empty? on
2
+ #objects, arrays and hashes
3
+ class Object
4
+ def empty?
5
+ false
6
+ end
7
+ end
8
+
9
+ module JsonResume
10
+ class Formatter
11
+ attr_reader :hash
12
+
13
+ def initialize(hash)
14
+ @hash = hash
15
+
16
+ #recursively defined proc
17
+ @hash_proc = Proc.new 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["linkedin_url"] = "http://linkedin.com/in/" + @hash["linkedin_id"] if @hash["linkedin_id"]
26
+ @hash["github_url"] = "http://github.com/" + @hash["github_id"] if @hash["github_id"]
27
+ end
28
+
29
+ def add_last_marker_on_stars
30
+ return if @hash['bio_data']['stars'].nil?
31
+ @hash["bio_data"]["stars"] = {
32
+ "items" => @hash["bio_data"]["stars"].map{ |i| { "name" => i } }
33
+ }
34
+ @hash["bio_data"]["stars"]["items"][-1]["last"] = true
35
+ end
36
+
37
+ def add_last_marker_on_skills
38
+ return if @hash['bio_data']['skills'].nil?
39
+ @hash['bio_data']['skills']['details'].each do |item|
40
+ item['items'].map!{|x| {'name'=>x} }
41
+ item['items'][-1]['last'] = true
42
+ end
43
+ end
44
+
45
+ def add_last_marker_on_tools
46
+ return if @hash['bio_data']['other_projects'].nil?
47
+ @hash['bio_data']['other_projects']['items'].each do |item|
48
+ next if item['technology_used'].nil?
49
+ item['technology_used']['tools'].map!{|x| {'name' => x} }
50
+ item['technology_used']['tools'][-1]['last'] = true
51
+ end
52
+ end
53
+
54
+ def add_last_marker_on_field field_name
55
+ return if @hash['bio_data'][field_name].nil?
56
+ @hash['bio_data'][field_name]['items'].each do |item|
57
+ next if item['technology_used'].nil?
58
+ item['technology_used']['tools'].map!{|x| {'name' => x} }
59
+ item['technology_used']['tools'][-1]['last'] = true
60
+ end
61
+ end
62
+
63
+ def cleanse
64
+ @hash.delete_if &@hash_proc
65
+ self
66
+ end
67
+
68
+ def format_to_output_type
69
+ format_proc = Proc.new do |k,v|
70
+ v = k if v.nil?
71
+ v.each{|x| format_proc.call(x)} if [Hash,Array].any? {|x| v.instance_of? x}
72
+ format_string v if v.instance_of? String
73
+ end
74
+ @hash.each{|x| format_proc.call(x)}
75
+ self
76
+ end
77
+
78
+ def format_string str
79
+ raise NotImplementedError.new("format_string not impl in formatter")
80
+ end
81
+
82
+ def is_false? item
83
+ item == false || item == 'false'
84
+ end
85
+
86
+ def purge_gpa
87
+ return if @hash['bio_data']['education'].nil?
88
+ @hash["bio_data"]["education"].delete("show_gpa") if is_false?(@hash["bio_data"]["education"]["show_gpa"]) || @hash["bio_data"]["education"]["schools"].all? {|sch| sch["gpa"].nil? || sch["gpa"].empty?}
89
+ end
90
+
91
+ def add_padding(course)
92
+ unless @hash["bio_data"].nil? || @hash["bio_data"][course].nil?
93
+ course_hash = @hash["bio_data"][course]
94
+ course_hash << {} if course_hash.size % 2 == 1
95
+ @hash["bio_data"][course] = {
96
+ "rows" => course_hash.each_slice(2).to_a.map{ |i| { "columns" => i } }
97
+ }
98
+ end
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
+ ["grad_courses", "undergrad_courses"].each do |course|
121
+ add_padding(course)
122
+ end
123
+
124
+ return self
125
+ end
126
+
127
+
128
+ end
129
+ end
130
+
@@ -0,0 +1,32 @@
1
+ require_relative 'formatter'
2
+
3
+ module JsonResume
4
+ class FormatterHtml < Formatter
5
+ def format_link str
6
+ str.gsub! /\[(.*?)\]\((.*?)\)/, '<a href="\2">\1</a>'
7
+ end
8
+
9
+ def format_autolink str
10
+ str.gsub! /<<(\S*?)>>/, '<a href="\1">\1</a>'
11
+ end
12
+
13
+ def format_emphasis str
14
+ str.gsub! /_(.+?)_/, '<i>\1</i>'
15
+ str.gsub! /\*\*(.+?)\*\*/, '<b>\1</b>'
16
+ end
17
+
18
+ def format_string str
19
+ format_link str
20
+ format_autolink str
21
+ format_emphasis str
22
+ end
23
+
24
+ def format
25
+ super
26
+
27
+ return self
28
+ end
29
+
30
+ end
31
+ end
32
+
@@ -0,0 +1,45 @@
1
+ require_relative 'formatter'
2
+
3
+ module JsonResume
4
+ class FormatterLatex < Formatter
5
+
6
+ def format_link str
7
+ str.gsub! /\[(.*?)\]\((.*?)\)/, '{\color{see} \href{\2}{\1}}'
8
+ end
9
+
10
+ def format_autolink str
11
+ str.gsub! /<<(\S*?)>>/, '{\color{see} \url{\1}}'
12
+ end
13
+
14
+ def format_emphasis str
15
+ str.gsub! /_(.+?)_/, '\textit{\1}'
16
+ str.gsub! /\*\*(.+?)\*\*/, '\textbf{\1}'
17
+ end
18
+
19
+ def format_superscripts str
20
+ str.gsub! /<sup>(.*?)<\/sup>/, '$^{\1}$'
21
+ str.gsub! /<sub>(.*?)<\/sub>/, '$_{\1}$'
22
+ end
23
+
24
+ def format_symbols str
25
+ str.gsub! /%/, '\%'
26
+ str.gsub! /_/, '\_'
27
+ end
28
+
29
+ def format_string str
30
+ format_link str
31
+ format_autolink str
32
+ format_emphasis str
33
+ format_symbols str
34
+ format_superscripts str
35
+ end
36
+
37
+ def format
38
+ super
39
+
40
+ return self
41
+ end
42
+ end
43
+ end
44
+
45
+
@@ -0,0 +1,21 @@
1
+ require_relative 'formatter'
2
+
3
+ module JsonResume
4
+ class FormatterMd < Formatter
5
+ def format_autolink str
6
+ str.gsub! /<<(\S*?)>>/, '[\1](\1)'
7
+ end
8
+
9
+ def format_string str
10
+ format_autolink str
11
+ end
12
+
13
+ def format
14
+ super
15
+
16
+ return self
17
+ end
18
+
19
+ end
20
+ end
21
+
@@ -0,0 +1,19 @@
1
+ require_relative 'reader'
2
+
3
+ module JsonResume
4
+ class << self
5
+ def new(json_input, options = {})
6
+ options = options.inject({}){|memo,(k,v)| memo[k.to_sym] = v; memo}
7
+ JsonResume::Core.new(json_input, options)
8
+ end
9
+ end
10
+
11
+ class Core
12
+ attr_accessor :reader
13
+
14
+ def initialize(json_input, options)
15
+ @reader = Reader.new(json_input, options)
16
+ @reader.format!
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,35 @@
1
+ require_relative 'formatter_html'
2
+ require_relative 'formatter_latex'
3
+ require_relative 'formatter_md'
4
+ require 'json'
5
+
6
+ module JsonResume
7
+ class Reader
8
+ attr_accessor :hash
9
+
10
+ def initialize(json_input, options)
11
+ output_type = options[:output_type] || "html" #default html, others latex, md
12
+ @json_string = case json_input
13
+ when /\.json$/i then File.read(json_input)
14
+ else json_input
15
+ end
16
+ @output_type = output_type
17
+ begin
18
+ @hash = JSON.parse(@json_string)
19
+ rescue JSON::ParserError => e
20
+ raise Exception, "Either you entered a file without .json extension or JSON string is wrong: "+e.message
21
+ end
22
+ end
23
+
24
+ def format!
25
+ formatters = {
26
+ :latex => JsonResume::FormatterLatex,
27
+ :html => JsonResume::FormatterHtml,
28
+ :markdown => JsonResume::FormatterMd,
29
+ }
30
+ type = @output_type.to_sym
31
+ @hash = formatters[type].new(@hash).format.hash
32
+ end
33
+ end
34
+ end
35
+
@@ -0,0 +1,3 @@
1
+ module JsonResume
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,95 @@
1
+ require 'spec_helper'
2
+ require 'json_resume/formatter_html'
3
+ require 'json_resume/formatter'
4
+
5
+ describe "#padder" do
6
+ it 'pads a row if items are odd' do
7
+ hash = {'bio_data' => {'test' => [
8
+ {'name'=>'sub1', 'url' => 'url1'},
9
+ {'name'=>'sub2', 'url' => 'url2'},
10
+ {'name'=>'sub3', 'url' => 'url3'}
11
+ ]}
12
+ }
13
+ formatter = JsonResume::FormatterHtml.new hash
14
+ formatter.add_padding('test')
15
+ expect(formatter.hash['bio_data']['test']['rows'].size).to eq(2)
16
+ expect(formatter.hash['bio_data']['test']['rows'][-1]['columns'][-1]).to eq({})
17
+ end
18
+
19
+ it 'doesn\'t pad a row if items are even' do
20
+ subs = [
21
+ {'name'=>'sub1', 'url' => 'url1'},
22
+ {'name'=>'sub2', 'url' => 'url2'}
23
+ ]
24
+ hash = {'bio_data' => {'test' => subs}}
25
+ formatter = JsonResume::FormatterHtml.new hash
26
+ formatter.add_padding('test')
27
+ expect(formatter.hash['bio_data']['test']['rows'].size).to eq(1)
28
+ expect(formatter.hash['bio_data']['test']['rows'][0]['columns']).to eq(subs)
29
+ end
30
+
31
+ it 'ignores if data is null' do
32
+ hash = {'bio_data' => {}}
33
+ formatter = JsonResume::FormatterHtml.new hash
34
+ formatter.add_padding('test')
35
+ expect(formatter.hash['bio_data']).to eq({})
36
+ end
37
+ end
38
+
39
+ describe '#urlformatter' do
40
+ context 'when given a link for html output' do
41
+ it 'converts link to href' do
42
+ formatter = JsonResume::FormatterHtml.new({})
43
+ str = "test [Hello](http://google.com)"
44
+ formatter.format_link str
45
+ expect(str).to eq('test <a href="http://google.com">Hello</a>')
46
+ end
47
+
48
+ it 'converts autolink to url' do
49
+ formatter = JsonResume::FormatterHtml.new({})
50
+ str = "test <<http://google.com>>"
51
+ formatter.format_autolink str
52
+ expect(str).to eq('test <a href="http://google.com">http://google.com</a>')
53
+ end
54
+
55
+ it 'converts links and autolinks to url' do
56
+ formatter = JsonResume::FormatterHtml.new({})
57
+ str = "test <<http://google.com>> [Hello](http://google.com) <<http://google.com>>"
58
+ formatter.format_string str
59
+ expect(str).to eq('test <a href="http://google.com">http://google.com</a> <a href="http://google.com">Hello</a> <a href="http://google.com">http://google.com</a>')
60
+ end
61
+ end
62
+ end
63
+
64
+ describe "#emphasis_formatting" do
65
+ it 'italicizes on _text_' do
66
+ formatter = JsonResume::FormatterHtml.new({})
67
+ str = "Last word should be _italicized_"
68
+ formatter.format_emphasis str
69
+ expect(str).to eq('Last word should be <i>italicized</i>')
70
+ end
71
+
72
+ it 'bolds on **text**' do
73
+ formatter = JsonResume::FormatterHtml.new({})
74
+ str = "Last word should be **bold**"
75
+ formatter.format_emphasis str
76
+ expect(str).to eq('Last word should be <b>bold</b>')
77
+ end
78
+
79
+ it 'italicizes and bolds if given both' do
80
+ formatter = JsonResume::FormatterHtml.new({})
81
+ str = "Last word should _be **bold and italicized**_"
82
+ formatter.format_emphasis str
83
+ expect(str).to eq('Last word should <i>be <b>bold and italicized</b></i>')
84
+ end
85
+ end
86
+
87
+ describe "#format" do
88
+ it 'calls parent format method' do
89
+ formatter = JsonResume::FormatterHtml.new({'bio_data' => {}})
90
+ expect(formatter).to receive(:cleanse).and_return(nil)
91
+ formatter.format
92
+ end
93
+ end
94
+
95
+
@@ -0,0 +1,51 @@
1
+ require 'spec_helper'
2
+ require 'json_resume/formatter_latex'
3
+
4
+ describe '#urlformatter' do
5
+ context 'when given a link for latex output' do
6
+ it 'converts link to href' do
7
+ formatter = JsonResume::FormatterLatex.new({})
8
+ str = "test [Hello](http://google.com)"
9
+ formatter.format_link str
10
+ expect(str).to eq('test {\color{see} \href{http://google.com}{Hello}}')
11
+ end
12
+
13
+ it 'converts autolink to url' do
14
+ formatter = JsonResume::FormatterLatex.new({})
15
+ str = "test <<http://google.com>>"
16
+ formatter.format_autolink str
17
+ expect(str).to eq('test {\color{see} \url{http://google.com}}')
18
+ end
19
+
20
+ it 'converts links and autolinks to url' do
21
+ formatter = JsonResume::FormatterLatex.new({})
22
+ str = "test <<http://google.com>> [Hello](http://google.com) <<http://google.com>>"
23
+ formatter.format_string str
24
+ expect(str).to eq('test {\color{see} \url{http://google.com}} {\color{see} \href{http://google.com}{Hello}} {\color{see} \url{http://google.com}}')
25
+ end
26
+ end
27
+ end
28
+
29
+ describe "#emphasis_formatting" do
30
+ it 'italicizes on _text_' do
31
+ formatter = JsonResume::FormatterLatex.new({})
32
+ str = "Last word should be _italicized_"
33
+ formatter.format_emphasis str
34
+ expect(str).to eq('Last word should be \textit{italicized}')
35
+ end
36
+
37
+ it 'bolds on **text**' do
38
+ formatter = JsonResume::FormatterLatex.new({})
39
+ str = "Last word should be **bold**"
40
+ formatter.format_emphasis str
41
+ expect(str).to eq('Last word should be \textbf{bold}')
42
+ end
43
+
44
+ it 'italicizes and bolds if given both' do
45
+ formatter = JsonResume::FormatterLatex.new({})
46
+ str = "Last word should _be **bold and italicized**_"
47
+ formatter.format_emphasis str
48
+ expect(str).to eq('Last word should \textit{be \textbf{bold and italicized}}')
49
+ end
50
+ end
51
+