Javascript in blogpost, but not on all sites at the same time?

Hi,
Im trying to find a way to include a javascript inside a single blogpost. i would really like to use charts.js inside one blogpost but not that this apply’s on all my sites.
Is something like this possible?
is there a option for hugo to 1:1 parse something like:

{{Hugo please ignore and parse 1:1}}

javascript function (blahblahblah)
{{Hugo please start and use the parser again}}

Thanks very much for help

1 Like

What prevents you from just inserting a script-tag into your content file á la

<script type="text/javascript" src="link/to/chart.js"></script>

Hi digitalcraftsman,
You are right ;=) i did think you can only write markdown … didnt even try it.

now i need to figure out a way to get this working with canvas…

<div id="myChart">
<canvas id="myChart" width="400" height="400"></canvas>
</div>
<script type="text/javascript">
    function loadCanvas(id) {
        var canvas = document.createElement('canvas');
        div = document.getElementById(id); 
        canvas.id     = "myChart";
        canvas.width  = 402;
        canvas.height = 402;
        canvas.style.zIndex   = 8;
        canvas.style.position = "absolute";
        canvas.style.border   = "1px solid";
        div.appendChild(canvas)
    }
</script>

<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/1.0.2/Chart.js"></script>

<script>
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
    type: 'bar',
    data: {
        labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
        datasets: [{
            label: '# of Votes',
            data: [12, 19, 3, 5, 2, 3],
            backgroundColor: [
                'rgba(255, 99, 132, 0.2)',
                'rgba(54, 162, 235, 0.2)',
                'rgba(255, 206, 86, 0.2)',
                'rgba(75, 192, 192, 0.2)',
                'rgba(153, 102, 255, 0.2)',
                'rgba(255, 159, 64, 0.2)'
            ],
            borderColor: [
                'rgba(255,99,132,1)',
                'rgba(54, 162, 235, 1)',
                'rgba(255, 206, 86, 1)',
                'rgba(75, 192, 192, 1)',
                'rgba(153, 102, 255, 1)',
                'rgba(255, 159, 64, 1)'
            ],
            borderWidth: 1
        }]
    },
    options: {
        scales: {
            yAxes: [{
                ticks: {
                    beginAtZero:true
                }
            }]
        }
    }
});
</script>

<script type="text/javascript">
    loadCanvas("myChart");
</script>

I see the 400x400 image… but its white and empty…
So this is then more my problem and nothing for hugo.

Btw, the Markdown format allows you to insert any kind of HTML. It was mainly designed to be finally converted into HTML.

lol, same for me… definitely good to know!

another idea could be using shortcodes maybe

i just found another problem…

if the document that is called test.md passed to hugo and it contains javascript, the javascript always gets the wrong encoding for the double quotes.

ENCODING     | HTML | JAVASCRIPT 
UTF8         |   1  |         0         
UTF8-nobom   |   1  |         0         
Win 1252     |   0  |         0         
UTF16LE      |   0  |         0

So im still not able to use javascript because of the encoding. All " get replaced with the encoding used.
Temporary solution would be that i write a shell script to replace those ““” with a ".

I dont see any other way currently without having such a tag , (what i was asking initialy)

My approach is to use the content metadata to instruct my footer template to load extra js files. The JS is not part of the content (that’s a presentation concern), so don’t try to marry them in your markdown if you can avoid it.

Example content metadata:

+++
js = ["chart", "dropdown/latest.min"]
+++

At the bottom of the footer template, I have this:

{{- range .Params.js }}
<script src="/js/{{ . }}.js"></script>
{{- end }}
3 Likes

@moorereason’s solution is awesome if you find yourself using a lot of page-level scripts, but to further the point made w/r/t separation of concerns if you’re talking about more than one page using a script not necessarily used by the entire site, you can also use block in your layouts…

So, baseof.html

<!--All the other stuff in you base template-->
<!-- Somewhere around your footer -->
...
<script src="/js/scrip-that-runs-everywhere"></script>
{{block "addscripts" . }}
{{end}}

Then in your layout for that page (or series of pages…):

