How can I render inline JavaScript with Jade / Pug? - node.js

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

Related

WebdriverIO | how to show html content of wdio-timeline-reporter or wdio-html-reporter generated file with css in the email body sent by nodemailer

I am trying to send the html content of the file (report.html in the pic below) and this file opens up in browser perfectly as the reference of css works fine when opening it from the folder. But when I am trying to send this file as html body using nodemailer it just loses all its styling and in email I am just receiving a plain text email just like below.
Can someone tell me how to tell nodemailer that all the css are present of this file is present in the html-reports folder and it should appear in the email body same as it opens up in the browser.
If anyone using WDIO and sharing any such information over email then please share this info with me.
I am using latest version of the WDIO btw viz. V7.7 (cucumber framework)
Basically I want to achieve below use case -
After running the test html report comes of all the cucumber scenario pass/fail/skipped along with error trace
I want to share this info in email body and not as attachment and my email body should be properly styled
Thanks much in advance !
To achieve the results that you mentioned you have to use internal CSS, this is placed in the head section of your report.html, within a style element.
So where you have the link to your external CSS you want to replace that with the actual CSS that is in the report-styles.css and place it in a style element.
report-styles.css:
h1 {
color: blue;
}
p {
color: red;
}
report.html before:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="report-styles.css">
</head>
<body>
<div>Your report</div>
</body>
</html>
Replace the CSS link with the actual CSS in the file
report.html after:
<!DOCTYPE html>
<html>
<head>
<style>
h1 {
color: blue;
}
p {
color: red;
}
</style>
</head>
<body>
<div>Your report</div>
</body>
</html>
Then you can add the report.html to your email and all the styles will be there without having to reference that external file.
This will require some additional coding on your end after your report is completed and before you send your email.
You can use something like gulp to do the replacement for you or write your own code for the replacement.
gulp.js example:
var gulp = require('gulp');
var replace = require('gulp-replace');
var fs = require('fs');
function getCSSFilename(linkTag) {
var hrefValue = /href\=\"([A-Za-z0-9/._]*)\"/g;
var cssFilename = linkTag.match(hrefValue);
cssFilename = cssFilename[0].replace("href=\"", "").replace("\"", "");
return cssFilename;
}
gulp.task('inject-styles', function () {
return gulp.src("./report/report.html")
.pipe(replace(/<link rel="stylesheet" href="[^"]*"*>/g, function(linkTag) {
var style = fs.readFileSync(`.${getCSSFilename(linkTag)}`, 'utf8');
return '<style>\n' + style + '\t</style>';
}))
.pipe(gulp.dest('./report'));
});
Hope this is helpful enough to let you know how you achieve what you described.

Not able to use asciimath using AsciidoctorJ

I am trying to convert a asciidoc file containing math expression to html using AsciidoctorJ, but have been unsuccessful so far.
This is the math.asciidoc that i am trying to convert.
= My Diabolical Mathmatical Opus
Jamie Moriarty
sample1
asciimath:[sqrt(4) = 2]
stem:[sqrt(4) = 2]
I am using the below configuration in Asciidoc
Attributes attributes = AttributesBuilder.attributes()
.math("asciimath")
.get();
Options options = OptionsBuilder.options()
.attributes(attributes)
.docType("article")
.safe(SafeMode.SERVER)
.backend("html5")
.get();
asciidoctor.convert(asciiDoc, options);
The output always shows something like this:
sample1
\$sqrt(4) = 2\$
\$sqrt(4) = 2\$
In the above generated HTML output, how do we render the mathematical equations?
Asciidoctor support asciimath and latexmath syntax and the output produced by asciimath can be rendered on browser using http://asciimath.org js library (other asciimath libraries can also be used).
Asciidoctorj uses \$ as the delimiter for asciimath markup, so we need to configure MathJax using the following configuration:
<html>
<head>
<script type="text/x-mathjax-config">
MathJax.Hub.Config({
asciimath2jax: {
delimiters: [['\\$','\\$'], ['`','`']]
}
});
</script>
<script type="text/javascript" async src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-MML-AM_CHTML">
</script>
...
</head>
//rest of html
</html>
After we include the above code snippet in <head> section of html, asciimath rendering shall work fine.
We can refer to this section of Asciidoctor documents for activating support of asciimath inside asciidocs: https://asciidoctor.org/docs/user-manual/#activating-stem-support

