kamisaku 0.3.3 → 0.4.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.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +17 -0
  3. data/Gemfile.lock +1 -1
  4. data/README.md +28 -64
  5. data/examples/birthday_invitation/dino/invitation.pdf +0 -0
  6. data/examples/resume/chromatic/example.pdf +0 -0
  7. data/examples/resume/gradient/example.pdf +0 -0
  8. data/examples/resume/meridian/example.pdf +0 -0
  9. data/examples/resume/paper/example.pdf +0 -0
  10. data/examples/resume/prism/example.pdf +0 -0
  11. data/examples/resume/sleek/example.pdf +0 -0
  12. data/examples/resume/zenith/example.pdf +0 -0
  13. data/lib/kamisaku/arg_parser.rb +4 -0
  14. data/lib/kamisaku/cli_runner.rb +2 -2
  15. data/lib/kamisaku/content_validators/base_content_validator.rb +14 -0
  16. data/lib/kamisaku/content_validators/birthday_invitation_content_validator.rb +218 -0
  17. data/lib/kamisaku/{content_validator.rb → content_validators/resume_content_validator.rb} +28 -11
  18. data/lib/kamisaku/html_builder.rb +4 -3
  19. data/lib/kamisaku/pdf.rb +17 -12
  20. data/lib/kamisaku/template_helpers.rb +0 -2
  21. data/lib/kamisaku/version.rb +1 -1
  22. data/lib/kamisaku.rb +4 -2
  23. data/lib/schema/birthday_invitation/example.yml +45 -0
  24. data/lib/schema/birthday_invitation/schema.yml +40 -0
  25. data/lib/schema/resume/example.yml +274 -0
  26. data/lib/schema/resume/schema.yml +112 -0
  27. data/lib/templates/birthday_invitation/dino/template.html.erb +486 -0
  28. data/lib/templates/resume/chromatic/template.html.erb +275 -0
  29. data/lib/templates/resume/gradient/template.html.erb +793 -0
  30. data/lib/templates/resume/meridian/template.html.erb +535 -0
  31. data/lib/templates/resume/paper/template.html.erb +525 -0
  32. data/lib/templates/resume/prism/template.html.erb +818 -0
  33. data/lib/templates/{sleek → resume/sleek}/template.html.erb +1 -1
  34. data/lib/templates/resume/zenith/template.html.erb +546 -0
  35. data/scripts/rebuild_examples.rb +45 -0
  36. metadata +25 -9
  37. data/examples/paper/john_doe.pdf +0 -0
  38. data/examples/paper/john_doe.yml +0 -157
  39. data/examples/sleek/john_doe.pdf +0 -0
  40. data/examples/sleek/john_doe.yml +0 -157
  41. data/lib/templates/paper/template.html.erb +0 -420
  42. data/template.yml +0 -64
