randometc / ejs-locals Goto Github PK
View Code? Open in Web Editor NEWThis project forked from publicclass/express-partials
Express 3.x layout, partial and block template functions for the EJS template engine.
This project forked from publicclass/express-partials
Express 3.x layout, partial and block template functions for the EJS template engine.
Hi!
I tried to ru my project on node 0.8.0 however I seem to have a problem with ejs-locals:
npm ERR! node -v v0.8.0
npm ERR! npm -v 1.1.32
npm ERR! message No compatible version found: ejs-locals@'>=0.1.3- <0.2.0-'
npm ERR! message No valid targets found.
npm ERR! message Perhaps not compatible with your version of node?
Do not understand, but i have errors, while use switch or if/else op...
Somethin like this :
<% switch ( state ) { %>
<% case 0: %>
some text
another one
First state
Second state
EJS supports includes in the form of <%- include('file.ejs', { data: 123 }) %>
, whereas, if we use ejs-locals
, we're forced to use the old includes syntax, <%- include file.ejs %>
where we can't pass data to the partials. This needs a fix.
Stupid error:
TypeError: /Users/holmes/Code/Bleep/app/views/secrets/secrets.ejs:1
>> 1| <? layout('layout.ejs') ?>
2| <?
3| var feedback = req.session.feedback;
4| ?>
string is not a function
at eval (eval at <anonymous> (/Users/holmes/Code/Bleep/app/node_modules/ejs-locals/node_modules/ejs/lib/ejs.js:234:12))
at exports.compile (/Users/holmes/Code/Bleep/app/node_modules/ejs-locals/node_modules/ejs/lib/ejs.js:239:15)
at Object.exports.render (/Users/holmes/Code/Bleep/app/node_modules/ejs-locals/node_modules/ejs/lib/ejs.js:277:13)
at Object.exports.renderFile (/Users/holmes/Code/Bleep/app/node_modules/ejs-locals/node_modules/ejs/lib/ejs.js:303:22)
at View.module.exports [as engine] (/Users/holmes/Code/Bleep/app/node_modules/ejs-locals/index.js:85:7)
at View.render (/Users/holmes/Code/Bleep/app/node_modules/express/lib/view.js:75:8)
at Function.app.render (/Users/holmes/Code/Bleep/app/node_modules/express/lib/application.js:504:10)
at ServerResponse.res.render (/Users/holmes/Code/Bleep/app/node_modules/express/lib/response.js:753:7)
at Function.controller.secrets (/Users/holmes/Code/Bleep/app/controllers/secrets.js:45:7)
at /Users/holmes/Code/Bleep/app/node_modules/yarn/yarn.js:5:41
Child template:
<? layout('layout.ejs') ?>
<?
var feedback = req.session.feedback;
?>
<div ...
Part of the app.js file:
// App Configuration
app.configure(function(){
app.engine('ejs', require('ejs-locals'));
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
app.locals.layout = 'layout.ejs'
app.locals.open = '<?';
app.locals.close = '?>';
What else do I need to post that would help with this problem? I'm following the instructions on how to use this library, but it doesn't work.
views/layout.ejs:
<!DOCTYPE html>
<html>
<head>
<title>test</title>
</head>
<body>
<%- body -%>
</body>
</html>
views/post.ejs:
<% layout('layout') -%>
<h1><%= title %></h1>
<p><%= body %></p>
Route:
exports.index = function(req, res){
res.render('index', { title: 'this is a test', body: 'test body' } );
};
Renders:
<!DOCTYPE html>
<html>
<head>
<title>test</title>
</head>
<body>
test body
</body>
</html>
Expected:
<!DOCTYPE html>
<html>
<head>
<title>test</title>
</head>
<body>
<h1>this is a test</h1>
<p>test body</p>
</body>
</html>
I've since changed my view to use "content" instead of "body" but thought it was best to bring this up. If it's expected behavior, you might want to add it to the readme.
This is causing page not to be rendered, data is not found:
login.ejs
<% layout(layout) %>
<% var title = 'Login page' %>
layout.ejs
<title><%= title %></title>
It works fine if I remove the 'var' in the partial.
How would I insert a script tag from a template with dynamic data?
In my layout I have
<%- block.scripts %>
In my page template I want to replace it with some dynamic data:
<% block('scripts', "<script> var app = window.app || {}; app.err = <%- JSON.stringify(err) %>, app.q = <%- JSON.stringify(q) %>; </script>") -%>
I get an error:
500 SyntaxError: Unexpected token % -- i'm assuming because I can't do <%= JSON.stringigy(err) %> here.
Details['11'] = {
'id': '11',
'name': 'Avanish'
};
res.render('/index',{'Message': Details});
Page code
<script>
var ERRORCONST = 'Error';
var NORECORDS = 'No records';
</script>
<%if(Message != undefined && Message != NORECORDS && Message != ERRORCONST ){%>
<%Message.forEach(function(key){%>
<span><%= key.id %> - <%= key.name %></span>
<%});%>
<%}%>
Getting error ``NORECORDS is not defined`and print all code on page. I have two error. One is how to use Multiple condition in single if statement and second is how to compare javascript varibale with server variable
if i remove && Message != NORECORDS && Message != ERRORCONST
after that getting error forEach not a function.
If i try to use a slash in a view name it silently fails. Took a while just to figure out what had happened. need to handle errors better. and allow slash in view name. but other than that this is lookin good!
*edit: when using partials.
Love the package, but trying to use the same template on server and client side. Have tried using the visionmedia/ejs client side library, unfortunately it expects a 'foreach' in the template, whereas ejs-locals partial does not. Is there a recommended way to do this, or is client-side support coming?
Thanks.
I want to toggle a block of html in layout.ejs when called from page.ejs
something like setting hide_title = true; and having layout.ejs look for that variable.
In JS file:
var ejs = require('ejs');
ejs.filters.escape = function(str) {
return escape(String(str));
}
In EJS template:
<%=: text | escape %>
Error:
Object # has no method 'escape'
I am trying to include an html fragment from a hosted server, this is due to how our decoupled cms works. It does not respect the url and tries to find the asset locally.
<%-include('http://www.website.co.uk/components/footer.html')%>
gets compiled and throws a 500 error due to missing file as:
'/localfilepath/http://www.website.co.uk/components/footer.html'
Is there anyway around this?
That should not be the case, because it keeps users to use <%- block(…) -%>
to remove linefeeds around the call to block()
when we simply use <% block(…) %>
.
From documentation it seems clear it's an instruction and therefore will return nothing and can safely be called with that kind of brackets ;)
There may be either a fix in documentation (if the behavior is desired and should be kept), or a fix in the behavior. What's your call?
I'm trying to include another file:
<%- include ("partials/messages") %>
but am getting this error:
Unexpected token ')' in <directory> while compiling ejs
I'm trying to work out how I can render a view without express. I can get this to work with ejs directly using the ejs.render() method but can't see how I can do this using ejs-locals.
Any pointers would be greatly appreciated.
Many Thanks
Oliver
The resolved paths of includes/partials inside a view that is itself an include/partial is relative to the original view and not the current rendering view.
I tried a quick debug trace and I'm not sure if it's ejs or ejs-locals
I've been trying to find a way of handling template overrides with a theme folder. The project I'm working on will implement themes that can override a default template. I would like to keep the syntax of calling templates so the following statement would look for the file in a theme folder first and load it if exists.
<% layout('layouts/public') -%>
So lets say that the default views folder is 'root/views' and the theme folder is 'root/themes/mytheme'. The engine would try to find 'layouts/public.ejs' relative to the theme folder and the file the template was called from. If it doesn't exist it should attempt to load the from the views folder.
If the template was called from
root/views/mymodule/index.ejs
it would look first for the file
root/themes/mytheme/mymodule/layouts/public.ejs
if not found it would look for
root/views/layouts/public.ejs
I've found a possible way to handle this by editing the renderFile method in index.js. I'd appreciate any feedback on the change and how one would go about getting it included.
I've added the following lines just before the call to ejs.renderFile()
//Get the theme folder (options.settings['theme'])
var themeFilePath = dirname(file).replace(resolve(options.settings.views), resolve(options.settings['theme']))
//If the current file exists reletive to the theme folder set the file to that path
if (fs.existsSync(resolve(themeFilePath, basename(file)))) file = resolve(themeFilePath, basename(file));`
This relies on the following being set when the view engine is declared, in my case in the server.js:
app.set('theme', __dirname + [PATH_TO_THEME]);
The ejs-locals renderFile method now looks like:
var renderFile = module.exports = function (file, options, fn) {
// Express used to set options.locals for us, but now we do it ourselves
// (EJS does some __proto__ magic to expose these funcs/values in the template)
if (!options.locals) {
options.locals = {};
}
if (!options.locals.blocks) {
// one set of blocks no matter how often we recurse
var blocks = { scripts: new Block(), stylesheets: new Block() };
options.locals.blocks = blocks;
options.locals.scripts = blocks.scripts;
options.locals.stylesheets = blocks.stylesheets;
options.locals.block = block.bind(blocks);
options.locals.stylesheet = stylesheet.bind(blocks.stylesheets);
options.locals.script = script.bind(blocks.scripts);
}
// override locals for layout/partial bound to current options
options.locals.layout = layout.bind(options);
options.locals.partial = partial.bind(options);
//Get the theme folder (options.settings['theme'])
var themeFilePath = dirname(file).replace(resolve(options.settings.views), resolve(options.settings['theme']))
//If the current file exists reletive to the theme folder set the file to that path
if (fs.existsSync(resolve(themeFilePath, basename(file)))) file = resolve(themeFilePath, basename(file));
ejs.renderFile(file, options, function (err, html) {
if (err) {
return fn(err, html);
}
var layout = options.locals._layoutFile;
// for backward-compatibility, allow options to
// set a default layout file for the view or the app
// (NB:- not called `layout` any more so it doesn't
// conflict with the layout() function)
if (layout === undefined) {
layout = options._layoutFile;
}
if (layout) {
// use default extension
var engine = options.settings['view engine'] || 'ejs',
desiredExt = '.' + engine;
// apply default layout if only "true" was set
if (layout === true) {
layout = path.sep + 'layout' + desiredExt;
}
if (extname(layout) !== desiredExt) {
layout += desiredExt;
}
// clear to make sure we don't recurse forever (layouts can be nested)
delete options.locals._layoutFile;
delete options._layoutFile;
// make sure caching works inside ejs.renderFile/render
delete options.filename;
if (layout.length > 0 && layout[0] === path.sep) {
// if layout is an absolute path, find it relative to view options:
layout = join(options.settings.views, layout.slice(1));
} else {
// otherwise, find layout path relative to current template:
layout = resolve(dirname(file), layout);
}
// now recurse and use the current result as `body` in the layout:
options.locals.body = html;
renderFile(layout, options, fn);
} else {
// no layout, just do the default:
fn(null, html);
}
});
};
Is it possible to pass a variable to a layout from withing a page.ejs file?
I am doing this now, but it is a global variable I believe:
item.ejs
<% pg = 'item'; %>
<% layout('../layout') -%>
layout.ejs
<section class="<%= pg ? pg : '' %>">
<% layout('boilerplate') -%>
what does trailing - do?
My application worked good with express 3.x, but after upgrade express module to 4.x, it didn't work anymore. Any plans to support the latest express? I really want to use ejs-locals with express 4.x. Can someone please help me?
Hey, I was just wondering what the support for nested layouts was like.
What I mean by that is a structure like this:
foo.ejs
<div>
<%body%>
</div>
bar.ejs
<% layout("foo") -%>
<strong><%body%></strong>
baz.ejs
<% layout("bar") -%>
Hey, it's me.
I don't mean this particular use case, but a structure that would have a template using a layout that's in turn using another layout.
Just upgraded ejs-locals to find that underscores in object (partial / view / layout) names are being transformed into camel case, I had to debug the code to find this out.
Why was this change made if the previous way was working correctly? I'd prefer to use lowercase names for all my view names in the fs...
Thanks!
I'm trying to send a partial into another partial, it works but the code is rendered as text.
<%- partial('../../assets/linker/templates/box', {box_content: partial('../../assets/linker/templates/icon', {icon: 'fa-users'}), box_title_icon: 'fa-user'}) %>
It's obvioulsy because we need to escape the content returned by the partial
function, but I don't know how here: box_content: partial('../../assets/linker/templates/icon', {icon: 'fa-users'})
I don't know if my approach is the right one, what's the best way to send a block as parameter with ejs-locals? I just found out this module a few days ago.
What I would love would be to send a block in the box_content
parameter that could include other partials and so on.
<?- partial('nav.jade') ?>
This includes nav.jade as EJS and doesn't render it with the jade engine. How do I do what I need to do?
Currently, it appears the only option is relative paths, which gets messy if you have any complex organization of your views.
Could pass Json(that is a array) data to Ejs directly???
The syntax
<%- include('header.ejs') %>
doesn't work here and throws the error:
Error: ENOENT, no such file or directory '/home/boris/express/views/('header.ejs')'
while the
<%- include header %>
is fine.
It is very common behaviour that when we use following code:
include("/folder/script")
the include function should start search for script in /APP_ROOT/folder/script currently instead of application root it uses current folder.
the express 2.x to 3.x transition was hell b/c it took me a while to realize that layout.ejs would never work without your work.
Cheers,
D
PS Thanks to you, wtfjs.org will now run on node 0.6.19, and posting will resume!
When I use inside of template like this:
include('shared/scripts')
and then inside the same template call:
include('someTemplate')
I get error message saying that it cannot find someTemplate inside shared folder.
This is strange that it is trying to lookup relative to previous include.
I want to override the function partial
used as the following: <%- partial('icon', {icon: box_title_icon}) %>
basically, I want to always search for my partials in a specific directory instead of writing the path each time. (Because I share them across app and client/server and the path is quite long)
How can I specify a default path? (Is there an option?) if not then how can I override the helper? What's the best way? i would prefer to not have to mess up with native ejs-locals code.
Thanks!
I want to define some common css files in the layout with stylesheet
for short. But the following code
<%- stylesheet('abc.css') %>
<%- stylesheets %>
generates:
<link rel="stylesheet" href="abc.css">
<link rel="stylesheet" href="abc.css"> // duplicate
Is that mean I should write
<link rel="stylesheet" href="abc.css">
in the layout instead of using stylesheet
? Thanks.
It works fine with express3.0.0rc2 but when I update the project to new express3.0.0rc3 I've got an error
TypeError: Cannot read property 'blocks' of undefined
at View.module.exports [as engine] (/var/www/lib/node_modules/ejs-locals/index.js:65:22)
at View.render (/var/www/lib/node_modules/express/lib/view.js:75:8)
at Function.app.render (/var/www/lib/node_modules/express/lib/application.js:504:10)
at ServerResponse.res.render (/var/www/lib/node_modules/express/lib/response.js:677:7)
at exports.index (/var/www/lib/routes/routes.js:271:7)
at callbacks (/var/www/lib/node_modules/express/lib/router/index.js:165:11)
at param (/var/www/lib/node_modules/express/lib/router/index.js:139:11)
at pass (/var/www/lib/node_modules/express/lib/router/index.js:146:5)
at Router._dispatch (/var/www/lib/node_modules/express/lib/router/index.js:173:5)
at Object.router (/var/www/lib/node_modules/express/lib/router/index.js:33:10)
Hi guys !
I got this error on the W3C validator when I use stylesheet function with media: <% stylesheet("/plugins/fullcalendar.print.css","print") -%>
Error Line 30, Column 91: No space between attributes.
…="/plugins/fullcalendar.print.css"media="print" />
It seems that the generated code missed a spacebar.
Have a good day !
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.