yaml-cv 0.1.0
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 +7 -0
- data/Gemfile +9 -0
- data/LICENSE +21 -0
- data/README.md +43 -0
- data/bin/yaml-cv +114 -0
- data/lib/assets/cv.mustache +169 -0
- data/lib/assets/icons/email.svg +1 -0
- data/lib/assets/icons/github.svg +1 -0
- data/lib/assets/icons/gitlab.svg +1 -0
- data/lib/assets/icons/linkedin.svg +1 -0
- data/lib/assets/icons/location.svg +1 -0
- data/lib/assets/icons/phone.svg +1 -0
- data/lib/assets/icons/skype.svg +1 -0
- data/lib/assets/icons/website.svg +1 -0
- data/lib/assets/style.css +157 -0
- data/lib/yaml-cv.rb +146 -0
- metadata +102 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 417f601294b5c11b34efa0e476da2ebdc93a44147a734f10f4883e003e00ccfa
|
4
|
+
data.tar.gz: 29535ef8d332911a517962ca62e042d011fd6f5905aacb1a4a2f028cdf6cb420
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 16224a46cc10eb7710fe9aa03ad1ef7395f6c6e8dcb4c5f7f7013d3ba9afdca5255567e8403d68d6ce40e0df516d7fab29892bf8a1cf12ffebd5cb04f94a7fb6
|
7
|
+
data.tar.gz: 28522fc7481a06ef7c614df6cf4ae29c75760b36403566e51290db7a451556572c7e3f6f0492e21e8e479e3e4d1f804249755b6c77b504445db47db0f44ee1ee
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2019 Greg Mantaos
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
# yaml-cv
|
2
|
+
|
3
|
+
Static CV generator from a YAML file, in HTML or PDF format.
|
4
|
+
|
5
|
+
<h1 align="center">
|
6
|
+
<img src="examples/demo.png">
|
7
|
+
</h1>
|
8
|
+
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
```shell
|
12
|
+
$ gem install yaml-cv
|
13
|
+
```
|
14
|
+
|
15
|
+
## Usage
|
16
|
+
|
17
|
+
By default, the output will be printed to stdout in HTML format.
|
18
|
+
|
19
|
+
```shell
|
20
|
+
$ yaml-cv my_cv.yml
|
21
|
+
<html>
|
22
|
+
<head>
|
23
|
+
<title> Doe John - Public Figure </title>
|
24
|
+
|
25
|
+
<style>
|
26
|
+
...
|
27
|
+
```
|
28
|
+
|
29
|
+
To save to a file, use one or both of the `--html` and `--pdf` arguments, while specifying the output file to write to.
|
30
|
+
|
31
|
+
```shell
|
32
|
+
$ yaml-cv my_cv.yml --html my_cv.html
|
33
|
+
```
|
34
|
+
|
35
|
+
```shell
|
36
|
+
$ yaml-cv my_cv.yml --pdf my_cv.pdf
|
37
|
+
```
|
38
|
+
|
39
|
+
The `--watch` option can also be used to watch the input file for changes and automatically regenerate the output.
|
40
|
+
|
41
|
+
```shell
|
42
|
+
$ yaml-cv my_cv.yml --html my_cv.html --watch
|
43
|
+
```
|
data/bin/yaml-cv
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$:.unshift File.dirname(__FILE__)
|
4
|
+
$:.unshift File.join(File.dirname(__FILE__), "../lib")
|
5
|
+
|
6
|
+
require "optparse"
|
7
|
+
require "ostruct"
|
8
|
+
require "yaml"
|
9
|
+
require "yaml-cv"
|
10
|
+
require "filewatcher"
|
11
|
+
|
12
|
+
class Options
|
13
|
+
|
14
|
+
def self.initialize
|
15
|
+
|
16
|
+
@@options = OpenStruct.new
|
17
|
+
@@options.file_name = ""
|
18
|
+
@@options.watch = false
|
19
|
+
@@options.html_file = ""
|
20
|
+
@@options.pdf_file = ""
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.parser
|
24
|
+
|
25
|
+
OptionParser.new do |opts|
|
26
|
+
|
27
|
+
opts.banner = "Usage: yaml-cv <path to yml file> [options]"
|
28
|
+
|
29
|
+
opts.on("-w", "--watch", "Watch the input file for changes and automatically regenerate the CV.") do |watch|
|
30
|
+
|
31
|
+
@@options.watch = watch
|
32
|
+
end
|
33
|
+
|
34
|
+
opts.on("--html [HTML_FILE]", "The output path to the generated HTML file.") do |html|
|
35
|
+
|
36
|
+
@@options.html_file = html
|
37
|
+
end
|
38
|
+
|
39
|
+
opts.on("--pdf [PDF_FILE]", "The output path to the generated PDF file.") do |pdf|
|
40
|
+
|
41
|
+
@@options.pdf_file = pdf
|
42
|
+
end
|
43
|
+
|
44
|
+
opts.on_tail("-h", "--help", "Print this message and exit.") do
|
45
|
+
|
46
|
+
puts opts
|
47
|
+
exit
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.parse(args)
|
55
|
+
|
56
|
+
initialize
|
57
|
+
|
58
|
+
parser.parse!(args)
|
59
|
+
|
60
|
+
@@options.file_name = ARGV.pop
|
61
|
+
|
62
|
+
raise "Please specify an input yml file." unless @@options.file_name
|
63
|
+
end
|
64
|
+
|
65
|
+
def self.options
|
66
|
+
|
67
|
+
@@options
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
def generate()
|
73
|
+
|
74
|
+
cv = CV.new Options.options.file_name
|
75
|
+
|
76
|
+
if !Options.options.html_file.to_s.empty?
|
77
|
+
|
78
|
+
cv.write_html Options.options.html_file
|
79
|
+
end
|
80
|
+
|
81
|
+
if !Options.options.pdf_file.to_s.empty?
|
82
|
+
|
83
|
+
cv.write_pdf Options.options.pdf_file
|
84
|
+
end
|
85
|
+
|
86
|
+
if Options.options.html_file.to_s.empty? and Options.options.pdf_file.to_s.empty?
|
87
|
+
|
88
|
+
puts cv.render
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
Options.parse(ARGV)
|
93
|
+
|
94
|
+
generate
|
95
|
+
|
96
|
+
if Options.options.watch
|
97
|
+
|
98
|
+
watchlist = [
|
99
|
+
Options.options.file_name,
|
100
|
+
File.join(File.dirname(__FILE__), "../lib/**/*")
|
101
|
+
]
|
102
|
+
|
103
|
+
Filewatcher.new(watchlist, spinner: true).watch do |filename, event|
|
104
|
+
|
105
|
+
puts "Input file updated."
|
106
|
+
|
107
|
+
begin
|
108
|
+
generate
|
109
|
+
rescue StandardError => e
|
110
|
+
puts e.message
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
@@ -0,0 +1,169 @@
|
|
1
|
+
<html>
|
2
|
+
<head>
|
3
|
+
<meta charset="UTF-8">
|
4
|
+
<title> {{ full_name }} - {{{ details.title }}} </title>
|
5
|
+
|
6
|
+
<style>
|
7
|
+
{{ css }}
|
8
|
+
</style>
|
9
|
+
</head>
|
10
|
+
<body>
|
11
|
+
|
12
|
+
<div class="cv-wrapper">
|
13
|
+
|
14
|
+
<div class="header">
|
15
|
+
<table>
|
16
|
+
<tr>
|
17
|
+
<td width="100%">
|
18
|
+
<p class="name">
|
19
|
+
<span class="cyan">{{ details.last_name }}</span>
|
20
|
+
<span>{{ details.first_name }}</span>
|
21
|
+
</p>
|
22
|
+
</td>
|
23
|
+
<td class="content-wrapper">
|
24
|
+
<ul class="contact-list">
|
25
|
+
{{# contact_padding}}
|
26
|
+
<li class="contact-wrapper"> </li>
|
27
|
+
{{/ contact_padding}}
|
28
|
+
{{# contact}}
|
29
|
+
<li class="contact-wrapper">
|
30
|
+
<a {{# url}}href="{{ url }}"{{/ url}} target="_blank">{{{icon}}}{{ text }}</a>
|
31
|
+
</li>
|
32
|
+
{{/ contact}}
|
33
|
+
</ul>
|
34
|
+
</td>
|
35
|
+
</tr>
|
36
|
+
</table>
|
37
|
+
<hr>
|
38
|
+
<p class="title">{{{ details.title }}}</p>
|
39
|
+
</div>
|
40
|
+
|
41
|
+
<table>
|
42
|
+
|
43
|
+
<!--
|
44
|
+
____________ ___________ _____ _ _____
|
45
|
+
| ___ \ ___ \ _ | ___|_ _| | | ___|
|
46
|
+
| |_/ / |_/ / | | | |_ | | | | | |__
|
47
|
+
| __/| /| | | | _| | | | | | __|
|
48
|
+
| | | |\ \\ \_/ / | _| |_| |____| |___
|
49
|
+
\_| \_| \_|\___/\_| \___/\_____/\____/
|
50
|
+
-->
|
51
|
+
<tr class="section">
|
52
|
+
<td class="title-wrapper">
|
53
|
+
<p class="title cyan">Profile</p>
|
54
|
+
</td>
|
55
|
+
<td class="content-wrapper">
|
56
|
+
<p class="content">{{{ profile }}}</p>
|
57
|
+
</td>
|
58
|
+
</tr>
|
59
|
+
|
60
|
+
<!--
|
61
|
+
_____ _ _______ _ _ _____
|
62
|
+
/ ___| | / /_ _| | | | / ___|
|
63
|
+
\ `--.| |/ / | | | | | | \ `--.
|
64
|
+
`--. \ \ | | | | | | `--. \
|
65
|
+
/\__/ / |\ \_| |_| |____| |____/\__/ /
|
66
|
+
\____/\_| \_/\___/\_____/\_____/\____/
|
67
|
+
-->
|
68
|
+
<tr class="section">
|
69
|
+
<td class="title-wrapper">
|
70
|
+
<p class="title cyan">Skills</p>
|
71
|
+
</td>
|
72
|
+
<td class="content-wrapper skills-section">
|
73
|
+
<div class="fields-wrapper">
|
74
|
+
<ul class="fields-list skill-list no-list" style="columns: {{ skills.columns }};">
|
75
|
+
{{# skills.fields}}
|
76
|
+
<li>
|
77
|
+
<span class="skill-title">{{ name }}</span>
|
78
|
+
<br>
|
79
|
+
<span class="content">{{{ description }}}</span>
|
80
|
+
</li>
|
81
|
+
{{/ skills.fields}}
|
82
|
+
</ul>
|
83
|
+
</div>
|
84
|
+
</td>
|
85
|
+
</tr>
|
86
|
+
|
87
|
+
<!--
|
88
|
+
_____ _____ _____ _ _ _ _ _____ _____ ___ _
|
89
|
+
|_ _| ___/ __ \| | | || \ | |_ _/ __ \ / _ \ | |
|
90
|
+
| | | |__ | / \/| |_| || \| | | | | / \// /_\ \| |
|
91
|
+
| | | __|| | | _ || . ` | | | | | | _ || |
|
92
|
+
| | | |___| \__/\| | | || |\ |_| |_| \__/\| | | || |____
|
93
|
+
\_/ \____/ \____/\_| |_/\_| \_/\___/ \____/\_| |_/\_____/
|
94
|
+
-->
|
95
|
+
<tr class="section">
|
96
|
+
<td class="title-wrapper">
|
97
|
+
<p class="title cyan">Technical</p>
|
98
|
+
</td>
|
99
|
+
<td class="content-wrapper">
|
100
|
+
<ul class="skill-list no-list">
|
101
|
+
{{# technical}}
|
102
|
+
<li>
|
103
|
+
<span class="skill-title">{{ category }}:</span>
|
104
|
+
<span class="content">{{{ items }}}</span>
|
105
|
+
</li>
|
106
|
+
{{/ technical}}
|
107
|
+
</ul>
|
108
|
+
</td>
|
109
|
+
</tr>
|
110
|
+
|
111
|
+
<!--
|
112
|
+
_____ _____ _____ _____ _____ _____ _ _ _____
|
113
|
+
/ ___| ___/ __ \_ _|_ _| _ | \ | |/ ___|
|
114
|
+
\ `--.| |__ | / \/ | | | | | | | | \| |\ `--.
|
115
|
+
`--. \ __|| | | | | | | | | | . ` | `--. \
|
116
|
+
/\__/ / |___| \__/\ | | _| |_\ \_/ / |\ |/\__/ /
|
117
|
+
\____/\____/ \____/ \_/ \___/ \___/\_| \_/\____/
|
118
|
+
-->
|
119
|
+
{{# sections}}
|
120
|
+
<tr class="section">
|
121
|
+
<td class="title-wrapper">
|
122
|
+
<p class="title cyan">{{ name }}</p>
|
123
|
+
</td>
|
124
|
+
<td class="content-wrapper">
|
125
|
+
{{# items}}
|
126
|
+
<table class="subsection">
|
127
|
+
<tr>
|
128
|
+
<td>
|
129
|
+
<p class="title">
|
130
|
+
{{# logo}}
|
131
|
+
<img class="logo" src="data:image/png;base64,{{ logo }}">
|
132
|
+
{{/ logo}}
|
133
|
+
{{ title }}
|
134
|
+
</p>
|
135
|
+
</td>
|
136
|
+
<td class="period-wrapper">
|
137
|
+
<p>
|
138
|
+
{{ from.month }} <b>{{ from.year }}</b> -
|
139
|
+
{{# to}}{{ to.month }} <b>{{ to.year }}</b>{{/ to}}
|
140
|
+
{{^ to}}Present{{/ to}}
|
141
|
+
</p>
|
142
|
+
</td>
|
143
|
+
</tr>
|
144
|
+
<tr>
|
145
|
+
<td>
|
146
|
+
<p class="subtitle">
|
147
|
+
{{ subtitle }}
|
148
|
+
</p>
|
149
|
+
</td>
|
150
|
+
<td class="location-wrapper">
|
151
|
+
<p class="cyan">{{ location }}</p>
|
152
|
+
</td>
|
153
|
+
</tr>
|
154
|
+
<tr>
|
155
|
+
<td colspan="2">
|
156
|
+
<ul class="no-list">
|
157
|
+
{{# description}}
|
158
|
+
<li class="content">{{& . }}</li>
|
159
|
+
{{/ description}}
|
160
|
+
</ul>
|
161
|
+
</td>
|
162
|
+
</tr>
|
163
|
+
</table>
|
164
|
+
{{/ items}}
|
165
|
+
</td>
|
166
|
+
</tr>
|
167
|
+
{{/ sections}}
|
168
|
+
</body>
|
169
|
+
</html>
|
@@ -0,0 +1 @@
|
|
1
|
+
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="envelope" class="svg-inline--fa fa-envelope fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M502.3 190.8c3.9-3.1 9.7-.2 9.7 4.7V400c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V195.6c0-5 5.7-7.8 9.7-4.7 22.4 17.4 52.1 39.5 154.1 113.6 21.1 15.4 56.7 47.8 92.2 47.6 35.7.3 72-32.8 92.3-47.6 102-74.1 131.6-96.3 154-113.7zM256 320c23.2.4 56.6-29.2 73.4-41.4 132.7-96.3 142.8-104.7 173.4-128.7 5.8-4.5 9.2-11.5 9.2-18.9v-19c0-26.5-21.5-48-48-48H48C21.5 64 0 85.5 0 112v19c0 7.4 3.4 14.3 9.2 18.9 30.6 23.9 40.7 32.4 173.4 128.7 16.8 12.2 50.2 41.8 73.4 41.4z"></path></svg>
|
@@ -0,0 +1 @@
|
|
1
|
+
<svg aria-hidden="true" focusable="false" data-prefix="fab" data-icon="github" class="svg-inline--fa fa-github fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><path fill="currentColor" d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"></path></svg>
|
@@ -0,0 +1 @@
|
|
1
|
+
<svg aria-hidden="true" focusable="false" data-prefix="fab" data-icon="gitlab" class="svg-inline--fa fa-gitlab fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M105.2 24.9c-3.1-8.9-15.7-8.9-18.9 0L29.8 199.7h132c-.1 0-56.6-174.8-56.6-174.8zM.9 287.7c-2.6 8 .3 16.9 7.1 22l247.9 184-226.2-294zm160.8-88l94.3 294 94.3-294zm349.4 88l-28.8-88-226.3 294 247.9-184c6.9-5.1 9.7-14 7.2-22zM425.7 24.9c-3.1-8.9-15.7-8.9-18.9 0l-56.6 174.8h132z"></path></svg>
|
@@ -0,0 +1 @@
|
|
1
|
+
<svg aria-hidden="true" focusable="false" data-prefix="fab" data-icon="linkedin" class="svg-inline--fa fa-linkedin fa-w-14" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor" d="M416 32H31.9C14.3 32 0 46.5 0 64.3v383.4C0 465.5 14.3 480 31.9 480H416c17.6 0 32-14.5 32-32.3V64.3c0-17.8-14.4-32.3-32-32.3zM135.4 416H69V202.2h66.5V416zm-33.2-243c-21.3 0-38.5-17.3-38.5-38.5S80.9 96 102.2 96c21.2 0 38.5 17.3 38.5 38.5 0 21.3-17.2 38.5-38.5 38.5zm282.1 243h-66.4V312c0-24.8-.5-56.7-34.5-56.7-34.6 0-39.9 27-39.9 54.9V416h-66.4V202.2h63.7v29.2h.9c8.9-16.8 30.6-34.5 62.9-34.5 67.2 0 79.7 44.3 79.7 101.9V416z"></path></svg>
|
@@ -0,0 +1 @@
|
|
1
|
+
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="map-marker-alt" class="svg-inline--fa fa-map-marker-alt fa-w-12" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><path fill="currentColor" d="M172.268 501.67C26.97 291.031 0 269.413 0 192 0 85.961 85.961 0 192 0s192 85.961 192 192c0 77.413-26.97 99.031-172.268 309.67-9.535 13.774-29.93 13.773-39.464 0zM192 272c44.183 0 80-35.817 80-80s-35.817-80-80-80-80 35.817-80 80 35.817 80 80 80z"></path></svg>
|
@@ -0,0 +1 @@
|
|
1
|
+
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="phone" class="svg-inline--fa fa-phone fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M493.4 24.6l-104-24c-11.3-2.6-22.9 3.3-27.5 13.9l-48 112c-4.2 9.8-1.4 21.3 6.9 28l60.6 49.6c-36 76.7-98.9 140.5-177.2 177.2l-49.6-60.6c-6.8-8.3-18.2-11.1-28-6.9l-112 48C3.9 366.5-2 378.1.6 389.4l24 104C27.1 504.2 36.7 512 48 512c256.1 0 464-207.5 464-464 0-11.2-7.7-20.9-18.6-23.4z"></path></svg>
|
@@ -0,0 +1 @@
|
|
1
|
+
<svg aria-hidden="true" focusable="false" data-prefix="fab" data-icon="skype" class="svg-inline--fa fa-skype fa-w-14" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor" d="M424.7 299.8c2.9-14 4.7-28.9 4.7-43.8 0-113.5-91.9-205.3-205.3-205.3-14.9 0-29.7 1.7-43.8 4.7C161.3 40.7 137.7 32 112 32 50.2 32 0 82.2 0 144c0 25.7 8.7 49.3 23.3 68.2-2.9 14-4.7 28.9-4.7 43.8 0 113.5 91.9 205.3 205.3 205.3 14.9 0 29.7-1.7 43.8-4.7 19 14.6 42.6 23.3 68.2 23.3 61.8 0 112-50.2 112-112 .1-25.6-8.6-49.2-23.2-68.1zm-194.6 91.5c-65.6 0-120.5-29.2-120.5-65 0-16 9-30.6 29.5-30.6 31.2 0 34.1 44.9 88.1 44.9 25.7 0 42.3-11.4 42.3-26.3 0-18.7-16-21.6-42-28-62.5-15.4-117.8-22-117.8-87.2 0-59.2 58.6-81.1 109.1-81.1 55.1 0 110.8 21.9 110.8 55.4 0 16.9-11.4 31.8-30.3 31.8-28.3 0-29.2-33.5-75-33.5-25.7 0-42 7-42 22.5 0 19.8 20.8 21.8 69.1 33 41.4 9.3 90.7 26.8 90.7 77.6 0 59.1-57.1 86.5-112 86.5z"></path></svg>
|
@@ -0,0 +1 @@
|
|
1
|
+
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="globe" class="svg-inline--fa fa-globe fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><path fill="currentColor" d="M336.5 160C322 70.7 287.8 8 248 8s-74 62.7-88.5 152h177zM152 256c0 22.2 1.2 43.5 3.3 64h185.3c2.1-20.5 3.3-41.8 3.3-64s-1.2-43.5-3.3-64H155.3c-2.1 20.5-3.3 41.8-3.3 64zm324.7-96c-28.6-67.9-86.5-120.4-158-141.6 24.4 33.8 41.2 84.7 50 141.6h108zM177.2 18.4C105.8 39.6 47.8 92.1 19.3 160h108c8.7-56.9 25.5-107.8 49.9-141.6zM487.4 192H372.7c2.1 21 3.3 42.5 3.3 64s-1.2 43-3.3 64h114.6c5.5-20.5 8.6-41.8 8.6-64s-3.1-43.5-8.5-64zM120 256c0-21.5 1.2-43 3.3-64H8.6C3.2 212.5 0 233.8 0 256s3.2 43.5 8.6 64h114.6c-2-21-3.2-42.5-3.2-64zm39.5 96c14.5 89.3 48.7 152 88.5 152s74-62.7 88.5-152h-177zm159.3 141.6c71.4-21.2 129.4-73.7 158-141.6h-108c-8.8 56.9-25.6 107.8-50 141.6zM19.3 352c28.6 67.9 86.5 120.4 158 141.6-24.4-33.8-41.2-84.7-50-141.6h-108z"></path></svg>
|
@@ -0,0 +1,157 @@
|
|
1
|
+
|
2
|
+
body {
|
3
|
+
padding: 0px;
|
4
|
+
background-color: rgb(218, 218, 218);
|
5
|
+
}
|
6
|
+
|
7
|
+
p, li {
|
8
|
+
font-family: Century Gothic, arial, sans-serif;
|
9
|
+
color: #989898;
|
10
|
+
}
|
11
|
+
|
12
|
+
.cyan {
|
13
|
+
color: #7dafd0;
|
14
|
+
}
|
15
|
+
|
16
|
+
.no-list {
|
17
|
+
padding-left: 0em;
|
18
|
+
margin: 0;
|
19
|
+
list-style-type: none;
|
20
|
+
}
|
21
|
+
|
22
|
+
.cv-wrapper {
|
23
|
+
background-color: white;
|
24
|
+
margin: auto;
|
25
|
+
|
26
|
+
width: 210mm;
|
27
|
+
box-sizing: border-box;
|
28
|
+
|
29
|
+
padding: .5in;
|
30
|
+
}
|
31
|
+
|
32
|
+
.header {
|
33
|
+
margin-bottom: 1em;
|
34
|
+
}
|
35
|
+
|
36
|
+
.header table {
|
37
|
+
width: 100%;
|
38
|
+
}
|
39
|
+
|
40
|
+
.header td {
|
41
|
+
padding: 0;
|
42
|
+
margin: 0;
|
43
|
+
vertical-align: bottom;
|
44
|
+
}
|
45
|
+
|
46
|
+
.header p {
|
47
|
+
margin: 0;
|
48
|
+
}
|
49
|
+
|
50
|
+
.header .name {
|
51
|
+
font-size: 1.5em;
|
52
|
+
font-weight: 800;
|
53
|
+
}
|
54
|
+
|
55
|
+
.contact-list {
|
56
|
+
list-style-type: none;
|
57
|
+
padding: 0;
|
58
|
+
margin: 0;
|
59
|
+
height: 3.4em;
|
60
|
+
|
61
|
+
column-count: 2;
|
62
|
+
column-gap: .3em;
|
63
|
+
column-fill: auto;
|
64
|
+
}
|
65
|
+
|
66
|
+
.contact-wrapper {
|
67
|
+
font-size: .62em;
|
68
|
+
white-space: nowrap;
|
69
|
+
padding: .2em;
|
70
|
+
}
|
71
|
+
|
72
|
+
.contact-wrapper a {
|
73
|
+
text-decoration: none;
|
74
|
+
color: inherit;
|
75
|
+
}
|
76
|
+
|
77
|
+
.contact-wrapper svg {
|
78
|
+
position: relative;
|
79
|
+
top: .3em;
|
80
|
+
height: 1.2em;
|
81
|
+
width: 1.2em;
|
82
|
+
color: #14527a;
|
83
|
+
margin-right: .6em;
|
84
|
+
}
|
85
|
+
|
86
|
+
.section .content-wrapper {
|
87
|
+
padding: 0 .5em .75em .5em;
|
88
|
+
}
|
89
|
+
|
90
|
+
.section .title-wrapper {
|
91
|
+
width: 16%;
|
92
|
+
vertical-align: top;
|
93
|
+
}
|
94
|
+
|
95
|
+
.section .title {
|
96
|
+
font-weight: 600;
|
97
|
+
text-transform: uppercase;
|
98
|
+
}
|
99
|
+
|
100
|
+
.section .content {
|
101
|
+
font-size: .8em;
|
102
|
+
}
|
103
|
+
|
104
|
+
.subsection {
|
105
|
+
width: 100%;
|
106
|
+
}
|
107
|
+
|
108
|
+
.subsection:not(:last-child) {
|
109
|
+
margin-bottom: .8em;
|
110
|
+
}
|
111
|
+
|
112
|
+
.subsection .title {
|
113
|
+
color: #696969;
|
114
|
+
font-size: .9em;
|
115
|
+
text-transform: none;
|
116
|
+
}
|
117
|
+
|
118
|
+
.subsection .period-wrapper,
|
119
|
+
.subsection .location-wrapper {
|
120
|
+
font-size: .7em;
|
121
|
+
text-align: right;
|
122
|
+
}
|
123
|
+
|
124
|
+
.subsection .subtitle {
|
125
|
+
font-size: .86em;
|
126
|
+
font-weight: 600;
|
127
|
+
}
|
128
|
+
|
129
|
+
.fields-list {
|
130
|
+
column-fill: balance;
|
131
|
+
}
|
132
|
+
.fields-list li {
|
133
|
+
break-inside: avoid-column;
|
134
|
+
display: inline-block;
|
135
|
+
page-break-inside: avoid;
|
136
|
+
}
|
137
|
+
|
138
|
+
.skill-list .skill-title {
|
139
|
+
color: #696969;
|
140
|
+
font-size: .86em;
|
141
|
+
font-weight: 600;
|
142
|
+
}
|
143
|
+
|
144
|
+
.skills-section {
|
145
|
+
padding-bottom: .25em !important;
|
146
|
+
}
|
147
|
+
|
148
|
+
.fields-list li {
|
149
|
+
margin-bottom: .5em;
|
150
|
+
}
|
151
|
+
|
152
|
+
.title .logo {
|
153
|
+
vertical-align: middle;
|
154
|
+
height: 1.4em;
|
155
|
+
top: -.2em;
|
156
|
+
position: relative;
|
157
|
+
}
|
data/lib/yaml-cv.rb
ADDED
@@ -0,0 +1,146 @@
|
|
1
|
+
require "mustache"
|
2
|
+
require "yaml"
|
3
|
+
require "tempfile"
|
4
|
+
require "uri"
|
5
|
+
require "open3"
|
6
|
+
require "base64"
|
7
|
+
|
8
|
+
def load_asset(asset_file)
|
9
|
+
file_path = File.join(File.dirname(__FILE__), "assets")
|
10
|
+
file_path = File.join(file_path, asset_file)
|
11
|
+
File.read(file_path)
|
12
|
+
end
|
13
|
+
|
14
|
+
def format_period(period)
|
15
|
+
month_names = {
|
16
|
+
1 => "Jun",
|
17
|
+
2 => "Feb",
|
18
|
+
3 => "Mar",
|
19
|
+
4 => "Apr",
|
20
|
+
5 => "May",
|
21
|
+
6 => "Jun",
|
22
|
+
7 => "Jul",
|
23
|
+
8 => "Aug",
|
24
|
+
9 => "Sep",
|
25
|
+
10 => "Oct",
|
26
|
+
11 => "Nov",
|
27
|
+
12 => "Dec"
|
28
|
+
}
|
29
|
+
index = period["month"]
|
30
|
+
period["month"] = month_names[ index ]
|
31
|
+
period
|
32
|
+
end
|
33
|
+
|
34
|
+
class CV < Mustache
|
35
|
+
|
36
|
+
self.template_file = File.join(File.dirname(__FILE__), "assets/cv.mustache")
|
37
|
+
|
38
|
+
def initialize(file_path)
|
39
|
+
@file_path = file_path
|
40
|
+
@cv = YAML.load_file(file_path)
|
41
|
+
|
42
|
+
if @cv["contact"]
|
43
|
+
@cv["contact"] = @cv["contact"].map { |c|
|
44
|
+
c["icon"] = icon(c["icon"])
|
45
|
+
c
|
46
|
+
}
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def details
|
51
|
+
@cv["details"]
|
52
|
+
end
|
53
|
+
|
54
|
+
def profile
|
55
|
+
@cv["profile"]
|
56
|
+
end
|
57
|
+
|
58
|
+
def skills
|
59
|
+
@cv["skills"]
|
60
|
+
end
|
61
|
+
|
62
|
+
def technical
|
63
|
+
@cv["technical"]
|
64
|
+
end
|
65
|
+
|
66
|
+
def sections
|
67
|
+
@cv["sections"].map { |s|
|
68
|
+
s["items"] = format_subsections s["items"]
|
69
|
+
s
|
70
|
+
}
|
71
|
+
end
|
72
|
+
|
73
|
+
def full_name
|
74
|
+
details["last_name"] + " " + details["first_name"]
|
75
|
+
end
|
76
|
+
|
77
|
+
def css
|
78
|
+
load_asset("style.css")
|
79
|
+
end
|
80
|
+
|
81
|
+
def contact
|
82
|
+
@cv["contact"]
|
83
|
+
end
|
84
|
+
|
85
|
+
def contact_padding
|
86
|
+
if !contact
|
87
|
+
return 0
|
88
|
+
end
|
89
|
+
|
90
|
+
columns = (contact.length / 3.0).ceil
|
91
|
+
padding = (2 - columns) * 3
|
92
|
+
|
93
|
+
Array.new(padding) { |i| 0 }
|
94
|
+
end
|
95
|
+
|
96
|
+
def icon(name)
|
97
|
+
load_asset("icons/#{name.strip}.svg")
|
98
|
+
end
|
99
|
+
|
100
|
+
def format_subsections(subsections)
|
101
|
+
if !subsections
|
102
|
+
return
|
103
|
+
end
|
104
|
+
|
105
|
+
subsections.map { |e|
|
106
|
+
if e["from"]
|
107
|
+
e["from"] = format_period e["from"]
|
108
|
+
end
|
109
|
+
if e["to"]
|
110
|
+
e["to"] = format_period e["to"]
|
111
|
+
end
|
112
|
+
|
113
|
+
if e["logo"]
|
114
|
+
e["logo"] = read_image e["logo"]
|
115
|
+
end
|
116
|
+
|
117
|
+
e
|
118
|
+
}
|
119
|
+
end
|
120
|
+
|
121
|
+
def read_image(img_path)
|
122
|
+
file_path = File.join(File.dirname(@file_path), img_path)
|
123
|
+
file = File.open(file_path, "rb")
|
124
|
+
data = file.read
|
125
|
+
Base64.strict_encode64(data)
|
126
|
+
end
|
127
|
+
|
128
|
+
def render
|
129
|
+
template = load_asset("cv.mustache")
|
130
|
+
super(template)
|
131
|
+
end
|
132
|
+
|
133
|
+
def write_html(file_path)
|
134
|
+
html = render
|
135
|
+
File.open(file_path, 'w') { |file| file.write(html) }
|
136
|
+
end
|
137
|
+
|
138
|
+
def write_pdf(file_path)
|
139
|
+
|
140
|
+
temp_file = Tempfile.new(["cv", ".html"])
|
141
|
+
temp_file << render
|
142
|
+
temp_file.flush
|
143
|
+
|
144
|
+
system("wkhtmltopdf #{temp_file.path} #{file_path}")
|
145
|
+
end
|
146
|
+
end
|
metadata
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: yaml-cv
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Greg Mantaos
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-03-02 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: mustache
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 1.1.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 1.1.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: wkhtmltopdf-binary
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.9.9
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.9.9
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: filewatcher
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 1.1.1
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 1.1.1
|
55
|
+
description: Simple tool, with which you can fully populate your CV in user-friendly
|
56
|
+
YAML and then have it generated in HTML or PDF format.
|
57
|
+
email: gmantaos@gmail.com
|
58
|
+
executables:
|
59
|
+
- yaml-cv
|
60
|
+
extensions: []
|
61
|
+
extra_rdoc_files: []
|
62
|
+
files:
|
63
|
+
- Gemfile
|
64
|
+
- LICENSE
|
65
|
+
- README.md
|
66
|
+
- bin/yaml-cv
|
67
|
+
- lib/assets/cv.mustache
|
68
|
+
- lib/assets/icons/email.svg
|
69
|
+
- lib/assets/icons/github.svg
|
70
|
+
- lib/assets/icons/gitlab.svg
|
71
|
+
- lib/assets/icons/linkedin.svg
|
72
|
+
- lib/assets/icons/location.svg
|
73
|
+
- lib/assets/icons/phone.svg
|
74
|
+
- lib/assets/icons/skype.svg
|
75
|
+
- lib/assets/icons/website.svg
|
76
|
+
- lib/assets/style.css
|
77
|
+
- lib/yaml-cv.rb
|
78
|
+
homepage: https://github.com/gmantaos/yaml-cv
|
79
|
+
licenses:
|
80
|
+
- MIT
|
81
|
+
metadata:
|
82
|
+
source_code_uri: https://github.com/gmantaos/yaml-cv
|
83
|
+
post_install_message:
|
84
|
+
rdoc_options: []
|
85
|
+
require_paths:
|
86
|
+
- lib
|
87
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
88
|
+
requirements:
|
89
|
+
- - ">="
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: '0'
|
92
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
requirements: []
|
98
|
+
rubygems_version: 3.0.2
|
99
|
+
signing_key:
|
100
|
+
specification_version: 4
|
101
|
+
summary: Static CV generator from a YAML file, in HTML or PDF format.
|
102
|
+
test_files: []
|