From d8c8b01a07a2eb46fdabff7a94a46e1201c14f9f Mon Sep 17 00:00:00 2001 From: dozens Date: Thu, 21 Dec 2023 15:23:57 -0700 Subject: [PATCH] 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. --- .gitignore | 2 - README.md | 4 +- example.pdf | Bin 18189 -> 12489 bytes justfile | 31 ++++---- lambdas.js | 27 +++++++ resume.template | 38 +++++----- view.js | 192 ++++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 254 insertions(+), 40 deletions(-) delete mode 100644 .gitignore create mode 100644 lambdas.js create mode 100644 view.js diff --git a/.gitignore b/.gitignore deleted file mode 100644 index a3ed5cd..0000000 --- a/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -resume.toml -resume.pdf diff --git a/README.md b/README.md index a6b6bae..65a25e2 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/example.pdf b/example.pdf index 8c30ed9f1661a5734f39b3203b355e4448e1b6d9..19ff837046c591482cd45b6e701a538bad504932 100644 GIT binary patch delta 1474 zcmZWpc{tPw7+&|7X2{C1xyJc;2=klEAS&xf>)J`p5Hc8}bck`Rpnj3oricT?iP*d< z%Z=~d6tl2p<}8eQq!gdtCsGDwV0BlAr>=yN>-&qUa#^N_&)|MrpRZVlPr6qONmdhQ zy)_a~a4(J_Uz7{9WyK&_Va4Y`oc2$Drs|&FXFc;L_}B# z7_K)pXy#?u5#QcJd84V(_Xm$A<$N^=ssXU)&A}RKQ7r>W7Q?*F08E~VQS$ubNzo^wRr^qF5SeeSnQael*nSD(AwLW<@uwY;dp=l^y zW=5jmkK$e@f>En7W9Up|BeG0|5T&2 z9;zlTHw}A?2@pvV{0( zhFTLyX8hHbkz9uX148xwbA;@yYw^aEZj!2uwk<>U2I6=Hx;wboj#5_5@#u1N@+fO# zx*wt4d*MsYyrHEO4T7z4GCxW(O}q|!un18yjl$PLdO*!(;#Oy~;5;*Fs>kPj0NCDk z*QGA}$PirRmx29{ts*<`BpNXqLGOWrQQ=~cSuUlvu)X2kPSx950?zS=08f+DsW=bY zV7qZ5Zf82mrz0!EIA8ibTzpNpsOmT>#KO?mNrNIh5*5>KaxAL@#qm7B)XulLI>X7q_N2n(Pyu@7cIeWvrY z@RaiHfOC&_$`jY<>q6oi3hEN`j=B!cD3LhuC9TE)77^gkal*$#O)vbBWgTZg3J#a) zT(I@+e3p|w?qmz^4wQ^FvDaendnHf@vnGWouBS{wwcj@X!iNCMqSgDSt+34N|B{6Amot zTg{k&s#zAJNqt-Qkr=Y3QoK&B#hUf zpbkL+fDIat!SY5F?7jhkHe|w-SLqbY({ZL^&`{*JLg27iG!_wt_{srjGzRgnin#QZ z+Z~9-^6H)OAb`bK?-7wGoXuVX5`zc+$KkMeo4sC~4S?Fq;gQ(AI{+kLjojolrAARwStgv*y{2;d(8wK{n&fr0?g|2=1N6fHiA5(WiO00s{=Hg@)M Gf&L9s^@j!k delta 2836 zcmZWrc|4SR7k|BzZ9>S>&C)Ynvh!>+^GudXZbT(Znj&4xj3sxh3CUbkw?d^y;Yw6D zl&xsd%}!)VS`A~3C=+R=;@@;4>j6 z)yj$*9udaz`iUBKwwT=#Cd3r0L`JJw-P@Emog5r}jCFY8*N{i93N4!cr<9e}AGA)0 zM7ut}4VctOs|Z|~zRNII!lE*+s&?S#g!nZd2SRFcr?mMsrgHUzp9x#HTs0zYbiVFbolu)nJ(D9!Xr2ll42*AJEW~1Nmp0DZTv`IrR<1ZtU^}l;s?O--IM&QN7e3I zR!e_PJmN5@?sRfP^MTa&pz4d3GY-Xp(}#82vN}hey~e69O2ls|>S(kqU|PJFi{9fG zRGv*U-5Y45q+`cX5EfOJzfca$KoH*;7Y#rVZB1j!rIf5|tf{kw-`_Lo?M(twzy9lFB)bsk zYvt1JYGj&bA?vs94AyC_Uu(ZrWskw*NmN}vpr(np#pu?Gr2M^E%_#2s!)%f(y4J(2mV^A6`aTc zte;jr(Owi{WU;*8-T=$pL%{~2+!<}hH206ouA@7xpv&CEEmBWtd1LaNDaFM*>WvLR z%jeNeL9BR3S#^D*bK8GZ+RPpaEz#@F<|<|}QuSP96r`P;8yp7SQ0|7xZPO|DF3wb56cT5}S9=^@Y1`vbTYKnJL52ldXWy0v|JqU*72|ea;nx%c z**w$5)nATp{JA-R-F5%f^6~96LV77 z<=OBxw>Ux2HNG#bxnUh&o2#i?NIMn%$B~)3hh3a>_H=yu)KF*bKFjB2tPZW%3eMDM z-=1Q{jIXXV&{pqYA@%q5MH?^FrQdSXZfBXCh%8CBHHXt|gP*qg_+P@M%N<)UcGWpl z4;w0igK8qQy8o*4t*3J4saBMy(?ydn72drDQvDv5?U!&I5F}Rew~a1yT`V%xKEsMB zYlqtSR~lA9{pc1aCAS0V&&+2ctzKnwd4t(p-;wN&EAKmM?L}IFb70ily8dd}-W;1T zu&Df%QJm}>sS_19^Vp_uXES}A4Mrx}pVpUj&rrRQ*cfXh13f#rK{^)i`*o5B5t`#dR-(Npi zj1LNDls%i-5^tT3#5Kj79v7W{!R~q2M<2Ub9k$v$uHCIY)?-#WF7_n@*Oj!9pyPp( zG#QW%!zhX(I4)`a_o4imWS>6nFDZ}9X(%q;7~vHZ;6pY0f#(zK8^H4eAOttn(2+oK zcPWSOQ5Xj3CvaEpIUK`n3DKBUq@gQJ^a79!c6QN zX99$5Ai?JwiI^Nh#-u0f#Cb9%O`InOh`))wSO;;Rm@w&4R1uvYiW1;3p#Tcv{#uYc zMrcQ&+vPs*_zC+>t4=r5tk+`NE9 z4Vgp8+P~`Q5P=LM08IZ@gW#LB)$tJ7Me5=!Sm1HKwh4vchL>uq&R=b*wwe@47lLp| zQ|r_UoB1rHsj5xxP4Xf=x#uqOMaALy273omA*6i&3OgBHl-P+l0~Qv5*}8Ba4le>= zVhGi2y;q1GC&14?g3tjgf2rppwTekK+YsdC7Y?u(L=?=6u(l440^C8s1csOZ1QL@l z48grjRn)})-*0{$&o77rm@x69rpb~B20$<_Zx$@Uzz>*dsHNkOLtWgMmkZnshoLw=+OBa}ExU00@47Gu6x`Acg}#jBn3fuds-y TFb 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< example.pdf diff --git a/lambdas.js b/lambdas.js new file mode 100644 index 0000000..d65b206 --- /dev/null +++ b/lambdas.js @@ -0,0 +1,27 @@ +bold: function() { + return function(text, render) { + return "" + render(text) + ""; + } +}, +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()) + } +} diff --git a/resume.template b/resume.template index 640e51c..5d5797e 100644 --- a/resume.template +++ b/resume.template @@ -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. +c s. +.\"cfI s. .TH ./" ============ ./" == HEADER == @@ -17,9 +19,9 @@ cfI s. {{email}} - {{phone}} {{#profiles}} {{{url}}} {{/profiles}} .sp 1 -T{ -{{{summary}}} -T} +.\"T{ +.\"{{{summary}}} +.\"T} {{/basics}} .sp 1 . @@ -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 diff --git a/view.js b/view.js new file mode 100644 index 0000000..9fd3934 --- /dev/null +++ b/view.js @@ -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 "" + render(text) + ""; + } +}, +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()) + } +} +}