|
27 | 27 | #let website-icon = box(fa-icon("globe", fill: color-darknight)) |
28 | 28 | #let address-icon = box(fa-icon("location-crosshairs", fill: color-darknight)) |
29 | 29 |
|
| 30 | +// const variables |
| 31 | +#let contact-item-inset = (left: 4pt) |
| 32 | + |
30 | 33 | /// Helpers |
31 | 34 |
|
32 | 35 | // Common helper functions |
|
131 | 134 | set box(height: 11pt) |
132 | 135 |
|
133 | 136 | align(right + horizon)[ |
134 | | - #fa-icon("github", fill: color-darkgray) #link( |
| 137 | + #fa-icon("github", fill: color-darkgray) #h(2pt) #link( |
135 | 138 | "https://github.com/" + github-path, |
136 | 139 | github-path, |
137 | 140 | ) |
|
186 | 189 | /// |
187 | 190 | /// - author (dictionary): Structure that takes in all the author's information |
188 | 191 | /// - profile-picture (image): The profile picture of the author. This will be cropped to a circle and should be square in nature. |
| 192 | +/// - contact-items-separator (content): Separator to use between the "contact" items in the header of the resume. This includes items like your email, website, Github account, phone number and so on. The default is blank spacing. |
189 | 193 | /// - date (string): The date the resume was created |
190 | 194 | /// - accent-color (color): The accent color of the resume |
191 | 195 | /// - colored-headers (boolean): Whether the headers should be colored or not |
|
199 | 203 | #let resume( |
200 | 204 | author: (:), |
201 | 205 | profile-picture: image, |
| 206 | + contact-items-separator: h(10pt), |
202 | 207 | date: datetime.today().display("[month repr:long] [day], [year]"), |
203 | 208 | accent-color: default-accent-color, |
204 | 209 | colored-headers: true, |
|
221 | 226 |
|
222 | 227 | let desc = if description == none { |
223 | 228 | ( |
224 | | - lflib._linguify("resume", lang: language, from: lang_data).ok |
225 | | - + " " |
226 | | - + author.firstname |
227 | | - + " " |
228 | | - + author.lastname |
| 229 | + lflib._linguify("resume", lang: language, from: lang_data).ok + " " + author.firstname + " " + author.lastname |
229 | 230 | ) |
230 | 231 | } else { |
231 | 232 | description |
|
324 | 325 | #if ("address" in author) [ |
325 | 326 | #if show-address-icon [ |
326 | 327 | #address-icon |
327 | | - #box[#text(author.address)] |
| 328 | + #box(inset: contact-item-inset)[#text(author.address)] |
328 | 329 | ] else [ |
329 | 330 | #text(author.address) |
330 | 331 | ] |
331 | 332 | ] |
332 | 333 | ] |
333 | 334 | } |
334 | 335 |
|
| 336 | + // Helper for contact items in the header. |
| 337 | + // - item (dictionary): The contact item with the following fields: text (string, required), icon (box, optional), link (string, optional) |
| 338 | + // - link-prefix (string): The prefix to use for the link (e.g. "mailto:") |
| 339 | + let contact-item(item, link-prefix: "") = { |
| 340 | + box[ |
| 341 | + #set align(bottom) |
| 342 | + #if ("icon" in item) { |
| 343 | + [#item.icon] |
| 344 | + } |
| 345 | + // Then modify the selection to use the constant: |
| 346 | + #box(inset: contact-item-inset)[ |
| 347 | + #if ("link" in item) { |
| 348 | + link(link-prefix + item.link)[#item.text] |
| 349 | + } else { |
| 350 | + item.text |
| 351 | + } |
| 352 | + ] |
| 353 | + ] |
| 354 | + } |
| 355 | + |
| 356 | + // Contact section |
335 | 357 | let contacts = { |
336 | 358 | set box(height: 9pt) |
337 | 359 | let items = () |
338 | | - |
| 360 | + |
339 | 361 | if "birth" in author { |
340 | | - items.push(box[ |
341 | | - #birth-icon |
342 | | - #box[#text(author.birth)] |
343 | | - ]) |
| 362 | + items.push( |
| 363 | + contact-item( |
| 364 | + (text: author.birth, icon: birth-icon), |
| 365 | + ), |
| 366 | + ) |
344 | 367 | } |
345 | 368 | if "phone" in author { |
346 | | - items.push(box[ |
347 | | - #phone-icon |
348 | | - #box[#link("tel:" + author.phone)[#author.phone]] |
349 | | - ]) |
| 369 | + items.push( |
| 370 | + contact-item( |
| 371 | + (text: author.phone, icon: phone-icon, link: author.phone), |
| 372 | + link-prefix: "tel:", |
| 373 | + ), |
| 374 | + ) |
350 | 375 | } |
351 | 376 | if "email" in author { |
352 | | - items.push(box[ |
353 | | - #email-icon |
354 | | - #box[#link("mailto:" + author.email)[#author.email]] |
355 | | - ]) |
| 377 | + items.push( |
| 378 | + contact-item( |
| 379 | + (text: author.email, icon: email-icon, link: author.email), |
| 380 | + link-prefix: "mailto:", |
| 381 | + ), |
| 382 | + ) |
356 | 383 | } |
357 | 384 | if "homepage" in author { |
358 | | - items.push(box[ |
359 | | - #homepage-icon |
360 | | - #box[#link(author.homepage)[#author.homepage]] |
361 | | - ]) |
| 385 | + items.push( |
| 386 | + contact-item( |
| 387 | + (text: author.homepage, icon: homepage-icon, link: author.homepage), |
| 388 | + ), |
| 389 | + ) |
362 | 390 | } |
363 | 391 | if "github" in author { |
364 | | - items.push(box[ |
365 | | - #github-icon |
366 | | - #box[#link("https://github.com/" + author.github)[#author.github]] |
367 | | - ]) |
| 392 | + items.push( |
| 393 | + contact-item( |
| 394 | + (text: author.github, icon: github-icon, link: author.github), |
| 395 | + link-prefix: "https://github.com/", |
| 396 | + ), |
| 397 | + ) |
368 | 398 | } |
369 | 399 | if "gitlab" in author { |
370 | | - items.push(box[ |
371 | | - #gitlab-icon |
372 | | - #box[#link("https://gitlab.com/" + author.gitlab)[#author.gitlab]] |
373 | | - ]) |
| 400 | + items.push( |
| 401 | + contact-item( |
| 402 | + (text: author.gitlab, icon: gitlab-icon, link: author.gitlab), |
| 403 | + link-prefix: "https://gitlab.com/", |
| 404 | + ), |
| 405 | + ) |
374 | 406 | } |
375 | 407 | if "bitbucket" in author { |
376 | | - items.push(box[ |
377 | | - #bitbucket-icon |
378 | | - #box[#link( |
379 | | - "https://bitbucket.org/" + author.bitbucket, |
380 | | - )[#author.bitbucket]] |
381 | | - ]) |
| 408 | + items.push( |
| 409 | + contact-item( |
| 410 | + (text: author.bitbucket, icon: bitbucket-icon, link: author.bitbucket), |
| 411 | + link-prefix: "https://bitbucket.org/", |
| 412 | + ), |
| 413 | + ) |
382 | 414 | } |
383 | 415 | if "linkedin" in author { |
384 | | - items.push(box[ |
385 | | - #linkedin-icon |
386 | | - #box[ |
387 | | - #link( |
388 | | - "https://www.linkedin.com/in/" + author.linkedin, |
389 | | - )[#author.firstname #author.lastname] |
390 | | - ] |
391 | | - ]) |
| 416 | + items.push( |
| 417 | + contact-item( |
| 418 | + ( |
| 419 | + text: author.firstname + " " + author.lastname, |
| 420 | + icon: linkedin-icon, |
| 421 | + link: author.linkedin, |
| 422 | + ), |
| 423 | + link-prefix: "https://www.linkedin.com/in/", |
| 424 | + ), |
| 425 | + ) |
392 | 426 | } |
393 | 427 | if "twitter" in author { |
394 | | - items.push(box[ |
395 | | - #twitter-icon |
396 | | - #box[#link( |
397 | | - "https://twitter.com/" + author.twitter, |
398 | | - )[\@#author.twitter]] |
399 | | - ]) |
| 428 | + items.push( |
| 429 | + contact-item( |
| 430 | + (text: "@" + author.twitter, icon: twitter-icon, link: author.twitter), |
| 431 | + link-prefix: "https://twitter.com/", |
| 432 | + ), |
| 433 | + ) |
400 | 434 | } |
401 | 435 | if "scholar" in author { |
402 | 436 | let fullname = str(author.firstname + " " + author.lastname) |
403 | | - items.push(box[ |
404 | | - #google-scholar-icon |
405 | | - #box[#link( |
406 | | - "https://scholar.google.com/citations?user=" + author.scholar, |
407 | | - )[#fullname]] |
408 | | - ]) |
| 437 | + items.push( |
| 438 | + contact-item( |
| 439 | + (text: fullname, icon: google-scholar-icon, link: author.scholar), |
| 440 | + link-prefix: "https://scholar.google.com/citations?user=", |
| 441 | + ), |
| 442 | + ) |
409 | 443 | } |
410 | 444 | if "orcid" in author { |
411 | | - items.push(box[ |
412 | | - #orcid-icon |
413 | | - #box[#link("https://orcid.org/" + author.orcid)[#author.orcid]] |
414 | | - ]) |
| 445 | + items.push( |
| 446 | + contact-item( |
| 447 | + (text: author.orcid, icon: orcid-icon, link: author.orcid), |
| 448 | + link-prefix: "https://orcid.org/", |
| 449 | + ), |
| 450 | + ) |
415 | 451 | } |
416 | 452 | if "website" in author { |
417 | | - items.push(box[ |
418 | | - #website-icon |
419 | | - #box[#link(author.website)[#author.website]] |
420 | | - ]) |
| 453 | + items.push( |
| 454 | + contact-item( |
| 455 | + (text: author.website, icon: website-icon, link: author.website), |
| 456 | + ), |
| 457 | + ) |
421 | 458 | } |
422 | 459 | if "custom" in author and type(author.custom) == array { |
423 | 460 | for item in author.custom { |
424 | 461 | if "text" in item { |
425 | | - items.push(box[ |
426 | | - #if ("icon" in item) { |
427 | | - box(fa-icon(item.icon, fill: color-darknight)) |
428 | | - } |
429 | | - #box[ |
430 | | - #if ("link" in item) { |
431 | | - link(item.link)[#item.text] |
432 | | - } else { |
433 | | - item.text |
434 | | - } |
435 | | - ] |
436 | | - ]) |
| 462 | + items.push( |
| 463 | + contact-item( |
| 464 | + ( |
| 465 | + text: item.text, |
| 466 | + icon: if ("icon" in item) { |
| 467 | + box(fa-icon(item.icon, fill: color-darknight)) |
| 468 | + } else { |
| 469 | + none |
| 470 | + }, |
| 471 | + link: if ("link" in item) { |
| 472 | + item.link |
| 473 | + } else { |
| 474 | + none |
| 475 | + }, |
| 476 | + ), |
| 477 | + link-prefix: "", |
| 478 | + ), |
| 479 | + ) |
437 | 480 | } |
438 | 481 | } |
439 | 482 | } |
440 | 483 |
|
441 | | - align(center+horizon)[ |
| 484 | + align(center + horizon)[ |
442 | 485 | #set text(size: 9pt, weight: "regular", style: "normal") |
443 | 486 | #block[ |
444 | | - #align(bottom)[ |
445 | | - #items.join(h(10pt)) |
| 487 | + #align(center + horizon)[ |
| 488 | + #items.join(contact-items-separator) |
446 | 489 | ] |
447 | 490 | ] |
448 | 491 | ] |
|
672 | 715 | show: body => context { |
673 | 716 | set document( |
674 | 717 | author: author.firstname + " " + author.lastname, |
675 | | - title: lflib |
676 | | - ._linguify("cover-letter", lang: language, from: lang_data) |
677 | | - .ok, |
| 718 | + title: lflib._linguify("cover-letter", lang: language, from: lang_data).ok, |
678 | 719 | description: desc, |
679 | 720 | keywords: keywords, |
680 | 721 | ) |
|
0 commit comments