Anki and AnkiDroid: Importing JSON from collection.media with javascript

I want to import files from collection.media that are not sound, image, or video. For example I'd like to import a JSON file.
I put the file _script.jquery-3.3.1.min.js and _data.json in my collection.media folder.
On Anki Desktop (Ubuntu), the following works:
<script src="_script.jquery-3.3.1.min.js"></script>
<script>
$.getJSON('_data.json', function(data) {
// succeeds on Anki Desktop, fails on AnkiDroid
});
</script>
(Note on Anki Desktop 2.0.47 I am using the JS Booster plugin).
On AnkiDroid, the situation is different. JQuery loads just fine in the script tag. However, $.getJSON fails to find the _data.json file.
I'd like to use _data.json on many cards/notes.
How can I import non-media, non-js files from collection.media in javascript, in a way that works both in Anki Desktop and AnkiDroid?
I have found some working answer for this.
To get character data in AnkiDroid card templates. (OFFLINE)
As we can access js and image file using this
<script src="some-js-file.js"></script>
<img src="some-image.png"></img>
To access json
I have tried same steps but getting CORS error so I used next steps.
<!-- It will give CORS error -->
<script src="我.json" type="application/json"></script>
With example,
To access 我.json file
Copy contents of 我.json into a javascript file 我.js, with any variable name,
var char_data = {"strokes":["M 350 571 Q 3....}
Add following tag to access that js file
<!-- Note : file type & name -->
<script src="我.js" type="text/javascript"></script>
Now also change code in _hanzi-writer.min.js
To change code, first beautify code using this https://beautifier.io, then make following change
a) Remove the link to load from internet
b) Change this 200 != r.status and replace/add this
JSON.parse(JSON.stringify(char_data))
( May be more good replacement can be done here )
....
....
// Note : char_data variable come from 我.js file
r.overrideMimeType && r.overrideMimeType("application/json"), r.open("GET", "", !0), r.onerror = function(t) {
....
....
4 === r.readyState && (200 != r.status ? i(JSON.parse(JSON.stringify(char_data))) : 0 !== r.status && n && n(r))
....
....
So final script will be like this
Front side of card
{{Pinyin}}
<div id="character-target-div"></div>
<script src= "我.js" type="text/javascript"></script>
<script>
var data = JSON.stringify(char_data);
console.log(data);
</script>
<script src="_hanzi-writer.min.js"></script>
<script>
var writer = HanziWriter.create('character-target-div', '我', {
width: 150,
height: 150,
showCharacter: false,
padding: 5
});
writer.quiz();
</script>
Above all the steps are for single file 我.js
To access other character repeat the same.
For similar issues view my code
https://github.com/infinyte7/Anki-xiehanzi
https://github.com/infinyte7/hanzi-writer-data-in-javascript
I assume this is related to how AnkiDroid handles collections.media files. If so, this might be a bug. A really hackish workaround could be to rename the file to .svg so that AnkiDroid treats it as an image and lets it through.

Conditionals within script. in jade

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")
| }

Cannot set up admins for facebook comments

