style(prettier): format all files and add CI check

This commit is contained in:
Rafael Bardini 2023-10-08 01:23:03 +02:00
parent a1d06cded1
commit 082678444d
24 changed files with 598 additions and 568 deletions

View File

@ -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

View File

@ -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"
} }

View File

@ -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

View File

@ -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 (
awards.length > 0 &&
html`
<section id="awards"> <section id="awards">
<h3>Awards</h3> <h3>Awards</h3>
<div class="stack"> <div class="stack">
${awards.map(({ awarder, date, summary, title }) => html` ${awards.map(
({ awarder, date, summary, title }) => html`
<article> <article>
<header> <header>
<h4>${title}</h4> <h4>${title}</h4>
<div class="meta"> <div class="meta">
${awarder && html` ${awarder && html`<div>Awarded by <strong>${awarder}</strong></div>`} ${date && Date(date)}
<div>
Awarded by <strong>${awarder}</strong>
</div>
`}
${date && Date(date)}
</div> </div>
</header> </header>
${summary && markdown(summary)} ${summary && markdown(summary)}
</article> </article>
`)} `,
)}
</div> </div>
</section> </section>
` `
)
} }

View File

@ -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 (
certificates.length > 0 &&
html`
<section id="certificates"> <section id="certificates">
<h3>Certificates</h3> <h3>Certificates</h3>
<div class="stack"> <div class="stack">
${certificates.map(({ date, issuer, name, url }) => html` ${certificates.map(
({ date, issuer, name, url }) => html`
<article> <article>
<header> <header>
<h4>${Link(url, name)}</h4> <h4>${Link(url, name)}</h4>
<div class="meta"> <div class="meta">
${issuer && html` ${issuer && html`<div>Issued by <strong>${issuer}</strong></div>`} ${date && Date(date)}
<div>
Issued by <strong>${issuer}</strong>
</div>
`}
${date && Date(date)}
</div> </div>
</header> </header>
</article> </article>
`)} `,
)}
</div> </div>
</section> </section>
` `
)
} }

View File

@ -8,11 +8,14 @@ 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 (
education.length > 0 &&
html`
<section id="education"> <section id="education">
<h3>Education</h3> <h3>Education</h3>
<div class="stack"> <div class="stack">
${education.map(({ area, courses = [], institution, startDate, endDate, studyType, url }) => html` ${education.map(
({ area, courses = [], institution, startDate, endDate, studyType, url }) => html`
<article> <article>
<header> <header>
<h4>${Link(url, institution)}</h4> <h4>${Link(url, institution)}</h4>
@ -22,15 +25,18 @@ export default function Education(education = []) {
</div> </div>
</header> </header>
${studyType && markdown(studyType)} ${studyType && markdown(studyType)}
${courses.length > 0 && html` ${courses.length > 0 &&
html`
<h5>Courses</h5> <h5>Courses</h5>
<ul> <ul>
${courses.map(course => html`<li>${markdown(course)}</li>`)} ${courses.map(course => html`<li>${markdown(course)}</li>`)}
</ul> </ul>
`} `}
</article> </article>
`)} `,
)}
</div> </div>
</section> </section>
` `
)
} }

View File

@ -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>`}
${profiles.map(
({ network, url, username }) => html`
<li> <li>
${Icon('link')} ${network && Icon(network, 'user')} ${Link(url, username)}
${Link(url)}
</li>
`}
${profiles.map(({ network, url, username }) => html`
<li>
${network && Icon(network, 'user')}
${Link(url, username)}
${network && html`<span class="network">(${network})</span>`} ${network && html`<span class="network">(${network})</span>`}
</li> </li>
`)} `,
)}
</ul> </ul>
</header> </header>
` `

View File

@ -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 (
interests.length > 0 &&
html`
<section id="interests"> <section id="interests">
<h3>Interests</h3> <h3>Interests</h3>
<div class="grid-list"> <div class="grid-list">
${interests.map(({ keywords = [], name }) => html` ${interests.map(
({ keywords = [], name }) => html`
<div> <div>
${name && html`<h4>${name}</h4>`} ${name && html`<h4>${name}</h4>`}
${keywords.length > 0 && html` ${keywords.length > 0 &&
html`
<ul class="tag-list"> <ul class="tag-list">
${keywords.map(keyword => html`<li>${keyword}</li>`)} ${keywords.map(keyword => html`<li>${keyword}</li>`)}
</ul> </ul>
`} `}
</div> </div>
`)} `,
)}
</div> </div>
</section> </section>
` `
)
} }

