jsonresume-theme-crewshin
Version:
A flat JSON Resume theme, compatible with the latest resume schema
308 lines (297 loc) • 16.1 kB
JavaScript
(function(s,t){typeof exports=="object"&&typeof module<"u"?t(exports,require("@rbardini/html"),require("micromark"),require("striptags"),require("feather-icons")):typeof define=="function"&&define.amd?define(["exports","@rbardini/html","micromark","striptags","feather-icons"],t):(s=typeof globalThis<"u"?globalThis:s||self,t(s.jsonresumeThemeEven={},s.html,s.micromark,s.striptags,s.feather))})(this,function(s,t,D,L,b){"use strict";var k=Object.freeze,J=Object.defineProperty;var x=(s,t)=>k(J(s,"raw",{value:k(t||s.slice())}));var w;const z=`const pluralize = (num, str) => \`\${num} \${num === 1 ? str : str.concat('s')}\`
class TimeDuration extends HTMLElement {
connectedCallback() {
const [from, to] = this.querySelectorAll('time')
if (!from) return
const startDate = new Date(from.dateTime || from.textContent)
const endDate = new Date(to ? to.dateTime || to.textContent : Date.now())
const diffDate = new Date(endDate - startDate)
const years = diffDate.getFullYear() - 1970
const months = diffDate.getMonth()
const days = diffDate.getDate() - 1
const segments = [
years && pluralize(years, 'yr'),
months && pluralize(months, 'mo'),
days && !years && !months && pluralize(days, 'day'),
].filter(Boolean)
if (!segments.length) return
const duration = document.createElement('time')
duration.classList.add('duration')
duration.textContent = '· '.concat(segments.join(' '))
this.append(' ', duration)
}
}
customElements.define('time-duration', TimeDuration)
`,C=':root{color-scheme:light dark;--color-background-light: #ffffff;--color-dimmed-light: #f3f4f5;--color-primary-light: #191e23;--color-secondary-light: #6c7781;--color-accent-light: #0073aa;--color-background-dark: #191e23;--color-dimmed-dark: #23282d;--color-primary-dark: #fbfbfc;--color-secondary-dark: #ccd0d4;--color-accent-dark: #00a0d2;--color-background: var(--color-background-light);--color-dimmed: var(--color-dimmed-light);--color-primary: var(--color-primary-light);--color-secondary: var(--color-secondary-light);--color-accent: var(--color-accent-light);--scale-ratio: 1.25;--scale0: 1rem;--scale1: calc(var(--scale0) * var(--scale-ratio));--scale2: calc(var(--scale1) * var(--scale-ratio));--scale3: calc(var(--scale2) * var(--scale-ratio));--scale4: calc(var(--scale3) * var(--scale-ratio));--scale5: calc(var(--scale4) * var(--scale-ratio))}@media (prefers-color-scheme: dark){:root{--color-background: var(--color-background-dark);--color-dimmed: var(--color-dimmed-dark);--color-primary: var(--color-primary-dark);--color-secondary: var(--color-secondary-dark);--color-accent: var(--color-accent-dark)}}*{box-sizing:border-box;margin:0;padding:0}html{font-size:14px}body{background:var(--color-background);color:var(--color-primary);display:grid;font:1em/1.5 Lato,sans-serif;gap:2em;grid-template-columns:[full-start] 1fr [main-start side-start] minmax(min-content,12em) [side-end content-start] minmax(min-content,36em) [main-end content-end] 1fr [full-end];grid-template-rows:auto [content] 0;margin-bottom:4em}body:before{content:"";grid-column:full;grid-row:content}ol,ul{padding-left:1em}:not(.icon-list,.tag-list)>li+li{margin-top:.4em}li::marker,.network{color:var(--color-secondary)}a{color:var(--color-accent);text-decoration:none}a:focus,a:hover{text-decoration:underline}h1,h2,h3,h5{font-weight:400}h1,h2,h3{line-height:1.2}h1{font-size:var(--scale5)}h2{color:var(--color-secondary);font-size:var(--scale4)}h3{color:var(--color-secondary);font-size:var(--scale3);grid-column:side;margin-bottom:1rem}h4{font-size:var(--scale2)}h5{font-size:var(--scale1)}h6{font-size:var(--scale0)}blockquote{border-left:.2em solid var(--color-dimmed);padding-left:1em}cite{color:var(--color-secondary);font-style:inherit}cite:before{content:"— "}svg{margin-right:.2em;vertical-align:text-bottom}.masthead{background:var(--color-dimmed);display:inherit;gap:inherit;grid-column:full;grid-template-columns:inherit;padding:4em 0;text-align:center}.masthead>*,section{grid-column:main}.masthead>img{border:4px solid;border-radius:50%;margin:0 auto;max-width:12em}article>*+*,blockquote>*+*,.timeline>div>*+*{margin-top:.6em}.meta{color:var(--color-secondary)}.stack{display:grid;gap:1.5em}.icon-list{display:flex;flex-wrap:wrap;gap:.4em 1em;justify-content:center;list-style:none;padding:0}.grid-list{display:grid;gap:1em}.tag-list{display:flex;flex-wrap:wrap;gap:.4em;list-style:none;padding:0}.tag-list>li{background:var(--color-dimmed);border-radius:.2em;padding:.2em .6em}.timeline>div{position:relative}.timeline>div:not(:last-child){padding-bottom:1rem}.timeline>div:not(:last-child):before{content:"";position:absolute;top:1rem;left:-15px;width:2px;height:100%;background:var(--color-secondary)}.timeline>div:not(:only-child):after{content:"";position:absolute;top:.6rem;left:-20px;width:8px;height:8px;background:var(--color-secondary);border:2px solid var(--color-background);border-radius:50%}@media print,(min-width: 48em){h3{text-align:right;margin-bottom:inherit}.masthead{text-align:inherit}.masthead>*,section{grid-column:content}.masthead img{grid-column:side;grid-row:span 2;max-width:100%}section{display:contents}.icon-list{flex-direction:column}.grid-list{grid-template-columns:repeat(auto-fit,minmax(calc((100% - 1em)/2),1fr))}}@media print{.duration{display:none}}';function j(e={}){const i=e.themeOptions?.colors;return i&&Object.entries(i).map(([n,[o,r=o]])=>`--color-${n}-light:${o}; --color-${n}-dark:${r};`).join(" ")}function d(e,i=!1){const n=D(e);return i?L(n):n}const T=e=>new Date(e).toLocaleDateString("en",{month:"short",year:"numeric",timeZone:"UTC"});function v(e){return t.html`<time datetime="${e}">${T(e)}</time>`}function q(e=[]){return e.length>0&&t.html`
<section id="awards">
<h3>Awards</h3>
<div class="stack">
${e.map(({awarder:i,date:n,summary:o,title:r})=>t.html`
<article>
<header>
<h4>${r}</h4>
<div class="meta">
${i&&t.html`<div>Awarded by <strong>${i}</strong></div>`} ${n&&v(n)}
</div>
</header>
${o&&d(o)}
</article>
`)}
</div>
</section>
`}const I=e=>e.replace(/^(https?:|)\/\//,"").replace(/\/$/,"");function h(e,i){return i?e?t.html`<a href="${e}">${i}</a>`:i:e&&t.html`<a href="${e}">${I(e)}</a>`}function P(e=[]){return e.length>0&&t.html`
<section id="certificates">
<h3>Certificates</h3>
<div class="stack">
${e.map(({date:i,issuer:n,name:o,url:r})=>t.html`
<article>
<header>
<h4>${h(r,o)}</h4>
<div class="meta">
${n&&t.html`<div>Issued by <strong>${n}</strong></div>`} ${i&&v(i)}
</div>
</header>
</article>
`)}
</div>
</section>
`}function f(e,i){return i===e?v(i):t.html`<time-duration>${v(e)} – ${i?v(i):"Present"}</time-duration>`}function R(e=[]){return e.length>0&&t.html`
<section id="education">
<h3>Education</h3>
<div class="stack">
${e.map(({area:i,courses:n=[],institution:o,startDate:r,endDate:l,studyType:a,url:c})=>t.html`
<article>
<header>
<h4>${h(c,o)}</h4>
<div class="meta">
${i&&t.html`<strong>${i}</strong>`}
${r&&t.html`<div>${f(r,l)}</div>`}
</div>
</header>
${a&&d(a)}
${n.length>0&&t.html`
<h5>Courses</h5>
<ul>
${n.map(m=>t.html`<li>${d(m)}</li>`)}
</ul>
`}
</article>
`)}
</div>
</section>
`}function p(e,i){return(b.icons[e.toLowerCase()]||i&&b.icons[i.toLowerCase()])?.toSvg({width:16,height:16})}const S=e=>Intl.DisplayNames?new Intl.DisplayNames(["en"],{type:"region"}).of(e):e;function E(e={}){const{email:i,image:n,label:o,location:r,name:l,phone:a,profiles:c=[],summary:m,url:$}=e;return t.html`
<header class="masthead">
${n&&t.html`<img src="${n}" alt="" />`}
<div>${l&&t.html`<h1>${l}</h1>`} ${o&&t.html`<h2>${o}</h2>`}</div>
${m&&t.html`<article>${d(m)}</article>`}
<ul class="icon-list">
${r?.city&&t.html`
<li>
${p("map-pin")} ${r.city}${r.countryCode&&t.html`, ${S(r.countryCode)}`}
</li>
`}
${i&&t.html`
<li>
${p("mail")}
<a href="mailto:${i}">${i}</a>
</li>
`}
${a&&t.html`
<li>
${p("phone")}
<a href="tel:${a.replace(/\s/g,"")}">${a}</a>
</li>
`}
${$&&t.html`<li>${p("link")} ${h($)}</li>`}
${c.map(({network:u,url:g,username:y})=>t.html`
<li>
${u&&p(u,"user")} ${h(g,y)}
${u&&t.html`<span class="network">(${u})</span>`}
</li>
`)}
</ul>
</header>
`}function O(e=[]){return e.length>0&&t.html`
<section id="interests">
<h3>Interests</h3>
<div class="grid-list">
${e.map(({keywords:i=[],name:n})=>t.html`
<div>
${n&&t.html`<h4>${n}</h4>`}
${i.length>0&&t.html`
<ul class="tag-list">
${i.map(o=>t.html`<li>${o}</li>`)}
</ul>
`}
</div>
`)}
</div>
</section>
`}function A(e=[]){return e.length>0&&t.html`
<section id="languages">
<h3>Languages</h3>
<div class="grid-list">
${e.map(({fluency:i,language:n})=>t.html`<div>${n&&t.html`<h4>${n}</h4>`} ${i}</div>`)}
</div>
</section>
`}function M(e={}){const{name:i,summary:n}=e;return t.html`
${i&&t.html`<title>${i}</title>`}
${n&&t.html`<meta name="description" content="${d(n,!0)}" />`}
`}const F=e=>Intl.ListFormat?new Intl.ListFormat("en").format(e):e.join(", ");function W(e=[]){return e.length>0&&t.html`
<section id="projects">
<h3>Projects</h3>
<div class="stack">
${e.map(({description:i,entity:n,highlights:o=[],keywords:r=[],name:l,startDate:a,endDate:c,roles:m=[],type:$,url:u})=>t.html`
<article>
<header>
<h4>${h(u,l)}</h4>
<div class="meta">
<div>
${m.length>0&&t.html`<strong>${F(m)}</strong>`}
${n&&t.html`at <strong>${n}</strong>`}
</div>
${a&&t.html`<div>${f(a,c)}</div>`} ${$&&t.html`<div>${$}</div>`}
</div>
</header>
${i&&d(i)}
${o.length>0&&t.html`
<ul>
${o.map(g=>t.html`<li>${d(g)}</li>`)}
</ul>
`}
${r.length>0&&t.html`
<ul class="tag-list">
${r.map(g=>t.html`<li>${g}</li>`)}
</ul>
`}
</article>
`)}
</div>
</section>
`}function B(e=[]){return e.length>0&&t.html`
<section id="publications">
<h3>Publications</h3>
<div class="stack">
${e.map(({name:i,publisher:n,releaseDate:o,summary:r,url:l})=>t.html`
<article>
<header>
<h4>${h(l,i)}</h4>
<div class="meta">
${n&&t.html`<div>Published by <strong>${n}</strong></div>`}
${o&&v(o)}
</div>
</header>
${r&&d(r)}
</article>
`)}
</div>
</section>
`}function H(e=[]){return e.length>0&&t.html`
<section id="references">
<h3>References</h3>
<div class="stack">
${e.map(({name:i,reference:n})=>t.html`
<blockquote>
${n&&d(n)}
${i&&t.html`
<p>
<cite>${i}</cite>
</p>
`}
</blockquote>
`)}
</div>
</section>
`}function N(e=[]){return e.length>0&&t.html`
<section id="skills">
<h3>Skills</h3>
<div class="grid-list">
${e.map(({keywords:i=[],name:n})=>t.html`
<div>
${n&&t.html`<h4>${n}</h4>`}
${i.length>0&&t.html`
<ul class="tag-list">
${i.map(o=>t.html`<li>${o}</li>`)}
</ul>
`}
</div>
`)}
</div>
</section>
`}function U(e=[]){return e.length>0&&t.html`
<section id="volunteer">
<h3>Volunteer</h3>
<div class="stack">
${e.map(({highlights:i=[],organization:n,position:o,startDate:r,endDate:l,summary:a,url:c})=>t.html`
<article>
<header>
<h4>${h(c,n)}</h4>
<div class="meta">
<strong>${o}</strong>
${r&&t.html`<div>${f(r,l)}</div>`}
</div>
</header>
${a&&d(a)}
${i.length>0&&t.html`
<ul>
${i.map(m=>t.html`<li>${d(m)}</li>`)}
</ul>
`}
</article>
`)}
</div>
</section>
`}function V(e=[]){const i=e.reduce((n,{description:o,name:r,url:l,...a})=>{const c=n[n.length-1];return c&&c.name===r&&c.description===o&&c.url===l?c.items.push(a):n.push({description:o,name:r,url:l,items:[a]}),n},[]);return e.length>0&&t.html`
<section id="work">
<h3>Work</h3>
<div class="stack">
${i.map(({description:n,name:o,url:r,items:l=[]})=>t.html`
<article>
<header>
<h4>${h(r,o)}</h4>
<div class="meta">${n&&t.html`<div>${n}</div>`}</div>
</header>
<div class="timeline">
${l.map(({highlights:a=[],location:c,position:m,startDate:$,endDate:u,summary:g})=>t.html`
<div>
<div>
<h5>${m}</h5>
<div class="meta">
${$&&t.html`<div>${f($,u)}</div>`}
${c&&t.html`<div>${c}</div>`}
</div>
</div>
${g&&d(g)}
${a.length>0&&t.html`
<ul>
${a.map(y=>t.html`<li>${d(y)}</li>`)}
</ul>
`}
</div>
`)}
</div>
</article>
`)}
</div>
</section>
`}function Y(e,{css:i,js:n}={}){return t.html`
<html lang="en" style="${j(e.meta)}">
<head>
<meta charset="utf-8" />
${M(e.basics)}
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Lato:400,700&display=swap" />
${i&&t.html`<style>
${i}
</style>`}
${n&&t.html(w||(w=x([`<script type="module">
`,`
<\/script>`])),n)}
</head>
<body>
${E(e.basics)} ${V(e.work)} ${U(e.volunteer)} ${R(e.education)}
${W(e.projects)} ${q(e.awards)} ${P(e.certificates)}
${B(e.publications)} ${N(e.skills)} ${A(e.languages)}
${O(e.interests)} ${H(e.references)}
</body>
</html>`}const Z={mediaType:"print",printBackground:!0},G=e=>Y(e,{css:C,js:z});s.pdfRenderOptions=Z,s.render=G,Object.defineProperty(s,Symbol.toStringTag,{value:"Module"})});