asciidoctor-plantuml 0.0.9 → 0.0.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9e836d29f06c357381929224f4c3c344aa1eea0288ac5aff95b391898ffd0e80
4
- data.tar.gz: e02e8fa50763daa1c78d86e8a9c4af7be72905c45de61ae4c60b8d7bf9e3a3fb
3
+ metadata.gz: '0758c3c21b6b684c8d1659332edbb2dd21e2733973cf59e8c4317754f1697505'
4
+ data.tar.gz: 5ea7379ddaf79330b11930a719b03b97df72580da00a2b291121378b5a785503
5
5
  SHA512:
6
- metadata.gz: 40d310baa03ed8f773d457bdde42ed92e7ef387c1bde39ef37475117a95b8c2544f7cf7420623491fbcbf0fcd024f03c8ad4139289728a7b4e010033ddea0853
7
- data.tar.gz: 1ca5d165518845bc57f5c0ddb8fbdddbcb52127faa950ebe51b551cd1a4604576409d6562a5035ec3dbbeb4f3c2577e1937a33446b4b38aff913b62fc2836551
6
+ metadata.gz: 647dfb74a0015698ffb4b85c72f35c7c299a52ac7bdff85fe2d4252d891cceadd636f0008089420d91e144d39e74c88dc080234d273f81b6f3175a586156ba56
7
+ data.tar.gz: cc9da76d59762c3dd34570a77d0b9c4ddb826af087798b34068d14bcbb8f5caf19f5cc075b1057b143cb419b88dc1e19117abef886ebaaa782984622e68272b6
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'asciidoctor'
2
4
  require 'asciidoctor/extensions'
3
- require_relative 'asciidoctor-plantuml/plantuml'
5
+ require_relative 'asciidoctor_plantuml/plantuml'
4
6
 
5
7
  Asciidoctor::Extensions.register do
6
8
  block Asciidoctor::PlantUml::BlockProcessor, :plantuml
