Problem with abcjs shortcode

abcjs is a javascript library for rendering music notation. It transforms something lilke this:

X: 24
T:Clouds 
C:Example
S:Copyright 2019
M:6/8
L:1/8
Q:3/8=116
R:Creepy Jig
K:Em
|:"Em"EEE E2G|"C7"_B2A A2F|"Em"EEE E2G|\
"C7"_B2A "B7"=B3|"Am"EEA E2G|
"D7"_B2A G2F|"Em"GFE "D (Bm7)"F2D|\
1"Em"E3-E3:|2"Em"E3-E2B|:"Em"e2e gfe|

Into standard music notation.
sheet

For this I am creating a shortcode templates/shortcodes/abcjs.html:

{{- $id := .Get 0 -}}

<div id="{{ $id }}"></div>
<script>
 var {{$id| safeJS}}= {{- .Inner|safeHTML -}};
 window.onload=function() {
     ABCJS.renderAbc("{{$id}}", {{$id|safeJS}});
 }
</script>

to be used like:

{{< abcjs mytune >}}
X: 24
T:Clouds 
C:Example
S:Copyright 2019
M:6/8
L:1/8
Q:3/8=116
R:Creepy Jig
K:Em
|:"Em"EEE E2G|"C7"_B2A A2F|"Em"EEE E2G|\
"C7"_B2A "B7"=B3|"Am"EEA E2G|
"D7"_B2A G2F|"Em"GFE "D (Bm7)"F2D|\
1"Em"E3-E3:|2"Em"E3-E2B|:"Em"e2e gfe|
{{< abcjs />}}

But Hugo adds a lot of escaping which makes it fails to render the expected music sheet, producing this:

<div id="mytune"></div>
<script>
 var mytune="\nX: 24\nT:Clouds \nC:Example\nS:Copyright 2019\nM:6/8\nL:1/8\nQ:3/8=116\nR:Creepy Jig\nK:Em\n|:\"Em\"EEE E2G|\"C7\"_B2A A2F|\"Em\"EEE E2G|\\\n\"C7\"_B2A \"B7\"=B3|\"Am\"EEA E2G|\n\"D7\"_B2A G2F|\"Em\"GFE \"D (Bm7)\"F2D|\\\n1\"Em\"E3-E3:|2\"Em\"E3-E2B|:\"Em\"e2e gfe|\n\u003cdiv id=\"\"\u003e\u003c/div\u003e\n\u003cscript\u003e\n var =\"\";\n window.onload=function() {\n     ABCJS.renderAbc(\"\", );\n }\n\u003c/script\u003e\n\n\n";
 window.onload=function() {
     ABCJS.renderAbc("mytune", mytune);
 }
</script>

How to avoid such escaping?

Checkout your new best friends: the safe functions:

1 Like

Not my friends in this case, I am already using safeHTML in the above example, also tried safeJS without luck.

How did you use safeJS? Can you post a sample code? In my opinion this is a case for safeJS.

In my other opinion (one that over-optimizes things) I would rework the whole construct so that the parts inside of the script tag live in it’s own template, then adding that template with safeJS, not parts of the code. I had a case recently where you could return something from a partial and then use that returned variable as output.

How do you call your shortcode? To me it looks like you give the notation via attribute on the shortcode. Better would be to put the notation between opening and closing shortcode and then using .Inner | safeJS on that?

Made a repo with an example of it: https://github.com/marcanuy/hugo-abcjs-shortcode
Output can be seen at: https://marcanuy.github.io/hugo-abcjs-shortcode/

Basically, using it in a post like:

{{< abcjs mytune >}}
X: 24
T:Clouds 
C:Example
S:Copyright 2019
M:6/8
L:1/8
Q:3/8=116
R:Creepy Jig
K:Em
|:"Em"EEE E2G|"C7"_B2A A2F|"Em"EEE E2G|\
"C7"_B2A "B7"=B3|"Am"EEA E2G|
"D7"_B2A G2F|"Em"GFE "D (Bm7)"F2D|\
1"Em"E3-E3:|2"Em"E3-E2B|:"Em"e2e gfe|
{{< abcjs />}}

With shortcode:

{{- $id := .Get 0 -}}

<div id="{{ $id }}"></div>
<script>
 var {{$id| safeJS}}= "{{- .Inner|safeJS -}}";
 window.onload=function() {
     ABCJS.renderAbc("{{$id}}", {{$id|safeJS}});
 }
</script>

’
It generates:

<div id="mytune"></div>
<script>
 var mytune= "\nX: 24\nT:Clouds \nC:Example\nS:Copyright 2019\nM:6\/8\nL:1\/8\nQ:3\/8=116\nR:Creepy Jig\nK:Em\n|:\x22Em\x22EEE E2G|\x22C7\x22_B2A A2F|\x22Em\x22EEE E2G|\\\n\x22C7\x22_B2A \x22B7\x22=B3|\x22Am\x22EEA E2G|\n\x22D7\x22_B2A G2F|\x22Em\x22GFE \x22D (Bm7)\x22F2D|\\\n1\x22Em\x22E3-E3:|2\x22Em\x22E3-E2B|:\x22Em\x22e2e gfe|\n\x3cdiv id=\x22\x22\x3e\x3c\/div\x3e\n\x3cscript\x3e\n var = \x22\x22;\n window.onload=function() {\n     ABCJS.renderAbc(\x22\x22, );\n }\n\x3c\/script\x3e\n\n\n\n\x3csmall\x3e*based in abcjs\x27s homepage example \x3c\/small\x3e\n\nBug? No content is shown after rendering shortcode\n";
 window.onload=function() {
     ABCJS.renderAbc("mytune", mytune);
 }
</script>

So it still doesn’t work.

Regarding over-optimization, which I agree it should be done here (I wanted to see it working a basic version before starting to optimize things :slight_smile: ) , I do not completely understand how to design it with a template, can you please post a quick example of it?

Maybe you can answer this faster than me reading the docs: is abcjs expecting linebreaks for these parameters? I think that is where the problem lies. JS doesn’t like that inside of a variable

Also, I see backslashes in the last 4 lines which points to ignored line-changes.

It’s probably not something that should be included into the shortcode, but more like a page resource where you put your abcjs configuration into a text file, then add a shortcode like {{< abcjs id="bla" config="fasel" >}} and then fasel.txt has your config, bla is the ID (which could probably being created without adding it manually.

JS does not like line breaks in variables. so var mytune will break in “realworld javascript” anyway.

Also please point me to a docu/sample where the multi-line-config is used in a variable. It will take a while to solve this, but we will get it in time I think. The problem is not encoding but “how do we get the configuration into a variable”.