Jade outputting raw HTML inside <pre> tags - html

I am new to using jade and have this simple script:
extends layout
block page
- var menu = 'events'
block content
div event
each item in events
| Event name: #{item.name} Venue: #{item.venue} Drink Price Score: #{item.drink_prices}
Which I expect to output as:
Event name: example Venue: The ex. Drink Price Score: 7
With some header and footer content above and below.
However the following is output:
When I check the Chrome Inspector the code is put as a string between 'pre' tags.
Why is this happening and how do I get this to render normally? Thanks!
EDIT SOLUTION
The error was occuring in my controller code event.js
exports.list = function(req, res, next) {
req.models.Event.list(function(error, events) {
if (error) return next(error);
// res.send({events:events}); <-- offending line
res.render('event', { events: events } );
});
};

If this is the output you want:
Event name: example Venue: The ex. Drink Price Score: 7
Then this is the code you need
each item in events
| Event name: #{item.name} Venue: #{item.venue} Drink Price Score: #{item.drink_prices}
You put h2 tags on each line, so of course it's going to spit out each line wrapped in <h2> tags. I'm not sure why you expected differently.
The jade language is just an abstraction over HTML and the Jade compiler spits out HTML to be rendered by the browser. Jade is not the browser and browsers don't understand Jade code. Jade isn't going to read the Jade code and present you with a pretty page. It's going to spit out HTML that the browser does understand. Jade is just there to help you write cleaner looking HTML, then the Jade compiler turns the Jade document into an HTML document that the browser knows how to render.

Related

How to render html tags as html tags instead of string if they are coming from an array in React Component?

For example, I have an array of 3 values in it. The values also have some html tags. When I try to map through that array and try to display each of my array item, the values are displayed as it is. I want the HTML tags in my array values to be executed as true html elements. Below is my App.js code of my sample react app:
const App = () => {
const [questions, setQuestions] = useState([
"<h1>Test 1</h1>",
"<h1>Test 2</h1>",
"<h1>Test 3</h1>",
]);
return (
<div>
{questions.map((question) => (
<div>{question}</div>
))}
</div>
);
};
export default App;
The above react component give me my output as following:
<h1>Test 1</h1>
<h1>Test 2</h1>
<h1>Test 3</h1>
However, I want my final output to be look like below in which the html h1 tags are applied on my array elements when displayed in the browser. I know if I write such sort of html tags in a vanilla javascript, the html page renders it correctly by automatically reading any html tags as true html tags but I dont know how to achieve it in React Component.
Test 1
Test 2
Test 3
You can use dangerouslySetInnerHTML(question) inside your map function instead of the <div>{question}</div> inside the render to get the desired behavior, but please be cautious while using it. It can lead to unwanted security risk (hence the name) like XSS.
More information: https://reactjs.org/docs/dom-elements.html

How to compile/add HTML inside md-tooltip

I am trying to add HTML inside an md-tooltip but haven't had any luck, even with ng-bind-html.
Without using ng-bind-html, the tooltip outputs:
Some html<br>
<strong>card</strong>.
With it, my HTML outputs as a string:
Some html<br><strong>card</strong>
In my controller, I use this custom filter to compile HTML used within an ng-repeat:
app.filter('unsafe', function($sce) { return $sce.trustAsHtml; });
This filter successfully works with other elements aside from tooltips.
The tooltip is written as:
<md-tooltip md-delay="1000" md-direction="bottom" class="tooltip-sort-display">
<span ng-bind-html="categoryItem.ToolTip | unsafe">
</md-tooltip>
Please note, when I don't use a json variable and instead add static text to the tooltip, HTML has no trouble rendering
<md-tooltip md-delay="1000" md-direction="bottom" class="tooltip-sort-display">
<strong>Tool</strong><br><em>tip</em>
</md-tooltip>
Any ideas on how I can make this work? I would put together an example, but my Angular skills aren't that advanced. I mainly do the front-end development off my colleagues' work.
In your case, your problem is that you are using HTML special chars. If not, your code will works fine. Anyways if you cannot avoid receive special chars, you can add the decode in your filter:
JSFIDDLE DEMO
.filter('unsafeSpecial', function($sce) {
return function(value) {
var txt = document.createElement("textarea");
txt.innerHTML = value;
return $sce.trustAsHtml(txt.value);
}
})
And the you can use like this way:
HTML
<md-tooltip>
<span ng-bind-html="msg | unsafeSpecial"></span>
</md-tooltip>
CONTROLLER
.controller('mainCtrl', function($scope) {
$scope.msg = 'Some html<br><strong>card</strong>';
})
For more info about decode html topic, check this question if you want: HTML Entity Decode

