Verified Commit 6b4e4805 authored by Aral Balkan's avatar Aral Balkan
Browse files

Merge branch 'partials'

parents 8a50a0dc 0ee31429
......@@ -29,10 +29,18 @@
jsdom = require 'jsdom'
fs = require 'fs'
path = require 'path'
crypto = require 'crypto'
# Load the Tally engine.
set = (fs.readFileSync __dirname + '/set.js', 'utf8').toString()
partialCache = {}
templateCache = {}
documentCache = {}
includeRegEx = /\<!--\s*include\s+(\S+)\s*--\>/g
# The Express 3 export.
exports.__express = (path, data, callback) ->
fs.readFile path, 'utf8', (error, template) ->
......@@ -44,7 +52,83 @@ exports.__express = (path, data, callback) ->
callback null, html
#
# Add partials to the template and return it
#
# Partial format:
#
# <!-- include route/to/partial.file -->
#
addPartials = (template) ->
# Check if the final template has already been generated from partials and cachced. If so, use that.
templateHash = crypto.createHash('md5').update(template).digest('hex')
cachedTemplate = templateCache[templateHash]
if cachedTemplate != undefined
# console.log "Using template from cache."
return cachedTemplate
# Template not found in cache. Try and render partials.
matches = []
viewsPath = path.normalize (path.join __dirname, '..', 'views')
while (theMatch = includeRegEx.exec template) != null
matches.push theMatch
for match in matches
tokenToReplace = match[0]
partialFilePath = path.join viewsPath, match[1]
partial = partialCache[partialFilePath]
if partial == undefined
# console.log "Loading partial #{partialFilePath}…"
partial = fs.readFileSync partialFilePath, 'utf8'
partialCache[partialFilePath] = partial
# else
# console.log "Using partial from cache: #{partialFilePath}"
# console.log partial
template = template.replace (new RegExp tokenToReplace, 'g'), partial
# Cache the template
templateCache[templateHash] = template
return template
render = (template, data) ->
# Debug: timing.
# startTime = new Date()
#
# To use document cache, explicitly set it on by passing
#
# { …, __set: {cache: true} }
#
# as part of your data object.
useCache = (data['__set'] != undefined) && (data['__set']['cache'] == true)
if useCache
# Check if the document rendered with this data exists in the cache.
documentHash = crypto.createHash('md5').update("#{template}#{JSON.stringify(data)}").digest('hex')
cachedDocument = documentCache[documentHash]
if cachedDocument != undefined
# console.log "Returning document from cache."
# console.log "Took: #{(new Date() - startTime)}"
return cachedDocument
# Add partials to template
template = addPartials template
# Create the DOM.
document = jsdom.jsdom(template)
......@@ -141,6 +225,13 @@ render = (template, data) ->
# Add the doctype to the top of the rest of the HTML
html = "#{doctypeHTML}#{html}"
if useCache
# Save the rendered document (for this data) in the cache.
documentCache[documentHash] = html
# Debug: timing.
# console.log "Took: #{(new Date() - startTime)} ms."
return html
exports.render = render
################################################################################
#
# Cached documents page.
#
# Demonstrates how cached documents are used.
#
# Copyright © Aral Balkan.
# Released with ♥ by Ind.ie under the MIT License.
# Portions released under the Apache License.
#
################################################################################
exports.route = (request, response) ->
data =
title: 'Ind.ie Labs: Set: Document Caching'
__set:
cache: true # Use the document cache
response.render 'document-caching', data
......@@ -15,4 +15,4 @@ exports.route = (request, response) ->
meta = require('../../package.json')
version = meta.version
response.render 'main', {version: version}
response.render 'main', {version: version, __set:{cache: true}}
################################################################################
#
# Set partials example.
#
# Demonstrates how partials are used.
#
# Copyright © Aral Balkan.
# Released with ♥ by Ind.ie under the MIT License.
# Portions released under the Apache License.
#
################################################################################
exports.route = (request, response) ->
data =
title: 'Ind.ie Labs: Set: Partials'
__set:
cache: true # Use the document cache
response.render 'partials', data
......@@ -25,4 +25,6 @@ exports.route = (request, response) ->
data.title = 'Read me!'
data.readme = readme
data.__set.cache = true
response.render 'readme', data
......@@ -12,7 +12,7 @@
# Sample data
data =
title: 'Set sample'
title: 'Simple Set Demo'
name: 'Set'
class: 'rendered-summary'
content: 'This is a simple example to demonstrate Set, a templating engine for Express (node.js) and client‐side JavaScript.'
......@@ -37,6 +37,7 @@ exports.route = (request, response) ->
return 'https://' + value + '.ie'
isSelected: (value) ->
return 'tab selected'
cache: true
}
response.render 'simple', data
......
......@@ -37,6 +37,12 @@ createRoute '/'
# Simple template example (with static data)
createRoute '/simple'
# Partials demo
createRoute '/partials'
# Document caching
createRoute '/document-caching'
# App.net global timeline example.
createRoute '/posts'
......
......@@ -2,7 +2,7 @@
<html lang='en'>
<head>
<!-- ***** -->
<!-- Note: Do not render this via a Set route -->
<!-- Labs common -->
<meta charset="utf-8">
......
<footer>
<p>Copyright © <a href='https://aralbalkan.com'>Aral Balkan</a>. Released with ♥ by <a href='https://ind.ie'>Ind.ie</a> under the MIT License. Portions released under the Apache License. <a href='mailto:aral@ind.ie'>Questions, feedback, etc.</a></p>
</footer>
<!doctype html>
<html lang='en'>
<head>
<!-- Labs common -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title data-set-text='title'>Ind.ie Labs: Set</title>
<link rel="alternate" type="application/rss+xml" title="Ind.ie Labs Blog" href="https://ind.ie/labs/blog/rss/index.xml">
<!--[if lte IE 8]>
<script src='https://ind.ie/assets/js/html5shiv.js'></script>
<![endif]-->
<link rel="shortcut icon" href="/favicon.ico">
<link rel="apple-touch-icon" href="https://ind.ie/assets/images/ios-180.png">
<link rel="apple-touch-icon" sizes="76x76" href="https://ind.ie/assets/images/ios-76.png">
<link rel="apple-touch-icon" sizes="120x120" href="https://ind.ie/assets/images/ios-120.png">
<link rel="apple-touch-icon" sizes="152x152" href="https://ind.ie/assets/images/ios-152.png">
<link rel="apple-touch-icon" sizes="152x152" href="https://ind.ie/assets/images/ios-180.png">
<link rel="stylesheet" href="https://ind.ie/assets/css/lab-styles.css">
<!-- Set -->
<link rel='stylesheet' type='text/css' href='css/base.css'>
<link data-set-dummy rel='stylesheet' type='text/css' href='css/set-highlights.css'>
<link rel='stylesheet' href='https://ind.ie/assets/css/set-styles.css'/>
<link rel='stylesheet' type='text/css' href='css/indie.css'>
<!-- Syntax highlighting for the code -->
<link rel='stylesheet' type='text/css' href='css/prism.css'>
<script data-set-dummy src='js/set-highlights.js'></script>
<link rel='stylesheet' type='text/css' href='css/simple.css'>
<!-- Labs common, inline styles -->
<style>
.main {
padding: 14px;
padding-top: 0;
}
@media only screen and (min-width: 600px) {
.main {
margin: 0 auto;
max-width: 700px;
padding: 21px;
padding-top: 0;
}
}
h1 {
margin-bottom: 14px;
}
h2 {
margin-top: 14px;
}
.projects {
border-bottom: 1px solid #d8d8d8;
margin: 0;
}
.projects li {
border-top: 1px solid #d8d8d8;
clear: both;
list-style-type: none;
overflow: hidden;
margin-bottom: 24px;
text-align: center;
}
@media only screen and (min-width: 745px) {
.projects li {
text-align: left;
display: -webkit-flex;
display: flex;
-webkit-flex-flow: row wrap;
flex-flow: row wrap;
-webkit-justify-content: center;
justify-content: center;
-webkit-box-align: center;
-moz-box-align: center;
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center;
margin-bottom: 0;
}
.projects li p {
-webkit-flex: 1 auto;
flex: 1 auto;
float: left;
margin-bottom: 0;
margin-left: 28px;
max-width: 337px;
}
}
.archived .old, .archived img, .archived h3 {
opacity: .6;
}
.archived .update {
opacity: 1;
}
.projects li h3 a {
display: block;
margin: 0 auto;
max-width: 335px;
}
@media only screen and (min-width: 745px) {
.projects li h3 a {
-webkit-flex: 1 auto;
flex: 1 auto;
margin: 0;
}
}
.projects .hero-image {
margin-top: 0;
}
@media only screen and (min-width: 745px) {
.projects .hero-image {
float: left;
}
}
@media only screen and (min-width: 745px) {
.oskar-the-scientist {
margin: 20px auto 0 auto;
max-width: 450px;
}
}
.sub-navigation--list {
margin: 0;
margin-top: 11px;
overflow: hidden;
padding: 0;
/* flex box to centre children */
display: -webkit-flex;
display: -moz-flex;
display: flex;
-webkit-flex-flow: row wrap;
-moz-flex-flow: row wrap;
flex-flow: row wrap;
-webkit-justify-content: center;
-moz-justify-content: center;
justify-content: center;
}
@media only screen and (min-width: 600px) {
.sub-navigation--list {
margin-top: 0;
}
}
.sub-navigation--list {
margin: 0;
/* Make sure that the rule is written out only once in case there is no rem substitution */
margin: 0;
margin-top: 11px;
margin-top: 0.6875rem;
overflow: hidden;
padding: 0;
/* Make sure that the rule is written out only once in case there is no rem substitution */
padding: 0;
/* flex box to centre children */
display: -webkit-flex;
display: -moz-flex;
display: flex;
-webkit-flex-flow: row wrap;
-moz-flex-flow: row wrap;
flex-flow: row wrap;
-webkit-justify-content: center;
-moz-justify-content: center;
justify-content: center;
}
@media only screen and (min-width: 600px) {
.sub-navigation--list {
margin-top: 0;
}
}
.sub-navigation--list li {
float: left;
list-style-type: none;
margin-bottom: 0;
padding: 0 13px 1px 1px;
/* Make sure that the rule is written out only once in case there is no rem substitution */
padding: 0 0.8125rem 0.4375rem 0.8125rem;
}
.sub-navigation--list li a {
border-bottom: 1px solid #191919;
border-bottom: 0.0625rem solid #191919;
color: #191919;
display: block;
float: left;
font-size: 16px;
font-size: 1rem;
line-height: 21px;
line-height: 1.3125rem;
padding: 18px 1px 1px 1px;
/* Make sure that the rule is written out only once in case there is no rem substitution */
padding: 1.125rem 0.0625rem 0.0625rem 0.0625rem;
text-decoration: none;
-webkit-transition: all 0.3s ease;
-moz-transition: all 0.3s ease;
-ms-transition: all 0.3s ease;
-o-transition: all 0.3s ease;
transition: all 0.3s ease;
}
.sub-navigation--list li a:hover,
.sub-navigation--list li a:active,
.sub-navigation--list li a:focus {
border-color: #000;
color: #000;
}
.labs-projects .sub-navigation .projects-link a,
.labs-blog .sub-navigation .blog-link a {
background: #ccc;
border-bottom: none;
-webkit-border-radius: 7px;
border-radius: 7px;
display: inline-block;
margin-top: 11px;
margin-top: 0.6875rem;
padding: 7px 14px 1px 1px;
/* Make sure that the rule is written out only once in case there is no rem substitution */
padding: 0.4375rem 0.875rem;
-webkit-transition: none;
-moz-transition: none;
-ms-transition: none;
-o-transition: none;
-webkit-transition: all none ease;
-moz-transition: all none ease;
-ms-transition: all none ease;
-o-transition: all none ease;
transition: all none ease;
}
@media only screen and (min-width: 770px) {
.labs-projects .sub-navigation .projects-link a,
.labs-blog .sub-navigation .blog-link a {
background: url("https://ind.ie/assets/images/sprite.svg") no-repeat top center;
border-bottom: 1px solid #191919;
border-bottom: 0.0625rem solid #191919;
-webkit-border-radius: 0;
border-radius: 0;
display: block;
margin-top: 0;
padding: 18px 1px 1px 1px;
padding: 1.125rem 0.0625rem 0.0625rem 0.0625rem;
}
.no-svg .labs-projects .sub-navigation .projects-link a,
.no-svg .labs-blog .sub-navigation .blog-link a {
background-image: url("https://ind.ie/assets/images/sprite.png");
}
}
/* Funding footer */
.fund-us {
border-top: 1px solid #ccc;
border-top: 0.0625rem solid #ccc;
border-bottom: 1px solid #ccc;
border-bottom: 0.0625rem solid #ccc;
margin-top: 56px;
margin-top: 3.5rem;
overflow: hidden;
}
@media only screen and (min-width: 580px) {
.fund-us {
margin-top: 140px;
margin-top: 8.75rem;
}
}
.flexbox .fund-us {
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
-webkit-flex-direction: row;
-ms-flex-direction: row;
flex-direction: row;
-webkit-flex-wrap: wrap;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
-webkit-justify-content: flex-start;
-ms-flex-pack: start;
justify-content: flex-start;
-webkit-align-content: stretch;
-ms-flex-line-pack: stretch;
align-content: stretch;
-webkit-align-items: flex-start;
-ms-flex-align: start;
align-items: flex-start;
}
.fund-us h2 {
font-size: 26px;
font-size: 1.625rem;
line-height: 35px;
line-height: 2.1875rem;
margin-top: 28px;
margin-top: 1.75rem;
margin-bottom: 14px;
margin-bottom: 0.875rem;
}
@media only screen and (min-width: 620px) {
.fund-us p {
float: left;
margin-bottom: 28px;
margin-bottom: 1.75rem;
max-width: 70%;
}
}
.fund-us .button {
background: #4d4d4d;
border: none;
-webkit-border-radius: 5px;
border-radius: 5px;
box-sizing: border-box;
color: #fff;
cursor: pointer;
font-size: 18px;
font-size: 1.125rem;
font-family: "Avenir Next", Avenir, 'Helvetica Neue', Helvetica, sans-serif;
height: 35px;
height: 2.1875rem;
line-height: 24px;
margin-top: 14px;
margin-top: 0.875rem;
margin-left: auto;
margin-bottom: 28px;
margin-bottom: 1.75rem;
margin-right: auto;
padding-right: 28px;
padding-right: 1.75rem;
padding-left: 28px;
padding-left: 1.75rem;
max-width: 130px;
max-width: 8.125rem;
text-decoration: none;
}
@media only screen and (min-width: 620px) {
.fund-us .button {
float: right;
margin-top: 0;
margin-right: 0;
margin-bottom: 28px;
margin-bottom: 1.75rem;
}
}
</style>
<!-- Custom head content, if any, can go on the specific page template itself. -->
\ No newline at end of file
</head>
<!-- Labs common -->
<body class="labs labs-projects">
<nav class="site-navigation">
<ul class="site-navigation--list">
<li class="home-link">
<a href="https://ind.ie/">Home</a>
</li>
<li class="about-link">
<a href="https://ind.ie/about">About</a>
</li>
<li class="labs-link">
<a href="https://ind.ie/labs">Labs</a>
</li>
<li class="forum-link">
<a href="https://forum.ind.ie">Forum</a>
</li>
<li class="videos-link">
<a href="https://ind.ie/videos">Videos</a>
</li>
<li class="news-link">
<a href="https://ind.ie/blog">News</a>
</li>
<li class="fund-link">
<a href="https://ind.ie/fund">Fund</a>
</li>
</ul>
</nav>
<nav class="sub-navigation labs-navigation">
<ul class="sub-navigation--list">
<li class="projects-link"><a href="">Projects</a></li>
<li class="blog-link"><a href="blog/">Blog</a></li>
</ul>
</nav>
<!-- Page specific -->