We're having a weird issue on our website with facebook comments. It looks like the facebook scraper is incorrectly parsing (at least one of) our web pages so that it isn't picking up on admins to moderate the comments.
If you go to this link:
http://www.beliefnet.com/Espanol/10-Atletas-olimpicos-mas-inspiradores.aspx
and view source, you'll see that we have the appropriate tags in the head, including one for fb:admins. If I am logged into facebook on that account, I get no moderator options.
Running the page through facebook object debugger, I get an error that we have meta tags in the body. Specifically, this error:
Meta Tags In Body: You have tags ouside of your . This is either because
your was malformed and they fell lower in the parse tree, or you accidentally
put your Open Graph tags in the wrong place. Either way you need to fix it
before the tags are usable.
Looking at the scraped URL at the bottom of that page, I see what looks to be that facebook has 'reorganized' our html, and placed the meta tags from the head into the body.
Does anyone have any idea what is causing this? I thought that maybe we had some malformed html somewhere in the page that was throwing everything off, but I went through the html for that page and it looks good. Is there something else that i'm missing here?
Running your URL through validator.w3.org shows a few warning signs:
Line 77, Column 14: document type does not allow element "noscript" here; assuming missing "object" start-tag
Line 154, Column 699: document type does not allow element "meta" here
I was able to narrow down the (potential) issue to these lines in your page:
document.write('<a href="' + OAS.config.url + 'click_nx.ads/' + OAS.config.sitepage + '/1' + OAS.config.rns + '#' + OAS.config.listpos + '!' + pos + '?' + OAS.config.query + '" target=' + OAS.config.target + '>');
document.write('<img src="' + OAS.config.url + 'adstream_nx.ads/' + OAS.config.sitepage + '/1' + OAS.config.rns + '#' + OAS.config.listpos + '!' + pos + '?' + OAS.config.query + '" border=\"0\" /></a>');
These document.write() lines are also failing the w3.org validator:
Line 53, Column 197: character "+" is not allowed in the value of attribute "target"
Moreover, I think it's bad to use document.write() for DOM insertion (and because it can lead to blocking of page rendering).
Can you change to using js objects and DOM manipulation?
After FB fetches your URL, it runs it through a DOM parser that is probably choking when it encounters those document.write() lines. The fact that those lines have an <a> element spanning two document.writes() is probably confusing the parser. And the parser probably thinks it has reached the <body> of the page, thus the 'Meta tags in body' error.
As a quick test, try putting the fb:admins meta tag above those document.write() lines. Though, I wouldn't be surprised if the parser still chokes, but it's worth a try.
To test your page's html source, I used the simple script provided in a comment at the end of this php.net page:
http://www.php.net/manual/en/class.domxpath.php
It produced errors:
Unexpected end tag : a in /home/dlee/tmp/tmp.html, line: 54
Unexpected end tag : head in /home/dlee/tmp/tmp.html, line: 183
htmlParseStartTag: misplaced <body> tag in /home/dlee/tmp/tmp.html, line: 184
Where tmp.html was the html of your page saved to a file.
Line 54 is the previously mentioned document.write() line.
Let me know if any of the above results in progress, and I will edit this answer accordingly.
so the problem ultimately was that there was a <noscript>...</noscript> nested in the head, that was trying to include a tracking pixel for browsers without javascript enabled, as part of an ad service we use.
the issue should've been obvious looking at the output facebook gave us for 'how they see your page'. the body begins immediately after the script, but immediately before where the tag starts. apparently the facebook parser freaks out when it sees an element in the head that should be in the body, so it immediately starts the body there.
... facebook output ...
console.log(OAS);
})();
</script><!-- End OAS Setup --><!-- Begin comScore Tag --><script>
var _comscore = _comscore || [];
_comscore.push({ c1: "2", c2: "8428430" });
(function() {
var s = document.createElement("script"), el = document.getElementsByTagName("script")[0]; s.async = true;
s.src = (document.location.protocol == "https:" ? "https://sb" : "http://b") + ".scorecardresearch.com/beacon.js";
el.parentNode.insertBefore(s, el);
})();
</script>
</head>
<body>
<noscript>
</noscript>
<!-- End comScore Tag -->
... our html ...
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<asp:PlaceHolder id="OASHeader" runat="server" />
<!-- Begin comScore Tag -->
<script type="text/javascript">
var _comscore = _comscore || [];
_comscore.push({ c1: "2", c2: "8428430" });
(function() {
var s = document.createElement("script"), el = document.getElementsByTagName("script")[0]; s.async = true;
s.src = (document.location.protocol == "https:" ? "https://sb" : "http://b") + ".scorecardresearch.com/beacon.js";
el.parentNode.insertBefore(s, el);
})();
</script>
<!-- End comScore Tag -->
<noscript>
<img src="http://b.scorecardresearch.com/p?c1=2&c2=8428430&cv=2.0&cj=1" alt="" />
</noscript>
<script type="text/javascript">
....
<body>
....
so in the future, invalid head elements could definitely be causing this problem.

Resources