kramdown-plantuml 1.0.4 → 1.1.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/codecov.yml +2 -0
- data/.github/dependabot.yml +23 -0
- data/.github/mergify.yml +22 -0
- data/.github/scripts/amend.sh +176 -0
- data/.github/scripts/build-gem.sh +6 -0
- data/.github/scripts/inspect-gem.sh +72 -0
- data/.github/scripts/publish-gem.sh +121 -0
- data/.github/scripts/test-gem.sh +170 -0
- data/.github/scripts/variables.sh +72 -0
- data/.github/workflows/amend.yml +19 -0
- data/.github/workflows/no-java.yml +3 -6
- data/.github/workflows/no-plantuml.yml +6 -9
- data/.github/workflows/ruby.yml +135 -81
- data/.github/workflows/shell.yml +11 -0
- data/.gitignore +9 -0
- data/.rubocop.yml +18 -0
- data/Gemfile +4 -8
- data/GitVersion.yml +5 -0
- data/LICENSE +201 -21
- data/README.md +130 -42
- data/Rakefile +33 -3
- data/bin/{plantuml.1.2020.5.jar → net/sourceforge/plantuml/plantuml/1.2021.8/plantuml-1.2021.8.jar} +0 -0
- data/kramdown-plantuml.gemspec +32 -17
- data/lib/kramdown-plantuml.rb +4 -6
- data/lib/kramdown-plantuml/bool_env.rb +24 -0
- data/lib/kramdown-plantuml/console_logger.rb +56 -0
- data/lib/kramdown-plantuml/converter.rb +40 -33
- data/lib/kramdown-plantuml/executor.rb +48 -0
- data/lib/kramdown-plantuml/logger.rb +89 -0
- data/lib/kramdown-plantuml/plantuml_error.rb +33 -0
- data/lib/kramdown-plantuml/plantuml_result.rb +50 -0
- data/lib/kramdown-plantuml/themer.rb +76 -0
- data/lib/kramdown-plantuml/version.rb +3 -2
- data/lib/kramdown_html.rb +21 -9
- data/lib/which.rb +3 -0
- data/pom.xml +16 -0
- metadata +128 -10
- data/bin/console +0 -14
- data/bin/setup +0 -8
data/Rakefile
CHANGED
@@ -1,10 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'rake'
|
2
4
|
require 'bundler/gem_tasks'
|
3
5
|
require 'rspec/core/rake_task'
|
4
6
|
|
5
7
|
RSpec::Core::RakeTask.new(:spec) do |t|
|
6
|
-
|
7
|
-
|
8
|
+
t.pattern = Dir.glob('spec/**/*_spec.rb')
|
9
|
+
t.rspec_opts = '--format documentation --tag ~no_plantuml --tag ~no_java --tag ~debug'
|
10
|
+
end
|
11
|
+
|
12
|
+
namespace :maven do
|
13
|
+
task :install do
|
14
|
+
require 'fileutils'
|
15
|
+
|
16
|
+
system 'mvn install'
|
17
|
+
bin_dir = File.join __dir__, 'bin'
|
18
|
+
target_file = File.join bin_dir, 'plantuml.jar'
|
19
|
+
repo_dir = File.expand_path '~/.m2/repository'
|
20
|
+
jar_glob = File.join repo_dir, '/**/plantuml*.jar'
|
21
|
+
first_jar = Dir[jar_glob].first
|
22
|
+
jar_file = File.expand_path first_jar
|
23
|
+
|
24
|
+
FileUtils.mkdir_p bin_dir
|
25
|
+
FileUtils.move(jar_file, target_file)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
namespace :codecov do
|
30
|
+
desc 'Uploads the latest SimpleCov result set to codecov.io'
|
31
|
+
task :upload do
|
32
|
+
require 'simplecov'
|
33
|
+
require 'codecov'
|
34
|
+
|
35
|
+
formatter = SimpleCov::Formatter::Codecov.new
|
36
|
+
formatter.format(SimpleCov::ResultMerger.merged_result)
|
37
|
+
end
|
8
38
|
end
|
9
39
|
|
10
|
-
task :
|
40
|
+
task default: :spec
|
data/bin/{plantuml.1.2020.5.jar → net/sourceforge/plantuml/plantuml/1.2021.8/plantuml-1.2021.8.jar}
RENAMED
Binary file
|
data/kramdown-plantuml.gemspec
CHANGED
@@ -1,33 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative 'lib/which'
|
2
4
|
require_relative 'lib/kramdown-plantuml/version'
|
3
5
|
|
4
6
|
Gem::Specification.new do |spec|
|
5
|
-
spec.name =
|
7
|
+
spec.name = 'kramdown-plantuml'
|
6
8
|
spec.version = Kramdown::PlantUml::VERSION
|
7
|
-
spec.authors = [
|
8
|
-
spec.email = [
|
9
|
+
spec.authors = ['Swedbank Pay']
|
10
|
+
spec.email = ['opensource@swedbankpay.com']
|
9
11
|
|
10
|
-
spec.summary =
|
11
|
-
|
12
|
-
|
13
|
-
|
12
|
+
spec.summary = <<~SUMMARY
|
13
|
+
kramdown-plantuml allows you to use PlantUML syntax within fenced code
|
14
|
+
blocks with Kramdown (Jekyll's default Markdown parser).
|
15
|
+
SUMMARY
|
16
|
+
spec.homepage = 'https://github.com/SwedbankPay/kramdown-plantuml'
|
17
|
+
spec.license = 'MIT'
|
18
|
+
spec.required_ruby_version = Gem::Requirement.new('>= 2.5.0')
|
14
19
|
|
15
|
-
spec.metadata[
|
16
|
-
spec.metadata[
|
20
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
21
|
+
spec.metadata['source_code_uri'] = 'https://github.com/SwedbankPay/kramdown-plantuml'
|
17
22
|
|
18
23
|
# Specify which files should be added to the gem when it is released.
|
19
|
-
# The `git ls-files -z` loads the files in the RubyGem that have been added into
|
20
|
-
spec.files
|
21
|
-
if Which
|
22
|
-
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
24
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into Git.
|
25
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
26
|
+
if Which.which('git')
|
27
|
+
files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
28
|
+
# Explicitly add plantuml.jar to the list of files as it is not committed to Git.
|
29
|
+
files.append(Dir['bin/**/plantuml*.jar'].first)
|
23
30
|
else
|
24
31
|
puts "Git not found, no files added to #{spec.name}."
|
25
32
|
end
|
26
33
|
end
|
27
|
-
spec.bindir =
|
34
|
+
spec.bindir = 'exe'
|
28
35
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
29
|
-
spec.require_paths = [
|
36
|
+
spec.require_paths = ['lib']
|
37
|
+
|
38
|
+
spec.add_dependency 'kramdown', '~> 2.3'
|
39
|
+
spec.add_dependency 'kramdown-parser-gfm', '~> 1.1'
|
40
|
+
spec.add_dependency 'open3', '~> 0.1'
|
30
41
|
|
31
|
-
spec.add_development_dependency
|
32
|
-
spec.add_development_dependency
|
42
|
+
spec.add_development_dependency 'rake', '~> 13.0'
|
43
|
+
spec.add_development_dependency 'rspec', '~> 3.2'
|
44
|
+
spec.add_development_dependency 'rspec-its', '~> 1.3'
|
45
|
+
spec.add_development_dependency 'rubocop', '~> 1.12'
|
46
|
+
spec.add_development_dependency 'rubocop-rake', '~> 0.6'
|
47
|
+
spec.add_development_dependency 'rubocop-rspec', '~> 2.4'
|
33
48
|
end
|
data/lib/kramdown-plantuml.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
|
-
|
2
|
-
require 'kramdown-plantuml/converter'
|
3
|
-
require 'kramdown_html'
|
1
|
+
# frozen_string_literal: true
|
4
2
|
|
5
|
-
|
6
|
-
|
7
|
-
|
3
|
+
require_relative 'kramdown-plantuml/version'
|
4
|
+
require_relative 'kramdown-plantuml/converter'
|
5
|
+
require_relative 'kramdown_html'
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kramdown
|
4
|
+
module PlantUml
|
5
|
+
# Converts envrionment variables to boolean values
|
6
|
+
class BoolEnv
|
7
|
+
TRUTHY_VALUES = %w[t true yes y 1].freeze
|
8
|
+
FALSEY_VALUES = %w[f false n no 0].freeze
|
9
|
+
|
10
|
+
def initialize(name)
|
11
|
+
@name = name
|
12
|
+
value = ENV.fetch(name, nil)
|
13
|
+
@value = value.to_s.downcase unless value.nil?
|
14
|
+
end
|
15
|
+
|
16
|
+
def true?
|
17
|
+
return true if TRUTHY_VALUES.include?(@value)
|
18
|
+
return false if FALSEY_VALUES.include?(@value) || @value.nil? || value.empty?
|
19
|
+
|
20
|
+
raise "The value '#{@value}' of '#{@name}' can't be converted to a boolean"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'bool_env'
|
4
|
+
|
5
|
+
module Kramdown
|
6
|
+
module PlantUml
|
7
|
+
# Logs to $stdout and $stderr
|
8
|
+
class ConsoleLogger
|
9
|
+
LOG_LEVELS = %i[debug info warn error].freeze
|
10
|
+
|
11
|
+
def initialize(level)
|
12
|
+
@configured_log_level = level
|
13
|
+
end
|
14
|
+
|
15
|
+
def debug(message)
|
16
|
+
write(:debug, message)
|
17
|
+
end
|
18
|
+
|
19
|
+
def info(message)
|
20
|
+
write(:info, message)
|
21
|
+
end
|
22
|
+
|
23
|
+
def warn(message)
|
24
|
+
write(:warn, message)
|
25
|
+
end
|
26
|
+
|
27
|
+
def error(message)
|
28
|
+
write(:error, message)
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def write(level, message)
|
34
|
+
return false unless write_message?(level)
|
35
|
+
|
36
|
+
pipe = pipe_for(level)
|
37
|
+
pipe.write("#{message}\n")
|
38
|
+
end
|
39
|
+
|
40
|
+
def write_message?(level_of_message)
|
41
|
+
LOG_LEVELS.index(@configured_log_level) <= LOG_LEVELS.index(level_of_message)
|
42
|
+
end
|
43
|
+
|
44
|
+
def pipe_for(level)
|
45
|
+
case level
|
46
|
+
when :debug, :info
|
47
|
+
$stdout
|
48
|
+
when :warn, :error
|
49
|
+
$stderr
|
50
|
+
else
|
51
|
+
raise ArgumentError, "Unknown log level '#{level}'."
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -1,45 +1,52 @@
|
|
1
|
-
|
2
|
-
require 'open3'
|
3
|
-
require_relative 'version'
|
4
|
-
|
5
|
-
module Kramdown::PlantUml
|
6
|
-
class Converter
|
7
|
-
def initialize
|
8
|
-
dir = File.dirname __dir__
|
9
|
-
bin = File.join dir, "../bin"
|
10
|
-
bin = File.expand_path bin
|
11
|
-
@plant_uml_jar_file = File.join bin, "plantuml.1.2020.5.jar"
|
1
|
+
# frozen_string_literal: true
|
12
2
|
|
13
|
-
|
14
|
-
|
3
|
+
require_relative 'version'
|
4
|
+
require_relative 'themer'
|
5
|
+
require_relative 'plantuml_error'
|
6
|
+
require_relative 'logger'
|
7
|
+
require_relative 'executor'
|
8
|
+
|
9
|
+
module Kramdown
|
10
|
+
module PlantUml
|
11
|
+
# Converts PlantUML markup to SVG
|
12
|
+
class Converter
|
13
|
+
def initialize(options = {})
|
14
|
+
@themer = Themer.new(options)
|
15
|
+
@logger = Logger.init
|
16
|
+
@executor = Executor.new
|
15
17
|
end
|
16
18
|
|
17
|
-
|
18
|
-
|
19
|
+
def convert_plantuml_to_svg(plantuml)
|
20
|
+
if plantuml.nil? || plantuml.empty?
|
21
|
+
@logger.warn ' kramdown-plantuml: PlantUML diagram is empty'
|
22
|
+
return plantuml
|
23
|
+
end
|
24
|
+
|
25
|
+
plantuml = @themer.apply_theme(plantuml)
|
26
|
+
plantuml = plantuml.strip
|
27
|
+
log(plantuml)
|
28
|
+
result = @executor.execute(plantuml)
|
29
|
+
result.validate(plantuml)
|
30
|
+
svg = result.without_xml_prologue
|
31
|
+
wrap(svg)
|
19
32
|
end
|
20
|
-
end
|
21
33
|
|
22
|
-
|
23
|
-
cmd = "java -jar #{@plant_uml_jar_file} -tsvg -pipe"
|
34
|
+
private
|
24
35
|
|
25
|
-
|
36
|
+
def wrap(svg)
|
37
|
+
theme_class = @themer.theme_name ? "theme-#{@themer.theme_name}" : ''
|
38
|
+
class_name = "plantuml #{theme_class}".strip
|
26
39
|
|
27
|
-
|
28
|
-
|
29
|
-
end
|
30
|
-
|
31
|
-
xml_prologue_start = "<?xml"
|
32
|
-
xml_prologue_end = "?>"
|
40
|
+
wrapper_element_start = "<div class=\"#{class_name}\">"
|
41
|
+
wrapper_element_end = '</div>'
|
33
42
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
stdout.slice! start_index, end_index
|
38
|
-
|
39
|
-
wrapper_element_start = "<div class=\"plantuml\">"
|
40
|
-
wrapper_element_end = "</div>"
|
43
|
+
"#{wrapper_element_start}#{svg}#{wrapper_element_end}"
|
44
|
+
end
|
41
45
|
|
42
|
-
|
46
|
+
def log(plantuml)
|
47
|
+
@logger.debug ' kramdown-plantuml: PlantUML converting diagram:'
|
48
|
+
@logger.debug_with_prefix ' kramdown-plantuml: ', plantuml
|
49
|
+
end
|
43
50
|
end
|
44
51
|
end
|
45
52
|
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: false
|
2
|
+
|
3
|
+
require 'open3'
|
4
|
+
require_relative '../which'
|
5
|
+
require_relative 'logger'
|
6
|
+
require_relative 'plantuml_result'
|
7
|
+
|
8
|
+
module Kramdown
|
9
|
+
module PlantUml
|
10
|
+
# Executes the PlantUML Java application.
|
11
|
+
class Executor
|
12
|
+
def initialize
|
13
|
+
@logger = Logger.init
|
14
|
+
@plantuml_jar_file = find_plantuml_jar_file
|
15
|
+
|
16
|
+
raise IOError, 'Java can not be found' unless Which.which('java')
|
17
|
+
raise IOError, "No 'plantuml.jar' file could be found" if @plantuml_jar_file.nil?
|
18
|
+
raise IOError, "'#{@plantuml_jar_file}' does not exist" unless File.exist? @plantuml_jar_file
|
19
|
+
end
|
20
|
+
|
21
|
+
def execute(stdin)
|
22
|
+
cmd = "java -Djava.awt.headless=true -jar #{@plantuml_jar_file} -tsvg -failfast -pipe"
|
23
|
+
cmd << if @logger.debug?
|
24
|
+
' -verbose'
|
25
|
+
else
|
26
|
+
' -nometadata'
|
27
|
+
end
|
28
|
+
|
29
|
+
@logger.debug " kramdown-plantuml: Executing '#{cmd}'."
|
30
|
+
|
31
|
+
stdout, stderr, status = Open3.capture3 cmd, stdin_data: stdin
|
32
|
+
|
33
|
+
@logger.debug " kramdown-plantuml: PlantUML exit code '#{status.exitstatus}'."
|
34
|
+
|
35
|
+
PlantUmlResult.new(stdout, stderr, status)
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def find_plantuml_jar_file
|
41
|
+
dir = File.dirname __dir__
|
42
|
+
jar_glob = File.join dir, '../bin/**/plantuml*.jar'
|
43
|
+
first_jar = Dir[jar_glob].first
|
44
|
+
File.expand_path first_jar unless first_jar.nil?
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'console_logger'
|
4
|
+
|
5
|
+
module Kramdown
|
6
|
+
module PlantUml
|
7
|
+
# Logs stuff
|
8
|
+
class Logger
|
9
|
+
def initialize(logger)
|
10
|
+
raise ArgumentError, 'logger cannot be nil' if logger.nil?
|
11
|
+
raise ArgumentError, 'logger must respond to #debug' unless logger.respond_to? :debug
|
12
|
+
raise ArgumentError, 'logger must respond to #info' unless logger.respond_to? :info
|
13
|
+
raise ArgumentError, 'logger must respond to #warn' unless logger.respond_to? :warn
|
14
|
+
raise ArgumentError, 'logger must respond to #error' unless logger.respond_to? :error
|
15
|
+
|
16
|
+
@logger = logger
|
17
|
+
end
|
18
|
+
|
19
|
+
def debug(message)
|
20
|
+
@logger.debug message
|
21
|
+
end
|
22
|
+
|
23
|
+
def debug_with_prefix(prefix, string)
|
24
|
+
return if string.nil? || string.empty?
|
25
|
+
|
26
|
+
lines = string.lines
|
27
|
+
lines.each do |line|
|
28
|
+
@logger.debug "#{prefix}#{line.rstrip}"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def info(message)
|
33
|
+
@logger.info message
|
34
|
+
end
|
35
|
+
|
36
|
+
def warn(message)
|
37
|
+
@logger.warn message
|
38
|
+
end
|
39
|
+
|
40
|
+
def error(message)
|
41
|
+
@logger.error message
|
42
|
+
end
|
43
|
+
|
44
|
+
def debug?
|
45
|
+
self.class.level == :debug
|
46
|
+
end
|
47
|
+
|
48
|
+
def level
|
49
|
+
@level ||= level_from_logger || self.class.env
|
50
|
+
end
|
51
|
+
|
52
|
+
class << self
|
53
|
+
def init
|
54
|
+
inner = nil
|
55
|
+
|
56
|
+
begin
|
57
|
+
require 'jekyll'
|
58
|
+
inner = Jekyll.logger
|
59
|
+
rescue LoadError
|
60
|
+
inner = ConsoleLogger.new level
|
61
|
+
end
|
62
|
+
|
63
|
+
Logger.new inner
|
64
|
+
end
|
65
|
+
|
66
|
+
def level
|
67
|
+
@level ||= level_from_env
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
def level_from_env
|
73
|
+
return :debug if BoolEnv.new('DEBUG').true?
|
74
|
+
return :debug if BoolEnv.new('VERBOSE').true?
|
75
|
+
|
76
|
+
:warn
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
private
|
81
|
+
|
82
|
+
def level_from_logger
|
83
|
+
return @logger.level if @logger.respond_to? :level
|
84
|
+
|
85
|
+
nil
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kramdown
|
4
|
+
module PlantUml
|
5
|
+
# PlantUML Error
|
6
|
+
class PlantUmlError < StandardError
|
7
|
+
def initialize(plantuml, stderr, exitcode)
|
8
|
+
message = <<~MESSAGE
|
9
|
+
Conversion of the following PlantUML diagram failed:
|
10
|
+
|
11
|
+
#{plantuml}
|
12
|
+
|
13
|
+
The error received from PlantUML was:
|
14
|
+
|
15
|
+
Exit code: #{exitcode}
|
16
|
+
#{stderr}
|
17
|
+
MESSAGE
|
18
|
+
|
19
|
+
super message
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.should_raise?(exitcode, stderr)
|
23
|
+
return false if exitcode.zero?
|
24
|
+
|
25
|
+
!stderr.nil? && !stderr.empty? && \
|
26
|
+
# If stderr is not empty, but contains the string 'CoreText note:',
|
27
|
+
# the error is caused by a bug in Java, and should be ignored.
|
28
|
+
# Circumvents https://bugs.openjdk.java.net/browse/JDK-8244621
|
29
|
+
!stderr.include?('CoreText note:')
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|