Add mustache lambdas

Now you can define lambdas in lambdas.js. In the build process, ed will
creat the json for the view from the toml, and insert the lambdas to be
fed to mustache to expand the templates to create the groff to create
the pdf.

See the examples in lambdas.js for guidance on writing lambdas.
dozens 2023-12-21 15:23:57 -07:00
parent bc51d57fe7
commit 1614f02e9b
7 changed files with 250 additions and 36 deletions

2
.gitignore vendored
View File

@ -1,2 +0,0 @@
resume.toml
resume.pdf

View File

@ -32,8 +32,8 @@ and then exported to pdf.
## You Will Need
1. GNU groff version 1.23.0: for typesetting and pdf output (with the ms macro package; it *should* be installed anywhere groff is installed)
2. mustache 4.2.0: for templates
1. groff 1.23.0: for typesetting and pdf output (with the ms macro package; it *should* be installed anywhere groff is installed)
2. mustache.js 4.2.0: for templates
3. taplo 0.8.1: toml toolkit. Provides conversion to JSON, formatting, and validation.
4. jq 1.6: json queries
5. (optional) just 1.14.0: just a command runner

Binary file not shown.

View File

@ -2,10 +2,6 @@
default:
just --list --unsorted
# convert to json
json:
taplo get -f resume.toml -o json
# format toml
fmt:
taplo fmt resume.toml
@ -14,17 +10,18 @@ fmt:
validate:
taplo lint resume.toml
# make groff
groff:
just json | mustache - resume.template
# make pdf
# create pdf
pdf:
just groff | groff -ms -t -Tpdf > resume.pdf
# example
example:
taplo get -f example.toml -o json \
| mustache - resume.template \
| groff -ms -t -Tpdf \
> example.pdf
#!/usr/bin/env sh
ed<<EOF
i
module.exports =
.
r !taplo get -f example.toml -o json
-1s/$/,
.r lambdas.js
w view.js
q
EOF
mustache view.js resume.template \
| groff -ms -t -Tpdf > example.pdf

27
lambdas.js 100644
View File

@ -0,0 +1,27 @@
bold: function() {
return function(text, render) {
return "<b>" + render(text) + "</b>";
}
},
join: function() {
return function(text, render) {
return render(text).split(',').join(', ');
}
},
formatdate: function() {
return function(text, render) {
return new Date(render(text)).toLocaleDateString(
'en-us',
{
year: 'numeric',
month: 'long',
day: 'numeric'
}
);
}
},
chicken: function() {
return function(text, render) {
return render(text).replace(/(.)(.)/g, (match) => match[0].toLowerCase() + match[1].toUpperCase())
}
}

View File

