Skip to content

Commit

Permalink
Implement basic templating
Browse files Browse the repository at this point in the history
  • Loading branch information
jsphpl committed Apr 10, 2021
1 parent 939865b commit 0dc6d17
Show file tree
Hide file tree
Showing 27 changed files with 383 additions and 3 deletions.
10 changes: 10 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
root = true

[*]
end_of_line = lf
insert_final_newline = true
indent_style = space
indent_size = 4

[Makefile]
indent_style = tab
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
node_modules
out
!out/.gitkeep
26 changes: 23 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,25 @@
Hier dokumentieren wir wie wir unser Portfolio erstellen.
# Portfolio (Mobiles FabLab)

Resourcen:
- [Druckvorlage](https://www.wir-machen-druck.de/broschueren-drahtheftung-din-a5-quer-extrem-guenstig-drucken,category,9437.html
> Content and (PDF-) generators for our portfolio (digital & print)
## Resources:
- [Print layout](https://www.wir-machen-druck.de/broschueren-drahtheftung-din-a5-quer-extrem-guenstig-drucken,category,9437.html
)

## Dev Setup
```sh
npm install
```

## Usage
1. Place content inside `content` directory (markdown with yaml front matter)
2. Define build targets in `targets.js`. Keys of the object are valid values for the `target` arugment to the generate command
3. Create templates (in `templates` directory)
4. Generate output: `npm run generate <target>`

## Guides
### Templating
This project uses handlebars.js for templating. Please refer to the [Language Guide](https://handlebarsjs.com/guide) on how to write handlebars templates.

### Markdown
The markdown parser used in this project is called [markdown-it](https://github.com/markdown-it/markdown-it). It implements the CommonMark standard plus some extensions. Please refer to the [CommonMark Spec](https://spec.commonmark.org/current/) for valid syntax.
3 changes: 3 additions & 0 deletions config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = {
templateDir: './templates',
}
Empty file removed content/.gitkeep
Empty file.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes
147 changes: 147 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 30 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"name": "portfolio",
"version": "0.0.1",
"description": "",
"main": "index.js",
"authors": [
{
"name": "Alexander Kutschera",
"email": "[email protected]"
},
{
"name": "Julian Heyder",
"email": "[email protected]"
},
{
"name": "Joseph Paul",
"email": "[email protected]"
}
],
"repository": "[email protected]:mobiles-fablab/portfolio.git/portfolio",
"scripts": {
"generate": "node src/generate.js"
},
"license": "MIT",
"devDependencies": {
"handlebars": "^4.7.7",
"markdown-it": "^12.0.4",
"yaml-front-matter": "^4.1.1"
}
}
68 changes: 68 additions & 0 deletions src/generate.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
const Loader = require('./loader')
const Parser = require('./parser')
const Renderer = require('./renderer')

const targets = require('../targets')
const config = require('../config')

const target = process.argv.slice(2)[0]
if (!target) {
displayUsage()
console.error('Please specify the <target> argument\n')
process.exit(-1)
}

process.exit(run(target))

/**
* Run the generator.
*
* @param {string} target
* @return {int}
*/
function run(target) {
if (!(target in targets)) {
console.error(`Target "${target}" not defined\n`)
return -1
}

const targetConfig = targets[target]

const renderer = new Renderer(config.templateDir)

const results = []
const loader = new Loader(targetConfig.sourceDir)
for (const page of loader.iterate()) {
results.push(generate(page, targetConfig, renderer))
}

console.log(renderer.render(targetConfig.skeleton, {
pages: results,
}))

return 0
}

/**
* Generate a single page.
*
* @param {object} page
* @param {object} targetConfig
* @param {Renderer} renderer
* @return {[type]}
*/
function generate(page, targetConfig, renderer) {
const parser = new Parser()
const html = parser.toHtml(page.__content)
delete page.__content
page.content = html

return renderer.render(targetConfig.template, page)
}

/**
* Display CLI usage instructions.
*/
function displayUsage() {
console.info('Usage: generate.js <target>\n')
}
47 changes: 47 additions & 0 deletions src/loader.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
var fs = require('fs')
var yamlFront = require('yaml-front-matter')

const DEFAULT_CONFIG = {
extensions: ['.md'],
}

class Loader {
constructor(directory, config = {}) {
this.directory = directory
this.config = Object.assign(Object.assign({}, DEFAULT_CONFIG), config)
}

*iterate() {
const files = fs.readdirSync(this.directory, { withFileTypes: true })
for (const entry of files) {
if (!this.fileIsRelevant(entry)) continue

yield this.parse(entry.name)
}
}

parse(filename) {
const rawContent = fs.readFileSync(this.directory + '/' + filename)
const page = yamlFront.loadFront(rawContent)
page.filename = filename

return page
}

fileIsRelevant(entry) {
if (!entry.isFile()) return false

let matchedExtension = false
for (const ext of this.config.extensions) {
if (entry.name.endsWith(ext)) {
matchedExtension = true
break
}
}
if (!matchedExtension) return false

return true
}
}

module.exports = Loader
13 changes: 13 additions & 0 deletions src/parser.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
var MarkdownIt = require('markdown-it')

class Parser {
constructor() {
this.md = new MarkdownIt()
}

toHtml(markdown) {
return this.md.render(markdown)
}
}

module.exports = Parser
25 changes: 25 additions & 0 deletions src/renderer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
const Handlebars = require("handlebars")
var fs = require('fs')

class Renderer {
constructor(directory) {
this.directory = directory
this.hb = Handlebars.create()
this.templates = {}
}

render(template, attributes) {
this.compileTemplate(template)

return this.templates[template](attributes)
}

compileTemplate(filename) {
if (filename in this.templates) return

const content = fs.readFileSync(this.directory + '/' + filename, 'utf-8')
this.templates[filename] = this.hb.compile(content)
}
}

module.exports = Renderer
8 changes: 8 additions & 0 deletions targets.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module.exports = {
portfolio: {
sourceDir: 'content/portfolio',
template: 'portfolio.html',
skeleton: '_skeleton.html',
outputDir: `out/portfolio`,
}
}
5 changes: 5 additions & 0 deletions templates/_skeleton.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{{#each pages}}
<div class="page">
{{ this }}
</div>
{{/each}}
Loading

0 comments on commit 0dc6d17

Please sign in to comment.