Read long text in Angular 2

I have a very long document - 40000 words - I would like to display in a styled manner, like html.
I need to display it with headers, paragraphs and bold styling.
I am building an Angular app. I tried loading the converted document as a local html, but it takes a very long time.
For instance, I tried this:
var html = this.http.get("../data.html").map(ref => {
console.log(html);
} );
Are there any other ways I can load this text? Maybe break it up into smaller chunks somehow?
Based on what you've provided with no other context:
You need to subscribe to the Observable otherwise, nothing will ever happen since Observable execution is lazy:
var html = this.http.get("../data.html")
.map(ref => {
console.log(html);
return ref;
})
.subscribe(ref => ...);
Also, you're using console.log(html) in your map, but html does not exist in the context of map so you would need to do something like:
var html = this.http.get("../data.html")
.map(ref => {
console.log(ref); // Does this log appear and what does it contain?
return ref;
})
.subscribe(ref => ...);
Finally, var html is an Observable not HTML so I'd probably rename this to something a bit more descriptive if you're passing it around and subscribing to the response:
const data$ = this.http.get("../data.html")
.map(ref => {
console.log(ref);
return ref;
});
// ... do other stuff
data$.subscribe(ref => ...);
Or if not passed chain it and subscribe which indicates the Observeable has completed:
this.http.get("../data.html")
.map(ref => {
console.log(ref);
return ref;
}).subscribe(ref => ...);
If this doesn't help answer the question it's because you haven't provided enough information, and I'd suggest answering:
In the second example what does console.log(ref) output?
Include more code that provides more context like do you use subscribe already and what does the data you're using look like?
Make an example in StackBlitz that replicates the issue. Just click Angular and you get a pre-made Angular application you can drop your code into and then people can hack directly on the issue. Takes tops 5 seconds to setup

Aurelia: sanity check template html?

