Conditionals within script. in jade - node.js

In Jade, is it possible to create a conditional if statement in a dynamicscript section?
For example:
doctype html
html
head
script.
-if( locals.display_JS )
console.log("Display_JS is TRUE")
-else
console.log("Display_JS is FALSE")
(locals.display_JS is a parameter pass to Jade in res.render.)
If display_JS is true, the desired output should look like:
<script ...>console.log("Display_JS is TRUE")</script>
However the output is:
<script>
-if( locals.display_JS )
console.log("Display_JS is TRUE")
-else
console.log("Display_JS is FALSE")
</script>
It could be that I am thinking wrong. My objective is to render different javascript functions based on parameters sent to res.render.

It can be done the other way, use the . whenever you want to nest javascript code.
doctype html
html
head
script
if( locals.display_JS )
.
/** Some JS code **/
console.log("Display_JS is TRUE")
else
.
console.log("Display_JS is FALSE")

Jade will not mess with anything within a script block. If you really need to use jade logic inside a script block you can get a little tricky and do something like this:
Router Code:
router.get('/', function(req, res){
res.render('index', {run_this:true});
});
Jade Code:
div
| <script type='text/javascript'>
if(run_this)
| console.log("Ran this!");
else
| console.log("Didn't run this");
| </script>
Another approach to running logic based on jade variables within a script tag is to do something like this:
script.
if(!{run_this}){
console.log("Ran This!");
}

When you use script. everything that comes after will be interpreted as plain text by jade. If you need to mix markup and plain text you can use |. For example:
script
| function bar(){
if(true)
| console.log("Ran this")
else
| console.log("Don't run this")
| }

Related

Node JS: given a html string, how can I get the content inside of all <script> tags, manipulate and replace it?

Overview:
I am working on a project that has dozens of .Liquid (Shopify) snippets with <script> tags inside of them containing JS code.
They're similar to HTML, they look something like this:
{% assign variable = 'test' %}
<p>hey {{variable}}</p>
<script>console.log("hey")</script>
{% schema %}
{
...json stuff
}
{% endschema %}
Issue:
Basically what I wanna do is get the content inside <script>, manipulate it and replace with the new manipulated one.
I managed to do this using cheerio, but it ends up messing up the Liquid variables since it doesn't recognize them.
My previous code was looking something like this:
let html = cheerio.load(code, { _useHtmlParser2: true });
const { data: js } = html("script").get()[0].children[0];
html("script").get()[0].children[0].data = await minifyJS(js);
const result = html.html();
Expected Behavior:
I need to:
Find all script tags in a HTML string;
Get the code inside of the <script> tag;
Manipulate this code (minify, essentially);
Replace it with the now minified code.
I am trying to avoid using regex, but I can't foresee any other solutions.
Any suggestion is greatly appreciated.
Thank you!
To get the content inside tags you can use Regular Expressions
<script(.|\n)*?<\/script>
This is just the regex
let str = <Whatever string or data you want to extract script tags>;
let result = let result = str.match(/<script(.|\n)*?<\/script>
/g);
console.log(result);
in result you will get the content inside the script tag

Writing nodejs scripts inside nextjs HTML

I am programing my new website in a structure with nodejs, nextjs and expressjs. The problem is tho that I want to write a if statement inside of the HTML part which in that case it will write the if statement as normal html on the website:
const Admin = () => (
<AdminLayout>
<style global jsx>
{
`body {
background: #eff0f3;
}`
}
</style>
<div className="jumbotron" style={jumbotron}>
if (1=1) {
<h3>Please select a tool first.</h3>
} else {
<h3>Something is wrong :/ .</h3>
}
</div>
</AdminLayout>
)
export default Admin
And the out put is just:
if (1=1)
Please select a tool first.
else
Something is wrong :/ .
as HTML on the website. How would I do this but having the script actually being a script?
Next.js uses React that allows you to write something called jsx, which is what you're calling the "HTML part". You can write JavaScript expressions in jsx, but they need to be wrapper in {} brackets. Otherwise any JS code will actually just be interpreted as a text string in the rendered HTML. Check out the React Docs for Embedding Expressions in JSX.
There's lots of ways to do conditional rendering in React.
Here's one way to rewrite your code using {} to embed an expression and the ternary operator:
const Admin = () => (
<AdminLayout>
<style global jsx>{`
body {
background: #eff0f3;
}
`}</style>
<div className="jumbotron" style={jumbotron}>
{1 == 1 ? (
<h3>Please select a tool first.</h3>
) : (
<h3>Something is wrong :/ .</h3>
)}
</div>
</AdminLayout>
)
export default Admin

handlebars - add content to head of view from partial

