kramdown-plantuml 1.1.4 → 1.1.8

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: beba25f229338deced9900f7a611c9040846e562c966de164e88dbb040acadde
4
- data.tar.gz: 8c2aa7aa04a1a6e59a98032e1cc325544a2be7c3bc3cd407cbb3af09babe390c
3
+ metadata.gz: f873d08b8ab86ebe4ea964c30ad59a43a75c28d042d6627af1694d1ff262cbfd
4
+ data.tar.gz: cca59110bbdac25b41dc4c7ef41f9df0f84b17aa4a6da662feab19a73ca61724
5
5
  SHA512:
6
- metadata.gz: fcdfa9c61a9b2c751aeae743edfb58d81c3602e1eb62f6b8993fd11b2372dd6ee271f77737f655967a093c03a90d0ebf3b4865c703b7a5ed2d7b806c5a4d19d5
7
- data.tar.gz: d35a3daea2ab515d0fd788d8b2fb0575c4993e4f25ba3c7ebda02631b8ae8d397dc88917b3809cf732e9b9a5d16bbbfa52cdfa2095a682c68de8d6ed8fba3377
6
+ metadata.gz: bbe10bc2e73c25b0a2bd09651e9bd73b2aeb612fa26f0470df0e9f0477c8f8f69f3c69d428b136826264e975068dc073724fcf4ab5e10b93e59585001983ada8
7
+ data.tar.gz: b74471596aadcf0bde3bf7878864918fb5bd6297172f69b5f9d30c214f84c1f67dfe2c11b7b6e1dc78bfb85c817c0a2c4a26e5bb9c420c519d490b5567b29fe8
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,17 +128,37 @@ test_gem() {
101
128
 
102
129
  cd "${workdir}"
103
130
 
131
+ # Recreate Gemfile
132
+ printf "# frozen_string_literal: true\nsource 'https://rubygems.org'\ngem 'jekyll'\ngem 'simplecov'\n" > Gemfile
133
+
104
134
  if [[ -n "${token}" ]]; then
105
135
  # A non-empty $token means we should install the Gem from GPR
106
136
  repository="https://rubygems.pkg.github.com/swedbankpay"
107
137
  bundle config "${repository}" "SwedbankPay:${token}"
108
- 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
109
139
  else
110
- echo "gem 'kramdown-plantuml', path: '${gemdir}'" >> Gemfile
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}"
149
+ else
150
+ class='plantuml'
151
+ fi
152
+
153
+ if [[ -n "${theme_directory}" ]]; then
154
+ printf " directory: %s\n" "${theme_directory}" >> _config.yml
111
155
  fi
112
156
 
113
157
  if [[ "${verbose}" = true ]]; then
158
+ printf "\nGemfile:\n"
114
159
  cat Gemfile
160
+ printf "\n_config.yml\n"
161
+ cat _config.yml
115
162
  jekyll_build_args+=(--verbose)
116
163
  fi
117
164
 