View File

@ -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 (
languages.length > 0 &&
html`
<section id="languages"> <section id="languages">
<h3>Languages</h3> <h3>Languages</h3>
<div class="grid-list"> <div class="grid-list">
${languages.map(({ fluency, language }) => html` ${languages.map(
<div> ({ fluency, language }) => html`<div>${language && html`<h4>${language}</h4>`} ${fluency}</div>`,
${language && html`<h4>${language}</h4>`} )}
${fluency}
</div>
`)}
</div> </div>
</section> </section>
` `
)
} }

View File

@ -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>`
} }

View File

@ -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)}" />`}
` `
} }

View File

@ -7,20 +7,32 @@ 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 (
projects.length > 0 &&
html`
<section id="projects"> <section id="projects">
<h3>Projects</h3> <h3>Projects</h3>
<div class="stack"> <div class="stack">
${projects.map(({ description, entity, highlights = [], keywords = [], name, startDate, endDate, roles = [], type, url }) => html` ${projects.map(
({
description,
entity,
highlights = [],
keywords = [],
name,
startDate,
endDate,
roles = [],
type,
url,
}) => html`
<article> <article>
<header> <header>
<h4>${Link(url, name)}</h4> <h4>${Link(url, name)}</h4>
@ -29,24 +41,27 @@ export default function Projects(projects = []) {
${roles.length > 0 && html`<strong>${formatRoles(roles)}</strong>`} ${roles.length > 0 && html`<strong>${formatRoles(roles)}</strong>`}
${entity && html`at <strong>${entity}</strong>`} ${entity && html`at <strong>${entity}</strong>`}
</div> </div>
${startDate && html`<div>${Duration(startDate, endDate)}</div>`} ${startDate && html`<div>${Duration(startDate, endDate)}</div>`} ${type && html`<div>${type}</div>`}
${type && html`<div>${type}</div>`}
</div> </div>
</header> </header>
${description && markdown(description)} ${description && markdown(description)}
${highlights.length > 0 && html` ${highlights.length > 0 &&
html`
<ul> <ul>
${highlights.map(highlight => html`<li>${markdown(highlight)}</li>`)} ${highlights.map(highlight => html`<li>${markdown(highlight)}</li>`)}
</ul> </ul>
`} `}
${keywords.length > 0 && html` ${keywords.length > 0 &&
html`
<ul class="tag-list"> <ul class="tag-list">
${keywords.map(keyword => html`<li>${keyword}</li>`)} ${keywords.map(keyword => html`<li>${keyword}</li>`)}
</ul> </ul>
`} `}
</article> </article>
`)} `,
)}
</div> </div>
</section> </section>
` `
)
} }

View File

@ -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 (
publications.length > 0 &&
html`
<section id="publications"> <section id="publications">
<h3>Publications</h3> <h3>Publications</h3>
<div class="stack"> <div class="stack">
${publications.map(({ name, publisher, releaseDate, summary, url }) => html` ${publications.map(
({ name, publisher, releaseDate, summary, url }) => html`
<article> <article>
<header> <header>
<h4>${Link(url, name)}</h4> <h4>${Link(url, name)}</h4>
<div class="meta"> <div class="meta">
${publisher && html` ${publisher && html`<div>Published by <strong>${publisher}</strong></div>`}
<div>
Published by <strong>${publisher}</strong>
</div>
`}
${releaseDate && Date(releaseDate)} ${releaseDate && Date(releaseDate)}
</div> </div>
</header> </header>
${summary && markdown(summary)} ${summary && markdown(summary)}
</article> </article>
`)} `,
)}
</div> </div>
</section> </section>
` `
)
} }

View File

@ -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 (
references.length > 0 &&
html`
<section id="references"> <section id="references">
<h3>References</h3> <h3>References</h3>
<div class="stack"> <div class="stack">
${references.map(({ name, reference }) => html` ${references.map(
({ name, reference }) => html`
<blockquote> <blockquote>
${reference && markdown(reference)} ${reference && markdown(reference)}
${name && html` ${name &&
html`
<p> <p>
<cite>${name}</cite> <cite>${name}</cite>
</p> </p>
`} `}
</blockquote> </blockquote>
`)} `,
)}
</div> </div>
</section> </section>
` `
)
} }

View File

@ -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 (
skills.length > 0 &&
html`
<section id="skills"> <section id="skills">
<h3>Skills</h3> <h3>Skills</h3>
<div class="grid-list"> <div class="grid-list">
${skills.map(({ keywords = [], name }) => html` ${skills.map(
({ keywords = [], name }) => html`
<div> <div>
${name && html`<h4>${name}</h4>`} ${name && html`<h4>${name}</h4>`}
${keywords.length > 0 && html` ${keywords.length > 0 &&
html`
<ul class="tag-list"> <ul class="tag-list">
${keywords.map(keyword => html`<li>${keyword}</li>`)} ${keywords.map(keyword => html`<li>${keyword}</li>`)}
</ul> </ul>
`} `}
</div> </div>
`)} `,
)}
</div> </div>
</section> </section>
` `
)
} }

