feat(contact): move contact information to header

- List location with city and country
- Linkify phone number
- Render decorative Feather icons
- Use Node.js 14 with Intl.DisplayNames support
This commit is contained in:
Rafael Bardini 2021-03-03 19:42:34 +01:00
parent cdea9ecf9f
commit 1c5b4cb7c5
8 changed files with 102 additions and 54 deletions

View File

@ -12,7 +12,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v1
with:
node-version: 12
node-version: 14
- name: Install
run: npm ci

View File

@ -17,6 +17,12 @@ fs.readdirSync(partialsDir)
Handlebars.registerPartial(path.basename(filename, extname), template),
)
Handlebars.registerHelper('formatCountry', countryCode =>
Intl.DisplayNames
? new Intl.DisplayNames(['en'], { type: 'region' }).of(countryCode)
: countryCode,
)
Handlebars.registerHelper('formatDate', dateString =>
new Date(dateString).toLocaleDateString('en', {
month: 'short',
@ -24,6 +30,10 @@ Handlebars.registerHelper('formatDate', dateString =>
}),
)
Handlebars.registerHelper('formatPhone', phone =>
phone.replace(/[^\d|+]+/g, ''),
)
Handlebars.registerHelper('formatURL', url =>
url.replace(/^(https?:|)\/\//, '').replace(/\/$/, ''),
)

View File

@ -1,23 +0,0 @@
<section id="contact">
<h3>Contact</h3>
<div class="grid-list">
{{#email}}
<div>
<h4>Email</h4>
<a href="mailto:{{.}}">{{.}}</a>
</div>
{{/email}}
{{#phone}}
<div>
<h4>Phone</h4>
{{.}}
</div>
{{/phone}}
{{#url}}
<div>
<h4>Website</h4>
<a href="{{.}}">{{formatURL .}}</a>
</div>
{{/url}}
</div>
</section>

View File

@ -1,8 +1,38 @@
<header class="masthead">
<div>
{{#name}}
<h1>{{.}}</h1>
{{/name}}
{{#label}}
<h2>{{.}}</h2>
{{/label}}
</div>
<ul class="icon-list">
{{#location}}
{{#if city}}
<li>
<svg viewBox="0 0 24 24" width="16" height="16" aria-hidden="true"><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>
{{city}}{{#countryCode}}, {{formatCountry .}}{{/countryCode}}
</li>
{{/if}}
{{/location}}
{{#email}}
<li>
<svg viewBox="0 0 24 24" width="16" height="16" aria-hidden="true"><path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"></path><polyline points="22,6 12,13 2,6"></polyline></svg>
<a href="mailto:{{.}}">{{.}}</a>
</li>
{{/email}}
{{#phone}}
<li>
<svg viewBox="0 0 24 24" width="16" height="16" aria-hidden="true"><path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"></path></svg>
<a href="tel:{{formatPhone .}}">{{.}}</a>
</li>
{{/phone}}
{{#url}}
<li>
<svg viewBox="0 0 24 24" width="16" height="16" aria-hidden="true"><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="{{.}}">{{formatURL .}}</a>
</li>
{{/url}}
</ul>
</header>

View File

@ -11,7 +11,6 @@
<body>
{{#resume.basics}}
{{> header}}
{{> contact}}
{{> about}}
{{> profiles}}
{{/resume.basics}}

View File

@ -57,7 +57,7 @@ ul {
}
li + li {
margin-top: 0.2em;
margin-top: 0.4em;
}
li::marker {
@ -130,6 +130,16 @@ cite::before {
content: '— ';
}
svg {
fill: none;
margin-right: 0.2em;
stroke: currentColor;
stroke-linecap: round;
stroke-linejoin: round;
stroke-width: 2;
vertical-align: -0.2em;
}
.masthead {
background: var(--mutedColor);
display: inherit;
@ -137,7 +147,6 @@ cite::before {
grid-column: full;
grid-template-columns: inherit;
padding: 4em 0;
row-gap: 0;
}
.masthead > *,
@ -155,6 +164,11 @@ blockquote > * + * {
gap: 1.5em;
}
.icon-list {
list-style: none;
padding: 0;
}
.grid-list {
display: grid;
gap: 1em;

View File

@ -73,7 +73,7 @@ ul {
}
li + li {
margin-top: 0.2em;
margin-top: 0.4em;
}
li::marker {
@ -146,6 +146,16 @@ cite::before {
content: '— ';
}
svg {
fill: none;
margin-right: 0.2em;
stroke: currentColor;
stroke-linecap: round;
stroke-linejoin: round;
stroke-width: 2;
vertical-align: -0.2em;
}
.masthead {
background: var(--mutedColor);
display: inherit;
@ -153,7 +163,6 @@ cite::before {
grid-column: full;
grid-template-columns: inherit;
padding: 4em 0;
row-gap: 0;
}
.masthead > *,
@ -171,6 +180,11 @@ blockquote > * + * {
gap: 1.5em;
}
.icon-list {
list-style: none;
padding: 0;
}
.grid-list {
display: grid;
gap: 1em;
@ -230,26 +244,29 @@ blockquote > * + * {
</head>
<body>
<header class="masthead">
<div>
<h1>Richard Hendriks</h1>
<h2>Programmer</h2>
</header>
<section id="contact">
<h3>Contact</h3>
<div class="grid-list">
<div>
<h4>Email</h4>
</div>
<ul class="icon-list">
<li>
<svg viewBox="0 0 24 24" width="16" height="16" aria-hidden="true"><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
</li>
<li>
<svg viewBox="0 0 24 24" width="16" height="16" aria-hidden="true"><path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"></path><polyline points="22,6 12,13 2,6"></polyline></svg>
<a href="mailto:richard.hendriks@mail.com">richard.hendriks@mail.com</a>
</div>
<div>
<h4>Phone</h4>
(912) 555-4321
</div>
<div>
<h4>Website</h4>
</li>
<li>
<svg viewBox="0 0 24 24" width="16" height="16" aria-hidden="true"><path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"></path></svg>
<a href="tel:9125554321">(912) 555-4321</a>
</li>
<li>
<svg viewBox="0 0 24 24" width="16" height="16" aria-hidden="true"><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>
</div>
</div>
</section>
</li>
</ul>
</header>
<section id="about">
<h3>About</h3>
<article>

View File

@ -12,6 +12,7 @@ test('renders a resume', t => {
test('renders valid HTML', t => {
const htmlvalidate = new HtmlValidate({
extends: ['html-validate:recommended'],
rules: { 'svg-focusable': 'off' },
})
const {