Vega-Lite Shortcode

I’m new to Hugo, and HTML, and trying to create a shortcode to embed Vega-Lite visualisations. I could find two other attempts, both with the same shortcode:

<div id='{{ .Get "id" }}'></div>
<script type="text/javascript">
  var spec = '{{ .Get "spec" }}';
  vegaEmbed('#{{ .Get "id" }}', spec).then(function(result) {
    // TOOD: do something?
  }).catch(console.error);
</script>

Given the identical spelling error, I suspect one copied from the other, and surprisingly there aren’t any other easily locatable examples of doing this. The problem is that neither of them work. The problem seems to be that the HTML is including the path to the spec file instead of its contents, e.g.:

<div id='imdb'></div>
<script type="text/javascript">
  var spec = '\/docs\/examples\/imdb-histogram.vg.json';
  vegaEmbed('#imdb', spec).then(function(result) {
    
  }).catch(console.error);
</script>

I tried using the information from some of the threads around including a file in the markdown, and came up with this:

{{$spec := .Get "spec"}}
<div id='{{ .Get "id" }}'></div>
<script type="text/javascript">
  var spec = {{ $spec  | readFile | safeHTML }}
  vegaEmbed('#{{ .Get "id" }}', spec).then(function(result) {
    // TODO: do something?
  }).catch(console.error);
</script>

but that does the same thing.

Some further research into vega-embed shows that the spec can be a URL, so perhaps it’s the escaping of the ‘/’ in the URL that’s causing a problem?

I feel like I’m flying blind here, and hoping someone can either spot the error or point me towards some examples that are similar so I can adapt them.

According to this, the code should work. I.e., spec is not the content of the JSON file but its location. So you have to make sure that this location is accessible by the webserver and all that.

Given that you do not really provide any information here (“neither of them work” is not really an information, it just says what you perceive), I can’t tell you more. You might want to check in your browser’s dev tools which path the HTML actually contains. And also read and digest the information in the link I posted.

“neither of them work” means that in both cases the vega-lite plot fails to render. I have tested these in a browser in a hand-constructed HTML file, where it does work.

I’ve think I’ve since narrowed the problem to the forward slashes being escaped. E.g., the URL for the schema:

var spec=/docs/examples/imdb-histogram.vg.json

is rendered as:

var spec = '\/docs\/examples\/imdb-histogram.vg.json';, whether it’s in the shortcode or embedded directly into the markdown file.

Searching for Hugo and slash escaping turns up some similar issues, but so far I’ve not been able to figure out where this escaping of the path is coming from.

What you consider to be an URL isn’t one: It is just a path to a file on your (probably) local disk. Please read the stuff I linked to before and try to understand the difference between what you pass in spec and what is required.

An URL always starts with a protocol, something like “http://”, “file:///” or “x-url…://”.

Escaping slashes shouldn’t be a problem in a JavaScript string: since a slash is not a special character, the backslash is simply ignored, I’d guess.

But all this has nothing to do with Hugo, it is basic HTML/JavaScript stuff.

You need to make sure /docs/examples/imdb-histogram.vg.json available in public dir after you build your site.

/docs/examples/imdb-histogram.vg.json

move it into static.

static/docs/examples/imdb-histogram.vg.json

try with safeJS

{{$spec := .Get "spec"}}
<div id='{{ .Get "id" }}'></div>
<script type="text/javascript">
++  var spec = {{ $spec  | safeJS }}
  vegaEmbed('#{{ .Get "id" }}', spec).then(function(result) {
    // TODO: do something?
  }).catch(console.error);
</script>
1 Like

Thanks all. I found the problem. A small, but significant error in the spec file. For the record:

  • http is not required. Javascript is smart enough to find the file from the local host
  • static isn’t required either, the spec file can be anywhere
  • The backslash-ified path’s are not a problem either, which is good because safeJS didn’t change them.

FTR: JavaScript has nothing to do with that. Hugo is doing the file finding and reading here. But you’re right, I misread your original posts, there’s no URL involved if you just read in the JSON file in Hugo and write its content to the HTML file.