Initial import
This commit is contained in:
commit
a5c24c4e46
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
[submodule "resume-schema"]
|
||||
path = resume-schema
|
||||
url = https://github.com/jsonresume/resume-schema/
|
7
README.md
Normal file
7
README.md
Normal file
|
@ -0,0 +1,7 @@
|
|||
jsonresume written in go
|
||||
------------------------
|
||||
|
||||
kendall and kendallfr themes are based on https://github.com/LinuxBozo/jsonresume-theme-kendall.
|
||||
|
||||
`$ go build -o jsonresume ./cli`
|
||||
`$ ./jsonresume -t kendall -r resume-schema/examples/valid/complete.json -o resume.html && cp themes/kendall/*.css .`
|
74
cli/resume.go
Normal file
74
cli/resume.go
Normal file
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Copyright (c) 2018 Arnaud Ysmal. All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
||||
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"jsonresume/model"
|
||||
"jsonresume/themes"
|
||||
_ "jsonresume/themes/kendall"
|
||||
_ "jsonresume/themes/kendallfr"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var r *model.Resume
|
||||
var resume string
|
||||
var theme string
|
||||
var err error
|
||||
var outf string
|
||||
var f *os.File
|
||||
|
||||
flag.StringVar(&resume, "resume", "resume.json", "JSON of resume")
|
||||
flag.StringVar(&resume, "r", "resume.json", "JSON of resume")
|
||||
flag.StringVar(&theme, "theme", "", "Theme of resume")
|
||||
flag.StringVar(&theme, "t", "", "Theme of resume")
|
||||
flag.StringVar(&outf, "out", "-", "Output file")
|
||||
flag.StringVar(&outf, "o", "-", "Output file")
|
||||
flag.Parse()
|
||||
|
||||
if outf == "-" {
|
||||
f = os.Stdout
|
||||
} else {
|
||||
if f, err = os.OpenFile(outf, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0755); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
if r, err = model.Parse(resume); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
if t, exists := themes.Themes[theme]; exists {
|
||||
if err = t.Render(r, f); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
} else {
|
||||
fmt.Printf("No such theme\n")
|
||||
}
|
||||
}
|
199
model/json.go
Normal file
199
model/json.go
Normal file
|
@ -0,0 +1,199 @@
|
|||
/*
|
||||
* Copyright (c) 2018 Arnaud Ysmal. All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
||||
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
const ISO8601DateLayout = "2006-01-02"
|
||||
|
||||
type ResumeDate struct {
|
||||
time.Time
|
||||
}
|
||||
|
||||
func (ct *ResumeDate) UnmarshalJSON(b []byte) (err error) {
|
||||
s := strings.Trim(string(b), "\"")
|
||||
if s == "null" {
|
||||
ct.Time = time.Time{}
|
||||
return
|
||||
}
|
||||
ct.Time, err = time.Parse(ISO8601DateLayout, s)
|
||||
return
|
||||
}
|
||||
|
||||
// Resume represent Curriculum Vitae
|
||||
type Resume struct {
|
||||
Title string `json:"title"`
|
||||
Basic Basic `json:"basics"`
|
||||
Work []Work `json:"work"`
|
||||
Volunteer []Volunteer `json:"volunteer"`
|
||||
Education []Education `json:"education"`
|
||||
Awards []Award `json:"awards"`
|
||||
Publications []Publication `json:"publications"`
|
||||
Skills []Skill `json:"skills"`
|
||||
Languages []Language `json:"languages"`
|
||||
Interests []Interest `json:"interests"`
|
||||
References []Reference `json:"references"`
|
||||
Projects []Project `json:"projects"`
|
||||
}
|
||||
|
||||
// Basic is the basic information for a resume
|
||||
type Basic struct {
|
||||
Name string `json:"name"`
|
||||
Label string `json:"label"`
|
||||
Image string `json:"image"`
|
||||
Email string `json:"email"`
|
||||
Phone string `json:"phone"`
|
||||
URL string `json:"url"`
|
||||
Summary string `json:"summary"`
|
||||
ResumeLocation Location `json:"location"`
|
||||
Profiles []SocialProfile `json:"profiles"`
|
||||
}
|
||||
|
||||
// Location is the location details of a resume owner.
|
||||
type Location struct {
|
||||
Address string `json:"address"`
|
||||
PostalCode string `json:"postalCode"`
|
||||
City string `json:"city"`
|
||||
CountryCode string `json:"countryCode"`
|
||||
Region string `json:"region"`
|
||||
}
|
||||
|
||||
// SocialProfile is the profile of the resume owner.
|
||||
type SocialProfile struct {
|
||||
Network string `json:"network"`
|
||||
UserName string `json:"username"`
|
||||
URL string `json:"url"`
|
||||
}
|
||||
|
||||
// Work is the work details of the resume owner.
|
||||
type Work struct {
|
||||
Name string `json:"name"`
|
||||
WorkLocation string `json:"location"`
|
||||
Description string `json:"description"`
|
||||
Position string `json:"position"`
|
||||
URL string `json:"url"`
|
||||
StartDate ResumeDate `json:"startDate"`
|
||||
EndDate ResumeDate `json:"endDate"`
|
||||
Summary string `json:"summary"`
|
||||
Highlights []string `json:"highlights"`
|
||||
}
|
||||
|
||||
// Volunteer is the volunteer details of the resume owner.
|
||||
type Volunteer struct {
|
||||
Organization string `json:"organization"`
|
||||
Position string `json:"position"`
|
||||
URL string `json:"url"`
|
||||
StartDate ResumeDate `json:"startDate"`
|
||||
EndDate ResumeDate `json:"endDate"`
|
||||
Summary string `json:"summary"`
|
||||
Highlights []string `json:"highlights"`
|
||||
}
|
||||
|
||||
// Education is the education details of the resume owner.
|
||||
type Education struct {
|
||||
Institution string `json:"institution"`
|
||||
Area string `json:"area"`
|
||||
StudyType string `json:"studyType"`
|
||||
StartDate ResumeDate `json:"startDate"`
|
||||
EndDate ResumeDate `json:"endDate"`
|
||||
GPA string `json:"gpa"`
|
||||
Courses []string `json:"courses"`
|
||||
}
|
||||
|
||||
// Award is the award details of the resume owner.
|
||||
type Award struct {
|
||||
Title string `json:"title"`
|
||||
Date ResumeDate `json:"date"`
|
||||
Awarder string `json:"awarder"`
|
||||
Summary string `json:"summary"`
|
||||
}
|
||||
|
||||
// Publication is the publication details of the resume owner.
|
||||
type Publication struct {
|
||||
Name string `json:"name"`
|
||||
Publisher string `json:"publisher"`
|
||||
ReleaseDate ResumeDate `json:"releaseDate"`
|
||||
URL string `json:"url"`
|
||||
Summary string `json:"summary"`
|
||||
}
|
||||
|
||||
// Skill is the skill details of the resume owner.
|
||||
type Skill struct {
|
||||
Name string `json:"name"`
|
||||
Level string `json:"level"`
|
||||
Keywords []string `json:"keywords"`
|
||||
}
|
||||
|
||||
// Language is the language details of the resume owner.
|
||||
type Language struct {
|
||||
Language string `json:"language"`
|
||||
Fluency string `json:"fluency"`
|
||||
}
|
||||
|
||||
// Interest is the interest details of the resume owner.
|
||||
type Interest struct {
|
||||
Name string `json:"name"`
|
||||
Keywords []string `json:"keywords"`
|
||||
}
|
||||
|
||||
// Referee is the details about a person who is refereeing for the resume owner.
|
||||
type Reference struct {
|
||||
Name string `json:"name"`
|
||||
Reference string `json:"reference"`
|
||||
}
|
||||
|
||||
// Volunteer is the volunteer details of the resume owner.
|
||||
type Project struct {
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Highlights []string `json:"highlights"`
|
||||
Keywords []string `json:"keywords"`
|
||||
StartDate ResumeDate `json:"startDate"`
|
||||
EndDate ResumeDate `json:"endDate"`
|
||||
URL string `json:"url"`
|
||||
Roles []string `json:"roles"`
|
||||
Entity string `json:"entity"`
|
||||
Type string `json:"type"`
|
||||
}
|
||||
|
||||
func Parse(f string) (*Resume, error) {
|
||||
var content []byte
|
||||
var err error
|
||||
var r Resume
|
||||
|
||||
if content, err = ioutil.ReadFile(f); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err = json.Unmarshal(content, &r); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &r, nil
|
||||
}
|
1
resume-schema
Submodule
1
resume-schema
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 8558e9e6e4badade1c871d5cfd253a740dbf3b34
|
1
themes/README.md
Normal file
1
themes/README.md
Normal file
|
@ -0,0 +1 @@
|
|||
kendall and kendallfr are based on https://github.com/LinuxBozo/jsonresume-theme-kendall
|
108
themes/kendall/kendall.go
Normal file
108
themes/kendall/kendall.go
Normal file
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
* Copyright (c) 2018 Arnaud Ysmal. All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
||||
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package kendall
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"jsonresume/model"
|
||||
"jsonresume/themes"
|
||||
"strings"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
var Theme = themes.Theme{
|
||||
Name: "kendall",
|
||||
Functions: template.FuncMap{
|
||||
"iconClass": iconClass,
|
||||
"formatDateWork": formatDateWork,
|
||||
"formatDateEdu": formatDateEdu,
|
||||
"formatDatePub": formatDatePub,
|
||||
},
|
||||
Template: "themes/kendall/resume.template",
|
||||
}
|
||||
|
||||
func init() {
|
||||
(&Theme).Register()
|
||||
}
|
||||
func iconClass(network string) string {
|
||||
network = strings.ToLower(network)
|
||||
switch network {
|
||||
// special cases
|
||||
case "google-plus":
|
||||
case "googleplus":
|
||||
return "fa fa-google-plus"
|
||||
case "flickr":
|
||||
case "flicker":
|
||||
return "fa fa-flickr"
|
||||
case "dribbble":
|
||||
case "dribble":
|
||||
return "fa fa-dribbble"
|
||||
case "codepen":
|
||||
return "fa fa-codepen"
|
||||
case "soundcloud":
|
||||
return "fa fa-soundcloud"
|
||||
case "reddit":
|
||||
return "fa fa-reddit"
|
||||
case "tumblr":
|
||||
case "tumbler":
|
||||
return "fa fa-tumblr"
|
||||
case "stack-overflow":
|
||||
case "stackoverflow":
|
||||
return "fa fa-stack-overflow"
|
||||
case "blog":
|
||||
case "rss":
|
||||
return "fa fa-rss"
|
||||
case "gitlab":
|
||||
return "fa fa-gitlab"
|
||||
case "keybase":
|
||||
return "fa fa-key"
|
||||
default:
|
||||
return "fa fa-" + network
|
||||
}
|
||||
|
||||
return "fa fa-" + network
|
||||
}
|
||||
|
||||
func formatDateWork(date model.ResumeDate) string {
|
||||
if date.IsZero() {
|
||||
return "Present"
|
||||
}
|
||||
return fmt.Sprintf("%s %d", date.Month().String(), date.Year())
|
||||
}
|
||||
|
||||
func formatDateEdu(date model.ResumeDate) string {
|
||||
if date.IsZero() {
|
||||
return "Present"
|
||||
}
|
||||
return fmt.Sprintf("%d", date.Year())
|
||||
}
|
||||
|
||||
func formatDatePub(date model.ResumeDate) string {
|
||||
if date.IsZero() {
|
||||
return "Present"
|
||||
}
|
||||
return fmt.Sprintf("%d %s %d", date.Day(), date.Month().String(), date.Year())
|
||||
}
|
91
themes/kendall/print.css
Normal file
91
themes/kendall/print.css
Normal file
|
@ -0,0 +1,91 @@
|
|||
body {
|
||||
font-size: .95em;
|
||||
-webkit-print-color-adjust: exact;
|
||||
}
|
||||
|
||||
a[href]:after {
|
||||
content: none !important;
|
||||
}
|
||||
|
||||
#photo{
|
||||
display: none;
|
||||
}
|
||||
|
||||
.box {
|
||||
margin-bottom: -10px;
|
||||
}
|
||||
|
||||
blockquote,
|
||||
#education,
|
||||
#awards,
|
||||
.contact-item,
|
||||
.publication,
|
||||
.skills,
|
||||
.interests {
|
||||
page-break-inside: avoid;
|
||||
}
|
||||
|
||||
.col-sm-5{
|
||||
width: 40%;
|
||||
padding: 0 15px;
|
||||
}
|
||||
|
||||
.col-sm-7{
|
||||
width: 60%;
|
||||
padding: 0 15px;
|
||||
}
|
||||
|
||||
.skills .col-sm-offset-1,
|
||||
.interests .col-sm-offset-1{
|
||||
margin-top: -10px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
#education {
|
||||
margin: 0;
|
||||
margin-bottom: -20px;
|
||||
}
|
||||
#awards:before,
|
||||
#education:before {
|
||||
background: none;
|
||||
}
|
||||
|
||||
#awards .description,
|
||||
#education .description,
|
||||
.job .details {
|
||||
border: 1px solid #eee;
|
||||
}
|
||||
.publication,
|
||||
.publication .panel-heading,
|
||||
.publication .name{
|
||||
margin: 0;
|
||||
padding: 0 5px;
|
||||
border: none;
|
||||
}
|
||||
.publication .panel-body {
|
||||
padding: 0 10px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.badge {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.list-group-item{
|
||||
border: none;
|
||||
margin: 0;
|
||||
padding: 5px 15px;
|
||||
}
|
||||
.list-group-item:after{
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
right: 0;
|
||||
left: -1px;
|
||||
height: 0;
|
||||
width: 0;
|
||||
border: solid transparent;
|
||||
border-right-color: #999;
|
||||
border-width: 4px;
|
||||
pointer-events: none;
|
||||
}
|
292
themes/kendall/resume.template
Normal file
292
themes/kendall/resume.template
Normal file
|
@ -0,0 +1,292 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Resume of {{.Basic.Name}}</title>
|
||||
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
|
||||
<link rel="stylesheet" type="text/css" href="style.css" media="screen">
|
||||
<link rel="stylesheet" type="text/css" href="print.css" media="print">
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<div id="photo-header" class="text-center">
|
||||
<!-- PHOTO (AVATAR) -->
|
||||
{{if .Basic.Image -}}
|
||||
<div id="photo">
|
||||
<img src="{{.Basic.Image}}" alt="avatar">
|
||||
</div>
|
||||
{{end -}}
|
||||
<div id="text-header" {{if not .Basic.Image}}style="margin-top: 90px;"{{end -}}>
|
||||
<h1>{{.Basic.Name}}<br>{{if .Basic.Label}}<span>{{.Basic.Label}}</span>{{end -}}</h1>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xs-12 col-sm-7">
|
||||
{{if .Basic.Summary -}}
|
||||
<!-- ABOUT ME -->
|
||||
<div class="box">
|
||||
<h2><i class="fa fa-user ico"></i> About</h2>
|
||||
<p>{{.Basic.Summary}}</p>
|
||||
</div>
|
||||
{{end -}}
|
||||
{{if .Work -}}
|
||||
<!-- WORK EXPERIENCE -->
|
||||
<div class="box">
|
||||
<h2><i class= "fa fa-suitcase ico"></i> Work Experience</h2>
|
||||
{{range .Work -}}
|
||||
<div class="job clearfix">
|
||||
<div class="row">
|
||||
<div class="details">
|
||||
<div class="where">{{.Name}}</div>
|
||||
{{if .URL -}}
|
||||
<div class="address">
|
||||
<a href="{{.URL}}" target= "_blank"><i class="fa fa-globe ico"></i> {{.URL}}</a>
|
||||
</div>
|
||||
{{end -}}
|
||||
<div class="year">{{formatDateWork .StartDate}} – {{formatDateWork .EndDate}}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="job-details col-xs-11">
|
||||
<div class="profession">{{.Position}}</div>
|
||||
<div class="description">
|
||||
{{.Summary -}}
|
||||
{{if .Highlights -}}
|
||||
<div class="highlights"></div>
|
||||
<ul class="list-group">
|
||||
{{range .Highlights -}}
|
||||
<li class="list-group-item">{{.}}</li>
|
||||
{{end -}}
|
||||
</ul>
|
||||
{{end -}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{end -}}
|
||||
</div>
|
||||
{{end -}}
|
||||
{{if .Awards -}}
|
||||
<!-- AWARDS -->
|
||||
<div class="box">
|
||||
<h2><i class="fa fa-certificate ico"></i> Awards</h2>
|
||||
<ul id="awards" class="clearfix">
|
||||
{{range .Awards -}}
|
||||
<li>
|
||||
<div class="year pull-left">{{formatDatePub .Date}}</div>
|
||||
<div class="description pull-right">
|
||||
<h3>{{.Awarder}}</h3>
|
||||
<p><i class="fa fa-trophy ico"></i> {{.Title}}</p>
|
||||
<p>{{.Summary}}</p>
|
||||
</div>
|
||||
</li>
|
||||
{{end -}}
|
||||
</ul>
|
||||
</div>
|
||||
{{end -}}
|
||||
{{if .Volunteer -}}
|
||||
<!-- VOLUNTEER -->
|
||||
<div class="box">
|
||||
<h2><i class= "fa fa-group ico"></i> Volunteer</h2>
|
||||
{{range .Volunteer -}}
|
||||
<div class="job clearfix">
|
||||
<div class="row">
|
||||
<div class="details">
|
||||
<div class="where">{{.Organization}}</div>
|
||||
{{if .URL -}}
|
||||
<div class="address">
|
||||
<a href="{{.URL}}" target= "_blank"><i class="fa fa-globe ico"></i> {{.URL}}</a>
|
||||
</div>
|
||||
{{end -}}
|
||||
<div class="year">{{formatDateWork .StartDate}} – {{formatDateWork .EndDate}}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="job-details col-xs-11">
|
||||
<div class="profession">{{.Position}}</div>
|
||||
<div class="description">
|
||||
{{.Summary -}}
|
||||
{{if .Highlights -}}
|
||||
<div class="highlights"></div>
|
||||
<ul class="list-group">
|
||||
{{range .Highlights -}}
|
||||
<li class="list-group-item">{{.}}</li>
|
||||
{{end -}}
|
||||
</ul>
|
||||
{{end -}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{end -}}
|
||||
</div>
|
||||
{{end -}}
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-5">
|
||||
<!-- CONTACT -->
|
||||
<div class="box clearfix">
|
||||
<h2><i class="fa fa-bullseye ico"></i> Contact</h2>
|
||||
{{if .Basic.ResumeLocation.City -}}
|
||||
<div class="contact-item">
|
||||
<div class="icon pull-left text-center"><span class="fa fa-map-marker fa-fw"></span></div>
|
||||
{{if .Basic.ResumeLocation.Address}}<div class="title pull-right">{{.Basic.ResumeLocation.Address}}</div>{{end -}}
|
||||
<div class="title {{if not .Basic.ResumeLocation.Address}}only {{end -}} pull-right">{{.Basic.ResumeLocation.City}}{{if .Basic.ResumeLocation.Region}}, {{.Basic.ResumeLocation.Region}}{{end -}}{{if .Basic.ResumeLocation.PostalCode}} {{.Basic.ResumeLocation.PostalCode}}{{end -}}{{if .Basic.ResumeLocation.CountryCode}} {{.Basic.ResumeLocation.CountryCode}}{{end -}}</div>
|
||||
</div>
|
||||
{{end -}}
|
||||
{{if .Basic.Phone -}}
|
||||
<div class="contact-item">
|
||||
<div class="icon pull-left text-center"><span class="fa fa-phone fa-fw"></span></div>
|
||||
<div class="title only pull-right">{{.Basic.Phone}}</div>
|
||||
</div>
|
||||
{{end -}}
|
||||
{{if .Basic.Email -}}
|
||||
<div class="contact-item">
|
||||
<div class="icon pull-left text-center"><span class="fa fa-envelope fa-fw"></span></div>
|
||||
<div class="title only pull-right"><a href="mailto:{{.Basic.Email}}" target="_blank">{{.Basic.Email}}</a></div>
|
||||
</div>
|
||||
{{end -}}
|
||||
{{if .Basic.URL -}}
|
||||
<div class="contact-item">
|
||||
<div class="icon pull-left text-center"><span class="fa fa-globe fa-fw"></span></div>
|
||||
<div class="title only pull-right"><a href="{{.Basic.URL}}" target="_blank">{{.Basic.URL}}</a></div>
|
||||
</div>
|
||||
{{end -}}
|
||||
{{range .Basic.Profiles -}}
|
||||
<div class="contact-item">
|
||||
<div class="icon pull-left text-center"><span class="{{iconClass .Network}} fa-fw"></span></div>
|
||||
<div class="title pull-right">{{.Network}}</div>
|
||||
<div class="description pull-right"><a href="{{.URL}}" target="_blank">{{if .UserName}}{{.UserName}}{{end -}}{{if not .UserName}}{{.URL}}{{end -}}</a></div>
|
||||
</div>
|
||||
{{end -}}
|
||||
</div>
|
||||
{{if .Education -}}
|
||||
<!-- EDUCATION -->
|
||||
<div class="box">
|
||||
<h2><i class="fa fa-university ico"></i> Education</h2>
|
||||
<ul id="education" class="clearfix">
|
||||
{{range .Education -}}
|
||||
<li>
|
||||
<div class="year pull-left">{{formatDateEdu .StartDate}} {{formatDateEdu .EndDate}}</div>
|
||||
<div class="description pull-right">
|
||||
<h3>{{.Institution}}</h3>
|
||||
{{if .StudyType}}<p><i class= "fa fa-graduation-cap ico"></i> {{.StudyType}}</p>{{end}}
|
||||
<p>{{.Area}}</p>
|
||||
{{if .GPA -}}
|
||||
<p>
|
||||
GPA: {{.GPA}}
|
||||
</p>
|
||||
{{end -}}
|
||||
{{if .Courses -}}
|
||||
<div>Courses</div>
|
||||
<ul class="list-group">
|
||||
{{range .Courses -}}
|
||||
<li class="list-group-item">{{.}}</li>
|
||||
{{end -}}
|
||||
</ul>
|
||||
{{end -}}
|
||||
</div>
|
||||
</li>
|
||||
{{end -}}
|
||||
</ul>
|
||||
</div>
|
||||
{{end -}}
|
||||
{{if .Skills -}}
|
||||
<!-- SKILLS -->
|
||||
<div class="box">
|
||||
<h2><i class="fa fa-tasks ico"></i> Skills</h2>
|
||||
{{range .Skills -}}
|
||||
<div class="skills clearfix">
|
||||
<div class="item-skills">
|
||||
{{.Name}}
|
||||
{{if .Level}}<span class="skill-level">{{.Level}}</span>{{end -}}
|
||||
</div>
|
||||
<div class="col-sm-offset-1 col-sm-12 clearfix">
|
||||
{{range .Keywords -}}
|
||||
<span class= "skill badge">{{.}}</span>
|
||||
{{end -}}
|
||||
</div>
|
||||
</div>
|
||||
{{end -}}
|
||||
</div>
|
||||
{{end -}}
|
||||
{{if .Publications -}}
|
||||
<!-- PUBLICATIONS -->
|
||||
<div class="box">
|
||||
<h2><i class="fa fa-book ico"></i> Publications</h2>
|
||||
{{range .Publications -}}
|
||||
<div class="publication panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<div class="name panel-title">{{.Name}}</div>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
{{if .Publisher -}}
|
||||
<div class="publisher"><i class= "fa fa-bookmark ico"></i> {{.Publisher}}</div>
|
||||
{{end -}}
|
||||
<div class="year">{{formatDatePub .ReleaseDate}}</div>
|
||||
{{if .URL -}}
|
||||
<div class="address">
|
||||
<a href="{{.URL}}" target= "_blank"><i class="fa fa-globe ico"></i> {{.URL}}</a>
|
||||
</div>
|
||||
{{end -}}
|
||||
{{if .Summary -}}
|
||||
<p>{{.Summary}}</p>
|
||||
{{end -}}
|
||||
</div>
|
||||
</div>
|
||||
{{end -}}
|
||||
</div>
|
||||
{{end -}}
|
||||
{{if .Languages -}}
|
||||
<!-- LANGUAGES -->
|
||||
<div class="box">
|
||||
<h2><i class="fa fa-language ico"></i> Languages</h2>
|
||||
<ul class="list-group">
|
||||
{{range .Languages -}}
|
||||
<li class=" list-group-item">{{.Language}}<span class="skill badge pull-right">{{.Fluency}}</span></li>
|
||||
{{end -}}
|
||||
</ul>
|
||||
</div>
|
||||
{{end -}}
|
||||
{{if .Interests -}}
|
||||
<!-- HOBBIES -->
|
||||
<div class="box">
|
||||
<h2><i class="fa fa-heart ico"></i> Interests</h2>
|
||||
{{range .Interests -}}
|
||||
<div class="interests clearfix">
|
||||
<div class="item-interests">
|
||||
{{.Name -}}
|
||||
</div>
|
||||
<div class="col-sm-offset-1 col-sm-12 clearfix">
|
||||
{{range .Keywords -}}
|
||||
<span class= "interest badge">{{.}}</span>
|
||||
{{end -}}
|
||||
</div>
|
||||
</div>
|
||||
{{end -}}
|
||||
</div>
|
||||
{{end -}}
|
||||
{{if .References -}}
|
||||
<div class="box">
|
||||
<h2><i class= "fa fa-check-square ico"></i> References</h2>
|
||||
{{range .References -}}
|
||||
<blockquote>
|
||||
<div>{{.Reference}}</div>
|
||||
<footer>{{.Name}}</footer>
|
||||
</blockquote><br>
|
||||
{{end -}}
|
||||
</div>
|
||||
{{end -}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
276
themes/kendall/style.css
Normal file
276
themes/kendall/style.css
Normal file
|
@ -0,0 +1,276 @@
|
|||
@import url(https://fonts.googleapis.com/css?family=Open+Sans:400,600,700,800);
|
||||
@charset "utf-8";
|
||||
@-webkit-viewport { width: device-width; }
|
||||
@-moz-viewport { width: device-width; }
|
||||
@-ms-viewport { width: device-width; }
|
||||
@-o-viewport { width: device-width; }
|
||||
@viewport { width: device-width; }
|
||||
|
||||
body{
|
||||
font-family: 'Open Sans', Arial, Tahoma;
|
||||
font-weight: 400;
|
||||
color: #363636;
|
||||
background: #334960;
|
||||
}
|
||||
blockquote {
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
.container{
|
||||
margin-top: 80px;
|
||||
margin-bottom: 15px;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
#photo-header{
|
||||
margin-top: -75px;
|
||||
}
|
||||
#photo{
|
||||
width: 160px;
|
||||
height: 160px;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
padding: 5px;
|
||||
background: #334960;
|
||||
display: inline-block;
|
||||
}
|
||||
#photo img{
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
#text-header h1{
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-size: 1.5em;
|
||||
font-weight: 700;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: -1px;
|
||||
}
|
||||
#text-header h1::first-line{
|
||||
font-size: 1.5em;
|
||||
font-weight: 800;
|
||||
line-height: 1.5em;
|
||||
}
|
||||
#text-header h1 span{
|
||||
color: #334960;
|
||||
opacity: 0.7;
|
||||
}
|
||||
#text-header h1 sup{
|
||||
opacity: 0.5;
|
||||
}
|
||||
#text-header:after{
|
||||
width: 100%;
|
||||
height: 3px;
|
||||
border-bottom: 1px solid #ddd;
|
||||
margin-top: 15px;
|
||||
content: '';
|
||||
display: block;
|
||||
}
|
||||
|
||||
.box{
|
||||
padding-bottom: 10px;
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
.box h2{
|
||||
color: #227c74;
|
||||
font-size: 1.5em;
|
||||
font-weight: 700;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
#awards,
|
||||
#education{
|
||||
margin-top: 20px;
|
||||
margin-bottom: 0;
|
||||
position: relative;
|
||||
padding: 1em 0;
|
||||
list-style: none;
|
||||
}
|
||||
#awards:before,
|
||||
#education:before {
|
||||
width: 5px;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
left: 35px;
|
||||
top: 0;
|
||||
content: ' ';
|
||||
display: block;
|
||||
background: #32475c;
|
||||
background: -moz-linear-gradient(top, #ffffff 0%, #32475c 7%, #32475c 89%, #ffffff 100%);
|
||||
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#ffffff), color-stop(7%,#32475c), color-stop(89%,#32475c), color-stop(100%,#ffffff));
|
||||
background: -webkit-linear-gradient(top, #ffffff 0%,#32475c 7%,#32475c 89%,#ffffff 100%);
|
||||
background: -o-linear-gradient(top, #ffffff 0%,#32475c 7%,#32475c 89%,#ffffff 100%);
|
||||
background: -ms-linear-gradient(top, #ffffff 0%,#32475c 7%,#32475c 89%,#ffffff 100%);
|
||||
background: linear-gradient(to bottom, #ffffff 0%,#32475c 7%,#32475c 89%,#ffffff 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffffff', endColorstr='#ffffff',GradientType=0 );
|
||||
}
|
||||
#awards li,
|
||||
#education li{
|
||||
width: 100%;
|
||||
z-index: 2;
|
||||
position: relative;
|
||||
float: left;
|
||||
}
|
||||
#awards .year,
|
||||
#education .year{
|
||||
width: 14%;
|
||||
background: #fff;
|
||||
padding: 10px;
|
||||
font-weight: 700;
|
||||
display: inline-block;
|
||||
}
|
||||
#awards .description,
|
||||
#education .description{
|
||||
width: 83%;
|
||||
display: inline-block;
|
||||
background: #eee;
|
||||
margin-bottom: 10px;
|
||||
position: relative;
|
||||
padding: 10px;
|
||||
border-bottom: 1px solid #ccc;
|
||||
border-right: 1px solid #ccc;
|
||||
}
|
||||
#awards .description:after,
|
||||
#education .description:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 15px;
|
||||
right: 0;
|
||||
left: -16px;
|
||||
height: 0;
|
||||
width: 0;
|
||||
border: solid transparent;
|
||||
border-right-color: #eee;
|
||||
border-width: 8px;
|
||||
pointer-events: none;
|
||||
}
|
||||
#awards .description h3,
|
||||
#education .description h3{
|
||||
font-size: 1.2em;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-weight: 700;
|
||||
}
|
||||
#awards .description p,
|
||||
#education .description p{
|
||||
margin-top: 5px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.job{
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
.job .details {
|
||||
margin-left: 3%;
|
||||
width: 95%;
|
||||
padding: 10px;
|
||||
margin-bottom: 10px;
|
||||
background: #eee;
|
||||
border-bottom: 1px solid #ccc;
|
||||
border-right: 1px solid #ccc;
|
||||
}
|
||||
.job .where{
|
||||
font-size: 1.2em;
|
||||
font-weight: bold;
|
||||
}
|
||||
.job .year{
|
||||
opacity: 0.7;
|
||||
}
|
||||
.job .profession{
|
||||
font-size: 1.2em;
|
||||
font-weight: bold;
|
||||
}
|
||||
.job .description{
|
||||
line-height: 1.5em;
|
||||
}
|
||||
.job .highlights{
|
||||
padding: 5px 0;
|
||||
font-weight: bold;
|
||||
}
|
||||
.job .job-details {
|
||||
padding-left: 5%;
|
||||
width: 100%;
|
||||
}
|
||||
.publication {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.publication .name{
|
||||
font-size: 1em;
|
||||
font-weight: bold;
|
||||
}
|
||||
.publication .year{
|
||||
opacity: 0.7;
|
||||
}
|
||||
.publication p{
|
||||
margin: 0;
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
.contact-item{
|
||||
width: 100%;
|
||||
float: left;
|
||||
}
|
||||
.contact-item .icon{
|
||||
padding: 10px;
|
||||
border-right: 1px solid #ccc;
|
||||
border-bottom: 1px solid #ccc;
|
||||
color: #32475c;
|
||||
background: #eee;
|
||||
}
|
||||
.contact-item:last-child .icon{
|
||||
border-bottom: none;
|
||||
}
|
||||
.contact-item .title{
|
||||
width: 80%;
|
||||
width: calc(100% - 55px);
|
||||
font-weight: 700;
|
||||
opacity: 0.9;
|
||||
}
|
||||
.contact-item .title.only{
|
||||
margin-top: 10px;
|
||||
}
|
||||
.contact-item .description{
|
||||
width: 80%;
|
||||
width: calc(100% - 55px);
|
||||
color: #334960;
|
||||
}
|
||||
|
||||
.item-interests,
|
||||
.item-skills{
|
||||
height: 30px;
|
||||
color: #334960;
|
||||
padding: 5px 10px;
|
||||
margin-bottom: 5px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
font-size: 1.1em;
|
||||
font-weight: 600;
|
||||
}
|
||||
.interest,
|
||||
.skill{
|
||||
color: #fff;
|
||||
display: inline-block;
|
||||
margin-right: 5px;
|
||||
margin-bottom: 5px;
|
||||
padding: 5px 10px;
|
||||
background: #32475c;
|
||||
position: relative;
|
||||
font-size: .85em;
|
||||
}
|
||||
.skill-level {
|
||||
background-color: #227c74;
|
||||
border-radius: 4px;
|
||||
color: #fff;
|
||||
padding: 1px 8px;
|
||||
font-size: .75em;
|
||||
position: absolute;
|
||||
margin: 1px 10px;
|
||||
}
|
||||
|
||||
#language-skills .skill{
|
||||
margin: 10px 0;
|
||||
padding-bottom: 10px;
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
137
themes/kendallfr/kendallfr.go
Normal file
137
themes/kendallfr/kendallfr.go
Normal file
|
@ -0,0 +1,137 @@
|
|||
/*
|
||||
* Copyright (c) 2018 Arnaud Ysmal. All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
||||
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package kendallfr
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"jsonresume/model"
|
||||
"jsonresume/themes"
|
||||
"strings"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
var Theme = themes.Theme{
|
||||
Name: "kendallfr",
|
||||
Functions: template.FuncMap{
|
||||
"iconClass": iconClass,
|
||||
"formatDateWork": formatDateWork,
|
||||
"formatDateEdu": formatDateEdu,
|
||||
"formatDatePub": formatDatePub,
|
||||
},
|
||||
Template: "themes/kendallfr/resume.template",
|
||||
}
|
||||
|
||||
func init() {
|
||||
(&Theme).Register()
|
||||
}
|
||||
func iconClass(network string) string {
|
||||
network = strings.ToLower(network)
|
||||
switch network {
|
||||
// special cases
|
||||
case "google-plus":
|
||||
case "googleplus":
|
||||
return "fa fa-google-plus"
|
||||
case "flickr":
|
||||
case "flicker":
|
||||
return "fa fa-flickr"
|
||||
case "dribbble":
|
||||
case "dribble":
|
||||
return "fa fa-dribbble"
|
||||
case "codepen":
|
||||
return "fa fa-codepen"
|
||||
case "soundcloud":
|
||||
return "fa fa-soundcloud"
|
||||
case "reddit":
|
||||
return "fa fa-reddit"
|
||||
case "tumblr":
|
||||
case "tumbler":
|
||||
return "fa fa-tumblr"
|
||||
case "stack-overflow":
|
||||
case "stackoverflow":
|
||||
return "fa fa-stack-overflow"
|
||||
case "blog":
|
||||
case "rss":
|
||||
return "fa fa-rss"
|
||||
case "gitlab":
|
||||
return "fa fa-gitlab"
|
||||
case "keybase":
|
||||
return "fa fa-key"
|
||||
default:
|
||||
return "fa fa-" + network
|
||||
}
|
||||
|
||||
return "fa fa-" + network
|
||||
}
|
||||
|
||||
func getMonth(date model.ResumeDate) string {
|
||||
switch date.Month() {
|
||||
case 1:
|
||||
return "Janvier"
|
||||
case 2:
|
||||
return "Février"
|
||||
case 3:
|
||||
return "Mars"
|
||||
case 4:
|
||||
return "Avril"
|
||||
case 5:
|
||||
return "Mai"
|
||||
case 6:
|
||||
return "Juin"
|
||||
case 7:
|
||||
return "Juillet"
|
||||
case 8:
|
||||
return "Août"
|
||||
case 9:
|
||||
return "Septembre"
|
||||
case 10:
|
||||
return "Octobre"
|
||||
case 11:
|
||||
return "Novembre"
|
||||
case 12:
|
||||
return "Décembre"
|
||||
}
|
||||
return ""
|
||||
}
|
||||
func formatDateWork(date model.ResumeDate) string {
|
||||
if date.IsZero() {
|
||||
return "Présent"
|
||||
}
|
||||
return fmt.Sprintf("%s %d", getMonth(date), date.Year())
|
||||
}
|
||||
|
||||
func formatDateEdu(date model.ResumeDate) string {
|
||||
if date.IsZero() {
|
||||
return "Présent"
|
||||
}
|
||||
return fmt.Sprintf("%d", date.Year())
|
||||
}
|
||||
|
||||
func formatDatePub(date model.ResumeDate) string {
|
||||
if date.IsZero() {
|
||||
return "Présent"
|
||||
}
|
||||
return fmt.Sprintf("%d %s %d", date.Day(), getMonth(date), date.Year())
|
||||
}
|
91
themes/kendallfr/print.css
Normal file
91
themes/kendallfr/print.css
Normal file
|
@ -0,0 +1,91 @@
|
|||
body {
|
||||
font-size: .95em;
|
||||
-webkit-print-color-adjust: exact;
|
||||
}
|
||||
|
||||
a[href]:after {
|
||||
content: none !important;
|
||||
}
|
||||
|
||||
#photo{
|
||||
display: none;
|
||||
}
|
||||
|
||||
.box {
|
||||
margin-bottom: -10px;
|
||||
}
|
||||
|
||||
blockquote,
|
||||
#education,
|
||||
#awards,
|
||||
.contact-item,
|
||||
.publication,
|
||||
.skills,
|
||||
.interests {
|
||||
page-break-inside: avoid;
|
||||
}
|
||||
|
||||
.col-sm-5{
|
||||
width: 40%;
|
||||
padding: 0 15px;
|
||||
}
|
||||
|
||||
.col-sm-7{
|
||||
width: 60%;
|
||||
padding: 0 15px;
|
||||
}
|
||||
|
||||
.skills .col-sm-offset-1,
|
||||
.interests .col-sm-offset-1{
|
||||
margin-top: -10px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
#education {
|
||||
margin: 0;
|
||||
margin-bottom: -20px;
|
||||
}
|
||||
#awards:before,
|
||||
#education:before {
|
||||
background: none;
|
||||
}
|
||||
|
||||
#awards .description,
|
||||
#education .description,
|
||||
.job .details {
|
||||
border: 1px solid #eee;
|
||||
}
|
||||
.publication,
|
||||
.publication .panel-heading,
|
||||
.publication .name{
|
||||
margin: 0;
|
||||
padding: 0 5px;
|
||||
border: none;
|
||||
}
|
||||
.publication .panel-body {
|
||||
padding: 0 10px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.badge {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.list-group-item{
|
||||
border: none;
|
||||
margin: 0;
|
||||
padding: 5px 15px;
|
||||
}
|
||||
.list-group-item:after{
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
right: 0;
|
||||
left: -1px;
|
||||
height: 0;
|
||||
width: 0;
|
||||
border: solid transparent;
|
||||
border-right-color: #999;
|
||||
border-width: 4px;
|
||||
pointer-events: none;
|
||||
}
|
292
themes/kendallfr/resume.template
Normal file
292
themes/kendallfr/resume.template
Normal file
|
@ -0,0 +1,292 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>CV de {{.Basic.Name}}</title>
|
||||
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
|
||||
<link rel="stylesheet" type="text/css" href="style.css" media="screen">
|
||||
<link rel="stylesheet" type="text/css" href="print.css" media="print">
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<div id="photo-header" class="text-center">
|
||||
<!-- PHOTO (AVATAR) -->
|
||||
{{if .Basic.Image -}}
|
||||
<div id="photo">
|
||||
<img src="{{.Basic.Image}}" alt="avatar">
|
||||
</div>
|
||||
{{end -}}
|
||||
<div id="text-header" {{if not .Basic.Image}}style="margin-top: 90px;"{{end -}}>
|
||||
<h1>{{.Basic.Name}}<br>{{if .Basic.Label}}<span>{{.Basic.Label}}</span>{{end -}}</h1>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xs-12 col-sm-7">
|
||||
{{if .Basic.Summary -}}
|
||||
<!-- ABOUT ME -->
|
||||
<div class="box">
|
||||
<h2><i class="fa fa-user ico"></i> À propos</h2>
|
||||
<p>{{.Basic.Summary}}</p>
|
||||
</div>
|
||||
{{end -}}
|
||||
{{if .Work -}}
|
||||
<!-- WORK EXPERIENCE -->
|
||||
<div class="box">
|
||||
<h2><i class= "fa fa-suitcase ico"></i> Expérience Professionnelle</h2>
|
||||
{{range .Work -}}
|
||||
<div class="job clearfix">
|
||||
<div class="row">
|
||||
<div class="details">
|
||||
<div class="where">{{.Name}}</div>
|
||||
{{if .URL -}}
|
||||
<div class="address">
|
||||
<a href="{{.URL}}" target= "_blank"><i class="fa fa-globe ico"></i> {{.URL}}</a>
|
||||
</div>
|
||||
{{end -}}
|
||||
<div class="year">{{formatDateWork .StartDate}} – {{formatDateWork .EndDate}}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="job-details col-xs-11">
|
||||
<div class="profession">{{.Position}}</div>
|
||||
<div class="description">
|
||||
{{.Summary -}}
|
||||
{{if .Highlights -}}
|
||||
<div class="highlights"></div>
|
||||
<ul class="list-group">
|
||||
{{range .Highlights -}}
|
||||
<li class="list-group-item">{{.}}</li>
|
||||
{{end -}}
|
||||
</ul>
|
||||
{{end -}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{end -}}
|
||||
</div>
|
||||
{{end -}}
|
||||
{{if .Awards -}}
|
||||
<!-- AWARDS -->
|
||||
<div class="box">
|
||||
<h2><i class="fa fa-certificate ico"></i> Awards</h2>
|
||||
<ul id="awards" class="clearfix">
|
||||
{{range .Awards -}}
|
||||
<li>
|
||||
<div class="year pull-left">{{formatDatePub .Date}}</div>
|
||||
<div class="description pull-right">
|
||||
<h3>{{.Awarder}}</h3>
|
||||
<p><i class="fa fa-trophy ico"></i> {{.Title}}</p>
|
||||
<p>{{.Summary}}</p>
|
||||
</div>
|
||||
</li>
|
||||
{{end -}}
|
||||
</ul>
|
||||
</div>
|
||||
{{end -}}
|
||||
{{if .Volunteer -}}
|
||||
<!-- VOLUNTEER -->
|
||||
<div class="box">
|
||||
<h2><i class= "fa fa-group ico"></i> Bénévolat</h2>
|
||||
{{range .Volunteer -}}
|
||||
<div class="job clearfix">
|
||||
<div class="row">
|
||||
<div class="details">
|
||||
<div class="where">{{.Organization}}</div>
|
||||
{{if .URL -}}
|
||||
<div class="address">
|
||||
<a href="{{.URL}}" target= "_blank"><i class="fa fa-globe ico"></i> {{.URL}}</a>
|
||||
</div>
|
||||
{{end -}}
|
||||
<div class="year">{{formatDateWork .StartDate}} – {{formatDateWork .EndDate}}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="job-details col-xs-11">
|
||||
<div class="profession">{{.Position}}</div>
|
||||
<div class="description">
|
||||
{{.Summary -}}
|
||||
{{if .Highlights -}}
|
||||
<div class="highlights"></div>
|
||||
<ul class="list-group">
|
||||
{{range .Highlights -}}
|
||||
<li class="list-group-item">{{.}}</li>
|
||||
{{end -}}
|
||||
</ul>
|
||||
{{end -}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{end -}}
|
||||
</div>
|
||||
{{end -}}
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-5">
|
||||
<!-- CONTACT -->
|
||||
<div class="box clearfix">
|
||||
<h2><i class="fa fa-bullseye ico"></i> Contact</h2>
|
||||
{{if .Basic.ResumeLocation.City -}}
|
||||
<div class="contact-item">
|
||||
<div class="icon pull-left text-center"><span class="fa fa-map-marker fa-fw"></span></div>
|
||||
{{if .Basic.ResumeLocation.Address}}<div class="title pull-right">{{.Basic.ResumeLocation.Address}}</div>{{end -}}
|
||||
<div class="title {{if not .Basic.ResumeLocation.Address}}only {{end -}} pull-right">{{.Basic.ResumeLocation.City}}{{if .Basic.ResumeLocation.Region}}, {{.Basic.ResumeLocation.Region}}{{end -}}{{if .Basic.ResumeLocation.PostalCode}} {{.Basic.ResumeLocation.PostalCode}}{{end -}}{{if .Basic.ResumeLocation.CountryCode}} {{.Basic.ResumeLocation.CountryCode}}{{end -}}</div>
|
||||
</div>
|
||||
{{end -}}
|
||||
{{if .Basic.Phone -}}
|
||||
<div class="contact-item">
|
||||
<div class="icon pull-left text-center"><span class="fa fa-phone fa-fw"></span></div>
|
||||
<div class="title only pull-right">{{.Basic.Phone}}</div>
|
||||
</div>
|
||||
{{end -}}
|
||||
{{if .Basic.Email -}}
|
||||
<div class="contact-item">
|
||||
<div class="icon pull-left text-center"><span class="fa fa-envelope fa-fw"></span></div>
|
||||
<div class="title only pull-right"><a href="mailto:{{.Basic.Email}}" target="_blank">{{.Basic.Email}}</a></div>
|
||||
</div>
|
||||
{{end -}}
|
||||
{{if .Basic.URL -}}
|
||||
<div class="contact-item">
|
||||
<div class="icon pull-left text-center"><span class="fa fa-globe fa-fw"></span></div>
|
||||
<div class="title only pull-right"><a href="{{.Basic.URL}}" target="_blank">{{.Basic.URL}}</a></div>
|
||||
</div>
|
||||
{{end -}}
|
||||
{{range .Basic.Profiles -}}
|
||||
<div class="contact-item">
|
||||
<div class="icon pull-left text-center"><span class="{{iconClass .Network}} fa-fw"></span></div>
|
||||
<div class="title pull-right">{{.Network}}</div>
|
||||
<div class="description pull-right"><a href="{{.URL}}" target="_blank">{{if .UserName}}{{.UserName}}{{end -}}{{if not .UserName}}{{.URL}}{{end -}}</a></div>
|
||||
</div>
|
||||
{{end -}}
|
||||
</div>
|
||||
{{if .Education -}}
|
||||
<!-- EDUCATION -->
|
||||
<div class="box">
|
||||
<h2><i class="fa fa-university ico"></i> Formation</h2>
|
||||
<ul id="education" class="clearfix">
|
||||
{{range .Education -}}
|
||||
<li>
|
||||
<div class="year pull-left">{{formatDateEdu .StartDate}} {{formatDateEdu .EndDate}}</div>
|
||||
<div class="description pull-right">
|
||||
<h3>{{.Institution}}</h3>
|
||||
{{if .StudyType}}<p><i class= "fa fa-graduation-cap ico"></i> {{.StudyType}}</p>{{end}}
|
||||
<p>{{.Area}}</p>
|
||||
{{if .GPA -}}
|
||||
<p>
|
||||
GPA: {{.GPA}}
|
||||
</p>
|
||||
{{end -}}
|
||||
{{if .Courses -}}
|
||||
<div>Courses</div>
|
||||
<ul class="list-group">
|
||||
{{range .Courses -}}
|
||||
<li class="list-group-item">{{.}}</li>
|
||||
{{end -}}
|
||||
</ul>
|
||||
{{end -}}
|
||||
</div>
|
||||
</li>
|
||||
{{end -}}
|
||||
</ul>
|
||||
</div>
|
||||
{{end -}}
|
||||
{{if .Skills -}}
|
||||
<!-- SKILLS -->
|
||||
<div class="box">
|
||||
<h2><i class="fa fa-tasks ico"></i> Compétences</h2>
|
||||
{{range .Skills -}}
|
||||
<div class="skills clearfix">
|
||||
<div class="item-skills">
|
||||
{{.Name}}
|
||||
{{if .Level}}<span class="skill-level">{{.Level}}</span>{{end -}}
|
||||
</div>
|
||||
<div class="col-sm-offset-1 col-sm-12 clearfix">
|
||||
{{range .Keywords -}}
|
||||
<span class= "skill badge">{{.}}</span>
|
||||
{{end -}}
|
||||
</div>
|
||||
</div>
|
||||
{{end -}}
|
||||
</div>
|
||||
{{end -}}
|
||||
{{if .Publications -}}
|
||||
<!-- PUBLICATIONS -->
|
||||
<div class="box">
|
||||
<h2><i class="fa fa-book ico"></i> Publications</h2>
|
||||
{{range .Publications -}}
|
||||
<div class="publication panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<div class="name panel-title">{{.Name}}</div>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
{{if .Publisher -}}
|
||||
<div class="publisher"><i class= "fa fa-bookmark ico"></i> {{.Publisher}}</div>
|
||||
{{end -}}
|
||||
<div class="year">{{formatDatePub .ReleaseDate}}</div>
|
||||
{{if .URL -}}
|
||||
<div class="address">
|
||||
<a href="{{.URL}}" target= "_blank"><i class="fa fa-globe ico"></i> {{.URL}}</a>
|
||||
</div>
|
||||
{{end -}}
|
||||
{{if .Summary -}}
|
||||
<p>{{.Summary}}</p>
|
||||
{{end -}}
|
||||
</div>
|
||||
</div>
|
||||
{{end -}}
|
||||
</div>
|
||||
{{end -}}
|
||||
{{if .Languages -}}
|
||||
<!-- LANGUAGES -->
|
||||
<div class="box">
|
||||
<h2><i class="fa fa-language ico"></i> Langues</h2>
|
||||
<ul class="list-group">
|
||||
{{range .Languages -}}
|
||||
<li class=" list-group-item">{{.Language}}<span class="skill badge pull-right">{{.Fluency}}</span></li>
|
||||
{{end -}}
|
||||
</ul>
|
||||
</div>
|
||||
{{end -}}
|
||||
{{if .Interests -}}
|
||||
<!-- HOBBIES -->
|
||||
<div class="box">
|
||||
<h2><i class="fa fa-heart ico"></i> Intérêts</h2>
|
||||
{{range .Interests -}}
|
||||
<div class="interests clearfix">
|
||||
<div class="item-interests">
|
||||
{{.Name -}}
|
||||
</div>
|
||||
<div class="col-sm-offset-1 col-sm-12 clearfix">
|
||||
{{range .Keywords -}}
|
||||
<span class= "interest badge">{{.}}</span>
|
||||
{{end -}}
|
||||
</div>
|
||||
</div>
|
||||
{{end -}}
|
||||
</div>
|
||||
{{end -}}
|
||||
{{if .References -}}
|
||||
<div class="box">
|
||||
<h2><i class= "fa fa-check-square ico"></i> Références</h2>
|
||||
{{range .References -}}
|
||||
<blockquote>
|
||||
<div>{{.Reference}}</div>
|
||||
<footer>{{.Name}}</footer>
|
||||
</blockquote><br>
|
||||
{{end -}}
|
||||
</div>
|
||||
{{end -}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
276
themes/kendallfr/style.css
Normal file
276
themes/kendallfr/style.css
Normal file
|
@ -0,0 +1,276 @@
|
|||
@import url(https://fonts.googleapis.com/css?family=Open+Sans:400,600,700,800);
|
||||
@charset "utf-8";
|
||||
@-webkit-viewport { width: device-width; }
|
||||
@-moz-viewport { width: device-width; }
|
||||
@-ms-viewport { width: device-width; }
|
||||
@-o-viewport { width: device-width; }
|
||||
@viewport { width: device-width; }
|
||||
|
||||
body{
|
||||
font-family: 'Open Sans', Arial, Tahoma;
|
||||
font-weight: 400;
|
||||
color: #363636;
|
||||
background: #334960;
|
||||
}
|
||||
blockquote {
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
.container{
|
||||
margin-top: 80px;
|
||||
margin-bottom: 15px;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
#photo-header{
|
||||
margin-top: -75px;
|
||||
}
|
||||
#photo{
|
||||
width: 160px;
|
||||
height: 160px;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
padding: 5px;
|
||||
background: #334960;
|
||||
display: inline-block;
|
||||
}
|
||||
#photo img{
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
#text-header h1{
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-size: 1.5em;
|
||||
font-weight: 700;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: -1px;
|
||||
}
|
||||
#text-header h1::first-line{
|
||||
font-size: 1.5em;
|
||||
font-weight: 800;
|
||||
line-height: 1.5em;
|
||||
}
|
||||
#text-header h1 span{
|
||||
color: #334960;
|
||||
opacity: 0.7;
|
||||
}
|
||||
#text-header h1 sup{
|
||||
opacity: 0.5;
|
||||
}
|
||||
#text-header:after{
|
||||
width: 100%;
|
||||
height: 3px;
|
||||
border-bottom: 1px solid #ddd;
|
||||
margin-top: 15px;
|
||||
content: '';
|
||||
display: block;
|
||||
}
|
||||
|
||||
.box{
|
||||
padding-bottom: 10px;
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
.box h2{
|
||||
color: #227c74;
|
||||
font-size: 1.5em;
|
||||
font-weight: 700;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
#awards,
|
||||
#education{
|
||||
margin-top: 20px;
|
||||
margin-bottom: 0;
|
||||
position: relative;
|
||||
padding: 1em 0;
|
||||
list-style: none;
|
||||
}
|
||||
#awards:before,
|
||||
#education:before {
|
||||
width: 5px;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
left: 35px;
|
||||
top: 0;
|
||||
content: ' ';
|
||||
display: block;
|
||||
background: #32475c;
|
||||
background: -moz-linear-gradient(top, #ffffff 0%, #32475c 7%, #32475c 89%, #ffffff 100%);
|
||||
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#ffffff), color-stop(7%,#32475c), color-stop(89%,#32475c), color-stop(100%,#ffffff));
|
||||
background: -webkit-linear-gradient(top, #ffffff 0%,#32475c 7%,#32475c 89%,#ffffff 100%);
|
||||
background: -o-linear-gradient(top, #ffffff 0%,#32475c 7%,#32475c 89%,#ffffff 100%);
|
||||
background: -ms-linear-gradient(top, #ffffff 0%,#32475c 7%,#32475c 89%,#ffffff 100%);
|
||||
background: linear-gradient(to bottom, #ffffff 0%,#32475c 7%,#32475c 89%,#ffffff 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffffff', endColorstr='#ffffff',GradientType=0 );
|
||||
}
|
||||
#awards li,
|
||||
#education li{
|
||||
width: 100%;
|
||||
z-index: 2;
|
||||
position: relative;
|
||||
float: left;
|
||||
}
|
||||
#awards .year,
|
||||
#education .year{
|
||||
width: 14%;
|
||||
background: #fff;
|
||||
padding: 10px;
|
||||
font-weight: 700;
|
||||
display: inline-block;
|
||||
}
|
||||
#awards .description,
|
||||
#education .description{
|
||||
width: 83%;
|
||||
display: inline-block;
|
||||
background: #eee;
|
||||
margin-bottom: 10px;
|
||||
position: relative;
|
||||
padding: 10px;
|
||||
border-bottom: 1px solid #ccc;
|
||||
border-right: 1px solid #ccc;
|
||||
}
|
||||
#awards .description:after,
|
||||
#education .description:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 15px;
|
||||
right: 0;
|
||||
left: -16px;
|
||||
height: 0;
|
||||
width: 0;
|
||||
border: solid transparent;
|
||||
border-right-color: #eee;
|
||||
border-width: 8px;
|
||||
pointer-events: none;
|
||||
}
|
||||
#awards .description h3,
|
||||
#education .description h3{
|
||||
font-size: 1.2em;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-weight: 700;
|
||||
}
|
||||
#awards .description p,
|
||||
#education .description p{
|
||||
margin-top: 5px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.job{
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
.job .details {
|
||||
margin-left: 3%;
|
||||
width: 95%;
|
||||
padding: 10px;
|
||||
margin-bottom: 10px;
|
||||
background: #eee;
|
||||
border-bottom: 1px solid #ccc;
|
||||
border-right: 1px solid #ccc;
|
||||
}
|
||||
.job .where{
|
||||
font-size: 1.2em;
|
||||
font-weight: bold;
|
||||
}
|
||||
.job .year{
|
||||
opacity: 0.7;
|
||||
}
|
||||
.job .profession{
|
||||
font-size: 1.2em;
|
||||
font-weight: bold;
|
||||
}
|
||||
.job .description{
|
||||
line-height: 1.5em;
|
||||
}
|
||||
.job .highlights{
|
||||
padding: 5px 0;
|
||||
font-weight: bold;
|
||||
}
|
||||
.job .job-details {
|
||||
padding-left: 5%;
|
||||
width: 100%;
|
||||
}
|
||||
.publication {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.publication .name{
|
||||
font-size: 1em;
|
||||
font-weight: bold;
|
||||
}
|
||||
.publication .year{
|
||||
opacity: 0.7;
|
||||
}
|
||||
.publication p{
|
||||
margin: 0;
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
.contact-item{
|
||||
width: 100%;
|
||||
float: left;
|
||||
}
|
||||
.contact-item .icon{
|
||||
padding: 10px;
|
||||
border-right: 1px solid #ccc;
|
||||
border-bottom: 1px solid #ccc;
|
||||
color: #32475c;
|
||||
background: #eee;
|
||||
}
|
||||
.contact-item:last-child .icon{
|
||||
border-bottom: none;
|
||||
}
|
||||
.contact-item .title{
|
||||
width: 80%;
|
||||
width: calc(100% - 55px);
|
||||
font-weight: 700;
|
||||
opacity: 0.9;
|
||||
}
|
||||
.contact-item .title.only{
|
||||
margin-top: 10px;
|
||||
}
|
||||
.contact-item .description{
|
||||
width: 80%;
|
||||
width: calc(100% - 55px);
|
||||
color: #334960;
|
||||
}
|
||||
|
||||
.item-interests,
|
||||
.item-skills{
|
||||
height: 30px;
|
||||
color: #334960;
|
||||
padding: 5px 10px;
|
||||
margin-bottom: 5px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
font-size: 1.1em;
|
||||
font-weight: 600;
|
||||
}
|
||||
.interest,
|
||||
.skill{
|
||||
color: #fff;
|
||||
display: inline-block;
|
||||
margin-right: 5px;
|
||||
margin-bottom: 5px;
|
||||
padding: 5px 10px;
|
||||
background: #32475c;
|
||||
position: relative;
|
||||
font-size: .85em;
|
||||
}
|
||||
.skill-level {
|
||||
background-color: #227c74;
|
||||
border-radius: 4px;
|
||||
color: #fff;
|
||||
padding: 1px 8px;
|
||||
font-size: .75em;
|
||||
position: absolute;
|
||||
margin: 1px 10px;
|
||||
}
|
||||
|
||||
#language-skills .skill{
|
||||
margin: 10px 0;
|
||||
padding-bottom: 10px;
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
59
themes/theme.go
Normal file
59
themes/theme.go
Normal file
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright (c) 2018 Arnaud Ysmal. All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
||||
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package themes
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"jsonresume/model"
|
||||
"path"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
type Theme struct {
|
||||
Name string
|
||||
Functions template.FuncMap
|
||||
Template string
|
||||
}
|
||||
|
||||
var Themes map[string]*Theme
|
||||
|
||||
func init() {
|
||||
Themes = make(map[string]*Theme)
|
||||
}
|
||||
|
||||
func (t *Theme) Render(r *model.Resume, w io.Writer) error {
|
||||
tmpl := template.Must(template.New(path.Base(t.Template)).Funcs(t.Functions).ParseFiles(t.Template))
|
||||
return tmpl.Execute(w, r)
|
||||
}
|
||||
|
||||
func (t *Theme) Register() error {
|
||||
if _, exists := Themes[t.Name]; exists {
|
||||
return fmt.Errorf("Package %s already registered", t.Name)
|
||||
}
|
||||
Themes[t.Name] = t
|
||||
return nil
|
||||
}
|
Loading…
Reference in New Issue
Block a user