Solution 1 :

It’s doable, as long as you can include javascript files for D3 itself and your chart definition:

Consider a slightly cut down version of this example:

/static/example.js

margin = ({top: 20, right: 0, bottom: 30, left: 40})

height = 500
width = 500
data = [
  {name: "E", value: 0.12702},
  {name: "T", value: 0.09056},
  {name: "A", value: 0.08167},
  {name: "O", value: 0.07507},
  {name: "I", value: 0.06966},
  {name: "N", value: 0.06749},
  {name: "S", value: 0.06327},
  {name: "H", value: 0.06094},
  {name: "R", value: 0.05987},
  {name: "D", value: 0.04253},
  {name: "L", value: 0.04025},
  {name: "C", value: 0.02782},
  {name: "U", value: 0.02758},
  {name: "M", value: 0.02406},
  {name: "W", value: 0.0236},
  {name: "F", value: 0.02288},
  {name: "G", value: 0.02015},
  {name: "Y", value: 0.01974},
  {name: "P", value: 0.01929},
  {name: "B", value: 0.01492}
]

yAxis = g => g
    .attr("transform", `translate(${margin.left},0)`)
    .call(d3.axisLeft(y))
    .call(g => g.select(".domain").remove())

xAxis = g => g
    .attr("transform", `translate(0,${height - margin.bottom})`)
    .call(d3.axisBottom(x).tickSizeOuter(0))

y = d3.scaleLinear()
    .domain([0, d3.max(data, d => d.value)]).nice()
    .range([height - margin.bottom, margin.top])

x = d3.scaleBand()
    .domain(data.map(d => d.name))
    .range([margin.left, width - margin.right])
    .padding(0.1)

function zoom(svg) {
  const extent = [[margin.left, margin.top], [width - margin.right, height - margin.top]];

  svg.call(d3.zoom()
      .scaleExtent([1, 8])
      .translateExtent(extent)
      .extent(extent)
      .on("zoom", zoomed));
  function zoomed() {
    x.range([margin.left, width - margin.right].map(d => d3.event.transform.applyX(d)));
    svg.selectAll(".bars rect").attr("x", d => x(d.name)).attr("width", x.bandwidth());
    svg.selectAll(".x-axis").call(xAxis);
  }
}

const svg = d3.select(".visualisation") 
      .append("svg")
      .attr("width", width)
      .attr("height", height)
      .call(zoom);

  svg.append("g")
      .attr("class", "bars")
      .attr("fill", "steelblue")
    .selectAll("rect")
    .data(data)
    .join("rect")
      .attr("x", d => x(d.name))
      .attr("y", d => y(d.value))
      .attr("height", d => y(0) - y(d.value))
      .attr("width", x.bandwidth());

  svg.append("g")
      .attr("class", "x-axis")
      .call(xAxis);

  svg.append("g")
      .attr("class", "y-axis")
      .call(yAxis);

content/posts/my-first-post.md

---
title: "D3.js bars"
date: 2020-03-24T00:00:00Z
draft: false
---

### Hello
<div class="visualisation"> </div> <!-- Hugo supports html in markdown -->
<script src = "https://cdnjs.cloudflare.com/ajax/libs/d3/5.15.0/d3.js"></script> <!-- load d3.js from CDN. you could potentially load it from /static folder as well-->
<script src = "/example.js"></script> <!-- this will pick our scipt up and render the chart -->

This structure might not be ideal as you could probably stick javascript references into reusable layout of some sort and potentially parametrise the chart definition so you didn’t have to repeat it for every page. Without knowing your specifics it’s however a bit hard to make these suggestions. I’m just hoping it gives you a good enough hint to keep going.

UPD I’m pretty sure the code itself is working: see this jsfiddle. Hugo has different file layout, but point I’m trying to make here is it should all be a matter of ensuring both your javascript files get loaded.

UPD2 starting version 0.60.0 Hugo will not by default allow unsafe html content (such as tags). To get it to work you need to enable it:

markup:
  goldmark:
    renderer:
      unsafe: true

Problem :

I have some D3.js visualizations I want to server on a Github Pages website I made using Hugo. I’m struggling how to include the visualization (html and js file) within the markdown file. Is this possible? If not, can I just use a standalone html file on Hugo?

Edit:
I implemented the example @timur suggested but the plot still doesn’t show.
Resulting webpage

Comments

Comment posted by documentation for hugo.js

Did you read the

Comment posted by Riley Finn

@Mehdi Going off the thread link: I tried adding a html file in my

Comment posted by Riley Finn

Thanks for getting me on the right track but this example doesn’t seem to be working. I even tried it on a local server without using hugo.

Comment posted by timur

Do you mind elaborating a bit more? What sort of error error you get?

Comment posted by Riley Finn

I don’t get any error but “Hello” is the only thing that shows in the post. I’m adding a screenshot of the result.

Comment posted by timur

JavaScript seems to not have been loaded. Check out page source around

Comment posted by timur

this is one place – you’d go there for debugging. I’m first suggesting to have a look at

By