resume_exporter 0.0.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/bin/resume_exporter +4 -2
  3. data/lib/exporters/html.rb +33 -0
  4. data/lib/exporters/pdf.rb +13 -0
  5. data/lib/extractors/html/linkedin.rb +145 -169
  6. data/lib/extractors/html/stackoverflow.rb +60 -72
  7. data/lib/extractors/html/xing.rb +46 -60
  8. data/lib/extractors/html.rb +1 -1
  9. data/lib/extractors/json/fresh.rb +196 -233
  10. data/lib/extractors/json/json_resume.rb +107 -127
  11. data/lib/extractors/json/prtflio.rb +20 -24
  12. data/lib/extractors/json.rb +7 -6
  13. data/lib/resume_exporter.rb +6 -0
  14. data/lib/templates/default.json.jbuilder +162 -229
  15. data/lib/templates/default.md.erb +99 -244
  16. data/lib/templates/default.txt.erb +99 -224
  17. data/lib/templates/default.xml.builder +162 -227
  18. data/lib/templates/fresh.json.jbuilder +149 -155
  19. data/lib/templates/html/_affiliation.liquid +53 -0
  20. data/lib/templates/html/_basics.liquid +19 -0
  21. data/lib/templates/html/_contact.liquid +27 -0
  22. data/lib/templates/html/_css.liquid +324 -0
  23. data/lib/templates/html/_disposition.liquid +13 -0
  24. data/lib/templates/html/_education.liquid +56 -0
  25. data/lib/templates/html/_employment.liquid +67 -0
  26. data/lib/templates/html/_extracurricular.liquid +53 -0
  27. data/lib/templates/html/_footer.liquid +1 -0
  28. data/lib/templates/html/_governance.liquid +52 -0
  29. data/lib/templates/html/_image.liquid +7 -0
  30. data/lib/templates/html/_interests.liquid +23 -0
  31. data/lib/templates/html/_languages.liquid +22 -0
  32. data/lib/templates/html/_open_source.liquid +53 -0
  33. data/lib/templates/html/_patents.liquid +50 -0
  34. data/lib/templates/html/_projects.liquid +53 -0
  35. data/lib/templates/html/_qualifications.liquid +53 -0
  36. data/lib/templates/html/_reading.liquid +52 -0
  37. data/lib/templates/html/_recognition.liquid +54 -0
  38. data/lib/templates/html/_references.liquid +28 -0
  39. data/lib/templates/html/_resume.liquid +49 -0
  40. data/lib/templates/html/_service.liquid +53 -0
  41. data/lib/templates/html/_skills.liquid +35 -0
  42. data/lib/templates/html/_social.liquid +25 -0
  43. data/lib/templates/html/_speaking.liquid +53 -0
  44. data/lib/templates/html/_writing.liquid +52 -0
  45. data/lib/templates/html/default.liquid +1 -0
  46. data/lib/templates/json_resume.json.jbuilder +72 -72
  47. metadata +119 -20