View File

@ -8,11 +8,14 @@ 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 (
volunteer.length > 0 &&
html`
<section id="volunteer"> <section id="volunteer">
<h3>Volunteer</h3> <h3>Volunteer</h3>
<div class="stack"> <div class="stack">
${volunteer.map(({ highlights = [], organization, position, startDate, endDate, summary, url }) => html` ${volunteer.map(
({ highlights = [], organization, position, startDate, endDate, summary, url }) => html`
<article> <article>
<header> <header>
<h4>${Link(url, organization)}</h4> <h4>${Link(url, organization)}</h4>
@ -22,14 +25,17 @@ export default function Volunteer(volunteer = []) {
</div> </div>
</header> </header>
${summary && markdown(summary)} ${summary && markdown(summary)}
${highlights.length > 0 && html` ${highlights.length > 0 &&
html`
<ul> <ul>
${highlights.map(highlight => html`<li>${markdown(highlight)}</li>`)} ${highlights.map(highlight => html`<li>${markdown(highlight)}</li>`)}
</ul> </ul>
`} `}
</article> </article>
`)} `,
)}
</div> </div>
</section> </section>
` `
)
} }

View File

@ -19,20 +19,22 @@ export default function Work(work = []) {
return acc return acc
}, /** @type {NestedWork[]} */ ([])) }, /** @type {NestedWork[]} */ ([]))
return work.length > 0 && html` return (
work.length > 0 &&
html`
<section id="work"> <section id="work">
<h3>Work</h3> <h3>Work</h3>
<div class="stack"> <div class="stack">
${nestedWork.map(({ description, name, url, items = [] }) => html` ${nestedWork.map(
({ description, name, url, items = [] }) => html`
<article> <article>
<header> <header>
<h4>${Link(url, name)}</h4> <h4>${Link(url, name)}</h4>
<div class="meta"> <div class="meta">${description && html`<div>${description}</div>`}</div>
${description && html`<div>${description}</div>`}
</div>
</header> </header>
<div class="timeline"> <div class="timeline">
${items.map(({highlights = [], location, position, startDate, endDate, summary }) => html` ${items.map(
({ highlights = [], location, position, startDate, endDate, summary }) => html`
<div> <div>
<div> <div>
<h5>${position}</h5> <h5>${position}</h5>
@ -42,17 +44,21 @@ export default function Work(work = []) {
</div> </div>
</div> </div>
${summary && markdown(summary)} ${summary && markdown(summary)}
${highlights.length > 0 && html` ${highlights.length > 0 &&
html`
<ul> <ul>
${highlights.map(highlight => html`<li>${markdown(highlight)}</li>`)} ${highlights.map(highlight => html`<li>${markdown(highlight)}</li>`)}
</ul> </ul>
`} `}
</div> </div>
`)} `,
)}
</div> </div>
</article> </article>
`)} `,
)}
</div> </div>
</section> </section>
` `
)
} }

View File

@ -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]')

37
package-lock.json generated
View File

@ -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",

View File

@ -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",

View File

@ -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>`
} }

View File

@ -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)
);
} }
} }

View File

