Overall Picture
I wanted to add easily and in a markdown-stile way a bunch of chart in one of my blog posts.
I already knew ChartJS and that’s why I tried a different framework.
But then, while I was randomly googling I found a super-duper-easy way.
The ChartJS easy solution.
I found this cool integration: https://github.com/Shen-Yu but that wasn’t exactly what I was looking for.
I wanted a simple and markdown-style way of generating a chart.
So I knew I was going to review the code a bit
The design
I wanted a simple integration design: using markdown tables
That’s how I can invoke use the shortcode.
{ {< chart "100%" "300px" "false" >} }
|Label |Data |
|------|---------|
| one |7 |
| two |7 |
|three |10 |
| four |6 |
| five |6 |
{ {< /chart-job >} }
Parameters are:
- width (default: 100%)
- height (default: 300px)
- showTable (default: true)
So I simply created a shortcode
, named shortcodes/chart.html
with this code.
{{ $width := default "100" (.Get 0) }}
{{ $height := default "300" (.Get 1) }}
{{ $showTable := default "true" (.Get 2)}}
{{ $r := ( .Inner | chomp ) }}
{{ $id := index (seq 999 | shuffle) 1 }}
{{ if eq $showTable "true" }}
{{ .Inner | markdownify}}
{{ end }}
<div style="width: {{ $width }}; height: {{ $height }}; margin: 0 auto">
<canvas id="{{ $id }}"></canvas>
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/Chart.min.js"></script>
<script type="text/javascript">
(function(){
function selectColor(number) {
const hue = number * 137.508; // use golden angle approximation
return `hsl(${hue},50%,75%)`;
}
const innerString = {{$r}};
const rowsString = innerString.trim().split('\n')
let itemsString = rowsString.map(x => x.substring(1,x.length-1).trim().split('|'))
// transpose
itemsString = itemsString[0].map((_, colIndex) => itemsString.map(row => row[colIndex]));
const labels = itemsString[0].slice(2).map(x => x.trim());
let datasets = itemsString.slice(1).filter(x => x[0]);
datasets = datasets.map((item, index) => {
return {
label: item[0].trim(),
fill: false,
borderColor: selectColor(index+1),
data: item.slice(2).map(x => Number(x.trim()))
};
})
var ctx = document.getElementById('{{ $id }}').getContext('2d');
var options = {
type: 'radar',
data: {
labels: labels,
datasets: datasets
},
options: {
maintainAspectRatio: false,
scale: {
angleLines: {
display: false
},
ticks: {
suggestedMin: 0,
suggestedMax: 10,
stepSize: 2,
showLabelBackdrop: false
},
},
legend: {
position: "right"
}
}
};
new Chart(ctx, options);
})();
</script>
Next Steps
I’ll probably evolve this tool and I may share this with an easier/direct installation with hugo.
But not so sure to be honest