Repository: getnikola/nikola

Issue:
Templating in charts - Feature
Regarding the chart directive https://www.getnikola.com/handbook.html#chart

Can we use templates with the charts?

So data could be stored as csv or json and not manually written?



Discussion:
This is **so** close to working with the shortcode :-)

If you put your data in a json file and put that in the "data" metadata field, you could turn this:

```
{{% chart Bar title='Browser usage evolution (in %)' %}}
        x_labels='["2002","2003","2004","2005","2006","2007","2008","2009","2010","2011","2012"]'%}}
        'Firefox', [None, None, 0, 16.6, 25, 31]
        'Chrome',  [None, None, None, None, None, None]
        'IE',      [85.8, 84.6, 84.7, 74.5, 66, 58.6]
        'Others',  [14.2, 15.4, 15.3, 8.9, 9, 10.4]
{{% /chart %}}
```

Into something like this:

```
{{% chart Bar title='Browser usage evolution (in %)' %}}
        x_labels='["2002","2003","2004","2005","2006","2007","2008","2009","2010","2011","2012"]'%}}
        % for k, v in post.data.items():
        '${k}', ${v}
        % endfor 
{{% /chart %}}
```

Or something similar, perhaps more complicated (not tried it yet)

OTOH, I think it makes a lot more sense to just have chart support a data_file option that lets you specify everything in a file. Would that be ok?

Resolving patch:
diff --git a/nikola/plugins/compile/rest/chart.py b/nikola/plugins/compile/rest/chart.py
--- a/nikola/plugins/compile/rest/chart.py
+++ b/nikola/plugins/compile/rest/chart.py
@@ -72,6 +72,7 @@ class Chart(Directive):
         "classes": directives.unchanged,
         "css": directives.unchanged,
         "defs": directives.unchanged,
+        "data_file": directives.unchanged,
         "disable_xml_declaration": directives.unchanged,
         "dots_size": directives.unchanged,
         "dynamic_print_values": directives.unchanged,
diff --git a/nikola/plugins/shortcode/chart.py b/nikola/plugins/shortcode/chart.py
--- a/nikola/plugins/shortcode/chart.py
+++ b/nikola/plugins/shortcode/chart.py
@@ -33,7 +33,7 @@
     pygal = None  # NOQA
 
 from nikola.plugin_categories import ShortcodePlugin
-from nikola.utils import req_missing
+from nikola.utils import req_missing, load_data
 
 _site = None
 
@@ -50,18 +50,30 @@ def handler(self, chart_type, **_options):
                 ['pygal'], 'use the Chart directive', optional=True)
             return '<div class="text-error">{0}</div>'.format(msg)
         options = {}
-        data = _options.pop('data')
+        chart_data = []
         _options.pop('post', None)
         _options.pop('site')
-        if 'style' in _options:
-            style_name = _options.pop('style')
-        else:
-            style_name = 'BlueStyle'
+        data = _options.pop('data')
+
+        for line in data.splitlines():
+            line = line.strip()
+            if line:
+                chart_data.append(literal_eval('({0})'.format(line)))
+        if 'data_file' in _options:
+            options = load_data(_options['data_file'])
+            _options.pop('data_file')
+            if not chart_data:  # If there is data in the document, it wins
+                for k, v in options.pop('data', {}).items():
+                    chart_data.append((k, v))
+
+        options.update(_options)
+
+        style_name = options.pop('style', 'BlueStyle')
         if '(' in style_name:  # Parametric style
             style = eval('pygal.style.' + style_name)
         else:
             style = getattr(pygal.style, style_name)
-        for k, v in _options.items():
+        for k, v in options.items():
             try:
                 options[k] = literal_eval(v)
             except Exception:
@@ -73,9 +85,6 @@ def handler(self, chart_type, **_options):
         if _site and _site.invariant:
             chart.no_prefix = True
         chart.config(**options)
-        for line in data.splitlines():
-            line = line.strip()
-            if line:
-                label, series = literal_eval('({0})'.format(line))
-                chart.add(label, series)
+        for label, series in chart_data:
+            chart.add(label, series)
         return chart.render().decode('utf8')


Test patch: