kramdown-plantuml 1.0.1 → 1.1.2
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.
- 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 +139 -86
- data/.github/workflows/shell.yml +11 -0
- data/.gitignore +9 -0
- data/.rubocop.yml +18 -0
- data/CODE_OF_CONDUCT.md +11 -9
- data/Gemfile +4 -8
- data/GitVersion.yml +5 -0
- data/LICENSE +201 -21
- data/README.md +143 -35
- 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 +39 -21
- data/lib/kramdown-plantuml/executor.rb +48 -0
- data/lib/kramdown-plantuml/hash.rb +14 -0
- data/lib/kramdown-plantuml/logger.rb +77 -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 +64 -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 +131 -12
- 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,34 +1,52 @@
|
|
1
|
-
|
2
|
-
require 'open3'
|
3
|
-
require_relative 'version'
|
1
|
+
# frozen_string_literal: true
|
4
2
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
bin = File.expand_path bin
|
11
|
-
@plant_uml_jar_file = File.join bin, "plantuml.1.2020.5.jar"
|
3
|
+
require_relative 'version'
|
4
|
+
require_relative 'themer'
|
5
|
+
require_relative 'plantuml_error'
|
6
|
+
require_relative 'logger'
|
7
|
+
require_relative 'executor'
|
12
8
|
|
13
|
-
|
14
|
-
|
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
|
-
|
34
|
+
private
|
35
|
+
|
36
|
+
def wrap(svg)
|
37
|
+
theme_class = @themer.theme_name ? "theme-#{@themer.theme_name}" : ''
|
38
|
+
class_name = "plantuml #{theme_class}".strip
|
24
39
|
|
25
|
-
|
40
|
+
wrapper_element_start = "<div class=\"#{class_name}\">"
|
41
|
+
wrapper_element_end = '</div>'
|
26
42
|
|
27
|
-
|
28
|
-
raise stderr
|
43
|
+
"#{wrapper_element_start}#{svg}#{wrapper_element_end}"
|
29
44
|
end
|
30
45
|
|
31
|
-
|
46
|
+
def log(plantuml)
|
47
|
+
@logger.debug 'kramdown-plantuml: PlantUML converting diagram:'
|
48
|
+
@logger.debug_with_prefix 'kramdown-plantuml: ', plantuml
|
49
|
+
end
|
32
50
|
end
|
33
51
|
end
|
34
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,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Ruby's Hash class.
|
4
|
+
class ::Hash
|
5
|
+
# Via https://stackoverflow.com/a/25835016/2257038
|
6
|
+
def symbolize_keys
|
7
|
+
h = map do |k, v|
|
8
|
+
v_sym = v.instance_of?(Hash) ? v.symbolize_keys : v
|
9
|
+
[k.to_sym, v_sym]
|
10
|
+
end
|
11
|
+
|
12
|
+
h.to_h
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'console_logger'
|
4
|
+
|
5
|
+
module Kramdown
|
6
|
+
module PlantUml
|
7
|
+
# Provides theming support for PlantUML
|
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
|
+
class << self
|
49
|
+
def init
|
50
|
+
inner = nil
|
51
|
+
|
52
|
+
begin
|
53
|
+
require 'jekyll'
|
54
|
+
inner = Jekyll.logger
|
55
|
+
rescue LoadError
|
56
|
+
inner = ConsoleLogger.new level
|
57
|
+
end
|
58
|
+
|
59
|
+
Logger.new inner
|
60
|
+
end
|
61
|
+
|
62
|
+
def level
|
63
|
+
@level ||= level_from_env
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def level_from_env
|
69
|
+
return :debug if BoolEnv.new('DEBUG').true?
|
70
|
+
return :debug if BoolEnv.new('VERBOSE').true?
|
71
|
+
|
72
|
+
:warn
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
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
|