jekyll-diagrams 0.9.2 → 0.9.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +32 -20
- data/features/blockdiag.feature +1 -2
- data/features/graphviz.feature +58 -6
- data/features/mermaid.feature +1 -2
- data/features/nomnoml.feature +2 -22
- data/features/plantuml.feature +17 -8
- data/features/smcat.feature +10 -15
- data/features/support/env.rb +11 -5
- data/features/syntrax.feature +1 -2
- data/features/vega.feature +24 -12
- data/features/wavedrom.feature +2 -8
- data/lib/jekyll-diagrams.rb +64 -1
- data/lib/jekyll-diagrams/block.rb +33 -8
- data/lib/jekyll-diagrams/blockdiag.rb +8 -6
- data/lib/jekyll-diagrams/erd.rb +7 -1
- data/lib/jekyll-diagrams/errors.rb +25 -0
- data/lib/jekyll-diagrams/graphviz.rb +2 -1
- data/lib/jekyll-diagrams/mermaid.rb +4 -5
- data/lib/jekyll-diagrams/nomnoml.rb +2 -2
- data/lib/jekyll-diagrams/plantuml.rb +3 -4
- data/lib/jekyll-diagrams/rendering.rb +67 -0
- data/lib/jekyll-diagrams/smcat.rb +2 -2
- data/lib/jekyll-diagrams/vega.rb +3 -1
- data/lib/jekyll-diagrams/version.rb +1 -1
- data/test/block_test.rb +6 -0
- data/test/blockdiag_test.rb +28 -0
- data/test/erd_test.rb +5 -2
- data/test/rendering_test.rb +20 -0
- data/test/svgbob_test.rb +22 -0
- data/test/test_helper.rb +12 -3
- metadata +118 -39
- data/.coveralls.yml +0 -1
- data/.github/workflows/test.yml +0 -83
- data/.gitignore +0 -4
- data/.rubocop.yml +0 -22
- data/.simplecov +0 -5
- data/.travis.yml +0 -50
- data/Dockerfile +0 -53
- data/Gemfile +0 -8
- data/Rakefile +0 -28
- data/features/svgbob.feature +0 -22
- data/jekyll-diagrams.gemspec +0 -31
- data/lib/jekyll-diagrams/util.rb +0 -95
- data/test/util_test.rb +0 -20
data/lib/jekyll-diagrams.rb
CHANGED
@@ -1,6 +1,69 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
require 'jekyll'
|
4
|
+
|
5
|
+
module Jekyll
|
6
|
+
module Diagrams
|
7
|
+
class << self
|
8
|
+
# Return configuration of Jekyll Diagrams
|
9
|
+
#
|
10
|
+
# @param context [Liquid::Context, :registers] Parsed context
|
11
|
+
# @return Configuration
|
12
|
+
def configuration(context)
|
13
|
+
site_config = context.registers[:site].config
|
14
|
+
page_config = context.registers[:page]
|
15
|
+
|
16
|
+
site_config.merge(page_config)
|
17
|
+
end
|
18
|
+
|
19
|
+
def config_for(context, name)
|
20
|
+
configuration(context).dig(config_name, name) || {}
|
21
|
+
end
|
22
|
+
|
23
|
+
def error_mode(context)
|
24
|
+
liquid_mode = configuration(context).dig('liquid', 'error_mode')
|
25
|
+
custom_mode = configuration(context).dig(config_name, 'error_mode')
|
26
|
+
|
27
|
+
(custom_mode || liquid_mode || :warn).to_sym
|
28
|
+
end
|
29
|
+
|
30
|
+
# Return file path under vendor path
|
31
|
+
#
|
32
|
+
# @param file [String] If not given, return directory path
|
33
|
+
def vendor_path(file = '')
|
34
|
+
File.join(File.expand_path('../vendor', __dir__), file)
|
35
|
+
end
|
36
|
+
|
37
|
+
# @param jar [String] Jar path to run
|
38
|
+
def run_jar(jar)
|
39
|
+
"java -Djava.awt.headless=true -jar #{jar} "
|
40
|
+
end
|
41
|
+
|
42
|
+
def normalized_attrs(attrs, prefix:, sep: '=')
|
43
|
+
attrs =
|
44
|
+
case attrs
|
45
|
+
when String
|
46
|
+
attrs
|
47
|
+
when Array
|
48
|
+
attrs.join(prefix)
|
49
|
+
when Hash
|
50
|
+
attrs.map { |k, v| "#{k}#{sep}#{v}" }.join(prefix)
|
51
|
+
end
|
52
|
+
|
53
|
+
"#{prefix}#{attrs}"
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def config_name
|
59
|
+
'jekyll-diagrams'
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
require_relative 'jekyll-diagrams/errors'
|
66
|
+
require_relative 'jekyll-diagrams/rendering'
|
4
67
|
require_relative 'jekyll-diagrams/block'
|
5
68
|
|
6
69
|
require_relative 'jekyll-diagrams/blockdiag'
|
@@ -3,23 +3,48 @@
|
|
3
3
|
module Jekyll
|
4
4
|
module Diagrams
|
5
5
|
class Block < Liquid::Block
|
6
|
-
include
|
6
|
+
include Rendering
|
7
7
|
|
8
8
|
def render(context)
|
9
|
-
|
10
|
-
|
9
|
+
config = Diagrams.config_for(context, block_name)
|
10
|
+
|
11
|
+
output = render_svg(super.to_s, config)
|
12
|
+
wrap_class(output)
|
13
|
+
rescue StandardError => e
|
14
|
+
error_mode = Diagrams.error_mode(context)
|
15
|
+
|
16
|
+
output = handle_error(e, error_mode)
|
17
|
+
wrap_class(output)
|
11
18
|
end
|
12
19
|
|
13
|
-
|
20
|
+
private
|
21
|
+
|
22
|
+
def render_svg(_code, _config)
|
14
23
|
''
|
15
24
|
end
|
16
25
|
|
17
|
-
def
|
18
|
-
|
26
|
+
def wrap_class(content)
|
27
|
+
<<~CONTENT
|
28
|
+
<div class='jekyll-diagrams diagrams #{block_name}'>
|
29
|
+
#{content}
|
30
|
+
</div>"
|
31
|
+
CONTENT
|
19
32
|
end
|
20
33
|
|
21
|
-
def
|
22
|
-
|
34
|
+
def handle_error(error, mode)
|
35
|
+
topic = 'Jekyll Diagrams:'
|
36
|
+
msg = error.message
|
37
|
+
|
38
|
+
case mode
|
39
|
+
when :lax
|
40
|
+
Jekyll.logger.info topic, msg
|
41
|
+
''
|
42
|
+
when :warn
|
43
|
+
Jekyll.logger.warn topic, msg
|
44
|
+
msg
|
45
|
+
when :strict
|
46
|
+
Jekyll.logger.abort_with topic, msg
|
47
|
+
end
|
23
48
|
end
|
24
49
|
end
|
25
50
|
end
|
@@ -4,6 +4,9 @@ module Jekyll
|
|
4
4
|
module Diagrams
|
5
5
|
class BlockdiagBlock < Block
|
6
6
|
CONFIGURATIONS = %w[config font fontmap size].freeze
|
7
|
+
SWITCHES = {
|
8
|
+
'antialias' => false
|
9
|
+
}.freeze
|
7
10
|
|
8
11
|
def render_svg(code, config)
|
9
12
|
command = build_command(config)
|
@@ -13,13 +16,12 @@ module Jekyll
|
|
13
16
|
end
|
14
17
|
end
|
15
18
|
|
16
|
-
def read_config(context)
|
17
|
-
config_for(context, 'blockdiag').merge(config_for(context, block_name))
|
18
|
-
end
|
19
|
-
|
20
19
|
def build_command(config)
|
21
|
-
command = "#{block_name} -T svg --nodoctype"
|
22
|
-
|
20
|
+
command = +"#{block_name} -T svg --nodoctype"
|
21
|
+
|
22
|
+
SWITCHES.merge(config.slice(*SWITCHES.keys)).each do |switch, value|
|
23
|
+
command << " --#{switch}" if value != false
|
24
|
+
end
|
23
25
|
|
24
26
|
CONFIGURATIONS.each do |conf|
|
25
27
|
command << " --#{conf}=#{config[conf]}" if config.key?(conf)
|
data/lib/jekyll-diagrams/erd.rb
CHANGED
@@ -5,6 +5,9 @@ module Jekyll
|
|
5
5
|
class ErdBlock < Block
|
6
6
|
XML_REGEX = /^<\?xml(([^>]|\n)*>\n?){2}/.freeze
|
7
7
|
CONFIGURATIONS = %w[config edge].freeze
|
8
|
+
SWITCHES = {
|
9
|
+
'dot-entity' => false
|
10
|
+
}.freeze
|
8
11
|
|
9
12
|
def render_svg(code, config)
|
10
13
|
command = build_command(config)
|
@@ -15,7 +18,10 @@ module Jekyll
|
|
15
18
|
|
16
19
|
def build_command(config)
|
17
20
|
command = +'erd --fmt=svg'
|
18
|
-
|
21
|
+
|
22
|
+
SWITCHES.merge(config.slice(*SWITCHES.keys)).each do |switch, value|
|
23
|
+
command << " --#{switch}" if value != false
|
24
|
+
end
|
19
25
|
|
20
26
|
CONFIGURATIONS.each do |conf|
|
21
27
|
command << " --#{conf}=#{config[conf]}" if config.key?(conf)
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Jekyll
|
4
|
+
module Diagrams
|
5
|
+
module Errors
|
6
|
+
BaseError = Class.new(::StandardError) do
|
7
|
+
def initialize(msg)
|
8
|
+
@msg = msg
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
CommandNotFoundError = Class.new(BaseError) do
|
13
|
+
def message
|
14
|
+
"Command Not Found: #{@msg}"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
RenderingFailedError = Class.new(BaseError) do
|
19
|
+
def message
|
20
|
+
"Rendering Failed: #{@msg}"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -27,7 +27,8 @@ module Jekyll
|
|
27
27
|
CONFIGRATIONS.each do |prefix, conf|
|
28
28
|
next unless config.key?(conf)
|
29
29
|
|
30
|
-
command << normalized_attrs(config[conf],
|
30
|
+
command << Diagrams.normalized_attrs(config[conf],
|
31
|
+
prefix: " -#{prefix}")
|
31
32
|
end
|
32
33
|
|
33
34
|
command
|
@@ -3,7 +3,8 @@
|
|
3
3
|
module Jekyll
|
4
4
|
module Diagrams
|
5
5
|
class MermaidBlock < Block
|
6
|
-
CONFIGURATIONS = %w[
|
6
|
+
CONFIGURATIONS = %w[theme width height backgroundColor
|
7
|
+
configFile cssFile scale].freeze
|
7
8
|
|
8
9
|
def render_svg(code, config)
|
9
10
|
command = build_command(config)
|
@@ -14,10 +15,8 @@ module Jekyll
|
|
14
15
|
end
|
15
16
|
|
16
17
|
def build_command(config)
|
17
|
-
command = +'mmdc'
|
18
|
-
command << '
|
19
|
-
command << vendor_path('mermaid_puppeteer_config.json')
|
20
|
-
command << ' --transparent' if config.fetch('transparent', false) != false
|
18
|
+
command = +'mmdc --puppeteerConfigFile '
|
19
|
+
command << Diagrams.vendor_path('mermaid_puppeteer_config.json')
|
21
20
|
|
22
21
|
CONFIGURATIONS.each do |conf|
|
23
22
|
command << " --#{conf} #{config[conf]}" if config.key?(conf)
|
@@ -13,10 +13,9 @@ module Jekyll
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def build_command(_config)
|
16
|
-
|
17
|
-
|
18
|
-
options
|
19
|
-
options << vendor_path('plantuml.1.2020.1.jar')
|
16
|
+
jar = Diagrams.vendor_path('plantuml.1.2020.1.jar')
|
17
|
+
|
18
|
+
options = +Diagrams.run_jar(jar)
|
20
19
|
options << ' -tsvg -pipe'
|
21
20
|
end
|
22
21
|
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'open3'
|
4
|
+
require 'tempfile'
|
5
|
+
require 'tmpdir'
|
6
|
+
|
7
|
+
module Jekyll
|
8
|
+
module Diagrams
|
9
|
+
module Rendering
|
10
|
+
module_function
|
11
|
+
|
12
|
+
# Render SVG with stdin and stdout
|
13
|
+
#
|
14
|
+
# @param command Command to run
|
15
|
+
# @param content Content passed to command
|
16
|
+
# @return The SVG output
|
17
|
+
def render_with_stdin_stdout(command, content)
|
18
|
+
render_with_command(command, :stdout, stdin_data: content)
|
19
|
+
end
|
20
|
+
|
21
|
+
# Render SVG with tempfile
|
22
|
+
#
|
23
|
+
# @param command Command to run
|
24
|
+
# @param content Content passed to command
|
25
|
+
# @param block Result of block will append to command
|
26
|
+
# @return The SVG output
|
27
|
+
def render_with_tempfile(command, content)
|
28
|
+
Dir.mktmpdir('jekyll-diagrams-rendering') do |dir|
|
29
|
+
input = Tempfile.new('input', tmpdir: dir)
|
30
|
+
output = Tempfile.new(%w[output .svg], tmpdir: dir)
|
31
|
+
|
32
|
+
File.write(input.path, content)
|
33
|
+
|
34
|
+
extra = yield input.path, output.path
|
35
|
+
command = "#{command} #{extra}"
|
36
|
+
|
37
|
+
render_with_command(command, output.path)
|
38
|
+
ensure
|
39
|
+
input.close!
|
40
|
+
output.close!
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# Render SVG with command
|
45
|
+
#
|
46
|
+
# @param command Command to run
|
47
|
+
# @param output Output path, use :stdout for stdout
|
48
|
+
# @param options Extra options passed to Open3.captrue3
|
49
|
+
# @return The SVG output
|
50
|
+
def render_with_command(command, output = :stdout, **options)
|
51
|
+
begin
|
52
|
+
stdout, stderr, status = Open3.capture3(command, **options)
|
53
|
+
rescue Errno::ENOENT
|
54
|
+
raise Errors::CommandNotFoundError, command.split(' ')[0]
|
55
|
+
end
|
56
|
+
|
57
|
+
unless status.success?
|
58
|
+
raise Errors::RenderingFailedError, <<~MSG
|
59
|
+
#{command}: #{stderr.empty? ? stdout : stderr}
|
60
|
+
MSG
|
61
|
+
end
|
62
|
+
|
63
|
+
output == :stdout ? stdout : File.read(output)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -9,8 +9,8 @@ module Jekyll
|
|
9
9
|
def render_svg(code, config)
|
10
10
|
command = build_command(config)
|
11
11
|
|
12
|
-
svg = render_with_tempfile(command, code
|
13
|
-
"#{input} --output-to
|
12
|
+
svg = render_with_tempfile(command, code) do |input, output|
|
13
|
+
"#{input} --output-to #{output}"
|
14
14
|
end
|
15
15
|
|
16
16
|
svg.sub!(XML_REGEX, '')
|
data/lib/jekyll-diagrams/vega.rb
CHANGED
@@ -6,7 +6,9 @@ module Jekyll
|
|
6
6
|
CONFIGURATIONS = %w[scale].freeze
|
7
7
|
|
8
8
|
def render_svg(code, config)
|
9
|
-
|
9
|
+
if block_name == 'vegalite'
|
10
|
+
code = render_with_stdin_stdout('vl2vg', code)
|
11
|
+
end
|
10
12
|
|
11
13
|
command = build_command(config)
|
12
14
|
|
data/test/block_test.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'test_helper'
|
4
|
+
|
5
|
+
class BlockdiagTest < Minitest::Test
|
6
|
+
def setup
|
7
|
+
@block = Jekyll::Diagrams::BlockdiagBlock.parse(
|
8
|
+
'blockdiag',
|
9
|
+
'',
|
10
|
+
Liquid::Tokenizer.new('{% endblockdiag %}'),
|
11
|
+
Liquid::ParseContext.new
|
12
|
+
)
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_build_command_with_default_config
|
16
|
+
config = {}
|
17
|
+
assert_equal 'blockdiag -T svg --nodoctype', @block.build_command(config)
|
18
|
+
|
19
|
+
config = { 'antialias' => true }
|
20
|
+
assert_match '--antialias', @block.build_command(config)
|
21
|
+
|
22
|
+
config = { 'antialias' => false }
|
23
|
+
refute_match '--antialias', @block.build_command(config)
|
24
|
+
|
25
|
+
config = { 'size' => 3 }
|
26
|
+
assert_match '--size=3', @block.build_command(config)
|
27
|
+
end
|
28
|
+
end
|
data/test/erd_test.rb
CHANGED
@@ -4,8 +4,11 @@ require 'test_helper'
|
|
4
4
|
|
5
5
|
class ErdTest < Minitest::Test
|
6
6
|
def setup
|
7
|
-
@block = Jekyll::Diagrams::ErdBlock.
|
8
|
-
|
7
|
+
@block = Jekyll::Diagrams::ErdBlock.parse(
|
8
|
+
'erd',
|
9
|
+
'',
|
10
|
+
Liquid::Tokenizer.new('test {% enderd %}'),
|
11
|
+
Liquid::ParseContext.new
|
9
12
|
)
|
10
13
|
end
|
11
14
|
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'test_helper'
|
4
|
+
|
5
|
+
class RenderingTest < Minitest::Test
|
6
|
+
include Jekyll::Diagrams::Errors
|
7
|
+
include Jekyll::Diagrams::Rendering
|
8
|
+
|
9
|
+
def test_raise_command_not_found_error
|
10
|
+
assert_raises CommandNotFoundError do
|
11
|
+
render_with_command('not_exist_command')
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_raise_rendering_failed_error
|
16
|
+
assert_raises RenderingFailedError do
|
17
|
+
render_with_command('/bin/bash -c "exit 1"')
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|