node.js and Handlebars: HTML compiled is escaped - node.js

Im using handlebars in a node aplication, and I have trouble.
This is the template index.html
{{CONTENT}}
This is the code
var fs = require("fs");
var handlebars = require("handlebars");
var data = {
CONTENT: "<b>Hello world!</b>"
};
var templateFile = fs.readFileSync('./index.html', 'utf8');
var template = handlebars.compile( templateFile );
var html = template(data);
The problem is that the tags <B> are escaped to <B>
How can I avoid this?

From handlebarsjs.com :
Handlebars HTML-escapes values returned by a {{expression}}. If you
don't want Handlebars to escape a value, use the "triple-stash".
<div class="entry">
<h1>{{title}}</h1>
<div class="body">
{{{body}}}
</div>
</div>
with this context:
{
title: "All about <p> Tags",
body: "<p>This is a post about <p> tags</p>"
}
results in:
<div class="entry">
<h1>All About <p> Tags</h1>
<div class="body">
<p>This is a post about <p> tags</p>
</div>
</div>
However from my point of view it may defeat the purpose of having a template separated than you're js file.
If you use precompile then use noEscape option:
handlebars.precompile(content, {noEscape: true})

You'd want to use the 'triple stash' in your template:
{{{CONTENT}}}

Related

Get text from span using cheerio and node.js

Hi I'm trying to the text inside the span, the one with "Text to get"
I'm getting the div with class="membership-limit-section capture-area" using cheerio and node.js, but I can't get the text from the span.
I have this function to get the div and I can see that it does have more elements inside, but I can«t get the text
url = "URLdata";
rp(url)
.then(function (html) {
var getHtml = $("div[class='membership-limit-section capture-area']", html);
console.log(getHtml);
})
.catch(function (err) {
console.log(err);
});
<body data-n-head>
<div id="_nuxt">
<div id="__layout">
<div class="app-wrapper purge-css-ignore">
<div class="main-container">
<section class="el-container">
<main
class="el-main auto-height-on-print capture-area"
id="components-root"
>
<div data-v-5cc60f9e>
<div data-v-5cc60f9e class="responsive-section">
<div
data-v-7ce2662e
data-v-5cc60f9e
class="membership-limit-section capture-area"
>
<div data-v-5cc60f9e class="dividends">
<div>
<div
data-v-593f497d
class="el-card capture-area is-always-shadow"
>
<h1 data-v-593f497d>Test</h1>
<div
role="alert"
class="el-alert el-alert--warning is-light"
data-v-593f497d
>
<div class="el-alert__content">
<span class="el-alert__title">Text to get</span>
<i
class="el-alert__closebtn el-icon-close"
style="display: none;"
></i>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</main>
</section>
</div>
</div>
</div>
</div>
</body>
Can someone help on how to get the text from the span?
Thanks
The following selector will do for that specific response: .membership-limit-section.capture-area .el-alert__title
Then you can use .text() to obtain the text of the span.
var getHtml = $(
".membership-limit-section.capture-area .el-alert__title",
html
);
console.log(getHtml.text())
Update:
gurufocus.com/stock/KO/dividend I want the "Continuous dividend
increase since 1963" but I cannot get it. I'm able to parse info from
yahoo using cheerio, but not from this website
The content you want to scrape, is loaded on the client side using XHR. So you won't be able to parse it directly using request & cheerio since that part is not being returned, either you hit the endpoint returning that data directly, or you use puppeteer on the main site.
When scraping with requests and cheerio, always log the content and see if what you want to parse is present.
The following selector will do for that specific response: const a=$('div.membership-limit-section capture-area').innerText Then just use a variable it has text of span tag.

See only that text which is clicked

I do not know why it is not working. I want to see that index paragraph which link paragraph is clicked and do not see others. That's my code:
Fiddle
<div class="greyBackground">
<div>
<nav>
<ul>
1234
4567
7890
0987
</ul>
</nav>
</div>
<div>
<h4>Something</h4>
<p>My code 1</p>
<p>My code 2</p>
<p>My code 3</p>
<p>My code 4</p>
</div>
</div>
$(function() {
var myDiv = $(".greyBackground");
var link = $(".myDiv").find("a");
var paragraph = $(".myDiv").find("p");
link.on("click", function(){
var index = $(this).index();
paragraph.hide();
paragraph.eq(index).show();
});
});
Your problem is there is no such class as myDiv so your jQuery won't find anything. You already found the div, though, so you just need to use the variable you created.
var myDiv = $(".greyBackground");
var link = myDiv.find("a");
var paragraph = myDiv.find("p");

CAN we do something like <% alert("TEMP") %> in EJS