@@ -120,7 +167,7 @@ test_gem() {
120
167
 
121
168
  file="${workdir}/_site/index.html"
122
169
 
123
- file_contains "${file}" "class=\"plantuml theme-spacelab\""
170
+ file_contains "${file}" "class=\"${class}\""
124
171
  file_contains "${file}" "<svg"
125
172
  file_contains "${file}" "<ellipse"
126
173
  file_contains "${file}" "<polygon"
@@ -94,7 +94,16 @@ jobs:
94
94
  - name: RSPec (debug)
95
95
  env:
96
96
  DEBUG: 1
97
- 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'
98
107
 
99
108
  - name: Test with Rake
100
109
  run: bundle exec rake
@@ -102,15 +111,31 @@ jobs:
102
111
  - name: Upload code coverage
103
112
  uses: actions/upload-artifact@v2
104
113
  with:
105
- name: coverage
114
+ name: rspec-coverage
106
115
  path: ./coverage
107
116
 
108
117
  - name: Codecov upload
109
118
  run: bundle exec rake codecov:upload || echo 'Codecov upload failed'
110
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
+
111
136
  - name: Build gem
112
137
  id: gem
113
- run: .github/scripts/build-gem.sh
138
+ run: .github/scripts/build-gem.sh --ref ${{ github.ref }} --verbose
114
139
 
115
140
  - name: Upload gem
116
141
  uses: actions/upload-artifact@v2-preview
@@ -122,7 +147,16 @@ jobs:
122
147
  run: .github/scripts/inspect-gem.sh --gem "${{ github.workspace }}/${{ steps.gem.outputs.name }}" --verbose
123
148
 
124
149
  - name: Test gem
125
- 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'
126
160
 
127
161
  publish-dev:
128
162
  needs: [version, gem]
@@ -156,15 +190,21 @@ jobs:
156
190
  - name: Publish to GPR
157
191
  run: .github/scripts/publish-gem.sh --gem ${{ needs.gem.outputs.name }} --token "${{ secrets.GPR_TOKEN }}" --owner SwedbankPay --verbose
158
192
 
159
- - name: Test gem
160
- 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"
161
201
 
162
202
  - name: Upload Jekyll site
163
203
  uses: actions/upload-artifact@v2-preview
164
204
  if: always()
165
205
  with:
166
206
  name: site
167
- path: ${{ github.workspace }}/spec/fixture/_site
207
+ path: ${{ github.workspace }}/spec/examples/_site
168
208
 
169
209
  publish-prod:
170
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|
@@ -35,6 +35,7 @@ Gem::Specification.new do |spec|
35
35
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
36
36
  spec.require_paths = ['lib']
37
37
 
38
+ spec.add_dependency 'htmlentities', '~> 4'
38
39
  spec.add_dependency 'kramdown', '~> 2.3'
39
40
  spec.add_dependency 'kramdown-parser-gfm', '~> 1.1'
40
41
  spec.add_dependency 'open3', '~> 0.1'
@@ -2,8 +2,9 @@
2
2
 
3
3
  require_relative 'version'
4
4
  require_relative 'theme'
5
+ require_relative 'options'
5
6
  require_relative 'plantuml_error'
6
- require_relative 'logger'
7
+ require_relative 'log_wrapper'
7
8
  require_relative 'executor'
8
9
 
9
10
  module Kramdown
@@ -12,28 +13,31 @@ module Kramdown
12
13
  class Diagram
13
14
  attr_reader :theme, :plantuml, :result
14
15
 
15
- def initialize(plantuml, options = {})
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
+
16
20
  @plantuml = plantuml
17
- @theme = Theme.new(options || {})
18
- @logger = Logger.init
21
+ @options = options
22
+ @theme = Theme.new(options)
23
+ @logger = LogWrapper.init
19
24
  @executor = Executor.new
25
+ @logger.warn 'PlantUML diagram is empty' if @plantuml.nil? || @plantuml.empty?
20
26
  end
21
27
 
22
28
  def convert_to_svg
23
29
  return @svg unless @svg.nil?
24
-
25
- if @plantuml.nil? || @plantuml.empty?
26
- @logger.warn ' kramdown-plantuml: PlantUML diagram is empty'
27
- return @plantuml
28
- end
30
+ return @plantuml if @plantuml.nil? || @plantuml.empty?
29
31
 
30
32
  @plantuml = @theme.apply(@plantuml)
31
- @plantuml = plantuml.strip
32
33
  log(plantuml)
33
34
  @result = @executor.execute(self)
34
35
  @result.validate
35
36
  @svg = wrap(@result.without_xml_prologue)
36
- @svg
37
+ rescue StandardError => e
38
+ raise e if @options.raise_errors?
39
+
40
+ @logger.error e.to_s
37
41
  end
38
42
 
39
43
  private
@@ -49,8 +53,8 @@ module Kramdown
49
53
  end
50
54
 
51
55
  def log(plantuml)
52
- @logger.debug ' kramdown-plantuml: PlantUML converting diagram:'
53
- @logger.debug_with_prefix ' kramdown-plantuml: ', plantuml
56
+ @logger.debug 'PlantUML converting diagram:'
57
+ @logger.debug_multiline plantuml
54
58
  end
55
59
  end
56
60
  end
@@ -1,8 +1,8 @@
1
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,12 +10,18 @@ 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
27
  def execute(diagram)
@@ -24,11 +30,11 @@ module Kramdown
24
30
 
25
31
  cmd = "java -Djava.awt.headless=true -jar #{@plantuml_jar_file} -tsvg -failfast -pipe #{debug_args}"
26
32
 
27
- @logger.debug " kramdown-plantuml: Executing '#{cmd}'."
33
+ @logger.debug "Executing '#{cmd}'."
28
34
 
29
35
  stdout, stderr, status = Open3.capture3 cmd, stdin_data: diagram.plantuml
30
36
 
31
- @logger.debug " kramdown-plantuml: PlantUML exit code '#{status.exitstatus}'."
37
+ @logger.debug "PlantUML exit code '#{status.exitstatus}'."
32
38
 
33
39
  PlantUmlResult.new(diagram, stdout, stderr, status.exitstatus)
34
40
  end
@@ -37,9 +43,13 @@ module Kramdown
37
43
 
38
44
  def find_plantuml_jar_file
39
45
  dir = File.dirname __dir__
40
- 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'
41
48
  first_jar = Dir[jar_glob].first
42
- 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
43
53
  end
44
54
 
45
55
  def debug_args
@@ -0,0 +1,104 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+ require 'English'
5
+ require 'htmlentities'
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
+ end
66
+ end
67
+
68
+ def replace_needle(json)
69
+ hash = JSON.parse(json)
70
+ options_hash = hash['options']
71
+ options = ::Kramdown::PlantUml::Options.new({ plantuml: options_hash })
72
+
73
+ begin
74
+ decode_and_convert(hash, options)
75
+ rescue StandardError => e
76
+ raise e if options.raise_errors?
77
+
78
+ logger.error 'Error while replacing needle.'
79
+ logger.error e.to_s
80
+ logger.debug_multiline json
81
+ end
82
+ end
83
+
84
+ def decode_and_convert(hash, options)
85
+ encoded_plantuml = hash['plantuml']
86
+ plantuml = HTMLEntities.new.decode encoded_plantuml
87
+ diagram = ::Kramdown::PlantUml::Diagram.new(plantuml, options)
88
+ diagram.convert_to_svg
89
+ end
90
+
91
+ def load_jekyll
92
+ require 'jekyll'
93
+ ::Jekyll
94
+ rescue LoadError
95
+ nil
96
+ end
97
+
98
+ def logger
99
+ @logger ||= ::Kramdown::PlantUml::LogWrapper.init
100
+ end
101
+ end
102
+ end
103
+ end
104
+ 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, multiline_string)
24
+ def debug_multiline(multiline_string)
24
25
  return if multiline_string.nil? || multiline_string.empty?
