multiformat-cv2 0.0.6

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: ea0b2f804d7fb2f5343f838661479add46a24a796fb87bff6ca464233bf9d88a
4
+ data.tar.gz: 469da0d9732299829d39f1837767cbf27eab1af019ea826a62d5d24139297f27
5
+ SHA512:
6
+ metadata.gz: 5ea427348ba5d91c7458e2edbdcb7a0e847cf5d57880ee35706726dee23321fda0d87e783057ab6c5960b11e5d4ced7bcb19dc18affe726ee4c15841f3b9ae8b
7
+ data.tar.gz: 9d4c3f21ca9cd0977eaa23cc88f290523f35aef2b1a6f172e9b996671d0da9960d7342c57d602418ea3c7c1c705f8ac98b66f33b27cb41810ddb831861248716
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2004-2019 David Heinemeier Hansson
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,34 @@
1
+ # Multiformat CV
2
+
3
+ Multi-format CV generator from YAML files and ERB templates.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ $ gem install multiformat-cv
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ Taking this repository's `sample` directory as a starting point, we can
14
+ generate the CV as follows:
15
+
16
+ ```bash
17
+ $ tree
18
+ .
19
+ ├── data
20
+ │   ├── contact.yml
21
+ │   ├── jobs.yml
22
+ │   └── personal.yml
23
+ └── onepager
24
+ ├── cv.css
25
+ └── cv.html.erb
26
+
27
+ 2 directories, 5 files
28
+ $ multiformatcv -d sample/data -s sample/onepager -o sample/onepager/cv.html
29
+ $ open sample/onepager/cv.html
30
+ ```
31
+
32
+ Which, after being printed from the browser, would look something like this:
33
+
34
+ ![Printed CV](sample/onepager/images/cv.png)
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "multiformatcv"
5
+ require "mercenary"
6
+
7
+ Mercenary.program(:multiformatcv) do |p|
8
+ p.version MultiformatCV::VERSION
9
+ p.description "Generate your CV in different formats"
10
+ p.syntax "multiformatcv <format> [-d './data'] [-t <directory>] [-o <file>]"
11
+
12
+ p.option "format", "-f FORMAT", "--format FORMAT", "Output format", String
13
+ p.option "data_dir", "-d DIR", "--data DIR", "YAML data files directory", String
14
+ p.option "templates", "-s DIR", "--templates DIR", "Templates directory, MUST contain cv.<format>.erb file", String
15
+ p.option "output", "-o FILE", "--outpu FILEt", "Output where to write result, defaults to STDOUT", String
16
+
17
+ p.action do |args, options|
18
+ MultiformatCV::generate(options)
19
+ end
20
+ end
@@ -0,0 +1,60 @@
1
+ require 'yaml'
2
+ require 'erubi'
3
+
4
+ module MultiformatCV
5
+
6
+ # YAML files that will be read from the specified directory
7
+ YML_FILES = %w( contact jobs personal )
8
+
9
+ # Parse yaml files located at data directory
10
+ #
11
+ # @param [Hash] opts Options to specify format and templates source
12
+ # @option opts [String] 'data_dir' Directory where the YAML files are located.
13
+ # @option opts [Symbol] 'format' One of [ :html, :tex ]
14
+ # @option opts [Symbol] 'output' Output file
15
+ # @option opts [String] 'templates' Directory where templates are located,
16
+ # expected template files are `cv.#{ format }.erb`
17
+ #
18
+ # @return [MultiformatCV::Resume] Resume with parsed data
19
+ # @see https://www.rubydoc.info/gems/erubi/1.8.0 Erubi documentation
20
+ # @see Erubi::Engine
21
+
22
+ def self.generate(opts = {})
23
+ opts['format'] ||= 'html'
24
+ opts['data_dir'] ||= 'data'
25
+ opts['templates'] ||= default_template_path
26
+ opts['output'] ||= nil
27
+
28
+ template = File.read("#{ opts['templates'] }/cv.#{ opts['format'] }.erb")
29
+ resume = Resume.new
30
+ yml = nil
31
+
32
+ YML_FILES.each do |f|
33
+ yml = YAML.load_file("#{ opts['data_dir'] }/#{ f }.yml")
34
+ if yml then
35
+ resume.send("add_#{ f }", yml[f])
36
+ end
37
+ end
38
+
39
+ resume.rendered = eval Erubi::Engine.new(template).src
40
+
41
+ if opts['output'] then
42
+ File.open(opts['output'], 'w') { |f| f.write(resume.rendered) }
43
+ end
44
+
45
+ resume
46
+ end
47
+
48
+ private
49
+
50
+ def self.default_template_path
51
+ File.expand_path('../../sample/onepager', __FILE__)
52
+ end
53
+ end
54
+
55
+ require 'multiformatcv/contact'
56
+ require 'multiformatcv/job'
57
+ require 'multiformatcv/personal'
58
+ require 'multiformatcv/project'
59
+ require 'multiformatcv/resume'
60
+ require 'multiformatcv/version'
@@ -0,0 +1,32 @@
1
+ class MultiformatCV::Contact
2
+ attr_accessor :name,
3
+ :title,
4
+ :phone,
5
+ :email
6
+
7
+ # Hash of links
8
+ #
9
+ # == Example:
10
+ # links = { github: 'https://www.github.com/john.doe/personal-dashboard' }
11
+ attr_accessor :links
12
+
13
+ # Create Contact instance
14
+ #
15
+ # == Example:
16
+ # contact = MultiformatCV::Contact.new(title: 'Accountant', name: 'John Doe')
17
+ #
18
+ # @param [Hash] h Instance initializer; keys *MUST* be strings
19
+ # @option h [String] 'name'
20
+ # @option h [String] 'title'
21
+ # @option h [String] 'email'
22
+ # @option h [String] 'phone'
23
+ # @option h [Hash<String, String>] 'links'
24
+
25
+ def initialize(h = {})
26
+ @name = h['name']
27
+ @title = h['title']
28
+ @email = h['email']
29
+ @phone = h['phone']
30
+ @links = h['links']
31
+ end
32
+ end
@@ -0,0 +1,42 @@
1
+ class MultiformatCV::Job
2
+ attr_accessor :position,
3
+ :company,
4
+ :start_date,
5
+ :end_date,
6
+ :summary
7
+
8
+ # List of projects that you worked on during this job
9
+ # @return [Array<MultiformatCV::Project>]
10
+ attr_accessor :projects
11
+
12
+ # Create Job instance
13
+ #
14
+ # == Example:
15
+ # job = MultiformatCV::Job.new(position: 'Accountant', company: 'Accountants Inc.')
16
+ #
17
+ # @param [Hash] h Instance initializer; keys *MUST* be strings
18
+ # @option h [String] 'position'
19
+ # @option h [String] 'company'
20
+ # @option h [String] 'start_date'
21
+ # @option h [String] 'end_date'
22
+ # @option h [String] 'summary'
23
+ # @option h [Array<Hash>] 'projects' List of hashes that will be used to
24
+ # initialize new MultiformatCV::Porject entries
25
+ #
26
+ # @see MultiformatCV::Project
27
+
28
+ def initialize(h = {})
29
+ @position = h['position']
30
+ @company = h['company']
31
+ @start_date = h['start_date']
32
+ @end_date = h['end_date']
33
+ @summary = h['summary']
34
+ @projects = []
35
+
36
+ if h['projects']
37
+ h['projects'].each do |p|
38
+ @projects << MultiformatCV::Project.new(p)
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,26 @@
1
+ class MultiformatCV::Personal
2
+ attr_accessor :summary
3
+
4
+ # List of personal projects
5
+ # @return [Array<MultiformatCV::Project>]
6
+ attr_accessor :projects
7
+
8
+ # Create Personal information instance
9
+ #
10
+ # == Example:
11
+ # personal = MultiformatCV::Personal.new(summary: 'Volunteer at...', projects: [])
12
+ #
13
+ # @param [Hash] h Instance initializer; keys *MUST* be strings
14
+ # @option h [String] 'summary'
15
+ # @option h [Array<Hash>] 'projects' List of hashes that will be used to
16
+ # initialize new MultiformatCV::Porject entries
17
+ #
18
+ # @see MultiformatCV::Project
19
+
20
+ def initialize(h = {})
21
+ @summary = h['summary']
22
+ @projects = []
23
+
24
+ h['projects'].each { |p| @projects << MultiformatCV::Project.new(p) }
25
+ end
26
+ end
@@ -0,0 +1,60 @@
1
+ class MultiformatCV::Project
2
+ attr_accessor :name,
3
+ :position,
4
+ :summary,
5
+ :tasks,
6
+ :skills
7
+
8
+ # Repository URL for the project
9
+ attr_accessor :repo
10
+
11
+ # Page or site URL for the project
12
+ attr_accessor :url
13
+
14
+ # Create Project instance
15
+ #
16
+ # == Example:
17
+ # project = MultiformatCV::Project.new(name: 'Life Solver (TM)', summary: '...', ...)
18
+ #
19
+ # @param [Hash] h Instance initializer; keys *MUST* be strings
20
+ # @option h [String] 'name'
21
+ # @option h [String] 'position'
22
+ # @option h [String] 'start_date'
23
+ # @option h [String] 'end_date'
24
+ # @option h [String] 'repo' Repository URL
25
+ # @option h [String] 'url' URL for the project
26
+ # @option h [String] 'summary' Project description, goals, etc.
27
+ # @option h [Array<String>] 'tasks' Tasks done for the project
28
+ # @option h [Array<String>] 'skills' skills used in the project
29
+
30
+ def initialize(h = {})
31
+ @name = h['name']
32
+ @position = h['position']
33
+ @start_date = h['start_date']
34
+ @end_date = h['end_date']
35
+ @repo = h['repo']
36
+ @summary = h['summary']
37
+ @url = h['url']
38
+ @tasks = []
39
+ @skills = []
40
+
41
+ h['tasks'].each { |t| @tasks << t } if h['tasks']
42
+ h['skills'].each { |t| @skills << t } if h['skills']
43
+ end
44
+
45
+ # @return [DateTime] Date or nil
46
+ def end_date
47
+ if @end_date and @end_date != ''
48
+ return DateTime.parse(@end_date)
49
+ end
50
+ return nil
51
+ end
52
+
53
+ # @return [DateTime] Date or nil
54
+ def start_date
55
+ if @start_date and @start_date != ''
56
+ return DateTime.parse(@start_date)
57
+ end
58
+ return nil
59
+ end
60
+ end
@@ -0,0 +1,127 @@
1
+ require 'date'
2
+
3
+ class MultiformatCV::Resume
4
+ # Contact information
5
+ # @return [MultiformatCV::Contact]
6
+ attr_accessor :contact
7
+
8
+ # List of jobs
9
+ # @return [Array<MultiformatCV::Job>]
10
+ attr_accessor :jobs
11
+
12
+ # List of skills
13
+ # @key skill name
14
+ # @value time duration in months
15
+ # @return [Hash]
16
+ attr_accessor :skills
17
+
18
+ # Personal accomplishments and projects
19
+ # @return [MultiformatCV::Personal]
20
+ attr_accessor :personal
21
+
22
+ # Rendered templates with CV data
23
+ # @return [String]
24
+ attr_accessor :rendered
25
+
26
+ # Initialize Resume
27
+ #
28
+ # @param [Hash] h Options
29
+ # @option h [Array<MultiformatCV::Contact>] 'contact' Contact information
30
+ # @option h [Array<MultiformatCV::Job>] 'jobs' Jobs list
31
+ # @option h [Array<MultiformatCV::Personal>] 'personal' Personal information
32
+
33
+ def initialize(h = {})
34
+ @contact = MultiformatCV::Contact.new(h['contact'] || []) if h['contact']
35
+ @jobs = []
36
+ @skills = {}
37
+ @personal = MultiformatCV::Personal.new(h['personal'] || []) if h['personal']
38
+
39
+ h['jobs'].each { |j| @jobs << MultiformatCV::Job.new(j) } if h['jobs']
40
+
41
+ estimate_skills_experience_duration! if jobs.length > 0
42
+ end
43
+
44
+ # Set contact information
45
+ # @param [Hash] h Hash used to initialize new MultiformatCV::Contact
46
+ # @see MultiformatCV::Contact
47
+
48
+ def add_contact(h = {})
49
+ @contact = MultiformatCV::Contact.new(h)
50
+ end
51
+
52
+ # Add list of job entries to @jobs list
53
+ #
54
+ # @param [Array<Hash>] arr List of hashes that will be used to initialize new
55
+ # MultiformatCV::Job entries
56
+ #
57
+ # @see MultiformatCV::Job
58
+
59
+ def add_jobs(arr = [])
60
+ arr.each { |j| @jobs << MultiformatCV::Job.new(j) }
61
+ estimate_skills_experience_duration!
62
+ end
63
+
64
+ # Set personal information
65
+ # @param [Hash] h Hash used to initialize new MultiformatCV::Personal
66
+ # @see MultiformatCV::Personal
67
+
68
+ def add_personal(h = {})
69
+ @personal = MultiformatCV::Personal.new(h)
70
+ end
71
+
72
+ private
73
+
74
+ # A skill can be shared among projects, so we need to **NOT** count the
75
+ # same skill more than once if it appears in more than one.
76
+ #
77
+ # We do a naive calculation of _assuming_ if a skill has the same
78
+ # duration in more than one project, then we count it only once.
79
+ #
80
+ # **NOTE**: the way dates are parsed, if they don't specify the day,
81
+ # start of the month assumed; if they don't specify month, start of the
82
+ # year is assumed.
83
+ #
84
+ # For example, this approach will give approximate results when
85
+ # `skill1` was used from January 'til March in `project1` and from
86
+ # June 'til August in `project2`, giving a total of 4 months
87
+ # assuming dates are:
88
+ #
89
+ # * 2020-01-01 -> 2020-03-01: 2 months
90
+ # * 2020-06-01 -> 2020-08-01: 2 months
91
+
92
+ def estimate_skills_experience_duration!
93
+ jobs.each do |job|
94
+ job_skills = {}
95
+ default_start_date = job.start_date
96
+ default_end_date = job.end_date || Time.now # present/current job
97
+
98
+ job.projects.each do |proj|
99
+ start_date = proj.start_date || default_start_date
100
+ end_date = proj.end_date || default_end_date
101
+
102
+ proj.skills.each do |s|
103
+ job_skills[s] ||= []
104
+ job_skills[s] << diff_in_months(start_date.to_time, end_date.to_time)
105
+ end
106
+ end
107
+
108
+ # we assume that if the same skill has the same duration twice for the
109
+ # same job, the projects were developed in parallel so we count the skill
110
+ # only once
111
+ job_skills.each { |s, arr| job_skills[s] = arr.uniq.sum }
112
+ skills.merge!(job_skills) { |k, oldval, newval| oldval + newval }
113
+ end
114
+
115
+ skills
116
+ end
117
+
118
+ # Generic (30-day) month duration in seconds
119
+ ONE_MONTH = 3600 * 24 * 30
120
+
121
+ # @param [Time] t1
122
+ # @param [Time] t2
123
+ # @return [Integer] Difference in months between dates
124
+ def diff_in_months(t1, t2)
125
+ ((t1 - t2) / ONE_MONTH).abs.round
126
+ end
127
+ end
@@ -0,0 +1,66 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
5
+ <title><%= "#{ resume.contact.name } - #{ resume.contact.title }" %></title>
6
+ <style>
7
+ html {
8
+ font: normal 16px/20px sans-serif, serif;
9
+ max-width: 90%;
10
+ margin: 2rem auto;
11
+ }
12
+ h1 { font-size: 1.6rem; line-height: 1.8rem; color: #000; }
13
+ h2 { font-size: 1.5rem; line-height: 1.7rem; color: #222; }
14
+ h3 { font-size: 1.4rem; line-height: 1.6rem; color: #444; }
15
+ h4 { font-size: 1.3rem; line-height: 1.5rem; color: #555; }
16
+ h5 { font-size: 1.2rem; line-height: 1.4rem; color: #666; }
17
+ h6 { font-size: 1.1rem; line-height: 1.3rem; color: #777; }
18
+ .text-right { text-align: right; }
19
+
20
+ .job {
21
+ border-bottom: 1px solid #666;
22
+ }
23
+ .project {}
24
+ </style>
25
+ </head>
26
+ <body>
27
+ <header>
28
+ <h1><%= "#{ resume.contact.name } - #{ resume.contact.title }" %></h1>
29
+ <div class="text-right">
30
+ <a href="mailto:<%= resume.contact.email %>" class="email"><%= resume.contact.email %></a><br>
31
+ <a href="tel:<%= resume.contact.phone %>" class="phone"><%= resume.contact.phone %></a>
32
+ </div>
33
+ </header>
34
+
35
+ <section id="jobs">
36
+ <h2>Work Experience</h2>
37
+ <% resume.jobs.each do |job| %>
38
+ <article class="job">
39
+ <header>
40
+ <h3><%= "#{ job.position } &mdash; #{ job.company }" %></h3>
41
+ </header>
42
+ <p><%= job.summary.chomp %></p>
43
+ <% job.projects.each do |project| %>
44
+ <article class="project">
45
+ <h4><%= project.name %></h4>
46
+
47
+ <h5>Skills</h5>
48
+ <ul class="skills">
49
+ <% project.skills.each do |tech| %>
50
+ <li><%= tech %></li>
51
+ <% end %>
52
+ </ul>
53
+
54
+ <h5>Tasks</h5>
55
+ <ul class="tasks">
56
+ <% project.tasks.each do |task| %>
57
+ <li><%= task %></li>
58
+ <% end %>
59
+ </ul>
60
+ </article>
61
+ <% end %>
62
+ </article>
63
+ <% end %>
64
+ </section>
65
+ </body>
66
+ </html>
@@ -0,0 +1,66 @@
1
+ \documentclass{article}
2
+
3
+ \title{<%= resume.contact.name %>}
4
+ \author{<%= resume.contact.name %>}
5
+
6
+ \begin{document}
7
+
8
+ \maketitle
9
+
10
+ \section{\centerline{Proffesional Experience}}
11
+
12
+ \vspace{8pt}
13
+
14
+ <% resume.jobs.each do |job| %>
15
+
16
+ \subsection{<%= job.company %> -- <%= job.position %>}
17
+ \hfill <%= job.start_date %> -- <%= job.end_date or 'present' %>
18
+
19
+ <%- if job.summary %><%= job.summary %><% end -%>
20
+
21
+ <% job.projects.each do |project| %>
22
+ \subsubsection{<%= project.name %>}
23
+
24
+ <%- if project.summary %><%= project.summary %><% end -%>
25
+
26
+
27
+ \noindent Skills
28
+
29
+ \begin{itemize}
30
+ <% project.skills.each do |tech| %>
31
+ \item <%= tech %>
32
+ <% end %>
33
+ \end{itemize}
34
+
35
+ \noindent Tasks
36
+
37
+ \begin{itemize}
38
+ <% project.tasks.each do |task| %>
39
+ \item <%= task %>
40
+ <% end %>
41
+ \end{itemize}
42
+ <% end %>
43
+ <% end %>
44
+
45
+ \section{\centerline{Personal Projects}}
46
+
47
+ \vspace{8pt}
48
+
49
+ <%- if resume.personal and resume.personal.summary %>
50
+ <%= resume.personal.summary %>
51
+ <% end -%>
52
+
53
+ <% resume.personal.projects.each do |project| %>
54
+ \subsubsection{<%= project.name %>}
55
+
56
+ <%- if project.summary %><%= project.summary %><% end -%>
57
+
58
+ \noindent Skills
59
+
60
+ \begin{itemize}
61
+ <% project.skills.each do |tech| %>
62
+ \item <%= tech %>
63
+ <% end %>
64
+ \end{itemize}
65
+ <% end %>
66
+ \end{document}
@@ -0,0 +1,4 @@
1
+ module MultiformatCV
2
+ # Gem version
3
+ VERSION = '0.0.6'
4
+ end
metadata ADDED
@@ -0,0 +1,83 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: multiformat-cv2
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.6
5
+ platform: ruby
6
+ authors:
7
+ - juankman94
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-08-28 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: erubi
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.8'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.8'
27
+ - !ruby/object:Gem::Dependency
28
+ name: mercenary
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 0.3.3
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 0.3.3
41
+ description: Multi-format CV generator from YAML files
42
+ email: juan.carlos@hey.com
43
+ executables:
44
+ - multiformatcv
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - MIT-LICENSE
49
+ - README.md
50
+ - bin/multiformatcv
51
+ - lib/multiformatcv.rb
52
+ - lib/multiformatcv/contact.rb
53
+ - lib/multiformatcv/job.rb
54
+ - lib/multiformatcv/personal.rb
55
+ - lib/multiformatcv/project.rb
56
+ - lib/multiformatcv/resume.rb
57
+ - lib/multiformatcv/templates/cv.html.erb
58
+ - lib/multiformatcv/templates/cv.tex.erb
59
+ - lib/multiformatcv/version.rb
60
+ homepage: https://www.gitlab.com/juankman94/multiformat-cv
61
+ licenses:
62
+ - MIT
63
+ metadata: {}
64
+ post_install_message:
65
+ rdoc_options: []
66
+ require_paths:
67
+ - lib
68
+ required_ruby_version: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: '0'
73
+ required_rubygems_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ requirements: []
79
+ rubygems_version: 3.1.2
80
+ signing_key:
81
+ specification_version: 4
82
+ summary: Generate your CV in different formats
83
+ test_files: []