kramdown-plantuml 1.1.1 → 1.1.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/mergify.yml +1 -0
- data/.github/scripts/build-gem.sh +70 -3
- data/.github/scripts/test-gem.sh +58 -12
- data/.github/workflows/ruby.yml +38 -8
- data/README.md +3 -0
- data/bin/net/sourceforge/plantuml/plantuml/{1.2021.8/plantuml-1.2021.8.jar → 1.2021.10/plantuml-1.2021.10.jar} +0 -0
- data/lib/kramdown-plantuml/bool_env.rb +2 -2
- data/lib/kramdown-plantuml/console_logger.rb +1 -1
- data/lib/kramdown-plantuml/diagram.rb +54 -0
- data/lib/kramdown-plantuml/executor.rb +16 -12
- data/lib/kramdown-plantuml/jekyll_provider.rb +76 -0
- data/lib/kramdown-plantuml/logger.rb +33 -15
- data/lib/kramdown-plantuml/plantuml_error.rb +51 -14
- data/lib/kramdown-plantuml/plantuml_result.rb +23 -6
- data/lib/kramdown-plantuml/theme.rb +76 -0
- data/lib/kramdown-plantuml/version.rb +1 -1
- data/lib/kramdown-plantuml.rb +3 -2
- data/lib/kramdown_html.rb +24 -5
- data/pom.xml +1 -1
- metadata +6 -6
- data/lib/kramdown-plantuml/converter.rb +0 -42
- data/lib/kramdown-plantuml/hash.rb +0 -14
- data/lib/kramdown-plantuml/themer.rb +0 -50
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3968b5c182c334e7dbe020e7cd02309f6349fedeab4c6011b63178aa570b5c7f
|
4
|
+
data.tar.gz: 804e7e4c062c10f1f1c7578c338a8b19ec70a23031081a129f90dc44fa087926
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ad3f371c0c4608c8d613ba9ec73414f6eea92c8eccf9a087fe7ccc487403b4742afc68c63574937aaf8ea30c9f90aaf56b7e5636764647b442137e7a683cbecd
|
7
|
+
data.tar.gz: c437216460a278794c2caeb20c151c5c2a98cce5d5a72e2a4d1b1fb077cc970ceb50fbb0fb3d832b92a7991d35b36776e019a295cbe9884ff928fee073dd9938
|
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,28 +128,47 @@ 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
|
111
139
|
else
|
112
|
-
|
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
|
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
|
|
120
165
|
bundle install
|
121
166
|
bundle exec jekyll build "${jekyll_build_args[@]}"
|
122
167
|
|
168
|
+
|
123
169
|
file="${workdir}/_site/index.html"
|
124
170
|
|
125
|
-
file_contains "${file}" "class=\"
|
171
|
+
file_contains "${file}" "class=\"${class}\""
|
126
172
|
file_contains "${file}" "<svg"
|
127
173
|
file_contains "${file}" "<ellipse"
|
128
174
|
file_contains "${file}" "<polygon"
|
data/.github/workflows/ruby.yml
CHANGED
@@ -91,20 +91,35 @@ 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
97
|
run: bundle exec rspec --tag debug
|
101
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
|
116
|
+
|
102
117
|
- name: Codecov upload
|
103
118
|
run: bundle exec rake codecov:upload || echo 'Codecov upload failed'
|
104
119
|
|
105
120
|
- name: Build gem
|
106
121
|
id: gem
|
107
|
-
run: .github/scripts/build-gem.sh
|
122
|
+
run: .github/scripts/build-gem.sh --ref ${{ github.ref }} --verbose
|
108
123
|
|
109
124
|
- name: Upload gem
|
110
125
|
uses: actions/upload-artifact@v2-preview
|
@@ -116,7 +131,16 @@ jobs:
|
|
116
131
|
run: .github/scripts/inspect-gem.sh --gem "${{ github.workspace }}/${{ steps.gem.outputs.name }}" --verbose
|
117
132
|
|
118
133
|
- name: Test gem
|
119
|
-
run: .github/scripts/test-gem.sh --workdir "${{ github.workspace }}/spec/
|
134
|
+
run: .github/scripts/test-gem.sh --workdir "${{ github.workspace }}/spec/examples" --gemdir "${{ github.workspace }}" --verbose
|
135
|
+
|
136
|
+
- name: Upload code coverage (gem)
|
137
|
+
uses: actions/upload-artifact@v2
|
138
|
+
with:
|
139
|
+
name: gem-coverage
|
140
|
+
path: ./coverage
|
141
|
+
|
142
|
+
- name: Codecov upload (gem)
|
143
|
+
run: bundle exec rake codecov:upload || echo 'Codecov upload failed'
|
120
144
|
|
121
145
|
publish-dev:
|
122
146
|
needs: [version, gem]
|
@@ -150,15 +174,21 @@ jobs:
|
|
150
174
|
- name: Publish to GPR
|
151
175
|
run: .github/scripts/publish-gem.sh --gem ${{ needs.gem.outputs.name }} --token "${{ secrets.GPR_TOKEN }}" --owner SwedbankPay --verbose
|
152
176
|
|
153
|
-
- name: Test gem
|
154
|
-
run: .github/scripts/test-gem.sh --workdir "${{ github.workspace }}/spec/
|
177
|
+
- name: Test gem (no theme)
|
178
|
+
run: .github/scripts/test-gem.sh --workdir "${{ github.workspace }}/spec/examples" --version ${{ needs.version.outputs.version }} --token "${{ secrets.GPR_TOKEN }}" --verbose
|
179
|
+
|
180
|
+
- name: Test gem (built-in theme)
|
181
|
+
run: .github/scripts/test-gem.sh --workdir "${{ github.workspace }}/spec/examples" --version ${{ needs.version.outputs.version }} --token "${{ secrets.GPR_TOKEN }}" --verbose --theme-name spacelab
|
182
|
+
|
183
|
+
- name: Test gem (custom theme)
|
184
|
+
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
185
|
|
156
186
|
- name: Upload Jekyll site
|
157
187
|
uses: actions/upload-artifact@v2-preview
|
158
188
|
if: always()
|
159
189
|
with:
|
160
190
|
name: site
|
161
|
-
path: ${{ github.workspace }}/spec/
|
191
|
+
path: ${{ github.workspace }}/spec/examples/_site
|
162
192
|
|
163
193
|
publish-prod:
|
164
194
|
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]
|
@@ -180,6 +181,8 @@ agreement][cla].
|
|
180
181
|
[clone]: https://docs.github.com/en/free-pro-team@latest/github/creating-cloning-and-archiving-repositories/cloning-a-repository
|
181
182
|
[coc-badge]: https://img.shields.io/badge/Contributor%20Covenant-v2.0%20adopted-ff69b4.svg
|
182
183
|
[coc]: ./CODE_OF_CONDUCT.md
|
184
|
+
[codacy-badge]: https://app.codacy.com/project/badge/Grade/de72385f4ca444c18819a3ce8a506638
|
185
|
+
[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
186
|
[codecov-badge]: https://codecov.io/gh/SwedbankPay/kramdown-plantuml/branch/main/graph/badge.svg?token=U3QJLVG3HY
|
184
187
|
[codecov]: https://codecov.io/gh/SwedbankPay/kramdown-plantuml/
|
185
188
|
[diagram-svg]: ./spec/examples/diagram.svg
|
Binary file
|
@@ -9,8 +9,8 @@ module Kramdown
|
|
9
9
|
|
10
10
|
def initialize(name)
|
11
11
|
@name = name
|
12
|
-
|
13
|
-
@value =
|
12
|
+
value = ENV.fetch(name, nil)
|
13
|
+
@value = value.to_s.downcase unless value.nil?
|
14
14
|
end
|
15
15
|
|
16
16
|
def true?
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'version'
|
4
|
+
require_relative 'theme'
|
5
|
+
require_relative 'plantuml_error'
|
6
|
+
require_relative 'logger'
|
7
|
+
require_relative 'executor'
|
8
|
+
|
9
|
+
module Kramdown
|
10
|
+
module PlantUml
|
11
|
+
# Represents a PlantUML diagram that can be converted to SVG.
|
12
|
+
class Diagram
|
13
|
+
attr_reader :theme, :plantuml, :result
|
14
|
+
|
15
|
+
def initialize(plantuml, options = {})
|
16
|
+
@plantuml = plantuml
|
17
|
+
@theme = Theme.new(options || {})
|
18
|
+
@logger = Logger.init
|
19
|
+
@executor = Executor.new
|
20
|
+
@logger.warn 'PlantUML diagram is empty' if @plantuml.nil? || @plantuml.empty?
|
21
|
+
end
|
22
|
+
|
23
|
+
def convert_to_svg
|
24
|
+
return @svg unless @svg.nil?
|
25
|
+
return @plantuml if @plantuml.nil? || @plantuml.empty?
|
26
|
+
|
27
|
+
@plantuml = @theme.apply(@plantuml)
|
28
|
+
@plantuml = plantuml.strip
|
29
|
+
log(plantuml)
|
30
|
+
@result = @executor.execute(self)
|
31
|
+
@result.validate
|
32
|
+
@svg = wrap(@result.without_xml_prologue)
|
33
|
+
@svg
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def wrap(svg)
|
39
|
+
theme_class = @theme.name ? "theme-#{@theme.name}" : ''
|
40
|
+
class_name = "plantuml #{theme_class}".strip
|
41
|
+
|
42
|
+
wrapper_element_start = "<div class=\"#{class_name}\">"
|
43
|
+
wrapper_element_end = '</div>'
|
44
|
+
|
45
|
+
"#{wrapper_element_start}#{svg}#{wrapper_element_end}"
|
46
|
+
end
|
47
|
+
|
48
|
+
def log(plantuml)
|
49
|
+
@logger.debug 'PlantUML converting diagram:'
|
50
|
+
@logger.debug_multiline plantuml
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# frozen_string_literal:
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'open3'
|
4
4
|
require_relative '../which'
|
@@ -18,21 +18,19 @@ module Kramdown
|
|
18
18
|
raise IOError, "'#{@plantuml_jar_file}' does not exist" unless File.exist? @plantuml_jar_file
|
19
19
|
end
|
20
20
|
|
21
|
-
def execute(
|
22
|
-
|
23
|
-
|
24
|
-
' -verbose'
|
25
|
-
else
|
26
|
-
' -nometadata'
|
27
|
-
end
|
21
|
+
def execute(diagram)
|
22
|
+
raise ArgumentError, 'diagram cannot be nil' if diagram.nil?
|
23
|
+
raise ArgumentError, "diagram must be a #{Diagram}" unless diagram.is_a?(Diagram)
|
28
24
|
|
29
|
-
|
25
|
+
cmd = "java -Djava.awt.headless=true -jar #{@plantuml_jar_file} -tsvg -failfast -pipe #{debug_args}"
|
30
26
|
|
31
|
-
|
27
|
+
@logger.debug "Executing '#{cmd}'."
|
32
28
|
|
33
|
-
|
29
|
+
stdout, stderr, status = Open3.capture3 cmd, stdin_data: diagram.plantuml
|
34
30
|
|
35
|
-
|
31
|
+
@logger.debug "PlantUML exit code '#{status.exitstatus}'."
|
32
|
+
|
33
|
+
PlantUmlResult.new(diagram, stdout, stderr, status.exitstatus)
|
36
34
|
end
|
37
35
|
|
38
36
|
private
|
@@ -43,6 +41,12 @@ module Kramdown
|
|
43
41
|
first_jar = Dir[jar_glob].first
|
44
42
|
File.expand_path first_jar unless first_jar.nil?
|
45
43
|
end
|
44
|
+
|
45
|
+
def debug_args
|
46
|
+
return ' -verbose' if @logger.debug?
|
47
|
+
|
48
|
+
' -nometadata'
|
49
|
+
end
|
46
50
|
end
|
47
51
|
end
|
48
52
|
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
require 'English'
|
5
|
+
require_relative 'logger'
|
6
|
+
require_relative 'diagram'
|
7
|
+
|
8
|
+
module Kramdown
|
9
|
+
module PlantUml
|
10
|
+
# Provides an instance of Jekyll if available.
|
11
|
+
module JekyllProvider
|
12
|
+
class << self
|
13
|
+
def jekyll
|
14
|
+
return @jekyll if defined? @jekyll
|
15
|
+
|
16
|
+
@jekyll = load_jekyll
|
17
|
+
end
|
18
|
+
|
19
|
+
def install
|
20
|
+
return @installed = false if jekyll.nil?
|
21
|
+
|
22
|
+
logger.debug 'Jekyll detected, hooking into :site:post_render'
|
23
|
+
|
24
|
+
Jekyll::Hooks.register :site, :post_render do |site|
|
25
|
+
logger.debug ':site:post_render triggered.'
|
26
|
+
|
27
|
+
site.pages.each do |page|
|
28
|
+
page.output = replace_needles(page.output)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
@installed = true
|
33
|
+
end
|
34
|
+
|
35
|
+
def installed?
|
36
|
+
@installed
|
37
|
+
end
|
38
|
+
|
39
|
+
def needle(plantuml, options)
|
40
|
+
plantuml_options = !options.nil? && options.key?(:plantuml) ? options[:plantuml] : nil
|
41
|
+
hash = { 'plantuml' => plantuml, 'options' => plantuml_options }
|
42
|
+
|
43
|
+
<<~NEEDLE
|
44
|
+
<!--#kramdown-plantuml.start#-->
|
45
|
+
#{hash.to_json}
|
46
|
+
<!--#kramdown-plantuml.end#-->
|
47
|
+
NEEDLE
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def replace_needles(html)
|
53
|
+
html.gsub(/<!--#kramdown-plantuml\.start#-->(?<json>.*?)<!--#kramdown-plantuml\.end#-->/m) do
|
54
|
+
json = $LAST_MATCH_INFO[:json]
|
55
|
+
hash = JSON.parse(json)
|
56
|
+
plantuml = hash['plantuml']
|
57
|
+
options = hash['options']
|
58
|
+
diagram = ::Kramdown::PlantUml::Diagram.new(plantuml, options)
|
59
|
+
return diagram.convert_to_svg
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def load_jekyll
|
64
|
+
require 'jekyll'
|
65
|
+
::Jekyll
|
66
|
+
rescue LoadError
|
67
|
+
nil
|
68
|
+
end
|
69
|
+
|
70
|
+
def logger
|
71
|
+
@logger ||= ::Kramdown::PlantUml::Logger.init
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -1,10 +1,11 @@
|
|
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
9
|
class Logger
|
9
10
|
def initialize(logger)
|
10
11
|
raise ArgumentError, 'logger cannot be nil' if logger.nil?
|
@@ -17,37 +18,42 @@ module Kramdown
|
|
17
18
|
end
|
18
19
|
|
19
20
|
def debug(message)
|
20
|
-
|
21
|
+
write :debug, message
|
22
|
+
end
|
23
|
+
|
24
|
+
def debug_multiline(multiline_string)
|
25
|
+
return if multiline_string.nil? || multiline_string.empty?
|
26
|
+
|
27
|
+
lines = multiline_string.lines
|
28
|
+
lines.each do |line|
|
29
|
+
write :debug, line.rstrip
|
30
|
+
end
|
21
31
|
end
|
22
32
|
|
23
33
|
def info(message)
|
24
|
-
|
34
|
+
write :info, message
|
25
35
|
end
|
26
36
|
|
27
37
|
def warn(message)
|
28
|
-
|
38
|
+
write :warn, message
|
29
39
|
end
|
30
40
|
|
31
41
|
def error(message)
|
32
|
-
|
42
|
+
write :error, message
|
33
43
|
end
|
34
44
|
|
35
45
|
def debug?
|
36
46
|
self.class.level == :debug
|
37
47
|
end
|
38
48
|
|
49
|
+
def level
|
50
|
+
@level ||= level_from_logger || self.class.env
|
51
|
+
end
|
52
|
+
|
39
53
|
class << self
|
40
54
|
def init
|
41
|
-
inner = nil
|
42
|
-
|
43
|
-
begin
|
44
|
-
require 'jekyll'
|
45
|
-
inner = Jekyll.logger
|
46
|
-
rescue LoadError
|
47
|
-
inner = ConsoleLogger.new(level)
|
48
|
-
end
|
49
|
-
|
50
|
-
Logger.new(inner)
|
55
|
+
inner = JekyllProvider.jekyll ? JekyllProvider.jekyll.logger : nil || ConsoleLogger.new(level)
|
56
|
+
Logger.new inner
|
51
57
|
end
|
52
58
|
|
53
59
|
def level
|
@@ -63,6 +69,18 @@ module Kramdown
|
|
63
69
|
:warn
|
64
70
|
end
|
65
71
|
end
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
def write(level, message)
|
76
|
+
@logger.public_send(level, " kramdown-plantuml: #{message}")
|
77
|
+
end
|
78
|
+
|
79
|
+
def level_from_logger
|
80
|
+
return @logger.level if @logger.respond_to? :level
|
81
|
+
|
82
|
+
nil
|
83
|
+
end
|
66
84
|
end
|
67
85
|
end
|
68
86
|
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
|
@@ -2,17 +2,24 @@
|
|
2
2
|
|
3
3
|
require_relative 'logger'
|
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 =
|
22
|
+
@exitcode = exitcode
|
16
23
|
@logger = Logger.init
|
17
24
|
end
|
18
25
|
|
@@ -37,12 +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
|
61
|
+
@logger.debug 'PlantUML log:'
|
62
|
+
@logger.debug_multiline @stderr
|
46
63
|
end
|
47
64
|
end
|
48
65
|
end
|
@@ -0,0 +1,76 @@
|
|
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 Theme
|
9
|
+
attr_reader :name, :directory
|
10
|
+
|
11
|
+
def initialize(options = {})
|
12
|
+
@logger = Logger.init
|
13
|
+
@name, @directory = theme_options(options)
|
14
|
+
end
|
15
|
+
|
16
|
+
def apply(plantuml)
|
17
|
+
if plantuml.nil? || !plantuml.is_a?(String) || plantuml.empty?
|
18
|
+
@logger.debug 'Empty diagram or not a String.'
|
19
|
+
return plantuml
|
20
|
+
end
|
21
|
+
|
22
|
+
if @name.nil? || @name.empty?
|
23
|
+
@logger.debug '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 "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
|
+
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 #{@name}"
|
64
|
+
theme_string << " from #{@directory}" unless @directory.nil?
|
65
|
+
|
66
|
+
@logger.debug "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
|
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,10 @@
|
|
2
2
|
|
3
3
|
require 'kramdown'
|
4
4
|
require 'kramdown-parser-gfm'
|
5
|
-
require_relative 'kramdown-plantuml/converter'
|
6
5
|
require_relative 'kramdown-plantuml/logger'
|
7
6
|
require_relative 'kramdown-plantuml/plantuml_error'
|
7
|
+
require_relative 'kramdown-plantuml/diagram'
|
8
|
+
require_relative 'kramdown-plantuml/jekyll_provider'
|
8
9
|
|
9
10
|
module Kramdown
|
10
11
|
module Converter
|
@@ -14,13 +15,31 @@ module Kramdown
|
|
14
15
|
alias super_convert_codeblock convert_codeblock
|
15
16
|
|
16
17
|
def convert_codeblock(element, indent)
|
17
|
-
return super_convert_codeblock(element, indent)
|
18
|
+
return super_convert_codeblock(element, indent) unless plantuml?(element)
|
18
19
|
|
19
|
-
|
20
|
+
jekyll = ::Kramdown::PlantUml::JekyllProvider
|
21
|
+
|
22
|
+
# If Jekyll is successfully loaded, we'll wait with converting the
|
23
|
+
# PlantUML diagram to SVG since a theme may be configured that needs to
|
24
|
+
# be copied to the assets directory before the PlantUML conversion can
|
25
|
+
# be performed. We therefore place a needle in the haystack that we will
|
26
|
+
# convert in the :site:pre_render hook.
|
27
|
+
return jekyll.needle(element.value, @options) if jekyll.installed?
|
28
|
+
|
29
|
+
convert_plantuml(element.value)
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def plantuml?(element)
|
35
|
+
element.attr['class'] == 'language-plantuml'
|
36
|
+
end
|
37
|
+
|
38
|
+
def convert_plantuml(plantuml)
|
20
39
|
plantuml_options = @options.key?(:plantuml) ? @options[:plantuml] : {}
|
21
|
-
converter = ::Kramdown::PlantUml::Converter.new(plantuml_options || {})
|
22
40
|
|
23
|
-
|
41
|
+
diagram = ::Kramdown::PlantUml::Diagram.new(plantuml, plantuml_options)
|
42
|
+
diagram.convert_to_svg
|
24
43
|
end
|
25
44
|
end
|
26
45
|
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.5
|
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-10-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: kramdown
|
@@ -166,18 +166,18 @@ 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.10/plantuml-1.2021.10.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
177
|
- lib/kramdown-plantuml/logger.rb
|
178
178
|
- lib/kramdown-plantuml/plantuml_error.rb
|
179
179
|
- lib/kramdown-plantuml/plantuml_result.rb
|
180
|
-
- lib/kramdown-plantuml/
|
180
|
+
- lib/kramdown-plantuml/theme.rb
|
181
181
|
- lib/kramdown-plantuml/version.rb
|
182
182
|
- lib/kramdown_html.rb
|
183
183
|
- lib/which.rb
|
@@ -1,42 +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
|
-
plantuml = @themer.apply_theme(plantuml)
|
21
|
-
plantuml = plantuml.strip
|
22
|
-
@logger.debug "PlantUML converting diagram:\n#{plantuml}"
|
23
|
-
result = @executor.execute(plantuml)
|
24
|
-
result.validate(plantuml)
|
25
|
-
svg = result.without_xml_prologue
|
26
|
-
wrap(svg)
|
27
|
-
end
|
28
|
-
|
29
|
-
private
|
30
|
-
|
31
|
-
def wrap(svg)
|
32
|
-
theme_class = @themer.theme_name ? "theme-#{@themer.theme_name}" : ''
|
33
|
-
class_name = "plantuml #{theme_class}".strip
|
34
|
-
|
35
|
-
wrapper_element_start = "<div class=\"#{class_name}\">"
|
36
|
-
wrapper_element_end = '</div>'
|
37
|
-
|
38
|
-
"#{wrapper_element_start}#{svg}#{wrapper_element_end}"
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
@@ -1,14 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# Ruby's Hash class.
|
4
|
-
class ::Hash
|
5
|
-
# Via https://stackoverflow.com/a/25835016/2257038
|
6
|
-
def symbolize_keys
|
7
|
-
h = map do |k, v|
|
8
|
-
v_sym = v.instance_of?(Hash) ? v.symbolize_keys : v
|
9
|
-
[k.to_sym, v_sym]
|
10
|
-
end
|
11
|
-
|
12
|
-
h.to_h
|
13
|
-
end
|
14
|
-
end
|
@@ -1,50 +0,0 @@
|
|
1
|
-
# frozen_string_literal: false
|
2
|
-
|
3
|
-
require_relative 'hash'
|
4
|
-
require_relative 'logger'
|
5
|
-
|
6
|
-
module Kramdown
|
7
|
-
module PlantUml
|
8
|
-
# Provides theming support for PlantUML
|
9
|
-
class Themer
|
10
|
-
attr_reader :theme_name, :theme_directory
|
11
|
-
|
12
|
-
def initialize(options = {})
|
13
|
-
options = options.symbolize_keys
|
14
|
-
@logger = Logger.init
|
15
|
-
@logger.debug(options)
|
16
|
-
@theme_name, @theme_directory = theme_options(options)
|
17
|
-
end
|
18
|
-
|
19
|
-
def apply_theme(plantuml)
|
20
|
-
return plantuml if plantuml.nil? || plantuml.empty? || @theme_name.nil? || @theme_name.empty?
|
21
|
-
|
22
|
-
startuml = '@startuml'
|
23
|
-
startuml_index = plantuml.index(startuml) + startuml.length
|
24
|
-
|
25
|
-
return plantuml if startuml_index.nil?
|
26
|
-
|
27
|
-
/@startuml.*/.match(plantuml) do |match|
|
28
|
-
theme_string = "\n!theme #{@theme_name}"
|
29
|
-
theme_string << " from #{@theme_directory}" unless @theme_directory.nil?
|
30
|
-
|
31
|
-
return plantuml.insert match.end(0), theme_string
|
32
|
-
end
|
33
|
-
|
34
|
-
plantuml
|
35
|
-
end
|
36
|
-
|
37
|
-
private
|
38
|
-
|
39
|
-
def theme_options(options)
|
40
|
-
return nil unless options.key?(:theme)
|
41
|
-
|
42
|
-
theme = options[:theme] || {}
|
43
|
-
theme_name = theme.key?(:name) ? theme[:name] : nil
|
44
|
-
theme_directory = theme.key?(:directory) ? theme[:directory] : nil
|
45
|
-
|
46
|
-
[theme_name, theme_directory]
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|