kramdown-plantuml 1.1.11 → 1.3.0
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/scripts/test-gem.sh +1 -0
- data/.github/workflows/ruby.yml +2 -2
- data/README.md +32 -1
- data/kramdown-plantuml.gemspec +1 -0
- data/lib/kramdown-plantuml/executor.rb +1 -1
- data/lib/kramdown-plantuml/jekyll_page_processor.rb +103 -0
- data/lib/kramdown-plantuml/jekyll_provider.rb +10 -57
- data/lib/kramdown-plantuml/none_s.rb +17 -0
- data/lib/kramdown-plantuml/options.rb +21 -1
- data/lib/kramdown-plantuml/{diagram.rb → plantuml_diagram.rb} +11 -22
- data/lib/kramdown-plantuml/plantuml_error.rb +5 -5
- data/lib/kramdown-plantuml/plantuml_result.rb +9 -26
- data/lib/kramdown-plantuml/style_builder.rb +56 -0
- data/lib/kramdown-plantuml/svg_diagram.rb +115 -0
- data/lib/kramdown-plantuml/theme.rb +19 -12
- data/lib/kramdown-plantuml/version.rb +1 -1
- data/lib/kramdown_html.rb +3 -3
- data/pom.xml +1 -1
- metadata +21 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bc1234f77cba369797da8b8efd79b0a1913e65cd07f14ab26189c0acb2fa4900
|
4
|
+
data.tar.gz: 445fea556a2c3f248a3158e3f8fd9383624a1aceefb1e03e549e48ce87a6a4de
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 62dea36dfd6f811cb0861db862a938ae6e10f4d36fa1783ef33ec2338355710cfe8c718fcaf246cc73974d652729ea99560220997ef12c44174a8b6b1adbab1b
|
7
|
+
data.tar.gz: b9b72275e8eec577c9a249802191f8e9a457b1dfdb4e83328e2e4a942f43077ab39c08fbff2790af23f7c1c3c6d451250bfab7effa7b47455d994472bea1c439
|
data/.github/scripts/test-gem.sh
CHANGED
data/.github/workflows/ruby.yml
CHANGED
@@ -15,13 +15,13 @@ jobs:
|
|
15
15
|
fetch-depth: 0
|
16
16
|
|
17
17
|
- name: Setup GitVersion
|
18
|
-
uses: gittools/actions/gitversion/setup@v0.9.
|
18
|
+
uses: gittools/actions/gitversion/setup@v0.9.11
|
19
19
|
with:
|
20
20
|
versionSpec: '5.x.x'
|
21
21
|
|
22
22
|
- name: Execute GitVersion
|
23
23
|
id: gitversion
|
24
|
-
uses: gittools/actions/gitversion/execute@v0.9.
|
24
|
+
uses: gittools/actions/gitversion/execute@v0.9.11
|
25
25
|
|
26
26
|
- name: Create variables
|
27
27
|
id: variables
|
data/README.md
CHANGED
@@ -130,6 +130,37 @@ kramdown:
|
|
130
130
|
directory: path/to/themes
|
131
131
|
```
|
132
132
|
|
133
|
+
### Dimensions and Styling
|
134
|
+
|
135
|
+
It's possible to customize the dimensions and scale of the diagram by providing
|
136
|
+
the `width`, `height` and `scale` configuration keys. It's also possible to add
|
137
|
+
arbitrary styling with the `style` key.
|
138
|
+
|
139
|
+
`scale` is applied before the diagram is generated, while `width` and `height`
|
140
|
+
are applied after, meaning they can be combined (to most likely detrimental
|
141
|
+
results, but YOLO).
|
142
|
+
|
143
|
+
```yaml
|
144
|
+
kramdown:
|
145
|
+
plantuml:
|
146
|
+
width: 200px
|
147
|
+
height: 100px
|
148
|
+
scale: 2
|
149
|
+
style: "border: 1px solid black"
|
150
|
+
```
|
151
|
+
|
152
|
+
To remove the `width`, `height` and `style` attributes from the `<svg />`
|
153
|
+
element, set the key's value to `none`. `scale` does not support a value of
|
154
|
+
`none` as it does not need to be removed.
|
155
|
+
|
156
|
+
```yaml
|
157
|
+
kramdown:
|
158
|
+
plantuml:
|
159
|
+
width: none
|
160
|
+
height: none
|
161
|
+
style: none
|
162
|
+
```
|
163
|
+
|
133
164
|
### Errors
|
134
165
|
|
135
166
|
By default, `kramdown-plantuml` will raise an error and crash if something goes
|
@@ -199,7 +230,7 @@ agreement][cla].
|
|
199
230
|
[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
|
200
231
|
[codecov-badge]: https://codecov.io/gh/SwedbankPay/kramdown-plantuml/branch/main/graph/badge.svg?token=U3QJLVG3HY
|
201
232
|
[codecov]: https://codecov.io/gh/SwedbankPay/kramdown-plantuml/
|
202
|
-
[diagram-svg]: ./spec/examples/diagram.svg
|
233
|
+
[diagram-svg]: ./spec/examples/network-diagram.svg
|
203
234
|
[fenced]: https://www.markdownguide.org/extended-syntax/#syntax-highlighting
|
204
235
|
[fork]: https://docs.github.com/en/free-pro-team@latest/github/getting-started-with-github/fork-a-repo
|
205
236
|
[gem-badge]: https://badge.fury.io/rb/kramdown-plantuml.svg
|
data/kramdown-plantuml.gemspec
CHANGED
@@ -42,6 +42,7 @@ Gem::Specification.new do |spec|
|
|
42
42
|
|
43
43
|
spec.add_development_dependency 'rake', '~> 13.0'
|
44
44
|
spec.add_development_dependency 'rspec', '~> 3.2'
|
45
|
+
spec.add_development_dependency 'rspec-html-matchers', '>= 0.9'
|
45
46
|
spec.add_development_dependency 'rspec-its', '~> 1.3'
|
46
47
|
spec.add_development_dependency 'rubocop', '~> 1.12'
|
47
48
|
spec.add_development_dependency 'rubocop-rake', '~> 0.6'
|
@@ -26,7 +26,7 @@ module Kramdown
|
|
26
26
|
|
27
27
|
def execute(diagram)
|
28
28
|
raise ArgumentError, 'diagram cannot be nil' if diagram.nil?
|
29
|
-
raise ArgumentError, "diagram must be a #{
|
29
|
+
raise ArgumentError, "diagram must be a #{PlantUmlDiagram}" unless diagram.is_a?(PlantUmlDiagram)
|
30
30
|
|
31
31
|
cmd = "java -Djava.awt.headless=true -jar #{@plantuml_jar_file} -tsvg -failfast -pipe #{debug_args}"
|
32
32
|
|
@@ -0,0 +1,103 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'htmlentities'
|
4
|
+
require 'json'
|
5
|
+
require_relative 'log_wrapper'
|
6
|
+
|
7
|
+
module Kramdown
|
8
|
+
module PlantUml
|
9
|
+
# Processes Jekyll pages.
|
10
|
+
class JekyllPageProcessor
|
11
|
+
PROCESSED_KEY = :kramdown_plantuml_processed
|
12
|
+
|
13
|
+
def initialize(page)
|
14
|
+
raise ArgumentError, 'page cannot be nil' if page.nil?
|
15
|
+
|
16
|
+
@page = page
|
17
|
+
end
|
18
|
+
|
19
|
+
def process(site_destination_directory)
|
20
|
+
@page.output = do_process
|
21
|
+
@page.data[PROCESSED_KEY] = true
|
22
|
+
@page.write(site_destination_directory)
|
23
|
+
end
|
24
|
+
|
25
|
+
def should_process?
|
26
|
+
return false unless @page.output_ext == '.html'
|
27
|
+
|
28
|
+
if !@page.data.nil? && @page.data.key?(PROCESSED_KEY) && @page.data[PROCESSED_KEY]
|
29
|
+
logger.debug "Skipping #{@page.path} because it has already been processed."
|
30
|
+
return false
|
31
|
+
end
|
32
|
+
|
33
|
+
true
|
34
|
+
end
|
35
|
+
|
36
|
+
class << self
|
37
|
+
def needle(plantuml, options)
|
38
|
+
hash = { 'plantuml' => plantuml, 'options' => options.to_h }
|
39
|
+
|
40
|
+
<<~NEEDLE
|
41
|
+
<!--#kramdown-plantuml.start#-->
|
42
|
+
#{hash.to_json}
|
43
|
+
<!--#kramdown-plantuml.end#-->
|
44
|
+
NEEDLE
|
45
|
+
rescue StandardError => e
|
46
|
+
raise e if options.nil? || options.raise_errors?
|
47
|
+
|
48
|
+
logger.error 'Error while placing needle.'
|
49
|
+
logger.error e.to_s
|
50
|
+
logger.debug_multiline plantuml
|
51
|
+
end
|
52
|
+
|
53
|
+
def logger
|
54
|
+
@logger ||= ::Kramdown::PlantUml::LogWrapper.init
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def do_process
|
61
|
+
logger.debug "Replacing Jekyll needles in #{@page.path}"
|
62
|
+
|
63
|
+
html = @page.output
|
64
|
+
|
65
|
+
return html if html.nil? || html.empty? || !html.is_a?(String)
|
66
|
+
|
67
|
+
html.gsub(/<!--#kramdown-plantuml\.start#-->(?<json>.*?)<!--#kramdown-plantuml\.end#-->/m) do
|
68
|
+
json = $LAST_MATCH_INFO ? $LAST_MATCH_INFO[:json] : nil
|
69
|
+
replace_needle(json) unless json.nil?
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def replace_needle(json)
|
74
|
+
logger.debug 'Replacing Jekyll needle.'
|
75
|
+
|
76
|
+
needle_hash = JSON.parse(json)
|
77
|
+
options_hash = needle_hash['options']
|
78
|
+
options = ::Kramdown::PlantUml::Options.new({ plantuml: options_hash })
|
79
|
+
|
80
|
+
begin
|
81
|
+
decode_and_convert(needle_hash, options)
|
82
|
+
rescue StandardError => e
|
83
|
+
raise e if options.raise_errors?
|
84
|
+
|
85
|
+
logger.error 'Error while replacing Jekyll needle.'
|
86
|
+
logger.error e.to_s
|
87
|
+
logger.debug_multiline json
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def decode_and_convert(hash, options)
|
92
|
+
encoded_plantuml = hash['plantuml']
|
93
|
+
plantuml = HTMLEntities.new.decode encoded_plantuml
|
94
|
+
diagram = ::Kramdown::PlantUml::PlantUmlDiagram.new(plantuml, options)
|
95
|
+
diagram.svg
|
96
|
+
end
|
97
|
+
|
98
|
+
def logger
|
99
|
+
@logger ||= ::Kramdown::PlantUml::LogWrapper.init
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -1,10 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'json'
|
4
|
-
require 'English'
|
5
|
-
require 'htmlentities'
|
6
3
|
require_relative 'log_wrapper'
|
7
|
-
require_relative '
|
4
|
+
require_relative 'jekyll_page_processor'
|
8
5
|
|
9
6
|
module Kramdown
|
10
7
|
module PlantUml
|
@@ -32,20 +29,7 @@ module Kramdown
|
|
32
29
|
end
|
33
30
|
|
34
31
|
def needle(plantuml, options)
|
35
|
-
|
36
|
-
|
37
|
-
<<~NEEDLE
|
38
|
-
<!--#kramdown-plantuml.start#-->
|
39
|
-
#{hash.to_json}
|
40
|
-
<!--#kramdown-plantuml.end#-->
|
41
|
-
NEEDLE
|
42
|
-
rescue StandardError => e
|
43
|
-
raise e if options.raise_errors?
|
44
|
-
|
45
|
-
puts e
|
46
|
-
logger.error 'Error while placing needle.'
|
47
|
-
logger.error e.to_s
|
48
|
-
logger.debug_multiline plantuml
|
32
|
+
JekyllPageProcessor.needle(plantuml, options)
|
49
33
|
end
|
50
34
|
|
51
35
|
private
|
@@ -63,54 +47,23 @@ module Kramdown
|
|
63
47
|
|
64
48
|
def register_hook
|
65
49
|
Jekyll::Hooks.register :site, :post_write do |site|
|
66
|
-
|
67
|
-
|
68
|
-
@site_destination_dir ||= site.dest
|
69
|
-
|
70
|
-
site.pages.each do |page|
|
71
|
-
page.output = replace_needles(page)
|
72
|
-
page.write(@site_destination_dir)
|
73
|
-
end
|
50
|
+
site_post_write(site)
|
74
51
|
end
|
75
52
|
end
|
76
53
|
|
77
|
-
def
|
78
|
-
logger.debug
|
79
|
-
|
80
|
-
html = page.output
|
81
|
-
return html if html.nil? || html.empty? || !html.is_a?(String)
|
54
|
+
def site_post_write(site)
|
55
|
+
logger.debug 'Jekyll:site:post_write triggered.'
|
56
|
+
@site_destination_dir ||= site.dest
|
82
57
|
|
83
|
-
|
84
|
-
|
85
|
-
return replace_needle(json)
|
86
|
-
end
|
87
|
-
end
|
58
|
+
site.pages.each do |page|
|
59
|
+
processor = JekyllPageProcessor.new(page)
|
88
60
|
|
89
|
-
|
90
|
-
logger.debug 'Replacing Jekyll needle.'
|
61
|
+
next unless processor.should_process?
|
91
62
|
|
92
|
-
|
93
|
-
options_hash = needle_hash['options']
|
94
|
-
options = ::Kramdown::PlantUml::Options.new({ plantuml: options_hash })
|
95
|
-
|
96
|
-
begin
|
97
|
-
decode_and_convert(needle_hash, options)
|
98
|
-
rescue StandardError => e
|
99
|
-
raise e if options.raise_errors?
|
100
|
-
|
101
|
-
logger.error 'Error while replacing Jekyll needle.'
|
102
|
-
logger.error e.to_s
|
103
|
-
logger.debug_multiline json
|
63
|
+
processor.process(site.dest)
|
104
64
|
end
|
105
65
|
end
|
106
66
|
|
107
|
-
def decode_and_convert(hash, options)
|
108
|
-
encoded_plantuml = hash['plantuml']
|
109
|
-
plantuml = HTMLEntities.new.decode encoded_plantuml
|
110
|
-
diagram = ::Kramdown::PlantUml::Diagram.new(plantuml, options)
|
111
|
-
diagram.convert_to_svg
|
112
|
-
end
|
113
|
-
|
114
67
|
def load_jekyll
|
115
68
|
require 'jekyll'
|
116
69
|
::Jekyll
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Ruby's Object class.
|
4
|
+
class Object
|
5
|
+
# Performs a case insensitive, trimmed comparison of the Object and the
|
6
|
+
# String 'none' and Symbol :none. Returns true if the comparison is true,
|
7
|
+
# otherwise false.
|
8
|
+
#
|
9
|
+
# @return [Boolean] True if the Object is equal to 'none' or :none,
|
10
|
+
# otherwise false.
|
11
|
+
def none_s?
|
12
|
+
return false if nil?
|
13
|
+
return true if self == :none
|
14
|
+
|
15
|
+
to_s.strip.casecmp?('none')
|
16
|
+
end
|
17
|
+
end
|
@@ -1,18 +1,20 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative 'none_s'
|
3
4
|
require_relative 'log_wrapper'
|
4
5
|
|
5
6
|
module Kramdown
|
6
7
|
module PlantUml
|
7
8
|
# Options for PlantUML processing
|
8
9
|
class Options
|
9
|
-
attr_reader :theme_name, :theme_directory
|
10
|
+
attr_reader :theme_name, :theme_directory, :width, :height, :style, :scale
|
10
11
|
|
11
12
|
def initialize(options_hash = {})
|
12
13
|
@logger = LogWrapper.init
|
13
14
|
@options = massage(options_hash) || {}
|
14
15
|
@raise_errors = extract_raise_errors(@options)
|
15
16
|
extract_theme_options(@options)
|
17
|
+
extract_style_options(@options)
|
16
18
|
end
|
17
19
|
|
18
20
|
def raise_errors?
|
@@ -64,6 +66,24 @@ module Kramdown
|
|
64
66
|
boolean(raise_errors, true)
|
65
67
|
end
|
66
68
|
|
69
|
+
def extract_style_options(options)
|
70
|
+
return if options.nil? || options.empty?
|
71
|
+
|
72
|
+
set_instance_property(:width, options)
|
73
|
+
set_instance_property(:height, options)
|
74
|
+
set_instance_property(:style, options)
|
75
|
+
set_instance_property(:scale, options)
|
76
|
+
end
|
77
|
+
|
78
|
+
def set_instance_property(key, options)
|
79
|
+
return unless options.key? key
|
80
|
+
|
81
|
+
value = options[key]
|
82
|
+
value = :none if value.none_s?
|
83
|
+
prop_name = "@#{key}".to_sym
|
84
|
+
instance_variable_set(prop_name, value)
|
85
|
+
end
|
86
|
+
|
67
87
|
def massage(options_hash)
|
68
88
|
if options_hash.nil? || !options_hash.is_a?(Hash) || options_hash.empty?
|
69
89
|
@logger.debug 'No options provided'
|
@@ -1,17 +1,18 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative '
|
4
|
-
require_relative '
|
3
|
+
require_relative 'executor'
|
4
|
+
require_relative 'log_wrapper'
|
5
5
|
require_relative 'options'
|
6
6
|
require_relative 'plantuml_error'
|
7
|
-
require_relative '
|
8
|
-
require_relative '
|
7
|
+
require_relative 'svg_diagram'
|
8
|
+
require_relative 'theme'
|
9
|
+
require_relative 'version'
|
9
10
|
|
10
11
|
module Kramdown
|
11
12
|
module PlantUml
|
12
13
|
# Represents a PlantUML diagram that can be converted to SVG.
|
13
|
-
class
|
14
|
-
attr_reader :theme, :plantuml, :result
|
14
|
+
class PlantUmlDiagram
|
15
|
+
attr_reader :theme, :plantuml, :result, :options
|
15
16
|
|
16
17
|
def initialize(plantuml, options)
|
17
18
|
raise ArgumentError, 'options cannot be nil' if options.nil?
|
@@ -25,15 +26,13 @@ module Kramdown
|
|
25
26
|
@logger.warn 'PlantUML diagram is empty' if @plantuml.nil? || @plantuml.empty?
|
26
27
|
end
|
27
28
|
|
28
|
-
def
|
29
|
-
return @
|
30
|
-
return @plantuml if @plantuml.nil? || @plantuml.empty?
|
29
|
+
def svg
|
30
|
+
return @svg_diagram unless @svg_diagram.nil?
|
31
31
|
|
32
32
|
@plantuml = @theme.apply(@plantuml)
|
33
|
-
log(plantuml)
|
33
|
+
log(@plantuml)
|
34
34
|
@result = @executor.execute(self)
|
35
|
-
@result
|
36
|
-
@svg = wrap(@result.without_xml_prologue)
|
35
|
+
@svg_diagram = SvgDiagram.new(@result)
|
37
36
|
rescue StandardError => e
|
38
37
|
raise e if @options.raise_errors?
|
39
38
|
|
@@ -42,16 +41,6 @@ module Kramdown
|
|
42
41
|
|
43
42
|
private
|
44
43
|
|
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
44
|
def log(plantuml)
|
56
45
|
@logger.debug 'PlantUML converting diagram:'
|
57
46
|
@logger.debug_multiline plantuml
|
@@ -31,11 +31,11 @@ module Kramdown
|
|
31
31
|
end
|
32
32
|
|
33
33
|
def header(result)
|
34
|
-
if theme_not_found?(result) && !result.
|
34
|
+
if theme_not_found?(result) && !result.plantuml_diagram.nil? && !result.plantuml_diagram.theme.nil?
|
35
35
|
return <<~HEADER
|
36
36
|
Conversion of the following PlantUML result failed because the
|
37
|
-
theme '#{result.
|
38
|
-
'#{result.
|
37
|
+
theme '#{result.plantuml_diagram.theme.name}' can't be found in the directory
|
38
|
+
'#{result.plantuml_diagram.theme.directory}':
|
39
39
|
HEADER
|
40
40
|
end
|
41
41
|
|
@@ -50,9 +50,9 @@ module Kramdown
|
|
50
50
|
end
|
51
51
|
|
52
52
|
def plantuml(result)
|
53
|
-
return nil if result.nil? || result.
|
53
|
+
return nil if result.nil? || result.plantuml_diagram.nil?
|
54
54
|
|
55
|
-
result.
|
55
|
+
result.plantuml_diagram.plantuml
|
56
56
|
end
|
57
57
|
|
58
58
|
def result(result)
|
@@ -2,46 +2,29 @@
|
|
2
2
|
|
3
3
|
require_relative 'log_wrapper'
|
4
4
|
require_relative 'plantuml_error'
|
5
|
-
require_relative '
|
5
|
+
require_relative 'svg_diagram'
|
6
6
|
|
7
7
|
module Kramdown
|
8
8
|
module PlantUml
|
9
9
|
# Executes the PlantUML Java application.
|
10
10
|
class PlantUmlResult
|
11
|
-
attr_reader :
|
11
|
+
attr_reader :plantuml_diagram, :stdout, :stderr, :exitcode
|
12
12
|
|
13
|
-
def initialize(
|
14
|
-
raise ArgumentError, 'diagram cannot be nil' if
|
15
|
-
raise ArgumentError, "diagram must be a #{
|
13
|
+
def initialize(plantuml_diagram, stdout, stderr, exitcode)
|
14
|
+
raise ArgumentError, 'diagram cannot be nil' if plantuml_diagram.nil?
|
15
|
+
raise ArgumentError, "diagram must be a #{PlantUmlDiagram}" unless plantuml_diagram.is_a?(PlantUmlDiagram)
|
16
16
|
raise ArgumentError, 'exitcode cannot be nil' if exitcode.nil?
|
17
17
|
raise ArgumentError, "exitcode must be a #{Integer}" unless exitcode.is_a?(Integer)
|
18
18
|
|
19
|
-
@
|
19
|
+
@plantuml_diagram = plantuml_diagram
|
20
20
|
@stdout = stdout
|
21
21
|
@stderr = stderr
|
22
22
|
@exitcode = exitcode
|
23
23
|
@logger = LogWrapper.init
|
24
24
|
end
|
25
25
|
|
26
|
-
def
|
27
|
-
|
28
|
-
|
29
|
-
xml_prologue_start = '<?xml'
|
30
|
-
xml_prologue_end = '?>'
|
31
|
-
|
32
|
-
start_index = @stdout.index(xml_prologue_start)
|
33
|
-
|
34
|
-
return @stdout if start_index.nil?
|
35
|
-
|
36
|
-
end_index = @stdout.index(xml_prologue_end, xml_prologue_start.length)
|
37
|
-
|
38
|
-
return @stdout if end_index.nil?
|
39
|
-
|
40
|
-
end_index += xml_prologue_end.length
|
41
|
-
|
42
|
-
@stdout.slice! start_index, end_index
|
43
|
-
|
44
|
-
@stdout
|
26
|
+
def svg_diagram
|
27
|
+
@plantuml_diagram.svg
|
45
28
|
end
|
46
29
|
|
47
30
|
def valid?
|
@@ -53,7 +36,7 @@ module Kramdown
|
|
53
36
|
@stderr.include?('CoreText note:')
|
54
37
|
end
|
55
38
|
|
56
|
-
def validate
|
39
|
+
def validate!
|
57
40
|
raise PlantUmlError, self unless valid?
|
58
41
|
|
59
42
|
return if @stderr.nil? || @stderr.empty?
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'none_s'
|
4
|
+
|
5
|
+
module Kramdown
|
6
|
+
module PlantUml
|
7
|
+
# Builds a CSS style string from a hash of style properties.
|
8
|
+
class StyleBuilder
|
9
|
+
def initialize
|
10
|
+
@hash = {}
|
11
|
+
end
|
12
|
+
|
13
|
+
def []=(key, value)
|
14
|
+
return if key.nil?
|
15
|
+
|
16
|
+
case key
|
17
|
+
when :width, :height
|
18
|
+
if none(value)
|
19
|
+
@hash.delete(key)
|
20
|
+
else
|
21
|
+
@hash[key] = value
|
22
|
+
end
|
23
|
+
else
|
24
|
+
self.style = value
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def to_s
|
29
|
+
@hash.sort_by { |key, _| key }.map { |key, value| "#{key}:#{value}" }.join(';')
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def none(value)
|
35
|
+
return true if value.nil?
|
36
|
+
|
37
|
+
value_s = value.to_s.strip
|
38
|
+
|
39
|
+
return true if value_s.empty? || value.none_s?
|
40
|
+
|
41
|
+
false
|
42
|
+
end
|
43
|
+
|
44
|
+
def style=(style)
|
45
|
+
return if style.nil? || style.strip.empty?
|
46
|
+
|
47
|
+
style.split(';').each do |pair|
|
48
|
+
key, value = pair.split(':')
|
49
|
+
key = key.strip.to_sym
|
50
|
+
value = value.strip
|
51
|
+
@hash[key] = value
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rexml/document'
|
4
|
+
require_relative 'none_s'
|
5
|
+
require_relative 'style_builder'
|
6
|
+
require_relative 'plantuml_diagram'
|
7
|
+
|
8
|
+
module Kramdown
|
9
|
+
module PlantUml
|
10
|
+
# A diagram in SVG format.
|
11
|
+
class SvgDiagram
|
12
|
+
def initialize(plantuml_result)
|
13
|
+
raise ArgumentError, 'plantuml_result cannot be nil' if plantuml_result.nil?
|
14
|
+
raise ArgumentError, "plantuml_result must be a #{PlantUmlResult}" unless plantuml_result.is_a?(PlantUmlResult)
|
15
|
+
|
16
|
+
plantuml_result.validate!
|
17
|
+
svg = plantuml_result.stdout
|
18
|
+
@doc = REXML::Document.new svg
|
19
|
+
@source = plantuml_result.plantuml_diagram
|
20
|
+
@style_builder = StyleBuilder.new
|
21
|
+
transfer_options(plantuml_result)
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_s
|
25
|
+
return '' if @doc.root.nil?
|
26
|
+
|
27
|
+
wrapper_doc = REXML::Document.new
|
28
|
+
wrapper_doc.context[:attribute_quote] = :quote
|
29
|
+
wrapper_element = REXML::Element.new('div').tap do |div|
|
30
|
+
div.add_attribute 'class', wrapper_class_name
|
31
|
+
div.add_element @doc.root
|
32
|
+
end
|
33
|
+
|
34
|
+
wrapper_doc.add_element wrapper_element
|
35
|
+
wrapper_doc.to_s
|
36
|
+
end
|
37
|
+
|
38
|
+
def width
|
39
|
+
get_xml_attribute_value(:width)
|
40
|
+
end
|
41
|
+
|
42
|
+
def height
|
43
|
+
get_xml_attribute_value(:height)
|
44
|
+
end
|
45
|
+
|
46
|
+
def style
|
47
|
+
get_xml_attribute_value(:style)
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def wrapper_class_name
|
53
|
+
theme_class = @source.theme.name ? "theme-#{@source.theme.name}" : ''
|
54
|
+
"plantuml #{theme_class}".strip
|
55
|
+
end
|
56
|
+
|
57
|
+
def get_xml_attribute_value(attribute_name)
|
58
|
+
return nil if @doc.root.nil?
|
59
|
+
|
60
|
+
name = attribute_name.to_s
|
61
|
+
value = @doc.root.attributes[name]
|
62
|
+
value.nil? || value.none_s? ? :none : value
|
63
|
+
end
|
64
|
+
|
65
|
+
def manipulate_xml_attribute(attribute_name, value)
|
66
|
+
if value.none_s?
|
67
|
+
remove_xml_attribute(attribute_name)
|
68
|
+
elsif !value.nil? && value.is_a?(String) && !value.strip.empty?
|
69
|
+
set_xml_attribute(attribute_name, value)
|
70
|
+
end
|
71
|
+
|
72
|
+
update_style unless attribute_name == :style || style == :none
|
73
|
+
end
|
74
|
+
|
75
|
+
def remove_xml_attribute(attribute_name)
|
76
|
+
@doc.root.attributes.get_attribute(attribute_name.to_s).remove
|
77
|
+
end
|
78
|
+
|
79
|
+
def set_xml_attribute(attribute_name, value)
|
80
|
+
name = attribute_name.to_s
|
81
|
+
@doc.root.attributes[name] = value
|
82
|
+
@style_builder[attribute_name] = value
|
83
|
+
end
|
84
|
+
|
85
|
+
def update_style
|
86
|
+
style = @style_builder.to_s
|
87
|
+
set_xml_attribute(:style, style)
|
88
|
+
end
|
89
|
+
|
90
|
+
def transfer_options(plantuml_result)
|
91
|
+
return if (options = options(plantuml_result)).nil?
|
92
|
+
|
93
|
+
%i[style width height].each do |attribute|
|
94
|
+
options.public_send(attribute).tap do |option_value|
|
95
|
+
next if option_value.nil?
|
96
|
+
|
97
|
+
option_value = option_value.to_s.strip
|
98
|
+
|
99
|
+
next if option_value.empty?
|
100
|
+
|
101
|
+
manipulate_xml_attribute(attribute, option_value)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def options(plantuml_result)
|
107
|
+
return nil if @doc.root.nil? \
|
108
|
+
|| plantuml_result.nil? \
|
109
|
+
|| plantuml_result.plantuml_diagram.nil?
|
110
|
+
|
111
|
+
plantuml_result.plantuml_diagram.options
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
@@ -8,7 +8,7 @@ module Kramdown
|
|
8
8
|
module PlantUml
|
9
9
|
# Provides theming support for PlantUML
|
10
10
|
class Theme
|
11
|
-
attr_reader :name, :directory
|
11
|
+
attr_reader :name, :directory, :scale
|
12
12
|
|
13
13
|
def initialize(options)
|
14
14
|
raise ArgumentError, 'options cannot be nil' if options.nil?
|
@@ -17,6 +17,7 @@ module Kramdown
|
|
17
17
|
@raise_errors = options.raise_errors?
|
18
18
|
@logger = LogWrapper.init
|
19
19
|
@name = options.theme_name
|
20
|
+
@scale = options.scale
|
20
21
|
@directory = resolve options.theme_directory
|
21
22
|
end
|
22
23
|
|
@@ -26,11 +27,6 @@ module Kramdown
|
|
26
27
|
return plantuml
|
27
28
|
end
|
28
29
|
|
29
|
-
if @name.nil? || @name.empty?
|
30
|
-
@logger.debug 'No theme to apply.'
|
31
|
-
return plantuml.strip
|
32
|
-
end
|
33
|
-
|
34
30
|
theme(plantuml)
|
35
31
|
end
|
36
32
|
|
@@ -59,13 +55,12 @@ module Kramdown
|
|
59
55
|
end
|
60
56
|
|
61
57
|
def theme(plantuml)
|
62
|
-
|
63
|
-
startuml_index = plantuml.index(startuml) + startuml.length
|
58
|
+
theme_string = build_theme_string
|
64
59
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
60
|
+
if theme_string.empty?
|
61
|
+
@logger.debug 'No theme to apply.'
|
62
|
+
return plantuml
|
63
|
+
end
|
69
64
|
|
70
65
|
@logger.debug "Applying #{theme_string.strip}"
|
71
66
|
|
@@ -75,6 +70,18 @@ module Kramdown
|
|
75
70
|
|
76
71
|
plantuml.strip
|
77
72
|
end
|
73
|
+
|
74
|
+
def build_theme_string
|
75
|
+
theme_string = ''
|
76
|
+
|
77
|
+
unless @name.nil? || @name.empty?
|
78
|
+
theme_string << "\n!theme #{@name}"
|
79
|
+
theme_string << " from #{@directory}" unless @directory.nil?
|
80
|
+
end
|
81
|
+
|
82
|
+
theme_string << "\nscale #{@scale}" unless @scale.nil?
|
83
|
+
theme_string
|
84
|
+
end
|
78
85
|
end
|
79
86
|
end
|
80
87
|
end
|
data/lib/kramdown_html.rb
CHANGED
@@ -5,7 +5,7 @@ require 'kramdown-parser-gfm'
|
|
5
5
|
require_relative 'kramdown-plantuml/log_wrapper'
|
6
6
|
require_relative 'kramdown-plantuml/plantuml_error'
|
7
7
|
require_relative 'kramdown-plantuml/options'
|
8
|
-
require_relative 'kramdown-plantuml/
|
8
|
+
require_relative 'kramdown-plantuml/plantuml_diagram'
|
9
9
|
require_relative 'kramdown-plantuml/jekyll_provider'
|
10
10
|
|
11
11
|
module Kramdown
|
@@ -38,8 +38,8 @@ module Kramdown
|
|
38
38
|
end
|
39
39
|
|
40
40
|
def convert_plantuml(plantuml, options)
|
41
|
-
diagram = ::Kramdown::PlantUml::
|
42
|
-
diagram.
|
41
|
+
diagram = ::Kramdown::PlantUml::PlantUmlDiagram.new(plantuml, options)
|
42
|
+
diagram.svg.to_s
|
43
43
|
rescue StandardError => e
|
44
44
|
raise e if options.raise_errors?
|
45
45
|
|
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.
|
4
|
+
version: 1.3.0
|
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-
|
11
|
+
date: 2021-11-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: htmlentities
|
@@ -94,6 +94,20 @@ dependencies:
|
|
94
94
|
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '3.2'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rspec-html-matchers
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0.9'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0.9'
|
97
111
|
- !ruby/object:Gem::Dependency
|
98
112
|
name: rspec-its
|
99
113
|
requirement: !ruby/object:Gem::Requirement
|
@@ -185,13 +199,17 @@ files:
|
|
185
199
|
- lib/kramdown-plantuml.rb
|
186
200
|
- lib/kramdown-plantuml/bool_env.rb
|
187
201
|
- lib/kramdown-plantuml/console_logger.rb
|
188
|
-
- lib/kramdown-plantuml/diagram.rb
|
189
202
|
- lib/kramdown-plantuml/executor.rb
|
203
|
+
- lib/kramdown-plantuml/jekyll_page_processor.rb
|
190
204
|
- lib/kramdown-plantuml/jekyll_provider.rb
|
191
205
|
- lib/kramdown-plantuml/log_wrapper.rb
|
206
|
+
- lib/kramdown-plantuml/none_s.rb
|
192
207
|
- lib/kramdown-plantuml/options.rb
|
208
|
+
- lib/kramdown-plantuml/plantuml_diagram.rb
|
193
209
|
- lib/kramdown-plantuml/plantuml_error.rb
|
194
210
|
- lib/kramdown-plantuml/plantuml_result.rb
|
211
|
+
- lib/kramdown-plantuml/style_builder.rb
|
212
|
+
- lib/kramdown-plantuml/svg_diagram.rb
|
195
213
|
- lib/kramdown-plantuml/theme.rb
|
196
214
|
- lib/kramdown-plantuml/version.rb
|
197
215
|
- lib/kramdown-plantuml/which.rb
|