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 +4 -4
- data/.github/mergify.yml +1 -0
- data/.github/scripts/build-gem.sh +70 -3
- data/.github/scripts/test-gem.sh +57 -12
- data/.github/workflows/ruby.yml +55 -9
- data/README.md +17 -0
- data/Rakefile +1 -1
- data/bin/net/sourceforge/plantuml/plantuml/{1.2021.8/plantuml-1.2021.8.jar → 1.2021.12/plantuml-1.2021.12.jar} +0 -0
- data/kramdown-plantuml.gemspec +1 -1
- data/lib/kramdown-plantuml/diagram.rb +61 -0
- data/lib/kramdown-plantuml/executor.rb +33 -19
- data/lib/kramdown-plantuml/jekyll_provider.rb +99 -0
- data/lib/kramdown-plantuml/{logger.rb → log_wrapper.rb} +17 -19
- data/lib/kramdown-plantuml/options.rb +91 -0
- data/lib/kramdown-plantuml/plantuml_error.rb +51 -14
- data/lib/kramdown-plantuml/plantuml_result.rb +25 -9
- data/lib/kramdown-plantuml/theme.rb +56 -0
- data/lib/kramdown-plantuml/version.rb +1 -1
- data/lib/{which.rb → kramdown-plantuml/which.rb} +2 -1
- data/lib/kramdown-plantuml.rb +3 -2
- data/lib/kramdown_html.rb +27 -7
- data/pom.xml +1 -1
- metadata +9 -7
- data/lib/kramdown-plantuml/converter.rb +0 -52
- data/lib/kramdown-plantuml/themer.rb +0 -76
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 178996116d7a833c324db54da1b3c367fe13c1d55fabc47026df12bec25b6f9d
|
4
|
+
data.tar.gz: d5dc3e4824ab5095b42b33e4b01cc6cb38735fe0bb220472f02e8014f069261b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5dd2e36fc7b66a4a8948ba801d75107c04fedbbb612fe525cabac758de15e3908368999d8779126a082dfcef70f990194c3abf0bace90eea019b182e3d26626c
|
7
|
+
data.tar.gz: 166be327fab188558c365c5284739d57ed7b851ce953e616b98d7f9002a20f89ab6af7527134a148eefdf547c4465adfe469d597eb8919af26a51cf3615e2b57
|
data/.github/mergify.yml
CHANGED
@@ -1,6 +1,73 @@
|
|
1
1
|
#!/usr/bin/env bash
|
2
2
|
set -o errexit # Abort if any command fails
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
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 "$@"
|
data/.github/scripts/test-gem.sh
CHANGED
@@ -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
|
-
|
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
|
-
|
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=\"
|
170
|
+
file_contains "${file}" "class=\"${class}\""
|
126
171
|
file_contains "${file}" "<svg"
|
127
172
|
file_contains "${file}" "<ellipse"
|
128
173
|
file_contains "${file}" "<polygon"
|
data/.github/workflows/ruby.yml
CHANGED
@@ -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/
|
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/
|
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/
|
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&utm_medium=referral&utm_content=SwedbankPay/kramdown-plantuml&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
|
Binary file
|
data/kramdown-plantuml.gemspec
CHANGED
@@ -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:
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'open3'
|
4
|
-
require_relative '
|
5
|
-
require_relative '
|
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 =
|
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(
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
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 "
|
33
|
+
@logger.debug "Executing '#{cmd}'."
|
30
34
|
|
31
|
-
stdout, stderr, status = Open3.capture3 cmd, stdin_data:
|
35
|
+
stdout, stderr, status = Open3.capture3 cmd, stdin_data: diagram.plantuml
|
32
36
|
|
33
|
-
@logger.debug "
|
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
|
-
|
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
|
-
|
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
|
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
|
-
|
21
|
+
write :debug, message
|
21
22
|
end
|
22
23
|
|
23
|
-
def
|
24
|
-
return if
|
24
|
+
def debug_multiline(multiline_string)
|
25
|
+
return if multiline_string.nil? || multiline_string.empty?
|
25
26
|
|
26
|
-
lines =
|
27
|
+
lines = multiline_string.lines
|
27
28
|
lines.each do |line|
|
28
|
-
|
29
|
+
write :debug, line.rstrip
|
29
30
|
end
|
30
31
|
end
|
31
32
|
|
32
33
|
def info(message)
|
33
|
-
|
34
|
+
write :info, message
|
34
35
|
end
|
35
36
|
|
36
37
|
def warn(message)
|
37
|
-
|
38
|
+
write :warn, message
|
38
39
|
end
|
39
40
|
|
40
41
|
def error(message)
|
41
|
-
|
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
|
-
|
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(
|
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
|
-
|
23
|
+
#{header}
|
10
24
|
|
11
25
|
#{plantuml}
|
12
26
|
|
13
|
-
|
14
|
-
|
15
|
-
Exit code: #{exitcode}
|
16
|
-
#{stderr}
|
27
|
+
#{result}
|
17
28
|
MESSAGE
|
18
29
|
|
19
|
-
|
30
|
+
message.strip
|
20
31
|
end
|
21
32
|
|
22
|
-
def
|
23
|
-
|
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
|
-
|
26
|
-
#
|
27
|
-
|
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 '
|
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,
|
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 =
|
16
|
-
@logger =
|
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
|
41
|
-
|
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 '
|
46
|
-
@logger.
|
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
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
#
|
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
|
data/lib/kramdown-plantuml.rb
CHANGED
@@ -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/
|
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)
|
19
|
+
return super_convert_codeblock(element, indent) unless plantuml?(element)
|
18
20
|
|
19
|
-
|
20
|
-
plantuml_options = @options.key?(:plantuml) ? @options[:plantuml] : {}
|
21
|
-
converter = ::Kramdown::PlantUml::Converter.new(plantuml_options || {})
|
21
|
+
jekyll = ::Kramdown::PlantUml::JekyllProvider
|
22
22
|
|
23
|
-
|
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
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.
|
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-
|
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.
|
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/
|
174
|
+
- lib/kramdown-plantuml/diagram.rb
|
175
175
|
- lib/kramdown-plantuml/executor.rb
|
176
|
-
- lib/kramdown-plantuml/
|
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/
|
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
|