jekyll-diagrams 0.9.2 → 0.9.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +32 -20
  3. data/features/blockdiag.feature +1 -2
  4. data/features/graphviz.feature +58 -6
  5. data/features/mermaid.feature +1 -2
  6. data/features/nomnoml.feature +2 -22
  7. data/features/plantuml.feature +17 -8
  8. data/features/smcat.feature +10 -15
  9. data/features/support/env.rb +11 -5
  10. data/features/syntrax.feature +1 -2
  11. data/features/vega.feature +24 -12
  12. data/features/wavedrom.feature +2 -8
  13. data/lib/jekyll-diagrams.rb +64 -1
  14. data/lib/jekyll-diagrams/block.rb +33 -8
  15. data/lib/jekyll-diagrams/blockdiag.rb +8 -6
  16. data/lib/jekyll-diagrams/erd.rb +7 -1
  17. data/lib/jekyll-diagrams/errors.rb +25 -0
  18. data/lib/jekyll-diagrams/graphviz.rb +2 -1
  19. data/lib/jekyll-diagrams/mermaid.rb +4 -5
  20. data/lib/jekyll-diagrams/nomnoml.rb +2 -2
  21. data/lib/jekyll-diagrams/plantuml.rb +3 -4
  22. data/lib/jekyll-diagrams/rendering.rb +67 -0
  23. data/lib/jekyll-diagrams/smcat.rb +2 -2
  24. data/lib/jekyll-diagrams/vega.rb +3 -1
  25. data/lib/jekyll-diagrams/version.rb +1 -1
  26. data/test/block_test.rb +6 -0
  27. data/test/blockdiag_test.rb +28 -0
  28. data/test/erd_test.rb +5 -2
  29. data/test/rendering_test.rb +20 -0
  30. data/test/svgbob_test.rb +22 -0
  31. data/test/test_helper.rb +12 -3
  32. metadata +118 -39
  33. data/.coveralls.yml +0 -1
  34. data/.github/workflows/test.yml +0 -83
  35. data/.gitignore +0 -4
  36. data/.rubocop.yml +0 -22
  37. data/.simplecov +0 -5
  38. data/.travis.yml +0 -50
  39. data/Dockerfile +0 -53
  40. data/Gemfile +0 -8
  41. data/Rakefile +0 -28
  42. data/features/svgbob.feature +0 -22
  43. data/jekyll-diagrams.gemspec +0 -31
  44. data/lib/jekyll-diagrams/util.rb +0 -95
  45. data/test/util_test.rb +0 -20
@@ -1,6 +1,69 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'jekyll-diagrams/util'
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 Util
6
+ include Rendering
7
7
 
8
8
  def render(context)
9
- svg = render_svg(super.to_s, read_config(context))
10
- wrap_class(svg)
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
- def render_svg(_, _)
20
+ private
21
+
22
+ def render_svg(_code, _config)
14
23
  ''
15
24
  end
16
25
 
17
- def read_config(context)
18
- config_for(context, block_name)
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 wrap_class(content)
22
- "<div class='jekyll-diagrams diagrams #{block_name}'>#{content}</div>"
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
- command << ' --antialias' if config.fetch('antialias', false) != false
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)
@@ -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
- command << ' --dot-entity' if config.fetch('dot-entity', false) != false
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], prefix: " -#{prefix}")
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[backgroundColor height theme width].freeze
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 << ' --puppeteerConfigFile '
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)
@@ -6,8 +6,8 @@ module Jekyll
6
6
  def render_svg(code, config)
7
7
  command = build_command(config)
8
8
 
9
- render_with_tempfile(command, code, stdout: true) do |input|
10
- input
9
+ render_with_tempfile(command, code) do |input, output|
10
+ "#{input} #{output}"
11
11
  end
12
12
  end
13
13
 
@@ -13,10 +13,9 @@ module Jekyll
13
13
  end
14
14
 
15
15
  def build_command(_config)
16
- options = +'java'
17
- options << ' -Djava.awt.headless=true'
18
- options << ' -jar '
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, stdout: true) do |input|
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, '')
@@ -6,7 +6,9 @@ module Jekyll
6
6
  CONFIGURATIONS = %w[scale].freeze
7
7
 
8
8
  def render_svg(code, config)
9
- code = render_with_stdin_stdout('vl2vg', code) if block_name == 'vegalite'
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
 
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Jekyll
4
4
  module Diagrams
5
- VERSION = '0.9.2'
5
+ VERSION = '0.9.3'
6
6
  end
7
7
  end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
4
+
5
+ class BlockTest < Minitest::Test
6
+ end
@@ -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.send(
8
- :new, 'erd', '', Liquid::ParseContext.new
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