require "asciidoctor/extensions"
require "fileutils"
module Asciidoctor
module Standoc
class AltTermInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
use_dsl
named :alt
parse_content_as :text
using_format :short
def process(parent, _target, attrs)
out = Asciidoctor::Inline.new(parent, :quoted, attrs["text"]).convert
%{#{out}}
end
end
class DeprecatedTermInlineMacro <
Asciidoctor::Extensions::InlineMacroProcessor
use_dsl
named :deprecated
parse_content_as :text
using_format :short
def process(parent, _target, attrs)
out = Asciidoctor::Inline.new(parent, :quoted, attrs["text"]).convert
%{#{out}}
end
end
class DomainTermInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
use_dsl
named :domain
parse_content_as :text
using_format :short
def process(parent, _target, attrs)
out = Asciidoctor::Inline.new(parent, :quoted, attrs["text"]).convert
%{#{out}}
end
end
class ToDoAdmonitionBlock < Extensions::BlockProcessor
use_dsl
named :TODO
on_contexts :example, :paragraph
def process parent, reader, attrs
attrs['name'] = 'todo'
attrs['caption'] = 'TODO'
create_block parent, :admonition, reader.lines, attrs, content_model: :compound
end
end
class ToDoInlineAdmonitionBlock < Extensions::Treeprocessor
def process document
(document.find_by context: :paragraph).each do |para|
next unless /^TODO: /.match para.lines[0]
parent = para.parent
para.set_attr("name", "todo")
para.set_attr("caption", "TODO")
para.lines[0].sub!(/^TODO: /, "")
todo = Block.new parent, :admonition, attributes: para.attributes,
source: para.lines, content_model: :compound
parent.blocks[parent.blocks.index(para)] = todo
end
end
end
class PlantUMLBlockMacroBackend
# https://stackoverflow.com/questions/2108727/which-in-ruby-checking-if-program-exists-in-path-from-ruby
def self.plantuml_installed?
cmd = "plantuml"
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
def self.generate_file parent, reader
src = reader.source
!reader.lines.first.sub(/\s+$/, "").match /^@startuml($| )/ or
src = "@startuml\n#{src}\n@enduml\n"
/^@startuml (?[^\n]+)\n/ =~ src
filename ||= parent.document.reader.lineno
FileUtils.mkdir_p "plantuml"
File.open("plantuml/#{filename}.pml", "w") { |f| f.write src }
system "plantuml plantuml/#{filename}.pml"
filename
end
def self.generate_attrs attrs
through_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
end
class PlantUMLBlockMacro < Asciidoctor::Extensions::BlockProcessor
use_dsl
named :plantuml
on_context :literal
parse_content_as :raw
def process(parent, reader, attrs)
if PlantUMLBlockMacroBackend.plantuml_installed?
filename = PlantUMLBlockMacroBackend.generate_file parent, reader
through_attrs = PlantUMLBlockMacroBackend.generate_attrs attrs
through_attrs["target"] = "plantuml/#{filename}.png"
create_image_block parent, through_attrs
else
warn "PlantUML not installed"
# attrs.delete(1) : remove the style attribute
attrs["language"] = "plantuml"
create_listing_block parent, reader.source, attrs.reject { |k, v| k == 1 }
end
end
end
end
end