I recently asked why self-closing elements do not work in Aurelia's templating system; and it was because self-closing elements are invalid html.
Yet, today I again made the same mistake (with widgets this time) and was left scratching my head why content was missing.
Question: Is there a away to sanitise Aurelia template html in a gulp task?
I've tried using:
gulp-htmlhint: couldn't get it to error on self-closed elements
gulp-htmllint: couldn't configure it; with default settings it blows up with errors.
gulp-html5-lint: doesn't look configurable and it hates aurelia's attributes.
We can solve the issue of finding and of reporting self-closing elements with parse5. It has a SAXParser class that should be quite robust (parse5 conforms to html5 standards). The parser raises an event, upon finding a start-tags, that contains a boolean as to whether the found tag self closes.
var parser = new SAXParser();
parser.on("startTag", (name, attrs, selfClosing)=>{
if(selfClosing){
//check if name is void, if not report error
}
});
parser.push(html);
To make use of this functionality I have set up a project that can be used in order to help sanitize html using the above approach. The developed lint tool is able to run a selection of Rules, collect any errors and return them as a Promise. This can then be reported to the user.
Vanilla Html/Templates
template-lint forms the base of the tool-set. It comprises of the Linter, and a couple of basic rules:
SelfClose - ensure non-void elements do not self-close
Parser - returns errors for unclosed or ill-matched elements, as captured during parsing
gulp-template-lint is the gulp wrapper for template-lint and can be used like so:
var gulp = require('gulp');
var linter = require('gulp-template-lint');
gulp.task('build-html', function () {
return gulp.src(['source/**/*.html'])
.pipe(linter())
.pipe(gulp.dest('output'));
});
Example
Given the following html:
<template>
<custom-element/>
<svg>
<rect/>
</svg>
<div>
<div>
</div>
</template>
produces:
Note: the self-closed <rect/> does not produce an error. svg elements contains xml and Rules can differentiate based on scope.
Aurelia Templates
I initially made aurelia-template-lint, but decided to split out the reusable (outside of aurelia) components into template-lint. While both are currently separate, I will have the aurelia-template-lint extend upon template-lint in due course. Currently has a few proof-of-concept rules:
SelfClose - ensure non-void elements do not self-close
Parser - returns errors for unclosed or ill-matched elements, as captured during parsing
Template - ensure root is a template element, and no more than one template element present
RouterView - don't allow router-view element to contain content elements
Require - ensure require elments have a 'from' attribute
there is a gulp wrapper that can be installed via:
npm install gulp-aurelia-template-lint
and used in a gulp build:
var linter = require('gulp-aurelia-template-lint');
gulp.task('lint-template-html', function () {
return gulp.src('**/*.html')
.pipe(linter())
.pipe(gulp.dest('output'));
});
this will use the default set of rules.
Example
a simple test with the following ill-formed aurelia template:
<link/>
<template bindable="items">
<require from="foo"/>
<require frm="foo"/>
<br/>
<div></div>
<router-view>
<div/>
</router-view>
</template>
<template>
</template>
outputs:
Improvements
there are lots of improvements needed; for instance there are a few ways to define vanilla templates without the <template> tag. There are also quite a few specific attributes introduced by Aurelia that could be sanitised.
Given no one has answered yet; I present the "Better than nothing (maybe)"™ solution.
var gulp = require('gulp');
var gutil = require('gulp-util');
var voidTags = [
'area', 'base', 'br', 'col', 'embed', 'hr',
'img', 'input', 'keygen', 'link', 'meta',
'param', 'source', 'track', 'wbr'];
var checkSelfClose = function () {
function sanitize(file, cb) {
var dirty = String(file.contents);
var matches = dirty.match(/(?:\<[\/\\\-\"\'!() a-z=.]+\/\>)/g);
var customTags = [];
if(matches && matches.length > 0)
{
matches.forEach((match)=>{
var tag = match.match(/[a-z\-]+/)[0];
if(voidTags.indexOf(tag) < 0)
customTags.push(tag);
});
};
if(customTags.length > 0)
gutil.log('WARNING', 'found ' + customTags.length + " non-void self-closed tags in",
file.path.substring(file.cwd.length, file.path.Length),
"tags:", customTags
);
cb(null, file);
}
return require('event-stream').map(sanitize);
}
gulp.task('build-html', function () {
return gulp.src('source/**/*.html')
.pipe(checkSelfClose())
.pipe(gulp.dest('output'));
});
tested with:
<template bindable="items">
<require from="./menu-bar.css" />
<custom-element/>
<custom-element click.delegate="subitem.execute()" repeat.for="item of items" />
<custom-element-moo></custom-element-moo>
<br>
<br/>
<div id="blahblah"/>
<button class="dropbtn"/>
</template>
gulp output:
[Update]
Leaving this here as it is a quick, dirty and dependency free way to check for self-closed tags; does answer the question and may be useful.

Backbone.js template: Render HTML from model?

I have an API that return HTML serialized in JSON accessed through a REST API. When I try to render the HTML from the API response, the HTML code is display as such:
<p>Hello this is a response!</p>, instead of as: Hello this is a response!
Is there any way to work around this?
Also, what are the potential security issues with doing this and actually render the HTML?
Best regards and help is much appreciated. :)
EDIT: Here are my models and my template. Sufficient to say, I'm new to Backbone.js, and this is mostly based on the Todos example.
Views:
app.DataView = Backbone.View.extend({
tagName: "li",
template: _.template($("#data-template").html()),
initialize: function() {
this.render();
},
render: function() {
this.$el.html(this.template(this.model.toJSON()));
return this;
}
});
app.AppView = Backbone.View.extend({
el: "#htmldataapp",
initialize: function() {
app.datamodels.on('reset', this.addAll, this);
app.datamodels.fetch();
this.render();
},
addOne: function(datamodel) {
var view = new app.DataView({model: datamodel});
$('#data-list').append(view.render().el);
},
addAll: function() {
this.$('#data-list').html('');
app.datamodels.each(this.addOne, this);
}
});
Template:
<script type="text/template" id="data-template">
<%= data %>
</script>
You state that your api sends you HTML already?
So could it be that the data you get back is like <p>Hello this is a response!</p>, thus including the HTML tags?
If you would have underscore render this string in a template, it's no surprise you actually get the HTML tags to display.
Look at the generated source of the page, is the string Hello this is a response! wrapped in double <p> elements?
I would suggest changing your API in such a way that it returns data only (i.e. the string without the HTML), and have your HTML rendering be done by the underscore template engine.
Hope it helps!
EDIT:
I think you were using the underscore template function to often, causing the data to be rendered as a string.
Please see this fiddle for a sample setup how I think you should setup your app