jonschlinkert / templates Goto Github PK
View Code? Open in Web Editor NEWSystem for creating and managing view collections, rendering, engines, routes and more. See the "dev" branch for most recent updates.
License: MIT License
System for creating and managing view collections, rendering, engines, routes and more. See the "dev" branch for most recent updates.
License: MIT License
@doowb @jonschlinkert
I have some template tags in Nunjucks that rely data from the view
property such as path
and key
. It looks like with templates 0.14.6
this may have potentially been removed. Any chance to get this back or should I deal with it in some middleware?
templates 0.13.7 => assemble-core 0.13.0
{
ext: '.html',
engineName: undefined,
settings: {},
view: <File "index.html" <Buffer 7b 25 20 65 78 74 65 6e 64 73 20 6c 61 79 6f 75 74 73 28 27 68 6f 6d 65 27 29 20 25 7d 0a 0a 7b 25 20 64 65 62 75 67 20 25 7d 0a 7b 25 20 62 6c 6f 63 ... >>,
async: true,
helpers:
{ view: [Function: wrapped],
page: [Function: wrapped],
pages: [Function: wrapped]
}
}
templates 0.14.6 => assemble-core 0.13.2
{ ext: '.html',
async: true,
helpers:
{ view: [Function: wrapped],
page: [Function: wrapped],
pages: [Function: wrapped]
},
engineName: undefined
}
const ext = '.html';
const nunj = nunjucks.configure({
watch: false,
noCache: true
});
app.engine(ext, consolidate.nunjucks);
//tempalte tag
export default class GetAsset {
constructor(app) {
this.app = app;
this.tags = ['get_asset'];
}
parse(parser, nodes, lexer) {
const tok = parser.nextToken();
const args = parser.parseSignature(null, true);
if (args.children.length === 0) {
args.addChild(new nodes.Literal(0, 0, ''));
}
parser.advanceAfterBlockEnd(tok.value);
return new nodes.CallExtension(this, 'run', args);
}
run(context, args) {
const {ctx} = context;
const {
assets = {}, //from app.data => assets = {'some/page/path': '/some/src.js'}
environment,
view
} = ctx; //ctx is page context
const {isDev} = environment;
const {path: viewPath} = view; //breaks here because there is no `view.path`
return new nunjucks.runtime.SafeString(`<script src="${assets[viewPath]}"></script>`);
}
}
https://github.com/dtothefp/build-boiler/blob/master/src/templates/layouts/default.html#L24
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
{% get_asset %}
</body>
</html>
After setting everything up setting the layout
on the index.pug
file to be _layout
and rendering it. This is what the output is.
Note: Below are the files that I used.
Actual:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p>
</body>
</html>
<ul>
<li>item</li>
<li>item</li>
<li>item</li>
<li>item</li>
</ul>
<h1>Partial</h1>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p>
<ul>
<li>item</li>
<li>item</li>
<li>item</li>
<li>item</li>
</ul>
<h1>Partial</h1>
</body>
</html>
_layout.pug
doctype html
html
head
meta(charset="utf-8")
body
{% body %}
index.pug
p Lorem ipsum dolor sit amet, consectetur adipisicing elit.
ul
li item
li item
li item
li item
!= helpers.partial('_partial')
_partial.pug
h1 Partial
I have a basic setup: a layout and 2 views built on top of the layout. When I render the first view everything is OK, but when I render second view unless
helper behaves in a weird way: it uses context param value of title
from a previous call to render.
'use strict';
var templates = require('templates');
var app = templates();
/**
* Defin the engine to use
*/
app.engine('txt', require('engine-handlebars'));
app.option('engine', 'txt');
/**
* Create view collections
*/
app.create('pages');
app.create('layouts', {viewType: 'layout'});
app.create('headings', {viewType: 'partial'});
/**
* Add some views
*/
// layout
app.layout('base', {
data: {},
content: '<div>{{#unless title}}{{ title }}{{/unless}}<span>{% body %}</span>{{ title }}</div>',
});
app.option('layout', 'base');
// pages
app.page('one', {
data: {title: 'title-A'},
content: 'ONE',
});
app.page('two', {
data: {},
content: 'TWO',
});
/**
* Render views
*/
app.render('one', {}, function(err, res) {
if (err) return console.log(err.stack);
console.log(res.content);
});
app.render('two', {}, function(err, res) {
if (err) return console.log(err.stack);
console.log(res.content);
});
Expected output:
<div><span>ONE</span>title-A</div>
<div><span>TWO</span></div>
Actual output:
<div><span>ONE</span>title-A</div>
<div>title-A<span>TWO</span></div>
Add an async render
helper that takes a view object and locals
when a view is created without a collection, it will not have a context method, which throws an error in render. We can just decorate the same methods that are used on collection-views onto view to avoid this
Using latest dev
branch of verb, so templates
is latest v0.14.5
(i checked it).
[charlike@voltaire bind-context]$ verb
/usr/local/lib/node_modules/verb/node_modules/templates/lib/plugins/helpers.js:79
this.debug.helpers('getting async helper "%s"', name);
^
TypeError: this.debug.helpers is not a function
at Verb.<anonymous> (/usr/local/lib/node_modules/verb/node_modules/templates/lib/plugins/helpers.js:79:16)
at Verb.<anonymous> (/usr/local/lib/node_modules/verb/node_modules/templates/lib/plugins/helpers.js:116:24)
at Object.module.exports (/usr/local/lib/node_modules/verb/node_modules/templates/lib/helpers/singular.js:7:11)
at Verb.Templates.create (/usr/local/lib/node_modules/verb/node_modules/templates/index.js:316:11)
at Verb.initVerb (/usr/local/lib/node_modules/verb/index.js:61:10)
at new Verb (/usr/local/lib/node_modules/verb/index.js:32:8)
at Verb (/usr/local/lib/node_modules/verb/index.js:28:12)
at Object.<anonymous> (/usr/local/lib/node_modules/verb/bin/verb.js:12:11)
at Module._compile (module.js:413:34)
at Object.Module._extensions..js (module.js:422:10)
And actually I can't realize how debug
comes into utils
, it's unreal hahaha, absolute absurd.
edit: Let's start. ./lib/debug.js
is called on the constructor on line 56. In this file lazy-loaded modules and all files from lib/utils/*
are merged, okey.
@jonschlinkert and I have talked about this and I've been looking through the current modules that have touch points to async helpers and trying some things out to try to improve the experience with some of the use cases that we've come across.
I think that the following steps can be taken to refactor and externalize some of the current pieces, while creating a couple new pieces for so cases:
refactor async-helpers
remove async-helpers from engine-cache
asyncHelpers
instance when compiling, and resolving async helper ids after the string has been rendered base-async-helpers
module that adds the async-helpers functionality to base
applications
asyncHelper
, asyncHelpers
, getAsyncHelper
, and hasAsyncHelper
methods from base-helpers
to `base-async-helpersengine-cache
methods to inject the async-helpers
functionality into .compile
and .render
(this can be more configurable and only enabled for specific engines) Make built-in singular
and plural
helpers "smarter" to know if they're being used as async or sync helpers. Either split them out into a module or just check for the callback.
base-handlebars-async-helpers
module to add necessary helpers and batch methods in Handlebars to allow using async-helpers with built in Handlebars partial syntax.
engine-handlebars
, but engine-handlebars
is not able to get a reference to the asyncHelpers
instance created by engine-cache
.engine-handlebars
in assemble
by default, we can include this also (or have an option to enable async-helpers which would then include base-async-helpers
and base-handlebars-async-helpers
) optional base-engine-async-helpers
module that will do something with engine-base
to get async-helpers to work with regular javascript conditional statements (I don't know exactly how to do this yet, but we've thrown around a few ideas)
I'll be working on these changes over the next few days. Feedback is welcome and encouraged!
I had assemble-core
shrink wrapped since 0.17.1
. Upon upgrading data added to file.data
in preRender
and preCompile
does not seem to persist into my Nunjucks template context. Front-matter added in onLoad
seems to work though.
https://github.com/dtothefp/assemble-view-issue
Run npm start
and see that any data added in preRender
and preCompile
is undefined
Hi
We're using a module named "assemble" and this module uses this one. The modules are installed with a "--production" flag. When using the assemble module, the following error occurs:
Error: Cannot find module 'async'
at Function.Module._resolveFilename (module.js:336:15)
at Function.Module._load (module.js:286:25)
at Module.require (module.js:365:17)
at require (module.js:384:17)
at Object. (/var/app/buildslave/jenkins/workspace/Team Awesom-O/APM/APM Frontend/APM Frontend - deploy DEV/node_modules/assemble/node_modules/assemble-core/node_modules/templates/lib/plugins/context.js:3:13)
It seems the context.js file uses the async-module, but according to the package.json, this should just be a devDependency. I believe that's where the problem is located.
If you need any more information, let me know.
Kind regards,
Yannick
@doowb and I had an interesting conversation a couple of days ago, as a result we're considering adding a fourth view type: grid
, for handling grid systems.
(This is only a partially-formed idea. it's really interesting but is not yet "planned". Feedback welcome)
Synopsis
Whereas "view collections" are used for organizing and caching views, "view types" determine how the individual views in a collection will be handled during the render cycle. For example, views with the partial
view type will be merged onto the context before being passed to the template engine for rendering, but views with the layout
and renderable
types will not.
View types
This library currently supports three view types: partial
, renderable
and layout
. Passed on the viewType
option when a collection is created, collections may have one or more view types, defaulting to renderable
if no other types are defined.
partial
: allows "partial views" to be injected into other views. useful for components, document fragments, or other snippets of reusable code or content.layout
: allows views to "wrap" other views (of any type, including other layouts or partials) with common code or content.renderable
: views that have a one-to-one relationship with rendered files that will eventually be visible to a user or visitor to a website. For example: pages or blog posts.Proposed
The grid
view type would combine concepts from the partial
and layout
types to allow users to pre-define complex page layout systems, whilst also keeping a separation of concerns between structure and content.
In practice, this means that grids themselves would be defined using a declarative configuration, the markup (rows and columns) of the grid would be entirely composed of user-defined views (templates), and the content that will eventually populate the individual "cells" of the grid can also be defined using a declarative configuration - allowing them to be modified on-the-fly during the build cycle (e.g. just as you can easily change the layout
of a view using middleware, you could also customize the cells of a grid on a page-by-page, or collection-by-collection, or task-by-task basis).
The concept
This is totally pseudo-code, but hopefully you will get the idea and be able to give feedback.
Grids will be created like any other views.
app.create('foo', {viewType: 'grid'});
Once created, you would add grid
views with app.foo()
(like other custom collections). We would add support for two special properties unique to grids (we're open to suggestions on the property names):
schema
: an object, for defining the actual grid system using columns, rows, and even other (nested) grids.structure
: an object that provides a semantic "mapping" between the grid-schema-object, and css-based grid "positions" that can be specified by other views (in other words, this would allow you to add a partial to the "banner" position on a grid, instead of row2.col1-col4
or whatever).app.foo('magazine', {
// main content here, along with a "grid" tag defining where the actual grid will be injected
content: '<div>{% grid %}</div>',
// grids can also use layouts, like any other view type
layout: 'main',
// rows and columns in the schema would define the "grid positions", as well as
// the context for those individual "cells"
schema: {
row1: {
// like layouts, the templates in "cells" would be resolved before injecting content
content: '{% row %}',
col1: {
content: '{% col %}',
}
},
row2: {
col1: {
content: '{% col %}',
}
},
row3: {
// nested grid
grid: 'baz',
}
},
structure: {
nav: 'row1.col1',
banner: 'row2.col1',
main: 'row3.grid.row2.co2'
}
});
Then, renderable
views (like pages, posts etc) can specify a grid to use, along with with content to populate the cells. For example:
app.page('whatever', {
content: 'this is some content...',
layout: 'default',
grid: {
name: 'magazine',
structure: {
nav: {
data: {span: 12},
content: '<div class="nav">...</div>'
},
banner: {
data: {span: 12},
content: '<div class="banner">...</div>'
},
main: {
data: {span: 6}
content: 'some content or partials or whatever for the `main` cell on the `magazine` grid'
}
}
}
});
This issue popped up today, not sure what is happening
"version": "0.15.11"
/Users/davidfox-powell/dev/balloon/balloon/server/static/node_modules/templates/lib/views.js:157
if (view.use) this.run(view);
^
TypeError: this.run is not a function
at Views.setView (/Users/davidfox-powell/dev/balloon/balloon/server/static/node_modules/templates/lib/views.js:157:22)
at DestroyableTransform._transform (/Users/davidfox-powell/dev/balloon/balloon/server/static/node_modules/assemble-fs/index.js:152:25)
at DestroyableTransform.Transform._read (/Users/davidfox-powell/dev/balloon/balloon/server/static/node_modules/through2/node_modules/readable-stream/lib/_stream_transform.js:159:10)
at DestroyableTransform.Transform._write (/Users/davidfox-powell/dev/balloon/balloon/server/static/node_modules/through2/node_modules/readable-stream/lib/_stream_transform.js:147:83)
at doWrite (/Users/davidfox-powell/dev/balloon/balloon/server/static/node_modules/through2/node_modules/readable-stream/lib/_stream_writable.js:313:64)
at writeOrBuffer (/Users/davidfox-powell/dev/balloon/balloon/server/static/node_modules/through2/node_modules/readable-stream/lib/_stream_writable.js:302:5)
at DestroyableTransform.Writable.write (/Users/davidfox-powell/dev/balloon/balloon/server/static/node_modules/through2/node_modules/readable-stream/lib/_stream_writable.js:241:11)
at DestroyableTransform.ondata (/Users/davidfox-powell/dev/balloon/balloon/server/static/node_modules/through2/node_modules/readable-stream/lib/_stream_readable.js:531:20)
at emitOne (events.js:90:13)
at DestroyableTransform.emit (events.js:182:7)
at readableAddChunk (/Users/davidfox-powell/dev/balloon/balloon/server/static/node_modules/through2/node_modules/readable-stream/lib/_stream_readable.js:198:18)
at DestroyableTransform.Readable.push (/Users/davidfox-powell/dev/balloon/balloon/server/static/node_modules/through2/node_modules/readable-stream/lib/_stream_readable.js:157:10)
at DestroyableTransform.Transform.push (/Users/davidfox-powell/dev/balloon/balloon/server/static/node_modules/through2/node_modules/readable-stream/lib/_stream_transform.js:123:32)
at afterTransform (/Users/davidfox-powell/dev/balloon/balloon/server/static/node_modules/through2/node_modules/readable-stream/lib/_stream_transform.js:79:51)
at TransformState.afterTransform (/Users/davidfox-powell/dev/balloon/balloon/server/static/node_modules/through2/node_modules/readable-stream/lib/_stream_transform.js:58:12)
at /Users/davidfox-powell/dev/balloon/balloon/server/static/node_modules/vinyl-fs/lib/src/getContents/bufferFile.js:18:5
at /Users/davidfox-powell/dev/balloon/balloon/server/static/node_modules/graceful-fs/graceful-fs.js:78:16
at FSReqWrap.readFileAfterClose [as oncomplete] (fs.js:404:3)
Tests were temporarily moved to base-test-suite to prevent creation of duplicate tests while we're updating all of the tests in the assemble, verb, update, generate and base libs.
Refactor the view
helper to return an object, instead of rendering the view
The "singular" collection helper should return an object instead of rendering the view.
I thought in the past if I did
app.data({bleep: 'bleep'})
app.onLoad(/\.html$/, (file, next) => {
file.data = {bleep: 'bloop'}
next(null, file);
})
that the same key on file.data
would overwrite that for app.cache.data
but that doesn't seem to be the case
here's an example, run node index.js
I'm a quite heavy user of assemble. Maybe there is no reason to change something in assemble, but the project seems to be sleeping for a while and for that reason I was looking for the next big thing in static site generation. I encountered templates and template and they appear to be very similar, not just their names.
Could you please provide some information which project to use, depending on the case?
And I'm asking myself how much value assemble provides compared to templates. Is it much more than a grunt-plugin calling template and selecting a template engine (handlebars)?
Where would templates be used? Typically "offline" site generation or delivering "online", embedded in something like express?
I apologize if the questions are dumb, maybe I'm not deep enough in that business and as a result not able to imagine what to do with the more low-level libraries you provide. BTW thanks for your great work!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.