Compare commits
25 commits
2024.08.03
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 03da18cacd | |||
| 5fb17b3e06 | |||
| 98ac6ab3fc | |||
| a06ad8aaab | |||
| 49243fd99e | |||
| cab11ef3af | |||
| 45743bd6df | |||
| 397bc485ec | |||
| 2ca6473869 | |||
| 34ca3c9b0e | |||
| 36b2ae610d | |||
| d395a29ca8 | |||
| 998041c97e | |||
| 1e9faa3249 | |||
| 5a8e0c1f7c | |||
| bf67c7b73f | |||
| f0a7f1de67 | |||
| 0e91c976e7 | |||
| 2b9c89378c | |||
| 4b642fbcea | |||
| 56e4da8bb9 | |||
| 339b953378 | |||
| 9a4fafe704 | |||
| ae378068c5 | |||
| af4d11b653 |
48 changed files with 718 additions and 4223 deletions
File diff suppressed because it is too large
Load diff
2
Justfile
2
Justfile
|
|
@ -1,5 +1,5 @@
|
|||
default:
|
||||
guix time-machine --channels=./channels.scm.lock -- shell --container --emulate-fhs --manifest=./manifest.scm -- typst compile ./src/main.typ ./out/resume.pdf --font-path=/usr/share/fonts
|
||||
guix time-machine --channels=./channels.scm.lock -- shell --container --emulate-fhs --manifest=./manifest.scm -- sh -c "mkdir -p ./out && typst compile ./src/document.typ ./out/resume.pdf --font-path=/usr/share/fonts --root=src"
|
||||
|
||||
fonts:
|
||||
guix time-machine --channels=./channels.scm.lock -- shell --container --emulate-fhs --manifest=./manifest.scm -- typst fonts --font-path=/usr/share/fonts
|
||||
|
|
|
|||
12
channels.scm
12
channels.scm
|
|
@ -6,4 +6,14 @@
|
|||
(make-channel-introduction
|
||||
"9edb3f66fd807b096b48283debdcddccfea34bad"
|
||||
(openpgp-fingerprint
|
||||
"BBB0 2DDF 2CEA F6A8 0D1D E643 A2A0 6DF2 A33A 54FA")))))
|
||||
"BBB0 2DDF 2CEA F6A8 0D1D E643 A2A0 6DF2 A33A 54FA"))))
|
||||
(channel
|
||||
(name 'guix-science)
|
||||
(url "https://codeberg.org/guix-science/guix-science")
|
||||
(branch "master")
|
||||
(introduction
|
||||
(make-channel-introduction
|
||||
"b1fe5aaff3ab48e798a4cce02f0212bc91f423dc"
|
||||
(openpgp-fingerprint
|
||||
"CA4F 8CF4 37D7 478F DA05 5FD4 4213 7701 1A37 8446")))))
|
||||
|
||||
|
|
|
|||
|
|
@ -3,9 +3,20 @@
|
|||
(url "https://git.savannah.gnu.org/git/guix.git")
|
||||
(branch "master")
|
||||
(commit
|
||||
"3689faac5c10249f052c979b527cba26054170d8")
|
||||
"e25cd565bf191691838702d76c764a2a3cd557d3")
|
||||
(introduction
|
||||
(make-channel-introduction
|
||||
"9edb3f66fd807b096b48283debdcddccfea34bad"
|
||||
(openpgp-fingerprint
|
||||
"BBB0 2DDF 2CEA F6A8 0D1D E643 A2A0 6DF2 A33A 54FA")))))
|
||||
"BBB0 2DDF 2CEA F6A8 0D1D E643 A2A0 6DF2 A33A 54FA"))))
|
||||
(channel
|
||||
(name 'guix-science)
|
||||
(url "https://codeberg.org/guix-science/guix-science")
|
||||
(branch "master")
|
||||
(commit
|
||||
"b9f41a281365e0681dd78ac4c756c78a5997fa30")
|
||||
(introduction
|
||||
(make-channel-introduction
|
||||
"b1fe5aaff3ab48e798a4cce02f0212bc91f423dc"
|
||||
(openpgp-fingerprint
|
||||
"CA4F 8CF4 37D7 478F DA05 5FD4 4213 7701 1A37 8446")))))
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
(add-to-load-path ".guix/modules")
|
||||
(use-modules (typst-package)
|
||||
(resume-package)
|
||||
(use-modules (resume-package)
|
||||
(font-rsms-inter-package)
|
||||
(gnu packages fontutils))
|
||||
(gnu packages fontutils)
|
||||
(guix-science packages typst))
|
||||
|
||||
(packages->manifest (list rust-typst-cli-0.11 font-rsms-inter fontconfig coreutils))
|
||||
(packages->manifest (list typst font-rsms-inter fontconfig coreutils))
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
paper: "us-letter",
|
||||
margin: (
|
||||
x: 0.5in,
|
||||
y: 0.3in,
|
||||
y: 0.4in,
|
||||
),
|
||||
body
|
||||
)
|
||||
|
|
|
|||
172
src/content.typ
Normal file
172
src/content.typ
Normal file
|
|
@ -0,0 +1,172 @@
|
|||
#let content = (
|
||||
identity: (
|
||||
name: "Ethan Reece",
|
||||
email: "contact@ethanreece.com",
|
||||
phone: "(208) 515-2094",
|
||||
location: "Richardson, TX",
|
||||
website: "linkedin.com/in/-ethanreece-"
|
||||
),
|
||||
skills: (
|
||||
(
|
||||
title: "DevOps and System Administration",
|
||||
items: (
|
||||
"Linux",
|
||||
"Git",
|
||||
"Docker",
|
||||
"Proxmox",
|
||||
"Nix",
|
||||
"Guix",
|
||||
"Terraform",
|
||||
"GitHub Actions",
|
||||
),
|
||||
),
|
||||
(
|
||||
title: "Programming Languages",
|
||||
items: (
|
||||
"JavaScript",
|
||||
"C#",
|
||||
"Rust",
|
||||
"Java",
|
||||
"C",
|
||||
"C++",
|
||||
),
|
||||
),
|
||||
(
|
||||
title: "Layout and Web Development",
|
||||
items: (
|
||||
"HTML",
|
||||
"CSS",
|
||||
"React",
|
||||
"ASP.NET",
|
||||
"Express.js",
|
||||
"Astro",
|
||||
"Typst",
|
||||
"LaTeX",
|
||||
),
|
||||
),
|
||||
),
|
||||
education: (
|
||||
(
|
||||
title: "The University of Texas at Dallas",
|
||||
degree: "Bachelor of Science in Computer Science",
|
||||
graduation: "Expected Graduation: December 2025",
|
||||
gpa: "Current GPA: 3.801",
|
||||
coursework: (
|
||||
completed: (
|
||||
"Programming Language Paradigms",
|
||||
"Digital Logic & Computer Design",
|
||||
"Operating Systems Concepts",
|
||||
"Data Structures & Algorithmic Analysis",
|
||||
"Software Engineering",
|
||||
"Systems Programming in UNIX",
|
||||
"Computer Architecture (CS 2340)",
|
||||
"Database Systems",
|
||||
"Cyber Attack & Defense Lab",
|
||||
"Computer Architecture (CS 6304)",
|
||||
"Advanced Operating Systems",
|
||||
),
|
||||
current: (
|
||||
"Design and Analysis of Computer Algorithms",
|
||||
"Computer Networks",
|
||||
"Real-Time Systems",
|
||||
),
|
||||
),
|
||||
highlights: (
|
||||
"Computer Science Fast Track Program, Systems Track",
|
||||
"Collegium V Honors Program",
|
||||
),
|
||||
),
|
||||
),
|
||||
experience: (
|
||||
(
|
||||
title: "Scrumfish Software",
|
||||
location: "Nampa, ID",
|
||||
timeframe: "June – August (2022, 2023)",
|
||||
role: "Software Engineering Intern",
|
||||
skills: (
|
||||
"C#/ASP.NET",
|
||||
"JavaScript/React",
|
||||
"Microsoft SQL Server",
|
||||
"GitHub",
|
||||
"Jira",
|
||||
),
|
||||
highlights: (
|
||||
"Developed ASP.NET APIs for data management, multifactor authentication, and document conversion.",
|
||||
"Created a React-based UI for a book critique platform, supporting document viewing, sharing, and annotation.",
|
||||
"Automated the update of email templates in the database using SQL and PowerShell scripts.",
|
||||
),
|
||||
),
|
||||
(
|
||||
title: "R-Technics",
|
||||
location: "Boise, ID",
|
||||
timeframe: "June – August (2022, 2023)",
|
||||
role: "Software Engineering Intern",
|
||||
skills: (
|
||||
"Azure",
|
||||
"Windows Server",
|
||||
"Docker",
|
||||
"C#/ASP.NET",
|
||||
),
|
||||
highlights: (
|
||||
"Supported server maintenance through update research, implementation, and monitoring.",
|
||||
"Developed a C# program to fetch song lyrics and metadata from an API, later integrated into the main product.",
|
||||
"Enhanced a server application with Docker and Linux support; established an Azure DevOps pipeline for build automation.",
|
||||
),
|
||||
),
|
||||
),
|
||||
projects: (
|
||||
(
|
||||
title: "Declarative Laptop Configuration",
|
||||
timeframe: "July 2024 – Present",
|
||||
role: "Personal Project",
|
||||
skills: (
|
||||
"Linux",
|
||||
"Guix/Guile",
|
||||
"Nix",
|
||||
"Git",
|
||||
),
|
||||
highlights: (
|
||||
"Leverage Guix and Nix to centralize my laptop user configuration for tracking history and improving maintainability.",
|
||||
"Utilize the \"time-machine\" function to ensure consistent software versions and to allow rolling back."
|
||||
),
|
||||
),
|
||||
(
|
||||
title: "Personal Server Administration",
|
||||
timeframe: "2020 – Present",
|
||||
role: "Personal Project",
|
||||
skills: (
|
||||
"Linux",
|
||||
"Docker",
|
||||
"Nix",
|
||||
"Terraform",
|
||||
"Git",
|
||||
"Proxmox",
|
||||
"Hetzner",
|
||||
"Cloudflare",
|
||||
),
|
||||
highlights: (
|
||||
"Manage a physical server using Proxmox, Debian VMs, and Docker for several applications.",
|
||||
"Host various services including Forgejo, TrueNAS, Nextcloud, and Vaultwarden.",
|
||||
"Use Terraform with NixOS, Hetzner, and Cloudflare integrations to centralize configurations for a VPN used to navigate CGNAT limitations.",
|
||||
),
|
||||
),
|
||||
(
|
||||
title: "Failure-Resistant Distributed Database System",
|
||||
timeframe: "April – May 2025",
|
||||
role: "Course Group Project",
|
||||
skills: (
|
||||
"Rust",
|
||||
"Tokio",
|
||||
"Serde",
|
||||
"Nix",
|
||||
"TCP",
|
||||
"Linux",
|
||||
"GitHub",
|
||||
),
|
||||
highlights: (
|
||||
"Implemented a basic distributed database system with an architecture similar to Amazon Dynamo, designed to tolerate a small number of server failures.",
|
||||
"Demonstrated that transaction logs remain totally ordered, even under a high load.",
|
||||
)
|
||||
),
|
||||
),
|
||||
)
|
||||
13
src/document.typ
Normal file
13
src/document.typ
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
#{
|
||||
import "content.typ": content
|
||||
import "page/resume.typ": page_resume
|
||||
|
||||
set document(
|
||||
title: "Resume",
|
||||
author: content.identity.name,
|
||||
keywords: "resume",
|
||||
date: none,
|
||||
)
|
||||
|
||||
page_resume(..content)
|
||||
}
|
||||
153
src/main.typ
153
src/main.typ
|
|
@ -1,153 +0,0 @@
|
|||
#{
|
||||
import "page_resume.typ": page_resume
|
||||
|
||||
let config = (
|
||||
identity: (
|
||||
name: "Ethan Reece",
|
||||
email: "contact@ethanreece.com",
|
||||
phone: "(208) 515-2094",
|
||||
location: "Richardson, TX",
|
||||
website: "https://ethanreece.com/"
|
||||
),
|
||||
skills: (
|
||||
(
|
||||
title: "DevOps and System Administration",
|
||||
items: (
|
||||
"Linux",
|
||||
"Git",
|
||||
"GitHub Actions",
|
||||
"Docker",
|
||||
"Guix",
|
||||
),
|
||||
),
|
||||
(
|
||||
title: "Programming Languages",
|
||||
items: (
|
||||
"JavaScript",
|
||||
"C#",
|
||||
"Java",
|
||||
"C",
|
||||
"C++",
|
||||
"Guile/Scheme",
|
||||
),
|
||||
),
|
||||
(
|
||||
title: "Layout and Web Development",
|
||||
items: (
|
||||
"HTML",
|
||||
"CSS",
|
||||
"React",
|
||||
"ASP.NET",
|
||||
"Express.js",
|
||||
"Astro",
|
||||
"Typst",
|
||||
),
|
||||
),
|
||||
),
|
||||
education: (
|
||||
(
|
||||
title: "The University of Texas at Dallas",
|
||||
degree: "Bachelor of Science in Computer Science",
|
||||
graduation: "May 2026",
|
||||
gpa: "Current GPA: 3.749",
|
||||
coursework: (
|
||||
completed: (
|
||||
"Programming Language Paradigms",
|
||||
"Digital Logic & Computer Design",
|
||||
"Operating Systems Concepts",
|
||||
"Probability and Statistics for CS",
|
||||
"Data Structures and Algorithms",
|
||||
"Software Engineering",
|
||||
"C/C++ Programming in UNIX",
|
||||
"Computer Architecture",
|
||||
"Discrete Mathematics II",
|
||||
),
|
||||
current: (
|
||||
"Database Systems",
|
||||
"Advanced Algorithm Design & Analysis",
|
||||
),
|
||||
),
|
||||
highlights: (
|
||||
"Collegium V Honors Program",
|
||||
),
|
||||
),
|
||||
),
|
||||
work_experience: (
|
||||
(
|
||||
title: "Scrumfish Software",
|
||||
location: "Nampa, ID",
|
||||
timeframe: "June – August (2022, 2023)",
|
||||
role: "Software Engineering Intern",
|
||||
skills: (
|
||||
"C#/ASP.NET",
|
||||
"JavaScript/React",
|
||||
"Microsoft SQL Server",
|
||||
"GitHub",
|
||||
),
|
||||
highlights: (
|
||||
"Developed ASP.NET APIs for data management, multifactor authentication, and document conversion.",
|
||||
"Created a React-based UI for a book critique platform, supporting document viewing, sharing, and annotation.",
|
||||
"Automated the update of email templates in the database using SQL and PowerShell scripts.",
|
||||
),
|
||||
),
|
||||
(
|
||||
title: "R-Technics",
|
||||
location: "Boise, ID",
|
||||
timeframe: "June – August (2022, 2023)",
|
||||
role: "Software Engineering Intern",
|
||||
skills: (
|
||||
"Azure",
|
||||
"Windows Server",
|
||||
"Docker",
|
||||
"C#/ASP.NET",
|
||||
),
|
||||
highlights: (
|
||||
"Supported server maintenance through update research, implementation, and monitoring.",
|
||||
"Developed a C# program to fetch song lyrics and metadata from an API, later integrated into the main product.",
|
||||
"Enhanced a server application with Docker and Linux support; established an Azure DevOps pipeline for build automation.",
|
||||
),
|
||||
),
|
||||
),
|
||||
professional_development: (
|
||||
(
|
||||
title: "Personal Server Administration",
|
||||
timeframe: "2020 – Present",
|
||||
role: "Hobby",
|
||||
skills: (
|
||||
"Linux",
|
||||
"Docker",
|
||||
"Guix/Guile",
|
||||
"Git",
|
||||
"Proxmox",
|
||||
"Google Cloud",
|
||||
),
|
||||
highlights: (
|
||||
"Manage a physical server using Proxmox, Debian VMs, and Docker for several applications.",
|
||||
"Migrate new applications to Guix to utilize declarative configuration for reduced state, fine-grained system control, and increased resource efficiency.",
|
||||
"Implement a VPN via Google Cloud Compute Engine to navigate CGNAT limitations.",
|
||||
"Host various services including Forgejo, TrueNAS, Nextcloud, and Vaultwarden.",
|
||||
),
|
||||
),
|
||||
(
|
||||
title: "Cybersecurity Courses",
|
||||
timeframe: "February 2023 – November 2023",
|
||||
role: "CodePath CYB101, CYB102",
|
||||
skills: (
|
||||
"Linux",
|
||||
),
|
||||
highlights: (
|
||||
"Gained knowledge in cybersecurity tools and defense strategies.",
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
set document(
|
||||
title: "Resume",
|
||||
author: config.identity.name,
|
||||
keywords: "resume",
|
||||
date: none,
|
||||
)
|
||||
|
||||
page_resume(..config)
|
||||
}
|
||||
64
src/page/resume.typ
Normal file
64
src/page/resume.typ
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
#let page_resume(
|
||||
identity: (
|
||||
name: "",
|
||||
email: "",
|
||||
phone: "",
|
||||
location: "",
|
||||
website: "",
|
||||
),
|
||||
skills: (
|
||||
(
|
||||
title: "",
|
||||
items: (""),
|
||||
),
|
||||
),
|
||||
education: (
|
||||
(
|
||||
title: "",
|
||||
degree: "",
|
||||
graduation: "",
|
||||
gpa: "",
|
||||
coursework: (""),
|
||||
highlights: (""),
|
||||
),
|
||||
),
|
||||
experience: (
|
||||
(
|
||||
title: "",
|
||||
location: "",
|
||||
timeframe: "",
|
||||
role: "",
|
||||
skills: (""),
|
||||
highlights: (""),
|
||||
),
|
||||
),
|
||||
projects: (
|
||||
(
|
||||
title: "",
|
||||
timeframe: "",
|
||||
role: "",
|
||||
skills: (""),
|
||||
highlights: (""),
|
||||
),
|
||||
),
|
||||
) = {
|
||||
import "../base/text.typ": base_text
|
||||
import "../base/page.typ": base_page
|
||||
import "resume/heading.typ": page_resume_heading
|
||||
import "resume/content.typ": page_resume_content
|
||||
|
||||
base_page(
|
||||
base_text(
|
||||
grid(
|
||||
gutter: 2.4em,
|
||||
page_resume_heading(identity: identity),
|
||||
page_resume_content(
|
||||
skills: skills,
|
||||
education: education,
|
||||
experience: experience,
|
||||
projects: projects,
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
50
src/page/resume/content.typ
Normal file
50
src/page/resume/content.typ
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
#let page_resume_content(
|
||||
skills: (
|
||||
(
|
||||
title: "",
|
||||
items: (""),
|
||||
),
|
||||
),
|
||||
education: (
|
||||
(
|
||||
title: "",
|
||||
degree: "",
|
||||
graduation: "",
|
||||
gpa: "",
|
||||
coursework: (""),
|
||||
highlights: (""),
|
||||
),
|
||||
),
|
||||
experience: (
|
||||
(
|
||||
title: "",
|
||||
location: "",
|
||||
timeframe: "",
|
||||
role: "",
|
||||
skills: (""),
|
||||
highlights: (""),
|
||||
),
|
||||
),
|
||||
projects: (
|
||||
(
|
||||
title: "",
|
||||
timeframe: "",
|
||||
role: "",
|
||||
skills: (""),
|
||||
highlights: (""),
|
||||
),
|
||||
),
|
||||
) = {
|
||||
import "../../section/skills.typ": section_skills
|
||||
import "../../section/education.typ": section_education
|
||||
import "../../section/experience.typ": section_experience
|
||||
import "../../section/projects.typ": section_projects
|
||||
|
||||
grid(
|
||||
gutter: 1.1em,
|
||||
section_skills(skills: skills),
|
||||
section_education(education: education),
|
||||
section_experience(experience: experience),
|
||||
section_projects(projects: projects),
|
||||
)
|
||||
}
|
||||
25
src/page/resume/heading.typ
Normal file
25
src/page/resume/heading.typ
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
#let page_resume_heading(
|
||||
identity: (
|
||||
name: "",
|
||||
email: "",
|
||||
phone: "",
|
||||
location: "",
|
||||
website: "",
|
||||
),
|
||||
) = {
|
||||
import "heading/name.typ": page_resume_heading_name
|
||||
import "heading/contact_info.typ": page_resume_heading_contact_info
|
||||
|
||||
grid(
|
||||
gutter: 1.5em,
|
||||
align: center,
|
||||
columns: 100%,
|
||||
page_resume_heading_name(name: identity.name),
|
||||
page_resume_heading_contact_info(
|
||||
email: identity.email,
|
||||
phone: identity.phone,
|
||||
location: identity.location,
|
||||
website: identity.website,
|
||||
),
|
||||
)
|
||||
}
|
||||
18
src/page/resume/heading/contact_info.typ
Normal file
18
src/page/resume/heading/contact_info.typ
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
#let page_resume_heading_contact_info(
|
||||
email: "",
|
||||
phone: "",
|
||||
location: "",
|
||||
website: "",
|
||||
) = text(
|
||||
size: 1.05em,
|
||||
weight: "medium",
|
||||
grid(
|
||||
columns: 4,
|
||||
rows: 1,
|
||||
gutter: 3em,
|
||||
email,
|
||||
phone,
|
||||
location,
|
||||
website,
|
||||
)
|
||||
)
|
||||
13
src/page/resume/heading/name.typ
Normal file
13
src/page/resume/heading/name.typ
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
#let page_resume_heading_name(name: "") = {
|
||||
import "../../../base/text.typ": base_text
|
||||
|
||||
heading(
|
||||
base_text(
|
||||
text(
|
||||
size: 2.8em,
|
||||
weight: "extrabold",
|
||||
name
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
@ -1,111 +0,0 @@
|
|||
#let page_resume(
|
||||
identity: (
|
||||
name: "",
|
||||
email: "",
|
||||
phone: "",
|
||||
location: "",
|
||||
website: "",
|
||||
),
|
||||
skills: (
|
||||
(
|
||||
title: "",
|
||||
items: (""),
|
||||
),
|
||||
),
|
||||
education: (
|
||||
(
|
||||
title: "",
|
||||
degree: "",
|
||||
graduation: "",
|
||||
gpa: "",
|
||||
coursework: (""),
|
||||
highlights: (""),
|
||||
),
|
||||
),
|
||||
work_experience: (
|
||||
(
|
||||
title: "",
|
||||
location: "",
|
||||
timeframe: "",
|
||||
role: "",
|
||||
skills: (""),
|
||||
highlights: (""),
|
||||
),
|
||||
),
|
||||
professional_development: (
|
||||
(
|
||||
title: "",
|
||||
timeframe: "",
|
||||
role: "",
|
||||
skills: (""),
|
||||
highlights: (""),
|
||||
),
|
||||
),
|
||||
) = {
|
||||
import "base/text.typ": base_text
|
||||
import "base/page.typ": base_page
|
||||
import "section/identity.typ": section_identity
|
||||
import "section/skills.typ": section_skills
|
||||
import "section/education.typ": section_education
|
||||
import "section/work_experience.typ": section_work_experience
|
||||
import "section/professional_development.typ": section_professional_development
|
||||
|
||||
let resume_content(
|
||||
skills: (
|
||||
(
|
||||
title: "",
|
||||
items: (""),
|
||||
),
|
||||
),
|
||||
education: (
|
||||
(
|
||||
title: "",
|
||||
degree: "",
|
||||
graduation: "",
|
||||
gpa: "",
|
||||
coursework: (""),
|
||||
highlights: (""),
|
||||
),
|
||||
),
|
||||
work_experience: (
|
||||
(
|
||||
title: "",
|
||||
location: "",
|
||||
timeframe: "",
|
||||
role: "",
|
||||
skills: (""),
|
||||
highlights: (""),
|
||||
),
|
||||
),
|
||||
professional_development: (
|
||||
(
|
||||
title: "",
|
||||
timeframe: "",
|
||||
role: "",
|
||||
skills: (""),
|
||||
highlights: (""),
|
||||
),
|
||||
),
|
||||
) = grid(
|
||||
gutter: 2.4em,
|
||||
section_skills(skills: skills),
|
||||
section_education(education: education),
|
||||
section_work_experience(work_experience: work_experience),
|
||||
section_professional_development(professional_development: professional_development),
|
||||
)
|
||||
|
||||
base_page(
|
||||
base_text(
|
||||
grid(
|
||||
gutter: 2.75em,
|
||||
section_identity(identity: identity),
|
||||
resume_content(
|
||||
skills: skills,
|
||||
education: education,
|
||||
work_experience: work_experience,
|
||||
professional_development: professional_development,
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
4
src/section/base/body.typ
Normal file
4
src/section/base/body.typ
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
#let section_base_body(body) = pad(
|
||||
left: 1em,
|
||||
body
|
||||
)
|
||||
|
|
@ -5,6 +5,7 @@
|
|||
title: "",
|
||||
subtitle: "",
|
||||
role: "",
|
||||
role_subtitle: "",
|
||||
timeframe: "",
|
||||
skills: (""),
|
||||
highlights: (""),
|
||||
|
|
@ -12,15 +13,10 @@
|
|||
),
|
||||
) = {
|
||||
import "small.typ": section_base_small
|
||||
import "item.typ": section_base_item
|
||||
import "items.typ": section_base_items
|
||||
|
||||
section_base_small(
|
||||
title: title,
|
||||
grid(
|
||||
gutter: 1.5em,
|
||||
for item in items {
|
||||
section_base_item(..item)
|
||||
}
|
||||
)
|
||||
section_base_items(items: items)
|
||||
)
|
||||
}
|
||||
|
|
|
|||
14
src/section/base/heading.typ
Normal file
14
src/section/base/heading.typ
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
#let section_base_heading(title: "") = {
|
||||
import "../../base/text.typ": base_text
|
||||
|
||||
heading(
|
||||
level: 2,
|
||||
base_text(
|
||||
text(
|
||||
size: 1.3em,
|
||||
weight: "bold",
|
||||
title
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
@ -2,35 +2,24 @@
|
|||
title: "",
|
||||
subtitle: "",
|
||||
role: "",
|
||||
role_subtitle: "",
|
||||
timeframe: "",
|
||||
skills: (""),
|
||||
highlights: (""),
|
||||
) = {
|
||||
import "../../base/text.typ": base_text
|
||||
import "item/header.typ": section_base_item_header
|
||||
|
||||
let item_highlights(highlights: highlights) = for highlight in highlights {
|
||||
block(
|
||||
below: 1em,
|
||||
par(
|
||||
justify: true,
|
||||
highlight
|
||||
)
|
||||
)
|
||||
}
|
||||
import "item/heading.typ": section_base_item_heading
|
||||
import "item/highlights.typ": section_base_item_highlights
|
||||
|
||||
grid(
|
||||
gutter: 0.95em,
|
||||
section_base_item_header(
|
||||
section_base_item_heading(
|
||||
title: title,
|
||||
subtitle: subtitle,
|
||||
role: role,
|
||||
role_subtitle: role_subtitle,
|
||||
timeframe: timeframe,
|
||||
skills: skills,
|
||||
),
|
||||
pad(
|
||||
left: 2em,
|
||||
item_highlights(highlights: highlights)
|
||||
)
|
||||
section_base_item_highlights(highlights: highlights)
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,66 +0,0 @@
|
|||
#let section_base_item_header(
|
||||
title: "",
|
||||
subtitle: "",
|
||||
role: "",
|
||||
timeframe: "",
|
||||
skills: (""),
|
||||
) = {
|
||||
import "../../../base/text.typ": base_text
|
||||
|
||||
let header_title(
|
||||
title: "",
|
||||
subtitle: "",
|
||||
) = grid(
|
||||
columns: 2,
|
||||
gutter: 1.5em,
|
||||
align: bottom,
|
||||
heading(
|
||||
level: 2,
|
||||
base_text(
|
||||
text(
|
||||
weight: "semibold",
|
||||
title
|
||||
)
|
||||
)
|
||||
),
|
||||
text(
|
||||
size: .9em,
|
||||
weight: "extralight",
|
||||
subtitle
|
||||
),
|
||||
)
|
||||
|
||||
grid(
|
||||
columns: 2,
|
||||
rows: 2,
|
||||
gutter: 0.75em,
|
||||
align: (
|
||||
left,
|
||||
right,
|
||||
),
|
||||
header_title(
|
||||
title: title,
|
||||
subtitle: subtitle,
|
||||
),
|
||||
block(
|
||||
width: 100%,
|
||||
text(
|
||||
weight: "regular",
|
||||
timeframe
|
||||
)
|
||||
),
|
||||
text(
|
||||
weight: "light",
|
||||
size: .95em,
|
||||
role
|
||||
),
|
||||
block(
|
||||
width: 100%,
|
||||
text(
|
||||
weight: "light",
|
||||
size: .95em,
|
||||
skills.join(", ")
|
||||
)
|
||||
),
|
||||
)
|
||||
}
|
||||
33
src/section/base/item/heading.typ
Normal file
33
src/section/base/item/heading.typ
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
#let section_base_item_heading(
|
||||
title: "",
|
||||
subtitle: "",
|
||||
role: "",
|
||||
role_subtitle: "",
|
||||
timeframe: "",
|
||||
skills: (""),
|
||||
) = {
|
||||
import "heading/title.typ": section_base_item_heading_title
|
||||
import "heading/timeframe.typ": section_base_item_heading_timeframe
|
||||
import "heading/role.typ": section_base_item_heading_role
|
||||
import "heading/skills.typ": section_base_item_heading_skills
|
||||
|
||||
grid(
|
||||
columns: 2,
|
||||
rows: 2,
|
||||
gutter: 0.6em,
|
||||
align: (
|
||||
left,
|
||||
right,
|
||||
),
|
||||
section_base_item_heading_title(
|
||||
title: title,
|
||||
subtitle: subtitle,
|
||||
),
|
||||
section_base_item_heading_timeframe(timeframe: timeframe),
|
||||
section_base_item_heading_role(
|
||||
title: role,
|
||||
subtitle: role_subtitle,
|
||||
),
|
||||
section_base_item_heading_skills(skills: skills),
|
||||
)
|
||||
}
|
||||
15
src/section/base/item/heading/role.typ
Normal file
15
src/section/base/item/heading/role.typ
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
#let section_base_item_heading_role(
|
||||
title: "",
|
||||
subtitle: "",
|
||||
) = {
|
||||
import "role/main.typ": section_base_item_heading_role_main
|
||||
import "role/subtitle.typ": section_base_item_heading_role_subtitle
|
||||
|
||||
grid(
|
||||
columns: 2,
|
||||
gutter: 1.5em,
|
||||
align: bottom,
|
||||
section_base_item_heading_role_main(title: title),
|
||||
section_base_item_heading_role_subtitle(subtitle: subtitle),
|
||||
)
|
||||
}
|
||||
5
src/section/base/item/heading/role/main.typ
Normal file
5
src/section/base/item/heading/role/main.typ
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
#let section_base_item_heading_role_main(title: "") = text(
|
||||
weight: "light",
|
||||
size: .9em,
|
||||
title
|
||||
)
|
||||
7
src/section/base/item/heading/role/subtitle.typ
Normal file
7
src/section/base/item/heading/role/subtitle.typ
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
#let section_base_item_heading_role_subtitle(
|
||||
subtitle: "",
|
||||
) = text(
|
||||
size: .85em,
|
||||
weight: "extralight",
|
||||
subtitle
|
||||
)
|
||||
10
src/section/base/item/heading/skills.typ
Normal file
10
src/section/base/item/heading/skills.typ
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
#let section_base_item_heading_skills(
|
||||
skills: ("")
|
||||
) = block(
|
||||
width: 100%,
|
||||
text(
|
||||
weight: "light",
|
||||
size: .9em,
|
||||
skills.join(", ")
|
||||
)
|
||||
)
|
||||
13
src/section/base/item/heading/timeframe.typ
Normal file
13
src/section/base/item/heading/timeframe.typ
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
#let section_base_item_heading_timeframe(
|
||||
title: "",
|
||||
subtitle: "",
|
||||
role: "",
|
||||
timeframe: "",
|
||||
skills: (""),
|
||||
) = block(
|
||||
width: 100%,
|
||||
text(
|
||||
weight: "regular",
|
||||
timeframe
|
||||
)
|
||||
)
|
||||
15
src/section/base/item/heading/title.typ
Normal file
15
src/section/base/item/heading/title.typ
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
#let section_base_item_heading_title(
|
||||
title: "",
|
||||
subtitle: "",
|
||||
) = {
|
||||
import "title/main.typ": section_base_item_heading_title_main
|
||||
import "title/subtitle.typ": section_base_item_heading_title_subtitle
|
||||
|
||||
grid(
|
||||
columns: 2,
|
||||
gutter: 1.5em,
|
||||
align: bottom,
|
||||
section_base_item_heading_title_main(title: title),
|
||||
section_base_item_heading_title_subtitle(subtitle: subtitle),
|
||||
)
|
||||
}
|
||||
13
src/section/base/item/heading/title/main.typ
Normal file
13
src/section/base/item/heading/title/main.typ
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
#let section_base_item_heading_title_main(title: "") = {
|
||||
import "../../../../../base/text.typ": base_text
|
||||
|
||||
heading(
|
||||
level: 3,
|
||||
base_text(
|
||||
text(
|
||||
weight: "semibold",
|
||||
title
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
8
src/section/base/item/heading/title/subtitle.typ
Normal file
8
src/section/base/item/heading/title/subtitle.typ
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
#let section_base_item_heading_title_subtitle(
|
||||
title: "",
|
||||
subtitle: "",
|
||||
) = text(
|
||||
size: .85em,
|
||||
weight: "extralight",
|
||||
subtitle
|
||||
)
|
||||
13
src/section/base/item/highlight.typ
Normal file
13
src/section/base/item/highlight.typ
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
#let section_base_item_highlight(
|
||||
highlight: "",
|
||||
) = text(
|
||||
size: 0.95em,
|
||||
if type(highlight) == str {
|
||||
par(
|
||||
justify: true,
|
||||
highlight
|
||||
)
|
||||
} else {
|
||||
highlight
|
||||
}
|
||||
)
|
||||
17
src/section/base/item/highlights.typ
Normal file
17
src/section/base/item/highlights.typ
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
#let section_base_item_highlights(
|
||||
highlights: (""),
|
||||
) = {
|
||||
import "highlight.typ": section_base_item_highlight
|
||||
import "marker.typ": section_base_item_marker
|
||||
|
||||
list(
|
||||
marker: section_base_item_marker,
|
||||
indent: 0.25em,
|
||||
body-indent: 1.5em,
|
||||
tight: false,
|
||||
spacing: 0.85em,
|
||||
..highlights.map(highlight =>
|
||||
section_base_item_highlight(highlight: highlight)
|
||||
)
|
||||
)
|
||||
}
|
||||
5
src/section/base/item/marker.typ
Normal file
5
src/section/base/item/marker.typ
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
#let section_base_item_marker = text(
|
||||
weight: "extralight",
|
||||
size: 0.95em,
|
||||
sym.dash.en
|
||||
)
|
||||
21
src/section/base/items.typ
Normal file
21
src/section/base/items.typ
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
#let section_base_items(
|
||||
items: (
|
||||
(
|
||||
title: "",
|
||||
subtitle: "",
|
||||
role: "",
|
||||
timeframe: "",
|
||||
skills: (""),
|
||||
highlights: (""),
|
||||
),
|
||||
),
|
||||
) = {
|
||||
import "item.typ": section_base_item
|
||||
|
||||
grid(
|
||||
gutter: 1.5em,
|
||||
for item in items {
|
||||
section_base_item(..item)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
@ -2,22 +2,12 @@
|
|||
title: "",
|
||||
body
|
||||
) = {
|
||||
import "../../base/text.typ": base_text
|
||||
import "heading.typ": section_base_heading
|
||||
import "body.typ": section_base_body
|
||||
|
||||
grid(
|
||||
gutter: 1.1em,
|
||||
heading(
|
||||
base_text(
|
||||
text(
|
||||
size: 1.3em,
|
||||
weight: "bold",
|
||||
title
|
||||
)
|
||||
)
|
||||
),
|
||||
pad(
|
||||
left: 1em,
|
||||
body
|
||||
)
|
||||
gutter: 0.8em,
|
||||
section_base_heading(title: title),
|
||||
section_base_body(body),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,8 +19,8 @@
|
|||
section_base_full(
|
||||
title: "Education",
|
||||
items: education.map(school => (
|
||||
title: school.title,
|
||||
role: school.degree,
|
||||
title: school.degree,
|
||||
role: school.title,
|
||||
timeframe: school.graduation,
|
||||
skills: (
|
||||
school.gpa,
|
||||
|
|
|
|||
|
|
@ -2,46 +2,15 @@
|
|||
completed: (""),
|
||||
current: (""),
|
||||
) = {
|
||||
let coursework_content(
|
||||
completed: (""),
|
||||
current: (""),
|
||||
) = grid(
|
||||
columns: 2,
|
||||
rows: 2,
|
||||
gutter: 1em,
|
||||
text(
|
||||
weight: "regular",
|
||||
"Completed",
|
||||
),
|
||||
text(
|
||||
weight: "light",
|
||||
completed.join(", "),
|
||||
),
|
||||
text(
|
||||
weight: "regular",
|
||||
"Current",
|
||||
),
|
||||
text(
|
||||
weight: "light",
|
||||
current.join(", "),
|
||||
),
|
||||
)
|
||||
import "coursework/heading.typ": section_education_coursework_heading
|
||||
import "coursework/content.typ": section_education_coursework_content
|
||||
|
||||
grid(
|
||||
gutter: .95em,
|
||||
text(
|
||||
weight: "medium",
|
||||
"Relevant Coursework"
|
||||
),
|
||||
pad(
|
||||
left: 1.5em,
|
||||
text(
|
||||
size: .95em,
|
||||
coursework_content(
|
||||
completed: completed,
|
||||
current: current,
|
||||
)
|
||||
)
|
||||
section_education_coursework_heading(),
|
||||
section_education_coursework_content(
|
||||
completed: completed,
|
||||
current: current,
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
|
|||
26
src/section/education/coursework/content.typ
Normal file
26
src/section/education/coursework/content.typ
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
#let section_education_coursework_content(
|
||||
completed: (""),
|
||||
current: (""),
|
||||
) = {
|
||||
import "content/section.typ": section_education_coursework_content_section
|
||||
|
||||
pad(
|
||||
left: 1.5em,
|
||||
text(
|
||||
size: .95em,
|
||||
grid(
|
||||
columns: 2,
|
||||
rows: 2,
|
||||
gutter: 1em,
|
||||
..section_education_coursework_content_section(
|
||||
title: "Completed",
|
||||
list: completed,
|
||||
),
|
||||
..section_education_coursework_content_section(
|
||||
title: "Current",
|
||||
list: current,
|
||||
),
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
12
src/section/education/coursework/content/section.typ
Normal file
12
src/section/education/coursework/content/section.typ
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
#let section_education_coursework_content_section(
|
||||
title: "",
|
||||
list: (""),
|
||||
) = {
|
||||
import "section/heading.typ": section_education_coursework_content_section_heading
|
||||
import "section/content.typ": section_education_coursework_content_section_content
|
||||
|
||||
(
|
||||
section_education_coursework_content_section_heading(title: title),
|
||||
section_education_coursework_content_section_content(list: list),
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
#let section_education_coursework_content_section_content(
|
||||
list: (""),
|
||||
) = text(
|
||||
weight: "light",
|
||||
par(
|
||||
justify: true,
|
||||
list.join(", ")
|
||||
)
|
||||
)
|
||||
13
src/section/education/coursework/content/section/heading.typ
Normal file
13
src/section/education/coursework/content/section/heading.typ
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
#let section_education_coursework_content_section_heading(title: "") = {
|
||||
import "../../../../../base/text.typ": base_text
|
||||
|
||||
heading(
|
||||
level: 5,
|
||||
base_text(
|
||||
text(
|
||||
weight: "regular",
|
||||
title,
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
13
src/section/education/coursework/heading.typ
Normal file
13
src/section/education/coursework/heading.typ
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
#let section_education_coursework_heading() = {
|
||||
import "../../../base/text.typ": base_text
|
||||
|
||||
heading(
|
||||
level: 4,
|
||||
base_text(
|
||||
text(
|
||||
weight: "medium",
|
||||
"Relevant Coursework"
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
#let section_work_experience(
|
||||
work_experience: (
|
||||
#let section_experience(
|
||||
experience: (
|
||||
(
|
||||
title: "",
|
||||
location: "",
|
||||
|
|
@ -13,12 +13,12 @@
|
|||
import "base/full.typ": section_base_full
|
||||
|
||||
section_base_full(
|
||||
title: "Work Experience",
|
||||
items: work_experience.map(company => (
|
||||
title: company.title,
|
||||
subtitle: company.location,
|
||||
title: "Experience",
|
||||
items: experience.map(company => (
|
||||
title: company.role,
|
||||
timeframe: company.timeframe,
|
||||
role: company.role,
|
||||
role: company.title,
|
||||
role_subtitle: company.location,
|
||||
skills: company.skills,
|
||||
highlights: company.highlights,
|
||||
)),
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
#let section_identity(
|
||||
identity: (
|
||||
name: "",
|
||||
email: "",
|
||||
phone: "",
|
||||
location: "",
|
||||
website: "",
|
||||
),
|
||||
) = {
|
||||
let title(title: "") = text(
|
||||
size: 2.8em,
|
||||
weight: "extrabold",
|
||||
title
|
||||
)
|
||||
|
||||
let contact_info(
|
||||
email: "",
|
||||
phone: "",
|
||||
location: "",
|
||||
website: "",
|
||||
) = text(
|
||||
size: 1.05em,
|
||||
weight: "medium",
|
||||
grid(
|
||||
columns: 4,
|
||||
rows: 1,
|
||||
gutter: 4em,
|
||||
email,
|
||||
phone,
|
||||
location,
|
||||
website,
|
||||
)
|
||||
)
|
||||
|
||||
grid(
|
||||
gutter: 1.5em,
|
||||
align: center,
|
||||
title(title: identity.name),
|
||||
contact_info(
|
||||
email: identity.email,
|
||||
phone: identity.phone,
|
||||
location: identity.location,
|
||||
website: identity.website,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
#let section_professional_development(
|
||||
professional_development: (
|
||||
#let section_projects(
|
||||
projects: (
|
||||
(
|
||||
title: "",
|
||||
timeframe: "",
|
||||
|
|
@ -12,8 +12,8 @@
|
|||
import "base/full.typ": section_base_full
|
||||
|
||||
section_base_full(
|
||||
title: "Professional Development",
|
||||
items: professional_development.map(item => (
|
||||
title: "Projects",
|
||||
items: projects.map(item => (
|
||||
title: item.title,
|
||||
timeframe: item.timeframe,
|
||||
role: item.role,
|
||||
|
|
@ -6,8 +6,8 @@
|
|||
),
|
||||
),
|
||||
) = {
|
||||
import "../base/text.typ": base_text
|
||||
import "base/small.typ": section_base_small
|
||||
import "skills/section.typ": section_skills_section
|
||||
|
||||
section_base_small(
|
||||
title: "Skills",
|
||||
|
|
@ -15,18 +15,7 @@
|
|||
columns: 2,
|
||||
gutter: 1em,
|
||||
..for skill in skills {
|
||||
(
|
||||
heading(
|
||||
level: 2,
|
||||
base_text(
|
||||
text(
|
||||
weight: "semibold",
|
||||
skill.title
|
||||
)
|
||||
)
|
||||
),
|
||||
skill.items.join(", "),
|
||||
)
|
||||
section_skills_section(..skill)
|
||||
}
|
||||
)
|
||||
)
|
||||
|
|
|
|||
12
src/section/skills/section.typ
Normal file
12
src/section/skills/section.typ
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
#let section_skills_section(
|
||||
title: "",
|
||||
items: (""),
|
||||
) = {
|
||||
import "section/heading.typ": section_skills_section_heading
|
||||
import "section/content.typ": section_skills_section_content
|
||||
|
||||
(
|
||||
section_skills_section_heading(title: title),
|
||||
section_skills_section_content(items: items),
|
||||
)
|
||||
}
|
||||
6
src/section/skills/section/content.typ
Normal file
6
src/section/skills/section/content.typ
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
#let section_skills_section_content(
|
||||
items: (""),
|
||||
) = text(
|
||||
size: 0.95em,
|
||||
items.join(", ")
|
||||
)
|
||||
14
src/section/skills/section/heading.typ
Normal file
14
src/section/skills/section/heading.typ
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
#let section_skills_section_heading(title: "") = {
|
||||
import "../../../base/text.typ": base_text
|
||||
|
||||
heading(
|
||||
level: 3,
|
||||
base_text(
|
||||
text(
|
||||
weight: "semibold",
|
||||
size: 0.95em,
|
||||
title
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
Reference in a new issue