@@ -1,420 +0,0 @@
1
- <html>
2
- <head>
3
- <meta content="text/html; charset=UTF-8" http-equiv="content-type">
4
- <style>
5
- /* latin */
6
- @font-face {
7
- font-family: 'Cambria';
8
- font-style: normal;
9
- font-weight: 400;
10
- src: url(https://fonts.gstatic.com/l/font?kit=GFDqWAB9jnWLT-HIK7ILrphaOAw&skey=d4699178559bc4b0&v=v18) format('woff2');
11
- unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
12
- }
13
-
14
- /* latin */
15
- @font-face {
16
- font-family: 'Cambria';
17
- font-style: normal;
18
- font-weight: 700;
19
- src: url(https://fonts.gstatic.com/l/font?kit=GFDvWAB9jnWLT-HIIwkuu7V4NSY7WWA&skey=5202a3b6f5388b49&v=v18) format('woff2');
20
- unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
21
- }
22
-
23
- /* cyrillic */
24
- @font-face {
25
- font-family: 'Garamond';
26
- font-style: normal;
27
- font-weight: 400;
28
- src: url(https://fonts.gstatic.com/l/font?kit=XoHl2Y_-T6Oo88RDZSQOn9IDlDLo&skey=a3a4b3361b12223a&v=v18) format('woff2');
29
- unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
30
- }
31
-
32
- /* greek */
33
- @font-face {
34
- font-family: 'Garamond';
35
- font-style: normal;
36
- font-weight: 400;
37
- src: url(https://fonts.gstatic.com/l/font?kit=XoHl2Y_-T6Oo88RDZSQJn9IDlDLo&skey=a3a4b3361b12223a&v=v18) format('woff2');
38
- unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
39
- }
40
-
41
- /* latin-ext */
42
- @font-face {
43
- font-family: 'Garamond';
44
- font-style: normal;
45
- font-weight: 400;
46
- src: url(https://fonts.gstatic.com/l/font?kit=XoHl2Y_-T6Oo88RDZSQEn9IDlDLo&skey=a3a4b3361b12223a&v=v18) format('woff2');
47
- unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
48
- }
49
-
50
- /* latin */
51
- @font-face {
52
- font-family: 'Garamond';
53
- font-style: normal;
54
- font-weight: 400;
55
- src: url(https://fonts.gstatic.com/l/font?kit=XoHl2Y_-T6Oo88RDZSQKn9IDlDLo&skey=a3a4b3361b12223a&v=v18) format('woff2');
56
- unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
57
- }
58
-
59
- /* cyrillic */
60
- @font-face {
61
- font-family: 'Garamond';
62
- font-style: normal;
63
- font-weight: 700;
64
- src: url(https://fonts.gstatic.com/l/font?kit=XoHi2Y_-T6Oo88RDZSyxuscqtj_C8ibe&skey=66cb3cbedfd2039d&v=v18) format('woff2');
65
- unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
66
- }
67
-
68
- /* greek */
69
- @font-face {
70
- font-family: 'Garamond';
71
- font-style: normal;
72
- font-weight: 700;
73
- src: url(https://fonts.gstatic.com/l/font?kit=XoHi2Y_-T6Oo88RDZSyxuscttj_C8ibe&skey=66cb3cbedfd2039d&v=v18) format('woff2');
74
- unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
75
- }
76
-
77
- /* latin-ext */
78
- @font-face {
79
- font-family: 'Garamond';
80
- font-style: normal;
81
- font-weight: 700;
82
- src: url(https://fonts.gstatic.com/l/font?kit=XoHi2Y_-T6Oo88RDZSyxuscgtj_C8ibe&skey=66cb3cbedfd2039d&v=v18) format('woff2');
83
- unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
84
- }
85
-
86
- /* latin */
87
- @font-face {
88
- font-family: 'Garamond';
89
- font-style: normal;
90
- font-weight: 700;
91
- src: url(https://fonts.gstatic.com/l/font?kit=XoHi2Y_-T6Oo88RDZSyxuscutj_C8ibe&skey=66cb3cbedfd2039d&v=v18) format('woff2');
92
- unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
93
- }
94
-
95
- @page {
96
- margin: 0;
97
- padding: 0.5in;
98
- size: 8.3in 11.7in;
99
- }
100
-
101
- body {
102
- font-family: "Cambria", serif;
103
- color: #000;
104
- font-size: 12pt;
105
- }
106
-
107
- ul {
108
- padding-left: 20px;
109
- margin-top: 2pt;
110
- }
111
-
112
- li {
113
-
114
- }
115
-
116
- a {
117
- color: #000000;
118
- }
119
-
120
- a:link {
121
- text-decoration: none;
122
- }
123
-
124
- a:visited {
125
- text-decoration: none;
126
- }
127
-
128
- a:hover {
129
- text-decoration: none;
130
- }
131
-
132
- a:active {
133
- text-decoration: none;
134
- }
135
-
136
- .bottom-ruler {
137
- border-bottom-color: #000000;
138
- border-bottom-width: 0.8pt;
139
- padding-bottom: 2pt;
140
- border-bottom-style: solid;
141
- }
142
-
143
- .upcase {
144
- text-transform: uppercase;
145
- }
146
-
147
- .flex {
148
- display: flex;
149
- }
150
-
151
- .flex-grow {
152
- flex-grow: 1;
153
- }
154
-
155
- .sb {
156
- justify-content: space-between;
157
- }
158
-
159
- .contact-section {
160
- .name {
161
- font-size: 24pt;
162
- font-weight: 700;
163
- font-family: "Garamond";
164
- }
165
-
166
- .contact {
167
- font-size: 16pt;
168
- font-weight: 400;
169
- font-family: "Garamond";
170
-
171
- a:not(:last-child)::after {
172
- content: " |";
173
- }
174
- }
175
- }
176
-
177
- .summary {
178
- margin-top: 12pt;
179
-
180
- .section-title {
181
- font-weight: bold;
182
- }
183
-
184
- .about {
185
- color: #000000;
186
- font-weight: 400;
187
- text-decoration: none;
188
- vertical-align: baseline;
189
- font-size: 12pt;
190
- font-family: "Garamond";
191
- font-style: normal;
192
- text-align: justify;
193
- }
194
-
195
- }
196
-
197
- .work-experience {
198
- margin-top: 12pt;
199
-
200
- .section-title {
201
- font-weight: bold;
202
- }
203
-
204
- .experience {
205
- margin-top: 12pt;
206
-
207
- .organisation-name, .time-period {
208
- font-weight: 700;
209
- font-family: "Garamond";
210
- }
211
-
212
- .achievements {
213
- .achievement-item {
214
- color: #000000;
215
- font-weight: 400;
216
- text-decoration: none;
217
- vertical-align: baseline;
218
- font-size: 12pt;
219
- font-family: "Garamond";
220
- font-style: normal;
221
- text-align: justify;
222
- }
223
- }
224
-
225
- .job-title, .job-location {
226
- font-style: italic;
227
- font-weight: 400;
228
- font-family: "Garamond";
229
- }
230
- }
231
- }
232
-
233
- .education {
234
- margin-top: 12pt;
235
-
236
- .section-title {
237
- font-weight: bold;
238
- }
239
-
240
- .education-item {
241
- margin-top: 12pt;
242
-
243
- .institute-name, .time-period {
244
- font-weight: 700;
245
- font-family: "Garamond";
246
- }
247
-
248
- .qualification, .education-location {
249
- font-style: italic;
250
- font-weight: 400;
251
- font-family: "Garamond";
252
- }
253
-
254
- .achievements {
255
- .achievement-item {
256
- color: #000000;
257
- font-weight: 400;
258
- text-decoration: none;
259
- vertical-align: baseline;
260
- font-size: 12pt;
261
- font-family: "Garamond";
262
- font-style: normal;
263
- text-align: justify;
264
- }
265
- }
266
- }
267
- }
268
-
269
- .generic-section {
270
- margin-top: 12pt;
271
-
272
- .section-title {
273
- font-weight: bold;
274
- margin-bottom: 12pt;
275
- }
276
-
277
- .item {
278
- color: #000000;
279
- font-weight: 400;
280
- text-decoration: none;
281
- vertical-align: baseline;
282
- font-size: 12pt;
283
- font-family: "Garamond";
284
- }
285
- }
286
- </style>
287
- </head>
288
- <body>
289
- <% if (profile = data[:profile]) %>
290
- <div class="bottom-ruler contact-section">
291
- <div class="name bottom-ruler"><%= profile.dig(:name) %></div>
292
- <% if (contact = data[:contact]) %>
293
- <div class="contact">
294
- <% if (email = contact[:email]) %>
295
- <a href="mailto:<%= email %>"><%= email %></a>
296
- <% end %>
297
-
298
- <% if (mobile = contact[:mobile]) %>
299
- <a href="tel:<%= mobile %>"><%= mobile %></a>
300
- <% end %>
301
-
302
- <% if (city = contact.dig(:location, :city)) || (country = contact.dig(:location, :country)) %>
303
- <%= "#{city}, #{country}".strip %>
304
- <% end %>
305
-
306
- <% if (website = contact[:website]) %>
307
- <a href="<%= website %>"><%= website %></a>
308
- <% end %>
309
-
310
- <% if (github = contact[:github]) %>
311
- <a href="https://github.com/<%= github %>">github.com/<%= github %></a>
312
- <% end %>
313
-
314
- <% if (linkedin = contact[:linkedin]) %>
315
- <a href="https://linkedin.com/in/<%= linkedin %>">linkedin.com/in/<%= linkedin %></a>
316
- <% end %>
317
- </div>
318
- <% end %>
319
- </div>
320
- <div class="summary">
321
- <div class="upcase bottom-ruler section-title">Summary</div>
322
- <div class="about"><%= profile[:about] %></div>
323
- </div>
324
- <% end %>
325
-
326
- <% if (experiences = data[:experiences]) %>
327
- <div class="work-experience">
328
- <div class="upcase bottom-ruler section-title">Work Experience</div>
329
- <% experiences.each do |experience| %>
330
- <div class="experience">
331
- <div class="flex flex-grow sb">
332
- <div class="organisation-name"><%= experience[:organisation] %></div>
333
- <div class="time-period">
334
- <%= "#{month_name experience.dig(:from, :month)} #{experience.dig(:from, :year)}" %> -
335
- <%= experience[:to] ? "#{month_name experience.dig(:to, :month)} #{experience.dig(:to, :year)}" : "Present" %>
336
- </div>
337
- </div>
338
-
339
- <div class="flex flex-grow sb">
340
- <div class="job-title"><%= experience[:title] %></div>
341
- <div class="job-location">
342
- <%= "#{experience.dig(:location, :city)}, #{experience.dig(:location, :country)}" %>
343
- </div>
344
- </div>
345
-
346
- <% if (achievements = experience[:achievements]) %>
347
- <ul class="achievements">
348
- <% achievements.each do |achievement| %>
349
- <li class="achievement-item"><%= achievement %></li>
350
- <% end %>
351
- </ul>
352
- <% end %>
353
- </div>
354
- <% end %>
355
- </div>
356
- <% end %>
357
-
358
- <% if (education_list = data[:education]) %>
359
- <div class="education">
360
- <div class="upcase bottom-ruler section-title">Education</div>
361
- <% education_list.each do |education| %>
362
- <div class="education-item">
363
- <div class="flex flex-grow sb">
364
- <div class="institute-name">
365
- <%= education[:institute] %>
366
- </div>
367
- <div class="time-period">
368
- <%= education.dig(:from) ? "#{month_name education.dig(:from, :month)} #{education.dig(:from, :year)} - " : "" %>
369
- <%= education.dig(:to) ? "#{month_name education.dig(:to, :month)} #{education.dig(:to, :year)}" : "Present" %>
370
- </div>
371
- </div>
372
-
373
- <div class="flex flex-grow sb">
374
- <div class="qualification"><%= education[:qualification] %></div>
375
- <div class="education-location">
376
- <%= "#{education.dig(:location, :city)}, #{education.dig(:location, :country)}".strip %>
377
- </div>
378
- </div>
379
-
380
- <% if (achievements = education[:achievements]) %>
381
- <ul class="achievements">
382
- <% achievements.each do |achievement| %>
383
- <li class="achievement-item"><%= achievement %></li>
384
- <% end %>
385
- </ul>
386
- <% end %>
387
- </div>
388
- <% end %>
389
- </div>
390
- <% end %>
391
-
392
-
393
- <% if (generic_sections = data.slice(:skills, :interests).compact) %>
394
- <% show_subtitle = generic_sections.keys.size > 1 %>
395
- <div class="generic-section">
396
- <div class="upcase bottom-ruler section-title"><%= generic_sections.keys.map(&:capitalize).join(', ') %></div>
397
- <ul>
398
- <% if (skills = generic_sections[:skills]) %>
399
- <li class="item">
400
- <% if show_subtitle %>
401
- <b>Skills: </b>
402
- <% end %>
403
- <%= skills.flat_map { |skill| skill[:items] }.join('; ') %>
404
- </li>
405
- <% end %>
406
-
407
- <% if (interests = generic_sections[:interests]) %>
408
- <li class="item">
409
- <% if show_subtitle %>
410
- <b>Interests: </b>
411
- <% end %>
412
- <%= interests.join('; ') %>
413
- </li>
414
- <% end %>
415
- </ul>
416
- </div>
417
- <% end %>
418
-
419
- </body>
420
- </html>
data/template.yml DELETED
@@ -1,64 +0,0 @@
1
- # Template structure for CV. The content should be in YAML format.
2
- # If you are not familiar with YAML, refer: https://devhints.io/yaml
3
- #
4
- # Tip: If you already have a sample file like an exising Resume/CV PDF and you want to convert that to a YAML file based on the structure,
5
- # You could provide this template file and the PDF to an LLM like Claude.AI prompt to generate a new YAML file.
6
- # Example prompt: "Based on the given template_structure.yml file, create a resume.yml for data in Profile.pdf"
7
- #
8
-
9
- version: 1
10
- profile:
11
- name: # Your name
12
- title: # Your current job title
13
- about: # Some sleek details about your experience
14
-
15
- contact:
16
- github: # GitHub username if available, otherwise ignore
17
- mobile: # Mobile number if available, otherwise ignore
18
- email: # email address if available, otherwise ignore
19
- linkedin: # LinkedIn username if available, otherwise ignore
20
- location:
21
- country: # country name you are based at
22
- city: # city name you are based at
23
-
24
- skills:
25
- - area: # specific skill area you are specialized in
26
- items:
27
- - # sub item such as a technology you have the skill in under the specialized area
28
-
29
- experiences:
30
- - title: # job title
31
- organisation: # Name of the place you worked
32
- location:
33
- city: # city name
34
- country: # country name
35
- from:
36
- month: # month integer number that you started
37
- year: # year integer number that you started
38
- # if following is not given, it is assumed you are still working
39
- to:
40
- month: # month integer number that you stopped
41
- year: # year integer number that you stopped
42
- skills:
43
- - # a short name for a specialized skill you gained at the organization
44
- achievements: # Optional section
45
- - # Things you have achieved or did as a sentence. Consider reflecting the impact it made.
46
-
47
- education:
48
- - institute: # name of the place you studied
49
- location:
50
- city: # city name
51
- country: # country name
52
- qualification: # name of the degree/diploma qualification
53
- field: # name of the field such as Computer Science
54
- from:
55
- month: # month integer number that you started
56
- year: # year integer number that you started
57
- to: # Optional. If you have finished studying at the institute, provide this section
58
- month: # month integer number that you stopped
59
- year: # year integer number that you stopped
60
- achievements: # Optional section
61
- - # A list of things you have achieved or did at the institute.
62
-
63
- interests: # optional section
64
- - # things that are interests to you