-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 42f654b
Showing
26 changed files
with
1,450 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
node_modules/ | ||
npm-debug.log | ||
resume.html | ||
resume.pdf | ||
resume.json | ||
.DS_Store | ||
.idea |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
node_modules/ | ||
npm-debug.log | ||
resume.html | ||
resume.pdf | ||
resume.json | ||
.DS_Store | ||
.idea |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
# Theme mocha responsive | ||
|
||
Dark, stylish theme strongly based on the [jsonresume-theme-caffeine](https://github.com/kelyvin/jsonresume-theme-caffeine) done by [Kelvin Nguyen](https://github.com/kelyvin). It's a theme for the [JSON Resume](http://jsonresume.org/) project and can by used with the [HackMyResume](https://github.com/hacksalot/HackMyResume) to generate nice resumes in many supported formats. | ||
|
||
![Screenshot](screenshot.png "Preview of the resume") | ||
|
||
The theme uses [handlebars](https://handlebarsjs.com/) templating engine for rendering and utilizes [Font Awesome](https://fontawesome.com/). The generated HTML should have very good browser support by explicitly relying on older styling techniques. | ||
|
||
The theme can be used with tools supporting asynchronous theme rendering. It converts local or remote profile images to Base64 format, including them directly in the markup, so the generated HTML file can be used standalone. For certain sections (_summary, work, education, volunteer ..._) __By default__, the image processing and | ||
|
||
For usage and issues associated with HackMyResume see the next section. | ||
|
||
## Using the theme | ||
|
||
The theme supports the [HackMyResume](https://github.com/hacksalot/HackMyResume) tool and shall be fully compatible with [resume-cli](https://github.com/jsonresume/resume-cli). | ||
|
||
### Using with HackMyresume | ||
|
||
The HackMyResume tool does not support async theme rendering, nor supports it helper transforming images to Base64 or converting markdown to HTML. Those helpers are disabled by default and yo should not use them with HackMyResume. | ||
|
||
## License | ||
|
||
Available under [the MIT license](http://mths.be/mit). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,158 @@ | ||
'use strict'; | ||
|
||
const fs = require('fs'); | ||
const path = require('path'); | ||
const promisedHandlebars = require('promised-handlebars'); | ||
const HandlebarsAsync = promisedHandlebars(require('handlebars')); | ||
const Handlebars = require('handlebars'); | ||
const handlebarsWax = require('handlebars-wax'); | ||
const addressFormat = require('address-format'); | ||
const moment = require('moment'); | ||
const Swag = require('swag'); | ||
const base64Img = require('base64-img'); | ||
const isUrl = require('is-url'); | ||
const marked = require('marked'); | ||
|
||
// Register swag handlebars helpers | ||
Swag.registerHelpers(HandlebarsAsync); | ||
Swag.registerHelpers(Handlebars); | ||
|
||
// global flags | ||
let RENDER_ASCYNC = false; | ||
let RENDER_MARKDOWN = process.env.RENDER_MARKDOWN || false; | ||
let PROCESS_IMAGE = process.env.PROCESS_IMAGE || false; | ||
|
||
const customHelpers = { | ||
/** | ||
* DO not use arrow functions! https://blog.pixelkritzel.de/posts/handlebars-dont-use-es6-arrow-functions-to-define-helpers/ | ||
*/ | ||
imgPathToBase64: function(imgPath) { | ||
// The image processing is disabled by default | ||
if (!PROCESS_IMAGE) return imgPath; | ||
|
||
// If no path provided throw an error | ||
if (!imgPath) { throw new Error('No valid path for the profile-picture image!'); } | ||
|
||
if (isUrl(imgPath)) { | ||
// Promise wrapper for base64Img.requestBase64 | ||
return RENDER_ASCYNC ? new Promise((resolve, reject) => { | ||
base64Img.requestBase64(imgPath, (err, res, body) => { | ||
if (err) { | ||
reject(err); | ||
} | ||
resolve(body); | ||
}); | ||
}) : imgPath; | ||
|
||
} else { | ||
// try catch | ||
try { | ||
if (!fs.existsSync(imgPath)) { throw new Error('The image for the profile picture cannot be found!'); } | ||
return base64Img.base64Sync(imgPath); | ||
} catch (e) { | ||
console.error(`There was an error when trying to convert the image ${imgPath}: ${e}`) | ||
} | ||
} | ||
}, | ||
|
||
removeProtocol: function(url) { | ||
return url.replace(/.*?:\/\//g, '') | ||
}, | ||
|
||
mdToHtml: function(string) { | ||
// The rendering of Markdown markup is disabled by default | ||
return RENDER_MARKDOWN ? marked(string) : string; | ||
}, | ||
|
||
concat: function() { | ||
let res = ''; | ||
|
||
for(let arg in arguments){ | ||
if (typeof arguments[arg] !== 'object') { | ||
res += arguments[arg]; | ||
} | ||
} | ||
|
||
return res; | ||
}, | ||
|
||
formatAddress: function(address, city, region, postalCode, countryCode) { | ||
let addressList = addressFormat({ | ||
address: address, | ||
city: city, | ||
subdivision: region, | ||
postalCode: postalCode, | ||
countryCode: countryCode | ||
}); | ||
|
||
return addressList.join('<br/>'); | ||
}, | ||
|
||
formatDate: function (date) { | ||
return moment(Date.parse(date)).format('MM/YYYY') | ||
}, | ||
}; | ||
|
||
// Register custom handlebars helpers | ||
HandlebarsAsync.registerHelper(customHelpers); | ||
Handlebars.registerHelper(customHelpers); | ||
|
||
/** | ||
* Setter for the RENDER_MARKDOWN flag | ||
*/ | ||
const enableMarkdownSupport = () => RENDER_MARKDOWN = true; | ||
|
||
/** | ||
* Setter for the PROCESS_IMAGE flag | ||
*/ | ||
const enableImageProcessing = () => PROCESS_IMAGE = true; | ||
|
||
/** | ||
* Function rendering the resume with 2promised-handlebars" allowing usage of async helpers | ||
* @param {Object} resumeJson The source resume object | ||
* @returns {Promise<String>} Promise resolving to the HTML markup | ||
*/ | ||
const renderAsync = async (resumeJson) => { | ||
// change the global flag | ||
RENDER_ASCYNC = true; | ||
return await render(resumeJson); | ||
}; | ||
|
||
/** | ||
* Renders resume from a resume object and returns HTML Markup | ||
* @param {Object] resumeJson The source resume object | ||
* @returns {string|Promise<String>} The rednered HMTML Markupt or a Promise resolving to it | ||
*/ | ||
const render = (resumeJson) => { | ||
let css, resumeTemplate; | ||
|
||
try { | ||
css = fs.readFileSync(path.resolve(__dirname, 'styles/main.css'), 'utf-8'); | ||
resumeTemplate = fs.readFileSync(path.resolve(__dirname, 'resume.hbs'), 'utf-8'); | ||
} catch (err) { | ||
throw new Error('The source handlebar template file or the stylesheet could not be read.'); | ||
} | ||
|
||
const handlebars = RENDER_ASCYNC ? handlebarsWax(HandlebarsAsync) : handlebarsWax(Handlebars); | ||
|
||
handlebars.partials(path.resolve(__dirname, 'views/partials/**/*.{hbs,js}')); | ||
handlebars.partials(path.resolve(__dirname, 'views/components/**/*.{hbs,js}')); | ||
|
||
try { | ||
// as long as we use promised-handlebars handlebars.compile returns a Promise! | ||
return handlebars.compile(resumeTemplate)({ | ||
css: css, | ||
resume: resumeJson | ||
}); | ||
} catch (err) { | ||
throw new Error(`Error when rendering the template: ${err}!`); | ||
} | ||
|
||
}; | ||
|
||
module.exports = { | ||
render, | ||
renderAsync, | ||
enableMarkdownSupport, | ||
enableImageProcessing, | ||
}; |
Oops, something went wrong.