Skip to content

Commit

Permalink
Merge pull request #79 from SwedbankPay/feature/dx-1622_diagram_width
Browse files Browse the repository at this point in the history
DX-1622: Configurable width
  • Loading branch information
asbjornu authored Nov 15, 2021
2 parents f5d339d + 0ce0d33 commit 458b401
Show file tree
Hide file tree
Showing 30 changed files with 656 additions and 127 deletions.
27 changes: 26 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,31 @@ kramdown:
directory: path/to/themes
```

### Dimensions and Styling

It's possible to customize the dimensions of the diagram by providing the
`width` and `height` configuration keys. It's also possible to add arbitrary
styling with the `style` key.

```yaml
kramdown:
plantuml:
width: 200px
height: 100px
style: "border: 1px solid black"
```

To remove the `width`, `height` and `style` attributes from the `<svg />`
element, set the key's value to `none`.

```yaml
kramdown:
plantuml:
width: none
height: none
style: none
```

### Errors

By default, `kramdown-plantuml` will raise an error and crash if something goes
Expand Down Expand Up @@ -199,7 +224,7 @@ agreement][cla].
[codacy]: https://www.codacy.com/gh/SwedbankPay/kramdown-plantuml/dashboard?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=SwedbankPay/kramdown-plantuml&amp;utm_campaign=Badge_Grade
[codecov-badge]: https://codecov.io/gh/SwedbankPay/kramdown-plantuml/branch/main/graph/badge.svg?token=U3QJLVG3HY
[codecov]: https://codecov.io/gh/SwedbankPay/kramdown-plantuml/
[diagram-svg]: ./spec/examples/diagram.svg
[diagram-svg]: ./spec/examples/network-diagram.svg
[fenced]: https://www.markdownguide.org/extended-syntax/#syntax-highlighting
[fork]: https://docs.github.com/en/free-pro-team@latest/github/getting-started-with-github/fork-a-repo
[gem-badge]: https://badge.fury.io/rb/kramdown-plantuml.svg
Expand Down
1 change: 1 addition & 0 deletions kramdown-plantuml.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ Gem::Specification.new do |spec|

spec.add_development_dependency 'rake', '~> 13.0'
spec.add_development_dependency 'rspec', '~> 3.2'
spec.add_development_dependency 'rspec-html-matchers', '>= 0.9'
spec.add_development_dependency 'rspec-its', '~> 1.3'
spec.add_development_dependency 'rubocop', '~> 1.12'
spec.add_development_dependency 'rubocop-rake', '~> 0.6'
Expand Down
2 changes: 1 addition & 1 deletion lib/kramdown-plantuml/executor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ def initialize

def execute(diagram)
raise ArgumentError, 'diagram cannot be nil' if diagram.nil?
raise ArgumentError, "diagram must be a #{Diagram}" unless diagram.is_a?(Diagram)
raise ArgumentError, "diagram must be a #{PlantUmlDiagram}" unless diagram.is_a?(PlantUmlDiagram)

cmd = "java -Djava.awt.headless=true -jar #{@plantuml_jar_file} -tsvg -failfast -pipe #{debug_args}"

Expand Down
4 changes: 2 additions & 2 deletions lib/kramdown-plantuml/jekyll_page_processor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,8 @@ def replace_needle(json)
def decode_and_convert(hash, options)
encoded_plantuml = hash['plantuml']
plantuml = HTMLEntities.new.decode encoded_plantuml
diagram = ::Kramdown::PlantUml::Diagram.new(plantuml, options)
diagram.convert_to_svg
diagram = ::Kramdown::PlantUml::PlantUmlDiagram.new(plantuml, options)
diagram.svg
end

def logger
Expand Down
17 changes: 17 additions & 0 deletions lib/kramdown-plantuml/none_s.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# frozen_string_literal: true

# Ruby's Object class.
class Object
# Performs a case insensitive, trimmed comparison of the Object and the
# String 'none' and Symbol :none. Returns true if the comparison is true,
# otherwise false.
#
# @return [Boolean] True if the Object is equal to 'none' or :none,
# otherwise false.
def none_s?
return false if nil?
return true if self == :none

to_s.strip.casecmp?('none')
end
end
21 changes: 20 additions & 1 deletion lib/kramdown-plantuml/options.rb
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
# frozen_string_literal: true

require_relative 'none_s'
require_relative 'log_wrapper'

module Kramdown
module PlantUml
# Options for PlantUML processing
class Options
attr_reader :theme_name, :theme_directory
attr_reader :theme_name, :theme_directory, :width, :height, :style

def initialize(options_hash = {})
@logger = LogWrapper.init
@options = massage(options_hash) || {}
@raise_errors = extract_raise_errors(@options)
extract_theme_options(@options)
extract_style_options(@options)
end

def raise_errors?
Expand Down Expand Up @@ -64,6 +66,23 @@ def extract_raise_errors(options)
boolean(raise_errors, true)
end

def extract_style_options(options)
return if options.nil? || options.empty?

set_instance_property(:width, options)
set_instance_property(:height, options)
set_instance_property(:style, options)
end

def set_instance_property(name, options)
return unless options.key? name

value = options[name]
value = :none if value.none_s?
prop_name = "@#{name}".to_sym
instance_variable_set(prop_name, value)
end

def massage(options_hash)
if options_hash.nil? || !options_hash.is_a?(Hash) || options_hash.empty?
@logger.debug 'No options provided'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
# frozen_string_literal: true

require_relative 'version'
require_relative 'theme'
require_relative 'executor'
require_relative 'log_wrapper'
require_relative 'options'
require_relative 'plantuml_error'
require_relative 'log_wrapper'
require_relative 'executor'
require_relative 'svg_diagram'
require_relative 'theme'
require_relative 'version'

module Kramdown
module PlantUml
# Represents a PlantUML diagram that can be converted to SVG.
class Diagram
attr_reader :theme, :plantuml, :result
class PlantUmlDiagram
attr_reader :theme, :plantuml, :result, :options

def initialize(plantuml, options)
raise ArgumentError, 'options cannot be nil' if options.nil?
Expand All @@ -25,15 +26,13 @@ def initialize(plantuml, options)
@logger.warn 'PlantUML diagram is empty' if @plantuml.nil? || @plantuml.empty?
end

def convert_to_svg
return @svg unless @svg.nil?
return @plantuml if @plantuml.nil? || @plantuml.empty?
def svg
return @svg_diagram unless @svg_diagram.nil?

@plantuml = @theme.apply(@plantuml)
log(plantuml)
@result = @executor.execute(self)
@result.validate
@svg = wrap(@result.without_xml_prologue)
@svg_diagram = SvgDiagram.new(@result)
rescue StandardError => e
raise e if @options.raise_errors?

Expand All @@ -42,16 +41,6 @@ def convert_to_svg

private

def wrap(svg)
theme_class = @theme.name ? "theme-#{@theme.name}" : ''
class_name = "plantuml #{theme_class}".strip

wrapper_element_start = "<div class=\"#{class_name}\">"
wrapper_element_end = '</div>'

"#{wrapper_element_start}#{svg}#{wrapper_element_end}"
end

def log(plantuml)
@logger.debug 'PlantUML converting diagram:'
@logger.debug_multiline plantuml
Expand Down
10 changes: 5 additions & 5 deletions lib/kramdown-plantuml/plantuml_error.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,11 @@ def create_message(result)
end

def header(result)
if theme_not_found?(result) && !result.diagram.nil? && !result.diagram.theme.nil?
if theme_not_found?(result) && !result.plantuml_diagram.nil? && !result.plantuml_diagram.theme.nil?
return <<~HEADER
Conversion of the following PlantUML result failed because the
theme '#{result.diagram.theme.name}' can't be found in the directory
'#{result.diagram.theme.directory}':
theme '#{result.plantuml_diagram.theme.name}' can't be found in the directory
'#{result.plantuml_diagram.theme.directory}':
HEADER
end

Expand All @@ -50,9 +50,9 @@ def theme_not_found?(result)
end

def plantuml(result)
return nil if result.nil? || result.diagram.nil?
return nil if result.nil? || result.plantuml_diagram.nil?

result.diagram.plantuml
result.plantuml_diagram.plantuml
end

def result(result)
Expand Down
35 changes: 9 additions & 26 deletions lib/kramdown-plantuml/plantuml_result.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,46 +2,29 @@

require_relative 'log_wrapper'
require_relative 'plantuml_error'
require_relative 'diagram'
require_relative 'svg_diagram'

module Kramdown
module PlantUml
# Executes the PlantUML Java application.
class PlantUmlResult
attr_reader :diagram, :stdout, :stderr, :exitcode
attr_reader :plantuml_diagram, :stdout, :stderr, :exitcode

def initialize(diagram, stdout, stderr, exitcode)
raise ArgumentError, 'diagram cannot be nil' if diagram.nil?
raise ArgumentError, "diagram must be a #{Diagram}" unless diagram.is_a?(Diagram)
def initialize(plantuml_diagram, stdout, stderr, exitcode)
raise ArgumentError, 'diagram cannot be nil' if plantuml_diagram.nil?
raise ArgumentError, "diagram must be a #{PlantUmlDiagram}" unless plantuml_diagram.is_a?(PlantUmlDiagram)
raise ArgumentError, 'exitcode cannot be nil' if exitcode.nil?
raise ArgumentError, "exitcode must be a #{Integer}" unless exitcode.is_a?(Integer)

@diagram = diagram
@plantuml_diagram = plantuml_diagram
@stdout = stdout
@stderr = stderr
@exitcode = exitcode
@logger = LogWrapper.init
end

def without_xml_prologue
return @stdout if @stdout.nil? || @stdout.empty?

xml_prologue_start = '<?xml'
xml_prologue_end = '?>'

start_index = @stdout.index(xml_prologue_start)

return @stdout if start_index.nil?

end_index = @stdout.index(xml_prologue_end, xml_prologue_start.length)

return @stdout if end_index.nil?

end_index += xml_prologue_end.length

@stdout.slice! start_index, end_index

@stdout
def svg_diagram
@plantuml_diagram.svg
end

def valid?
Expand All @@ -53,7 +36,7 @@ def valid?
@stderr.include?('CoreText note:')
end

def validate
def validate!
raise PlantUmlError, self unless valid?

return if @stderr.nil? || @stderr.empty?
Expand Down
56 changes: 56 additions & 0 deletions lib/kramdown-plantuml/style_builder.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# frozen_string_literal: true

require_relative 'none_s'

module Kramdown
module PlantUml
# Builds a CSS style string from a hash of style properties.
class StyleBuilder
def initialize
@hash = {}
end

def []=(key, value)
return if key.nil?

case key
when :width, :height
if none(value)
@hash.delete(key)
else
@hash[key] = value
end
else
self.style = value
end
end

def to_s
@hash.sort_by { |key, _| key }.map { |key, value| "#{key}:#{value}" }.join(';')
end

private

def none(value)
return true if value.nil?

value_s = value.to_s.strip

return true if value_s.empty? || value.none_s?

false
end

def style=(style)
return if style.nil? || style.strip.empty?

style.split(';').each do |pair|
key, value = pair.split(':')
key = key.strip.to_sym
value = value.strip
@hash[key] = value
end
end
end
end
end
Loading

0 comments on commit 458b401

Please sign in to comment.