I have sent a variable in node.js from res.render() function and I have to use that variable for my script in EJS templating for DOM manipulation.
From Node.js:
res.render('index', {TEMP: 'xyz'});
In the HTML:
<p>This is a HTML demo</p>
<div>
I'm the TEMP variable: <%= TEMP %> <!-- this is going to output xyz -->
<script>
var getTemp = <%= TEMP %>;
console.log(getTemp);
</script>
</div>

marionette keep class on layout element

I'm trying to preserve the full markup of a template, including the class on the root node when using a marionette region. I'm also trying to avoid creating an extra wrapping div. I've solved the problem, but in a way which I don't think is satisfactory.
I am creating and rendering a layout like this:
MyApp = new Backbone.Marionette.Application();
MyApp.addRegions({
mainRegion: "#main"
});
AppLayout = Backbone.Marionette.Layout.extend({
template: '
<div class="row">
<div class="col-md-8"></div>
<div class="col-md-4"></div>
</div>
'
});
var layout = new AppLayout();
MyApp.mainRegion.show(layout);
layout.show(new MenuView());
And the result is that my template is rendered like this:
<div id="main">
<div>
<div class="col-md-8"></div>
<div class="col-md-4"></div>
</div>
</div>
Notice, the class="row" is missing from the root node of the template. It appears that marionette is removing the root div from my template, and then wrapping the contents in a new div.
I have managed to hack a solution to this like this
AppLayout = Backbone.Marionette.Layout.extend({
template: '
<div><!-- sacrificial div -->
<div class="row">
<div class="col-md-8"></div>
<div class="col-md-4"></div>
</div>
</div>
',
onRender: function () {
// get rid of that pesky wrapping-div
// assumes 1 child element.
this.$el = this.$el.children();
this.setElement(this.$el);
}
});
I'm adding an extra root div (my sacrificial div) to my template which marionette removes, and then I'm telling marionette to use the first child as the layouts 'el' (as per Turning off div wrap for Backbone.Marionette.ItemView).
This seems crazy!
Can somebody suggest a better way?
EDIT: n.b. I'd like to keep all the template logic in the template, so don't want to have to use code in my view to specify the class on the root node - if I do this, I end up with a maintenance headache.
Try with
AppLayout = Backbone.Marionette.Layout.extend({
template: '
<div class="col-md-8"></div>
<div class="col-md-4"></div>
',
className: "row"
});
AppLayout is missing its region(s).
AppLayout = Backbone.Marionette.Layout.extend({
template: '
<div class="row">
<div id="region1" class="col-md-8"></div>
<div id="region2" class="col-md-4"></div>
</div>
',
regions: {
region1: '#region1',
region2: '#region2'
}
});
Then at your instantiated layout:
layout.region1.show(new MenuView());
layout.region2.show(new MenuView());
Instead of assigning the template to a string, compile the HTML into a template function with underscore. Something like this:
template: _.template(
'<div class="row">' +
'<div class="col-md-8"></div>' +
'<div class="col-md-4"></div>' +
'</div>'
)

Use layouts with meteor-router

From this discussion here,
Allow a passed in variable to {{renderPages}} helper
I am trying to display a template within an existing {{renderPage}};
My Use case: I have a very simple high level body template
<template name="body">
{{> header}}
{{> notifications}}
<div class="content" id="content">
<div id="main-content">
{{{renderPage}}}
</div>
</div>
{{> footer}}
</template>
And as you can see, my main-content has the {{renderPage}}. This works great, when i set up a route:
'/home': 'home'
The route finds the template 'home' and replaces renderPage with that template. I want to expand that now and see if route templates can be placed within specific divs.
For example, in my home.html template:
<template name="home">
{{#if isAdmin}}
<h1>student</h1>
{{/if}}
<div id="inner_home">
{{renderPage innerHome}}
</div>
</template>
Is it possible to have a different route /home/tools : 'home_tools render it's template not in the highest main content div but within my child div inner_home?
EDIT:
I am evaluating an approach that just uses JQuery and the callback function of the meteor-router method to grab the template i am looking for and add it directly to the concerning div tag.
Something like:
var foundTemplate = _.template($('#item-template').html())
$('#div_example').html(foundTemplate); //
If anyone has a better approach, please let me know.
Sure.
client.js
Meteor.Router.add({
'/home/tools': function() {
Session.set("homeTemplate", "tools");
return 'home';
},
'/home/admin': function() {
Session.set("homeTemplate", "admin");
return 'home';
}
});
home.js
Template.home.homeTemplateTools = function() {
return Session.equal("homeTemplate", "tools");
};
Template.home.homeTemplateAdmin = function() {
return Session.equal("homeTemplate", "admin");
};
home.html
<template name="home">
{{#if isAdmin}}
<h1>student</h1>
{{/if}}
<div id="inner_home">
{{#if homeTemplateTools}}
{{> homeTools}}
{{/if}}
{{#if homeTemplateAdmin}}
{{> homeAdmin}}
{{/if}}
</div>
</template>

Resources