25
26
 
26
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,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'logger'
3
+ require_relative 'log_wrapper'
4
4
  require_relative 'plantuml_error'
5
5
  require_relative 'diagram'
6
6
 
@@ -20,7 +20,7 @@ module Kramdown
20
20
  @stdout = stdout
21
21
  @stderr = stderr
22
22
  @exitcode = exitcode
23
- @logger = Logger.init
23
+ @logger = LogWrapper.init
24
24
  end
25
25
 
26
26
  def without_xml_prologue
@@ -58,8 +58,8 @@ module Kramdown
58
58
 
59
59
  return if @stderr.nil? || @stderr.empty?
60
60
 
61
- @logger.debug ' kramdown-plantuml: PlantUML log:'
62
- @logger.debug_with_prefix ' kramdown-plantuml: ', @stderr
61
+ @logger.debug 'PlantUML log:'
62
+ @logger.debug_multiline @stderr
63
63
  end
64
64
  end
65
65
  end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: false
2
2
 
3
- require_relative 'logger'
3
+ require_relative 'options'
4
+ require_relative 'log_wrapper'
4
5
 
5
6
  module Kramdown
6
7
  module PlantUml
@@ -8,20 +9,24 @@ module Kramdown
8
9
  class Theme
9
10
  attr_reader :name, :directory
10
11
 
11
- def initialize(options = {})
12
- @logger = Logger.init
13
- @name, @directory = theme_options(options)
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
14
19
  end
15
20
 
16
21
  def apply(plantuml)
17
22
  if plantuml.nil? || !plantuml.is_a?(String) || plantuml.empty?
18
- @logger.debug ' kramdown-plantuml: Empty diagram or not a String.'
23
+ @logger.debug 'Empty diagram or not a String.'
19
24
  return plantuml
20
25
  end
21
26
 
22
27
  if @name.nil? || @name.empty?
23
- @logger.debug ' kramdown-plantuml: No theme to apply.'
24
- return plantuml
28
+ @logger.debug 'No theme to apply.'
29
+ return plantuml.strip
25
30
  end
