kramdown-plantuml 1.1.3 → 1.1.7

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 51cbb0be0b06278afe3b3d1eb572190a9f7a04fc869454b023854d5d8012e596
4
- data.tar.gz: 0e7cb4345aeab6972d3b0009b71ddc714f046f5b558ae1d37b334697af39575b
3
+ metadata.gz: 178996116d7a833c324db54da1b3c367fe13c1d55fabc47026df12bec25b6f9d
4
+ data.tar.gz: d5dc3e4824ab5095b42b33e4b01cc6cb38735fe0bb220472f02e8014f069261b
5
5
  SHA512:
6
- metadata.gz: c18e9c35a4fef278f506106c1365839e7f58b0b45c8b352912187cd324df373b342400e56f51b9c13278ab199fd5fb6101c63cd02aa25ce9efef07722d7c517a
7
- data.tar.gz: d822db2c31c38db0f7ce0a5b92221ebf30a55be1f5d011141199d07d94a01b5ddba99a1ba127d13b88219f6135a384d90741315b6e00b88d0e72c20fa1220d2f
6
+ metadata.gz: 5dd2e36fc7b66a4a8948ba801d75107c04fedbbb612fe525cabac758de15e3908368999d8779126a082dfcef70f990194c3abf0bace90eea019b182e3d26626c
7
+ data.tar.gz: 166be327fab188558c365c5284739d57ed7b851ce953e616b98d7f9002a20f89ab6af7527134a148eefdf547c4465adfe469d597eb8919af26a51cf3615e2b57
data/.github/mergify.yml CHANGED
@@ -17,6 +17,7 @@ pull_request_rules:
17
17
  - name: Thank contributor
18
18
  conditions:
19
19
  - merged
20
+ - -author~=^.*\[bot\]$
20
21
  actions:
21
22
  comment:
22
23
  message: "Thank you @{{author}} for your contribution!"
@@ -1,6 +1,73 @@
1
1
  #!/usr/bin/env bash
2
2
  set -o errexit # Abort if any command fails
3
3
 
