asciidoctor-chart 1.0.0.alpha.1 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.adoc +38 -0
- data/README.adoc +89 -3
- data/asciidoctor-chart.gemspec +18 -11
- data/lib/asciidoctor/chart/block_macro_processor.rb +1 -3
- data/lib/asciidoctor/chart/block_processor.rb +1 -3
- data/lib/asciidoctor/chart/chart_block.rb +45 -0
- data/lib/asciidoctor/chart/converter/c3js.rb +231 -0
- data/lib/asciidoctor/chart/converter/chartist.rb +81 -0
- data/lib/asciidoctor/chart/converter/chartjs.rb +102 -0
- data/lib/asciidoctor/chart/converter.rb +13 -0
- data/lib/asciidoctor/chart/docinfo_processor.rb +69 -20
- data/lib/asciidoctor/chart/html5_chart_converter_ext.rb +25 -0
- data/lib/asciidoctor/chart/preprocessor.rb +13 -0
- data/lib/asciidoctor/chart/registry.rb +17 -0
- data/lib/asciidoctor/chart/version.rb +1 -1
- data/lib/asciidoctor/chart.rb +36 -4
- metadata +33 -12
- data/lib/asciidoctor/chart/backend.rb +0 -58
- data/lib/asciidoctor/chart/c3js/chart_builder.rb +0 -226
- data/lib/asciidoctor/chart/chartist/chart_builder.rb +0 -88
- data/lib/asciidoctor/chart/chartjs/chart_builder.rb +0 -66
@@ -0,0 +1,102 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Asciidoctor
|
4
|
+
module Chart
|
5
|
+
module Converter
|
6
|
+
class Html5ChartjsConverter < Asciidoctor::Chart::Converter::Base
|
7
|
+
CSS_VALUE_UNIT_RX = /^([+-]?(?:\d+|\d*\.\d+))([a-z]*|%)$/.freeze
|
8
|
+
DEFAULT_COLORS = [{ r: 220, g: 220, b: 220 }, { r: 151, g: 187, b: 205 }].freeze
|
9
|
+
|
10
|
+
def convert_line_chart node
|
11
|
+
data, labels = prepare_data node
|
12
|
+
datasets = data.map do |set|
|
13
|
+
color = DEFAULT_COLORS[data.index(set) % 2]
|
14
|
+
color_rgba = "rgba(#{color[:r]},#{color[:g]},#{color[:b]},1.0)"
|
15
|
+
<<~JSON
|
16
|
+
{
|
17
|
+
borderColor: "#{color_rgba}",
|
18
|
+
backgroundColor: "#{color_rgba}",
|
19
|
+
fill: false,
|
20
|
+
tension: 0.1,
|
21
|
+
data: #{set.to_s}
|
22
|
+
}
|
23
|
+
JSON
|
24
|
+
end.join ','
|
25
|
+
|
26
|
+
chart_id = node.attr 'id'
|
27
|
+
inline_styles = []
|
28
|
+
if (chart_height = get_height node)
|
29
|
+
inline_styles.push("height: #{chart_height}")
|
30
|
+
end
|
31
|
+
if (chart_width = get_width node)
|
32
|
+
inline_styles.push("max-width: #{chart_width}")
|
33
|
+
end
|
34
|
+
maintain_aspect_ratio = chart_height.nil? && chart_width.nil?
|
35
|
+
title_element = node.title? ? %(\n <div class="title">#{node.captioned_title}</div>) : ''
|
36
|
+
<<~HTML
|
37
|
+
<div class="chartblock">
|
38
|
+
<div class="content chartjs-content" style="#{inline_styles.join('; ')}">
|
39
|
+
<canvas id="#{chart_id}"></canvas>
|
40
|
+
</div>#{title_element}
|
41
|
+
</div>
|
42
|
+
<script>
|
43
|
+
window.addEventListener('load', function(event) {
|
44
|
+
var data = {
|
45
|
+
labels: #{labels.to_s},
|
46
|
+
datasets: [#{datasets}]
|
47
|
+
}
|
48
|
+
var chart = new Chart(document.getElementById("#{chart_id}").getContext("2d"), {
|
49
|
+
type: 'line',
|
50
|
+
data: data,
|
51
|
+
options: {
|
52
|
+
interaction: {
|
53
|
+
mode: 'index'
|
54
|
+
},
|
55
|
+
responsive : true,
|
56
|
+
maintainAspectRatio: #{maintain_aspect_ratio},
|
57
|
+
plugins: {
|
58
|
+
legend: {
|
59
|
+
display: false
|
60
|
+
}
|
61
|
+
}
|
62
|
+
}
|
63
|
+
})
|
64
|
+
})
|
65
|
+
</script>
|
66
|
+
HTML
|
67
|
+
end
|
68
|
+
|
69
|
+
def prepare_data node
|
70
|
+
raw_data = node.attr 'data-raw', []
|
71
|
+
return [[], []] if raw_data.length <= 1 # question: should we warn?
|
72
|
+
|
73
|
+
labels = raw_data[0]
|
74
|
+
raw_data.shift
|
75
|
+
[raw_data, labels]
|
76
|
+
end
|
77
|
+
|
78
|
+
private
|
79
|
+
|
80
|
+
def get_height node
|
81
|
+
return unless (height = node.attr 'height')
|
82
|
+
|
83
|
+
to_css_size height
|
84
|
+
end
|
85
|
+
|
86
|
+
def get_width node
|
87
|
+
return unless (width = node.attr 'width')
|
88
|
+
|
89
|
+
to_css_size width
|
90
|
+
end
|
91
|
+
|
92
|
+
def to_css_size str
|
93
|
+
return str unless (parts = str.match(CSS_VALUE_UNIT_RX))
|
94
|
+
|
95
|
+
value, unit = parts.captures
|
96
|
+
unit = 'px' if unit == ''
|
97
|
+
"#{value}#{unit}"
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -6,26 +6,75 @@ module Asciidoctor
|
|
6
6
|
use_dsl
|
7
7
|
# at_location :head
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
9
|
+
C3JS_DIR_ATTR = 'c3jsdir'
|
10
|
+
C3JS_DEFAULT_PATH = 'https://cdnjs.cloudflare.com/ajax/libs/c3/0.7.20/'
|
11
|
+
|
12
|
+
CHARTJS_DIR_ATTR = 'chartjsdir'
|
13
|
+
CHARTJS_DEFAULT_PATH = 'https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.0/'
|
14
|
+
|
15
|
+
CHARTIST_DIR_ATTR = 'chartistdir'
|
16
|
+
CHARTIST_DEFAULT_PATH = 'https://cdn.jsdelivr.net/npm/chartist@0.11.x/dist/'
|
17
|
+
|
18
|
+
D3JS_DIR_ATTR = 'd3jsdir'
|
19
|
+
D3JS_DEFAULT_PATH = 'https://cdnjs.cloudflare.com/ajax/libs/d3/5.16.0/'
|
20
|
+
|
21
|
+
DEFAULT_STYLE = <<~HTML.chomp
|
22
|
+
<style>
|
23
|
+
.chartblock {
|
24
|
+
margin-bottom: 1.25em;
|
25
|
+
}
|
26
|
+
.chartblock > .title {
|
27
|
+
text-rendering: optimizeLegibility;
|
28
|
+
text-align: left;
|
29
|
+
font-size: 1rem;
|
30
|
+
font-style: italic;
|
31
|
+
line-height: 1.45;
|
32
|
+
color: #7a2518;
|
33
|
+
font-weight: 400;
|
34
|
+
}
|
35
|
+
.chartblock > .chartjs-content {
|
36
|
+
position: relative;
|
37
|
+
margin-bottom: 0.25em;
|
38
|
+
}
|
39
|
+
</style>
|
40
|
+
HTML
|
41
|
+
|
42
|
+
def process(doc)
|
43
|
+
engines = doc.x_chart[:engines]
|
44
|
+
(engines.map {|engine| send(engine, doc) }.to_a + [DEFAULT_STYLE]).join "\n"
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def get_path(doc, attr_name, default_path, asset_to_include)
|
50
|
+
doc.normalize_web_path asset_to_include, (doc.attr attr_name, default_path), false
|
51
|
+
end
|
52
|
+
|
53
|
+
def create_script_directive(doc, attr_name, default_path, asset_to_include)
|
54
|
+
%(<script src="#{get_path doc, attr_name, default_path, asset_to_include}"></script>)
|
55
|
+
end
|
56
|
+
|
57
|
+
def create_link_css_directive(doc, attr_name, default_path, asset_to_include)
|
58
|
+
%(<link rel="stylesheet" href="#{get_path doc, attr_name, default_path, asset_to_include}">)
|
59
|
+
end
|
60
|
+
|
61
|
+
def chartjs(doc)
|
62
|
+
create_script_directive(doc, CHARTJS_DIR_ATTR, CHARTJS_DEFAULT_PATH, 'chart.min.js')
|
63
|
+
end
|
64
|
+
|
65
|
+
def chartist(doc)
|
66
|
+
result = []
|
67
|
+
result << create_link_css_directive(doc, CHARTIST_DIR_ATTR, CHARTIST_DEFAULT_PATH, 'chartist.min.css')
|
68
|
+
result << create_script_directive(doc, CHARTIST_DIR_ATTR, CHARTIST_DEFAULT_PATH, 'chartist.min.js')
|
69
|
+
result
|
70
|
+
end
|
71
|
+
|
72
|
+
def c3js(doc)
|
73
|
+
result = []
|
74
|
+
result << create_link_css_directive(doc, C3JS_DIR_ATTR, C3JS_DEFAULT_PATH, 'c3.min.css')
|
75
|
+
result << create_script_directive(doc, D3JS_DIR_ATTR, D3JS_DEFAULT_PATH, 'd3.min.js')
|
76
|
+
result << create_script_directive(doc, C3JS_DIR_ATTR, C3JS_DEFAULT_PATH, 'c3.min.js')
|
77
|
+
result
|
29
78
|
end
|
30
79
|
end
|
31
80
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Asciidoctor
|
4
|
+
module Chart
|
5
|
+
module Html5ChartConverterExt
|
6
|
+
def convert_chart node
|
7
|
+
chart_engine = node.attr 'engine'
|
8
|
+
chart_type = node.attr 'type'
|
9
|
+
chart_converter = Asciidoctor::Chart::Registry.for chart_engine
|
10
|
+
|
11
|
+
if chart_converter
|
12
|
+
if chart_converter.handles? chart_type
|
13
|
+
chart_converter.send "convert_#{chart_type}_chart", node
|
14
|
+
else
|
15
|
+
logger.warn %(missing chart convert handler for type '#{chart_type}' in #{chart_converter})
|
16
|
+
nil
|
17
|
+
end
|
18
|
+
else
|
19
|
+
logger.warn %(missing chart convert for engine '#{chart_engine}')
|
20
|
+
nil
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Asciidoctor
|
4
|
+
module Chart
|
5
|
+
module Registry
|
6
|
+
@registry = {}
|
7
|
+
|
8
|
+
def self.register converter, engine
|
9
|
+
@registry[engine] = converter
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.for engine
|
13
|
+
@registry[engine]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/asciidoctor/chart.rb
CHANGED
@@ -1,19 +1,51 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'asciidoctor/extensions'
|
4
|
+
require 'tilt'
|
5
|
+
require_relative 'chart/html5_chart_converter_ext'
|
6
|
+
require_relative 'chart/registry'
|
7
|
+
require_relative 'chart/preprocessor'
|
4
8
|
require_relative 'chart/block_macro_processor'
|
5
9
|
require_relative 'chart/block_processor'
|
6
10
|
require_relative 'chart/docinfo_processor'
|
7
|
-
require_relative 'chart/
|
11
|
+
require_relative 'chart/chart_block'
|
8
12
|
require_relative 'chart/plain_ruby_csv'
|
9
13
|
require_relative 'chart/plain_ruby_random'
|
10
|
-
require_relative 'chart/
|
11
|
-
require_relative 'chart/
|
12
|
-
require_relative 'chart/chartist
|
14
|
+
require_relative 'chart/converter'
|
15
|
+
require_relative 'chart/converter/c3js'
|
16
|
+
require_relative 'chart/converter/chartist'
|
17
|
+
require_relative 'chart/converter/chartjs'
|
18
|
+
|
19
|
+
CHART_HTML_TEMPLATE = Tilt.new('chart.html.erb', format: :html5, pretty: true, disable_escape: true) do |_t|
|
20
|
+
<<-ERB
|
21
|
+
<%= Class.new.extend(Asciidoctor::Chart::Html5ChartConverterExt).convert_chart self %>
|
22
|
+
ERB
|
23
|
+
end
|
24
|
+
|
25
|
+
# providers
|
26
|
+
Asciidoctor::Chart::Registry.register Asciidoctor::Chart::Converter::Html5ChartjsConverter.new, 'chartjs'
|
27
|
+
Asciidoctor::Chart::Registry.register Asciidoctor::Chart::Converter::Html5ChartistConverter.new, 'chartist'
|
28
|
+
Asciidoctor::Chart::Registry.register Asciidoctor::Chart::Converter::Html5C3jsConverter.new, 'c3js'
|
29
|
+
|
30
|
+
def register_chart_converter converter
|
31
|
+
if (converter.instance_of? Asciidoctor::Converter::TemplateConverter) || (converter.respond_to? 'register')
|
32
|
+
# Template based converter
|
33
|
+
converter.register 'chart', CHART_HTML_TEMPLATE
|
34
|
+
else
|
35
|
+
converter.extend(Asciidoctor::Chart::Html5ChartConverterExt)
|
36
|
+
end
|
37
|
+
end
|
13
38
|
|
14
39
|
Asciidoctor::Extensions.register do
|
15
40
|
return unless document.basebackend? 'html'
|
16
41
|
|
42
|
+
converter = document.converter
|
43
|
+
if converter.instance_of? Asciidoctor::Converter::CompositeConverter
|
44
|
+
register_chart_converter(converter.converters[0])
|
45
|
+
else
|
46
|
+
register_chart_converter(converter)
|
47
|
+
end
|
48
|
+
preprocessor Asciidoctor::Chart::Preprocessor
|
17
49
|
block_macro Asciidoctor::Chart::BlockMacroProcessor
|
18
50
|
block Asciidoctor::Chart::BlockProcessor
|
19
51
|
docinfo_processor Asciidoctor::Chart::DocinfoProcessor
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: asciidoctor-chart
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.0
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Guillaume Grossetie
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-10-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: asciidoctor
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '2.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: tilt
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 2.0.0
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 2.0.0
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: rake
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -52,35 +66,42 @@ dependencies:
|
|
52
66
|
- - "~>"
|
53
67
|
- !ruby/object:Gem::Version
|
54
68
|
version: 3.9.0
|
55
|
-
description:
|
56
|
-
|
69
|
+
description: |-
|
70
|
+
A set of Asciidoctor extensions that add a chart block and block macro to AsciiDoc
|
71
|
+
for including charts in your AsciiDoc document.
|
57
72
|
email: ggrossetie@gmail.com
|
58
73
|
executables: []
|
59
74
|
extensions: []
|
60
75
|
extra_rdoc_files: []
|
61
76
|
files:
|
77
|
+
- CHANGELOG.adoc
|
62
78
|
- LICENSE.adoc
|
63
79
|
- README.adoc
|
64
80
|
- asciidoctor-chart.gemspec
|
65
81
|
- lib/asciidoctor-chart.rb
|
66
82
|
- lib/asciidoctor/chart.rb
|
67
|
-
- lib/asciidoctor/chart/backend.rb
|
68
83
|
- lib/asciidoctor/chart/block_macro_processor.rb
|
69
84
|
- lib/asciidoctor/chart/block_processor.rb
|
70
|
-
- lib/asciidoctor/chart/
|
71
|
-
- lib/asciidoctor/chart/
|
72
|
-
- lib/asciidoctor/chart/
|
85
|
+
- lib/asciidoctor/chart/chart_block.rb
|
86
|
+
- lib/asciidoctor/chart/converter.rb
|
87
|
+
- lib/asciidoctor/chart/converter/c3js.rb
|
88
|
+
- lib/asciidoctor/chart/converter/chartist.rb
|
89
|
+
- lib/asciidoctor/chart/converter/chartjs.rb
|
73
90
|
- lib/asciidoctor/chart/docinfo_processor.rb
|
91
|
+
- lib/asciidoctor/chart/html5_chart_converter_ext.rb
|
74
92
|
- lib/asciidoctor/chart/plain_ruby_csv.rb
|
75
93
|
- lib/asciidoctor/chart/plain_ruby_random.rb
|
94
|
+
- lib/asciidoctor/chart/preprocessor.rb
|
95
|
+
- lib/asciidoctor/chart/registry.rb
|
76
96
|
- lib/asciidoctor/chart/version.rb
|
77
97
|
homepage: https://asciidoctor.org
|
78
98
|
licenses:
|
79
99
|
- MIT
|
80
100
|
metadata:
|
81
101
|
bug_tracker_uri: https://github.com/asciidoctor/asciidoctor-chart/issues
|
82
|
-
|
102
|
+
community_chat_uri: https://asciidoctor.zulipchat.com
|
83
103
|
source_code_uri: https://github.com/asciidoctor/asciidoctor-chart
|
104
|
+
rubygems_mfa_required: 'true'
|
84
105
|
post_install_message:
|
85
106
|
rdoc_options: []
|
86
107
|
require_paths:
|
@@ -92,11 +113,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
92
113
|
version: '0'
|
93
114
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
94
115
|
requirements:
|
95
|
-
- - "
|
116
|
+
- - ">="
|
96
117
|
- !ruby/object:Gem::Version
|
97
|
-
version:
|
118
|
+
version: '0'
|
98
119
|
requirements: []
|
99
|
-
rubygems_version: 3.0.3
|
120
|
+
rubygems_version: 3.0.3.1
|
100
121
|
signing_key:
|
101
122
|
specification_version: 4
|
102
123
|
summary: Adds a chart block and block macro to AsciiDoc
|
@@ -1,58 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Asciidoctor
|
4
|
-
module Chart
|
5
|
-
class Backend
|
6
|
-
def self.resolve_engine attrs, document
|
7
|
-
if attrs.key? 'engine'
|
8
|
-
attrs['engine'].downcase
|
9
|
-
elsif document.attributes.key? 'chart-engine'
|
10
|
-
document.attributes['chart-engine'].downcase
|
11
|
-
else
|
12
|
-
'c3js'
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
def self.process engine, attrs, raw_data
|
17
|
-
# TODO: Check that the engine can process the required type (bar, line, step...)
|
18
|
-
type = attrs['type']
|
19
|
-
case engine
|
20
|
-
when 'c3js'
|
21
|
-
if type == 'pie'
|
22
|
-
C3js::ChartBuilder.pie raw_data, attrs
|
23
|
-
else
|
24
|
-
data, labels = C3js::ChartBuilder.prepare_data raw_data
|
25
|
-
case type
|
26
|
-
when 'bar'
|
27
|
-
C3js::ChartBuilder.bar data, labels, attrs
|
28
|
-
when 'line'
|
29
|
-
C3js::ChartBuilder.line data, labels, attrs
|
30
|
-
when 'step'
|
31
|
-
C3js::ChartBuilder.step data, labels, attrs
|
32
|
-
when 'spline'
|
33
|
-
C3js::ChartBuilder.spline data, labels, attrs
|
34
|
-
else
|
35
|
-
# By default chart line
|
36
|
-
C3js::ChartBuilder.line data, labels, attrs
|
37
|
-
end
|
38
|
-
end
|
39
|
-
when 'chartist'
|
40
|
-
data, labels = Chartist::ChartBuilder.prepare_data raw_data
|
41
|
-
case type
|
42
|
-
when 'bar'
|
43
|
-
Chartist::ChartBuilder.bar data, labels, attrs
|
44
|
-
when 'line'
|
45
|
-
Chartist::ChartBuilder.line data, labels, attrs
|
46
|
-
else
|
47
|
-
# By default chart line
|
48
|
-
Chartist::ChartBuilder.line data, labels, attrs
|
49
|
-
end
|
50
|
-
when 'chartjs'
|
51
|
-
data, labels = Chartjs::ChartBuilder.prepare_data raw_data
|
52
|
-
# By default chart line
|
53
|
-
Chartjs::ChartBuilder.line data, labels, attrs
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|