@ -1,13 +1,15 @@
.EH ''''
.OH ''''
.nr HM .5i
.nr FM .5i
.TS H
.EH '''' \" delete header (even pages)
.OH '''' \" delete header (odd pages)
.nr HM .5i \" tighter header margin
.nr FM .5i \" tighter footer margin
.nr PI 2n \" tighter paragraph indentation (for bullet lists)
.nr PD 0 \" tighter paragraph spacing
.TS H \" Table Start!
center tab(;);
cbx s
c s
c s
cfI s.
lfI s.
.TH
./" ============
./" == HEADER ==
@ -29,7 +31,7 @@ T}
./" == WORK ==
./" ==========
.T&
lbv1 s
lbv2 s
- -
{{#work}}
lb r
@ -39,18 +41,16 @@ l s
{{/highlights}}
{{/work}}
l l.
Experience
.ds
{{#chicken}}Experience{{/chicken}}
{{#work}}
{{{name}}};{{{location}}}
{{{position}}};{{startDate}}-{{endDate}}
{{{position}}};{{#formatdate}}{{startDate}}{{/formatdate}}\*[-]{{#formatdate}}{{endDate}}{{/formatdate}}
{{#highlights}}
T{
.IP \(bu
{{{.}}}
T}
{{/highlights}}
.de
.sp 1
{{/work}}
;
@ -69,7 +69,7 @@ l s
l s.
Skills
{{#skills}}
{{{name}}}: {{#keywords}} {{{.}}} {{/keywords}}
{{{name}}}: {{#join}} {{{keywords}}} {{/join}}
{{/skills}}
;
.
@ -87,7 +87,7 @@ l r
l r.
Awards
{{#awards}}
{{title}}, {{awarder}};{{date}}
{{title}}, {{awarder}};{{#formatdate}}{{date}}{{/formatdate}}
{{/awards}}
;
.
@ -105,7 +105,7 @@ l r
l l.
Education
{{#education}}
{{institution}}, {{area}};{{startDate}}-{{endDate}}
{{institution}}, {{area}};{{#formatdate}}{{startDate}}{{/formatdate}}\*[-]{{#formatdate}}{{endDate}}{{/formatdate}}
{{/education}}
;
.
@ -123,7 +123,7 @@ l s
l s.
Interests
{{#interests}}
{{name}}: {{#keywords}} {{{.}}} {{/keywords}}
{{name}}: {{#join}} {{{keywords}}} {{/join}}
{{/interests}}
;
.TE

192
view.js 100644
View File

@ -0,0 +1,192 @@
module.exports =
{
"$schema": "https://raw.githubusercontent.com/jsonresume/resume-schema/v1.0.0/schema.json",
"basics": {
"name": "Richard Hendriks",
"label": "Programmer",
"image": "",
"email": "richard.hendriks@mail.com",
"phone": "(912) 555-4321",
"url": "http://richardhendricks.example.com",
"summary": "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!",
"location": {
"address": "2712 Broadway St",
"postalCode": "CA 94115",
"city": "San Francisco",
"countryCode": "US",
"region": "California"
},
"profiles": [
{
"network": "Twitter",
"username": "neutralthoughts",
"url": ""
},
{
"network": "SoundCloud",
"username": "dandymusicnl",
"url": "https://soundcloud.example.com/dandymusicnl"
}
]
},
"work": [
{
"name": "Pied Piper",
"location": "Palo Alto, CA",
"description": "Awesome compression company",
"position": "CEO/President",
"url": "http://piedpiper.example.com",
"startDate": "2013-12-01",
"endDate": "2014-12-01",
"summary": "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.",
"highlights": [
"Build an algorithm for artist to detect if their music was violating copy right infringement laws",
"Successfully won Techcrunch Disrupt",
"Optimized an algorithm that holds the current world record for Weisman Scores"
]
}
],
"volunteer": [
{
"organization": "CoderDojo",
"position": "Teacher",
"url": "http://coderdojo.example.com/",
"startDate": "2012-01-01",
"endDate": "2013-01-01",
"summary": "Global movement of free coding clubs for young people.",
"highlights": [
"Awarded 'Teacher of the Month'"
]
}
],
"education": [
{
"institution": "University of Oklahoma",
"url": "https://www.ou.edu/",
"area": "Information Technology",
"studyType": "Bachelor",
"startDate": "2011-06-01",
"endDate": "2014-01-01",
"score": "4.0",
"courses": [
"DB1101 - Basic SQL",
"CS2011 - Java Introduction"
]
}
],
"awards": [
{
"title": "Digital Compression Pioneer Award",
"date": "2014-11-01",
"awarder": "Techcrunch",
"summary": "There is no spoon."
}
],
"publications": [
{
"name": "Video compression for 3d media",
"publisher": "Hooli",
"releaseDate": "2014-10-01",
"url": "http://en.wikipedia.org/wiki/Silicon_Valley_(TV_series)",
"summary": "Innovative middle-out compression algorithm that changes the way we store data."
}
],
"skills": [
{
"name": "Web Development",
"level": "Master",
"keywords": [
"HTML",
"CSS",
"Javascript"
]
},
{
"name": "Compression",
"level": "Master",
"keywords": [
"Mpeg",
"MP4",
"GIF"
]
}
],
"languages": [
{
"language": "English",
"fluency": "Native speaker"
}
],
"interests": [
{
"name": "Wildlife",
"keywords": [
"Ferrets",
"Unicorns"
]
}
],
"references": [
{
"name": "Erlich Bachman",
"reference": "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."
}
],
"projects": [
{
"name": "Miss Direction",
"description": "A mapping engine that misguides you",
"highlights": [
"Won award at AIHacks 2016",
"Built by all women team of newbie programmers",
"Using modern technologies such as GoogleMaps, Chrome Extension and Javascript"
],
"keywords": [
"GoogleMaps",
"Chrome Extension",
"Javascript"
],
"startDate": "2016-08-24",
"endDate": "2016-08-24",
"url": "missdirection.example.com",
"roles": [
"Team lead",
"Designer"
],
"entity": "Smoogle",
"type": "application"
}
],
"meta": {
"canonical": "https://raw.githubusercontent.com/jsonresume/resume-schema/master/sample.resume.json",
"version": "v1.0.0",
"lastModified": "2017-12-24T15:53:00"
},
bold: function() {
return function(text, render) {
return "<b>" + render(text) + "</b>";
}
},
join: function() {
return function(text, render) {
return render(text).split(',').join(', ');
}
},
formatdate: function() {
return function(text, render) {
return new Date(render(text)).toLocaleDateString(
'en-us',
{
year: 'numeric',
month: 'long',
day: 'numeric'
}
);
}
},
chicken: function() {
return function(text, render) {
return render(text).replace(/(.)(.)/g, (match) => match[0].toLowerCase() + match[1].toUpperCase())
}
}
}