@ -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,29 +39,21 @@ 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>
</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-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
<span class=\\"network\\">(Twitter)</span> <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> <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>
<a href=\\"https://soundcloud.example.com/dandymusicnl\\">dandymusicnl</a>
<span class=\\"network\\">(SoundCloud)</span> <span class=\\"network\\">(SoundCloud)</span>
</li> </li>
</ul> </ul>
</header> </header>
<section id=\\"work\\"> <section id=\\"work\\">
<h3>Work</h3> <h3>Work</h3>
<div class=\\"stack\\"> <div class=\\"stack\\">
@ -71,9 +61,7 @@ exports[`renders a resume 1`] = `
<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 class=\\"meta\\"><div>Awesome compression company</div></div>
<div>Awesome compression company</div>
</div>
</header> </header>
<div class=\\"timeline\\"> <div class=\\"timeline\\">
@ -99,7 +87,6 @@ exports[`renders a resume 1`] = `
</div> </div>
</section> </section>
<section id=\\"volunteer\\"> <section id=\\"volunteer\\">
<h3>Volunteer</h3> <h3>Volunteer</h3>
<div class=\\"stack\\"> <div class=\\"stack\\">
@ -123,7 +110,6 @@ exports[`renders a resume 1`] = `
</div> </div>
</section> </section>
<section id=\\"education\\"> <section id=\\"education\\">
<h3>Education</h3> <h3>Education</h3>
<div class=\\"stack\\"> <div class=\\"stack\\">
@ -161,8 +147,7 @@ exports[`renders a resume 1`] = `
<strong>Team lead and Designer</strong> <strong>Team lead and Designer</strong>
at <strong>Smoogle</strong> at <strong>Smoogle</strong>
</div> </div>
<div><time datetime=\\"2016-08-24\\">Aug 2016</time> <time datetime=\\"2016-08-24\\">Aug 2016</time></div> <div><time datetime=\\"2016-08-24\\">Aug 2016</time> <time datetime=\\"2016-08-24\\">Aug 2016</time></div> <div>application</div>
<div>application</div>
</div> </div>
</header> </header>
<p>A mapping engine that misguides you</p> <p>A mapping engine that misguides you</p>
@ -181,7 +166,6 @@ exports[`renders a resume 1`] = `
</div> </div>
</section> </section>
<section id=\\"awards\\"> <section id=\\"awards\\">
<h3>Awards</h3> <h3>Awards</h3>
<div class=\\"stack\\"> <div class=\\"stack\\">
@ -190,12 +174,7 @@ exports[`renders a resume 1`] = `
<header> <header>
<h4>Digital Compression Pioneer Award</h4> <h4>Digital Compression Pioneer Award</h4>
<div class=\\"meta\\"> <div class=\\"meta\\">
<div>Awarded by <strong>Techcrunch</strong></div> <time datetime=\\"2014-11-01\\">Nov 2014</time>
<div>
Awarded by <strong>Techcrunch</strong>
</div>
<time datetime=\\"2014-11-01\\">Nov 2014</time>
</div> </div>
</header> </header>
<p>There is no spoon.</p> <p>There is no spoon.</p>
@ -205,7 +184,6 @@ exports[`renders a resume 1`] = `
</section> </section>
<section id=\\"publications\\"> <section id=\\"publications\\">
<h3>Publications</h3> <h3>Publications</h3>
<div class=\\"stack\\"> <div class=\\"stack\\">
@ -214,11 +192,7 @@ exports[`renders a resume 1`] = `
<header> <header>
<h4><a href=\\"http://en.wikipedia.org/wiki/Silicon_Valley_(TV_series)\\">Video compression for 3d media</a></h4> <h4><a href=\\"http://en.wikipedia.org/wiki/Silicon_Valley_(TV_series)\\">Video compression for 3d media</a></h4>
<div class=\\"meta\\"> <div class=\\"meta\\">
<div>Published by <strong>Hooli</strong></div>
<div>
Published by <strong>Hooli</strong>
</div>
<time datetime=\\"2014-10-01\\">Oct 2014</time> <time datetime=\\"2014-10-01\\">Oct 2014</time>
</div> </div>
</header> </header>
@ -228,7 +202,6 @@ exports[`renders a resume 1`] = `
</div> </div>
</section> </section>
<section id=\\"skills\\"> <section id=\\"skills\\">
<h3>Skills</h3> <h3>Skills</h3>
<div class=\\"grid-list\\"> <div class=\\"grid-list\\">
@ -254,16 +227,10 @@ exports[`renders a resume 1`] = `
</div> </div>
</section> </section>
<section id=\\"languages\\"> <section id=\\"languages\\">
<h3>Languages</h3> <h3>Languages</h3>
<div class=\\"grid-list\\"> <div class=\\"grid-list\\">
<div><h4>English</h4> Native speaker</div>
<div>
<h4>English</h4>
Native speaker
</div>
</div> </div>
</section> </section>
@ -284,7 +251,6 @@ exports[`renders a resume 1`] = `
</div> </div>
</section> </section>
<section id=\\"references\\"> <section id=\\"references\\">
<h3>References</h3> <h3>References</h3>
<div class=\\"stack\\"> <div class=\\"stack\\">

View File

@ -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',