Class: Metanorma::Standoc::PlantUMLBlockMacroBackend

Inherits:
Object
  • Object
show all
Defined in:
lib/metanorma/standoc/macros_plantuml.rb

Class Method Summary collapse

Class Method Details

.generate_attrs(attrs) ⇒ Object



84
85
86
87
88
89
90
# File 'lib/metanorma/standoc/macros_plantuml.rb', line 84

def self.generate_attrs(attrs)
  %w(id align float title role width height alt)
    .inject({}) do |memo, key|
    memo[key] = attrs[key] if attrs.has_key? key
    memo
  end
end

.generate_file(parent, reader) ⇒ Object

if no :imagesdir: leave image file in plantuml sleep need for windows because dot works in separate process and plantuml process may finish earlier then dot, as result png file maybe not created yet after plantuml finish

# Warning: metanorma/metanorma-standoc#187 Windows Ruby 2.4 will crash if a Tempfile is “mv”ed. This is why we need to copy and then unlink.



36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/metanorma/standoc/macros_plantuml.rb', line 36

def self.generate_file(parent, reader)
  ldir = localdir(parent)
  imagesdir = parent.document.attr("imagesdir")
  umlfile, outfile = save_plantuml parent, reader, ldir
  run(umlfile, outfile) or
    raise "No image output from PlantUML (#{umlfile}, #{outfile})!"
  umlfile.unlink
  path = path_prep(ldir, imagesdir)
  filename = File.basename(outfile.to_s)
  FileUtils.cp(outfile, path) and outfile.unlink
  imagesdir ? filename : File.join(path, filename)
end

.localdir(parent) ⇒ Object



49
50
51
52
53
54
# File 'lib/metanorma/standoc/macros_plantuml.rb', line 49

def self.localdir(parent)
  ret = Metanorma::Utils::localdir(parent.document)
  File.writable?(ret) or
    raise "Destination directory #{ret} not writable for PlantUML!"
  ret
end

.path_prep(localdir, imagesdir) ⇒ Object



56
57
58
59
60
61
62
63
# File 'lib/metanorma/standoc/macros_plantuml.rb', line 56

def self.path_prep(localdir, imagesdir)
  path = Pathname.new(localdir) + (imagesdir || "plantuml")
  path.mkpath
  File.writable?(path) or
    raise "Destination path #{path} not writable for PlantUML!"
  # File.exist?(path) or raise "Destination path #{path} already exists for PlantUML!"
  path
end

.plantuml_binObject



10
11
12
13
14
15
16
# File 'lib/metanorma/standoc/macros_plantuml.rb', line 10

def self.plantuml_bin
  if Gem.win_platform? || which("plantumlc")
    "plantumlc"
  else
    "plantuml"
  end
end

.plantuml_installed?Boolean

Returns:

  • (Boolean)


4
5
6
7
8
# File 'lib/metanorma/standoc/macros_plantuml.rb', line 4

def self.plantuml_installed?
  unless which("plantuml")
    raise "PlantUML not installed"
  end
end

.prep_source(reader) ⇒ Object



75
76
77
78
79
80
81
82
# File 'lib/metanorma/standoc/macros_plantuml.rb', line 75

def self.prep_source(reader)
  src = reader.source
  reader.lines.first.sub(/(?<!\s)\s+$/, "").match /^@startuml($| )/ or
    src = "@startuml\n#{src}\n@enduml\n"
  %r{@enduml\s*$}m.match?(src) or
    raise "@startuml without matching @enduml in PlantUML!"
  src
end

.run(umlfile, outfile) ⇒ Object



18
19
20
21
22
23
24
25
26
# File 'lib/metanorma/standoc/macros_plantuml.rb', line 18

def self.run(umlfile, outfile)
  system "#{plantuml_bin} #{umlfile.path}" or (warn $? and return false)
  i = 0
  until !Gem.win_platform? || File.exist?(outfile) || i == 15
    sleep(1)
    i += 1
  end
  File.exist?(outfile)
end

.save_plantuml(_parent, reader, _localdir) ⇒ Object



65
66
67
68
69
70
71
72
73
# File 'lib/metanorma/standoc/macros_plantuml.rb', line 65

def self.save_plantuml(_parent, reader, _localdir)
  src = prep_source(reader)
  /^@startuml (?<fn>[^\n]+)\n/ =~ src
  Tempfile.open(["plantuml", ".pml"], encoding: "utf-8") do |f|
    f.write(src)
    [f, File.join(File.dirname(f.path),
                  "#{fn || File.basename(f.path, '.pml')}.png")]
  end
end

.which(cmd) ⇒ Object



93
94
95
96
97
98
99
100
101
102
# File 'lib/metanorma/standoc/macros_plantuml.rb', line 93

def self.which(cmd)
  exts = ENV["PATHEXT"] ? ENV["PATHEXT"].split(";") : [""]
  ENV["PATH"].split(File::PATH_SEPARATOR).each do |path|
    exts.each do |ext|
      exe = File.join(path, "#{cmd}#{ext}")
      return exe if File.executable?(exe) && !File.directory?(exe)
    end
  end
  nil
end