I am using express-handlebars in my project and have the following problem:
Question
I want to be able to add <script> oder such tags to my overall views head from a partial that is called inside the view.
Example:
The view
{{#layout/master}}
{{#*inline "head-block"}}
<script src="some/source/of/script">
{{/inline}}
...
{{>myPartial}}
{{/layout/master}}
The view is extending another partial (layouts/master) that I use as a layout. It adds its content to that ones head block through the inline partial notation, which works fine
the Partial "myPartial
<script src="another/script/src/bla"></script>
<h1> HELLO </h1>
Now I would like that particular script tag in there to be added to my views head-block. I tried going via #root notation but can only reference context there. Not change anything.
I know I could use jquery or similar to just add the content by referencing the documents head and such. But I wanted to know if this is possible at all via Handlebars.
I do doubt it is in any way. But if you have any ideas or suggestions, please do send them my way! Many thanks!!!
UPDATE
This wont work if you have more than one thing injected into your layout / view. Since this happens when the browser loads the page, it creates some kind of raceconditions where the helpers has to collect the things that have to be injected into the parent file. If its not quick enough, the DOMTree will be built before the helper resolves. So all in all, this solution is NOT what I hoped for. I will research more and try to find a better one...
Here is how I did it. Thanks to Marcel Wasilewski who commented on the post and pointed me to the right thing!
I used the handlebars-extend-block helper. I did not install the package, as it is not compatible with express-handlebars directly (Disclaimer: There is one package that says it is, but it only threw errors for me)
So I just used his helpers that he defines, copied them from the github (I am of course linking to his repo and crediting him!) like so:
var helpers = function() {
// ALL CREDIT FOR THIS CODE GOES TO:
// https://www.npmjs.com/package/handlebars-extend-block
// https://github.com/defunctzombie/handlebars-extend-block
var blocks = Object.create(null);
return {
extend: function (name,context) {
var block = blocks[name];
if (!block) {
block = blocks[name] = [];
}
block.push(context.fn(this));
},
block: function (name) {
var val = (blocks[name] || []).join('\n');
// clear the block
blocks[name] = [];
return val;
}
}
};
module.exports.helpers = helpers;
I then required them into my express handlebars instance like so:
let hbsInstance = exphbs.create({
extname: 'hbs',
helpers: require('../folder/toHelpers/helpersFile').helpers() ,
partialsDir: partialDirs
});
Went into my central layout/master file that`is extended by my view Partial and added this to its <head> section
{{{block 'layout-partial-hook'}}}
(The triple braces are required because the content is HTML. Else handlebars wont recognize that)
Then in the partial itself I added things like so:
{{#extend "layout-partial-hook"}}
<link rel="stylesheet" href="/css/index.css"/>
{{/extend}}
And that did the trick! Thanks!!!

Jade helper for FontAwesome

I want to write some helper for FontAwesome in jade template in Express.js, so I did in app.js:
app.locals.icon = function(icon){ return '<i class="fa fa-' + icon + '"></i>'; };
and called in template:
block content
h1= title
p Welcome to #{title}
= icon('users')
however it returns me escaped HTML code. What is a good practise for writing this kind of helpers ? How to return raw HTML ?
Try with != operator
!= icon('users')
Refrence from http://jade-lang.com/
Unescaped buffered code starts with != and outputs the result of evaluating the JavaScript expression in the template. This does not do any escaping, so is not safe for user input.

How can I render inline JavaScript with Jade / Pug?

I'm trying to get JavaScript to render on my page using Jade (http://jade-lang.com/)
My project is in NodeJS with Express, eveything is working correctly until I want to write some inline JavaScript in the head. Even taking the examples from the Jade docs I can't get it to work what am I missing?
Jade template
!!! 5
html(lang="en")
head
title "Test"
script(type='text/javascript')
if (10 == 10) {
alert("working")
}
body
Resulting rendered HTML in browser
<!DOCTYPE html>
<html lang="en">
<head>
<title>"Test"</title>
<script type="text/javascript">
<if>(10 == 10) {<alert working></alert></if>}
</script>
</head>
<body>
</body>
</html>
Somethings definitely a miss here any ideas?
simply use a 'script' tag with a dot after.
script.
var users = !{JSON.stringify(users).replace(/<\//g, "<\\/")}
https://github.com/pugjs/pug/blob/master/packages/pug/examples/dynamicscript.pug
The :javascript filter was removed in version 7.0
The docs says you should use a script tag now, followed by a . char and no preceding space.
Example:
script.
if (usingJade)
console.log('you are awesome')
else
console.log('use jade')
will be compiled to
<script>
if (usingJade)
console.log('you are awesome')
else
console.log('use jade')
</script>
Use script tag with the type specified, simply include it before the dot:
script(type="text/javascript").
if (10 == 10) {
alert("working");
}
This will compile to:
<script type="text/javascript">
if (10 == 10) {
alert("working");
}
</script>
No use script tag only.
Solution with |:
script
| if (10 == 10) {
| alert("working")
| }
Or with a .:
script.
if (10 == 10) {
alert("working")
}
THIRD VERSION OF MY ANSWER:
Here's a multiple line example of inline Jade Javascript. I don't think you can write it without using a -. This is a flash message example that I use in a partial. Hope this helps!
-if(typeof(info) !== 'undefined')
-if (info)
- if(info.length){
ul
-info.forEach(function(info){
li= info
-})
-}
Is the code you're trying to get to compile the code in your question?
If so, you don't need two things: first, you don't need to declare that it's Javascript/a script, you can just started coding after typing -; second, after you type -if you don't need to type the { or } either. That's what makes Jade pretty sweet.
--------------ORIGINAL ANSWER BELOW ---------------
Try prepending if with -:
-if(10 == 10)
//do whatever you want here as long as it's indented two spaces from
the `-` above
There are also tons of Jade examples at:
https://github.com/visionmedia/jade/blob/master/examples/
script(nonce="some-nonce").
console.log("test");
//- Workaround
<script nonce="some-nonce">console.log("test");</script>
For multi-line content jade normally uses a "|", however:
Tags that accept only text such as
script, style, and textarea do not
need the leading | character
This said, i cannot reproduce the problem you are having. When i paste that code in a jade template, it produces the right output and prompts me with an alert on page-load.
Use the :javascript filter. This will generate a script tag and escape the script contents as CDATA:
!!! 5
html(lang="en")
head
title "Test"
:javascript
if (10 == 10) {
alert("working")
}
body

Resources