asciidoctor-plantuml-0.0.7/0000755000175000017500000000000013124404241017134 5ustar balasankarcbalasankarcasciidoctor-plantuml-0.0.7/test/0000755000175000017500000000000013124404241020113 5ustar balasankarcbalasankarcasciidoctor-plantuml-0.0.7/test/test_plantuml.rb0000644000175000017500000001240013124404241023330 0ustar balasankarcbalasankarcrequire "test/unit" require "asciidoctor" require "stringio" require "nokogiri" require "asciidoctor-plantuml" DOC_BASIC = <<-eos = Hello PlantUML! [plantuml, format="png"] -- User -> (Start) User --> (Use the application) : Label -- eos DOC_BASIC2 = <<-eos = Hello PlantUML! [plantuml, format="png"] @startuml User -> (Start) User --> (Use the application) : Label @enduml eos DOC_ID = <<-eos = Hello PlantUML! [plantuml, format="png", id="myId"] User -> (Start) User --> (Use the application) : Label eos DOC_DIM = <<-eos = Hello PlantUML! [plantuml, format="png", width="100px", height="50px"] User -> (Start) User --> (Use the application) : Label eos DOC_ALT = <<-eos = Hello PlantUML! [plantuml, format="png", alt="alt"] User -> (Start) User --> (Use the application) : Label eos DOC_BAD_FORMAT = <<-eos = Hello PlantUML! [plantuml, format="jpg"] User -> (Start) User --> (Use the application) : Label eos DOC_MULTI = <<-eos = Hello PlantUML! [plantuml, format="png"] User -> (Start) User --> (Use the application) : Label [plantuml, format="png"] User -> (Start) User --> (Use the application) : Label [plantuml, format="txt"] User -> (Start) User --> (Use the application) : Label eos DOC_TXT = <<-eos = Hello PlantUML! [plantuml, format="txt"] -- User -> (Start) User --> (Use the application) : Label -- eos class PlantUmlTest < Test::Unit::TestCase GENURL = "http://localhost:8080/plantuml/png/U9npA2v9B2efpStX2YrEBLBGjLFG20Q9Q4Bv804WIw4a8rKXiQ0W9pCviIGpFqzJmKh19p4fDOVB8JKl1QWT05kd5wq0" def setup Asciidoctor::PlantUml.configure do |c| c.url = "http://localhost:8080/plantuml" c.txt_enable = true end end def test_plantuml_block_processor html = ::Asciidoctor.convert(StringIO.new(DOC_BASIC), backend: "html5") page = Nokogiri::HTML(html) elements = page.css('img.plantuml') assert_equal elements.size, 1 element = elements.first assert_equal GENURL, element["src"] end def test_plantuml_block_processor2 html = ::Asciidoctor.convert(StringIO.new(DOC_BASIC2), backend: "html5") page = Nokogiri::HTML(html) elements = page.css('img.plantuml') assert_equal elements.size, 1 element = elements.first assert_equal GENURL, element["src"] end def test_plantuml_id_attribute html = ::Asciidoctor.convert(StringIO.new(DOC_ID), backend: "html5") page = Nokogiri::HTML(html) elements = page.css('img.plantuml') assert_equal elements.size, 1 element = elements.first assert_equal "myId", element["id"] end def test_plantuml_dimension_attribute html = ::Asciidoctor.convert(StringIO.new(DOC_DIM), backend: "html5") page = Nokogiri::HTML(html) elements = page.css('img.plantuml') assert_equal elements.size, 1 element = elements.first assert_equal "100px", element["width"] assert_equal "50px", element["height"] end def test_plantuml_alt_attribute html = ::Asciidoctor.convert(StringIO.new(DOC_ALT), backend: "html5") page = Nokogiri::HTML(html) elements = page.css('img.plantuml') assert_equal elements.size, 1 element = elements.first assert_equal "alt", element["alt"] end def test_should_show_bad_format html = ::Asciidoctor.convert(StringIO.new(DOC_BAD_FORMAT), backend: "html5") page = Nokogiri::HTML(html) elements = page.css('pre.plantuml-error') assert_equal elements.size, 1 end def test_plantuml_multiple html = ::Asciidoctor.convert(StringIO.new(DOC_MULTI), backend: "html5") page = Nokogiri::HTML(html) elements = page.css('img.plantuml') assert elements.size >= 2 elements = page.css('.plantuml-error') assert_equal elements.size, 0 end def test_plantuml_bad_server Asciidoctor::PlantUml.configure do |c| c.url = "http://nonexistent.com/plantuml" end html = ::Asciidoctor.convert(StringIO.new(DOC_MULTI), backend: "html5") page = Nokogiri::HTML(html) elements = page.css('img.plantuml') assert_equal elements.size, 3 elements = page.css('.plantuml-error') assert_equal elements.size, 0 end def test_plantuml_invalid_uri Asciidoctor::PlantUml.configure do |c| c.url = "ftp://test.com" end html = ::Asciidoctor.convert(StringIO.new(DOC_BASIC), backend: "html5") page = Nokogiri::HTML(html) elements = page.css('pre.plantuml-error') assert_equal elements.size, 1 end def test_plantuml_nil_uri Asciidoctor::PlantUml.configure do |c| c.url = nil end html = ::Asciidoctor.convert(StringIO.new(DOC_BASIC), backend: "html5") page = Nokogiri::HTML(html) elements = page.css('pre.plantuml-error') assert_equal elements.size, 1 end def test_plantuml_empty_uri Asciidoctor::PlantUml.configure do |c| c.url = "" end html = ::Asciidoctor.convert(StringIO.new(DOC_BASIC), backend: "html5") page = Nokogiri::HTML(html) elements = page.css('pre.plantuml-error') assert_equal elements.size, 1 end def test_disable_txt Asciidoctor::PlantUml.configure do |c| c.url = "http://localhost:8080/plantuml" c.txt_enable = false end html = ::Asciidoctor.convert(StringIO.new(DOC_TXT), backend: "html5") page = Nokogiri::HTML(html) elements = page.css('pre.plantuml-error') assert_equal elements.size, 1 end end asciidoctor-plantuml-0.0.7/lib/0000755000175000017500000000000013124404241017702 5ustar balasankarcbalasankarcasciidoctor-plantuml-0.0.7/lib/asciidoctor-plantuml.rb0000644000175000017500000000031213124404241024360 0ustar balasankarcbalasankarcrequire 'asciidoctor' require 'asciidoctor/extensions' require_relative 'asciidoctor-plantuml/plantuml' Asciidoctor::Extensions.register do block Asciidoctor::PlantUml::BlockProcessor, :plantuml end asciidoctor-plantuml-0.0.7/lib/asciidoctor-plantuml/0000755000175000017500000000000013124404241024037 5ustar balasankarcbalasankarcasciidoctor-plantuml-0.0.7/lib/asciidoctor-plantuml/plantuml.rb0000644000175000017500000001742113124404241026225 0ustar balasankarcbalasankarcrequire 'uri' require 'zlib' require 'open-uri' require 'net/http' module Asciidoctor module PlantUml class Configuration DEFAULT_URL = ENV["PLANTUML_URL"] || "" attr_accessor :url, :txt_enable, :svg_enable, :png_enable def initialize @url = DEFAULT_URL @txt_enable = true @svg_enable = true @png_enable = true end end class << self attr_writer :configuration end def self.configuration @configuration ||= Configuration.new end def self.configure yield(configuration) end class Processor FORMATS = ["png", "svg", "txt"] DEFAULT_FORMAT = FORMATS[0] class << self def valid_format?(format) FORMATS.include?(format) end def server_url PlantUml::configuration.url end def txt_enabled? PlantUml::configuration.txt_enable end def png_enabled? PlantUml::configuration.png_enable end def svg_enabled? PlantUml::configuration.svg_enable end def enabled? txt_enabled? || png_enabled? || svg_enabled? end def plantuml_content(code, attrs = {}) format = attrs["format"] || DEFAULT_FORMAT if !enabled? return plantuml_disabled_content(code, attrs) end if !valid_uri?(server_url) return plantuml_server_unavailable_content(server_url, attrs) end case format when "png" plantuml_img_content(code, format, attrs) when "txt" if txt_enabled? plantuml_txt_content(code, format, attrs) else plantuml_invalid_content(format, attrs) end when "svg" plantuml_img_content(code, format, attrs) else plantuml_invalid_content(format, attrs) end end # Compression code used to generate PlantUML URLs. Taken directly from the # Transcoder class in the PlantUML java code. def gen_url(text, format) result = "" compressedData = Zlib::Deflate.deflate(text) compressedData.chars.each_slice(3) do |bytes| #print bytes[0], ' ' , bytes[1] , ' ' , bytes[2] b1 = bytes[0].nil? ? 0 : (bytes[0].ord & 0xFF) b2 = bytes[1].nil? ? 0 : (bytes[1].ord & 0xFF) b3 = bytes[2].nil? ? 0 : (bytes[2].ord & 0xFF) result += append3bytes(b1, b2, b3) end join_paths(server_url, "/#{format}/", result).to_s end private def plantuml_txt_content(code, format, attrs = {}) begin url = gen_url(code, format) open(url) do |f| plantuml_ascii_content(f.read, format, attrs) end rescue plantuml_img_content(code, format, attrs) end end def plantuml_ascii_content(code, format, attrs = {}) content = "
" content += "
" content += "
\n"
          content += code
          content +="
