kramdown-plantuml 1.1.11 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|