...
{{define "addscripts"}}
<script src="/scripts/script-only-for-this-type-of-layout.js"></script>
{{end}}

This keeps you from having to muddy metadata (arguably part of content as well) with your presentation and behavior. That said, it’s less on-the-fly flexible as the solution put together by @moorereason. You could also use a series of partials and then pipe the appropriate partial into the newly defined block or just add the partial to the layout.

That said, if you are really nutso about performance and reducing HTTP requests, using a build tool to uglify and minify, and fiddling with cache-control, you may want to add the additional js to a single final concatenated js, use a try and catch or check for a value, etc…but this is all you in terms of the type of content you’re serving up and the anticipated behavior of your users.

From what i see this comes from the golang http/template pkg , a character like " gets escaped. Is there a way (with changing hugo’s source, to change the behavior to not escape javascript double quotes?

problem i have is all solutions here mentioned are ok if you need the javascript many times on different pages. What if you have 2-3 different javascripts per blogpost (content is dynamically generated) in this way the only solution is to prevent hugo from escaping those chars.

i am looking for a option (without having to go away from standard hugo source). something like

{{ do-not-escape }}
my javascript code that should not get escaped…
{{ end-do-not-escape }}

but i think it is not possible for now without changing hugo’s source because of the use from html/template. Am i wrong with this?

another way (because the content is automatically generated) is to create for each post in parallel a partial site (which is a huge waste… but if thats the only way… ok)

Again, my recommendation is to keep your Javascript out of your markdown content.

But are you saying that you are trying to embed a <script> section in your markdown, and it’s being escaped by Hugo? If so, make sure you set the type for the script section.

@moorereason

Input:
https://github.com/snapo/source.jans.li/blob/master/content/post/test.md

Output:
https://github.com/snapo/www.jans.li/blob/gh-pages/2007/01/28/test/index.html

In the output you can see that the problem starts on line 170 where double quotes get escaped with “ and ”

I did not yet found a way to circumvent this. I have a script the automatically generates XXXX.md files where i wanna have this chart inside with different data and other charts. If i dont get it working i probably have to switch and do it with CSS instead of javascript.

Most probably its just my error :slightly_smiling:

Repeating myself: try setting the type attribute on the script tag:

<script type="text/javascript">

@moorereason , thanks and sorry if you missunderstood me… i did try it already with and without, it dosent make a difference. the variable values get escaped. I personally give up now… because it is a little frustrating to look for reasons why escaping is happening and why not. Somehow i dont understand the whole thing:

Works:
<script src="myscript.js"></script>

Does not work:
<script type="text/javascript">
var TEST = ["variable1", "variable2", "variable3"];
</script>

my guess is because of the [ ]

Anyway… thanks for help, will do in in SVG or CSS (those i tested and work… javascript was just more flexible)

EDIT: found the reason, the script needs to be in one line, hugo does not check if the <script> has multiple lines… after the script tag it starts again to do/convert it to markup where the escaping would be correct. Only <script> is checked, but not where </script> is…

EDIT2: Can someone explain me what i probably need to change on hugo’s source to get this working without having everything on one line?

2 Likes

I encountered an escaped quotes problem that @snapo mentions above. As a workaround I added an eval() in a shortcode.

For example, I used the following shortcode in my markdown file.

{{< javascript `
var name = "John"
window.alert("Hello " + name);
` >}}

Then in layouts/shortcodes/javascript.html I put:

<script>
eval({{ .Get 0 }})
</script>

WARNING: Don’t do any of this if you accept markdown content from people you don’t necessarily trust. By design, these techniques open up the possibility for unsafe HTML and JavaScript in your markdown files.

I also found @moorereason 's approach helpful for larger JavaScript or CSS files. The only additional piece of information that I would add, is that it must go in baseof.html not in one of the partials. When I tried putting the code below into layouts/partials/site-footer.html I got inconsistent results. Sometimes when I ran hugo or hugo server it would appear in the final webpage HTML and sometimes it wouldn’t. I suspect there are some race condition bugs in Hugo.

{{ range .Params.js }}
<script src="{{ . }}.js"></script>
{{ end }}