Compare commits
No commits in common. "502749c838ccd5f9021bfd23f4d7234b8b80c44f" and "493193872f85ebfe51e83eb017f693bcb42cfcea" have entirely different histories.
502749c838
...
493193872f
6 changed files with 644 additions and 666 deletions
950
Cargo.lock
generated
950
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
14
Cargo.toml
14
Cargo.toml
|
@ -2,13 +2,13 @@
|
||||||
name = "panres"
|
name = "panres"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
authors = ["Edward Shen <code@eddie.sh>"]
|
authors = ["Edward Shen <code@eddie.sh>"]
|
||||||
edition = "2021"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
tera = "1"
|
tera = "1.0.0-beta.13"
|
||||||
clap = { version = "3", features = ["derive", "cargo"] }
|
clap = "2"
|
||||||
serde = "1"
|
serde = "1"
|
||||||
serde_json = "1"
|
serde_json = "1.0"
|
||||||
json5 = "0.4"
|
json5 = "0.2.8"
|
||||||
notify = "5.0.0-pre.15"
|
notify = "5.0.0-pre.3"
|
||||||
crossbeam = "0.8"
|
crossbeam = "0.7"
|
||||||
|
|
105
config.json5
105
config.json5
|
@ -2,10 +2,10 @@
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Edward Shen",
|
"name": "Edward Shen",
|
||||||
"addresses": {
|
"addresses": {
|
||||||
"home": "550 Moreland Way Apt 4410, Santa Clara, CA 95054",
|
"home": "8080 Highland Farms Drive, East Amherst, NY 14051",
|
||||||
"school": "480 Parker Street, Boston, MA 02115"
|
"school": "480 Parker Street, Boston, MA 02115"
|
||||||
},
|
},
|
||||||
"email": "hi@eddie.sh",
|
"email": "code@eddie.sh",
|
||||||
"phone": "(716) 491-3343",
|
"phone": "(716) 491-3343",
|
||||||
"website": "eddie.sh",
|
"website": "eddie.sh",
|
||||||
"github": "edward-shen",
|
"github": "edward-shen",
|
||||||
|
@ -19,17 +19,22 @@
|
||||||
"school": "Northeastern University",
|
"school": "Northeastern University",
|
||||||
"college": "Khoury College of Computer Sciences",
|
"college": "Khoury College of Computer Sciences",
|
||||||
"location": "Boston, MA",
|
"location": "Boston, MA",
|
||||||
"start": "Sep. 2017",
|
"start": "Sept. 2017",
|
||||||
"end_date": "May 2021",
|
"end": "Present",
|
||||||
|
"end_date": "Present (May 2021)",
|
||||||
"list": [
|
"list": [
|
||||||
{
|
{
|
||||||
"name": "degree",
|
"name": "degree",
|
||||||
"desc": "Bachelor of Science in Computer Science"
|
"desc": "Candidate for a Bachelor of Science in Computer Science"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "honors",
|
"name": "honors",
|
||||||
"desc": "3.85 / 4.00; summa cum laude; Dean's List"
|
"desc": "3.84 / 4.00, Dean's List"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "courses",
|
||||||
|
"desc": "Data Collection, Integration, and Analysis; Machine Learning/Data Mining 1; Algorithms and Data; Object-Oriented Design; Networks and Distributed Systems"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"skills": [
|
"skills": [
|
||||||
|
@ -37,82 +42,63 @@
|
||||||
"name": "languages",
|
"name": "languages",
|
||||||
"desc": [
|
"desc": [
|
||||||
{
|
{
|
||||||
"level": "primary",
|
"level": "proficient",
|
||||||
"langs": "Rust",
|
"langs": "Rust, Python, TypeScript, HTML5, CSS"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"level": "secondary",
|
"level": "familiar",
|
||||||
"langs": "Python, Bash",
|
"langs": "JavaScript, Java, LaTeX, C++, Bash"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"level": "auxiliary",
|
"level": "explored",
|
||||||
"langs": "C, C++, TypeScript",
|
"langs": "C, Ruby, Racket, Scala"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "recent technology",
|
"name": "other",
|
||||||
"desc": "cxx.rs, libc, fbthrift, cgroups v2",
|
"desc": "Git, (Arch) Linux, VS Code, Raspberry Pi"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "miscellaneous",
|
"name": "certs",
|
||||||
"desc": "Regex, LaTeX"
|
"desc": "CompTIA A+, Dell Certified Technician, Apple Certified Mac Technician"
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "interests",
|
|
||||||
"desc": "Rhythm games; Self-hosting; Security; Scalability; Free software",
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"experiences": [
|
"experiences": [
|
||||||
{
|
// {
|
||||||
"title": "Production Engineer",
|
// "title": "Software Development Engineer Intern",
|
||||||
"company": "Meta",
|
// "company": "Apple",
|
||||||
"location": "Menlo Park, CA",
|
// "location": "Menlo Park, CA",
|
||||||
"start": "Sep. 2021",
|
// "start": "Aug. 2020",
|
||||||
"end": "Present",
|
// "end": "Dec. 2020",
|
||||||
"notes": [
|
// "notes": [
|
||||||
"Joined the PE Executable Access Control team to identify, track, and jail untrusted binaries running on internal hosts.",
|
// "sekureetee"
|
||||||
"Tech lead for Alcatraz, an internal binary that presents common frontend for process-level jailing backends.",
|
// ]
|
||||||
"Advocate for Rust adoption, volunteering for Rust code reviews and presenting Rust talks to teams.",
|
// },
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "SEAR Intern",
|
|
||||||
"company": "Apple",
|
|
||||||
"location": "Cupertino, CA",
|
|
||||||
"remote": true,
|
|
||||||
"start": "Aug. 2020",
|
|
||||||
"end": "Dec. 2020",
|
|
||||||
"notes": [
|
|
||||||
"Joined the Trusted Execution team, focused on code execution across the Apple ecosystem.",
|
|
||||||
"Planned, driven, and completed proof-of-concept for iOS 16's Lockdown Mode.",
|
|
||||||
"Developed kernel and bootloader security policies focused on attack surface reduction.",
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"title": "Production Engineer Intern",
|
"title": "Production Engineer Intern",
|
||||||
"company": "Facebook",
|
"company": "Facebook",
|
||||||
"location": "Menlo Park, CA",
|
"location": "Menlo Park, CA",
|
||||||
"remote": true,
|
|
||||||
"start": "May 2020",
|
"start": "May 2020",
|
||||||
"end": "Aug. 2020",
|
"end": "Aug. 2020",
|
||||||
"notes": [
|
"notes": [
|
||||||
"Rewritten Python config generation in multithreaded asynchronous Rust, reducing overall runtime by 80\\% on large inputs and improving runtime of profiled areas by a factor of 36.6.",
|
"Rewritten Python config generation in multithreaded asynchronous Rust, reducing overall runtime by 80\\% on large inputs and improving runtime of profiled areas by a factor of 36.6.",
|
||||||
"Designed core Rust libraries for foundational services for ubiquitous use across all Rust applications.",
|
"Designed core Rust libraries for foundational services for ubiquitous use across all Rust applications.",
|
||||||
"Highlighted as a top intern project for the Production Engineering organization."
|
"Detected and resolved soundness issues and misconfigurations in existing python code to preempt Severity 1 site events."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Software Engineer Intern",
|
||||||
|
"company": "Datto",
|
||||||
|
"location": "Boston, MA",
|
||||||
|
"start": "Aug. 2019",
|
||||||
|
"end": "Dec. 2019",
|
||||||
|
"notes": [
|
||||||
|
"Refactored frontend codebase to utilize Typescript, Webpack, and Babel while reducing average JS footprint by 98\\% percent, from 10.4MB to 250KB.",
|
||||||
|
"Assisted and completed developer environment virtualization project to reduce onboarding time for new developers by 5 days.",
|
||||||
|
"Integrated into Scrum team that focused on re-implementation of license management systems in a legacy Ruby codebase to Scala and PHP."
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
// {
|
|
||||||
// "title": "Software Engineer Intern",
|
|
||||||
// "company": "Datto",
|
|
||||||
// "location": "Boston, MA",
|
|
||||||
// "start": "Aug. 2019",
|
|
||||||
// "end": "Dec. 2019",
|
|
||||||
// "notes": [
|
|
||||||
// "Refactored frontend codebase to utilize Typescript, Webpack, and Babel while reducing average JS footprint by 98\\% percent, from 10.4MB to 250KB.",
|
|
||||||
// "Integrated into Scrum team that focused on re-implementation of license management systems in a legacy Ruby codebase to Scala and PHP."
|
|
||||||
// ]
|
|
||||||
// },
|
|
||||||
{
|
{
|
||||||
"title": "Production Engineer Intern",
|
"title": "Production Engineer Intern",
|
||||||
"company": "Facebook",
|
"company": "Facebook",
|
||||||
|
@ -121,7 +107,8 @@
|
||||||
"end": "Aug. 2019",
|
"end": "Aug. 2019",
|
||||||
"notes": [
|
"notes": [
|
||||||
"Implemented a disaster mitigation for decentralized service discovery when upstream data source is unavailable or in a degraded state.",
|
"Implemented a disaster mitigation for decentralized service discovery when upstream data source is unavailable or in a degraded state.",
|
||||||
"Designed an out-of-band flow to resolve core infrastructure services dependent on service discovery in disaster scenarios to minimize downtime for all Facebook products.",
|
"Designed an out-of-band flow to allow resolution of core infrastructure services dependent on service discovery in disaster scenarios to minimize downtime for all Facebook products.",
|
||||||
|
"Modernized and restructured core tooling to improve reliability and testing."
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
64
src/main.rs
64
src/main.rs
|
@ -1,14 +1,13 @@
|
||||||
#![forbid(unsafe_code)]
|
#![forbid(unsafe_code)]
|
||||||
|
|
||||||
use clap::{crate_authors, crate_version, Parser};
|
use clap::{crate_authors, crate_version, App, AppSettings, Arg};
|
||||||
use crossbeam::channel::unbounded;
|
use crossbeam::crossbeam_channel::unbounded;
|
||||||
use json5::from_str;
|
use json5::from_str;
|
||||||
use notify::{RecommendedWatcher, RecursiveMode, Watcher};
|
use notify::{RecommendedWatcher, RecursiveMode, Watcher};
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::fs::{create_dir_all, read_dir, read_to_string, write};
|
use std::fs::{create_dir_all, read_dir, read_to_string, write};
|
||||||
use std::path::{Path, PathBuf};
|
|
||||||
use std::process;
|
use std::process;
|
||||||
use tera::{Context, Error as TeraError, Tera};
|
use tera::{Context, Error as TeraError, Tera};
|
||||||
|
|
||||||
|
@ -29,51 +28,60 @@ fn env_or_default(env_name: &str, default: &str) -> String {
|
||||||
env::var(env_name).unwrap_or_else(|_| String::from(default))
|
env::var(env_name).unwrap_or_else(|_| String::from(default))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Universal resume formatter
|
|
||||||
#[derive(Parser)]
|
|
||||||
#[clap(version = crate_version!(), author = crate_authors!())]
|
|
||||||
struct Args {
|
|
||||||
/// Watch for changes
|
|
||||||
#[clap(short)]
|
|
||||||
watch: bool,
|
|
||||||
/// Specifies which output format you want
|
|
||||||
#[clap(short, long, multiple_occurrences = true)]
|
|
||||||
output: Vec<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn run() -> Result<(), Box<dyn Error>> {
|
fn run() -> Result<(), Box<dyn Error>> {
|
||||||
let config: Value = from_str(&read_to_string("config.json5")?)?;
|
let config: Value = from_str(&read_to_string("config.json5")?)?;
|
||||||
let template_dir = env_or_default("PANRES_TEMPLATE_DIR", DEFAULT_TEMPLATE_DIR);
|
let template_dir = env_or_default("PANRES_TEMPLATE_DIR", DEFAULT_TEMPLATE_DIR);
|
||||||
let output_dir = env_or_default("PANRES_OUTPUT_DIR", DEFAULT_OUTPUT_DIR);
|
let output_dir = env_or_default("PANRES_OUTPUT_DIR", DEFAULT_OUTPUT_DIR);
|
||||||
|
|
||||||
let args = Args::parse();
|
let matches = get_args();
|
||||||
|
|
||||||
let tera = Tera::new(&format!("{template_dir}/**/*"))?;
|
let tera = Tera::new(&format!("{}/**/*", template_dir))?;
|
||||||
let mut context = Context::new();
|
let mut context = Context::new();
|
||||||
context.insert("config", &config);
|
context.insert("config", &config);
|
||||||
let template_dir = PathBuf::from(template_dir);
|
let outputs: Vec<String> = matches
|
||||||
|
.values_of("output-format")
|
||||||
|
.unwrap_or_default()
|
||||||
|
.map(String::from)
|
||||||
|
.collect();
|
||||||
|
|
||||||
output(&tera, &context, &output_dir, &args.output, &template_dir)?;
|
output(&tera, &context, &output_dir, &outputs, &template_dir)?;
|
||||||
|
|
||||||
if args.watch {
|
if matches.is_present("watch") {
|
||||||
watch_mode(tera, context, output_dir, args.output, &template_dir)?;
|
watch_mode(tera, context, output_dir, outputs, template_dir)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the args passed by the user.
|
||||||
|
fn get_args() -> clap::ArgMatches<'static> {
|
||||||
|
App::new("panres")
|
||||||
|
.version(crate_version!())
|
||||||
|
.author(crate_authors!())
|
||||||
|
.about("Universal resume formatter")
|
||||||
|
.arg(Arg::with_name("watch").short("w").help("Watch for changes"))
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("output-format")
|
||||||
|
.help("Specifies which output format you want")
|
||||||
|
.required(true)
|
||||||
|
.multiple(true),
|
||||||
|
)
|
||||||
|
.settings(&[AppSettings::ArgRequiredElseHelp])
|
||||||
|
.get_matches()
|
||||||
|
}
|
||||||
|
|
||||||
/// Usually never returns, unless there was an error initializing the watcher.
|
/// Usually never returns, unless there was an error initializing the watcher.
|
||||||
/// Handles watching for file changes, and reloads tera if there's a change.
|
/// Handles watching for file changes, and reloads tera if there's a change.
|
||||||
fn watch_mode(
|
fn watch_mode<'a>(
|
||||||
mut engine: Tera,
|
mut engine: Tera,
|
||||||
context: Context,
|
context: Context,
|
||||||
dir: String,
|
dir: String,
|
||||||
outputs: Vec<String>,
|
outputs: Vec<String>,
|
||||||
template_dir: &Path,
|
template_dir: String,
|
||||||
) -> Result<(), Box<dyn Error>> {
|
) -> Result<(), Box<dyn Error>> {
|
||||||
let (tx, rx) = unbounded();
|
let (tx, rx) = unbounded();
|
||||||
let mut watcher: RecommendedWatcher = Watcher::new(move |res| tx.send(res).unwrap())?;
|
let mut watcher: RecommendedWatcher = Watcher::new_immediate(move |res| tx.send(res).unwrap())?;
|
||||||
watcher.watch(template_dir, RecursiveMode::Recursive)?;
|
watcher.watch(&template_dir, RecursiveMode::Recursive)?;
|
||||||
|
|
||||||
for res in rx {
|
for res in rx {
|
||||||
match res {
|
match res {
|
||||||
|
@ -81,7 +89,7 @@ fn watch_mode(
|
||||||
Ok(event) => {
|
Ok(event) => {
|
||||||
println!("got event {:?}", event);
|
println!("got event {:?}", event);
|
||||||
engine.full_reload().expect("Failed to perform full reload");
|
engine.full_reload().expect("Failed to perform full reload");
|
||||||
output(&engine, &context, &dir, &outputs, template_dir)
|
output(&engine, &context, &dir, &outputs, &template_dir)
|
||||||
.expect("Failed to call output");
|
.expect("Failed to call output");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -92,12 +100,12 @@ fn watch_mode(
|
||||||
|
|
||||||
/// Parses the output values and generates a file for each format specified or
|
/// Parses the output values and generates a file for each format specified or
|
||||||
/// found, if told to generate all outputs.
|
/// found, if told to generate all outputs.
|
||||||
fn output(
|
fn output<'a>(
|
||||||
engine: &Tera,
|
engine: &Tera,
|
||||||
context: &Context,
|
context: &Context,
|
||||||
dir: &str,
|
dir: &str,
|
||||||
outputs: &[String],
|
outputs: &[String],
|
||||||
template_dir: &Path,
|
template_dir: &'a str,
|
||||||
) -> Result<(), Box<dyn Error>> {
|
) -> Result<(), Box<dyn Error>> {
|
||||||
if outputs.contains(&String::from("all")) {
|
if outputs.contains(&String::from("all")) {
|
||||||
for output in read_dir(template_dir)? {
|
for output in read_dir(template_dir)? {
|
||||||
|
|
173
templates/latex
173
templates/latex
|
@ -9,7 +9,6 @@
|
||||||
\usepackage{multirow}
|
\usepackage{multirow}
|
||||||
\usepackage{colortbl} % Colored table vlines
|
\usepackage{colortbl} % Colored table vlines
|
||||||
\usepackage{graphicx} % Rotate text
|
\usepackage{graphicx} % Rotate text
|
||||||
\usepackage[hidelinks]{hyperref} % Clickable PDF URLs
|
|
||||||
|
|
||||||
% macros which are illegal in .sty (primarily just font awesome stuff)
|
% macros which are illegal in .sty (primarily just font awesome stuff)
|
||||||
|
|
||||||
|
@ -23,111 +22,93 @@
|
||||||
|
|
||||||
\setmainfont{Corbert}
|
\setmainfont{Corbert}
|
||||||
% Set up table styles
|
% Set up table styles
|
||||||
\arrayrulecolor{AccentColor}
|
\arrayrulecolor{red}
|
||||||
\setlength\arrayrulewidth{1.2pt}
|
\setlength\arrayrulewidth{1.2pt}
|
||||||
\begin{tabularx}{\textwidth}{X c l}
|
\begin{tabularx}{\textwidth}{X c l}
|
||||||
\multirow[b]{3}{*}{\name}
|
\multirow[b]{3}{*}{\name}
|
||||||
& \accent{\glyph{"F0AC}} & \href{
|
& \accent{\glyph{"F0AC}} & {{ config.author.website }} \\
|
||||||
https://{{ config.author.website }}
|
& \accent{\glyph{"F003}} & {{ config.author.email }} \\
|
||||||
}{
|
& \accent{\glyph{"F09B}} & {{ config.author.github }}
|
||||||
{{ config.author.website }}
|
|
||||||
}\\
|
|
||||||
& \accent{\glyph{"F003}} & \href{
|
|
||||||
mailto:{{ config.author.email }}
|
|
||||||
}{
|
|
||||||
{{ config.author.email }}
|
|
||||||
} \\
|
|
||||||
& \accent{\glyph{"F09B}} & \href {
|
|
||||||
https://github.com/{{ config.author.github }}
|
|
||||||
}{
|
|
||||||
{{ config.author.github }}
|
|
||||||
}
|
|
||||||
\end{tabularx}
|
\end{tabularx}
|
||||||
|
|
||||||
% Contact info
|
% Contact info
|
||||||
|
|
||||||
\begin{tabularx}{\textwidth}{c X c}
|
\begin{tabularx}{\textwidth}{ c | r X r }
|
||||||
{
|
\sectiontitle{Education} \\[-8pt]
|
||||||
|
{% raw -%}
|
||||||
|
& \widel{ {\large\title{%
|
||||||
|
{% endraw -%}
|
||||||
|
{{ config.education.school }}}}\hint{ {{ config.education.location }}}} & {{ config.education.start }}---{{ config.education.end_date }} \\
|
||||||
|
& \widel{\footnotesize {{ config.education.college }}} \\
|
||||||
|
{% for row in config.education.list -%}
|
||||||
|
{% raw -%}
|
||||||
|
& \hint{%
|
||||||
|
{% endraw -%}
|
||||||
|
{{ row.name | title }}:} &
|
||||||
|
{% raw -%}
|
||||||
|
\multicolumn{2}{X}{%
|
||||||
|
{% endraw -%}
|
||||||
|
{{ row.desc }}} \\
|
||||||
|
{% endfor -%}
|
||||||
|
|
||||||
\begin{tabularx}{300pt}{c | r r r }
|
\spacer
|
||||||
\sectiontitle{Experiences\;\;}
|
|
||||||
{% for experience in config.experiences -%} \\[-8pt]
|
|
||||||
{% raw -%}
|
|
||||||
& \widel{\large\title{%
|
|
||||||
{% endraw -%}
|
|
||||||
{{ experience.company }}}\hint{ {{experience.title }} }} & {{ experience.start }}---{{ experience.end }} \\
|
|
||||||
& \widel{\footnotesize {{ experience.location }}
|
|
||||||
{% if experience.remote -%}
|
|
||||||
\color[rgb]{.8,.8,.8}{(Remote)}
|
|
||||||
{% endif -%}
|
|
||||||
} \\[-8pt]
|
|
||||||
\\
|
|
||||||
|
|
||||||
{% for note in experience.notes -%}
|
\sectiontitle{Skills} \\[-8pt]
|
||||||
& \bullet
|
{% for row in config.skills -%}
|
||||||
{% raw -%}
|
& \hint{ {{ row.name | title }}:} &
|
||||||
& \widex{%
|
{% raw -%}
|
||||||
{% endraw -%}
|
\multicolumn{2}{X}{%
|
||||||
{{note}}
|
{% endraw -%}
|
||||||
} \\[-8pt]
|
{% if row.name == "languages" -%}
|
||||||
\\
|
\multirow{3}{*}{
|
||||||
{% endfor -%}
|
\begin{tabularx}{\textwidth}{ r l }
|
||||||
\\[-8pt]
|
{% for group in row.desc -%}
|
||||||
{% endfor -%}
|
{% raw -%}
|
||||||
|
\hint{%
|
||||||
|
{% endraw -%}
|
||||||
|
{{ group.level | title }}:} & {{ group.langs }} \\
|
||||||
|
{% endfor -%}
|
||||||
\end{tabularx}
|
\end{tabularx}
|
||||||
}
|
} \newline \newline % 100% hack pls fix
|
||||||
& &
|
{% else -%}
|
||||||
{
|
{{ row.desc }}
|
||||||
\begin{tabularx}{150pt}{ c | X }
|
{% endif -%}
|
||||||
\sectiontitle{Degree\;\;} \\[-8pt]
|
}\\
|
||||||
{% raw -%}
|
{% endfor -%}
|
||||||
& {\large\title{%
|
|
||||||
{% endraw -%}
|
|
||||||
{{ config.education.school }}
|
|
||||||
}} \\
|
|
||||||
& \footnotesize{ {{ config.education.location }}} \\
|
|
||||||
& \hint{Date}\\
|
|
||||||
& {{ config.education.start }}---{{ config.education.end_date }} \\
|
|
||||||
{% for row in config.education.list -%}
|
|
||||||
{% raw -%}
|
|
||||||
& \hint{%
|
|
||||||
{% endraw -%}
|
|
||||||
{{ row.name | title }}} \\
|
|
||||||
& {{ row.desc }} \\
|
|
||||||
{% endfor -%}
|
|
||||||
\\[-8pt]
|
|
||||||
\\
|
|
||||||
|
|
||||||
\spacer
|
|
||||||
\spacer
|
|
||||||
\spacer
|
|
||||||
\spacer
|
|
||||||
|
|
||||||
\sectiontitle{Skills and Interests\;\;} \\[-8pt]
|
|
||||||
{% for row in config.skills -%}
|
|
||||||
|
|
||||||
{% raw -%}
|
|
||||||
& \title{%
|
|
||||||
{% endraw -%}
|
|
||||||
{{ row.name | title }}} \\
|
|
||||||
|
|
||||||
{% if row.name == "languages" -%}
|
|
||||||
{% for group in row.desc -%}
|
|
||||||
{% raw -%}
|
|
||||||
& \hint{%
|
|
||||||
{% endraw -%}
|
|
||||||
{{ group.level | title }}} \\
|
|
||||||
& {{ group.langs }} \\
|
|
||||||
{% endfor -%}
|
|
||||||
{% else -%}
|
|
||||||
& \begin{flushleft}
|
|
||||||
{{ row.desc }} \\
|
|
||||||
\end{flushleft}
|
|
||||||
{% endif -%}
|
|
||||||
\\[-8pt]
|
|
||||||
\\
|
|
||||||
{% endfor -%}
|
|
||||||
\end{tabularx}
|
\end{tabularx}
|
||||||
}
|
|
||||||
|
\begin{tabularx}{\textwidth}{c | r X r }
|
||||||
|
\sectiontitle{Experiences}
|
||||||
|
{% for experience in config.experiences -%} \\[-8pt]
|
||||||
|
{% raw -%}
|
||||||
|
& \widel{\large\title{%
|
||||||
|
{% endraw -%}
|
||||||
|
{{ experience.company }}}\hint{ {{experience.title }} }} & {{ experience.start }}---{{ experience.end }} \\
|
||||||
|
& \widel{\footnotesize {{ experience.location }}} \\
|
||||||
|
{% for note in experience.notes -%}
|
||||||
|
& \bullet
|
||||||
|
{% raw -%}
|
||||||
|
& \widex{%
|
||||||
|
{% endraw -%}
|
||||||
|
{{note}}} \\
|
||||||
|
{% endfor -%}
|
||||||
|
{% endfor -%}
|
||||||
|
\end{tabularx}
|
||||||
|
|
||||||
|
\begin{tabularx}{\textwidth}{c | r X r }
|
||||||
|
\sectiontitle{Projects}
|
||||||
|
{% for project in config.projects -%} \\[-8pt]
|
||||||
|
{% raw -%}
|
||||||
|
& \widel{\large\title{%
|
||||||
|
{% endraw -%}
|
||||||
|
{{ project.name }}}\hint{ {{ project.lang }} }} \\
|
||||||
|
{% for note in project.notes -%}
|
||||||
|
& \bullet
|
||||||
|
{% raw -%}
|
||||||
|
& \widex{%
|
||||||
|
{% endraw -%}
|
||||||
|
{{note}}} \\
|
||||||
|
{% endfor -%}
|
||||||
|
{% endfor -%}
|
||||||
\end{tabularx}
|
\end{tabularx}
|
||||||
\end{document}
|
\end{document}
|
||||||
|
|
|
@ -8,11 +8,9 @@
|
||||||
]
|
]
|
||||||
\newfontfamily{\fa}{FontAwesome}
|
\newfontfamily{\fa}{FontAwesome}
|
||||||
|
|
||||||
\definecolor{AccentColor}{HTML}{238de4}
|
|
||||||
|
|
||||||
{% raw %}
|
{% raw %}
|
||||||
% Changes the color of any text inside to the accent color
|
% Changes the color of any text inside to the accent color
|
||||||
\renewcommand{\accent}[1] {{\color{AccentColor}{#1}}}
|
\renewcommand{\accent}[1] {{\color{red}{#1}}}
|
||||||
{% endraw %}
|
{% endraw %}
|
||||||
|
|
||||||
{% raw %}
|
{% raw %}
|
||||||
|
|
Loading…
Reference in a new issue