How to set a variable layout in Jade? - layout

I want to set a customisable layout path in Jade.
I get the path from my app and put it in Express in res.locals._layout like it (app.js is under /lib):
app.set('views', __dirname + '/../views');
app.set('view engine', 'jade');
res.locals._layout = layout_path;
Then I try to pass it to extends in my view like it:
extends _layout
I also tested extends #{_layout}, with also bad results...
Here is the error I get for the last one:
ENOENT, no such file or directory '/root_path/views/#{_layout}.jade'
The doc is not verbose on such a point.

I don't think what you're trying to do is supported by jade. The extends is resolved when the template is compiled, before any res.locals state can be applied. But there are some workarounds mentioned in this thread.
https://github.com/jadejs/jade/issues/520

Related

Nunjucks rendering file paths relative to route being called and overriding express.static setting

Using Nunjucks with Node
Trying to figure out a graceful solution to the following problem. With a directory tree sorda like this:
app_dir
--app.js
--public
----stylesheets
------mystyles.css
--views
----page.html
----templates
------page_template.html
Have static files like CSS inside my public directory
app.use(express.static(path.join(__dirname, 'public')));
Have the root directory of Nunjucks configured as views
nunjucks.configure('views', {
autoescape: true,
express : app,
watch: true
});
When I am referencing a css file from within page_template.html, nunjucks (I think) automagically creates a relative path based on the route and overrides the static behavior.
For example, when I use /stylesheets/mystyles.css path on page_template.html but call the file that extends it using
/:publication/:page path, the rendered html is /:publication/:page/stylesheets/mystyle.css
I can always write a quick hack that creates relative paths to CSS and other resources based on the route but that doesn't feel like a particularly graceful solution :( Any help much appreciated.
When I am referencing a css file from within page_template.html, nunjucks (I think) automagically creates a relative path based on the route and overrides the static behavior.
I think it's mistake. Nunjucks don't generate any path.
In template from any folder (view, view/templates, etc) you must specify filename considering that public dir is root, e.g.
/stylesheets/mystyles.css for %app%/public/stylesheets/mystyles.css.
I use subfolders in view for grouping templates, e.g. /macros (stored macros), /tools (stored additional pages for my app). Also you can use it to router, e.g. /user/view.html, user/add.html...

ExpressJS static dynamically

I'd like to serve /mbti/:lang/ with static files from directory ./mbti/:lang/.
That is:
/mbti/en/ -> ./mbti/en/index.html
/mbti/en/some.json -> ./mbti/en/some.json
I found static, but seems like it can't do this:
app.use('/mbti/:lang/', express.static(__dirname + '/mbti/' + :lang));
How can I implement this? thanks.
You shouldn't need to do that, just make /mbti/ a static route and anything below that root will be served as static
express.static(__dirname + '/mbti');

Using app.set vs app.value in Express

In my app.js file, I use app.set(valName, value) to pass several config values to my routes.
I then pass the app to my routes: app.use('/', require('./routes/index')(app));
I can then easily use app.get(valName) to retrieve the values in the routes.
My question is: wouldn't it be easier to just use app.valName = value; and then just access app.valName in the route?
Do I have to use the .set and .get? Or will this be violating something?
Do I have to use the .set and .get? Or will this be violating something?
Do you have to? No. Should you? Yes!
By setting your application properties directly to the app object (e.g. app.valName = value;), you may be overwriting properties that Express has initialized for internal use.
You can see from Express's source code that Express applications create the following properties in their init function:
this._baseRoutes = {};
this.cache = {};
this.settings = {};
this.engines = {};
this.defaultConfiguration();
And even more properties are set after the defaultConfiguration function is executed. This means that if you want to have a property named cache, settings, or engines, just to name a few, you will be stepping on Express's toes and will probably cause something to go wrong when your application is running.
You can see from the source of app.set that application settings are sorted in a settings object, not directly in the application object. This is to prevent what I just described above: conflicts with internal property names.

Node app variables passed into stylus file

I am building a little node app and using Express with Jade and Stylus to render some basic HTMl pages.
I was curious if there is a way for me to pass some variables INTO the .styl file that are generated from Node? I am well aware that i can define variables inside of the .styl file but I have a need to be more dynamic. Specifically i was looking for an easy way to store some colors in the db, have node grab those values, then insert those into the .styl file so that when the page is rendered these variables are passed in. It seems like this should be do-able but i am lacking on the details. Any help is appreciated. Thanks!
Thanks to #ebohlman as his advice was close to what i ultimately implemented.
basically i was trying to figure out how to do this on top of the Connect Middleware and here is what i came up with:
when doing app.configure i used the custom compile compile function (key 'compile') like so:
app.use(require('stylus')
.middleware({
src: app.root + '/app/public',
compile: compile
})
);
then i created a couple of functions:
var stylus = require('stylus');
var mylib = function(style){
style.define('themeColor1', function(){
//call to the db that returns a color
color = 'blue';
color = color ? color : 'orange';
return new stylus.nodes.Literal(color);
});
};
var compile = function(str, path) {
return stylus(str)
.use(mylib);
};
then inside of the .styl file i do:
background-color themeColor1();
the ternary operator in the themeColor1 function allows for easy defaults and an override. It took me a bit to figure out the API based upon the examples but it seems like this COULD be a solution others would want to know how to do. If anyone has any downfalls of this approach please let me know.
You can use the Stylus API's define() function to set Stylus variables and make JS functions available to it.

CoffeeScript compiling express.static __dirname + '/public' wrong

I am pretty new to CoffeeScript. I am trying to create Node.js application using the Express.js framework. And in my express app configuration I have this line of code that is compiling wrong:
app.use express.static path + '/public'
it is compiling to this:
app.use(express["static"](path + '/public'));
when I need to be this:
app.use(express.static(path + '/public'));
Does anyone know why this happening and how to fix this? It is causing my public folder to unaccessible.
I am using CoffeeScript 1.3.1
static could be a reserved word in future versions of javascript/ecmascript. Just like top now. So using it as a variable name could cause errors somewhere.
That's why coffee is trying to avoid it.
But they are equivalent, so try to find errors somewhere else.
They're equivalent, don't worry about it.
Express framework using 'serve-static' module for export static method:
exports.static = require('serve-static');
You may try solve your problem like this:
app.use '/static', require('serve-static')(__dirname + '/static')
or override static method in your module.

Resources