al_folio_cv 1.0.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/CHANGELOG.md +5 -0
- data/LICENSE +21 -0
- data/README.md +28 -0
- data/assets/css/al-folio-cv.css +1 -0
- data/lib/al_folio_cv/version.rb +5 -0
- data/lib/al_folio_cv.rb +55 -0
- data/templates/cv/awards.liquid +66 -0
- data/templates/cv/certificates.liquid +28 -0
- data/templates/cv/education.liquid +93 -0
- data/templates/cv/experience.liquid +91 -0
- data/templates/cv/interests.liquid +29 -0
- data/templates/cv/languages.liquid +28 -0
- data/templates/cv/projects.liquid +31 -0
- data/templates/cv/publications.liquid +70 -0
- data/templates/cv/references.liquid +15 -0
- data/templates/cv/render.liquid +389 -0
- data/templates/cv/skills.liquid +32 -0
- metadata +152 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: e37c2fee391369069d49478404ddc88f4b69337992b96d7cba2ec39472c6c16c
|
|
4
|
+
data.tar.gz: 49c29ef1bbaccbff167e8d4a86dfad41efef7c5ec73beab5239cd81a1b619de2
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 347cd226c6de23f5cc8797594643f61d02a274ad2ae0d011ceaf6b28ac04334c48dbe33deb69c5948c073a0ee7070b77a4a15a5314e66e810a1c3f0dccd6093c
|
|
7
|
+
data.tar.gz: 8d3ece2ff37d0298b3c2a9ea60fb261ed485d7a3713b7a76169690c40fef87ae12fb586b35e98f913b571cda5436958c37b074611fbcd11facca206b64b2c934
|
data/CHANGELOG.md
ADDED
data/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 al-folio maintainers
|
|
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,28 @@
|
|
|
1
|
+
# al-folio-cv
|
|
2
|
+
|
|
3
|
+
CV rendering plugin for al-folio v1.x.
|
|
4
|
+
|
|
5
|
+
## What it provides
|
|
6
|
+
|
|
7
|
+
- Shared CV rendering templates used by `layout: cv`
|
|
8
|
+
- CV helper Liquid tag: `{% al_folio_cv_render %}`
|
|
9
|
+
- Packaged stylesheet at `/assets/css/al-folio-cv.css`
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
Add the gem and plugin:
|
|
14
|
+
|
|
15
|
+
```ruby
|
|
16
|
+
gem 'al_folio_cv'
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
```yml
|
|
20
|
+
plugins:
|
|
21
|
+
- al_folio_cv
|
|
22
|
+
al_folio:
|
|
23
|
+
features:
|
|
24
|
+
cv:
|
|
25
|
+
enabled: true
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
`al_folio_core` delegates `layout: cv` rendering to this plugin.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
div.container-link-button{margin-right:.5rem}table.table-cv{background-color:rgba(0,0,0,0) !important}table.table-cv td,table.table-cv th{padding:1px}a.btncv{color:var(--global-text-color) !important;border:1px solid var(--global-text-color) !important;border-radius:.125rem;padding-left:1rem;padding-right:1rem;padding-top:.25rem;padding-bottom:.25rem;text-decoration:none;font-weight:400;font-size:.7rem;text-align:center;vertical-align:middle;text-transform:uppercase;white-space:nowrap}a.btncv:hover{color:var(--global-theme-color) !important;border-color:var(--global-theme-color) !important;text-decoration:none !important}p.location{font-size:.7rem;white-space:nowrap}i.iconlocation{color:var(--global-theme-color);font-size:.8rem}i.iconinstitution{color:var(--global-theme-color);font-size:.95rem;margin-right:.3rem}i.icondepartment{color:var(--global-theme-color);font-size:.8rem;margin-right:.3rem}table.institution{margin-bottom:1rem}td.department{font-size:.8rem}div.container-links{display:flex;flex-direction:row;flex-wrap:wrap;align-items:center;justify-content:flex-start;margin-top:1rem;margin-bottom:.5rem}div.container-pdf{display:flex;flex-direction:row;flex-wrap:wrap;align-items:center;justify-content:flex-start}div.list-groups{display:flex;flex-wrap:wrap;justify-content:flex-start;flex-direction:row;align-content:center}div.list-group{display:flex;flex-wrap:wrap;flex-direction:column;align-items:flex-start;margin-bottom:2rem}td.list-group-category{color:var(--global-theme-color);margin-bottom:.5rem}td.list-group-category-icon{font-size:.8rem;color:var(--global-theme-color);width:1.4rem;padding-right:.4rem}td.list-group-name{font-size:.8rem}td.list-group-level{font-size:.8rem;padding-left:.5rem}td.list-group-school{font-size:.7rem;padding-left:.5rem;text-align:center}p.list-group-time{font-size:.7rem;padding-left:.5rem}td.list-group-link{padding-left:.5rem}a.anchor{display:block;position:relative;top:-50px;visibility:hidden}ul.timeline{margin-top:2rem;margin-bottom:2rem}ul.timeline li{position:relative;min-height:2.2rem;color:var(--global-text-color);list-style-position:inside}span.badge-toc{color:var(--global-bg-color);background-color:var(--global-theme-color);border-radius:.125rem;padding:.125rem .5rem .125rem .5rem;font-weight:700 !important;display:inline-block;inline-size:fit-content}ul.timeline li::before{content:"";min-height:2.5rem;width:1px;background:var(--global-text-color);margin:0;padding:0;position:absolute;left:2px;top:-0.5rem}/*# sourceMappingURL=al-folio-cv.css.map */
|
data/lib/al_folio_cv.rb
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "jekyll"
|
|
4
|
+
require_relative "al_folio_cv/version"
|
|
5
|
+
|
|
6
|
+
module AlFolioCv
|
|
7
|
+
PLUGIN_ROOT = File.expand_path("..", __dir__)
|
|
8
|
+
TEMPLATES_ROOT = File.join(PLUGIN_ROOT, "templates")
|
|
9
|
+
ASSETS_ROOT = File.join(PLUGIN_ROOT, "assets")
|
|
10
|
+
|
|
11
|
+
class PluginStaticFile < Jekyll::StaticFile; end
|
|
12
|
+
|
|
13
|
+
module_function
|
|
14
|
+
|
|
15
|
+
def enabled?(site)
|
|
16
|
+
site.config.dig("al_folio", "features", "cv", "enabled") != false
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
class AssetsGenerator < Jekyll::Generator
|
|
20
|
+
safe true
|
|
21
|
+
priority :low
|
|
22
|
+
|
|
23
|
+
def generate(site)
|
|
24
|
+
return unless AlFolioCv.enabled?(site)
|
|
25
|
+
|
|
26
|
+
Dir.glob(File.join(ASSETS_ROOT, "**", "*")).sort.each do |source_path|
|
|
27
|
+
next if File.directory?(source_path)
|
|
28
|
+
|
|
29
|
+
relative_dir = File.dirname(source_path).sub("#{PLUGIN_ROOT}/", "")
|
|
30
|
+
site.static_files << PluginStaticFile.new(site, PLUGIN_ROOT, relative_dir, File.basename(source_path))
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
class RenderTag < Liquid::Tag
|
|
36
|
+
def render(context)
|
|
37
|
+
site = context.registers[:site]
|
|
38
|
+
return "" unless site && AlFolioCv.enabled?(site)
|
|
39
|
+
|
|
40
|
+
Liquid::Template.parse("{% include cv/render.liquid %}").render!(
|
|
41
|
+
context.environments.first,
|
|
42
|
+
registers: context.registers
|
|
43
|
+
)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
Liquid::Template.register_tag("al_folio_cv_render", AlFolioCv::RenderTag)
|
|
49
|
+
|
|
50
|
+
Jekyll::Hooks.register :site, :after_init do |site|
|
|
51
|
+
next unless site.respond_to?(:includes_load_paths)
|
|
52
|
+
|
|
53
|
+
include_path = AlFolioCv::TEMPLATES_ROOT
|
|
54
|
+
site.includes_load_paths << include_path unless site.includes_load_paths.include?(include_path)
|
|
55
|
+
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
{% comment %}
|
|
2
|
+
Unified awards entry renderer for both formats
|
|
3
|
+
{% endcomment %}
|
|
4
|
+
|
|
5
|
+
<ul class="card-text font-weight-light list-group list-group-flush">
|
|
6
|
+
{% for entry in entries %}
|
|
7
|
+
<li class="list-group-item">
|
|
8
|
+
<div class="row">
|
|
9
|
+
{% capture start_date %}
|
|
10
|
+
{% if entry.date %}{{ entry.date }}{% endif %}
|
|
11
|
+
{% endcapture %}
|
|
12
|
+
|
|
13
|
+
{% if start_date != '' %}
|
|
14
|
+
<div class="col-xs-2 col-sm-2 col-md-2 text-center">
|
|
15
|
+
<table class="table-cv">
|
|
16
|
+
<tbody>
|
|
17
|
+
<tr>
|
|
18
|
+
<td>
|
|
19
|
+
<span class="badge font-weight-bold danger-color-dark text-uppercase align-middle" style="min-width: 75px">
|
|
20
|
+
{{- start_date | split: '-' | slice: 0, 1 | join: '' -}}
|
|
21
|
+
</span>
|
|
22
|
+
</td>
|
|
23
|
+
</tr>
|
|
24
|
+
</tbody>
|
|
25
|
+
</table>
|
|
26
|
+
</div>
|
|
27
|
+
<div class="col-xs-10 col-sm-10 col-md-10 mt-2 mt-md-0">
|
|
28
|
+
{% if entry.url %}
|
|
29
|
+
<h6 class="title font-weight-bold ml-1 ml-md-4">
|
|
30
|
+
<a href="{{ entry.url }}">{{ entry.title }}</a>
|
|
31
|
+
</h6>
|
|
32
|
+
{% elsif entry.title %}
|
|
33
|
+
<h6 class="title font-weight-bold ml-1 ml-md-4">{{ entry.title }}</h6>
|
|
34
|
+
{% endif %}
|
|
35
|
+
|
|
36
|
+
{% if entry.awarder %}
|
|
37
|
+
<h6 class="ml-1 ml-md-4" style="font-size: 0.95rem">{{ entry.awarder }}</h6>
|
|
38
|
+
{% endif %}
|
|
39
|
+
|
|
40
|
+
{% if entry.summary %}
|
|
41
|
+
<p class="ml-1 ml-md-4">{{ entry.summary | markdownify | remove: '<p>' | remove: '</p>' }}</p>
|
|
42
|
+
{% endif %}
|
|
43
|
+
</div>
|
|
44
|
+
{% else %}
|
|
45
|
+
<div class="col-xs-12 col-sm-12 col-md-12">
|
|
46
|
+
{% if entry.url %}
|
|
47
|
+
<h6 class="title font-weight-bold ml-1 ml-md-4">
|
|
48
|
+
<a href="{{ entry.url }}">{{ entry.title }}</a>
|
|
49
|
+
</h6>
|
|
50
|
+
{% elsif entry.title %}
|
|
51
|
+
<h6 class="title font-weight-bold ml-1 ml-md-4">{{ entry.title }}</h6>
|
|
52
|
+
{% endif %}
|
|
53
|
+
|
|
54
|
+
{% if entry.awarder %}
|
|
55
|
+
<h6 class="ml-1 ml-md-4" style="font-size: 0.95rem">{{ entry.awarder }}</h6>
|
|
56
|
+
{% endif %}
|
|
57
|
+
|
|
58
|
+
{% if entry.summary %}
|
|
59
|
+
<p class="ml-1 ml-md-4">{{ entry.summary | markdownify | remove: '<p>' | remove: '</p>' }}</p>
|
|
60
|
+
{% endif %}
|
|
61
|
+
</div>
|
|
62
|
+
{% endif %}
|
|
63
|
+
</div>
|
|
64
|
+
</li>
|
|
65
|
+
{% endfor %}
|
|
66
|
+
</ul>
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{% comment %}
|
|
2
|
+
Unified certificates entry renderer for both formats
|
|
3
|
+
{% endcomment %}
|
|
4
|
+
|
|
5
|
+
<ul class="card-text font-weight-light list-group list-group-flush">
|
|
6
|
+
{% for entry in entries %}
|
|
7
|
+
<li class="list-group-item">
|
|
8
|
+
{% if entry.icon %}
|
|
9
|
+
<i class="{{ entry.icon }}"></i>
|
|
10
|
+
{% endif %}
|
|
11
|
+
{% if entry.url %}
|
|
12
|
+
<strong
|
|
13
|
+
><a href="{{ entry.url }}" target="_blank">{{ entry.name }}</a></strong
|
|
14
|
+
>
|
|
15
|
+
{% else %}
|
|
16
|
+
<strong>{{ entry.name }}</strong>
|
|
17
|
+
{% endif %}
|
|
18
|
+
|
|
19
|
+
{% if entry.issuer %}
|
|
20
|
+
- <em>{{ entry.issuer }}</em>
|
|
21
|
+
{% endif %}
|
|
22
|
+
|
|
23
|
+
{% if entry.date %}
|
|
24
|
+
({{ entry.date | split: '-' | slice: 0, 1 | join: '' }})
|
|
25
|
+
{% endif %}
|
|
26
|
+
</li>
|
|
27
|
+
{% endfor %}
|
|
28
|
+
</ul>
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
{% comment %}
|
|
2
|
+
Unified education entry renderer for both RenderCV and JSONResume formats
|
|
3
|
+
Handles both:
|
|
4
|
+
- RenderCV: institution, area, studyType (or degree), start_date, end_date, location, courses, highlights
|
|
5
|
+
- JSONResume: institution, area, studyType, startDate, endDate, location, courses, highlights
|
|
6
|
+
{% endcomment %}
|
|
7
|
+
|
|
8
|
+
<ul class="card-text font-weight-light list-group list-group-flush">
|
|
9
|
+
{% for entry in entries %}
|
|
10
|
+
<li class="list-group-item">
|
|
11
|
+
<div class="row">
|
|
12
|
+
<div class="col-xs-2 col-sm-2 col-md-2 text-center date-column">
|
|
13
|
+
{% capture start_date %}
|
|
14
|
+
{% if entry.start_date %}{{ entry.start_date }}{% elsif entry.startDate %}{{ entry.startDate }}{% endif %}
|
|
15
|
+
{% endcapture %}
|
|
16
|
+
{% capture end_date %}
|
|
17
|
+
{% if entry.end_date %}{{ entry.end_date }}{% elsif entry.endDate %}{{ entry.endDate }}{% endif %}
|
|
18
|
+
{% endcapture %}
|
|
19
|
+
|
|
20
|
+
{% if start_date != '' %}
|
|
21
|
+
{% comment %} Extract year only from dates like "1933-01-01" or just use "1933" as is {% endcomment %}
|
|
22
|
+
{% assign startDate = start_date | split: '-' | first %}
|
|
23
|
+
{% assign endDate = end_date | split: '-' | first | default: 'Present' %}
|
|
24
|
+
{% assign date = startDate | append: ' - ' | append: endDate %}
|
|
25
|
+
{% else %}
|
|
26
|
+
{% assign date = null %}
|
|
27
|
+
{% endif %}
|
|
28
|
+
|
|
29
|
+
<table class="table-cv">
|
|
30
|
+
<tbody>
|
|
31
|
+
<tr>
|
|
32
|
+
<td>
|
|
33
|
+
{% if date %}
|
|
34
|
+
<span class="badge font-weight-bold danger-color-dark text-uppercase align-middle" style="min-width: 75px">{{ date }}</span>
|
|
35
|
+
{% endif %}
|
|
36
|
+
</td>
|
|
37
|
+
</tr>
|
|
38
|
+
{% capture location %}
|
|
39
|
+
{% if entry.location %}{{ entry.location }}{% endif %}
|
|
40
|
+
{% endcapture %}
|
|
41
|
+
{% if location != '' %}
|
|
42
|
+
<tr>
|
|
43
|
+
<td>
|
|
44
|
+
<p class="location">
|
|
45
|
+
<i class="fa-solid fa-location-dot iconlocation"></i>
|
|
46
|
+
{{ location }}
|
|
47
|
+
</p>
|
|
48
|
+
</td>
|
|
49
|
+
</tr>
|
|
50
|
+
{% endif %}
|
|
51
|
+
</tbody>
|
|
52
|
+
</table>
|
|
53
|
+
</div>
|
|
54
|
+
<div class="col-xs-10 col-sm-10 col-md-10 mt-2 mt-md-0">
|
|
55
|
+
{% capture study_type %}
|
|
56
|
+
{% if entry.studyType %}{{ entry.studyType }}{% elsif entry.degree %}{{ entry.degree }}{% endif %}
|
|
57
|
+
{% endcapture %}
|
|
58
|
+
|
|
59
|
+
{% if entry.url %}
|
|
60
|
+
<h6 class="title font-weight-bold ml-1 ml-md-4">
|
|
61
|
+
<a href="{{ entry.url }}">{{ study_type }}</a>
|
|
62
|
+
</h6>
|
|
63
|
+
{% elsif study_type != '' %}
|
|
64
|
+
<h6 class="title font-weight-bold ml-1 ml-md-4">{{ study_type }}</h6>
|
|
65
|
+
{% endif %}
|
|
66
|
+
|
|
67
|
+
{% if entry.institution %}
|
|
68
|
+
<h6 class="ml-1 ml-md-4" style="font-size: 0.95rem">{{ entry.institution }}</h6>
|
|
69
|
+
{% endif %}
|
|
70
|
+
|
|
71
|
+
{% if entry.area %}
|
|
72
|
+
<h6 class="ml-1 ml-md-4" style="font-size: 0.95rem; font-style: italic">{{ entry.area }}</h6>
|
|
73
|
+
{% endif %}
|
|
74
|
+
|
|
75
|
+
{% if entry.courses or entry.highlights %}
|
|
76
|
+
<ul class="items">
|
|
77
|
+
{% for item in entry.courses %}
|
|
78
|
+
<li>
|
|
79
|
+
<span class="item">{{ item }}</span>
|
|
80
|
+
</li>
|
|
81
|
+
{% endfor %}
|
|
82
|
+
{% for item in entry.highlights %}
|
|
83
|
+
<li>
|
|
84
|
+
<span class="item">{{ item | markdownify | remove: '<p>' | remove: '</p>' }}</span>
|
|
85
|
+
</li>
|
|
86
|
+
{% endfor %}
|
|
87
|
+
</ul>
|
|
88
|
+
{% endif %}
|
|
89
|
+
</div>
|
|
90
|
+
</div>
|
|
91
|
+
</li>
|
|
92
|
+
{% endfor %}
|
|
93
|
+
</ul>
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
{% comment %}
|
|
2
|
+
Unified work/experience entry renderer for both RenderCV and JSONResume formats
|
|
3
|
+
Handles both:
|
|
4
|
+
- RenderCV: company, position, start_date, end_date, location, url, summary, highlights
|
|
5
|
+
- JSONResume: name, position, startDate, endDate, location, url, summary, highlights
|
|
6
|
+
{% endcomment %}
|
|
7
|
+
|
|
8
|
+
<ul class="card-text font-weight-light list-group list-group-flush">
|
|
9
|
+
{% for entry in entries %}
|
|
10
|
+
<li class="list-group-item">
|
|
11
|
+
<div class="row">
|
|
12
|
+
<div class="col-xs-2 col-sm-2 col-md-2 text-center date-column">
|
|
13
|
+
{% capture start_date %}
|
|
14
|
+
{% if entry.start_date %}{{ entry.start_date }}{% elsif entry.startDate %}{{ entry.startDate }}{% endif %}
|
|
15
|
+
{% endcapture %}
|
|
16
|
+
{% capture end_date %}
|
|
17
|
+
{% if entry.end_date %}{{ entry.end_date }}{% elsif entry.endDate %}{{ entry.endDate }}{% endif %}
|
|
18
|
+
{% endcapture %}
|
|
19
|
+
|
|
20
|
+
{% if start_date != '' %}
|
|
21
|
+
{% comment %} Extract year only from dates like "1933-01-01" or just use "1933" as is {% endcomment %}
|
|
22
|
+
{% assign startDate = start_date | split: '-' | first %}
|
|
23
|
+
{% assign endDate = end_date | split: '-' | first | default: 'Present' %}
|
|
24
|
+
{% assign date = startDate | append: ' - ' | append: endDate %}
|
|
25
|
+
{% else %}
|
|
26
|
+
{% assign date = '' %}
|
|
27
|
+
{% endif %}
|
|
28
|
+
|
|
29
|
+
<table class="table-cv">
|
|
30
|
+
<tbody>
|
|
31
|
+
<tr>
|
|
32
|
+
<td>
|
|
33
|
+
<span class="badge font-weight-bold danger-color-dark text-uppercase align-middle" style="min-width: 75px">{{ date }}</span>
|
|
34
|
+
</td>
|
|
35
|
+
</tr>
|
|
36
|
+
{% capture location %}
|
|
37
|
+
{% if entry.location %}{{ entry.location }}{% endif %}
|
|
38
|
+
{% endcapture %}
|
|
39
|
+
{% if location != '' %}
|
|
40
|
+
<tr>
|
|
41
|
+
<td>
|
|
42
|
+
<p class="location">
|
|
43
|
+
<i class="fa-solid fa-location-dot iconlocation"></i>
|
|
44
|
+
{{ location }}
|
|
45
|
+
</p>
|
|
46
|
+
</td>
|
|
47
|
+
</tr>
|
|
48
|
+
{% endif %}
|
|
49
|
+
</tbody>
|
|
50
|
+
</table>
|
|
51
|
+
</div>
|
|
52
|
+
<div class="col-xs-10 col-sm-10 col-md-10 mt-2 mt-md-0">
|
|
53
|
+
{% capture position_title %}
|
|
54
|
+
{% if entry.position %}{{ entry.position }}{% endif %}
|
|
55
|
+
{% endcapture %}
|
|
56
|
+
|
|
57
|
+
{% if entry.url %}
|
|
58
|
+
<h6 class="title font-weight-bold ml-1 ml-md-4">
|
|
59
|
+
<a href="{{ entry.url }}">{{ position_title }}</a>
|
|
60
|
+
</h6>
|
|
61
|
+
{% elsif position_title != '' %}
|
|
62
|
+
<h6 class="title font-weight-bold ml-1 ml-md-4">{{ position_title }}</h6>
|
|
63
|
+
{% endif %}
|
|
64
|
+
|
|
65
|
+
{% capture company_name %}
|
|
66
|
+
{% if entry.name %}{{ entry.name }}{% elsif entry.company %}{{ entry.company }}{% elsif entry.organization %}{{ entry.organization }}{% endif %}
|
|
67
|
+
{% endcapture %}
|
|
68
|
+
{% if company_name != '' %}
|
|
69
|
+
<h6 class="ml-1 ml-md-4" style="font-size: 0.95rem">{{ company_name }}</h6>
|
|
70
|
+
{% endif %}
|
|
71
|
+
|
|
72
|
+
{% if entry.summary %}
|
|
73
|
+
<h6 class="ml-1 ml-md-4" style="font-size: 0.95rem; font-style: italic">
|
|
74
|
+
{{ entry.summary | markdownify | remove: '<p>' | remove: '</p>' }}
|
|
75
|
+
</h6>
|
|
76
|
+
{% endif %}
|
|
77
|
+
|
|
78
|
+
{% if entry.highlights %}
|
|
79
|
+
<ul class="items">
|
|
80
|
+
{% for item in entry.highlights %}
|
|
81
|
+
<li>
|
|
82
|
+
<span class="item">{{ item | markdownify | remove: '<p>' | remove: '</p>' }}</span>
|
|
83
|
+
</li>
|
|
84
|
+
{% endfor %}
|
|
85
|
+
</ul>
|
|
86
|
+
{% endif %}
|
|
87
|
+
</div>
|
|
88
|
+
</div>
|
|
89
|
+
</li>
|
|
90
|
+
{% endfor %}
|
|
91
|
+
</ul>
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{% comment %}
|
|
2
|
+
Unified interests entry renderer for both formats
|
|
3
|
+
{% endcomment %}
|
|
4
|
+
|
|
5
|
+
<div class="card-text font-weight-light">
|
|
6
|
+
{% for entry in entries %}
|
|
7
|
+
<div class="interest-item">
|
|
8
|
+
{% if entry.icon %}
|
|
9
|
+
<i class="{{ entry.icon }}"></i>
|
|
10
|
+
{% endif %}
|
|
11
|
+
<strong>{{ entry.name }}:</strong>
|
|
12
|
+
{% if entry.keywords %}
|
|
13
|
+
{% for keyword in entry.keywords %}
|
|
14
|
+
{% if forloop.last %}
|
|
15
|
+
{{ keyword }}
|
|
16
|
+
{% else %}
|
|
17
|
+
{{ keyword }},
|
|
18
|
+
{% endif %}
|
|
19
|
+
{% endfor %}
|
|
20
|
+
{% endif %}
|
|
21
|
+
</div>
|
|
22
|
+
{% endfor %}
|
|
23
|
+
</div>
|
|
24
|
+
|
|
25
|
+
<style>
|
|
26
|
+
.interest-item {
|
|
27
|
+
padding: 0.5rem 0;
|
|
28
|
+
}
|
|
29
|
+
</style>
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{% comment %}
|
|
2
|
+
Unified languages entry renderer for both formats
|
|
3
|
+
- RenderCV uses: name, summary
|
|
4
|
+
- JSONResume uses: language, fluency
|
|
5
|
+
{% endcomment %}
|
|
6
|
+
|
|
7
|
+
<div class="card-text font-weight-light">
|
|
8
|
+
{% for entry in entries %}
|
|
9
|
+
<div class="language-item">
|
|
10
|
+
{% if entry.icon %}
|
|
11
|
+
<i class="{{ entry.icon }}"></i>
|
|
12
|
+
{% endif %}
|
|
13
|
+
{% capture lang_name %}
|
|
14
|
+
{% if entry.name %}{{ entry.name }}{% elsif entry.language %}{{ entry.language }}{% endif %}
|
|
15
|
+
{% endcapture %}
|
|
16
|
+
{% capture fluency %}
|
|
17
|
+
{% if entry.summary %}{{ entry.summary }}{% elsif entry.fluency %}{{ entry.fluency }}{% endif %}
|
|
18
|
+
{% endcapture %}
|
|
19
|
+
<strong>{{ lang_name }}:</strong> {{ fluency }}
|
|
20
|
+
</div>
|
|
21
|
+
{% endfor %}
|
|
22
|
+
</div>
|
|
23
|
+
|
|
24
|
+
<style>
|
|
25
|
+
.language-item {
|
|
26
|
+
padding: 0.5rem 0;
|
|
27
|
+
}
|
|
28
|
+
</style>
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{% comment %}
|
|
2
|
+
Unified projects entry renderer for both formats
|
|
3
|
+
{% endcomment %}
|
|
4
|
+
|
|
5
|
+
<ul class="card-text font-weight-light list-group list-group-flush">
|
|
6
|
+
{% for entry in entries %}
|
|
7
|
+
<li class="list-group-item">
|
|
8
|
+
{% if entry.url %}
|
|
9
|
+
<h6 class="title font-weight-bold">
|
|
10
|
+
<a href="{{ entry.url }}" target="_blank">{{ entry.name }}</a>
|
|
11
|
+
</h6>
|
|
12
|
+
{% else %}
|
|
13
|
+
<h6 class="title font-weight-bold">{{ entry.name }}</h6>
|
|
14
|
+
{% endif %}
|
|
15
|
+
|
|
16
|
+
{% if entry.summary %}
|
|
17
|
+
<p>{{ entry.summary | markdownify | remove: '<p>' | remove: '</p>' }}</p>
|
|
18
|
+
{% endif %}
|
|
19
|
+
|
|
20
|
+
{% if entry.highlights %}
|
|
21
|
+
<ul class="items">
|
|
22
|
+
{% for item in entry.highlights %}
|
|
23
|
+
<li>
|
|
24
|
+
<span class="item">{{ item | markdownify | remove: '<p>' | remove: '</p>' }}</span>
|
|
25
|
+
</li>
|
|
26
|
+
{% endfor %}
|
|
27
|
+
</ul>
|
|
28
|
+
{% endif %}
|
|
29
|
+
</li>
|
|
30
|
+
{% endfor %}
|
|
31
|
+
</ul>
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
{% comment %}
|
|
2
|
+
Unified publications entry renderer for both formats
|
|
3
|
+
{% endcomment %}
|
|
4
|
+
|
|
5
|
+
<ul class="card-text font-weight-light list-group list-group-flush">
|
|
6
|
+
{% for entry in entries %}
|
|
7
|
+
<li class="list-group-item">
|
|
8
|
+
<div class="row">
|
|
9
|
+
{% capture pub_date %}
|
|
10
|
+
{% if entry.releaseDate %}{{ entry.releaseDate }}{% elsif entry.date %}{{ entry.date }}{% endif %}
|
|
11
|
+
{% endcapture %}
|
|
12
|
+
|
|
13
|
+
{% if pub_date != '' %}
|
|
14
|
+
<div class="col-xs-2 col-sm-2 col-md-2 text-center">
|
|
15
|
+
<table class="table-cv">
|
|
16
|
+
<tbody>
|
|
17
|
+
<tr>
|
|
18
|
+
<td>
|
|
19
|
+
<span class="badge font-weight-bold danger-color-dark text-uppercase align-middle" style="min-width: 75px">
|
|
20
|
+
{{- pub_date | split: '-' | slice: 0, 1 | join: '' -}}
|
|
21
|
+
</span>
|
|
22
|
+
</td>
|
|
23
|
+
</tr>
|
|
24
|
+
</tbody>
|
|
25
|
+
</table>
|
|
26
|
+
</div>
|
|
27
|
+
<div class="col-xs-10 col-sm-10 col-md-10 mt-2 mt-md-0">
|
|
28
|
+
{% if entry.url %}
|
|
29
|
+
<h6 class="title font-weight-bold ml-1 ml-md-4">
|
|
30
|
+
<a href="{{ entry.url }}">{{ entry.title | default: entry.name }}</a>
|
|
31
|
+
</h6>
|
|
32
|
+
{% elsif entry.title %}
|
|
33
|
+
<h6 class="title font-weight-bold ml-1 ml-md-4">{{ entry.title }}</h6>
|
|
34
|
+
{% endif %}
|
|
35
|
+
|
|
36
|
+
{% if entry.publisher %}
|
|
37
|
+
<h6 class="ml-1 ml-md-4" style="font-size: 0.95rem">
|
|
38
|
+
<em>{{ entry.publisher }}</em>
|
|
39
|
+
</h6>
|
|
40
|
+
{% endif %}
|
|
41
|
+
|
|
42
|
+
{% if entry.summary %}
|
|
43
|
+
<p class="ml-1 ml-md-4">{{ entry.summary | markdownify | remove: '<p>' | remove: '</p>' }}</p>
|
|
44
|
+
{% endif %}
|
|
45
|
+
</div>
|
|
46
|
+
{% else %}
|
|
47
|
+
<div class="col-xs-12 col-sm-12 col-md-12">
|
|
48
|
+
{% if entry.url %}
|
|
49
|
+
<h6 class="title font-weight-bold ml-1 ml-md-4">
|
|
50
|
+
<a href="{{ entry.url }}">{{ entry.title | default: entry.name }}</a>
|
|
51
|
+
</h6>
|
|
52
|
+
{% elsif entry.title %}
|
|
53
|
+
<h6 class="title font-weight-bold ml-1 ml-md-4">{{ entry.title }}</h6>
|
|
54
|
+
{% endif %}
|
|
55
|
+
|
|
56
|
+
{% if entry.publisher %}
|
|
57
|
+
<h6 class="ml-1 ml-md-4" style="font-size: 0.95rem">
|
|
58
|
+
<em>{{ entry.publisher }}</em>
|
|
59
|
+
</h6>
|
|
60
|
+
{% endif %}
|
|
61
|
+
|
|
62
|
+
{% if entry.summary %}
|
|
63
|
+
<p class="ml-1 ml-md-4">{{ entry.summary | markdownify | remove: '<p>' | remove: '</p>' }}</p>
|
|
64
|
+
{% endif %}
|
|
65
|
+
</div>
|
|
66
|
+
{% endif %}
|
|
67
|
+
</div>
|
|
68
|
+
</li>
|
|
69
|
+
{% endfor %}
|
|
70
|
+
</ul>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{% comment %}
|
|
2
|
+
Unified references entry renderer for both formats
|
|
3
|
+
{% endcomment %}
|
|
4
|
+
|
|
5
|
+
<ul class="card-text font-weight-light list-group list-group-flush">
|
|
6
|
+
{% for entry in entries %}
|
|
7
|
+
<li class="list-group-item">
|
|
8
|
+
{% if entry.icon %}
|
|
9
|
+
<i class="{{ entry.icon }}"></i>
|
|
10
|
+
{% endif %}
|
|
11
|
+
<strong>{{ entry.name }}</strong>
|
|
12
|
+
<p>{{ entry.reference | markdownify | remove: '<p>' | remove: '</p>' }}</p>
|
|
13
|
+
</li>
|
|
14
|
+
{% endfor %}
|
|
15
|
+
</ul>
|
|
@@ -0,0 +1,389 @@
|
|
|
1
|
+
{% comment %}
|
|
2
|
+
Unified CV layout that handles both RenderCV (YAML) and JSONResume (JSON) formats
|
|
3
|
+
- If page.cv_format is set, it determines which format to render:
|
|
4
|
+
- 'rendercv': Load and render only RenderCV data (site.data.cv.cv)
|
|
5
|
+
- 'jsonresume': Load and render only JSONResume data (site.data.resume)
|
|
6
|
+
- If page.cv_format is not set, the legacy behavior applies:
|
|
7
|
+
- RenderCV data is in site.data.cv.cv
|
|
8
|
+
- JSONResume data is in site.data.resume
|
|
9
|
+
- RenderCV is prioritized if both exist
|
|
10
|
+
Both formats use the same unified rendering includes for consistent output
|
|
11
|
+
{% endcomment %}
|
|
12
|
+
|
|
13
|
+
<div class="post">
|
|
14
|
+
<header class="post-header">
|
|
15
|
+
<h1 class="post-title">
|
|
16
|
+
{{ page.title }}
|
|
17
|
+
{% if page.cv_pdf %}
|
|
18
|
+
<a
|
|
19
|
+
{% if page.cv_pdf contains '://' %}
|
|
20
|
+
href="{{ page.cv_pdf }}"
|
|
21
|
+
{% else %}
|
|
22
|
+
href="{{ page.cv_pdf | relative_url }}"
|
|
23
|
+
{% endif %}
|
|
24
|
+
target="_blank"
|
|
25
|
+
rel="noopener noreferrer"
|
|
26
|
+
class="float-right"
|
|
27
|
+
>
|
|
28
|
+
<i class="fa-solid fa-file-pdf"></i>
|
|
29
|
+
</a>
|
|
30
|
+
{% endif %}
|
|
31
|
+
</h1>
|
|
32
|
+
{% if page.description %}
|
|
33
|
+
<p class="post-description">{{ page.description }}</p>
|
|
34
|
+
{% endif %}
|
|
35
|
+
</header>
|
|
36
|
+
|
|
37
|
+
<article>
|
|
38
|
+
<div class="cv">
|
|
39
|
+
{% comment %} Determine which CV format to render {% endcomment %}
|
|
40
|
+
{% assign render_rendercv = false %}
|
|
41
|
+
{% assign render_jsonresume = false %}
|
|
42
|
+
|
|
43
|
+
{% if page.cv_format == 'rendercv' %}
|
|
44
|
+
{% assign render_rendercv = true %}
|
|
45
|
+
{% elsif page.cv_format == 'jsonresume' %}
|
|
46
|
+
{% assign render_jsonresume = true %}
|
|
47
|
+
{% else %}
|
|
48
|
+
{% comment %} Legacy behavior: RenderCV takes priority if both exist {% endcomment %}
|
|
49
|
+
{% if site.data.cv and site.data.cv.cv %}
|
|
50
|
+
{% assign render_rendercv = true %}
|
|
51
|
+
{% elsif site.data.resume %}
|
|
52
|
+
{% assign render_jsonresume = true %}
|
|
53
|
+
{% endif %}
|
|
54
|
+
{% endif %}
|
|
55
|
+
|
|
56
|
+
{% if render_rendercv and site.data.cv and site.data.cv.cv %}
|
|
57
|
+
{% comment %} RenderCV format {% endcomment %}
|
|
58
|
+
{% assign cv = site.data.cv.cv %}
|
|
59
|
+
|
|
60
|
+
<!-- Header/Contact Information -->
|
|
61
|
+
{% if cv.name or cv.label or cv.location or cv.email or cv.phone or cv.website %}
|
|
62
|
+
<div class="card mt-3 p-3">
|
|
63
|
+
<h3 class="card-title font-weight-medium">Contact Information</h3>
|
|
64
|
+
<table class="table table-cv table-sm table-borderless">
|
|
65
|
+
{% if cv.name %}
|
|
66
|
+
<tr>
|
|
67
|
+
<td class="p-1 pr-2 font-weight-bold"><b>Name</b></td>
|
|
68
|
+
<td class="p-1 pl-2 font-weight-light">{{ cv.name }}</td>
|
|
69
|
+
</tr>
|
|
70
|
+
{% endif %}
|
|
71
|
+
{% if cv.label %}
|
|
72
|
+
<tr>
|
|
73
|
+
<td class="p-1 pr-2 font-weight-bold"><b>Professional Title</b></td>
|
|
74
|
+
<td class="p-1 pl-2 font-weight-light">{{ cv.label }}</td>
|
|
75
|
+
</tr>
|
|
76
|
+
{% endif %}
|
|
77
|
+
{% if cv.email %}
|
|
78
|
+
<tr>
|
|
79
|
+
<td class="p-1 pr-2 font-weight-bold"><b>Email</b></td>
|
|
80
|
+
<td class="p-1 pl-2 font-weight-light">{{ cv.email }}</td>
|
|
81
|
+
</tr>
|
|
82
|
+
{% endif %}
|
|
83
|
+
{% if cv.phone %}
|
|
84
|
+
<tr>
|
|
85
|
+
<td class="p-1 pr-2 font-weight-bold"><b>Phone</b></td>
|
|
86
|
+
<td class="p-1 pl-2 font-weight-light">{{ cv.phone }}</td>
|
|
87
|
+
</tr>
|
|
88
|
+
{% endif %}
|
|
89
|
+
{% if cv.address %}
|
|
90
|
+
<tr>
|
|
91
|
+
<td class="p-1 pr-2 font-weight-bold"><b>Location</b></td>
|
|
92
|
+
<td class="p-1 pl-2 font-weight-light">
|
|
93
|
+
{% if cv.address.street %}{{ cv.address.street }}, {% endif %}
|
|
94
|
+
{% if cv.address.city %}{{ cv.address.city }}, {% endif %}
|
|
95
|
+
{% if cv.address.region %}{{ cv.address.region }} {% endif %}
|
|
96
|
+
{% if cv.address.postalCode %}{{ cv.address.postalCode }}{% endif %}
|
|
97
|
+
</td>
|
|
98
|
+
</tr>
|
|
99
|
+
{% endif %}
|
|
100
|
+
{% if cv.website %}
|
|
101
|
+
<tr>
|
|
102
|
+
<td class="p-1 pr-2 font-weight-bold"><b>Website</b></td>
|
|
103
|
+
<td class="p-1 pl-2 font-weight-light">
|
|
104
|
+
<a href="{{ cv.website }}" target="_blank">{{ cv.website }}</a>
|
|
105
|
+
</td>
|
|
106
|
+
</tr>
|
|
107
|
+
{% endif %}
|
|
108
|
+
</table>
|
|
109
|
+
</div>
|
|
110
|
+
{% endif %}
|
|
111
|
+
|
|
112
|
+
<!-- Summary -->
|
|
113
|
+
{% if cv.summary %}
|
|
114
|
+
<div class="card mt-3 p-3">
|
|
115
|
+
<h3 class="card-title font-weight-medium">Professional Summary</h3>
|
|
116
|
+
<p>{{ cv.summary | markdownify | remove: '<p>' | remove: '</p>' }}</p>
|
|
117
|
+
</div>
|
|
118
|
+
{% endif %}
|
|
119
|
+
|
|
120
|
+
<!-- RenderCV Sections - Merge Experience and Volunteer -->
|
|
121
|
+
{% comment %} First, combine Experience and Volunteer entries {% endcomment %}
|
|
122
|
+
{% assign empty_array = '' | split: ',' %}
|
|
123
|
+
{% assign exp = cv.sections.Experience | default: empty_array %}
|
|
124
|
+
{% assign vol = cv.sections.Volunteer | default: empty_array %}
|
|
125
|
+
{% assign combined_experience = exp | concat: vol %}
|
|
126
|
+
{% if combined_experience.size > 0 %}
|
|
127
|
+
<a class="anchor" id="experience"></a>
|
|
128
|
+
<div class="card mt-3 p-3">
|
|
129
|
+
<h3 class="card-title font-weight-medium">Experience</h3>
|
|
130
|
+
<div>
|
|
131
|
+
{% assign entries = combined_experience %}
|
|
132
|
+
{% include cv/experience.liquid %}
|
|
133
|
+
</div>
|
|
134
|
+
</div>
|
|
135
|
+
{% endif %}
|
|
136
|
+
|
|
137
|
+
{% comment %} Now render all other sections except Experience and Volunteer {% endcomment %}
|
|
138
|
+
{% for section_pair in cv.sections %}
|
|
139
|
+
{% assign section_title = section_pair[0] %}
|
|
140
|
+
{% assign section_entries = section_pair[1] %}
|
|
141
|
+
|
|
142
|
+
{% comment %} Skip Experience and Volunteer as we've already processed them combined {% endcomment %}
|
|
143
|
+
{% if section_title == 'Experience' or section_title == 'Volunteer' %}
|
|
144
|
+
{% continue %}
|
|
145
|
+
{% endif %}
|
|
146
|
+
|
|
147
|
+
<a class="anchor" id="{{ section_title | slugify }}"></a>
|
|
148
|
+
<div class="card mt-3 p-3">
|
|
149
|
+
<h3 class="card-title font-weight-medium">{{ section_title }}</h3>
|
|
150
|
+
<div>
|
|
151
|
+
{% if section_title == 'Education' %}
|
|
152
|
+
{% assign entries = section_entries %}
|
|
153
|
+
{% include cv/education.liquid %}
|
|
154
|
+
{% elsif section_title == 'Awards' or section_title == 'Honors and Awards' %}
|
|
155
|
+
{% assign entries = section_entries %}
|
|
156
|
+
{% include cv/awards.liquid %}
|
|
157
|
+
{% elsif section_title == 'Publications' %}
|
|
158
|
+
{% assign entries = section_entries %}
|
|
159
|
+
{% include cv/publications.liquid %}
|
|
160
|
+
{% elsif section_title == 'Skills' %}
|
|
161
|
+
{% assign entries = section_entries %}
|
|
162
|
+
{% include cv/skills.liquid %}
|
|
163
|
+
{% elsif section_title == 'Languages' %}
|
|
164
|
+
{% assign entries = section_entries %}
|
|
165
|
+
{% include cv/languages.liquid %}
|
|
166
|
+
{% elsif section_title == 'Interests' or section_title == 'Academic Interests' %}
|
|
167
|
+
{% assign entries = section_entries %}
|
|
168
|
+
{% include cv/interests.liquid %}
|
|
169
|
+
{% elsif section_title == 'Certificates' %}
|
|
170
|
+
{% assign entries = section_entries %}
|
|
171
|
+
{% include cv/certificates.liquid %}
|
|
172
|
+
{% elsif section_title == 'Projects' or section_title == 'Open Source Projects' %}
|
|
173
|
+
{% assign entries = section_entries %}
|
|
174
|
+
{% include cv/projects.liquid %}
|
|
175
|
+
{% elsif section_title == 'References' %}
|
|
176
|
+
{% assign entries = section_entries %}
|
|
177
|
+
{% include cv/references.liquid %}
|
|
178
|
+
{% else %}
|
|
179
|
+
<!-- Generic section -->
|
|
180
|
+
{% for entry in section_entries %}
|
|
181
|
+
{% if entry.bullet %}
|
|
182
|
+
<ul class="card-text font-weight-light list-group list-group-flush">
|
|
183
|
+
<li class="list-group-item">{{ entry.bullet | markdownify | remove: '<p>' | remove: '</p>' }}</li>
|
|
184
|
+
</ul>
|
|
185
|
+
{% elsif entry.label %}
|
|
186
|
+
<div class="card-text font-weight-light">
|
|
187
|
+
<strong>{{ entry.label }}:</strong> {{ entry.details }}
|
|
188
|
+
</div>
|
|
189
|
+
{% endif %}
|
|
190
|
+
{% endfor %}
|
|
191
|
+
{% endif %}
|
|
192
|
+
</div>
|
|
193
|
+
</div>
|
|
194
|
+
{% endfor %}
|
|
195
|
+
|
|
196
|
+
{% elsif render_jsonresume and site.data.resume %}
|
|
197
|
+
{% comment %} JSONResume format {% endcomment %}
|
|
198
|
+
|
|
199
|
+
<!-- Contact Information -->
|
|
200
|
+
{% if site.data.resume.basics %}
|
|
201
|
+
<div class="card mt-3 p-3">
|
|
202
|
+
<h3 class="card-title font-weight-medium">Contact Information</h3>
|
|
203
|
+
{% assign basics = site.data.resume.basics %}
|
|
204
|
+
<table class="table table-cv table-sm table-borderless">
|
|
205
|
+
{% if basics.name %}
|
|
206
|
+
<tr>
|
|
207
|
+
<td class="p-1 pr-2 font-weight-bold"><b>Name</b></td>
|
|
208
|
+
<td class="p-1 pl-2 font-weight-light">{{ basics.name }}</td>
|
|
209
|
+
</tr>
|
|
210
|
+
{% endif %}
|
|
211
|
+
{% if basics.label %}
|
|
212
|
+
<tr>
|
|
213
|
+
<td class="p-1 pr-2 font-weight-bold"><b>Professional Title</b></td>
|
|
214
|
+
<td class="p-1 pl-2 font-weight-light">{{ basics.label }}</td>
|
|
215
|
+
</tr>
|
|
216
|
+
{% endif %}
|
|
217
|
+
{% if basics.email %}
|
|
218
|
+
<tr>
|
|
219
|
+
<td class="p-1 pr-2 font-weight-bold"><b>Email</b></td>
|
|
220
|
+
<td class="p-1 pl-2 font-weight-light">{{ basics.email }}</td>
|
|
221
|
+
</tr>
|
|
222
|
+
{% endif %}
|
|
223
|
+
{% if basics.phone %}
|
|
224
|
+
<tr>
|
|
225
|
+
<td class="p-1 pr-2 font-weight-bold"><b>Phone</b></td>
|
|
226
|
+
<td class="p-1 pl-2 font-weight-light">{{ basics.phone }}</td>
|
|
227
|
+
</tr>
|
|
228
|
+
{% endif %}
|
|
229
|
+
{% if basics.location %}
|
|
230
|
+
<tr>
|
|
231
|
+
<td class="p-1 pr-2 font-weight-bold"><b>Location</b></td>
|
|
232
|
+
<td class="p-1 pl-2 font-weight-light">
|
|
233
|
+
{% if basics.location.address %}{{ basics.location.address }}, {% endif %}
|
|
234
|
+
{% if basics.location.city %}{{ basics.location.city }}, {% endif %}
|
|
235
|
+
{% if basics.location.region %}{{ basics.location.region }} {% endif %}
|
|
236
|
+
{% if basics.location.postalCode %}{{ basics.location.postalCode }}{% endif %}
|
|
237
|
+
</td>
|
|
238
|
+
</tr>
|
|
239
|
+
{% endif %}
|
|
240
|
+
{% if basics.url %}
|
|
241
|
+
<tr>
|
|
242
|
+
<td class="p-1 pr-2 font-weight-bold"><b>Website</b></td>
|
|
243
|
+
<td class="p-1 pl-2 font-weight-light">
|
|
244
|
+
<a href="{{ basics.url }}" target="_blank">{{ basics.url }}</a>
|
|
245
|
+
</td>
|
|
246
|
+
</tr>
|
|
247
|
+
{% endif %}
|
|
248
|
+
</table>
|
|
249
|
+
</div>
|
|
250
|
+
{% endif %}
|
|
251
|
+
|
|
252
|
+
<!-- Summary -->
|
|
253
|
+
{% if site.data.resume.basics.summary %}
|
|
254
|
+
<div class="card mt-3 p-3">
|
|
255
|
+
<h3 class="card-title font-weight-medium">Professional Summary</h3>
|
|
256
|
+
<p>{{ site.data.resume.basics.summary | markdownify | remove: '<p>' | remove: '</p>' }}</p>
|
|
257
|
+
</div>
|
|
258
|
+
{% endif %}
|
|
259
|
+
|
|
260
|
+
<!-- JSONResume Sections - Merge work and volunteer into Experience -->
|
|
261
|
+
{% assign empty_array = '' | split: ',' %}
|
|
262
|
+
{% assign work = site.data.resume.work | default: empty_array %}
|
|
263
|
+
{% assign vol = site.data.resume.volunteer | default: empty_array %}
|
|
264
|
+
{% assign combined_experience = work | concat: vol %}
|
|
265
|
+
{% if combined_experience.size > 0 %}
|
|
266
|
+
<a class="anchor" id="experience"></a>
|
|
267
|
+
<div class="card mt-3 p-3">
|
|
268
|
+
<h3 class="card-title font-weight-medium">Experience</h3>
|
|
269
|
+
<div>
|
|
270
|
+
{% assign entries = combined_experience %}
|
|
271
|
+
{% include cv/experience.liquid %}
|
|
272
|
+
</div>
|
|
273
|
+
</div>
|
|
274
|
+
{% endif %}
|
|
275
|
+
|
|
276
|
+
<!-- Education -->
|
|
277
|
+
{% if site.data.resume.education.size > 0 %}
|
|
278
|
+
<a class="anchor" id="education"></a>
|
|
279
|
+
<div class="card mt-3 p-3">
|
|
280
|
+
<h3 class="card-title font-weight-medium">Education</h3>
|
|
281
|
+
<div>
|
|
282
|
+
{% assign entries = site.data.resume.education %}
|
|
283
|
+
{% include cv/education.liquid %}
|
|
284
|
+
</div>
|
|
285
|
+
</div>
|
|
286
|
+
{% endif %}
|
|
287
|
+
|
|
288
|
+
<!-- Awards -->
|
|
289
|
+
{% if site.data.resume.awards.size > 0 %}
|
|
290
|
+
<a class="anchor" id="awards"></a>
|
|
291
|
+
<div class="card mt-3 p-3">
|
|
292
|
+
<h3 class="card-title font-weight-medium">Awards</h3>
|
|
293
|
+
<div>
|
|
294
|
+
{% assign entries = site.data.resume.awards %}
|
|
295
|
+
{% include cv/awards.liquid %}
|
|
296
|
+
</div>
|
|
297
|
+
</div>
|
|
298
|
+
{% endif %}
|
|
299
|
+
|
|
300
|
+
<!-- Publications -->
|
|
301
|
+
{% if site.data.resume.publications.size > 0 %}
|
|
302
|
+
<a class="anchor" id="publications"></a>
|
|
303
|
+
<div class="card mt-3 p-3">
|
|
304
|
+
<h3 class="card-title font-weight-medium">Publications</h3>
|
|
305
|
+
<div>
|
|
306
|
+
{% assign entries = site.data.resume.publications %}
|
|
307
|
+
{% include cv/publications.liquid %}
|
|
308
|
+
</div>
|
|
309
|
+
</div>
|
|
310
|
+
{% endif %}
|
|
311
|
+
|
|
312
|
+
<!-- Skills -->
|
|
313
|
+
{% if site.data.resume.skills.size > 0 %}
|
|
314
|
+
<a class="anchor" id="skills"></a>
|
|
315
|
+
<div class="card mt-3 p-3">
|
|
316
|
+
<h3 class="card-title font-weight-medium">Skills</h3>
|
|
317
|
+
<div>
|
|
318
|
+
{% assign entries = site.data.resume.skills %}
|
|
319
|
+
{% include cv/skills.liquid %}
|
|
320
|
+
</div>
|
|
321
|
+
</div>
|
|
322
|
+
{% endif %}
|
|
323
|
+
|
|
324
|
+
<!-- Languages -->
|
|
325
|
+
{% if site.data.resume.languages.size > 0 %}
|
|
326
|
+
<a class="anchor" id="languages"></a>
|
|
327
|
+
<div class="card mt-3 p-3">
|
|
328
|
+
<h3 class="card-title font-weight-medium">Languages</h3>
|
|
329
|
+
<div>
|
|
330
|
+
{% assign entries = site.data.resume.languages %}
|
|
331
|
+
{% include cv/languages.liquid %}
|
|
332
|
+
</div>
|
|
333
|
+
</div>
|
|
334
|
+
{% endif %}
|
|
335
|
+
|
|
336
|
+
<!-- Interests -->
|
|
337
|
+
{% if site.data.resume.interests.size > 0 %}
|
|
338
|
+
<a class="anchor" id="interests"></a>
|
|
339
|
+
<div class="card mt-3 p-3">
|
|
340
|
+
<h3 class="card-title font-weight-medium">Interests</h3>
|
|
341
|
+
<div>
|
|
342
|
+
{% assign entries = site.data.resume.interests %}
|
|
343
|
+
{% include cv/interests.liquid %}
|
|
344
|
+
</div>
|
|
345
|
+
</div>
|
|
346
|
+
{% endif %}
|
|
347
|
+
|
|
348
|
+
<!-- Certificates -->
|
|
349
|
+
{% if site.data.resume.certificates.size > 0 %}
|
|
350
|
+
<a class="anchor" id="certificates"></a>
|
|
351
|
+
<div class="card mt-3 p-3">
|
|
352
|
+
<h3 class="card-title font-weight-medium">Certificates</h3>
|
|
353
|
+
<div>
|
|
354
|
+
{% assign entries = site.data.resume.certificates %}
|
|
355
|
+
{% include cv/certificates.liquid %}
|
|
356
|
+
</div>
|
|
357
|
+
</div>
|
|
358
|
+
{% endif %}
|
|
359
|
+
|
|
360
|
+
<!-- Projects -->
|
|
361
|
+
{% if site.data.resume.projects.size > 0 %}
|
|
362
|
+
<a class="anchor" id="projects"></a>
|
|
363
|
+
<div class="card mt-3 p-3">
|
|
364
|
+
<h3 class="card-title font-weight-medium">Projects</h3>
|
|
365
|
+
<div>
|
|
366
|
+
{% assign entries = site.data.resume.projects %}
|
|
367
|
+
{% include cv/projects.liquid %}
|
|
368
|
+
</div>
|
|
369
|
+
</div>
|
|
370
|
+
{% endif %}
|
|
371
|
+
|
|
372
|
+
<!-- References -->
|
|
373
|
+
{% if site.data.resume.references.size > 0 %}
|
|
374
|
+
<a class="anchor" id="references"></a>
|
|
375
|
+
<div class="card mt-3 p-3">
|
|
376
|
+
<h3 class="card-title font-weight-medium">References</h3>
|
|
377
|
+
<div>
|
|
378
|
+
{% assign entries = site.data.resume.references %}
|
|
379
|
+
{% include cv/references.liquid %}
|
|
380
|
+
</div>
|
|
381
|
+
</div>
|
|
382
|
+
{% endif %}
|
|
383
|
+
|
|
384
|
+
{% else %}
|
|
385
|
+
<p>No CV data found. Please configure either RenderCV (cv.yml) or JSONResume (resume.json) data.</p>
|
|
386
|
+
{% endif %}
|
|
387
|
+
</div>
|
|
388
|
+
</article>
|
|
389
|
+
</div>
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{% comment %}
|
|
2
|
+
Unified skills entry renderer for both formats
|
|
3
|
+
{% endcomment %}
|
|
4
|
+
|
|
5
|
+
<div class="card-text font-weight-light">
|
|
6
|
+
{% for entry in entries %}
|
|
7
|
+
<div class="skill-item">
|
|
8
|
+
{% if entry.icon %}
|
|
9
|
+
<i class="{{ entry.icon }}"></i>
|
|
10
|
+
{% endif %}
|
|
11
|
+
<strong>
|
|
12
|
+
{{- entry.name -}}
|
|
13
|
+
{%- if entry.level %} ({{ entry.level }}){% endif %}:</strong
|
|
14
|
+
>
|
|
15
|
+
{% if entry.keywords %}
|
|
16
|
+
{% for keyword in entry.keywords %}
|
|
17
|
+
{% if forloop.last %}
|
|
18
|
+
{{ keyword }}
|
|
19
|
+
{% else %}
|
|
20
|
+
{{ keyword }},
|
|
21
|
+
{% endif %}
|
|
22
|
+
{% endfor %}
|
|
23
|
+
{% endif %}
|
|
24
|
+
</div>
|
|
25
|
+
{% endfor %}
|
|
26
|
+
</div>
|
|
27
|
+
|
|
28
|
+
<style>
|
|
29
|
+
.skill-item {
|
|
30
|
+
padding: 0.5rem 0;
|
|
31
|
+
}
|
|
32
|
+
</style>
|
metadata
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: al_folio_cv
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- al-folio maintainers
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2026-02-16 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: jekyll
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - ">="
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '3.9'
|
|
20
|
+
- - "<"
|
|
21
|
+
- !ruby/object:Gem::Version
|
|
22
|
+
version: '5.0'
|
|
23
|
+
type: :runtime
|
|
24
|
+
prerelease: false
|
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
26
|
+
requirements:
|
|
27
|
+
- - ">="
|
|
28
|
+
- !ruby/object:Gem::Version
|
|
29
|
+
version: '3.9'
|
|
30
|
+
- - "<"
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '5.0'
|
|
33
|
+
- !ruby/object:Gem::Dependency
|
|
34
|
+
name: liquid
|
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - ">="
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '4.0'
|
|
40
|
+
- - "<"
|
|
41
|
+
- !ruby/object:Gem::Version
|
|
42
|
+
version: '6.0'
|
|
43
|
+
type: :runtime
|
|
44
|
+
prerelease: false
|
|
45
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
46
|
+
requirements:
|
|
47
|
+
- - ">="
|
|
48
|
+
- !ruby/object:Gem::Version
|
|
49
|
+
version: '4.0'
|
|
50
|
+
- - "<"
|
|
51
|
+
- !ruby/object:Gem::Version
|
|
52
|
+
version: '6.0'
|
|
53
|
+
- !ruby/object:Gem::Dependency
|
|
54
|
+
name: bundler
|
|
55
|
+
requirement: !ruby/object:Gem::Requirement
|
|
56
|
+
requirements:
|
|
57
|
+
- - ">="
|
|
58
|
+
- !ruby/object:Gem::Version
|
|
59
|
+
version: '2.0'
|
|
60
|
+
- - "<"
|
|
61
|
+
- !ruby/object:Gem::Version
|
|
62
|
+
version: '3.0'
|
|
63
|
+
type: :development
|
|
64
|
+
prerelease: false
|
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
66
|
+
requirements:
|
|
67
|
+
- - ">="
|
|
68
|
+
- !ruby/object:Gem::Version
|
|
69
|
+
version: '2.0'
|
|
70
|
+
- - "<"
|
|
71
|
+
- !ruby/object:Gem::Version
|
|
72
|
+
version: '3.0'
|
|
73
|
+
- !ruby/object:Gem::Dependency
|
|
74
|
+
name: rake
|
|
75
|
+
requirement: !ruby/object:Gem::Requirement
|
|
76
|
+
requirements:
|
|
77
|
+
- - "~>"
|
|
78
|
+
- !ruby/object:Gem::Version
|
|
79
|
+
version: '13.0'
|
|
80
|
+
type: :development
|
|
81
|
+
prerelease: false
|
|
82
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
83
|
+
requirements:
|
|
84
|
+
- - "~>"
|
|
85
|
+
- !ruby/object:Gem::Version
|
|
86
|
+
version: '13.0'
|
|
87
|
+
- !ruby/object:Gem::Dependency
|
|
88
|
+
name: minitest
|
|
89
|
+
requirement: !ruby/object:Gem::Requirement
|
|
90
|
+
requirements:
|
|
91
|
+
- - "~>"
|
|
92
|
+
- !ruby/object:Gem::Version
|
|
93
|
+
version: '5.0'
|
|
94
|
+
type: :development
|
|
95
|
+
prerelease: false
|
|
96
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
97
|
+
requirements:
|
|
98
|
+
- - "~>"
|
|
99
|
+
- !ruby/object:Gem::Version
|
|
100
|
+
version: '5.0'
|
|
101
|
+
description: Provides CV templates, rendering tags, and packaged CV assets for al-folio
|
|
102
|
+
sites.
|
|
103
|
+
email:
|
|
104
|
+
- maintainers@al-folio.dev
|
|
105
|
+
executables: []
|
|
106
|
+
extensions: []
|
|
107
|
+
extra_rdoc_files: []
|
|
108
|
+
files:
|
|
109
|
+
- CHANGELOG.md
|
|
110
|
+
- LICENSE
|
|
111
|
+
- README.md
|
|
112
|
+
- assets/css/al-folio-cv.css
|
|
113
|
+
- lib/al_folio_cv.rb
|
|
114
|
+
- lib/al_folio_cv/version.rb
|
|
115
|
+
- templates/cv/awards.liquid
|
|
116
|
+
- templates/cv/certificates.liquid
|
|
117
|
+
- templates/cv/education.liquid
|
|
118
|
+
- templates/cv/experience.liquid
|
|
119
|
+
- templates/cv/interests.liquid
|
|
120
|
+
- templates/cv/languages.liquid
|
|
121
|
+
- templates/cv/projects.liquid
|
|
122
|
+
- templates/cv/publications.liquid
|
|
123
|
+
- templates/cv/references.liquid
|
|
124
|
+
- templates/cv/render.liquid
|
|
125
|
+
- templates/cv/skills.liquid
|
|
126
|
+
homepage: https://github.com/al-org-dev/al-folio-cv
|
|
127
|
+
licenses:
|
|
128
|
+
- MIT
|
|
129
|
+
metadata:
|
|
130
|
+
allowed_push_host: https://rubygems.org
|
|
131
|
+
homepage_uri: https://github.com/al-org-dev/al-folio-cv
|
|
132
|
+
source_code_uri: https://github.com/al-org-dev/al-folio-cv
|
|
133
|
+
post_install_message:
|
|
134
|
+
rdoc_options: []
|
|
135
|
+
require_paths:
|
|
136
|
+
- lib
|
|
137
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
138
|
+
requirements:
|
|
139
|
+
- - ">="
|
|
140
|
+
- !ruby/object:Gem::Version
|
|
141
|
+
version: '2.7'
|
|
142
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
143
|
+
requirements:
|
|
144
|
+
- - ">="
|
|
145
|
+
- !ruby/object:Gem::Version
|
|
146
|
+
version: '0'
|
|
147
|
+
requirements: []
|
|
148
|
+
rubygems_version: 3.4.10
|
|
149
|
+
signing_key:
|
|
150
|
+
specification_version: 4
|
|
151
|
+
summary: CV rendering plugin for al-folio v1.x
|
|
152
|
+
test_files: []
|