" content += "
" content += "
" end def plantuml_img_content(code, format, attrs = {}) content = "
" content += "
" content += "" content += "
" content += "
" end def plantuml_invalid_content(format, attrs = {}) content = "
" content += "
" content += "
 "
          content += "PlantUML Error: Invalid format \"#{format}\""
          content +="
" content += "
" content += "
" end def plantuml_server_unavailable_content(url, attrs = {}) content = "
" content += "
" content += "
 "
          content += "PlantUML Error: cannot connect to PlantUML server at \"#{url}\""
          content +="
" content += "
" content += "
" end def plantuml_disabled_content(code, attrs = {}) content = "
" content += "
" content += "
\n"
          content += code
          content +="
" content += "
" content += "
" end def encode6bit(b) if b < 10 return ('0'.ord + b).chr end b = b - 10 if b < 26 return ('A'.ord + b).chr end b = b - 26 if b < 26 return ('a'.ord + b).chr end b = b - 26 if b == 0 return '-' end if b == 1 return '_' end return '?' end def append3bytes(b1, b2, b3) c1 = b1 >> 2 c2 = ((b1 & 0x3) << 4) | (b2 >> 4) c3 = ((b2 & 0xF) << 2) | (b3 >> 6) c4 = b3 & 0x3F return encode6bit(c1 & 0x3F).chr + encode6bit(c2 & 0x3F).chr + encode6bit(c3 & 0x3F).chr + encode6bit(c4 & 0x3F).chr end # Make a call to the PlantUML server with the simplest diagram possible to # check if the server is available or not. def check_server(check_url) response = Net::HTTP.get_response(URI(check_url)) return response.is_a?(Net::HTTPSuccess) rescue return false end def valid_uri?(uri) !(uri =~ /\A#{URI::regexp(['http', 'https'])}\z/).nil? end def join_paths(*paths, separator: '/') paths = paths.compact.reject(&:empty?) last = paths.length - 1 paths.each_with_index.map { |path, index| expand_path(path, index, last, separator) }.join end def expand_path(path, current, last, separator) if path.start_with?(separator) && current != 0 path = path[1..-1] end unless path.end_with?(separator) || current == last path = [path, separator] end path end end end class BlockProcessor < Asciidoctor::Extensions::BlockProcessor def process(parent, target, attrs) lines = target.lines if !(target.lines[0] =~ /@startuml/) lines = ["@startuml"] + target.lines end if !(target.lines[-1] =~ /@enduml/) lines += ["@enduml"] end content = Processor.plantuml_content(lines.join("\n"), attrs) return create_plantuml_block(parent, content) end private def create_plantuml_block(parent, content) Asciidoctor::Block.new parent, :pass, :content_model => :raw, :source => content, :subs => :default end end end end asciidoctor-plantuml-0.0.7/lib/asciidoctor-plantuml/version.rb0000644000175000017500000000010513124404241026045 0ustar balasankarcbalasankarcmodule Asciidoctor module PlantUML VERSION = "0.0.7" end end asciidoctor-plantuml-0.0.7/asciidoctor-plantuml.gemspec0000644000175000017500000000372413124404241024644 0ustar balasankarcbalasankarc######################################################### # This file has been automatically generated by gem2tgz # ######################################################### # -*- encoding: utf-8 -*- # stub: asciidoctor-plantuml 0.0.7 ruby lib Gem::Specification.new do |s| s.name = "asciidoctor-plantuml".freeze s.version = "0.0.7" s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.require_paths = ["lib".freeze] s.authors = ["Horacio Sanson".freeze] s.date = "2017-01-22" s.description = "Asciidoctor PlantUML extension".freeze s.email = ["hsanson@gmail.com".freeze] s.files = ["lib/asciidoctor-plantuml.rb".freeze, "lib/asciidoctor-plantuml/plantuml.rb".freeze, "lib/asciidoctor-plantuml/version.rb".freeze, "test/test_plantuml.rb".freeze] s.homepage = "https://github.com/hsanson/asciidoctor-plantuml".freeze s.licenses = ["MIT".freeze] s.rubygems_version = "2.5.2".freeze s.summary = "An extension for Asciidoctor that enables support for PlantUML diagrams.".freeze s.test_files = ["test/test_plantuml.rb".freeze] if s.respond_to? :specification_version then s.specification_version = 4 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_runtime_dependency(%q.freeze, ["~> 1.5"]) s.add_development_dependency(%q.freeze, ["~> 1.3"]) s.add_development_dependency(%q.freeze, ["~> 1.6"]) s.add_development_dependency(%q.freeze, ["~> 10.5"]) else s.add_dependency(%q.freeze, ["~> 1.5"]) s.add_dependency(%q.freeze, ["~> 1.3"]) s.add_dependency(%q.freeze, ["~> 1.6"]) s.add_dependency(%q.freeze, ["~> 10.5"]) end else s.add_dependency(%q.freeze, ["~> 1.5"]) s.add_dependency(%q.freeze, ["~> 1.3"]) s.add_dependency(%q.freeze, ["~> 1.6"]) s.add_dependency(%q.freeze, ["~> 10.5"]) end end