@@ -0,0 +1,324 @@
1
+ <style type="text/css">
2
+ @charset "UTF-8";
3
+ .container:before, .container:after, .row:before, .row:after {
4
+ display: table;
5
+ content: " "; }
6
+
7
+ .container:after, .row:after {
8
+ clear: both; }
9
+
10
+ .col-sm-2, .col-sm-4, .col-sm-6, .col-sm-8, .col-sm-10, .col-md-3, .col-md-8 {
11
+ position: relative;
12
+ min-height: 1px; }
13
+
14
+ @media print {
15
+ .col-sm-2, .col-sm-4, .col-sm-6, .col-sm-8, .col-sm-10 {
16
+ float: left; }
17
+
18
+ .col-sm-10 {
19
+ width: 83.33333333%; }
20
+
21
+ .col-sm-8 {
22
+ width: 66.66666667%; }
23
+
24
+ .col-sm-6 {
25
+ width: 50%; }
26
+
27
+ .col-sm-4 {
28
+ width: 33.33333333%; }
29
+
30
+ .col-sm-2 {
31
+ width: 16.66666667%; } }
32
+ @media screen {
33
+ .container {
34
+ padding-right: 15px;
35
+ padding-left: 15px;
36
+ margin-right: auto;
37
+ margin-left: auto; } }
38
+ @media screen and (min-width: 768px) {
39
+ .col-sm-2, .col-sm-4, .col-sm-6, .col-sm-8, .col-sm-10 {
40
+ float: left; }
41
+
42
+ .col-sm-10 {
43
+ width: 83.33333333%; }
44
+
45
+ .col-sm-8 {
46
+ width: 66.66666667%; }
47
+
48
+ .col-sm-6 {
49
+ width: 50%; }
50
+
51
+ .col-sm-4 {
52
+ width: 33.33333333%; }
53
+
54
+ .col-sm-2 {
55
+ width: 16.66666667%; } }
56
+ @media screen and (min-width: 992px) {
57
+ .col-md-3, .col-md-8 {
58
+ float: left; }
59
+
60
+ .col-md-8 {
61
+ width: 66.66666667%; }
62
+
63
+ .col-md-3 {
64
+ width: 25%; } }
65
+ @media screen and (min-width: 768px) {
66
+ .container {
67
+ width: 750px; } }
68
+ @media screen and (min-width: 992px) {
69
+ .container {
70
+ width: 970px; } }
71
+ @media screen and (min-width: 1200px) {
72
+ .container {
73
+ width: 1170px; } }
74
+ @media print {
75
+ html {
76
+ box-sizing: border-box;
77
+ -webkit-box-sizing: border-box;
78
+ -moz-box-sizing: border-box; }
79
+
80
+ *, *:before, *:after {
81
+ box-sizing: inherit;
82
+ -webkit-box-sizing: border-box;
83
+ -moz-box-sizing: border-box; }
84
+
85
+ html, body {
86
+ font-size: 12px !important;
87
+ -webkit-print-color-adjust: exact; }
88
+
89
+ .noprint {
90
+ display: none !important; }
91
+
92
+ .section, .section .entry {
93
+ page-break-inside: avoid; }
94
+
95
+ .entry.last, .language-entry.last {
96
+ margin-bottom: 10px !important; }
97
+
98
+ .entry {
99
+ margin-bottom: 5px !important;
100
+ padding-bottom: 10px !important; }
101
+
102
+ .subtitle, .entry .summary, .entry .keywords {
103
+ padding-bottom: 4px !important; }
104
+
105
+ .right {
106
+ text-align: right; } }
107
+ @media screen and (max-width: 768px) {
108
+ .md-only {
109
+ display: none !important; } }
110
+ @media screen and (min-width: 768px) {
111
+ .sm-only {
112
+ display: none !important; }
113
+
114
+ .main, .sidebar {
115
+ padding-top: 15px; } }
116
+ @media screen, print {
117
+ html {
118
+ font-family: sans-serif;
119
+ line-height: 1.15;
120
+ -ms-text-size-adjust: 100%;
121
+ -webkit-text-size-adjust: 100%; }
122
+
123
+ body {
124
+ margin: 0; }
125
+
126
+ h1 {
127
+ font-size: 2em;
128
+ margin: 0.67em 0; }
129
+
130
+ a {
131
+ background-color: transparent;
132
+ -webkit-text-decoration-skip: objects; }
133
+
134
+ a:active,
135
+ a:hover {
136
+ outline-width: 0; }
137
+
138
+ b,
139
+ strong {
140
+ font-weight: inherit; }
141
+
142
+ b,
143
+ strong {
144
+ font-weight: bolder; }
145
+
146
+ code,
147
+ kbd,
148
+ samp {
149
+ font-family: monospace, monospace;
150
+ font-size: 1em; }
151
+
152
+ img {
153
+ border-style: none; }
154
+
155
+ [hidden] {
156
+ display: none; }
157
+
158
+ html {
159
+ -webkit-box-sizing: border-box;
160
+ box-sizing: border-box; }
161
+
162
+ *,
163
+ *::before,
164
+ *::after {
165
+ -webkit-box-sizing: inherit;
166
+ box-sizing: inherit; }
167
+
168
+ @-ms-viewport {
169
+ width: device-width; }
170
+ html {
171
+ -ms-overflow-style: scrollbar;
172
+ -webkit-tap-highlight-color: transparent; }
173
+
174
+ body {
175
+ font-size: 1rem;
176
+ font-weight: normal;
177
+ line-height: 1.5;
178
+ color: #292b2c;
179
+ background-color: #fff; }
180
+
181
+ h1, h2, h3, h4, h5, h6 {
182
+ margin-top: 0;
183
+ margin-bottom: .5rem; }
184
+
185
+ p {
186
+ margin-top: 0;
187
+ margin-bottom: 1rem; }
188
+
189
+ ol,
190
+ ul,
191
+ dl {
192
+ margin-top: 0;
193
+ margin-bottom: 1rem; }
194
+
195
+ ol ol,
196
+ ul ul,
197
+ ol ul,
198
+ ul ol {
199
+ margin-bottom: 0; }
200
+
201
+ blockquote {
202
+ margin: 0 0 1rem; }
203
+
204
+ a {
205
+ color: #0275d8;
206
+ text-decoration: none; }
207
+
208
+ a:focus, a:hover {
209
+ color: #014c8c;
210
+ text-decoration: underline; }
211
+
212
+ a:not([href]):not([tabindex]) {
213
+ color: inherit;
214
+ text-decoration: none; }
215
+
216
+ a:not([href]):not([tabindex]):focus, a:not([href]):not([tabindex]):hover {
217
+ color: inherit;
218
+ text-decoration: none; }
219
+
220
+ a:not([href]):not([tabindex]):focus {
221
+ outline: 0; }
222
+
223
+ img {
224
+ vertical-align: middle; }
225
+
226
+ a {
227
+ -ms-touch-action: manipulation;
228
+ touch-action: manipulation; }
229
+
230
+ @import url("https://fonts.googleapis.com/css?family=PT+Serif");
231
+ body {
232
+ font-family: 'PT Serif', serif;
233
+ font-size: 16px; }
234
+
235
+ a {
236
+ color: black;
237
+ font-weight: bold;
238
+ font-style: italic; }
239
+
240
+ a:hover {
241
+ color: #cb0000; }
242
+
243
+ .entry {
244
+ margin-bottom: 30px;
245
+ padding-bottom: 20px;
246
+ border-bottom: 1px solid #efefef; }
247
+
248
+ .entry.last, .language-entry.last {
249
+ border-bottom: 0;
250
+ margin-bottom: 50px; }
251
+
252
+ .entry, .entry .subtitle, .entry .description, .entry .summary, .entry .keywords, .language-entry {
253
+ margin-left: 20px; }
254
+
255
+ .section-heading {
256
+ font-size: 1.5em;
257
+ margin: 20px 0;
258
+ color: #cb0000;
259
+ border-bottom: 1px solid #cdcdcd; }
260
+
261
+ .title .right {
262
+ padding-left: 20px; }
263
+
264
+ .subtitle {
265
+ font-style: italic; }
266
+
267
+ .subtitle, .entry .summary, .entry .keywords {
268
+ padding-bottom: 10px; }
269
+
270
+ .keywords .keyword {
271
+ display: inline-block; }
272
+
273
+ .name {
274
+ margin-top: 10px;
275
+ margin-bottom: 0px;
276
+ font-size: 1.5em; }
277
+
278
+ .label {
279
+ margin-top: 0px;
280
+ font-size: 1em; }
281
+
282
+ .sidebar {
283
+ padding-left: 50px; }
284
+
285
+ .sidebar .image img {
286
+ max-width: 100%; }
287
+
288
+ .reference-entry .name {
289
+ font-size: 1.2em; }
290
+
291
+ .keyword {
292
+ background-color: #ffe3e3;
293
+ padding: 5px;
294
+ margin-right: 5px; }
295
+
296
+ blockquote {
297
+ background: #f9f9f9;
298
+ border-left: 10px solid #ccc;
299
+ padding: 0.5em 10px;
300
+ quotes: "“" "”" "‘" "’"; }
301
+
302
+ blockquote:before {
303
+ color: #ccc;
304
+ content: open-quote;
305
+ font-size: 2em;
306
+ line-height: 0.1em;
307
+ margin-right: 0.25em;
308
+ vertical-align: -0.4em; }
309
+
310
+ blockquote p {
311
+ display: inline; }
312
+
313
+ .footer {
314
+ margin: 40px 0 20px 0; }
315
+
316
+ .footer small, .footer small a {
317
+ color: grey; } }
318
+ @media screen and (min-width: 768px) {
319
+ .right {
320
+ text-align: right; } }
321
+ @media screen {
322
+ .footer {
323
+ display: block !important; } }
324
+ </style>
@@ -0,0 +1,13 @@
1
+ {% if site.data.resume.basics.disposition %}
2
+ <div class="row disposition section" id="disposition">
3
+ <div class="col-12">
4
+ <h2 class="section-heading">Disposition</h2>
5
+
6
+ <div class="entry last">
7
+ <div class="summary">
8
+ {{ site.data.resume.basics.disposition }}
9
+ </div>
10
+ </div>
11
+ </div>
12
+ </div>
13
+ {% endif %}
@@ -0,0 +1,56 @@
1
+ {% if site.data.resume.education.size > 0 %}
2
+ <div class="row education section" id="education">
3
+ <div class="col-12">
4
+ <h2 class="section-heading">Education</h2>
5
+
6
+ {% for school in site.data.resume.education %}
7
+ <div class="education-entry entry {% if school == site.data.resume.education.last %}last{% endif %}">
8
+
9
+ <div class="row no-gutters title">
10
+ <div class="col-sm-6">
11
+ <h3>
12
+ {% if school.url %}
13
+ <a href="{{school.url}}">{{school.institution}}</a>
14
+ {% else %}
15
+ {{school.institution}}
16
+ {% endif %}
17
+ </h3>
18
+ </div>
19
+ <div class="col-sm-6 right">
20
+ {% capture dates %}{{ school.startDate }}{% if school.startDate.size > 0 and school.endDate.size > 0 %} - {% endif %} {{school.endDate}}{%endcapture%}
21
+ {{ dates }}
22
+ </div>
23
+ </div>
24
+
25
+ <div class="row no-gutters subtitle">
26
+ <div class="col-sm-6">
27
+ {% capture title %}<span class="field_of_study">{{ school.fieldOfStudy }}</span>{% if school.fieldOfStudy and school.degree %}, {% endif %}<span class="degree">{{ school.degree }}</span>{% if school.grade %} <span class="grade">({{ school.grade }})</span> {% endif %}{% endcapture %}
28
+ {{ title }}
29
+ </div>
30
+ <div class="col-sm-6 right">
31
+ {{school.location}}
32
+ </div>
33
+ </div>
34
+
35
+ {% if school.summary %}
36
+ <div class="summary">
37
+ {{school.summary}}
38
+ </div>
39
+ {% endif %}
40
+
41
+ {% if school.keywords %}
42
+ <div class="keywords">
43
+ {% for keyword in school.keywords %}
44
+ <span class="keyword tag">
45
+ {{ keyword }}
46
+ </span>
47
+ {% endfor %}
48
+ </div>
49
+ {% endif %}
50
+
51
+ </div>
52
+ {% endfor %}
53
+ </div>
54
+ </div>
55
+ {% endif %}
56
+
@@ -0,0 +1,67 @@
1
+ {% if site.data.resume.employment.size > 0 %}
2
+ <div class="row employment section" id="employment" style="page-break-inside: avoid;">
3
+ <div class="col-12">
4
+ <h2 class="section-heading">Work Experience</h2>
5
+
6
+ {% for job in site.data.resume.employment %}
7
+ <div class="employment-entry entry {% if job == site.data.resume.employment.last %}last{% endif %}" style="page-break-inside: avoid;">
8
+
9
+ <div class="row no-gutters title">
10
+ <div class="employer col-sm-6">
11
+ <h3>
12
+ {% if job.url %}
13
+ <a href="{{job.url}}">{{job.employer}}</a>
14
+ {% else %}
15
+ {{job.employer}}
16
+ {% endif %}
17
+ </h3>
18
+ </div>
19
+
20
+ <div class="col-sm-6 right">
21
+ <span class="date">
22
+ {% capture dates %}{{ job.startDate }}{% if job.startDate.size > 0 and job.endDate.size > 0 %} - {% endif %} {{job.endDate}}{%endcapture%}
23
+ {{ dates }}
24
+ </span>
25
+ </div>
26
+ </div>
27
+ <div class="row no-gutters subtitle">
28
+ <div class="position col-sm-6">
29
+ {% if job.position %}
30
+ {{job.position}}
31
+ {% endif %}
32
+ </div>
33
+
34
+ <div class="location col-sm-6 right">
35
+ {% if job.location %}
36
+ {{job.location}}
37
+ {% endif %}
38
+ </div>
39
+ </div>
40
+
41
+ {% if job.summary %}
42
+ <div class="summary row">
43
+ <div class="col-12">
44
+ {{job.summary}}
45
+ </div>
46
+ </div>
47
+ {% endif %}
48
+
49
+
50
+ {% if job.keywords %}
51
+ <div class="keywords row">
52
+ <div class="col-12">
53
+
54
+ {% for keyword in job.keywords %}
55
+ <span class="keyword tag">
56
+ {{ keyword }}
57
+ </span>
58
+ {% endfor %}
59
+ </div>
60
+ </div>
61
+ {% endif %}
62
+
63
+ </div>
64
+ {% endfor %}
65
+ </div>
66
+ </div>
67
+ {% endif %}
@@ -0,0 +1,53 @@
1
+ {% if site.data.resume.extracurricular.size > 0 %}
2
+ <div class="row extracurricular section" id="extracurricular" style="page-break-inside: avoid;">
3
+ <div class="col-12">
4
+ <h2 class="section-heading">Extracurricular</h2>
5
+
6
+ {% for extracurricular in site.data.resume.extracurricular %}
7
+ <div class="extracurricular entry {% if extracurricular == site.data.resume.extracurricular.last %}last{% endif %}" style="page-break-inside: avoid;">
8
+ <div class="row no-gutters title">
9
+ <div class="col-sm-6">
10
+ <h3>
11
+ {% if extracurricular.url %}
12
+ <a href="{{extracurricular.url}}">{{extracurricular.title}}</a>
13
+ {% else %}
14
+ {{extracurricular.title}}
15
+ {% endif %}
16
+ </h3>
17
+ </div>
18
+ <div class="col-sm-6 right">
19
+ {% capture dates %}{{ extracurricular.startDate }}{% if extracurricular.startDate.size > 0 and extracurricular.endDate.size > 0 %} - {% endif %} {{extracurricular.endDate}}{%endcapture%}
20
+ {{ dates }}
21
+ </div>
22
+ </div>
23
+
24
+ <div class="row no-gutters subtitle">
25
+ <div class="col-sm-6">
26
+ {{ extracurricular.category }}
27
+ </div>
28
+ <div class="col-sm-6 right">
29
+ {{ extracurricular.from }}
30
+ </div>
31
+ </div>
32
+
33
+ {% if extracurricular.summary %}
34
+ <div class="summary">
35
+ {{extracurricular.summary}}
36
+ </div>
37
+ {% endif %}
38
+
39
+ {% if extracurricular.keywords %}
40
+ <div class="keywords">
41
+ {% for keyword in extracurricular.keywords %}
42
+ <span class="keyword tag">
43
+ {{ keyword }}
44
+ </span>
45
+ {% endfor %}
46
+ </div>
47
+ {% endif %}
48
+
49
+ </div>
50
+ {% endfor %}
51
+ </div>
52
+ </div>
53
+ {% endif %}
@@ -0,0 +1 @@
1
+ <small>Powered by <a href="https://programmercv.com">ProgrammerCV</a></small>
@@ -0,0 +1,52 @@
1
+ {% if site.data.resume.governance.size > 0 %}
2
+ <div class="row governance section" id="governance" style="page-break-inside: avoid;">
3
+ <div class="col-12">
4
+ <h2 class="section-heading">Governance</h2>
5
+
6
+ {% for governance_entry in site.data.resume.governance %}
7
+ <div class="governance_entry entry {% if governance_entry == site.data.resume.governance.last %}last{% endif %}" style="page-break-inside: avoid;">
8
+ <div class="row no-gutters title">
9
+ <div class="col-sm-6">
10
+ <h3>
11
+ {% if governance_entry.url %}
12
+ <a href="{{governance_entry.url}}">{{governance_entry.organization}}</a>
13
+ {% else %}
14
+ {{governance_entry.organization}}
15
+ {% endif %}
16
+ </h3>
17
+ </div>
18
+ <div class="col-sm-6 right">
19
+ {% capture dates %}{{ governance_entry.startDate }}{% if governance_entry.startDate.size > 0 and governance_entry.endDate.size > 0 %} - {% endif %} {{governance_entry.endDate}}{%endcapture%}
20
+ {{ dates }}
21
+ </div>
22
+ </div>
23
+
24
+ <div class="row no-gutters subtitle">
25
+ <div class="col-sm-6">
26
+ {{ governance_entry.category }}
27
+ </div>
28
+ <div class="col-sm-6 right">
29
+ </div>
30
+ </div>
31
+
32
+ {% if governance_entry.summary %}
33
+ <div class="summary">
34
+ {{governance_entry.summary}}
35
+ </div>
36
+ {% endif %}
37
+
38
+ {% if governance_entry.keywords %}
39
+ <div class="keywords">
40
+ {% for keyword in governance_entry.keywords %}
41
+ <span class="keyword tag">
42
+ {{ keyword }}
43
+ </span>
44
+ {% endfor %}
45
+ </div>
46
+ {% endif %}
47
+
48
+ </div>
49
+ {% endfor %}
50
+ </div>
51
+ </div>
52
+ {% endif %}
@@ -0,0 +1,7 @@
1
+ {% if site.data.resume.basics.image %}
2
+ <div class="row image noprint">
3
+ <div class="col-12">
4
+ <img class="profile-image" src="{{ site.data.resume.basics.image }}" />
5
+ </div>
6
+ </div>
7
+ {% endif %}
@@ -0,0 +1,23 @@
1
+ {% if site.data.resume.interests.size > 0 %}
2
+ <div class="row interests section" id="interests" style="page-break-inside: avoid;">
3
+ <div class="col-12">
4
+ <h2 class="section-heading">Interests</h2>
5
+
6
+ {% for interest in site.data.resume.interests %}
7
+ <div class="interest-entry entry {% if interest == site.data.resume.interests.last %}last{% endif %}" style="page-break-inside: avoid;">
8
+ {% if interest.name %}
9
+ <div class="name">
10
+ {{interest.name}}
11
+ </div>
12
+ {% endif %}
13
+
14
+ {% if interest.summary %}
15
+ <div class="description">
16
+ {{interest.summary}}
17
+ </div>
18
+ {% endif %}
19
+ </div>
20
+ {% endfor %}
21
+ </div>
22
+ </div>
23
+ {% endif %}
@@ -0,0 +1,22 @@
1
+ {% if site.data.resume.languages.size > 0 %}
2
+ <div class="row languages section" id="languages" style="page-break-inside: avoid;">
3
+ <div class="col-12">
4
+ <h2 class="section-heading">Languages</h2>
5
+
6
+ {% for language in site.data.resume.languages %}
7
+ <div class="language-entry {% if language == site.data.resume.languages.last %}last{% endif %}">
8
+ {% if language.language %}
9
+ <div class="language">
10
+ <strong>{{language.language}}:</strong>
11
+ {% if language.level or language.years %}
12
+ <span class="level">
13
+ {{language.level}}{% if language.years %}, {{language.years}} year(s){% endif %}
14
+ </span>
15
+ {% endif %}
16
+ </div>
17
+ {% endif %}
18
+ </div>
19
+ {% endfor %}
20
+ </div>
21
+ </div>
22
+ {% endif %}
@@ -0,0 +1,53 @@
1
+ {% if site.data.resume.openSource.size > 0 %}
2
+ <div class="row open_source section" id="open_source" style="page-break-inside: avoid;">
3
+ <div class="col-12">
4
+ <h2 class="section-heading">Open Source</h2>
5
+
6
+ {% for open_source in site.data.resume.openSource %}
7
+ <div class="open_source-entry entry {% if open_source == site.data.resume.openSource.last %}last{% endif %}" style="page-break-inside: avoid;">
8
+ <div class="row no-gutters title">
9
+ <div class="col-sm-6">
10
+ <h3>
11
+ {% if open_source.url %}
12
+ <a href="{{open_source.url}}">{{open_source.title}}</a>
13
+ {% else %}
14
+ {{open_source.title}}
15
+ {% endif %}
16
+ </h3>
17
+ </div>
18
+ <div class="col-sm-6 right">
19
+ {% capture dates %}{{ open_source.startDate }}{% if open_source.startDate.size > 0 and open_source.endDate.size > 0 %} - {% endif %} {{open_source.endDate}}{%endcapture%}
20
+ {{ dates }}
21
+ </div>
22
+ </div>
23
+
24
+ <div class="row no-gutters subtitle">
25
+ <div class="col-sm-6">
26
+ {{open_source.category}}
27
+ </div>
28
+ <div class="col-sm-6 right">
29
+ <a href="{{open_source.repo}}">{{open_source.repo}}</a>
30
+ </div>
31
+ </div>
32
+
33
+ {% if open_source.summary %}
34
+ <div class="summary">
35
+ {{open_source.summary}}
36
+ </div>
37
+ {% endif %}
38
+
39
+ {% if open_source.keywords %}
40
+ <div class="keywords">
41
+ {% for keyword in open_source.keywords %}
42
+ <span class="keyword tag">
43
+ {{ keyword }}
44
+ </span>
45
+ {% endfor %}
46
+ </div>
47
+ {% endif %}
48
+
49
+ </div>
50
+ {% endfor %}
51
+ </div>
52
+ </div>
53
+ {% endif %}