@@ -0,0 +1,288 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'uri'
4
+ require 'open-uri'
5
+ require 'zlib'
6
+ require 'net/http'
7
+
8
+ module Asciidoctor
9
+ # PlantUML Module
10
+ module PlantUml
11
+ # PlantUML Configuration
12
+ class Configuration
13
+ DEFAULT_URL = ENV['PLANTUML_URL'] || ''
14
+ DEFAULT_ENCODING = ENV['PLANTUML_ENCODING'] || 'legacy'
15
+
16
+ attr_accessor :url, :txt_enable, :svg_enable, :png_enable, :encoding
17
+
18
+ def initialize
19
+ @url = DEFAULT_URL
20
+ @txt_enable = true
21
+ @svg_enable = true
22
+ @png_enable = true
23
+ @encoding = DEFAULT_ENCODING
24
+ end
25
+ end
26
+
27
+ class << self
28
+ attr_writer :configuration
29
+ end
30
+
31
+ def self.configuration
32
+ @configuration ||= Configuration.new
33
+ end
34
+
35
+ def self.configure
36
+ yield(configuration)
37
+ end
38
+
39
+ # PlantUML Processor
40
+ class Processor
41
+ FORMATS = %w[png svg txt].freeze
42
+ DEFAULT_FORMAT = FORMATS[0]
43
+
44
+ ENCODINGS = %w[legacy deflate].freeze
45
+ DEFAULT_ENCODING = ENCODINGS[0]
46
+
47
+ ENCODINGS_MAGIC_STRINGS_MAP = Hash.new('')
48
+ ENCODINGS_MAGIC_STRINGS_MAP['deflate'] = '~1'
49
+
50
+ URI_SCHEMES_REGEXP = ::URI::DEFAULT_PARSER.make_regexp(%w[http https])
51
+
52
+ class << self
53
+ def valid_format?(format)
54
+ FORMATS.include?(format)
55
+ end
56
+
57
+ def valid_encoding?(encoding)
58
+ ENCODINGS.include?(encoding)
59
+ end
60
+
61
+ def server_url
62
+ PlantUml.configuration.url
63
+ end
64
+
65
+ def txt_enabled?
66
+ PlantUml.configuration.txt_enable
67
+ end
68
+
69
+ def png_enabled?
70
+ PlantUml.configuration.png_enable
71
+ end
72
+
73
+ def svg_enabled?
74
+ PlantUml.configuration.svg_enable
75
+ end
76
+
77
+ def enabled?
78
+ txt_enabled? || png_enabled? || svg_enabled?
79
+ end
80
+
81
+ def plantuml_content_format(code, format, attrs = {})
82
+ if %w[png svg txt].include?(format) &&
83
+ method("#{format}_enabled?").call
84
+ method("plantuml_#{format}_content").call(code, format, attrs)
85
+ else
86
+ plantuml_invalid_content(format, attrs)
87
+ end
88
+ end
89
+
90
+ def plantuml_content(code, attrs = {})
91
+ format = attrs['format'] || DEFAULT_FORMAT
92
+
93
+ return plantuml_disabled_content(code, attrs) unless enabled?
94
+
95
+ return plantuml_server_unavailable_content(server_url, attrs) unless valid_uri?(server_url)
96
+
97
+ plantuml_content_format(code, format, attrs)
98
+ end
99
+
100
+ # Compression code used to generate PlantUML URLs. Taken directly from
101
+ # the transcoder class in the PlantUML java code.
102
+ def gen_url(text, format)
103
+ result = ''
104
+ result += encoding_magic_prefix
105
+ compressed_data = Zlib::Deflate.deflate(text)
106
+ compressed_data.chars.each_slice(3) do |bytes|
107
+ # print bytes[0], ' ' , bytes[1] , ' ' , bytes[2]
108
+ b1 = bytes[0].nil? ? 0 : (bytes[0].ord & 0xFF)
109
+ b2 = bytes[1].nil? ? 0 : (bytes[1].ord & 0xFF)
110
+ b3 = bytes[2].nil? ? 0 : (bytes[2].ord & 0xFF)
111
+ result += append3bytes(b1, b2, b3)
112
+ end
113
+ join_paths(server_url, "#{format}/", result).to_s
114
+ end
115
+
116
+ private
117
+
118
+ def plantuml_txt_content(code, format, attrs = {})
119
+ url = gen_url(code, format)
120
+ URI(url).open do |f|
121
+ plantuml_ascii_content(f.read, attrs)
122
+ end
123
+ rescue OpenURI::HTTPError, Errno::ECONNREFUSED, SocketError
124
+ plantuml_png_content(code, format, attrs)
125
+ end
126
+
127
+ def plantuml_ascii_content(code, attrs = {})
128
+ content = '<div class="listingblock">'
129
+ content += '<div class="content">'
130
+ content += '<pre '
131
+ content += "id=\"#{attrs['id']}\" " if attrs['id']
132
+ content += 'class="plantuml">\n'
133
+ content += code
134
+ content += '</pre>'
135
+ content += '</div>'
136
+ content + '</div>'
137
+ end
138
+
139
+ def plantuml_png_content(code, format, attrs = {})
140
+ content = '<div class="imageblock">'
141
+ content += '<div class="content">'
142
+ content += '<img '
143
+ content += "id=\"#{attrs['id']}\" " if attrs['id']
144
+ content += 'class="plantuml" '
145
+ content += "width=\"#{attrs['width']}\" " if attrs['width']
146
+ content += "height=\"#{attrs['height']}\" " if attrs['height']
147
+ content += "alt=\"#{attrs['alt']}\" " if attrs['alt']
148
+ content += "src=\"#{gen_url(code, format)}\" />"
149
+ content += '</div>'
150
+ content + '</div>'
151
+ end
152
+
153
+ def plantuml_svg_content(code, format, attrs = {})
154
+ content = '<div class="imageblock">'
155
+ content += '<div class="content">'
156
+ content += '<object type="image/svg+xml" '
157
+ content += "data=\"#{gen_url(code, format)}\" "
158
+ content += "id=\"#{attrs['id']}\" " if attrs['id']
159
+ content += "width=\"#{attrs['width']}\" " if attrs['width']
160
+ content += "height=\"#{attrs['height']}\" " if attrs['height']
161
+ content += '>'
162
+ attrs['id'] = 'fallback_' + attrs['id'] if attrs['id']
163
+ content += plantuml_png_content(code, format, attrs)
164
+ content += '</object>'
165
+ content += '</div>'
166
+ content + '</div>'
167
+ end
168
+
169
+ def plantuml_invalid_content(format, attrs = {})
170
+ error = "PlantUML Error: Invalid format \"#{format}\""
171
+ _plantuml_error_content(error, attrs)
172
+ end
173
+
174
+ def plantuml_server_unavailable_content(url, attrs = {})
175
+ error = "Error: cannot connect to PlantUML server at \"#{url}\""
176
+ _plantuml_error_content(error, attrs)
177
+ end
178
+
179
+ def plantuml_disabled_content(code, attrs = {})
180
+ _plantuml_error_content(code, attrs)
181
+ end
182
+
183
+ def _plantuml_error_content(error, attrs = {})
184
+ content = '<div class="listingblock">'
185
+ content += '<div class="content">'
186
+ content += '<pre '
187
+ content += "id=\"#{attrs['id']}\" " if attrs['id']
188
+ content += 'class="plantuml plantuml-error">\n'
189
+ content += error
190
+ content += '</pre>'
191
+ content += '</div>'
192
+ content + '</div>'
193
+ end
194
+
195
+ def encode6bit(bit)
196
+ return ('0'.ord + bit).chr if bit < 10
197
+
198
+ bit -= 10
199
+ return ('A'.ord + bit).chr if bit < 26
200
+
201
+ bit -= 26
202
+ return ('a'.ord + bit).chr if bit < 26
203
+
204
+ bit -= 26
205
+ return '-' if bit.zero?
206
+
207
+ return '_' if bit == 1
208
+
209
+ '?'
210
+ end
211
+
212
+ def append3bytes(bit1, bit2, bit3)
213
+ c1 = bit1 >> 2
214
+ c2 = ((bit1 & 0x3) << 4) | (bit2 >> 4)
215
+ c3 = ((bit2 & 0xF) << 2) | (bit3 >> 6)
216
+ c4 = bit3 & 0x3F
217
+ encode6bit(c1 & 0x3F).chr +
218
+ encode6bit(c2 & 0x3F).chr +
219
+ encode6bit(c3 & 0x3F).chr +
220
+ encode6bit(c4 & 0x3F).chr
221
+ end
222
+
223
+ def encoding_magic_prefix
224
+ ENCODINGS_MAGIC_STRINGS_MAP[PlantUml.configuration.encoding]
225
+ end
226
+
227
+ # Make a call to the PlantUML server with the simplest diagram possible
228
+ # to check if the server is available or not.
229
+ def check_server(check_url)
230
+ response = Net::HTTP.get_response(URI(check_url))
231
+ response.is_a?(Net::HTTPSuccess)
232
+ rescue OpenURI::HTTPError, Errno::ECONNREFUSED, SocketError
233
+ false
234
+ end
235
+
236
+ def valid_uri?(uri)
237
+ !(uri =~ /\A#{URI_SCHEMES_REGEXP}\z/).nil?
238
+ end
239
+
240
+ def join_paths(*paths, separator: '/')
241
+ paths = paths.compact.reject(&:empty?)
242
+ last = paths.length - 1
243
+ paths.each_with_index.map do |path, index|
244
+ expand_path(path, index, last, separator)
245
+ end.join
246
+ end
247
+
248
+ def expand_path(path, current, last, separator)
249
+ path = path[1..-1] if path.start_with?(separator) && current.zero?
250
+
251
+ path = [path, separator] unless path.end_with?(separator) || current == last
252
+
253
+ path
254
+ end
255
+ end
256
+ end
257
+
258
+ # PlantUML BlockProcessor
259
+ class BlockProcessor < Asciidoctor::Extensions::BlockProcessor
260
+ use_dsl
261
+ named :plantuml
262
+ on_context :listing, :literal
263
+ content_model :simple
264
+
265
+ def process(parent, target, attrs)
266
+ lines = target.lines
267
+
268
+ lines = ['@startuml'] + target.lines unless target.lines[0] =~ /@startuml/
269
+
270
+ lines += ['@enduml'] unless target.lines[-1] =~ /@enduml/
271
+
272
+ content = Processor.plantuml_content(lines.join("\n"), attrs)
273
+
274
+ create_plantuml_block(parent, content, attrs)
275
+ end
276
+
277
+ private
278
+
279
+ def create_plantuml_block(parent, content, attrs)
280
+ Asciidoctor::Block.new parent, :pass, {
281
+ content_model: :raw,
282
+ source: content,
283
+ subs: :default
284
+ }.merge(attrs)
285
+ end
286
+ end
287
+ end
288
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Asciidoctor
4
+ module PlantUML
5
+ VERSION = '0.0.14'
6
+ end
7
+ end
@@ -1,133 +1,221 @@
1
- require "test/unit"
2
- require "asciidoctor"
3
- require "stringio"
4
- require "nokogiri"
5
- require "asciidoctor-plantuml"
6
-
7
- DOC_BASIC = <<-eos
8
- = Hello PlantUML!
9
-
10
- [plantuml, format="png"]
11
- .Title Of this
12
- ----
13
- User -> (Start)
14
- User --> (Use the application) : Label
15
- ----
16
- eos
17
-
18
- DOC_BASIC2 = <<-eos
19
- = Hello PlantUML!
20
-
21
- [plantuml, format="png"]
22
- .Title Of this
23
- [[fig-xref]]
24
- ----
25
- @startuml
26
- User -> (Start)
27
- User --> (Use the application) : Label
28
- @enduml
29
- ----
30
- eos
31
-
32
- DOC_BASIC3 = <<-eos
33
- = Hello Compound PlantUML!
34
-
35
- [plantuml, format="png"]
36
- ----
37
- [COMP1]
38
- [COMP2]
39
- [COMP1] -> [COMP2]
40
- [COMP2] --> [COMP3]
41
- ----
42
- eos
43
-
44
- DOC_ID = <<-eos
45
- = Hello PlantUML!
46
-
47
- [plantuml, format="png", id="myId"]
48
- ----
49
- User -> (Start)
50
- User --> (Use the application) : Label
51
- ----
52
- eos
53
-
54
- DOC_DIM = <<-eos
55
- = Hello PlantUML!
56
-
57
- [plantuml, format="png", width="100px", height="50px"]
58
- ----
59
- User -> (Start)
60
- User --> (Use the application) : Label
61
- ----
62
- eos
63
-
64
- DOC_ALT = <<-eos
65
- = Hello PlantUML!
66
-
67
- [plantuml, format="png", alt="alt"]
68
- ----
69
- User -> (Start)
70
- User --> (Use the application) : Label
71
- ----
72
- eos
73
-
74
- DOC_BAD_FORMAT = <<-eos
75
- = Hello PlantUML!
76
-
77
- [plantuml, format="jpg"]
78
- ----
79
- User -> (Start)
80
- User --> (Use the application) : Label
81
- ----
82
- eos
83
-
84
- DOC_MULTI = <<-eos
85
- = Hello PlantUML!
86
-
87
- [plantuml, format="png"]
88
- ----
89
- User -> (Start)
90
- User --> (Use the application) : Label
91
- ----
92
-
93
- [plantuml, format="png"]
94
- ----
95
- User -> (Start)
96
- User --> (Use the application) : Label
97
- ----
98
-
99
- [plantuml, format="txt"]
100
- ----
101
- User -> (Start)
102
- User --> (Use the application) : Label
103
- ----
104
- eos
105
-
106
- DOC_TXT = <<-eos
107
- = Hello PlantUML!
108
-
109
- [plantuml, format="txt"]
110
- ----
111
- User -> (Start)
112
- User --> (Use the application) : Label
113
- ----
114
- eos
1
+ # frozen_string_literal: true
2
+
3
+ require 'test/unit'
4
+ require 'asciidoctor'
5
+ require 'stringio'
6
+ require 'nokogiri'
7
+ require 'asciidoctor-plantuml'
8
+
9
+ DOC_BASIC = <<~ENDOFSTRING
10
+ = Hello PlantUML!
11
+
12
+ [plantuml, format="png"]
13
+ .Title Of this
14
+ ----
15
+ User -> (Start)
16
+ User --> (Use the application) : Label
17
+ ----
18
+ ENDOFSTRING
19
+
20
+ DOC_BASIC_LITERAL = <<~ENDOFSTRING
21
+ = Hello PlantUML!
22
+
23
+ [plantuml, format="png"]
24
+ .Title Of this
25
+ ....
26
+ User -> (Start)
27
+ User --> (Use the application) : Label
28
+ ....
29
+ ENDOFSTRING
30
+
31
+ DOC_BASIC2 = <<~ENDOFSTRING
32
+ = Hello PlantUML!
33
+
34
+ [plantuml, format="png"]
35
+ .Title Of this
36
+ [[fig-xref]]
37
+ ----
38
+ @startuml
39
+ User -> (Start)
40
+ User --> (Use the application) : Label
41
+ @enduml
42
+ ----
43
+ ENDOFSTRING
44
+
45
+ DOC_BASIC2_LITERAL = <<~ENDOFSTRING
46
+ = Hello PlantUML!
47
+
48
+ [plantuml, format="png"]
49
+ .Title Of this
50
+ [[fig-xref]]
51
+ ....
52
+ @startuml
53
+ User -> (Start)
54
+ User --> (Use the application) : Label
55
+ @enduml
56
+ ....
57
+ ENDOFSTRING
58
+
59
+ DOC_BASIC3 = <<~ENDOFSTRING
60
+ = Hello Compound PlantUML!
61
+
62
+ [plantuml, format="png"]
63
+ ----
64
+ [COMP1]
65
+ [COMP2]
66
+ [COMP1] -> [COMP2]
67
+ [COMP2] --> [COMP3]
68
+ ----
69
+ ENDOFSTRING
70
+
71
+ DOC_BASIC3_LITERAL = <<~ENDOFSTRING
72
+ = Hello Compound PlantUML!
73
+
74
+ [plantuml, format="png"]
75
+ ....
76
+ [COMP1]
77
+ [COMP2]
78
+ [COMP1] -> [COMP2]
79
+ [COMP2] --> [COMP3]
80
+ ....
81
+ ENDOFSTRING
82
+
83
+ DOC_ID = <<~ENDOFSTRING
84
+ = Hello PlantUML!
85
+
86
+ [plantuml, format="png", id="myId"]
87
+ ----
88
+ User -> (Start)
89
+ User --> (Use the application) : Label
90
+ ----
91
+ ENDOFSTRING
92
+
93
+ DOC_DIM = <<~ENDOFSTRING
94
+ = Hello PlantUML!
95
+
96
+ [plantuml, format="png", width="100px", height="50px"]
97
+ ----
98
+ User -> (Start)
99
+ User --> (Use the application) : Label
100
+ ----
101
+ ENDOFSTRING
102
+
103
+ DOC_ALT = <<~ENDOFSTRING
104
+ = Hello PlantUML!
105
+
106
+ [plantuml, format="png", alt="alt"]
107
+ ----
108
+ User -> (Start)
109
+ User --> (Use the application) : Label
110
+ ----
111
+ ENDOFSTRING
112
+
113
+ DOC_BAD_FORMAT = <<~ENDOFSTRING
114
+ = Hello PlantUML!
115
+
116
+ [plantuml, format="jpg"]
117
+ ----
118
+ User -> (Start)
119
+ User --> (Use the application) : Label
120
+ ----
121
+ ENDOFSTRING
122
+
123
+ DOC_MULTI = <<~ENDOFSTRING
124
+ = Hello PlantUML!
125
+
126
+ [plantuml, format="png"]
127
+ ----
128
+ User -> (Start)
129
+ User --> (Use the application) : Label
130
+ ----
131
+
132
+ [plantuml, format="png"]
133
+ ----
134
+ User -> (Start)
135
+ User --> (Use the application) : Label
136
+ ----
137
+
138
+ [plantuml, format="txt"]
139
+ ----
140
+ User -> (Start)
141
+ User --> (Use the application) : Label
142
+ ----
143
+ ENDOFSTRING
144
+
145
+ DOC_MULTI_LITERAL = <<~ENDOFSTRING
146
+ = Hello PlantUML!
147
+
148
+ [plantuml, format="png"]
149
+ ....
150
+ User -> (Start)
151
+ User --> (Use the application) : Label
152
+ ....
153
+
154
+ [plantuml, format="png"]
155
+ ....
156
+ User -> (Start)
157
+ User --> (Use the application) : Label
158
+ ....
159
+
160
+ [plantuml, format="txt"]
161
+ ....
162
+ User -> (Start)
163
+ User --> (Use the application) : Label
164
+ ....
165
+ ENDOFSTRING
166
+
167
+ DOC_TXT = <<~ENDOFSTRING
168
+ = Hello PlantUML!
169
+
170
+ [plantuml, format="txt"]
171
+ ----
172
+ User -> (Start)
173
+ User --> (Use the application) : Label
174
+ ----
175
+ ENDOFSTRING
176
+
177
+ DOC_SVG = <<~ENDOFSTRING
178
+ = Hello PlantUML!
179
+
180
+ [plantuml, format="svg"]
181
+ ----
182
+ User -> (Start)
183
+ User --> (Use the application) : Label
184
+ ----
185
+ ENDOFSTRING
115
186
 
116
187
  class PlantUmlTest < Test::Unit::TestCase
117
-
118
- GENURL = "http://localhost:8080/plantuml/png/U9npA2v9B2efpStX2YrEBLBGjLFG20Q9Q4Bv804WIw4a8rKXiQ0W9pCviIGpFqzJmKh19p4fDOVB8JKl1QWT05kd5wq0"
119
- GENURL2 = "http://localhost:8080/plantuml/png/U9npA2v9B2efpStXYdRszmqmZ8NGHh4mleAkdGAAa15G22Pc7Clba9gN0jGE00W75Cm0"
188
+ GENURL = 'http://localhost:8080/plantuml/png/U9npA2v9B2efpStX2YrEBLBGjLFG20Q9Q4Bv804WIw4a8rKXiQ0W9pCviIGpFqzJmKh19p4fDOVB8JKl1QWT05kd5wq0'
189
+ GENURL2 = 'http://localhost:8080/plantuml/png/U9npA2v9B2efpStXYdRszmqmZ8NGHh4mleAkdGAAa15G22Pc7Clba9gN0jGE00W75Cm0'
190
+ GENURL_ENCODING = 'http://localhost:8080/plantuml/png/~1U9npA2v9B2efpStX2YrEBLBGjLFG20Q9Q4Bv804WIw4a8rKXiQ0W9pCviIGpFqzJmKh19p4fDOVB8JKl1QWT05kd5wq0'
191
+ SVGGENURL = 'http://localhost:8080/plantuml/svg/~1U9npA2v9B2efpStX2YrEBLBGjLFG20Q9Q4Bv804WIw4a8rKXiQ0W9pCviIGpFqzJmKh19p4fDOVB8JKl1QWT05kd5wq0'
120
192
 
121
193
  def setup
122
194
  Asciidoctor::PlantUml.configure do |c|
123
- c.url = "http://localhost:8080/plantuml"
195
+ c.url = 'http://localhost:8080/plantuml'
124
196
  c.txt_enable = true
197
+ c.png_enable = true
198
+ c.svg_enable = true
125
199
  end
126
200
  end
127
201
 
128
202
  def test_plantuml_block_processor
203
+ html = ::Asciidoctor.convert(StringIO.new(DOC_BASIC), backend: 'html5')
204
+ page = Nokogiri::HTML(html)
205
+
206
+ elements = page.css('img.plantuml')
207
+
208
+ assert_equal elements.size, 1
129
209
 
130
- html = ::Asciidoctor.convert(StringIO.new(DOC_BASIC), backend: "html5")
210
+ element = elements.first
211
+
212
+ assert_equal GENURL, element['src']
213
+ end
214
+
215
+ def test_plantuml_block_literal_processor
216
+ html = ::Asciidoctor.convert(
217
+ StringIO.new(DOC_BASIC_LITERAL), backend: 'html5'
218
+ )
131
219
  page = Nokogiri::HTML(html)
132
220
 
133
221
  elements = page.css('img.plantuml')
@@ -136,11 +224,28 @@ class PlantUmlTest < Test::Unit::TestCase
136
224
 
137
225
  element = elements.first
138
226
 
139
- assert_equal GENURL, element["src"]
227
+ assert_equal GENURL, element['src']
140
228
  end
141
229
 
142
230
  def test_plantuml_block_processor2
143
- html = ::Asciidoctor.convert(StringIO.new(DOC_BASIC2), backend: "html5")
231
+ html = ::Asciidoctor.convert(
232
+ StringIO.new(DOC_BASIC2), backend: 'html5'
233
+ )
234
+ page = Nokogiri::HTML(html)
235
+
236
+ elements = page.css('img.plantuml')
237
+
238
+ assert_equal elements.size, 1
239
+
240
+ element = elements.first
241
+
242
+ assert_equal GENURL, element['src']
243
+ end
244
+
245
+ def test_plantuml_block_literal_processor2
246
+ html = ::Asciidoctor.convert(
247
+ StringIO.new(DOC_BASIC2_LITERAL), backend: 'html5'
248
+ )
144
249
  page = Nokogiri::HTML(html)
145
250
 
146
251
  elements = page.css('img.plantuml')
@@ -149,11 +254,11 @@ class PlantUmlTest < Test::Unit::TestCase
149
254
 
150
255
  element = elements.first
151
256
 
152
- assert_equal GENURL, element["src"]
257
+ assert_equal GENURL, element['src']
153
258
  end
154
259
 
155
260
  def test_plantuml_block_processor3
156
- html = ::Asciidoctor.convert(StringIO.new(DOC_BASIC3), backend: "html5")
261
+ html = ::Asciidoctor.convert(StringIO.new(DOC_BASIC3), backend: 'html5')
157
262
  page = Nokogiri::HTML(html)
158
263
 
159
264
  elements = page.css('img.plantuml')
@@ -162,26 +267,55 @@ class PlantUmlTest < Test::Unit::TestCase
162
267
 
163
268
  element = elements.first
164
269
 
165
- assert_equal GENURL2, element["src"]
270
+ assert_equal GENURL2, element['src']
166
271
  end
167
272
 
168
- def test_plantuml_id_attribute
273
+ def test_plantuml_block_literal_processor3
274
+ html = ::Asciidoctor.convert(
275
+ StringIO.new(DOC_BASIC3_LITERAL), backend: 'html5'
276
+ )
277
+ page = Nokogiri::HTML(html)
169
278
 
170
- html = ::Asciidoctor.convert(StringIO.new(DOC_ID), backend: "html5")
279
+ elements = page.css('img.plantuml')
280
+
281
+ assert_equal elements.size, 1
282
+
283
+ element = elements.first
284
+
285
+ assert_equal GENURL2, element['src']
286
+ end
287
+
288
+ def test_plantuml_block_processor_encoding
289
+ Asciidoctor::PlantUml.configure do |c|
290
+ c.encoding = 'deflate'
291
+ end
292
+
293
+ html = ::Asciidoctor.convert(StringIO.new(DOC_BASIC), backend: 'html5')
171
294
  page = Nokogiri::HTML(html)
172
295
 
173
296
  elements = page.css('img.plantuml')
174
297
 
175
298
  assert_equal elements.size, 1
299
+
176
300
  element = elements.first
177
301
 
178
- assert_equal "myId", element["id"]
302
+ assert_equal GENURL_ENCODING, element['src']
303
+ end
304
+
305
+ def test_plantuml_id_attribute
306
+ html = ::Asciidoctor.convert(StringIO.new(DOC_ID), backend: 'html5')
307
+ page = Nokogiri::HTML(html)
179
308
 
309
+ elements = page.css('img.plantuml')
310
+
311
+ assert_equal elements.size, 1
312
+ element = elements.first
313
+
314
+ assert_equal 'myId', element['id']
180
315
  end
181
316
 
182
317
  def test_plantuml_dimension_attribute
183
-
184
- html = ::Asciidoctor.convert(StringIO.new(DOC_DIM), backend: "html5")
318
+ html = ::Asciidoctor.convert(StringIO.new(DOC_DIM), backend: 'html5')
185
319
  page = Nokogiri::HTML(html)
186
320
 
187
321
  elements = page.css('img.plantuml')
@@ -189,14 +323,12 @@ class PlantUmlTest < Test::Unit::TestCase
189
323
  assert_equal elements.size, 1
190
324
  element = elements.first
191
325
 
192
- assert_equal "100px", element["width"]
193
- assert_equal "50px", element["height"]
194
-
326
+ assert_equal '100px', element['width']
327
+ assert_equal '50px', element['height']
195
328
  end
196
329
 
197
330
  def test_plantuml_alt_attribute
198
-
199
- html = ::Asciidoctor.convert(StringIO.new(DOC_ALT), backend: "html5")
331
+ html = ::Asciidoctor.convert(StringIO.new(DOC_ALT), backend: 'html5')
200
332
  page = Nokogiri::HTML(html)
201
333
 
202
334
  elements = page.css('img.plantuml')
@@ -204,23 +336,20 @@ class PlantUmlTest < Test::Unit::TestCase
204
336
  assert_equal elements.size, 1
205
337
  element = elements.first
206
338
 
207
- assert_equal "alt", element["alt"]
208
-
339
+ assert_equal 'alt', element['alt']
209
340
  end
210
341
 
211
342
  def test_should_show_bad_format
212
- html = ::Asciidoctor.convert(StringIO.new(DOC_BAD_FORMAT), backend: "html5")
343
+ html = ::Asciidoctor.convert(StringIO.new(DOC_BAD_FORMAT), backend: 'html5')
213
344
 
214
345
  page = Nokogiri::HTML(html)
215
346
 
216
347
  elements = page.css('pre.plantuml-error')
217
348
  assert_equal elements.size, 1
218
-
219
349
  end
220
350
 
221
- def test_plantuml_multiple
222
-
223
- html = ::Asciidoctor.convert(StringIO.new(DOC_MULTI), backend: "html5")
351
+ def test_plantuml_multiple_listing
352
+ html = ::Asciidoctor.convert(StringIO.new(DOC_MULTI), backend: 'html5')
224
353
  page = Nokogiri::HTML(html)
225
354
 
226
355
  elements = page.css('img.plantuml')
@@ -228,72 +357,118 @@ class PlantUmlTest < Test::Unit::TestCase
228
357
 
229
358
  elements = page.css('.plantuml-error')
230
359
  assert_equal elements.size, 0
360
+ end
361
+
362
+ def test_plantuml_multiple_literal
363
+ html = ::Asciidoctor.convert(
364
+ StringIO.new(DOC_MULTI_LITERAL), backend: 'html5'
365
+ )
366
+ page = Nokogiri::HTML(html)
367
+
368
+ elements = page.css('img.plantuml')
369
+ assert elements.size >= 2
231
370
 
371
+ elements = page.css('.plantuml-error')
372
+ assert_equal elements.size, 0
232
373
  end
233
374
 
234
375
  def test_plantuml_bad_server
235
-
236
376
  Asciidoctor::PlantUml.configure do |c|
237
- c.url = "http://nonexistent.com/plantuml"
377
+ c.url = 'http://nonexistent.com/plantuml'
238
378
  end
239
379
 
240
- html = ::Asciidoctor.convert(StringIO.new(DOC_MULTI), backend: "html5")
380
+ html = ::Asciidoctor.convert(StringIO.new(DOC_MULTI), backend: 'html5')
241
381
  page = Nokogiri::HTML(html)
242
382
 
243
383
  elements = page.css('img.plantuml')
244
- assert_equal elements.size, 3
384
+ assert_equal 3, elements.size
245
385
 
246
386
  elements = page.css('.plantuml-error')
247
- assert_equal elements.size, 0
387
+ assert_equal 0, elements.size
248
388
  end
249
389
 
250
390
  def test_plantuml_invalid_uri
251
-
252
391
  Asciidoctor::PlantUml.configure do |c|
253
- c.url = "ftp://test.com"
392
+ c.url = 'ftp://test.com'
254
393
  end
255
394
 
256
- html = ::Asciidoctor.convert(StringIO.new(DOC_BASIC), backend: "html5")
395
+ html = ::Asciidoctor.convert(StringIO.new(DOC_BASIC), backend: 'html5')
257
396
  page = Nokogiri::HTML(html)
258
397
  elements = page.css('pre.plantuml-error')
259
398
  assert_equal elements.size, 1
260
399
  end
261
400
 
262
401
  def test_plantuml_nil_uri
263
-
264
402
  Asciidoctor::PlantUml.configure do |c|
265
403
  c.url = nil
266
404
  end
267
405
 
268
- html = ::Asciidoctor.convert(StringIO.new(DOC_BASIC), backend: "html5")
406
+ html = ::Asciidoctor.convert(StringIO.new(DOC_BASIC), backend: 'html5')
269
407
  page = Nokogiri::HTML(html)
270
408
  elements = page.css('pre.plantuml-error')
271
409
  assert_equal elements.size, 1
272
410
  end
273
411
 
274
412
  def test_plantuml_empty_uri
275
-
276
413
  Asciidoctor::PlantUml.configure do |c|
277
- c.url = ""
414
+ c.url = ''
278
415
  end
279
416
 
280
- html = ::Asciidoctor.convert(StringIO.new(DOC_BASIC), backend: "html5")
417
+ html = ::Asciidoctor.convert(StringIO.new(DOC_BASIC), backend: 'html5')
281
418
  page = Nokogiri::HTML(html)
282
419
  elements = page.css('pre.plantuml-error')
283
420
  assert_equal elements.size, 1
284
421
  end
285
422
 
286
423
  def test_disable_txt
287
-
288
424
  Asciidoctor::PlantUml.configure do |c|
289
- c.url = "http://localhost:8080/plantuml"
425
+ c.url = 'http://localhost:8080/plantuml'
290
426
  c.txt_enable = false
291
427
  end
292
428
 
293
- html = ::Asciidoctor.convert(StringIO.new(DOC_TXT), backend: "html5")
429
+ html = ::Asciidoctor.convert(StringIO.new(DOC_TXT), backend: 'html5')
430
+ page = Nokogiri::HTML(html)
431
+ elements = page.css('pre.plantuml-error')
432
+ assert_equal elements.size, 1
433
+ end
434
+
435
+ def test_svg
436
+ Asciidoctor::PlantUml.configure do |c|
437
+ c.url = 'http://localhost:8080/plantuml'
438
+ c.svg_enable = true
439
+ end
440
+
441
+ html = ::Asciidoctor.convert(StringIO.new(DOC_SVG), backend: 'html5')
442
+ page = Nokogiri::HTML(html)
443
+ elements = page.css("object[type='image/svg+xml']")
444
+ assert_equal elements.size, 1
445
+
446
+ element = elements.first
447
+
448
+ assert_equal SVGGENURL, element['data']
449
+ end
450
+
451
+ def test_disable_svg
452
+ Asciidoctor::PlantUml.configure do |c|
453
+ c.url = 'http://localhost:8080/plantuml'
454
+ c.svg_enable = false
455
+ end
456
+
457
+ html = ::Asciidoctor.convert(StringIO.new(DOC_SVG), backend: 'html5')
294
458
  page = Nokogiri::HTML(html)
295
459
  elements = page.css('pre.plantuml-error')
296
460
  assert_equal elements.size, 1
461
+ end
297
462
 
463
+ def test_disable_png
464
+ Asciidoctor::PlantUml.configure do |c|
465
+ c.url = 'http://localhost:8080/plantuml'
466
+ c.png_enable = false
467
+ end
468
+
469
+ html = ::Asciidoctor.convert(StringIO.new(DOC_BASIC_LITERAL), backend: 'html5')
470
+ page = Nokogiri::HTML(html)
471
+ elements = page.css('pre.plantuml-error')
472
+ assert_equal elements.size, 1
298
473
  end
299
474
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: asciidoctor-plantuml
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.9
4
+ version: 0.0.14
5
5
  platform: ruby
6
6
  authors:
7
7
  - Horacio Sanson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-06-17 00:00:00.000000000 Z
11
+ date: 2021-05-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -24,34 +24,48 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: nokogiri
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.11'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.11'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: rake
29
43
  requirement: !ruby/object:Gem::Requirement
30
44
  requirements:
31
45
  - - "~>"
32
46
  - !ruby/object:Gem::Version
33
- version: '10.5'
47
+ version: '13.0'
34
48
  type: :development
35
49
  prerelease: false
36
50
  version_requirements: !ruby/object:Gem::Requirement
37
51
  requirements:
38
52
  - - "~>"
39
53
  - !ruby/object:Gem::Version
40
- version: '10.5'
54
+ version: '13.0'
41
55
  - !ruby/object:Gem::Dependency
42
- name: nokogiri
56
+ name: rubocop
43
57
  requirement: !ruby/object:Gem::Requirement
44
58
  requirements:
45
59
  - - "~>"
46
60
  - !ruby/object:Gem::Version
47
- version: '1.6'
61
+ version: '1.7'
48
62
  type: :development
49
63
  prerelease: false
50
64
  version_requirements: !ruby/object:Gem::Requirement
51
65
  requirements:
52
66
  - - "~>"
53
67
  - !ruby/object:Gem::Version
54
- version: '1.6'
68
+ version: '1.7'
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: test-unit
57
71
  requirement: !ruby/object:Gem::Requirement
@@ -94,8 +108,8 @@ extensions: []
94
108
  extra_rdoc_files: []
95
109
  files:
96
110
  - lib/asciidoctor-plantuml.rb
97
- - lib/asciidoctor-plantuml/plantuml.rb
98
- - lib/asciidoctor-plantuml/version.rb
111
+ - lib/asciidoctor_plantuml/plantuml.rb
112
+ - lib/asciidoctor_plantuml/version.rb
99
113
  - test/test_plantuml.rb
100
114
  homepage: https://github.com/hsanson/asciidoctor-plantuml
101
115
  licenses:
@@ -109,17 +123,16 @@ required_ruby_version: !ruby/object:Gem::Requirement
109
123
  requirements:
110
124
  - - ">="
111
125
  - !ruby/object:Gem::Version
112
- version: '2.1'
126
+ version: '2.5'
113
127
  required_rubygems_version: !ruby/object:Gem::Requirement
114
128
  requirements:
115
129
  - - ">="
116
130
  - !ruby/object:Gem::Version
117
131
  version: '0'
118
132
  requirements: []
119
- rubyforge_project:
120
- rubygems_version: 2.7.6
133
+ rubygems_version: 3.1.2
121
134
  signing_key:
122
135
  specification_version: 4
123
- summary: An extension for Asciidoctor that enables support for PlantUML diagrams.
136
+ summary: Asciidoctor support for PlantUML diagrams.
124
137
  test_files:
125
138
  - test/test_plantuml.rb
@@ -1,286 +0,0 @@
1
- require 'uri'
2
- require 'zlib'
3
- require 'open-uri'
4
- require 'net/http'
5
-
6
- module Asciidoctor
7
- module PlantUml
8
-
9
- class Configuration
10
-
11
- DEFAULT_URL = ENV["PLANTUML_URL"] || ""
12
-
13
- attr_accessor :url, :txt_enable, :svg_enable, :png_enable
14
-
15
- def initialize
16
- @url = DEFAULT_URL
17
- @txt_enable = true
18
- @svg_enable = true
19
- @png_enable = true
20
- end
21
- end
22
-
23
- class << self
24
- attr_writer :configuration
25
- end
26
-
27
- def self.configuration
28
- @configuration ||= Configuration.new
29
- end
30
-
31
- def self.configure
32
- yield(configuration)
33
- end
34
-
35
- class Processor
36
-
37
- FORMATS = ["png", "svg", "txt"]
38
- DEFAULT_FORMAT = FORMATS[0]
39
-
40
- class << self
41
- def valid_format?(format)
42
- FORMATS.include?(format)
43
- end
44
-
45
- def server_url
46
- PlantUml::configuration.url
47
- end
48
-
49
- def txt_enabled?
50
- PlantUml::configuration.txt_enable
51
- end
52
-
53
- def png_enabled?
54
- PlantUml::configuration.png_enable
55
- end
56
-
57
- def svg_enabled?
58
- PlantUml::configuration.svg_enable
59
- end
60
-
61
- def enabled?
62
- txt_enabled? || png_enabled? || svg_enabled?
63
- end
64
-
65
- def plantuml_content(code, attrs = {})
66
-
67
- format = attrs["format"] || DEFAULT_FORMAT
68
-
69
- if !enabled?
70
- return plantuml_disabled_content(code, attrs)
71
- end
72
-
73
- if !valid_uri?(server_url)
74
- return plantuml_server_unavailable_content(server_url, attrs)
75
- end
76
-
77
- case format
78
- when "png"
79
- plantuml_img_content(code, format, attrs)
80
- when "txt"
81
- if txt_enabled?
82
- plantuml_txt_content(code, format, attrs)
83
- else
84
- plantuml_invalid_content(format, attrs)
85
- end
86
- when "svg"
87
- plantuml_img_content(code, format, attrs)
88
- else
89
- plantuml_invalid_content(format, attrs)
90
- end
91
- end
92
-
93
- # Compression code used to generate PlantUML URLs. Taken directly from the
94
- # Transcoder class in the PlantUML java code.
95
- def gen_url(text, format)
96
- result = ""
97
- compressedData = Zlib::Deflate.deflate(text)
98
- compressedData.chars.each_slice(3) do |bytes|
99
- #print bytes[0], ' ' , bytes[1] , ' ' , bytes[2]
100
- b1 = bytes[0].nil? ? 0 : (bytes[0].ord & 0xFF)
101
- b2 = bytes[1].nil? ? 0 : (bytes[1].ord & 0xFF)
102
- b3 = bytes[2].nil? ? 0 : (bytes[2].ord & 0xFF)
103
- result += append3bytes(b1, b2, b3)
104
- end
105
- join_paths(server_url, "/#{format}/", result).to_s
106
- end
107
-
108
- private
109
-
110
- def plantuml_txt_content(code, format, attrs = {})
111
- begin
112
- url = gen_url(code, format)
113
- open(url) do |f|
114
- plantuml_ascii_content(f.read, format, attrs)
115
- end
116
- rescue
117
- plantuml_img_content(code, format, attrs)
118
- end
119
- end
120
-
121
- def plantuml_ascii_content(code, format, attrs = {})
122
- content = "<div class=\"listingblock\">"
123
- content += "<div class=\"content\">"
124
- content += "<pre "
125
- content +="id=\"#{attrs['id']}\" " if attrs['id']
126
- content +="class=\"plantuml\">\n"
127
- content += code
128
- content +="</pre>"
129
- content += "</div>"
130
- content += "</div>"
131
- end
132
-
133
- def plantuml_img_content(code, format, attrs = {})
134
- content = "<div class=\"imageblock\">"
135
- content += "<div class=\"content\">"
136
- content += "<img "
137
- content +="id=\"#{attrs['id']}\" " if attrs['id']
138
- content +="class=\"plantuml\" "
139
- content +="width=\"#{attrs['width']}\" " if attrs['width']
140
- content +="height=\"#{attrs['height']}\" " if attrs['height']
141
- content +="alt=\"#{attrs['alt']}\" " if attrs['alt']
142
- content +="src=\"#{gen_url(code, format)}\" />"
143
- content += "</div>"
144
- content += "</div>"
145
- end
146
-
147
- def plantuml_invalid_content(format, attrs = {})
148
- content = "<div class=\"listingblock\">"
149
- content += "<div class=\"content\">"
150
- content += "<pre "
151
- content +="id=\"#{attrs['id']}\" " if attrs['id']
152
- content +="class=\"plantuml plantuml-error\"> "
153
- content += "PlantUML Error: Invalid format \"#{format}\""
154
- content +="</pre>"
155
- content += "</div>"
156
- content += "</div>"
157
- end
158
-
159
- def plantuml_server_unavailable_content(url, attrs = {})
160
- content = "<div class=\"listingblock\">"
161
- content += "<div class=\"content\">"
162
- content += "<pre "
163
- content +="id=\"#{attrs['id']}\" " if attrs['id']
164
- content +="class=\"plantuml plantuml-error\"> "
165
- content += "PlantUML Error: cannot connect to PlantUML server at \"#{url}\""
166
- content +="</pre>"
167
- content += "</div>"
168
- content += "</div>"
169
- end
170
-
171
- def plantuml_disabled_content(code, attrs = {})
172
- content = "<div class=\"listingblock\">"
173
- content += "<div class=\"content\">"
174
- content += "<pre "
175
- content +="id=\"#{attrs['id']}\" " if attrs['id']
176
- content +="class=\"plantuml plantuml-error\">\n"
177
- content += code
178
- content +="</pre>"
179
- content += "</div>"
180
- content += "</div>"
181
- end
182
-
183
- def encode6bit(b)
184
- if b < 10
185
- return ('0'.ord + b).chr
186
- end
187
- b = b - 10
188
- if b < 26
189
- return ('A'.ord + b).chr
190
- end
191
- b = b - 26
192
- if b < 26
193
- return ('a'.ord + b).chr
194
- end
195
- b = b - 26
196
- if b == 0
197
- return '-'
198
- end
199
- if b == 1
200
- return '_'
201
- end
202
- return '?'
203
- end
204
-
205
- def append3bytes(b1, b2, b3)
206
- c1 = b1 >> 2
207
- c2 = ((b1 & 0x3) << 4) | (b2 >> 4)
208
- c3 = ((b2 & 0xF) << 2) | (b3 >> 6)
209
- c4 = b3 & 0x3F
210
- return encode6bit(c1 & 0x3F).chr +
211
- encode6bit(c2 & 0x3F).chr +
212
- encode6bit(c3 & 0x3F).chr +
213
- encode6bit(c4 & 0x3F).chr
214
- end
215
-
216
- # Make a call to the PlantUML server with the simplest diagram possible to
217
- # check if the server is available or not.
218
- def check_server(check_url)
219
- response = Net::HTTP.get_response(URI(check_url))
220
- return response.is_a?(Net::HTTPSuccess)
221
- rescue
222
- return false
223
- end
224
-
225
- def valid_uri?(uri)
226
- !(uri =~ /\A#{URI::regexp(['http', 'https'])}\z/).nil?
227
- end
228
-
229
- def join_paths(*paths, separator: '/')
230
- paths = paths.compact.reject(&:empty?)
231
- last = paths.length - 1
232
- paths.each_with_index.map { |path, index|
233
- expand_path(path, index, last, separator)
234
- }.join
235
- end
236
-
237
- def expand_path(path, current, last, separator)
238
- if path.start_with?(separator) && current != 0
239
- path = path[1..-1]
240
- end
241
-
242
- unless path.end_with?(separator) || current == last
243
- path = [path, separator]
244
- end
245
-
246
- path
247
- end
248
- end
249
- end
250
-
251
- class BlockProcessor < Asciidoctor::Extensions::BlockProcessor
252
-
253
- use_dsl
254
- named :plantuml
255
- on_context :listing
256
- content_model :simple
257
-
258
- def process(parent, target, attrs)
259
-
260
- lines = target.lines
261
-
262
- if !(target.lines[0] =~ /@startuml/)
263
- lines = ["@startuml"] + target.lines
264
- end
265
-
266
- if !(target.lines[-1] =~ /@enduml/)
267
- lines += ["@enduml"]
268
- end
269
-
270
- content = Processor.plantuml_content(lines.join("\n"), attrs)
271
-
272
- return create_plantuml_block(parent, content, attrs)
273
-
274
- end
275
-
276
- private
277
-
278
- def create_plantuml_block(parent, content, attrs)
279
- Asciidoctor::Block.new parent, :pass, { content_model: :raw,
280
- source: content, subs: :default }.merge(attrs)
281
- end
282
-
283
- end
284
-
285
- end
286
- end
@@ -1,5 +0,0 @@
1
- module Asciidoctor
2
- module PlantUML
3
- VERSION = '0.0.9'.freeze
4
- end
5
- end