Chart.js and Ghost

I’m migrating this site over to Ghost. Over the 15+ years I’ve had this blog on WordPress, there are a few plugins I’ve come to rely on heavily. And the one that’s been the toughest to find an alternative to is Visualizer. It renders the graphs on the several pages that use it, such as my very long article on abortion.

In the search I discovered Chart.js, which looks to be a viable replacement. But integrating it into Ghost isn’t all that easy. Rather than use code injection on the posts where I want to use it, I opted to create a “partial” that is scoped based on an internal tag:

{{#is "page,post"}}
  {{#post}}
    {{#has tag="#chartjs"}}

    <link rel="stylesheet" href='{{asset "css/chartjs.css"}}' />
    <script src='{{asset "js/chartjs/chart.js"}}'></script>
    <!--<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>-->
    <script>
    function chart(chart_options) {
      new Chart(
        document.getElementById(chart_options.container_id),
        {
          type: chart_options.chart_type,
          data: chart_options.chart_data,
          options: {
            responsive: true,
            plugins: {
              legend: {
                position: chart_options.legend_position || 'right'
              },
              title: {
                display: chart_options.display_chart_title || true,
                text: chart_options.chart_title
              }
            }
          }
        });
    }
    </script>

    {{/has}}
  {{/post}}
{{/is}}

This is the code I’m using as of this writing. I’ll update this post as I go, but for now this appears to give me what I want. I have the above in a partial – chartjs.hbs – and call it from within the header on my default.hbs template file after everything else. That way I’m not relying on per-post code injection to use it. Instead I rely on an internal tag – #chartjs – to turn it on for posts that use it over loading it for every post.

For the time being I’m not loading chart.js externally while I’m developing a theme, hence the CDN line being commented out in favor of pulling from the assets.

And this is an example of calling the chart function through an HTML card to provide a line graph like this:

<div class="chartjs"><canvas id="mass-shootings-per-year" /></div>
  <script>
  chart({
    container_id: 'mass-shootings-per-year',
    chart_type: 'line',
    chart_data: {
      labels: ['1982', '1983', '1984', '1985', '1986', '1987', '1988', '1989', '1990', '1991', '1992', '1993', '1994', '1995', '1996', '1997', '1998', '1999', '2000', '2001', '2002', '2003', '2004', '2005', '2006', '2007', '2008', '2009', '2010', '2011', '2012', '2013', '2014', '2015', '2016', '2017', '2018', '2019' ],
      datasets: [{
        label: 'Mass shootings',
        data: [ 01, 00, 02, 00, 01, 01, 01, 02, 01, 03, 02, 04, 01, 01, 01, 02, 03, 05, 01, 01, 00, 01, 01, 02, 03, 04, 03, 04, 01, 03, 07, 05, 04, 07, 06, 11, 12, 10 ]
      }]
    },
    chart_title: 'Mass shootings per year, United States, 1982-2019'
  });
</script>

Which looks like this:

This can definitely be enhanced further, and I’ll update this post or put everything on Github as things progress.