26
31
 
27
32
  theme(plantuml)
@@ -29,31 +34,6 @@ module Kramdown
29
34
 
30
35
  private
31
36
 
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
- name = theme.key?(:name) ? theme[:name] : nil
41
- directory = theme.key?(:directory) ? theme[:directory] : nil
42
-
43
- [name, 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
37
  def theme(plantuml)
58
38
  startuml = '@startuml'
59
39
  startuml_index = plantuml.index(startuml) + startuml.length
@@ -63,13 +43,13 @@ module Kramdown
63
43
  theme_string = "\n!theme #{@name}"
64
44
  theme_string << " from #{@directory}" unless @directory.nil?
65
45
 
66
- @logger.debug " kramdown-plantuml: Applying #{theme_string.strip}"
46
+ @logger.debug "Applying #{theme_string.strip}"
67
47
 
68
48
  /@startuml.*/.match(plantuml) do |match|
69
49
  return plantuml.insert match.end(0), theme_string
70
50
  end
71
51
 
72
- plantuml
52
+ plantuml.strip
73
53
  end
74
54
  end
75
55
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Kramdown
4
4
  module PlantUml
5
- VERSION = '1.1.4'
5
+ VERSION = '1.1.8'
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,3 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
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/logger'
5
+ require_relative 'kramdown-plantuml/log_wrapper'
6
6
  require_relative 'kramdown-plantuml/plantuml_error'
7
+ require_relative 'kramdown-plantuml/options'
7
8
  require_relative 'kramdown-plantuml/diagram'
9
+ require_relative 'kramdown-plantuml/jekyll_provider'
8
10
 
9
11
  module Kramdown
10
12
  module Converter
@@ -14,12 +16,34 @@ 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
- diagram = ::Kramdown::PlantUml::Diagram.new(plantuml, plantuml_options)
21
+ jekyll = ::Kramdown::PlantUml::JekyllProvider
22
+
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, options)
32
+ end
33
+
34
+ private
35
+
36
+ def plantuml?(element)
37
+ element.attr['class'] == 'language-plantuml'
38
+ end
39
+
40
+ def convert_plantuml(plantuml, options)
41
+ diagram = ::Kramdown::PlantUml::Diagram.new(plantuml, options)
22
42
  diagram.convert_to_svg
43
+ rescue StandardError => e
44
+ raise e if options.raise_errors?
45
+
46
+ logger.error "Error while replacing needle: #{e.inspect}"
23
47
  end
24
48
  end
25
49
  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,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kramdown-plantuml
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.4
4
+ version: 1.1.8
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-30 00:00:00.000000000 Z
11
+ date: 2021-11-01 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: htmlentities
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '4'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '4'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: kramdown
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -166,20 +180,22 @@ files:
166
180
  - LICENSE
167
181
  - README.md
168
182
  - Rakefile
169
- - bin/net/sourceforge/plantuml/plantuml/1.2021.9/plantuml-1.2021.9.jar
183
+ - bin/net/sourceforge/plantuml/plantuml/1.2021.12/plantuml-1.2021.12.jar
170
184
  - kramdown-plantuml.gemspec
171
185
  - lib/kramdown-plantuml.rb
172
186
  - lib/kramdown-plantuml/bool_env.rb
173
187
  - lib/kramdown-plantuml/console_logger.rb
174
188
  - lib/kramdown-plantuml/diagram.rb
175
189
  - lib/kramdown-plantuml/executor.rb
176
- - lib/kramdown-plantuml/logger.rb
190
+ - lib/kramdown-plantuml/jekyll_provider.rb
191
+ - lib/kramdown-plantuml/log_wrapper.rb
192
+ - lib/kramdown-plantuml/options.rb
177
193
  - lib/kramdown-plantuml/plantuml_error.rb
178
194
  - lib/kramdown-plantuml/plantuml_result.rb
179
195
  - lib/kramdown-plantuml/theme.rb
180
196
  - lib/kramdown-plantuml/version.rb
197
+ - lib/kramdown-plantuml/which.rb
181
198
  - lib/kramdown_html.rb
182
- - lib/which.rb
183
199
  - pom.xml
184
200
  homepage: https://github.com/SwedbankPay/kramdown-plantuml
185
201
  licenses: