require 'asciidoctor/extensions' require_relative 'chart_data' module Asciinurse module Chart module ChartCreator def get_engine(doc) doc.attributes['charts'] || Asciinurse.config('charts.default') end def create_chart(parent, attrs, config) document = parent.document backend = document.attributes['backend'] if backend == 'html5' html = create_from_json document, config create_pass_block parent, html, attrs, subs: nil else attrs['target'] = create_image document, config, attrs attrs['width'] ||= 480 attrs['height'] ||= 250 create_image_block parent, attrs end end def create_from_json(document, config) id = 'chart_%s' % document.counter(:chart_id) engine = get_engine document template = Asciinurse.read_resource "#{engine}/templates/chart.html.erb" ERB.new(template).result binding end def create_from_csv(engine, data, attrs) csv_data = CSVData::new engine, attrs, data csv_data.to_chart_json end def create_image(document, config, attrs) engine = get_engine document converter_file = Asciinurse.config "charts.#{engine}.convert.file" tmpdir = Asciinurse.tmp_dir document id = document.counter(:chart_id) config_file = "#{tmpdir}/config-#{id}.json" image_file = "#{tmpdir}/chart-#{id}.png" IO.write config_file, config converter = Asciinurse.find_resource "#{engine}/converter/#{converter_file}" command = Asciinurse.config("charts.#{engine}.convert.command") % [converter, config_file, image_file] `#{command}` image_file end end class ChartBlockMacro < Asciidoctor::Extensions::BlockMacroProcessor include ChartCreator use_dsl named :chart name_positional_attributes 'type', 'width', 'height' def process(parent, target, attrs) engine = get_engine parent.document data_path = parent.normalize_asset_path(target, 'target') data = parent.read_asset(data_path, warn_on_failure: true, normalize: true) data = create_from_csv engine, data, attrs if data_path.end_with? '.csv' create_chart parent, attrs, data end end class ChartBlockProcessor < Asciidoctor::Extensions::BlockProcessor include ChartCreator use_dsl named :chart on_context :literal name_positional_attributes 'type', 'width', 'height' parse_content_as :raw def process(parent, reader, attrs) engine = get_engine parent.document data = create_from_csv engine, reader.source, attrs create_chart parent, attrs, data end end class ChartAssetsDocinfoProcessor < Asciidoctor::Extensions::DocinfoProcessor include ChartCreator use_dsl at_location :header def process(doc) engine = get_engine(doc) scripts = Asciinurse.config "charts.#{engine}.include" if doc.attributes['backend'] == 'html5' (scripts.collect do |script| if script.start_with? 'http' "" else %() end end).join $/ end end end end end Asciidoctor::Extensions.register do |registry| registry.block_macro Asciinurse::Chart::ChartBlockMacro registry.block Asciinurse::Chart::ChartBlockProcessor registry.docinfo_processor Asciinurse::Chart::ChartAssetsDocinfoProcessor end