Skip to content

Commit

Permalink
Add "highway" theme, update Readme, minor code fixes (#3)
Browse files Browse the repository at this point in the history
* Add new theme, improve the "simple" theme

* Update README.md, add more log output

* Separate themes docs

* Remove file

* Clean up the code

* Increase a version to v0.2.2

Co-authored-by: Serhii Cheredko <[email protected]>
  • Loading branch information
SergChr and Serhii Cheredko committed Nov 20, 2020
1 parent 48598d5 commit 321d6b8
Show file tree
Hide file tree
Showing 12 changed files with 158 additions and 11 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "qcv"
version = "0.2.0"
version = "0.2.2"
authors = ["SergChr <[email protected]>"]
edition = "2018"
license = "MIT"
Expand Down
12 changes: 11 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
`qcv` is a tool to generate HTML resume from JSON template.
![img](https://travis-ci.com/SergChr/qcv.svg?token=2R5NQSKq8dFxzneyxJie&branch=master)

## Content
- [Use cases](#use-cases)
- [How does it work](#how-does-it-work)
- [List of the available themes](/src/assets/themes/README.md)
- [Custom HTML themes](#custom-html-themes)
- **[How to install](#installing)**

## Use cases
#### Keeping a JSON resume in Git
The tool allows to have one JSON file where the resume information placed. It can be stored in a `git` repository to make the updating process more seamless. There could be branching applied for different versions; the diffs are more simpler to track.
Expand All @@ -10,7 +17,7 @@ No more `CV_1.pdf`, `CV_1_updated.pdf`, `CV_1_updated_for_facebook.pdf`.
No need to move between different services that generate a resume or/and store it.

#### Generating a simple portfolio website
The tool generates a HTML file based on a HTML template that can be customizable.
The tool generates a HTML file based on a HTML template that can be customized.

## How does it work
The tool replaces variables in a HTML template (see `src/assets/themes`) with corresponding values in the JSON template. Example:
Expand Down Expand Up @@ -85,6 +92,9 @@ This is the JSON template example below. It will be generated by the `init` comm
```
Put your information into this file. Then use the `build simple` command to generate the `cv.html` output.

## Available themes
See [themes documentation](/src/assets/themes/README.md)

## Custom HTML themes
There is an ability to build your custom HTML template and generate a resume from it. Example:
```sh
Expand Down
12 changes: 12 additions & 0 deletions src/assets/themes/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
## Available themes
Usage:
```sh
$ qcv build <theme_name>
# See theme names below
# e.g. qcv build simple
```
#### Simple
![Simple](/src/assets/themes/simple/simple.png "Simple")

#### Highway
![Highway](/src/assets/themes/highway/highway.png "Highway")
Binary file added src/assets/themes/highway/highway.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
96 changes: 96 additions & 0 deletions src/assets/themes/highway/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">

<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>

<title>{{basics.name}}'s resume</title>
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet">
<style type="text/css">
* { margin: 0; padding: 0; }
</style>
</head>

<body class="h-screen">
<div class="flex flex-col md:flex-row bg-gray-900 h-full py-8">
<div class="flex-1 text-gray-700 justify-start flex-col h-auto mx-3">
<div class="bg-gray-100 w-full h-auto mb-5 rounded-md p-5 leading-9">
<div class="font-bold text-4xl">{{basics.name}}</div>
<div class="text-xl text-gray-600">{{basics.label}}</div>
<hr class="my-5">
<div class="font-light">{{basics.location.address}} {{basics.location.city}}, {{basics.location.country}}</div>
<div class="font-light">
<a href="mailto:{{basics.email}}">{{basics.email}}</a>
| {{basics.phone}}
<br>
<a href="{{basics.website}}" class="underline">{{basics.website}}</a>
</div>
<hr class="my-4">
<div>
{!basics.profiles
<a class="font-light mx-2" href="{url}">{network}:{username}</a>
!}
</div>
</div>

<div class="bg-gray-100 w-full h-auto mb-5 rounded-md p-5">
<div class="font-light leading-9">{{basics.summary}}</div>
<hr class="my-4">

<div class="flex">
{!skills
<div class="text-sm bg-gray-800 p-2 text-gray-100 rounded-md mx-2">{name}</div>
!}
</div>

<hr class="my-4">
<div class="font-light">Languages</div>
{!languages
<div class="flex flex-col px-4 py-2 m-2">
<div class="font-bold">{language}</div>
<div class="font-light">{level}</div>
</div>
!}
</div>
</div>

<div class="flex-1 text-gray-700 justify-start flex-col h-auto mx-3">
<div class="bg-gray-100 w-full h-auto mb-5 rounded-md p-5 leading-7">
<div class="text-lg">Education</div>
<hr class="my-4">
{!education
<div class="font-bold uppercase">{institution}</div>
<div class="font-thin text-xs my-1">{location}</div>
<div>{area} - {study_type} | {start_date} - {end_date}</div>
!}
</div>

<div class="bg-gray-100 w-full h-auto mb-5 rounded-md p-5 leading-7">
<div class="text-lg">Work experience</div>
<hr class="my-4">
{!work
<a href="{website}" class="font-bold uppercase">{company}</a>
<div class="font-thin my-1">{position} | {start_date} - {end_date}</div>
<div>{summary}</div>
<hr class="my-4">
!}
</div>
</div>

<div class="flex-1 text-gray-700 justify-start flex-col h-auto mx-3">
<div class="bg-gray-100 w-full h-auto mb-5 rounded-md p-5 leading-7">
<div class="text-lg">Projects</div>
<hr class="my-4">
{!projects
<div class="font-bold">{name}</div>
<div class="font-light text-sm">{description}</div>
!}
</div>
</div>

</div>
</body>

</html>
7 changes: 4 additions & 3 deletions src/assets/themes/simple/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@

<body class="flex justify-center font-sans bg-gray-100">
<div class="main flex flex-col p-1 w-9/12 bg-white rounded-sm p-6 shadow-sm">
<section id="header">
<section id="header" class="leading-8">
<div class="font-bold text-2xl">{{basics.name}}</div>
<div>{{basics.label}}</div>
<div class="font-light">{{basics.location.address}}, {{basics.location.city}}, {{basics.location.country}}</div>
<div class="font-light">{{basics.location.address}} {{basics.location.city}}, {{basics.location.country}}</div>
<div class="font-light">
<a href="mailto:{{basics.email}}">{{basics.email}}</a>
| {{basics.phone}}
Expand Down Expand Up @@ -52,6 +52,7 @@
<a href="{website}" class="font-bold uppercase">{company}</a>
<div class="font-thin my-1">{position} | {start_date} - {end_date}</div>
<div>{summary}</div>
<div class="m-8"></div>
!}
</section>

Expand All @@ -70,7 +71,7 @@

<section id="skills" class="p-4 flex">
{!skills
<div class="text-sm bg-gray-600 p-2 text-gray-200 rounded-sm">{name}</div>
<div class="text-sm bg-gray-600 p-2 text-gray-200 rounded-sm mx-1">{name}</div>
!}
</section>

Expand Down
Binary file added src/assets/themes/simple/simple.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 17 additions & 3 deletions src/cli/mod.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
use std::fs;
use std::io::prelude::*;
use rust_embed::RustEmbed;
use std::path::Path;

use crate::parser;
use crate::utils::logger;

const JSON_FILE_NAME: &str = "cv.json";
const OUTPUT_HTML_FILE_NAME: &str = "cv.html";
Expand Down Expand Up @@ -45,7 +47,7 @@ fn create_json() {
Ok(f) => f,
Err(_err) => panic!("Cannot create a JSON file. Probably it already exists.")
};
println!("File created.");
logger::write("File created.");
let template = Asset::get("cv_template.json")
.expect("Cannot read the CV template file");
file.write(&template)
Expand Down Expand Up @@ -77,7 +79,19 @@ fn cmd_build() {
fn build_from_template(html: &str) {
let resume = parser::extract_resume(JSON_FILE_NAME);
let result = parser::replace_html_vars(html, resume);
let write_file = || {
fs::write(OUTPUT_HTML_FILE_NAME, result)
.expect("Cannot write the result to html file");
logger::write("Successfully created HTML(see cv.html).");
};

fs::write(OUTPUT_HTML_FILE_NAME, result)
.expect("Cannot write the result to html file");
let is_html_exists = Path::new(OUTPUT_HTML_FILE_NAME).exists();
if is_html_exists {
match fs::remove_file(OUTPUT_HTML_FILE_NAME) {
Ok(()) => write_file(),
Err(_e) => panic!("Cannot rewrite the HTML file"),
};
} else {
write_file();
}
}
2 changes: 2 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
mod cli;
mod parser;
#[path="utils/logger.rs"]
mod utils;

extern crate regex;

Expand Down
11 changes: 9 additions & 2 deletions src/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,17 @@ use regex::{Captures, Regex};
use std::fs;
use std::io::prelude::*;
use structs::Resume;
use crate::utils::logger;

pub fn extract_resume(path: &str) -> Resume {
let mut file = fs::File::open(path).expect("Unable to read the JSON file");
let mut file;
match fs::File::open(path) {
Ok(f) => file = f,
Err(_e) => {
logger::write("Make sure you created 'cv.json' file in the root. Run 'qcv init'");
panic!("Unable to read JSON file");
},
};
let mut content = String::new();
file.read_to_string(&mut content)
.expect("Unable to read the JSON file");
Expand Down Expand Up @@ -55,7 +63,6 @@ pub fn replace_html_vars(html: &str, resume: Resume) -> String {
pub fn json_get(json: &serde_json::Value, key_str: &str) -> serde_json::Value {
use serde_json::Value;
let keys: Vec<&str> = key_str.split(".").collect();
eprintln!("{:?}", keys);
let get_err_msg = |key: &str| {
format!(
"Invalid key used in the HTML template: \"{}\"; full path: \"{}\"",
Expand Down
5 changes: 5 additions & 0 deletions src/utils/logger.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
pub mod logger {
pub fn write(m: &str) {
println!("{}", m);
}
}

0 comments on commit 321d6b8

Please sign in to comment.