4
- gem_build_name=$(gem build kramdown-plantuml.gemspec | awk '/File/ {print $2}')
5
- echo "Gem filename: '${gem_build_name}'"
6
- echo "::set-output name=name::${gem_build_name}"
4
+ me=$(basename "$0")
5
+ help_message="\
6
+ Usage:
7
+ ${me} [--ref <ref>] [--verbose]
8
+ ${me} --help
9
+ Arguments:
10
+ -r, --ref The Git reference that is being built.
11
+ -h, --help Displays this help screen.
12
+ -v, --verbose Increase verbosity. Useful for debugging."
13
+
14
+ parse_args() {
15
+ while : ; do
16
+ if [[ $1 = "-h" || $1 = "--help" ]]; then
17
+ echo "${help_message}"
18
+ return 0
19
+ elif [[ $1 = "-v" || $1 = "--verbose" ]]; then
20
+ verbose=true
21
+ shift
22
+ elif [[ $1 = "-r" || $1 = "--ref" ]]; then
23
+ ref=${2// }
24
+
25
+ if [[ "${ref}" = "--"* ]]; then
26
+ ref=""
27
+ shift 1
28
+ else
29
+ shift 2
30
+ fi
31
+ else
32
+ break
33
+ fi
34
+ done
35
+ }
36
+
37
+ # Echo expanded commands as they are executed (for debugging)
38
+ enable_expanded_output() {
39
+ if [ "${verbose}" = true ]; then
40
+ set -o xtrace
41
+ set +o verbose
42
+ export VERBOSE=true
43
+ fi
44
+ }
45
+
46
+ add_coverage() {
47
+ # If we're not building a tag, bootstrap code coverage.
48
+ if [[ "${ref}" != "refs/tags/"* ]]; then
49
+ [[ "${verbose}" = true ]] && echo "Bootstrapping code coverage."
50
+ export COVER=true
51
+ export COVERAGE=true
52
+ printf "require 'simplecov'\nSimpleCov.start\n" >> lib/kramdown-plantuml.rb
53
+ elif [[ "${verbose}" = true ]]; then
54
+ echo "Skipping coverage report since a tag ref was pushed."
55
+ fi
56
+ }
57
+
58
+ build_gem() {
59
+ gem_build_name=$(gem build kramdown-plantuml.gemspec | awk '/File/ {print $2}')
60
+
61
+ [[ "${verbose}" = true ]] && echo "Gem filename: '${gem_build_name}'"
62
+
63
+ echo "::set-output name=name::${gem_build_name}"
64
+ }
65
+
66
+ main() {
67
+ parse_args "$@"
68
+ enable_expanded_output
69
+ add_coverage
70
+ build_gem
71
+ }
72
+
73
+ main "$@"
@@ -6,7 +6,7 @@ me=$(basename "$0")
6
6
 
7
7
  help_message="\
8
8
  Usage:
9
- ${me} --workdir <workdir> [--gemdir <gemdir> | --version <version> --token <token>] [--verbose]
9
+ ${me} --workdir <workdir> [--gemdir <gemdir> | --version <version> --token <token>] [--verbose] [--theme <name> [--theme-directory <path>]]
10
10
  ${me} --help
11
11
  Arguments:
12
12
  -w, --workdir <workdir> The path to the working directory.
@@ -14,6 +14,8 @@ Arguments:
14
14
  -v, --version <version> The version of the Gem to test.
15
15
  -t, --token <token> The GitHub token to use for retrieving the gem
16
16
  from the GitHub Package Registry.
17
+ -T, --theme-name <name> The theme name to use for the test.
18
+ -p, --theme-directory <path> The directory in which the [--theme-name] is placed.
17
19
  -h, --help Displays this help screen.
18
20
  -v, --verbose Increase verbosity. Useful for debugging."
19
21
 
@@ -52,6 +54,24 @@ parse_args() {
52
54
  else
53
55
  shift 2
54
56
  fi
57
+ elif [[ $1 = "-T" || $1 = "--theme-name" ]]; then
58
+ theme_name=${2// }
59
+
60
+ if [[ "${theme_name}" = "--"* ]]; then
61
+ theme_name=""
62
+ shift 1
63
+ else
64
+ shift 2
65
+ fi
66
+ elif [[ $1 = "-p" || $1 = "--theme-directory" ]]; then
67
+ theme_directory=${2// }
68
+
69
+ if [[ "${theme_directory}" = "--"* ]]; then
70
+ theme_directory=""
71
+ shift 1
72
+ else
73
+ shift 2
74
+ fi
55
75
  elif [[ $1 = "-w" || $1 = "--workdir" ]]; then
56
76
  workdir=${2// }
57
77
 
@@ -67,22 +87,29 @@ parse_args() {
67
87
  done
68
88
 
69
89
  if [[ -z "${workdir}" ]]; then
70
- echo "Missing required argument: --workdir <workdir>."
71
- echo "${help_message}"
90
+ echo "Missing required argument: --workdir <workdir>." >&2
91
+ echo "${help_message}" >&2
72
92
  return 1
73
93
  fi
74
94
 
75
95
  if [[ (-z "${gemdir}" && -z "${token}") || (-n "${gemdir}" && -n "${token}") ]]; then
76
- echo "Missing or invalid required arguments: --gemdir <gem-path> or --token <token>."
77
- echo "Either [--gemdir] or [--token] needs to be provided, but not both."
96
+ echo "Missing or invalid required arguments: --gemdir <gem-path> or --token <token>." >&2
97
+ echo "Either [--gemdir] or [--token] needs to be provided, but not both." >&2
78
98
  echo "${help_message}"
79
99
  return 1
80
100
  fi
81
101
 
82
102
  if [[ (-n "${version}" && -z "${token}") || (-z "${version}" && -n "${token}") ]]; then
83
- echo "Missing or invalid required arguments: --version <gem-path> and --token <token>."
84
- echo "When either argument is present, both must be."
85
- echo "${help_message}"
103
+ echo "Missing or invalid required arguments: --version <gem-path> and --token <token>." >&2
104
+ echo "When either argument is present, both must be." >&2
105
+ echo "${help_message}" >&2
106
+ return 1
107
+ fi
108
+
109
+ if [[ -z "${theme_name}" && -n "${theme_directory}" ]]; then
110
+ echo "Missing or invalid required arguments: --theme-name <name>." >&2
111
+ echo "[--theme-name] is required when [--theme-directory] is provided." >&2
112
+ echo "${help_message}" >&2
86
113
  return 1
87
114
  fi
88
115
  }
@@ -101,19 +128,37 @@ test_gem() {
101
128
 
102
129
  cd "${workdir}"
103
130
 
104
- gem install bundler
131
+ # Recreate Gemfile
132
+ printf "# frozen_string_literal: true\nsource 'https://rubygems.org'\ngem 'jekyll'\ngem 'simplecov'\n" > Gemfile
105
133
 
106
134
  if [[ -n "${token}" ]]; then
107
135
  # A non-empty $token means we should install the Gem from GPR
108
136
  repository="https://rubygems.pkg.github.com/swedbankpay"
109
137
  bundle config "${repository}" "SwedbankPay:${token}"
110
- printf "source '%s' do\n\tgem 'kramdown-plantuml', '%s'\nend" "${repository}" "${version}" >> Gemfile
138
+ printf "source '%s' do\n\tgem 'kramdown-plantuml', '%s'\nend\n" "${repository}" "${version}" >> Gemfile
139
+ else
140
+ printf "gem 'kramdown-plantuml', path: '%s'\n" "${gemdir}" >> Gemfile
141
+ fi
142
+
143
+ # Recreate _config.yml
144
+ printf "plugins:\n- kramdown-plantuml\n" > _config.yml
145
+
146
+ if [[ -n "${theme_name}" ]]; then
147
+ printf "kramdown:\n plantuml:\n theme:\n name: %s\n" "${theme_name}" >> _config.yml
148
+ class="plantuml theme-${theme_name}"
111
149
  else
112
- echo "gem 'kramdown-plantuml', path: '${gemdir}'" >> Gemfile
150
+ class='plantuml'
151
+ fi
152
+
153
+ if [[ -n "${theme_directory}" ]]; then
154
+ printf " directory: %s\n" "${theme_directory}" >> _config.yml
113
155
  fi
114
156
 
115
157
  if [[ "${verbose}" = true ]]; then
158
+ printf "\nGemfile:\n"
116
159
  cat Gemfile
160
+ printf "\n_config.yml\n"
161
+ cat _config.yml
117
162
  jekyll_build_args+=(--verbose)
118
163
  fi
119
164
 
@@ -122,7 +167,7 @@ test_gem() {
122
167
 
123
168
  file="${workdir}/_site/index.html"
124
169
 
125
- file_contains "${file}" "class=\"plantuml theme-spacelab\""
170
+ file_contains "${file}" "class=\"${class}\""
126
171
  file_contains "${file}" "<svg"
127
172
  file_contains "${file}" "<ellipse"
128
173
  file_contains "${file}" "<polygon"
@@ -91,20 +91,51 @@ jobs:
91
91
  - name: rubocop
92
92
  run: bundle exec rubocop --fail-level warning --display-only-fail-level-offenses
93
93
 
94
- - name: Test with Rake
95
- run: bundle exec rake
96
-
97
94
  - name: RSPec (debug)
98
95
  env:
99
96
  DEBUG: 1
100
- run: bundle exec rspec --tag debug
97
+ run: bundle exec rspec --format documentation --tag debug
98
+
99
+ - name: Upload code coverage (debug)
100
+ uses: actions/upload-artifact@v2
101
+ with:
102
+ name: rspec-debug-coverage
103
+ path: ./coverage
104
+
105
+ - name: Codecov upload (debug)
106
+ run: bundle exec rake codecov:upload || echo 'Codecov upload failed'
107
+
108
+ - name: Test with Rake
109
+ run: bundle exec rake
110
+
111
+ - name: Upload code coverage
112
+ uses: actions/upload-artifact@v2
113
+ with:
114
+ name: rspec-coverage
115
+ path: ./coverage
101
116
 
102
117
  - name: Codecov upload
103
118
  run: bundle exec rake codecov:upload || echo 'Codecov upload failed'
104
119
 
120
+ - name: RSPec (Jekyll)
121
+ run: |
122
+ echo "gem 'jekyll', require: false, group: :test" >> Gemfile
123
+ bundle install
124
+ bundle exec rspec --format documentation --tag jekyll
125
+ git checkout HEAD -- Gemfile
126
+
127
+ - name: Upload code coverage (Jekyll)
128
+ uses: actions/upload-artifact@v2
129
+ with:
130
+ name: rspec-jekyll-coverage
131
+ path: ./coverage
132
+
133
+ - name: Codecov upload (Jekyll)
134
+ run: bundle exec rake codecov:upload || echo 'Codecov upload failed'
135
+
105
136
  - name: Build gem
106
137
  id: gem
107
- run: .github/scripts/build-gem.sh
138
+ run: .github/scripts/build-gem.sh --ref ${{ github.ref }} --verbose
108
139
 
109
140
  - name: Upload gem
110
141
  uses: actions/upload-artifact@v2-preview
@@ -116,7 +147,16 @@ jobs:
116
147
  run: .github/scripts/inspect-gem.sh --gem "${{ github.workspace }}/${{ steps.gem.outputs.name }}" --verbose
117
148
 
118
149
  - name: Test gem
119
- run: .github/scripts/test-gem.sh --workdir "${{ github.workspace }}/spec/fixture" --gemdir "${{ github.workspace }}" --verbose
150
+ run: .github/scripts/test-gem.sh --workdir "${{ github.workspace }}/spec/examples" --gemdir "${{ github.workspace }}" --verbose
151
+
152
+ - name: Upload code coverage (gem)
153
+ uses: actions/upload-artifact@v2
154
+ with:
155
+ name: gem-coverage
156
+ path: ./coverage
157
+
158
+ - name: Codecov upload (gem)
159
+ run: bundle exec rake codecov:upload || echo 'Codecov upload failed'
120
160
 
121
161
  publish-dev:
122
162
  needs: [version, gem]
@@ -150,15 +190,21 @@ jobs:
150
190
  - name: Publish to GPR
151
191
  run: .github/scripts/publish-gem.sh --gem ${{ needs.gem.outputs.name }} --token "${{ secrets.GPR_TOKEN }}" --owner SwedbankPay --verbose
152
192
 
153
- - name: Test gem
154
- run: .github/scripts/test-gem.sh --workdir "${{ github.workspace }}/spec/fixture" --version ${{ needs.version.outputs.version }} --token "${{ secrets.GPR_TOKEN }}" --verbose
193
+ - name: Test gem (no theme)
194
+ run: .github/scripts/test-gem.sh --workdir "${{ github.workspace }}/spec/examples" --version ${{ needs.version.outputs.version }} --token "${{ secrets.GPR_TOKEN }}" --verbose
195
+
196
+ - name: Test gem (built-in theme)
197
+ run: .github/scripts/test-gem.sh --workdir "${{ github.workspace }}/spec/examples" --version ${{ needs.version.outputs.version }} --token "${{ secrets.GPR_TOKEN }}" --verbose --theme-name spacelab
198
+
199
+ - name: Test gem (custom theme)
200
+ run: .github/scripts/test-gem.sh --workdir "${{ github.workspace }}/spec/examples" --version ${{ needs.version.outputs.version }} --token "${{ secrets.GPR_TOKEN }}" --verbose --theme-name c2a3b0 --theme-directory "${{ github.workspace }}/spec/examples"
155
201
 
156
202
  - name: Upload Jekyll site
157
203
  uses: actions/upload-artifact@v2-preview
158
204
  if: always()
159
205
  with:
160
206
  name: site
161
- path: ${{ github.workspace }}/spec/fixture/_site
207
+ path: ${{ github.workspace }}/spec/examples/_site
162
208
 
163
209
  publish-prod:
164
210
  needs: [version, gem]
data/README.md CHANGED
@@ -6,6 +6,7 @@
6
6
  [![No PlantUML][no-plantuml-badge]][no-plantuml-workflow]
7
7
  [![Shell][shell-badge]][shell-workflow]
8
8
  [![Codecov][codecov-badge]][codecov]
9
+ [![Codacy Badge][codacy-badge]][codacy]
9
10
  [![License][license-badge]][license]
10
11
  [![CLA assistant][cla-badge]][cla]
11
12
  [![Contributor Covenant][coc-badge]][coc]
@@ -129,6 +130,20 @@ kramdown:
129
130
  directory: path/to/themes
130
131
  ```
131
132
 
133
+ ### Errors
134
+
135
+ By default, `kramdown-plantuml` will raise an error and crash if something goes
136
+ wrong during processing. This can be circumvented by setting the `raise_errors`
137
+ configuration key to `false`:
138
+
139
+ ```yaml
140
+ kramdown:
141
+ plantuml:
142
+ raise_errors: false
143
+ ```
144
+
145
+ The default value of `raise_errors` is `true`.
146
+
132
147
  ## Contributing
133
148
 
134
149
  Bug reports and pull requests are welcome on [GitHub][github]. This project is
@@ -180,6 +195,8 @@ agreement][cla].
180
195
  [clone]: https://docs.github.com/en/free-pro-team@latest/github/creating-cloning-and-archiving-repositories/cloning-a-repository
181
196
  [coc-badge]: https://img.shields.io/badge/Contributor%20Covenant-v2.0%20adopted-ff69b4.svg
182
197
  [coc]: ./CODE_OF_CONDUCT.md
198
+ [codacy-badge]: https://app.codacy.com/project/badge/Grade/de72385f4ca444c18819a3ce8a506638
199
+ [codacy]: https://www.codacy.com/gh/SwedbankPay/kramdown-plantuml/dashboard?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=SwedbankPay/kramdown-plantuml&amp;utm_campaign=Badge_Grade
183
200
  [codecov-badge]: https://codecov.io/gh/SwedbankPay/kramdown-plantuml/branch/main/graph/badge.svg?token=U3QJLVG3HY
184
201
  [codecov]: https://codecov.io/gh/SwedbankPay/kramdown-plantuml/
185
202
  [diagram-svg]: ./spec/examples/diagram.svg
data/Rakefile CHANGED
@@ -6,7 +6,7 @@ require 'rspec/core/rake_task'
6
6
 
7
7
  RSpec::Core::RakeTask.new(:spec) do |t|
8
8
  t.pattern = Dir.glob('spec/**/*_spec.rb')
9
- t.rspec_opts = '--format documentation --tag ~no_plantuml --tag ~no_java --tag ~debug'
9
+ t.rspec_opts = '--format documentation --tag ~no_plantuml --tag ~no_java --tag ~debug --tag ~jekyll'
10
10
  end
11
11
 
12
12
  namespace :maven do
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'lib/which'
3
+ require_relative 'lib/kramdown-plantuml/which'
4
4
  require_relative 'lib/kramdown-plantuml/version'
5
5
 
6
6
  Gem::Specification.new do |spec|
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'version'
4
+ require_relative 'theme'
5
+ require_relative 'options'
6
+ require_relative 'plantuml_error'
7
+ require_relative 'log_wrapper'
8
+ require_relative 'executor'
9
+
10
+ module Kramdown
11
+ module PlantUml
12
+ # Represents a PlantUML diagram that can be converted to SVG.
13
+ class Diagram
14
+ attr_reader :theme, :plantuml, :result
15
+
16
+ def initialize(plantuml, options)
17
+ raise ArgumentError, 'options cannot be nil' if options.nil?
18
+ raise ArgumentError, "options must be a '#{Options}'." unless options.is_a?(Options)
19
+
20
+ @plantuml = plantuml
21
+ @options = options
22
+ @theme = Theme.new(options)
23
+ @logger = LogWrapper.init
24
+ @executor = Executor.new
25
+ @logger.warn 'PlantUML diagram is empty' if @plantuml.nil? || @plantuml.empty?
26
+ end
27
+
28
+ def convert_to_svg
29
+ return @svg unless @svg.nil?
30
+ return @plantuml if @plantuml.nil? || @plantuml.empty?
31
+
32
+ @plantuml = @theme.apply(@plantuml)
33
+ log(plantuml)
34
+ @result = @executor.execute(self)
35
+ @result.validate
36
+ @svg = wrap(@result.without_xml_prologue)
37
+ rescue StandardError => e
38
+ raise e if @options.raise_errors?
39
+
40
+ @logger.error e.to_s
41
+ end
42
+
43
+ private
44
+
45
+ def wrap(svg)
46
+ theme_class = @theme.name ? "theme-#{@theme.name}" : ''
47
+ class_name = "plantuml #{theme_class}".strip
48
+
49
+ wrapper_element_start = "<div class=\"#{class_name}\">"
50
+ wrapper_element_end = '</div>'
51
+
52
+ "#{wrapper_element_start}#{svg}#{wrapper_element_end}"
53
+ end
54
+
55
+ def log(plantuml)
56
+ @logger.debug 'PlantUML converting diagram:'
57
+ @logger.debug_multiline plantuml
58
+ end
59
+ end
60
+ end
61
+ end
@@ -1,8 +1,8 @@
1
- # frozen_string_literal: false
1
+ # frozen_string_literal: true
2
2
 
3
3
  require 'open3'
4
- require_relative '../which'
5
- require_relative 'logger'
4
+ require_relative 'which'
5
+ require_relative 'log_wrapper'
6
6
  require_relative 'plantuml_result'
7
7
 
8
8
  module Kramdown
@@ -10,38 +10,52 @@ module Kramdown
10
10
  # Executes the PlantUML Java application.
11
11
  class Executor
12
12
  def initialize
13
- @logger = Logger.init
13
+ @logger = LogWrapper.init
14
+
15
+ java_location = Which.which('java')
16
+
17
+ raise IOError, 'Java can not be found' if java_location.nil?
18
+
19
+ @logger.debug "Java found: #{java_location}"
14
20
  @plantuml_jar_file = find_plantuml_jar_file
15
21
 
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
22
  raise IOError, "'#{@plantuml_jar_file}' does not exist" unless File.exist? @plantuml_jar_file
23
+
24
+ @logger.debug "plantuml.jar found: #{@plantuml_jar_file}"
19
25
  end
20
26
 
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
27
+ def execute(diagram)
28
+ raise ArgumentError, 'diagram cannot be nil' if diagram.nil?
29
+ raise ArgumentError, "diagram must be a #{Diagram}" unless diagram.is_a?(Diagram)
30
+
31
+ cmd = "java -Djava.awt.headless=true -jar #{@plantuml_jar_file} -tsvg -failfast -pipe #{debug_args}"
28
32
 
29
- @logger.debug " kramdown-plantuml: Executing '#{cmd}'."
33
+ @logger.debug "Executing '#{cmd}'."
30
34
 
31
- stdout, stderr, status = Open3.capture3 cmd, stdin_data: stdin
35
+ stdout, stderr, status = Open3.capture3 cmd, stdin_data: diagram.plantuml
32
36
 
33
- @logger.debug " kramdown-plantuml: PlantUML exit code '#{status.exitstatus}'."
37
+ @logger.debug "PlantUML exit code '#{status.exitstatus}'."
34
38
 
35
- PlantUmlResult.new(stdout, stderr, status)
39
+ PlantUmlResult.new(diagram, stdout, stderr, status.exitstatus)
36
40
  end
37
41
 
38
42
  private
39
43
 
40
44
  def find_plantuml_jar_file
41
45
  dir = File.dirname __dir__
42
- jar_glob = File.join dir, '../bin/**/plantuml*.jar'
46
+ bin_dir = File.expand_path File.join dir, '../bin'
47
+ jar_glob = File.join bin_dir, '/**/plantuml*.jar'
43
48
  first_jar = Dir[jar_glob].first
44
- File.expand_path first_jar unless first_jar.nil?
49
+
50
+ raise IOError, "No 'plantuml.jar' file could be found within the '#{bin_dir}' directory." if first_jar.nil?
51
+
52
+ File.expand_path first_jar
53
+ end
54
+
55
+ def debug_args
56
+ return ' -verbose' if @logger.debug?
57
+
58
+ ' -nometadata'
45
59
  end
46
60
  end
47
61
  end
@@ -0,0 +1,99 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+ require 'English'
5
+ require 'rexml/document'
6
+ require_relative 'log_wrapper'
7
+ require_relative 'diagram'
8
+
9
+ module Kramdown
10
+ module PlantUml
11
+ # Provides an instance of Jekyll if available.
12
+ module JekyllProvider
13
+ class << self
14
+ def jekyll
15
+ return @jekyll if defined? @jekyll
16
+
17
+ @jekyll = load_jekyll
18
+ end
19
+
20
+ def install
21
+ return @installed = false if jekyll.nil?
22
+
23
+ logger.debug 'Jekyll detected, hooking into :site:post_render'
24
+
25
+ Jekyll::Hooks.register :site, :post_render do |site|
26
+ logger.debug ':site:post_render triggered.'
27
+
28
+ site.pages.each do |page|
29
+ page.output = replace_needles(page.output)
30
+ end
31
+ end
32
+
33
+ @installed = true
34
+ end
35
+
36
+ def installed?
37
+ @installed
38
+ end
39
+
40
+ def needle(plantuml, options)
41
+ hash = { 'plantuml' => plantuml, 'options' => options.to_h }
42
+
43
+ <<~NEEDLE
44
+ <!--#kramdown-plantuml.start#-->
45
+ #{hash.to_json}
46
+ <!--#kramdown-plantuml.end#-->
47
+ NEEDLE
48
+ rescue StandardError => e
49
+ raise e if options.raise_errors?
50
+
51
+ puts e
52
+ logger.error 'Error while placing needle.'
53
+ logger.error e.to_s
54
+ logger.debug_multiline plantuml
55
+ end
56
+
57
+ private
58
+
59
+ def replace_needles(html)
60
+ return html if html.nil? || html.empty? || !html.is_a?(String)
61
+
62
+ html.gsub(/<!--#kramdown-plantuml\.start#-->(?<json>.*?)<!--#kramdown-plantuml\.end#-->/m) do
63
+ json = $LAST_MATCH_INFO[:json]
64
+ return replace_needle(json)
65
+ rescue StandardError => e
66
+ raise e if options.raise_errors?
67
+
68
+ logger.error "Error while replacing needle: #{e.inspect}"
69
+ end
70
+ end
71
+
72
+ def replace_needle(json)
73
+ hash = JSON.parse(json)
74
+ encoded_plantuml = hash['plantuml']
75
+ plantuml = decode_html_entities(encoded_plantuml)
76
+ options = ::Kramdown::PlantUml::Options.new({ plantuml: hash['options'] })
77
+ diagram = ::Kramdown::PlantUml::Diagram.new(plantuml, options)
78
+ diagram.convert_to_svg
79
+ end
80
+
81
+ def decode_html_entities(encoded_plantuml)
82
+ doc = REXML::Document.new "<plantuml>#{encoded_plantuml}</plantuml>"
83
+ doc.root.text
84
+ end
85
+
86
+ def load_jekyll
87
+ require 'jekyll'
88
+ ::Jekyll
89
+ rescue LoadError
90
+ nil
91
+ end
92
+
93
+ def logger
94
+ @logger ||= ::Kramdown::PlantUml::LogWrapper.init
95
+ end
96
+ end
97
+ end
98
+ end
99
+ end
@@ -1,11 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'console_logger'
4
+ require_relative 'jekyll_provider'
4
5
 
5
6
  module Kramdown
6
7
  module PlantUml
7
8
  # Logs stuff
8
- class Logger
9
+ class LogWrapper
9
10
  def initialize(logger)
10
11
  raise ArgumentError, 'logger cannot be nil' if logger.nil?
11
12
  raise ArgumentError, 'logger must respond to #debug' unless logger.respond_to? :debug
@@ -17,28 +18,28 @@ module Kramdown
17
18
  end
18
19
 
19
20
  def debug(message)
20
- @logger.debug message
21
+ write :debug, message
21
22
  end
22
23
 
23
- def debug_with_prefix(prefix, string)
24
- return if string.nil? || string.empty?
24
+ def debug_multiline(multiline_string)
25
+ return if multiline_string.nil? || multiline_string.empty?
25
26
 
26
- lines = string.lines
27
+ lines = multiline_string.lines
27
28
  lines.each do |line|
28
- @logger.debug "#{prefix}#{line.rstrip}"
29
+ write :debug, line.rstrip
29
30
  end
30
31
  end
31
32
 
32
33
  def info(message)
33
- @logger.info message
34
+ write :info, message
34
35
  end
35
36
 
36
37
  def warn(message)
37
- @logger.warn message
38
+ write :warn, message
38
39
  end
39
40
 
40
41
  def error(message)
41
- @logger.error message
42
+ write :error, message
42
43
  end
43
44
 
44
45
  def debug?
@@ -51,16 +52,9 @@ module Kramdown
51
52
 
52
53
  class << self
53
54
  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
55
+ inner = JekyllProvider.jekyll ? JekyllProvider.jekyll.logger : nil
56
+ inner ||= ConsoleLogger.new(level)
57
+ new inner
64
58
  end
65
59
 
66
60
  def level
@@ -79,6 +73,10 @@ module Kramdown
79
73
 
80
74
  private
81
75
 
76
+ def write(level, message)
77
+ @logger.public_send(level, " kramdown-plantuml: #{message}")
78
+ end
79
+
82
80
  def level_from_logger
83
81
  return @logger.level if @logger.respond_to? :level
84
82
 
@@ -0,0 +1,91 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'log_wrapper'
4
+
5
+ module Kramdown
6
+ module PlantUml
7
+ # Options for PlantUML processing
8
+ class Options
9
+ attr_reader :theme_name, :theme_directory
10
+
11
+ def initialize(options_hash = {})
12
+ @logger = LogWrapper.init
13
+ @options = massage(options_hash)
14
+ @raise_errors = extract_raise_errors(@options)
15
+ extract_theme_options(@options)
16
+ end
17
+
18
+ def raise_errors?
19
+ @raise_errors
20
+ end
21
+
22
+ def to_h
23
+ @options
24
+ end
25
+
26
+ private
27
+
28
+ def boolean(value, default_value)
29
+ return value if [true, false].include? value
30
+ return default_value if value.nil?
31
+
32
+ s = value.to_s.strip
33
+ return true if %w[true yes 1].select { |v| v.casecmp(s).zero? }.any?
34
+ return false if %w[false no 0].select { |v| v.casecmp(s).zero? }.any?
35
+
36
+ default_value
37
+ end
38
+
39
+ def extract_plantuml_options(options_hash)
40
+ return options_hash[:plantuml] if options_hash.key?(:plantuml)
41
+ return options_hash['plantuml'] if options_hash.key?('plantuml')
42
+
43
+ {}
44
+ end
45
+
46
+ def extract_theme_options(options)
47
+ return if options.empty? || !options.key?(:theme)
48
+
49
+ theme = options[:theme] || {}
50
+
51
+ unless theme.is_a?(Hash)
52
+ @logger.warn ":theme is not a Hash: #{theme}"
53
+ return
54
+ end
55
+
56
+ @theme_name = theme.key?(:name) ? theme[:name] : nil
57
+ @theme_directory = theme.key?(:directory) ? theme[:directory] : nil
58
+ end
59
+
60
+ def extract_raise_errors(options)
61
+ if options.key?(:raise_errors)
62
+ raise_errors = options[:raise_errors]
63
+ return boolean(raise_errors, true)
64
+ end
65
+
66
+ true
67
+ end
68
+
69
+ def massage(options_hash)
70
+ if options_hash.nil? || !options_hash.is_a?(Hash) || options_hash.empty?
71
+ @logger.debug 'No options provided'
72
+ return {}
73
+ end
74
+
75
+ plantuml_options = extract_plantuml_options(options_hash)
76
+ symbolize_keys(plantuml_options)
77
+ end
78
+
79
+ def symbolize_keys(options)
80
+ return options if options.nil? || options.empty?
81
+
82
+ array = options.map do |key, value|
83
+ value = value.is_a?(Hash) ? symbolize_keys(value) : value
84
+ [key.to_sym, value]
85
+ end
86
+
87
+ array.to_h
88
+ end
89
+ end
90
+ end
91
+ end
@@ -1,32 +1,69 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'plantuml_result'
4
+
3
5
  module Kramdown
4
6
  module PlantUml
5
7
  # PlantUML Error
6
8
  class PlantUmlError < StandardError
7
- def initialize(plantuml, stderr, exitcode)
9
+ def initialize(result)
10
+ raise ArgumentError, 'result cannot be nil' if result.nil?
11
+ raise ArgumentError, "result must be a #{PlantUmlResult}" unless result.is_a?(PlantUmlResult)
12
+
13
+ super create_message(result)
14
+ end
15
+
16
+ private
17
+
18
+ def create_message(result)
19
+ header = header(result).gsub("\n", ' ').strip
20
+ plantuml = plantuml(result)
21
+ result = result(result)
8
22
  message = <<~MESSAGE
9
- Conversion of the following PlantUML diagram failed:
23
+ #{header}
10
24
 
11
25
  #{plantuml}
12
26
 
13
- The error received from PlantUML was:
14
-
15
- Exit code: #{exitcode}
16
- #{stderr}
27
+ #{result}
17
28
  MESSAGE
18
29
 
19
- super message
30
+ message.strip
20
31
  end
21
32
 
22
- def self.should_raise?(exitcode, stderr)
23
- return false if exitcode.zero?
33
+ def header(result)
34
+ if theme_not_found?(result) && !result.diagram.nil? && !result.diagram.theme.nil?
35
+ return <<~HEADER
36
+ Conversion of the following PlantUML result failed because the
37
+ theme '#{result.diagram.theme.name}' can't be found in the directory
38
+ '#{result.diagram.theme.directory}':
39
+ HEADER
40
+ end
41
+
42
+ 'Conversion of the following PlantUML result failed:'
43
+ end
44
+
45
+ def theme_not_found?(result)
46
+ !result.nil? \
47
+ && !result.stderr.nil? \
48
+ && result.stderr.include?('NullPointerException') \
49
+ && result.stderr.include?('getTheme')
50
+ end
51
+
52
+ def plantuml(result)
53
+ return nil if result.nil? || result.diagram.nil?
54
+
55
+ result.diagram.plantuml
56
+ end
57
+
58
+ def result(result)
59
+ return nil if result.nil?
60
+
61
+ <<~RESULT
62
+ The error received from PlantUML was:
24
63
 
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:')
64
+ Exit code: #{result.exitcode}
65
+ #{result.stderr}
66
+ RESULT
30
67
  end
31
68
  end
32
69
  end
@@ -1,19 +1,26 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'logger'
3
+ require_relative 'log_wrapper'
4
4
  require_relative 'plantuml_error'
5
+ require_relative 'diagram'
5
6
 
6
7
  module Kramdown
7
8
  module PlantUml
8
9
  # Executes the PlantUML Java application.
9
10
  class PlantUmlResult
10
- attr_reader :stdout, :stderr, :exitcode
11
+ attr_reader :diagram, :stdout, :stderr, :exitcode
11
12
 
12
- def initialize(stdout, stderr, status)
13
+ def initialize(diagram, stdout, stderr, exitcode)
14
+ raise ArgumentError, 'diagram cannot be nil' if diagram.nil?
15
+ raise ArgumentError, "diagram must be a #{Diagram}" unless diagram.is_a?(Diagram)
16
+ raise ArgumentError, 'exitcode cannot be nil' if exitcode.nil?
17
+ raise ArgumentError, "exitcode must be a #{Integer}" unless exitcode.is_a?(Integer)
18
+
19
+ @diagram = diagram
13
20
  @stdout = stdout
14
21
  @stderr = stderr
15
- @exitcode = status.exitstatus
16
- @logger = Logger.init
22
+ @exitcode = exitcode
23
+ @logger = LogWrapper.init
17
24
  end
18
25
 
19
26
  def without_xml_prologue
@@ -37,13 +44,22 @@ module Kramdown
37
44
  @stdout
38
45
  end
39
46
 
40
- def validate(plantuml)
41
- raise PlantUmlError.new(plantuml, @stderr, @exitcode) if PlantUmlError.should_raise?(@exitcode, @stderr)
47
+ def valid?
48
+ return true if @exitcode.zero? || @stderr.nil? || @stderr.empty?
49
+
50
+ # If stderr is not empty, but contains the string 'CoreText note:',
51
+ # the error is caused by a bug in Java, and should be ignored.
52
+ # Circumvents https://bugs.openjdk.java.net/browse/JDK-8244621
53
+ @stderr.include?('CoreText note:')
54
+ end
55
+
56
+ def validate
57
+ raise PlantUmlError, self unless valid?
42
58
 
43
59
  return if @stderr.nil? || @stderr.empty?
44
60
 
45
- @logger.debug ' kramdown-plantuml: PlantUML log:'
46
- @logger.debug_with_prefix ' kramdown-plantuml: ', @stderr
61
+ @logger.debug 'PlantUML log:'
62
+ @logger.debug_multiline @stderr
47
63
  end
48
64
  end
49
65
  end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: false
2
+
3
+ require_relative 'options'
4
+ require_relative 'log_wrapper'
5
+
6
+ module Kramdown
7
+ module PlantUml
8
+ # Provides theming support for PlantUML
9
+ class Theme
10
+ attr_reader :name, :directory
11
+
12
+ def initialize(options)
13
+ raise ArgumentError, 'options cannot be nil' if options.nil?
14
+ raise ArgumentError, "options must be a '#{Options}'." unless options.is_a?(Options)
15
+
16
+ @logger = LogWrapper.init
17
+ @name = options.theme_name
18
+ @directory = options.theme_directory
19
+ end
20
+
21
+ def apply(plantuml)
22
+ if plantuml.nil? || !plantuml.is_a?(String) || plantuml.empty?
23
+ @logger.debug 'Empty diagram or not a String.'
24
+ return plantuml
25
+ end
26
+
27
+ if @name.nil? || @name.empty?
28
+ @logger.debug 'No theme to apply.'
29
+ return plantuml.strip
30
+ end
31
+
32
+ theme(plantuml)
33
+ end
34
+
35
+ private
36
+
37
+ def theme(plantuml)
38
+ startuml = '@startuml'
39
+ startuml_index = plantuml.index(startuml) + startuml.length
40
+
41
+ return plantuml if startuml_index.nil?
42
+
43
+ theme_string = "\n!theme #{@name}"
44
+ theme_string << " from #{@directory}" unless @directory.nil?
45
+
46
+ @logger.debug "Applying #{theme_string.strip}"
47
+
48
+ /@startuml.*/.match(plantuml) do |match|
49
+ return plantuml.insert match.end(0), theme_string
50
+ end
51
+
52
+ plantuml.strip
53
+ end
54
+ end
55
+ end
56
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Kramdown
4
4
  module PlantUml
5
- VERSION = '1.1.3'
5
+ VERSION = '1.1.7'
6
6
  end
7
7
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Wraps the `which` Unix utility
3
+ # Mimics the `which` Unix utility
4
4
  class Which
5
5
  def self.which(cmd)
6
6
  exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
@@ -10,6 +10,7 @@ class Which
10
10
  return exe if File.executable?(exe) && !File.directory?(exe)
11
11
  end
12
12
  end
13
+
13
14
  nil
14
15
  end
15
16
  end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'kramdown-plantuml/version'
4
- require_relative 'kramdown-plantuml/converter'
5
3
  require_relative 'kramdown_html'
4
+ require_relative 'kramdown-plantuml/jekyll_provider'
5
+
6
+ ::Kramdown::PlantUml::JekyllProvider.install
data/lib/kramdown_html.rb CHANGED
@@ -2,9 +2,11 @@
2
2
 
3
3
  require 'kramdown'
4
4
  require 'kramdown-parser-gfm'
5
- require_relative 'kramdown-plantuml/converter'
6
- require_relative 'kramdown-plantuml/logger'
5
+ require_relative 'kramdown-plantuml/log_wrapper'
7
6
  require_relative 'kramdown-plantuml/plantuml_error'
7
+ require_relative 'kramdown-plantuml/options'
8
+ require_relative 'kramdown-plantuml/diagram'
9
+ require_relative 'kramdown-plantuml/jekyll_provider'
8
10
 
9
11
  module Kramdown
10
12
  module Converter
@@ -14,13 +16,31 @@ module Kramdown
14
16
  alias super_convert_codeblock convert_codeblock
15
17
 
16
18
  def convert_codeblock(element, indent)
17
- return super_convert_codeblock(element, indent) if element.attr['class'] != 'language-plantuml'
19
+ return super_convert_codeblock(element, indent) unless plantuml?(element)
18
20
 
19
- plantuml = element.value
20
- plantuml_options = @options.key?(:plantuml) ? @options[:plantuml] : {}
21
- converter = ::Kramdown::PlantUml::Converter.new(plantuml_options || {})
21
+ jekyll = ::Kramdown::PlantUml::JekyllProvider
22
22
 
23
- converter.convert_plantuml_to_svg(plantuml)
23
+ # If Jekyll is successfully loaded, we'll wait with converting the
24
+ # PlantUML diagram to SVG since a theme may be configured that needs to
25
+ # be copied to the assets directory before the PlantUML conversion can
26
+ # be performed. We therefore place a needle in the haystack that we will
27
+ # convert in the :site:pre_render hook.
28
+ options = ::Kramdown::PlantUml::Options.new(@options)
29
+ return jekyll.needle(element.value, options) if jekyll.installed?
30
+
31
+ convert_plantuml(element.value)
32
+ end
33
+
34
+ private
35
+
36
+ def plantuml?(element)
37
+ element.attr['class'] == 'language-plantuml'
38
+ end
39
+
40
+ def convert_plantuml(plantuml)
41
+ options = ::Kramdown::PlantUml::Options.new(@options)
42
+ diagram = ::Kramdown::PlantUml::Diagram.new(plantuml, options)
43
+ diagram.convert_to_svg
24
44
  end
25
45
  end
26
46
  end
data/pom.xml CHANGED
@@ -10,7 +10,7 @@
10
10
  <dependency>
11
11
  <groupId>net.sourceforge.plantuml</groupId>
12
12
  <artifactId>plantuml</artifactId>
13
- <version>1.2021.9</version>
13
+ <version>1.2021.12</version>
14
14
  </dependency>
15
15
  </dependencies>
16
16
  </project>
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kramdown-plantuml
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.3
4
+ version: 1.1.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Swedbank Pay
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-08-04 00:00:00.000000000 Z
11
+ date: 2021-11-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: kramdown
@@ -166,20 +166,22 @@ files:
166
166
  - LICENSE
167
167
  - README.md
168
168
  - Rakefile
169
- - bin/net/sourceforge/plantuml/plantuml/1.2021.8/plantuml-1.2021.8.jar
169
+ - bin/net/sourceforge/plantuml/plantuml/1.2021.12/plantuml-1.2021.12.jar
170
170
  - kramdown-plantuml.gemspec
171
171
  - lib/kramdown-plantuml.rb
172
172
  - lib/kramdown-plantuml/bool_env.rb
173
173
  - lib/kramdown-plantuml/console_logger.rb
174
- - lib/kramdown-plantuml/converter.rb
174
+ - lib/kramdown-plantuml/diagram.rb
175
175
  - lib/kramdown-plantuml/executor.rb
176
- - lib/kramdown-plantuml/logger.rb
176
+ - lib/kramdown-plantuml/jekyll_provider.rb
177
+ - lib/kramdown-plantuml/log_wrapper.rb
178
+ - lib/kramdown-plantuml/options.rb
177
179
  - lib/kramdown-plantuml/plantuml_error.rb
178
180
  - lib/kramdown-plantuml/plantuml_result.rb
179
- - lib/kramdown-plantuml/themer.rb
181
+ - lib/kramdown-plantuml/theme.rb
180
182
  - lib/kramdown-plantuml/version.rb
183
+ - lib/kramdown-plantuml/which.rb
181
184
  - lib/kramdown_html.rb
182
- - lib/which.rb
183
185
  - pom.xml
184
186
  homepage: https://github.com/SwedbankPay/kramdown-plantuml
185
187
  licenses:
@@ -1,52 +0,0 @@
1
- # frozen_string_literal: true
2
-
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
17
- end
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)
32
- end
33
-
34
- private
35
-
36
- def wrap(svg)
37
- theme_class = @themer.theme_name ? "theme-#{@themer.theme_name}" : ''
38
- class_name = "plantuml #{theme_class}".strip
39
-
40
- wrapper_element_start = "<div class=\"#{class_name}\">"
41
- wrapper_element_end = '</div>'
42
-
43
- "#{wrapper_element_start}#{svg}#{wrapper_element_end}"
44
- end
45
-
46
- def log(plantuml)
47
- @logger.debug ' kramdown-plantuml: PlantUML converting diagram:'
48
- @logger.debug_with_prefix ' kramdown-plantuml: ', plantuml
49
- end
50
- end
51
- end
52
- end
@@ -1,76 +0,0 @@
1
- # frozen_string_literal: false
2
-
3
- require_relative 'logger'
4
-
5
- module Kramdown
6
- module PlantUml
7
- # Provides theming support for PlantUML
8
- class Themer
9
- attr_reader :theme_name, :theme_directory
10
-
11
- def initialize(options = {})
12
- @logger = Logger.init
13
- @theme_name, @theme_directory = theme_options(options)
14
- end
15
-
16
- def apply_theme(plantuml)
17
- if plantuml.nil? || plantuml.empty?
18
- @logger.debug ' kramdown-plantuml: Empty diagram.'
19
- return plantuml
20
- end
21
-
22
- if @theme_name.nil? || @theme_name.empty?
23
- @logger.debug ' kramdown-plantuml: No theme to apply.'
24
- return plantuml
25
- end
26
-
27
- theme(plantuml)
28
- end
29
-
30
- private
31
-
32
- def theme_options(options)
33
- options = symbolize_keys(options)
34
-
35
- @logger.debug " kramdown-plantuml: Options: #{options}"
36
-
37
- return nil if options.nil? || !options.key?(:theme)
38
-
39
- theme = options[:theme] || {}
40
- theme_name = theme.key?(:name) ? theme[:name] : nil
41
- theme_directory = theme.key?(:directory) ? theme[:directory] : nil
42
-
43
- [theme_name, theme_directory]
44
- end
45
-
46
- def symbolize_keys(options)
47
- return options if options.nil?
48
-
49
- array = options.map do |key, value|
50
- value = value.is_a?(Hash) ? symbolize_keys(value) : value
51
- [key.to_sym, value]
52
- end
53
-
54
- array.to_h
55
- end
56
-
57
- def theme(plantuml)
58
- startuml = '@startuml'
59
- startuml_index = plantuml.index(startuml) + startuml.length
60
-
61
- return plantuml if startuml_index.nil?
62
-
63
- theme_string = "\n!theme #{@theme_name}"
64
- theme_string << " from #{@theme_directory}" unless @theme_directory.nil?
65
-
66
- @logger.debug " kramdown-plantuml: Applying #{theme_string.strip}"
67
-
68
- /@startuml.*/.match(plantuml) do |match|
69
- return plantuml.insert match.end(0), theme_string
70
- end
71
-
72
- plantuml
73
- end
74
- end
75
- end
76
- end