style(prettier): format all files and add CI check
This commit is contained in:
parent
a1d06cded1
commit
082678444d
|
@ -26,6 +26,9 @@ jobs:
|
||||||
- name: Test
|
- name: Test
|
||||||
run: npm test -- --coverage
|
run: npm test -- --coverage
|
||||||
|
|
||||||
|
- name: Format-check
|
||||||
|
run: npm run format -- --check
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
run: npm run build
|
run: npm run build
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{
|
{
|
||||||
"*.js": ["eslint --fix", "prettier --write"],
|
"*.js": ["eslint --fix", "prettier --write"],
|
||||||
"*.{css,json,md,yml}": "prettier --write"
|
"*.{css,html,json,md,yml}": "prettier --write"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
{
|
{
|
||||||
"arrowParens": "avoid",
|
"arrowParens": "avoid",
|
||||||
|
"plugins": ["prettier-plugin-organize-imports", "prettier-plugin-packagejson"],
|
||||||
"printWidth": 120,
|
"printWidth": 120,
|
||||||
"semi": false,
|
"semi": false,
|
||||||
"singleQuote": true
|
"singleQuote": true
|
||||||
|
|
|
@ -7,27 +7,27 @@ import Date from './date.js'
|
||||||
* @returns {string | false}
|
* @returns {string | false}
|
||||||
*/
|
*/
|
||||||
export default function Awards(awards = []) {
|
export default function Awards(awards = []) {
|
||||||
return awards.length > 0 && html`
|
return (
|
||||||
<section id="awards">
|
awards.length > 0 &&
|
||||||
<h3>Awards</h3>
|
html`
|
||||||
<div class="stack">
|
<section id="awards">
|
||||||
${awards.map(({ awarder, date, summary, title }) => html`
|
<h3>Awards</h3>
|
||||||
<article>
|
<div class="stack">
|
||||||
<header>
|
${awards.map(
|
||||||
<h4>${title}</h4>
|
({ awarder, date, summary, title }) => html`
|
||||||
<div class="meta">
|
<article>
|
||||||
${awarder && html`
|
<header>
|
||||||
<div>
|
<h4>${title}</h4>
|
||||||
Awarded by <strong>${awarder}</strong>
|
<div class="meta">
|
||||||
|
${awarder && html`<div>Awarded by <strong>${awarder}</strong></div>`} ${date && Date(date)}
|
||||||
</div>
|
</div>
|
||||||
`}
|
</header>
|
||||||
${date && Date(date)}
|
${summary && markdown(summary)}
|
||||||
</div>
|
</article>
|
||||||
</header>
|
`,
|
||||||
${summary && markdown(summary)}
|
)}
|
||||||
</article>
|
</div>
|
||||||
`)}
|
</section>
|
||||||
</div>
|
`
|
||||||
</section>
|
)
|
||||||
`
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,26 +7,26 @@ import Link from './link.js'
|
||||||
* @returns {string | false}
|
* @returns {string | false}
|
||||||
*/
|
*/
|
||||||
export default function Certificates(certificates = []) {
|
export default function Certificates(certificates = []) {
|
||||||
return certificates.length > 0 && html`
|
return (
|
||||||
<section id="certificates">
|
certificates.length > 0 &&
|
||||||
<h3>Certificates</h3>
|
html`
|
||||||
<div class="stack">
|
<section id="certificates">
|
||||||
${certificates.map(({ date, issuer, name, url }) => html`
|
<h3>Certificates</h3>
|
||||||
<article>
|
<div class="stack">
|
||||||
<header>
|
${certificates.map(
|
||||||
<h4>${Link(url, name)}</h4>
|
({ date, issuer, name, url }) => html`
|
||||||
<div class="meta">
|
<article>
|
||||||
${issuer && html`
|
<header>
|
||||||
<div>
|
<h4>${Link(url, name)}</h4>
|
||||||
Issued by <strong>${issuer}</strong>
|
<div class="meta">
|
||||||
|
${issuer && html`<div>Issued by <strong>${issuer}</strong></div>`} ${date && Date(date)}
|
||||||
</div>
|
</div>
|
||||||
`}
|
</header>
|
||||||
${date && Date(date)}
|
</article>
|
||||||
</div>
|
`,
|
||||||
</header>
|
)}
|
||||||
</article>
|
</div>
|
||||||
`)}
|
</section>
|
||||||
</div>
|
`
|
||||||
</section>
|
)
|
||||||
`
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,29 +8,35 @@ import Link from './link.js'
|
||||||
* @returns {string | false}
|
* @returns {string | false}
|
||||||
*/
|
*/
|
||||||
export default function Education(education = []) {
|
export default function Education(education = []) {
|
||||||
return education.length > 0 && html`
|
return (
|
||||||
<section id="education">
|
education.length > 0 &&
|
||||||
<h3>Education</h3>
|
html`
|
||||||
<div class="stack">
|
<section id="education">
|
||||||
${education.map(({ area, courses = [], institution, startDate, endDate, studyType, url }) => html`
|
<h3>Education</h3>
|
||||||
<article>
|
<div class="stack">
|
||||||
<header>
|
${education.map(
|
||||||
<h4>${Link(url, institution)}</h4>
|
({ area, courses = [], institution, startDate, endDate, studyType, url }) => html`
|
||||||
<div class="meta">
|
<article>
|
||||||
${area && html`<strong>${area}</strong>`}
|
<header>
|
||||||
${startDate && html`<div>${Duration(startDate, endDate)}</div>`}
|
<h4>${Link(url, institution)}</h4>
|
||||||
</div>
|
<div class="meta">
|
||||||
</header>
|
${area && html`<strong>${area}</strong>`}
|
||||||
${studyType && markdown(studyType)}
|
${startDate && html`<div>${Duration(startDate, endDate)}</div>`}
|
||||||
${courses.length > 0 && html`
|
</div>
|
||||||
<h5>Courses</h5>
|
</header>
|
||||||
<ul>
|
${studyType && markdown(studyType)}
|
||||||
${courses.map(course => html`<li>${markdown(course)}</li>`)}
|
${courses.length > 0 &&
|
||||||
</ul>
|
html`
|
||||||
`}
|
<h5>Courses</h5>
|
||||||
</article>
|
<ul>
|
||||||
`)}
|
${courses.map(course => html`<li>${markdown(course)}</li>`)}
|
||||||
</div>
|
</ul>
|
||||||
</section>
|
`}
|
||||||
`
|
</article>
|
||||||
|
`,
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
`
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,9 +7,8 @@ import Link from './link.js'
|
||||||
* @param {string} countryCode
|
* @param {string} countryCode
|
||||||
* @returns {string | undefined}
|
* @returns {string | undefined}
|
||||||
*/
|
*/
|
||||||
const formatCountry = countryCode => Intl.DisplayNames
|
const formatCountry = countryCode =>
|
||||||
? new Intl.DisplayNames(['en'], { type: 'region' }).of(countryCode)
|
Intl.DisplayNames ? new Intl.DisplayNames(['en'], { type: 'region' }).of(countryCode) : countryCode
|
||||||
: countryCode
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {import('../schema.d.ts').ResumeSchema['basics']} basics
|
* @param {import('../schema.d.ts').ResumeSchema['basics']} basics
|
||||||
|
@ -20,44 +19,39 @@ export default function Header(basics = {}) {
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<header class="masthead">
|
<header class="masthead">
|
||||||
${image && html`<img src="${image}" alt="">`}
|
${image && html`<img src="${image}" alt="" />`}
|
||||||
<div>
|
<div>${name && html`<h1>${name}</h1>`} ${label && html`<h2>${label}</h2>`}</div>
|
||||||
${name && html`<h1>${name}</h1>`}
|
|
||||||
${label && html`<h2>${label}</h2>`}
|
|
||||||
</div>
|
|
||||||
${summary && html`<article>${markdown(summary)}</article>`}
|
${summary && html`<article>${markdown(summary)}</article>`}
|
||||||
<ul class="icon-list">
|
<ul class="icon-list">
|
||||||
${location?.city && html`
|
${location?.city &&
|
||||||
|
html`
|
||||||
<li>
|
<li>
|
||||||
${Icon('map-pin')}
|
${Icon('map-pin')} ${location.city}${location.countryCode && html`, ${formatCountry(location.countryCode)}`}
|
||||||
${location.city}${location.countryCode && html`, ${formatCountry(location.countryCode)}`}
|
|
||||||
</li>
|
</li>
|
||||||
`}
|
`}
|
||||||
${email && html`
|
${email &&
|
||||||
|
html`
|
||||||
<li>
|
<li>
|
||||||
${Icon('mail')}
|
${Icon('mail')}
|
||||||
<a href="mailto:${email}">${email}</a>
|
<a href="mailto:${email}">${email}</a>
|
||||||
</li>
|
</li>
|
||||||
`}
|
`}
|
||||||
${phone && html`
|
${phone &&
|
||||||
|
html`
|
||||||
<li>
|
<li>
|
||||||
${Icon('phone')}
|
${Icon('phone')}
|
||||||
<a href="tel:${phone.replace(/\s/g, '')}">${phone}</a>
|
<a href="tel:${phone.replace(/\s/g, '')}">${phone}</a>
|
||||||
</li>
|
</li>
|
||||||
`}
|
`}
|
||||||
${url && html`
|
${url && html`<li>${Icon('link')} ${Link(url)}</li>`}
|
||||||
<li>
|
${profiles.map(
|
||||||
${Icon('link')}
|
({ network, url, username }) => html`
|
||||||
${Link(url)}
|
<li>
|
||||||
</li>
|
${network && Icon(network, 'user')} ${Link(url, username)}
|
||||||
`}
|
${network && html`<span class="network">(${network})</span>`}
|
||||||
${profiles.map(({ network, url, username }) => html`
|
</li>
|
||||||
<li>
|
`,
|
||||||
${network && Icon(network, 'user')}
|
)}
|
||||||
${Link(url, username)}
|
|
||||||
${network && html`<span class="network">(${network})</span>`}
|
|
||||||
</li>
|
|
||||||
`)}
|
|
||||||
</ul>
|
</ul>
|
||||||
</header>
|
</header>
|
||||||
`
|
`
|
||||||
|
|
|
@ -5,21 +5,27 @@ import html from '../utils/html.js'
|
||||||
* @returns {string | false}
|
* @returns {string | false}
|
||||||
*/
|
*/
|
||||||
export default function Interests(interests = []) {
|
export default function Interests(interests = []) {
|
||||||
return interests.length > 0 && html`
|
return (
|
||||||
<section id="interests">
|
interests.length > 0 &&
|
||||||
<h3>Interests</h3>
|
html`
|
||||||
<div class="grid-list">
|
<section id="interests">
|
||||||
${interests.map(({ keywords = [], name }) => html`
|
<h3>Interests</h3>
|
||||||
<div>
|
<div class="grid-list">
|
||||||
${name && html`<h4>${name}</h4>`}
|
${interests.map(
|
||||||
${keywords.length > 0 && html`
|
({ keywords = [], name }) => html`
|
||||||
<ul class="tag-list">
|
<div>
|
||||||
${keywords.map(keyword => html`<li>${keyword}</li>`)}
|
${name && html`<h4>${name}</h4>`}
|
||||||
</ul>
|
${keywords.length > 0 &&
|
||||||
`}
|
html`
|
||||||
</div>
|
<ul class="tag-list">
|
||||||
`)}
|
${keywords.map(keyword => html`<li>${keyword}</li>`)}
|
||||||
</div>
|
</ul>
|
||||||
</section>
|
`}
|
||||||
`
|
</div>
|
||||||
|
`,
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
`
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,17 +5,17 @@ import html from '../utils/html.js'
|
||||||
* @returns {string | false}
|
* @returns {string | false}
|
||||||
*/
|
*/
|
||||||
export default function Languages(languages = []) {
|
export default function Languages(languages = []) {
|
||||||
return languages.length > 0 && html`
|
return (
|
||||||
<section id="languages">
|
languages.length > 0 &&
|
||||||
<h3>Languages</h3>
|
html`
|
||||||
<div class="grid-list">
|
<section id="languages">
|
||||||
${languages.map(({ fluency, language }) => html`
|
<h3>Languages</h3>
|
||||||
<div>
|
<div class="grid-list">
|
||||||
${language && html`<h4>${language}</h4>`}
|
${languages.map(
|
||||||
${fluency}
|
({ fluency, language }) => html`<div>${language && html`<h4>${language}</h4>`} ${fluency}</div>`,
|
||||||
</div>
|
)}
|
||||||
`)}
|
</div>
|
||||||
</div>
|
</section>
|
||||||
</section>
|
`
|
||||||
`
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,5 @@ const formatURL = url => url.replace(/^(https?:|)\/\//, '').replace(/\/$/, '')
|
||||||
* @returns {string | undefined}
|
* @returns {string | undefined}
|
||||||
*/
|
*/
|
||||||
export default function Link(url, name) {
|
export default function Link(url, name) {
|
||||||
return name
|
return name ? (url ? html`<a href="${url}">${name}</a>` : name) : url && html`<a href="${url}">${formatURL(url)}</a>`
|
||||||
? (url ? html`<a href="${url}">${name}</a>` : name)
|
|
||||||
: url && html`<a href="${url}">${formatURL(url)}</a>`
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,6 @@ export default function Meta(basics = {}) {
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
${name && html`<title>${name}</title>`}
|
${name && html`<title>${name}</title>`}
|
||||||
${summary && html`<meta name="description" content="${markdown(summary, true)}">`}
|
${summary && html`<meta name="description" content="${markdown(summary, true)}" />`}
|
||||||
`
|
`
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,46 +7,61 @@ import Link from './link.js'
|
||||||
* @param {string[]} roles
|
* @param {string[]} roles
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
const formatRoles = roles => Intl.ListFormat
|
const formatRoles = roles => (Intl.ListFormat ? new Intl.ListFormat('en').format(roles) : roles.join(', '))
|
||||||
? new Intl.ListFormat('en').format(roles)
|
|
||||||
: roles.join(', ')
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {import('../schema.d.ts').ResumeSchema['projects']} projects
|
* @param {import('../schema.d.ts').ResumeSchema['projects']} projects
|
||||||
* @returns {string | false}
|
* @returns {string | false}
|
||||||
*/
|
*/
|
||||||
export default function Projects(projects = []) {
|
export default function Projects(projects = []) {
|
||||||
return projects.length > 0 && html`
|
return (
|
||||||
<section id="projects">
|
projects.length > 0 &&
|
||||||
<h3>Projects</h3>
|
html`
|
||||||
<div class="stack">
|
<section id="projects">
|
||||||
${projects.map(({ description, entity, highlights = [], keywords = [], name, startDate, endDate, roles = [], type, url }) => html`
|
<h3>Projects</h3>
|
||||||
<article>
|
<div class="stack">
|
||||||
<header>
|
${projects.map(
|
||||||
<h4>${Link(url, name)}</h4>
|
({
|
||||||
<div class="meta">
|
description,
|
||||||
<div>
|
entity,
|
||||||
${roles.length > 0 && html`<strong>${formatRoles(roles)}</strong>`}
|
highlights = [],
|
||||||
${entity && html`at <strong>${entity}</strong>`}
|
keywords = [],
|
||||||
</div>
|
name,
|
||||||
${startDate && html`<div>${Duration(startDate, endDate)}</div>`}
|
startDate,
|
||||||
${type && html`<div>${type}</div>`}
|
endDate,
|
||||||
</div>
|
roles = [],
|
||||||
</header>
|
type,
|
||||||
${description && markdown(description)}
|
url,
|
||||||
${highlights.length > 0 && html`
|
}) => html`
|
||||||
<ul>
|
<article>
|
||||||
${highlights.map(highlight => html`<li>${markdown(highlight)}</li>`)}
|
<header>
|
||||||
</ul>
|
<h4>${Link(url, name)}</h4>
|
||||||
`}
|
<div class="meta">
|
||||||
${keywords.length > 0 && html`
|
<div>
|
||||||
<ul class="tag-list">
|
${roles.length > 0 && html`<strong>${formatRoles(roles)}</strong>`}
|
||||||
${keywords.map(keyword => html`<li>${keyword}</li>`)}
|
${entity && html`at <strong>${entity}</strong>`}
|
||||||
</ul>
|
</div>
|
||||||
`}
|
${startDate && html`<div>${Duration(startDate, endDate)}</div>`} ${type && html`<div>${type}</div>`}
|
||||||
</article>
|
</div>
|
||||||
`)}
|
</header>
|
||||||
</div>
|
${description && markdown(description)}
|
||||||
</section>
|
${highlights.length > 0 &&
|
||||||
`
|
html`
|
||||||
|
<ul>
|
||||||
|
${highlights.map(highlight => html`<li>${markdown(highlight)}</li>`)}
|
||||||
|
</ul>
|
||||||
|
`}
|
||||||
|
${keywords.length > 0 &&
|
||||||
|
html`
|
||||||
|
<ul class="tag-list">
|
||||||
|
${keywords.map(keyword => html`<li>${keyword}</li>`)}
|
||||||
|
</ul>
|
||||||
|
`}
|
||||||
|
</article>
|
||||||
|
`,
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
`
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,27 +8,28 @@ import Link from './link.js'
|
||||||
* @returns {string | false}
|
* @returns {string | false}
|
||||||
*/
|
*/
|
||||||
export default function Publications(publications = []) {
|
export default function Publications(publications = []) {
|
||||||
return publications.length > 0 && html`
|
return (
|
||||||
<section id="publications">
|
publications.length > 0 &&
|
||||||
<h3>Publications</h3>
|
html`
|
||||||
<div class="stack">
|
<section id="publications">
|
||||||
${publications.map(({ name, publisher, releaseDate, summary, url }) => html`
|
<h3>Publications</h3>
|
||||||
<article>
|
<div class="stack">
|
||||||
<header>
|
${publications.map(
|
||||||
<h4>${Link(url, name)}</h4>
|
({ name, publisher, releaseDate, summary, url }) => html`
|
||||||
<div class="meta">
|
<article>
|
||||||
${publisher && html`
|
<header>
|
||||||
<div>
|
<h4>${Link(url, name)}</h4>
|
||||||
Published by <strong>${publisher}</strong>
|
<div class="meta">
|
||||||
|
${publisher && html`<div>Published by <strong>${publisher}</strong></div>`}
|
||||||
|
${releaseDate && Date(releaseDate)}
|
||||||
</div>
|
</div>
|
||||||
`}
|
</header>
|
||||||
${releaseDate && Date(releaseDate)}
|
${summary && markdown(summary)}
|
||||||
</div>
|
</article>
|
||||||
</header>
|
`,
|
||||||
${summary && markdown(summary)}
|
)}
|
||||||
</article>
|
</div>
|
||||||
`)}
|
</section>
|
||||||
</div>
|
`
|
||||||
</section>
|
)
|
||||||
`
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,21 +6,27 @@ import markdown from '../utils/markdown.js'
|
||||||
* @returns {string | false}
|
* @returns {string | false}
|
||||||
*/
|
*/
|
||||||
export default function References(references = []) {
|
export default function References(references = []) {
|
||||||
return references.length > 0 && html`
|
return (
|
||||||
<section id="references">
|
references.length > 0 &&
|
||||||
<h3>References</h3>
|
html`
|
||||||
<div class="stack">
|
<section id="references">
|
||||||
${references.map(({ name, reference }) => html`
|
<h3>References</h3>
|
||||||
<blockquote>
|
<div class="stack">
|
||||||
${reference && markdown(reference)}
|
${references.map(
|
||||||
${name && html`
|
({ name, reference }) => html`
|
||||||
<p>
|
<blockquote>
|
||||||
<cite>${name}</cite>
|
${reference && markdown(reference)}
|
||||||
</p>
|
${name &&
|
||||||
`}
|
html`
|
||||||
</blockquote>
|
<p>
|
||||||
`)}
|
<cite>${name}</cite>
|
||||||
</div>
|
</p>
|
||||||
</section>
|
`}
|
||||||
`
|
</blockquote>
|
||||||
|
`,
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
`
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,21 +5,27 @@ import html from '../utils/html.js'
|
||||||
* @returns {string | false}
|
* @returns {string | false}
|
||||||
*/
|
*/
|
||||||
export default function Skills(skills = []) {
|
export default function Skills(skills = []) {
|
||||||
return skills.length > 0 && html`
|
return (
|
||||||
<section id="skills">
|
skills.length > 0 &&
|
||||||
<h3>Skills</h3>
|
html`
|
||||||
<div class="grid-list">
|
<section id="skills">
|
||||||
${skills.map(({ keywords = [], name }) => html`
|
<h3>Skills</h3>
|
||||||
<div>
|
<div class="grid-list">
|
||||||
${name && html`<h4>${name}</h4>`}
|
${skills.map(
|
||||||
${keywords.length > 0 && html`
|
({ keywords = [], name }) => html`
|
||||||
<ul class="tag-list">
|
<div>
|
||||||
${keywords.map(keyword => html`<li>${keyword}</li>`)}
|
${name && html`<h4>${name}</h4>`}
|
||||||
</ul>
|
${keywords.length > 0 &&
|
||||||
`}
|
html`
|
||||||
</div>
|
<ul class="tag-list">
|
||||||
`)}
|
${keywords.map(keyword => html`<li>${keyword}</li>`)}
|
||||||
</div>
|
</ul>
|
||||||
</section>
|
`}
|
||||||
`
|
</div>
|
||||||
|
`,
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
`
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,28 +8,34 @@ import Link from './link.js'
|
||||||
* @returns {string | false}
|
* @returns {string | false}
|
||||||
*/
|
*/
|
||||||
export default function Volunteer(volunteer = []) {
|
export default function Volunteer(volunteer = []) {
|
||||||
return volunteer.length > 0 && html`
|
return (
|
||||||
<section id="volunteer">
|
volunteer.length > 0 &&
|
||||||
<h3>Volunteer</h3>
|
html`
|
||||||
<div class="stack">
|
<section id="volunteer">
|
||||||
${volunteer.map(({ highlights = [], organization, position, startDate, endDate, summary, url }) => html`
|
<h3>Volunteer</h3>
|
||||||
<article>
|
<div class="stack">
|
||||||
<header>
|
${volunteer.map(
|
||||||
<h4>${Link(url, organization)}</h4>
|
({ highlights = [], organization, position, startDate, endDate, summary, url }) => html`
|
||||||
<div class="meta">
|
<article>
|
||||||
<strong>${position}</strong>
|
<header>
|
||||||
${startDate && html`<div>${Duration(startDate, endDate)}</div>`}
|
<h4>${Link(url, organization)}</h4>
|
||||||
</div>
|
<div class="meta">
|
||||||
</header>
|
<strong>${position}</strong>
|
||||||
${summary && markdown(summary)}
|
${startDate && html`<div>${Duration(startDate, endDate)}</div>`}
|
||||||
${highlights.length > 0 && html`
|
</div>
|
||||||
<ul>
|
</header>
|
||||||
${highlights.map(highlight => html`<li>${markdown(highlight)}</li>`)}
|
${summary && markdown(summary)}
|
||||||
</ul>
|
${highlights.length > 0 &&
|
||||||
`}
|
html`
|
||||||
</article>
|
<ul>
|
||||||
`)}
|
${highlights.map(highlight => html`<li>${markdown(highlight)}</li>`)}
|
||||||
</div>
|
</ul>
|
||||||
</section>
|
`}
|
||||||
`
|
</article>
|
||||||
|
`,
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
`
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,40 +19,46 @@ export default function Work(work = []) {
|
||||||
return acc
|
return acc
|
||||||
}, /** @type {NestedWork[]} */ ([]))
|
}, /** @type {NestedWork[]} */ ([]))
|
||||||
|
|
||||||
return work.length > 0 && html`
|
return (
|
||||||
<section id="work">
|
work.length > 0 &&
|
||||||
<h3>Work</h3>
|
html`
|
||||||
<div class="stack">
|
<section id="work">
|
||||||
${nestedWork.map(({ description, name, url, items = [] }) => html`
|
<h3>Work</h3>
|
||||||
<article>
|
<div class="stack">
|
||||||
<header>
|
${nestedWork.map(
|
||||||
<h4>${Link(url, name)}</h4>
|
({ description, name, url, items = [] }) => html`
|
||||||
<div class="meta">
|
<article>
|
||||||
${description && html`<div>${description}</div>`}
|
<header>
|
||||||
</div>
|
<h4>${Link(url, name)}</h4>
|
||||||
</header>
|
<div class="meta">${description && html`<div>${description}</div>`}</div>
|
||||||
<div class="timeline">
|
</header>
|
||||||
${items.map(({highlights = [], location, position, startDate, endDate, summary }) => html`
|
<div class="timeline">
|
||||||
<div>
|
${items.map(
|
||||||
<div>
|
({ highlights = [], location, position, startDate, endDate, summary }) => html`
|
||||||
<h5>${position}</h5>
|
<div>
|
||||||
<div class="meta">
|
<div>
|
||||||
${startDate && html`<div>${Duration(startDate, endDate)}</div>`}
|
<h5>${position}</h5>
|
||||||
${location && html`<div>${location}</div>`}
|
<div class="meta">
|
||||||
</div>
|
${startDate && html`<div>${Duration(startDate, endDate)}</div>`}
|
||||||
</div>
|
${location && html`<div>${location}</div>`}
|
||||||
${summary && markdown(summary)}
|
</div>
|
||||||
${highlights.length > 0 && html`
|
</div>
|
||||||
<ul>
|
${summary && markdown(summary)}
|
||||||
${highlights.map(highlight => html`<li>${markdown(highlight)}</li>`)}
|
${highlights.length > 0 &&
|
||||||
</ul>
|
html`
|
||||||
`}
|
<ul>
|
||||||
|
${highlights.map(highlight => html`<li>${markdown(highlight)}</li>`)}
|
||||||
|
</ul>
|
||||||
|
`}
|
||||||
|
</div>
|
||||||
|
`,
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
`)}
|
</article>
|
||||||
</div>
|
`,
|
||||||
</article>
|
)}
|
||||||
`)}
|
</div>
|
||||||
</div>
|
</section>
|
||||||
</section>
|
`
|
||||||
`
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import { indentWithTab } from '@codemirror/commands'
|
import { indentWithTab } from '@codemirror/commands'
|
||||||
import { json } from '@codemirror/lang-json'
|
import { json } from '@codemirror/lang-json'
|
||||||
import { EditorView, keymap } from '@codemirror/view'
|
|
||||||
import { oneDark } from '@codemirror/theme-one-dark'
|
import { oneDark } from '@codemirror/theme-one-dark'
|
||||||
|
import { EditorView, keymap } from '@codemirror/view'
|
||||||
import { basicSetup } from 'codemirror'
|
import { basicSetup } from 'codemirror'
|
||||||
import { debounce } from 'debounce'
|
import { debounce } from 'debounce'
|
||||||
import resume from 'resume-schema/sample.resume.json' assert { type: 'json' }
|
import resume from 'resume-schema/sample.resume.json' assert { type: 'json' }
|
||||||
|
|
||||||
import { render } from './index.js'
|
|
||||||
import './editor.css'
|
import './editor.css'
|
||||||
|
import { render } from './index.js'
|
||||||
|
|
||||||
const preview = document.querySelector('iframe')
|
const preview = document.querySelector('iframe')
|
||||||
const printButton = document.querySelector('button[name=print]')
|
const printButton = document.querySelector('button[name=print]')
|
||||||
|
|
|
@ -31,7 +31,8 @@
|
||||||
"json-schema-to-typescript": "13.1.1",
|
"json-schema-to-typescript": "13.1.1",
|
||||||
"lint-staged": "14.0.1",
|
"lint-staged": "14.0.1",
|
||||||
"prettier": "3.0.3",
|
"prettier": "3.0.3",
|
||||||
"prettier-plugin-packagejson": "2.4.5",
|
"prettier-plugin-organize-imports": "3.2.3",
|
||||||
|
"prettier-plugin-packagejson": "2.4.6",
|
||||||
"resume-schema": "1.0.0",
|
"resume-schema": "1.0.0",
|
||||||
"typescript": "5.2.2",
|
"typescript": "5.2.2",
|
||||||
"vite": "4.4.9",
|
"vite": "4.4.9",
|
||||||
|
@ -4248,13 +4249,33 @@
|
||||||
"url": "https://github.com/prettier/prettier?sponsor=1"
|
"url": "https://github.com/prettier/prettier?sponsor=1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/prettier-plugin-organize-imports": {
|
||||||
|
"version": "3.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/prettier-plugin-organize-imports/-/prettier-plugin-organize-imports-3.2.3.tgz",
|
||||||
|
"integrity": "sha512-KFvk8C/zGyvUaE3RvxN2MhCLwzV6OBbFSkwZ2OamCrs9ZY4i5L77jQ/w4UmUr+lqX8qbaqVq6bZZkApn+IgJSg==",
|
||||||
|
"dev": true,
|
||||||
|
"peerDependencies": {
|
||||||
|
"@volar/vue-language-plugin-pug": "^1.0.4",
|
||||||
|
"@volar/vue-typescript": "^1.0.4",
|
||||||
|
"prettier": ">=2.0",
|
||||||
|
"typescript": ">=2.9"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@volar/vue-language-plugin-pug": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@volar/vue-typescript": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/prettier-plugin-packagejson": {
|
"node_modules/prettier-plugin-packagejson": {
|
||||||
"version": "2.4.5",
|
"version": "2.4.6",
|
||||||
"resolved": "https://registry.npmjs.org/prettier-plugin-packagejson/-/prettier-plugin-packagejson-2.4.5.tgz",
|
"resolved": "https://registry.npmjs.org/prettier-plugin-packagejson/-/prettier-plugin-packagejson-2.4.6.tgz",
|
||||||
"integrity": "sha512-glG71jE1gO3y5+JNAhC8X+4yrlN28rub6Aj461SKbaPie9RgMiHKcInH2Moi2VGOfkTXaEHBhg4uVMBqa+kBUA==",
|
"integrity": "sha512-5JGfzkJRL0DLNyhwmiAV9mV0hZLHDwddFCs2lc9CNxOChpoWUQVe8K4qTMktmevmDlMpok2uT10nvHUyU59sNw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"sort-package-json": "2.5.1",
|
"sort-package-json": "2.6.0",
|
||||||
"synckit": "0.8.5"
|
"synckit": "0.8.5"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
|
@ -4773,9 +4794,9 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/sort-package-json": {
|
"node_modules/sort-package-json": {
|
||||||
"version": "2.5.1",
|
"version": "2.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/sort-package-json/-/sort-package-json-2.5.1.tgz",
|
"resolved": "https://registry.npmjs.org/sort-package-json/-/sort-package-json-2.6.0.tgz",
|
||||||
"integrity": "sha512-vx/KoZxm8YNMUqdlw7SGTfqR5pqZ/sUfgOuRtDILiOy/3AvzhAibyUe2cY3OpLs3oRSow9up4yLVtQaM24rbDQ==",
|
"integrity": "sha512-XSQ+lY9bAYA8ZsoChcEoPlgcSMaheziEp1beox1JVxy1SV4F2jSq9+h2rJ+3mC/Dhu9Ius1DLnInD5AWcsDXZw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"detect-indent": "^7.0.1",
|
"detect-indent": "^7.0.1",
|
||||||
|
|
|
@ -28,8 +28,8 @@
|
||||||
"main": "./dist/index.cjs",
|
"main": "./dist/index.cjs",
|
||||||
"unpkg": "./dist/index.umd.cjs",
|
"unpkg": "./dist/index.umd.cjs",
|
||||||
"module": "./dist/index.js",
|
"module": "./dist/index.js",
|
||||||
"typings": "./dist/index.d.ts",
|
|
||||||
"source": "index.js",
|
"source": "index.js",
|
||||||
|
"typings": "./dist/index.d.ts",
|
||||||
"bin": {
|
"bin": {
|
||||||
"jsonresume-theme-even": "bin/cli.js"
|
"jsonresume-theme-even": "bin/cli.js"
|
||||||
},
|
},
|
||||||
|
@ -67,7 +67,8 @@
|
||||||
"json-schema-to-typescript": "13.1.1",
|
"json-schema-to-typescript": "13.1.1",
|
||||||
"lint-staged": "14.0.1",
|
"lint-staged": "14.0.1",
|
||||||
"prettier": "3.0.3",
|
"prettier": "3.0.3",
|
||||||
"prettier-plugin-packagejson": "2.4.5",
|
"prettier-plugin-organize-imports": "3.2.3",
|
||||||
|
"prettier-plugin-packagejson": "2.4.6",
|
||||||
"resume-schema": "1.0.0",
|
"resume-schema": "1.0.0",
|
||||||
"typescript": "5.2.2",
|
"typescript": "5.2.2",
|
||||||
"vite": "4.4.9",
|
"vite": "4.4.9",
|
||||||
|
|
28
resume.js
28
resume.js
|
@ -20,28 +20,22 @@ import html from './utils/html.js'
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export default function Resume(resume, css) {
|
export default function Resume(resume, css) {
|
||||||
return html`<!DOCTYPE html>
|
return html`<!doctype html>
|
||||||
<html lang="en" style="${colors(resume.meta)}">
|
<html lang="en" style="${colors(resume.meta)}">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8" />
|
||||||
${Meta(resume.basics)}
|
${Meta(resume.basics)}
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<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">
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Lato:400,700&display=swap" />
|
||||||
<style>${css}</style>
|
<style>
|
||||||
|
${css}
|
||||||
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
${Header(resume.basics)}
|
${Header(resume.basics)} ${Work(resume.work)} ${Volunteer(resume.volunteer)} ${Education(resume.education)}
|
||||||
${Work(resume.work)}
|
${Projects(resume.projects)} ${Awards(resume.awards)} ${Certificates(resume.certificates)}
|
||||||
${Volunteer(resume.volunteer)}
|
${Publications(resume.publications)} ${Skills(resume.skills)} ${Languages(resume.languages)}
|
||||||
${Education(resume.education)}
|
${Interests(resume.interests)} ${References(resume.references)}
|
||||||
${Projects(resume.projects)}
|
|
||||||
${Awards(resume.awards)}
|
|
||||||
${Certificates(resume.certificates)}
|
|
||||||
${Publications(resume.publications)}
|
|
||||||
${Skills(resume.skills)}
|
|
||||||
${Languages(resume.languages)}
|
|
||||||
${Interests(resume.interests)}
|
|
||||||
${References(resume.references)}
|
|
||||||
</body>
|
</body>
|
||||||
</html>`
|
</html>`
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,9 @@ body {
|
||||||
background: var(--color-background);
|
background: var(--color-background);
|
||||||
color: var(--color-primary);
|
color: var(--color-primary);
|
||||||
display: grid;
|
display: grid;
|
||||||
font: 1em/1.5 Lato, sans-serif;
|
font:
|
||||||
|
1em/1.5 Lato,
|
||||||
|
sans-serif;
|
||||||
gap: 2em;
|
gap: 2em;
|
||||||
grid-template-columns:
|
grid-template-columns:
|
||||||
[full-start]
|
[full-start]
|
||||||
|
@ -283,9 +285,6 @@ blockquote > * + *,
|
||||||
}
|
}
|
||||||
|
|
||||||
.grid-list {
|
.grid-list {
|
||||||
grid-template-columns: repeat(
|
grid-template-columns: repeat(auto-fit, minmax(calc((100% - 1em) / 2), 1fr));
|
||||||
auto-fit,
|
|
||||||
minmax(calc((100% - 1em) / 2), 1fr)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,32 +1,30 @@
|
||||||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||||
|
|
||||||
exports[`renders a resume 1`] = `
|
exports[`renders a resume 1`] = `
|
||||||
"<!DOCTYPE html>
|
"<!doctype html>
|
||||||
<html lang=\\"en\\" style=\\"--color-background-light:lightgray; --color-background-dark:darkgray;\\">
|
<html lang=\\"en\\" style=\\"--color-background-light:lightgray; --color-background-dark:darkgray;\\">
|
||||||
<head>
|
<head>
|
||||||
<meta charset=\\"utf-8\\">
|
<meta charset=\\"utf-8\\" />
|
||||||
|
|
||||||
<title>Richard Hendriks</title>
|
<title>Richard Hendriks</title>
|
||||||
<meta name=\\"description\\" content=\\"Richard hails from Tulsa. He has earned degrees from the University of Oklahoma and Stanford. (Go Sooners and Cardinal!) Before starting Pied Piper, he worked for Hooli as a part time software developer. While his work focuses on applied information theory, mostly optimizing lossless compression schema of both the length-limited and adaptive variants, his non-work interests range widely, everything from quantum computing to chaos theory. He could tell you about it, but THAT would NOT be a “length-limited” conversation!\\">
|
<meta name=\\"description\\" content=\\"Richard hails from Tulsa. He has earned degrees from the University of Oklahoma and Stanford. (Go Sooners and Cardinal!) Before starting Pied Piper, he worked for Hooli as a part time software developer. While his work focuses on applied information theory, mostly optimizing lossless compression schema of both the length-limited and adaptive variants, his non-work interests range widely, everything from quantum computing to chaos theory. He could tell you about it, but THAT would NOT be a “length-limited” conversation!\\" />
|
||||||
|
|
||||||
<meta name=\\"viewport\\" content=\\"width=device-width, initial-scale=1\\">
|
<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\\">
|
<link rel=\\"stylesheet\\" href=\\"https://fonts.googleapis.com/css?family=Lato:400,700&display=swap\\" />
|
||||||
<style></style>
|
<style>
|
||||||
|
|
||||||
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<header class=\\"masthead\\">
|
<header class=\\"masthead\\">
|
||||||
<img src=\\"image.jpg\\" alt=\\"\\">
|
<img src=\\"image.jpg\\" alt=\\"\\" />
|
||||||
<div>
|
<div><h1>Richard Hendriks</h1> <h2>Programmer</h2></div>
|
||||||
<h1>Richard Hendriks</h1>
|
|
||||||
<h2>Programmer</h2>
|
|
||||||
</div>
|
|
||||||
<article><p>Richard hails from Tulsa. He has earned degrees from the University of Oklahoma and Stanford. (Go Sooners and Cardinal!) Before starting Pied Piper, he worked for Hooli as a part time software developer. While his work focuses on applied information theory, mostly optimizing lossless compression schema of both the length-limited and adaptive variants, his non-work interests range widely, everything from quantum computing to chaos theory. He could tell you about it, but THAT would NOT be a “length-limited” conversation!</p></article>
|
<article><p>Richard hails from Tulsa. He has earned degrees from the University of Oklahoma and Stanford. (Go Sooners and Cardinal!) Before starting Pied Piper, he worked for Hooli as a part time software developer. While his work focuses on applied information theory, mostly optimizing lossless compression schema of both the length-limited and adaptive variants, his non-work interests range widely, everything from quantum computing to chaos theory. He could tell you about it, but THAT would NOT be a “length-limited” conversation!</p></article>
|
||||||
<ul class=\\"icon-list\\">
|
<ul class=\\"icon-list\\">
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
<svg xmlns=\\"http://www.w3.org/2000/svg\\" width=\\"16\\" height=\\"16\\" viewBox=\\"0 0 24 24\\" fill=\\"none\\" stroke=\\"currentColor\\" stroke-width=\\"2\\" stroke-linecap=\\"round\\" stroke-linejoin=\\"round\\" class=\\"feather feather-map-pin\\"><path d=\\"M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z\\"></path><circle cx=\\"12\\" cy=\\"10\\" r=\\"3\\"></circle></svg>
|
<svg xmlns=\\"http://www.w3.org/2000/svg\\" width=\\"16\\" height=\\"16\\" viewBox=\\"0 0 24 24\\" fill=\\"none\\" stroke=\\"currentColor\\" stroke-width=\\"2\\" stroke-linecap=\\"round\\" stroke-linejoin=\\"round\\" class=\\"feather feather-map-pin\\"><path d=\\"M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z\\"></path><circle cx=\\"12\\" cy=\\"10\\" r=\\"3\\"></circle></svg> San Francisco, United States
|
||||||
San Francisco, United States
|
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
@ -41,266 +39,234 @@ exports[`renders a resume 1`] = `
|
||||||
<a href=\\"tel:(912)555-4321\\">(912) 555-4321</a>
|
<a href=\\"tel:(912)555-4321\\">(912) 555-4321</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
<li><svg xmlns=\\"http://www.w3.org/2000/svg\\" width=\\"16\\" height=\\"16\\" viewBox=\\"0 0 24 24\\" fill=\\"none\\" stroke=\\"currentColor\\" stroke-width=\\"2\\" stroke-linecap=\\"round\\" stroke-linejoin=\\"round\\" class=\\"feather feather-link\\"><path d=\\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\\"></path><path d=\\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\\"></path></svg> <a href=\\"http://richardhendricks.example.com\\">richardhendricks.example.com</a></li>
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
<svg xmlns=\\"http://www.w3.org/2000/svg\\" width=\\"16\\" height=\\"16\\" viewBox=\\"0 0 24 24\\" fill=\\"none\\" stroke=\\"currentColor\\" stroke-width=\\"2\\" stroke-linecap=\\"round\\" stroke-linejoin=\\"round\\" class=\\"feather feather-link\\"><path d=\\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\\"></path><path d=\\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\\"></path></svg>
|
<svg xmlns=\\"http://www.w3.org/2000/svg\\" width=\\"16\\" height=\\"16\\" viewBox=\\"0 0 24 24\\" fill=\\"none\\" stroke=\\"currentColor\\" stroke-width=\\"2\\" stroke-linecap=\\"round\\" stroke-linejoin=\\"round\\" class=\\"feather feather-twitter\\"><path d=\\"M23 3a10.9 10.9 0 0 1-3.14 1.53 4.48 4.48 0 0 0-7.86 3v1A10.66 10.66 0 0 1 3 4s-4 9 5 13a11.64 11.64 0 0 1-7 2c9 5 20 0 20-11.5a4.5 4.5 0 0 0-.08-.83A7.72 7.72 0 0 0 23 3z\\"></path></svg> neutralthoughts
|
||||||
<a href=\\"http://richardhendricks.example.com\\">richardhendricks.example.com</a>
|
<span class=\\"network\\">(Twitter)</span>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
<li>
|
<svg xmlns=\\"http://www.w3.org/2000/svg\\" width=\\"16\\" height=\\"16\\" viewBox=\\"0 0 24 24\\" fill=\\"none\\" stroke=\\"currentColor\\" stroke-width=\\"2\\" stroke-linecap=\\"round\\" stroke-linejoin=\\"round\\" class=\\"feather feather-user\\"><path d=\\"M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2\\"></path><circle cx=\\"12\\" cy=\\"7\\" r=\\"4\\"></circle></svg> <a href=\\"https://soundcloud.example.com/dandymusicnl\\">dandymusicnl</a>
|
||||||
<svg xmlns=\\"http://www.w3.org/2000/svg\\" width=\\"16\\" height=\\"16\\" viewBox=\\"0 0 24 24\\" fill=\\"none\\" stroke=\\"currentColor\\" stroke-width=\\"2\\" stroke-linecap=\\"round\\" stroke-linejoin=\\"round\\" class=\\"feather feather-twitter\\"><path d=\\"M23 3a10.9 10.9 0 0 1-3.14 1.53 4.48 4.48 0 0 0-7.86 3v1A10.66 10.66 0 0 1 3 4s-4 9 5 13a11.64 11.64 0 0 1-7 2c9 5 20 0 20-11.5a4.5 4.5 0 0 0-.08-.83A7.72 7.72 0 0 0 23 3z\\"></path></svg>
|
<span class=\\"network\\">(SoundCloud)</span>
|
||||||
neutralthoughts
|
</li>
|
||||||
<span class=\\"network\\">(Twitter)</span>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li>
|
|
||||||
<svg xmlns=\\"http://www.w3.org/2000/svg\\" width=\\"16\\" height=\\"16\\" viewBox=\\"0 0 24 24\\" fill=\\"none\\" stroke=\\"currentColor\\" stroke-width=\\"2\\" stroke-linecap=\\"round\\" stroke-linejoin=\\"round\\" class=\\"feather feather-user\\"><path d=\\"M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2\\"></path><circle cx=\\"12\\" cy=\\"7\\" r=\\"4\\"></circle></svg>
|
|
||||||
<a href=\\"https://soundcloud.example.com/dandymusicnl\\">dandymusicnl</a>
|
|
||||||
<span class=\\"network\\">(SoundCloud)</span>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
|
<section id=\\"work\\">
|
||||||
<section id=\\"work\\">
|
<h3>Work</h3>
|
||||||
<h3>Work</h3>
|
<div class=\\"stack\\">
|
||||||
<div class=\\"stack\\">
|
|
||||||
|
<article>
|
||||||
<article>
|
<header>
|
||||||
<header>
|
<h4><a href=\\"http://piedpiper.example.com\\">Pied Piper</a></h4>
|
||||||
<h4><a href=\\"http://piedpiper.example.com\\">Pied Piper</a></h4>
|
<div class=\\"meta\\"><div>Awesome compression company</div></div>
|
||||||
<div class=\\"meta\\">
|
</header>
|
||||||
<div>Awesome compression company</div>
|
<div class=\\"timeline\\">
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
<div class=\\"timeline\\">
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<div>
|
|
||||||
<h5>CEO/President</h5>
|
|
||||||
<div class=\\"meta\\">
|
|
||||||
<div><time datetime=\\"2013-12-01\\">Dec 2013</time> – <time datetime=\\"2014-12-01\\">Dec 2014</time></div>
|
|
||||||
<div>Palo Alto, CA</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<p>Pied Piper is a multi-platform technology based on a proprietary universal compression algorithm that has consistently fielded high Weisman Scores™ that are not merely competitive, but approach the theoretical limit of lossless compression.</p>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><p>Build an algorithm for artist to detect if their music was violating copy right infringement laws</p></li><li><p>Successfully won Techcrunch Disrupt</p></li><li><p>Optimized an algorithm that holds the current world record for Weisman Scores</p></li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
<h5>CEO/President</h5>
|
||||||
|
<div class=\\"meta\\">
|
||||||
|
<div><time datetime=\\"2013-12-01\\">Dec 2013</time> – <time datetime=\\"2014-12-01\\">Dec 2014</time></div>
|
||||||
|
<div>Palo Alto, CA</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p>Pied Piper is a multi-platform technology based on a proprietary universal compression algorithm that has consistently fielded high Weisman Scores™ that are not merely competitive, but approach the theoretical limit of lossless compression.</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><p>Build an algorithm for artist to detect if their music was violating copy right infringement laws</p></li><li><p>Successfully won Techcrunch Disrupt</p></li><li><p>Optimized an algorithm that holds the current world record for Weisman Scores</p></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
</article>
|
||||||
</div>
|
|
||||||
</article>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
|
|
||||||
<section id=\\"volunteer\\">
|
|
||||||
<h3>Volunteer</h3>
|
|
||||||
<div class=\\"stack\\">
|
|
||||||
|
|
||||||
<article>
|
|
||||||
<header>
|
|
||||||
<h4><a href=\\"http://coderdojo.example.com/\\">CoderDojo</a></h4>
|
|
||||||
<div class=\\"meta\\">
|
|
||||||
<strong>Teacher</strong>
|
|
||||||
<div><time datetime=\\"2012-01-01\\">Jan 2012</time> – <time datetime=\\"2013-01-01\\">Jan 2013</time></div>
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
<p>Global movement of free coding clubs for young people.</p>
|
|
||||||
|
|
||||||
<ul>
|
</div>
|
||||||
<li><p>Awarded 'Teacher of the Month'</p></li>
|
</section>
|
||||||
</ul>
|
|
||||||
|
<section id=\\"volunteer\\">
|
||||||
|
<h3>Volunteer</h3>
|
||||||
|
<div class=\\"stack\\">
|
||||||
|
|
||||||
|
<article>
|
||||||
|
<header>
|
||||||
|
<h4><a href=\\"http://coderdojo.example.com/\\">CoderDojo</a></h4>
|
||||||
|
<div class=\\"meta\\">
|
||||||
|
<strong>Teacher</strong>
|
||||||
|
<div><time datetime=\\"2012-01-01\\">Jan 2012</time> – <time datetime=\\"2013-01-01\\">Jan 2013</time></div>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
<p>Global movement of free coding clubs for young people.</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><p>Awarded 'Teacher of the Month'</p></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
</article>
|
||||||
|
|
||||||
</article>
|
</div>
|
||||||
|
</section>
|
||||||
</div>
|
|
||||||
</section>
|
<section id=\\"education\\">
|
||||||
|
<h3>Education</h3>
|
||||||
|
<div class=\\"stack\\">
|
||||||
<section id=\\"education\\">
|
|
||||||
<h3>Education</h3>
|
<article>
|
||||||
<div class=\\"stack\\">
|
<header>
|
||||||
|
<h4><a href=\\"https://www.ou.edu/\\">University of Oklahoma</a></h4>
|
||||||
<article>
|
<div class=\\"meta\\">
|
||||||
<header>
|
<strong>Information Technology</strong>
|
||||||
<h4><a href=\\"https://www.ou.edu/\\">University of Oklahoma</a></h4>
|
<div><time datetime=\\"2011-06-01\\">Jun 2011</time> – <time datetime=\\"2014-01-01\\">Jan 2014</time></div>
|
||||||
<div class=\\"meta\\">
|
</div>
|
||||||
<strong>Information Technology</strong>
|
</header>
|
||||||
<div><time datetime=\\"2011-06-01\\">Jun 2011</time> – <time datetime=\\"2014-01-01\\">Jan 2014</time></div>
|
<p>Bachelor</p>
|
||||||
</div>
|
|
||||||
</header>
|
<h5>Courses</h5>
|
||||||
<p>Bachelor</p>
|
<ul>
|
||||||
|
<li><p>DB1101 - Basic SQL</p></li><li><p>CS2011 - Java Introduction</p></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
</article>
|
||||||
|
|
||||||
<h5>Courses</h5>
|
</div>
|
||||||
<ul>
|
</section>
|
||||||
<li><p>DB1101 - Basic SQL</p></li><li><p>CS2011 - Java Introduction</p></li>
|
|
||||||
</ul>
|
|
||||||
|
<section id=\\"projects\\">
|
||||||
|
<h3>Projects</h3>
|
||||||
|
<div class=\\"stack\\">
|
||||||
|
|
||||||
|
<article>
|
||||||
|
<header>
|
||||||
|
<h4><a href=\\"missdirection.example.com\\">Miss Direction</a></h4>
|
||||||
|
<div class=\\"meta\\">
|
||||||
|
<div>
|
||||||
|
<strong>Team lead and Designer</strong>
|
||||||
|
at <strong>Smoogle</strong>
|
||||||
|
</div>
|
||||||
|
<div><time datetime=\\"2016-08-24\\">Aug 2016</time> – <time datetime=\\"2016-08-24\\">Aug 2016</time></div> <div>application</div>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
<p>A mapping engine that misguides you</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><p>Won award at AIHacks 2016</p></li><li><p>Built by all women team of newbie programmers</p></li><li><p>Using modern technologies such as GoogleMaps, Chrome Extension and Javascript</p></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
<ul class=\\"tag-list\\">
|
||||||
|
<li>GoogleMaps</li><li>Chrome Extension</li><li>Javascript</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
</article>
|
||||||
|
|
||||||
</article>
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id=\\"awards\\">
|
||||||
|
<h3>Awards</h3>
|
||||||
|
<div class=\\"stack\\">
|
||||||
|
|
||||||
|
<article>
|
||||||
|
<header>
|
||||||
|
<h4>Digital Compression Pioneer Award</h4>
|
||||||
|
<div class=\\"meta\\">
|
||||||
|
<div>Awarded by <strong>Techcrunch</strong></div> <time datetime=\\"2014-11-01\\">Nov 2014</time>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
<p>There is no spoon.</p>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
<section id=\\"publications\\">
|
||||||
</section>
|
<h3>Publications</h3>
|
||||||
|
<div class=\\"stack\\">
|
||||||
|
|
||||||
<section id=\\"projects\\">
|
<article>
|
||||||
<h3>Projects</h3>
|
<header>
|
||||||
<div class=\\"stack\\">
|
<h4><a href=\\"http://en.wikipedia.org/wiki/Silicon_Valley_(TV_series)\\">Video compression for 3d media</a></h4>
|
||||||
|
<div class=\\"meta\\">
|
||||||
<article>
|
<div>Published by <strong>Hooli</strong></div>
|
||||||
<header>
|
<time datetime=\\"2014-10-01\\">Oct 2014</time>
|
||||||
<h4><a href=\\"missdirection.example.com\\">Miss Direction</a></h4>
|
</div>
|
||||||
<div class=\\"meta\\">
|
</header>
|
||||||
|
<p>Innovative middle-out compression algorithm that changes the way we store data.</p>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id=\\"skills\\">
|
||||||
|
<h3>Skills</h3>
|
||||||
|
<div class=\\"grid-list\\">
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<strong>Team lead and Designer</strong>
|
<h4>Web Development</h4>
|
||||||
at <strong>Smoogle</strong>
|
|
||||||
|
<ul class=\\"tag-list\\">
|
||||||
|
<li>HTML</li><li>CSS</li><li>Javascript</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div><time datetime=\\"2016-08-24\\">Aug 2016</time> – <time datetime=\\"2016-08-24\\">Aug 2016</time></div>
|
|
||||||
<div>application</div>
|
<div>
|
||||||
</div>
|
<h4>Compression</h4>
|
||||||
</header>
|
|
||||||
<p>A mapping engine that misguides you</p>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><p>Won award at AIHacks 2016</p></li><li><p>Built by all women team of newbie programmers</p></li><li><p>Using modern technologies such as GoogleMaps, Chrome Extension and Javascript</p></li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
|
|
||||||
<ul class=\\"tag-list\\">
|
|
||||||
<li>GoogleMaps</li><li>Chrome Extension</li><li>Javascript</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
</article>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
|
|
||||||
<section id=\\"awards\\">
|
|
||||||
<h3>Awards</h3>
|
|
||||||
<div class=\\"stack\\">
|
|
||||||
|
|
||||||
<article>
|
|
||||||
<header>
|
|
||||||
<h4>Digital Compression Pioneer Award</h4>
|
|
||||||
<div class=\\"meta\\">
|
|
||||||
|
|
||||||
<div>
|
<ul class=\\"tag-list\\">
|
||||||
Awarded by <strong>Techcrunch</strong>
|
<li>Mpeg</li><li>MP4</li><li>GIF</li>
|
||||||
</div>
|
</ul>
|
||||||
|
|
||||||
<time datetime=\\"2014-11-01\\">Nov 2014</time>
|
|
||||||
</div>
|
</div>
|
||||||
</header>
|
|
||||||
<p>There is no spoon.</p>
|
</div>
|
||||||
</article>
|
</section>
|
||||||
|
|
||||||
|
<section id=\\"languages\\">
|
||||||
|
<h3>Languages</h3>
|
||||||
|
<div class=\\"grid-list\\">
|
||||||
|
<div><h4>English</h4> Native speaker</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
<section id=\\"interests\\">
|
||||||
</section>
|
<h3>Interests</h3>
|
||||||
|
<div class=\\"grid-list\\">
|
||||||
|
|
||||||
|
<div>
|
||||||
<section id=\\"publications\\">
|
<h4>Wildlife</h4>
|
||||||
<h3>Publications</h3>
|
|
||||||
<div class=\\"stack\\">
|
|
||||||
|
|
||||||
<article>
|
|
||||||
<header>
|
|
||||||
<h4><a href=\\"http://en.wikipedia.org/wiki/Silicon_Valley_(TV_series)\\">Video compression for 3d media</a></h4>
|
|
||||||
<div class=\\"meta\\">
|
|
||||||
|
|
||||||
<div>
|
<ul class=\\"tag-list\\">
|
||||||
Published by <strong>Hooli</strong>
|
<li>Ferrets</li><li>Unicorns</li>
|
||||||
</div>
|
</ul>
|
||||||
|
|
||||||
<time datetime=\\"2014-10-01\\">Oct 2014</time>
|
|
||||||
</div>
|
</div>
|
||||||
</header>
|
|
||||||
<p>Innovative middle-out compression algorithm that changes the way we store data.</p>
|
|
||||||
</article>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
|
|
||||||
<section id=\\"skills\\">
|
|
||||||
<h3>Skills</h3>
|
|
||||||
<div class=\\"grid-list\\">
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<h4>Web Development</h4>
|
|
||||||
|
|
||||||
<ul class=\\"tag-list\\">
|
</div>
|
||||||
<li>HTML</li><li>CSS</li><li>Javascript</li>
|
</section>
|
||||||
</ul>
|
|
||||||
|
<section id=\\"references\\">
|
||||||
|
<h3>References</h3>
|
||||||
|
<div class=\\"stack\\">
|
||||||
|
|
||||||
|
<blockquote>
|
||||||
|
<p>It is my pleasure to recommend Richard, his performance working as a consultant for Main St. Company proved that he will be a valuable addition to any company.</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<cite>Erlich Bachman</cite>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</blockquote>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
</section>
|
||||||
<div>
|
|
||||||
<h4>Compression</h4>
|
|
||||||
|
|
||||||
<ul class=\\"tag-list\\">
|
|
||||||
<li>Mpeg</li><li>MP4</li><li>GIF</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
|
|
||||||
<section id=\\"languages\\">
|
|
||||||
<h3>Languages</h3>
|
|
||||||
<div class=\\"grid-list\\">
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<h4>English</h4>
|
|
||||||
Native speaker
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
|
|
||||||
<section id=\\"interests\\">
|
|
||||||
<h3>Interests</h3>
|
|
||||||
<div class=\\"grid-list\\">
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<h4>Wildlife</h4>
|
|
||||||
|
|
||||||
<ul class=\\"tag-list\\">
|
|
||||||
<li>Ferrets</li><li>Unicorns</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
|
|
||||||
<section id=\\"references\\">
|
|
||||||
<h3>References</h3>
|
|
||||||
<div class=\\"stack\\">
|
|
||||||
|
|
||||||
<blockquote>
|
|
||||||
<p>It is my pleasure to recommend Richard, his performance working as a consultant for Main St. Company proved that he will be a valuable addition to any company.</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<cite>Erlich Bachman</cite>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
</blockquote>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>"
|
</html>"
|
||||||
`;
|
`;
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import { HtmlValidate } from 'html-validate'
|
import { HtmlValidate } from 'html-validate'
|
||||||
import { expect, it } from 'vitest'
|
import { expect, it } from 'vitest'
|
||||||
|
|
||||||
import { render } from '../index.js'
|
|
||||||
import sampleResume from 'resume-schema/sample.resume.json' assert { type: 'json' }
|
import sampleResume from 'resume-schema/sample.resume.json' assert { type: 'json' }
|
||||||
|
import { render } from '../index.js'
|
||||||
|
|
||||||
const resume = {
|
const resume = {
|
||||||
...sampleResume,
|
...sampleResume,
|
||||||
|
@ -26,8 +26,9 @@ it('renders a resume', () => {
|
||||||
|
|
||||||
it('renders valid HTML', async () => {
|
it('renders valid HTML', async () => {
|
||||||
const htmlvalidate = new HtmlValidate({
|
const htmlvalidate = new HtmlValidate({
|
||||||
extends: ['html-validate:recommended'],
|
extends: ['html-validate:recommended', 'html-validate:prettier'],
|
||||||
rules: {
|
rules: {
|
||||||
|
'doctype-style': 'off',
|
||||||
'no-inline-style': 'off',
|
'no-inline-style': 'off',
|
||||||
'no-trailing-whitespace': 'off',
|
'no-trailing-whitespace': 'off',
|
||||||
'tel-non-breaking': 'off',
|
'tel-non-breaking': 'off',
|
||||||
|
|
Loading…
Reference in New Issue