markdoc 1.1.0 → 2.0.0
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 +7 -0
- data/bin/markdoc +1 -0
- data/bin/pseudo2svg +1 -0
- data/bin/sequence2svg +1 -0
- data/lib/markdoc/pseudocode.rb +31 -27
- data/lib/markdoc/renderer.rb +19 -18
- data/lib/markdoc/sequence.rb +266 -157
- data/lib/markdoc/version.rb +3 -1
- data/lib/markdoc.rb +2 -0
- metadata +45 -43
- data/lib/markdoc/sequence.pic +0 -406
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: a313ccc3aef3a547c0d688e8a84dac9097c6fad2e7e5e27e46475311646e1e67
|
4
|
+
data.tar.gz: 4491396850eac63988494d4e68f110db83813304a9cc1bab00458eb5875e497e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 949e3a80919e9b9b54f624b659c5bbb72ca0cf9b7746c9080dd8fd08a27b012147099cc2c50397d68694f05a717eb8265d14bb058146b8174416cb59dbce9db3
|
7
|
+
data.tar.gz: a32fbb8e268d9035ff15c4b2d93726e48a9bb5ab3fb9af6e13c95a7d8979f7b6ee57b1d469c23871c6179b3d2b83c0da9c6658351cf8932a66c6ecf777682f7b
|
data/bin/markdoc
CHANGED
data/bin/pseudo2svg
CHANGED
data/bin/sequence2svg
CHANGED
data/lib/markdoc/pseudocode.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'polyglot'
|
2
4
|
require 'treetop'
|
3
5
|
|
@@ -13,14 +15,17 @@ module Markdoc
|
|
13
15
|
|
14
16
|
class ActionLiteral < Treetop::Runtime::SyntaxNode
|
15
17
|
def out(file)
|
16
|
-
file.write %
|
18
|
+
file.write %(#{id} [shape=box label="#{label}"]\n)
|
17
19
|
end
|
20
|
+
|
18
21
|
def id
|
19
22
|
sentence.id
|
20
23
|
end
|
24
|
+
|
21
25
|
def label
|
22
26
|
sentence.value
|
23
27
|
end
|
28
|
+
|
24
29
|
def ends
|
25
30
|
[id]
|
26
31
|
end
|
@@ -28,33 +33,34 @@ module Markdoc
|
|
28
33
|
|
29
34
|
class IfLiteral < Treetop::Runtime::SyntaxNode
|
30
35
|
def out(file)
|
31
|
-
file.write %
|
36
|
+
file.write %(#{id} [shape=diamond label="#{cond.value}"]\n)
|
32
37
|
|
33
38
|
unless yes.nil?
|
34
39
|
yes.out(file)
|
35
|
-
file.write %
|
40
|
+
file.write %( #{id} -> #{yes.id} [label="Yes"]\n)
|
36
41
|
end
|
37
42
|
unless no.nil?
|
38
43
|
no.out(file)
|
39
|
-
file.write %
|
44
|
+
file.write %( #{id} -> #{no.id} [label="No"]\n)
|
40
45
|
end
|
41
46
|
end
|
42
47
|
|
43
48
|
def id
|
44
49
|
cond.id
|
45
50
|
end
|
51
|
+
|
46
52
|
def ends
|
47
53
|
ary = []
|
48
|
-
if yes.elements.empty?
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
if no.elements.empty?
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
54
|
+
ary << if yes.elements.empty?
|
55
|
+
yes.id
|
56
|
+
else
|
57
|
+
yes.elements.last.ends
|
58
|
+
end
|
59
|
+
ary << if no.elements.empty?
|
60
|
+
no.id
|
61
|
+
else
|
62
|
+
no.elements.last.ends
|
63
|
+
end
|
58
64
|
ary.flatten
|
59
65
|
end
|
60
66
|
end
|
@@ -63,6 +69,7 @@ module Markdoc
|
|
63
69
|
def value
|
64
70
|
text_value.strip
|
65
71
|
end
|
72
|
+
|
66
73
|
def id
|
67
74
|
@id ||= Register.id
|
68
75
|
end
|
@@ -73,11 +80,10 @@ module Markdoc
|
|
73
80
|
prev = nil
|
74
81
|
elements.each do |node|
|
75
82
|
next if node.nil?
|
83
|
+
|
76
84
|
node.out(file)
|
77
|
-
|
78
|
-
|
79
|
-
file.write %Q(#{endid} -> #{node.id}\n)
|
80
|
-
end
|
85
|
+
prev&.ends&.each do |endid|
|
86
|
+
file.write %(#{endid} -> #{node.id}\n)
|
81
87
|
end
|
82
88
|
prev = node
|
83
89
|
end
|
@@ -90,11 +96,11 @@ module Markdoc
|
|
90
96
|
def ends
|
91
97
|
ary = []
|
92
98
|
elements.each do |node|
|
93
|
-
if node.elements.empty?
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
99
|
+
ary << if node.elements.empty?
|
100
|
+
node.id
|
101
|
+
else
|
102
|
+
node.ends
|
103
|
+
end
|
98
104
|
end
|
99
105
|
ary.flatten
|
100
106
|
end
|
@@ -104,7 +110,7 @@ module Markdoc
|
|
104
110
|
parser = PseudocodeParser.new
|
105
111
|
tree = parser.parse(code)
|
106
112
|
|
107
|
-
if
|
113
|
+
if tree.nil?
|
108
114
|
puts parser.failure_reason
|
109
115
|
raise "Can't generate graphviz code"
|
110
116
|
else
|
@@ -118,9 +124,7 @@ module Markdoc
|
|
118
124
|
graphviz = file.path
|
119
125
|
end
|
120
126
|
|
121
|
-
if format == :graphviz
|
122
|
-
return IO.read(graphviz)
|
123
|
-
end
|
127
|
+
return IO.read(graphviz) if format == :graphviz
|
124
128
|
|
125
129
|
image = Tempfile.new([digest, ".#{format}"])
|
126
130
|
image.close
|
data/lib/markdoc/renderer.rb
CHANGED
@@ -1,9 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'redcarpet'
|
2
4
|
require 'pygments'
|
3
5
|
|
4
6
|
module Markdoc
|
5
7
|
class Renderer < Redcarpet::Render::HTML
|
6
|
-
|
7
8
|
def block_code(code, language)
|
8
9
|
case language
|
9
10
|
when 'pseudo', 'pseudocode'
|
@@ -17,27 +18,27 @@ module Markdoc
|
|
17
18
|
|
18
19
|
# removes xml or doctype meta info
|
19
20
|
def wrap_svg(source)
|
20
|
-
stripped = source
|
21
|
-
sub(/<\?xml[^>]+>/i, '')
|
22
|
-
sub(/<!DOCTYPE[^>]+>/im, '')
|
23
|
-
gsub(
|
21
|
+
stripped = source
|
22
|
+
.sub(/<\?xml[^>]+>/i, '')
|
23
|
+
.sub(/<!DOCTYPE[^>]+>/im, '')
|
24
|
+
.gsub(/<!--[^>]+-->/, '')
|
24
25
|
|
25
|
-
%
|
26
|
+
%(<div class="svg-holder">\n#{stripped}\n</div>)
|
26
27
|
end
|
27
28
|
|
28
29
|
def doc_header
|
29
|
-
|
30
|
-
<html>
|
31
|
-
<head>
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
#{IO.read File.expand_path('
|
36
|
-
#{IO.read File.expand_path('
|
37
|
-
|
38
|
-
</head>
|
39
|
-
<body>
|
40
|
-
|
30
|
+
<<~HEADER
|
31
|
+
<html>
|
32
|
+
<head>
|
33
|
+
<title>Doc</title>
|
34
|
+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
35
|
+
<style>
|
36
|
+
#{IO.read File.expand_path('../../css/style.css', __dir__)}
|
37
|
+
#{IO.read File.expand_path('../../css/pygments.css', __dir__)}
|
38
|
+
</style>
|
39
|
+
</head>
|
40
|
+
<body>
|
41
|
+
HEADER
|
41
42
|
end
|
42
43
|
|
43
44
|
def doc_footer
|
data/lib/markdoc/sequence.rb
CHANGED
@@ -1,210 +1,319 @@
|
|
1
|
+
# frozen_string_literal: false
|
2
|
+
|
1
3
|
module Markdoc
|
2
4
|
module Sequence
|
3
|
-
|
4
|
-
|
5
|
+
DEFAULTS = {
|
6
|
+
diagram: {
|
7
|
+
offsetx: 10,
|
8
|
+
offsety: 10,
|
9
|
+
width: 900,
|
10
|
+
height: 600
|
11
|
+
},
|
12
|
+
role: {
|
13
|
+
font: "'Roboto Condensed', sans-serif",
|
14
|
+
border: '#3c4260',
|
15
|
+
fill: '#dcd7d7',
|
16
|
+
radius: 2,
|
17
|
+
spacing: 100,
|
18
|
+
width: 100,
|
19
|
+
height: 55,
|
20
|
+
line: 3
|
21
|
+
},
|
22
|
+
message: {
|
23
|
+
color: '#3c4260',
|
24
|
+
font: "'Roboto Condensed', sans-serif",
|
25
|
+
size: 11,
|
26
|
+
spacing: 40,
|
27
|
+
offset: 100, # from top
|
28
|
+
line: 3,
|
29
|
+
dash: '4,2'
|
30
|
+
}
|
31
|
+
}.freeze
|
32
|
+
|
33
|
+
def self.draw(code)
|
34
|
+
diagram = Diagram.new(code)
|
35
|
+
diagram.parse
|
36
|
+
diagram.print
|
37
|
+
end
|
5
38
|
|
6
|
-
|
39
|
+
class Role
|
40
|
+
include Comparable
|
41
|
+
|
42
|
+
attr_accessor :id, :label, :messages, :column,
|
43
|
+
:offsetx, :offsety, :border, :fill, :radius, :spacing, :width, :height, :line, :font,
|
44
|
+
:prev, :succ
|
45
|
+
|
46
|
+
def initialize(args)
|
47
|
+
self.messages = []
|
48
|
+
self.id = args[:id].strip
|
49
|
+
self.label = args[:label].strip
|
7
50
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
51
|
+
# ui settings
|
52
|
+
self.column = args[:column]
|
53
|
+
self.offsetx = args[:diagram][:offsetx]
|
54
|
+
self.offsety = args[:diagram][:offsety]
|
55
|
+
self.border = args[:ui][:border]
|
56
|
+
self.fill = args[:ui][:fill]
|
57
|
+
self.radius = args[:ui][:radius]
|
58
|
+
self.spacing = args[:ui][:spacing]
|
59
|
+
self.width = args[:ui][:width]
|
60
|
+
self.height = args[:ui][:height]
|
61
|
+
self.line = args[:ui][:line]
|
62
|
+
self.font = args[:ui][:font]
|
12
63
|
end
|
13
64
|
|
14
|
-
|
15
|
-
|
65
|
+
def <=>(other)
|
66
|
+
column <=> other.column
|
16
67
|
end
|
17
68
|
|
18
|
-
|
19
|
-
|
69
|
+
def type
|
70
|
+
case label
|
71
|
+
when /actor/i
|
72
|
+
:actor
|
73
|
+
when /database/i
|
74
|
+
:database
|
75
|
+
when /site|web/i
|
76
|
+
:website
|
77
|
+
when /application|system/i
|
78
|
+
:system
|
79
|
+
else
|
80
|
+
:component
|
81
|
+
end
|
82
|
+
end
|
20
83
|
|
21
|
-
|
22
|
-
|
23
|
-
else
|
24
|
-
raise "Can't generate sequence diagram"
|
84
|
+
def center
|
85
|
+
x + width / 2
|
25
86
|
end
|
26
|
-
end
|
27
87
|
|
28
|
-
|
29
|
-
|
30
|
-
def initialize(type, id, label)
|
31
|
-
self.type, self.id, self.label = type, id, label
|
32
|
-
self.active = false
|
88
|
+
def x
|
89
|
+
offsetx + column * (width + spacing)
|
33
90
|
end
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
"active(#{id});"
|
91
|
+
|
92
|
+
def y
|
93
|
+
offsety
|
38
94
|
end
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
95
|
+
|
96
|
+
def print
|
97
|
+
elements = []
|
98
|
+
case type
|
99
|
+
when :actor
|
100
|
+
elements << %[<g transform="translate(#{x + 10},0)"><path d="M74,64 a30,30 0 0,0 -27,-27 a16,18 0 1,0 -16,0 a30,30 0, 0,0 -27,27 z" stroke-width="#{line}" fill="#{fill}" stroke="#{border}"/></g>]
|
101
|
+
elements << %(<text x="#{x + 46 - 2 * id.size}" y="#{y + height - 5}" font-family="#{font}" font-size="12" fill="#{border}">#{id}</text>)
|
102
|
+
else
|
103
|
+
elements << %(<rect fill="#{fill}" stroke="#{border}" rx="#{radius}" ry="#{radius}" x="#{x}" y="#{y}" width="#{width}" height="#{height}" stroke-width="#{line}"/>)
|
104
|
+
elements << %(<text x="#{x + 10}" y="#{y + 20}" font-family="#{font}" font-size="12" fill="#{border}">#{label}</text>)
|
105
|
+
end
|
106
|
+
|
107
|
+
x1 = center
|
108
|
+
y1 = offsety + height
|
109
|
+
x2 = center
|
110
|
+
y2 = messages.last.y + 10
|
111
|
+
elements << %(<line x1="#{x1}" y1="#{y1}" x2="#{x2}" y2="#{y2}" stroke="#{border}" stroke-width="#{line}"/>)
|
112
|
+
|
113
|
+
elements.join("\n")
|
43
114
|
end
|
44
115
|
end
|
45
116
|
|
46
117
|
class Message
|
47
|
-
attr_accessor :
|
48
|
-
|
49
|
-
|
50
|
-
|
118
|
+
attr_accessor :source, :dest, :op, :label, :comment, :row,
|
119
|
+
:offset, :color, :font, :size, :spacing, :line, :dash,
|
120
|
+
:options
|
121
|
+
|
122
|
+
def initialize(args)
|
123
|
+
self.options = []
|
124
|
+
self.label = args[:label].strip
|
125
|
+
self.comment = args[:comment].strip
|
126
|
+
|
127
|
+
self.op = args[:op]
|
128
|
+
self.row = args[:row]
|
129
|
+
# ui
|
130
|
+
self.offset = args[:ui][:offset]
|
131
|
+
self.color = args[:ui][:color]
|
132
|
+
self.font = args[:ui][:font]
|
133
|
+
self.size = args[:ui][:size]
|
134
|
+
self.spacing = args[:ui][:spacing]
|
135
|
+
self.line = args[:ui][:line]
|
136
|
+
self.dash = args[:ui][:dash]
|
137
|
+
|
138
|
+
if op.index('~')
|
139
|
+
options << %(stroke-dasharray="#{dash}")
|
140
|
+
elsif op.index('-').nil?
|
141
|
+
raise 'Message direction must be one of ->, ~>, <-, <~'
|
142
|
+
end
|
51
143
|
|
52
|
-
|
53
|
-
|
144
|
+
if op.index('>')
|
145
|
+
self.source = args[:role1]
|
146
|
+
self.dest = args[:role2]
|
147
|
+
elsif op.index('<')
|
148
|
+
self.source = args[:role2]
|
149
|
+
self.dest = args[:role1]
|
150
|
+
else
|
151
|
+
raise 'Message direction must be one of ->, ~>, <-, <~'
|
152
|
+
end
|
153
|
+
|
154
|
+
source.messages << self
|
155
|
+
dest.messages << self unless source.eql?(dest)
|
54
156
|
end
|
55
157
|
|
56
|
-
def
|
57
|
-
|
158
|
+
def print
|
159
|
+
role1, role2 = *(source < dest ? [source, dest] : [dest, source])
|
160
|
+
elements = []
|
161
|
+
|
162
|
+
x1 = role1.center
|
163
|
+
if role1.eql?(role2)
|
164
|
+
y1 = y
|
165
|
+
x2 = x1 + 50
|
166
|
+
y2 = y1 + spacing
|
167
|
+
|
168
|
+
elements << %(<polyline points="#{x1},#{y1} #{x2},#{y1} #{x2},#{y2} #{x1 + 5},#{y2}" fill="none" stroke-width="2" stroke-linejoin="round" stroke="#{color}" #{options.join ' '}/>)
|
169
|
+
elements << %(<polygon points="#{x1 + 10},#{y2 - 5} #{x1},#{y2} #{x1 + 10},#{y2 + 5}" fill="#{color}"/>)
|
170
|
+
elements << %(<text x="#{x1 + 10}" y="#{y1 - 5}" font-family="#{font}" font-size="#{size}" fill="#{color}">#{label}</text>)
|
171
|
+
else
|
172
|
+
x2 = role2.center
|
173
|
+
|
174
|
+
if role1 == source
|
175
|
+
x2 -= 10
|
176
|
+
elements << %(<polygon points="#{x2},#{y - 5} #{x2 + 10},#{y} #{x2},#{y + 5}" fill="#{color}"/>)
|
177
|
+
else
|
178
|
+
x1 += 10
|
179
|
+
elements << %(<polygon points="#{x1},#{y - 5} #{x1 - 10},#{y} #{x1},#{y + 5}" fill="#{color}"/>)
|
180
|
+
end
|
181
|
+
|
182
|
+
elements << %(<line x1="#{x1}" y1="#{y}" x2="#{x2}" y2="#{y}" stroke="#{color}" stroke-width="2" #{options.join ' '}/>)
|
183
|
+
elements << %(<text x="#{x1 + 40}" y="#{y - 5}" font-family="#{font}" font-size="#{size}" fill="#{color}">#{label}</text>)
|
184
|
+
|
185
|
+
if comment.size.positive?
|
186
|
+
x = role2.prev.center + 15
|
187
|
+
elements << %(<path fill="#eeeeee" d="M#{x2 - 30},#{y + 1} L#{x2 - 30},#{y + 10} H#{x} V#{y + 2 * spacing - 25} H#{x2} V#{y + 10} H#{x2 - 20} z" />)
|
188
|
+
elements << %(<text x="#{x + 5}" y="#{y + 23}" font-family="#{font}" font-size="#{size}" fill="#{color}">)
|
189
|
+
split(comment).each_with_index do |line, i|
|
190
|
+
elements << %(<tspan x="#{x + 5}" y="#{y + 23 + 13 * i}">#{line}</tspan>)
|
191
|
+
end
|
192
|
+
elements << '</text>'
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
elements.join("\n")
|
58
197
|
end
|
59
198
|
|
60
|
-
def
|
61
|
-
|
62
|
-
width = comment.length > 10 ? 1 : comment.length * 0.13
|
63
|
-
width = 0.5 if width < 0.5
|
64
|
-
%Q[comment(#{dest.id},C,up 0.2 right, wid #{'%.1f' % width} ht 0.3 "#{comment}");]
|
199
|
+
def y
|
200
|
+
offset + row * spacing
|
65
201
|
end
|
66
202
|
|
67
|
-
|
68
|
-
|
203
|
+
private
|
204
|
+
|
205
|
+
def split(text, max = 35)
|
206
|
+
ary = []
|
207
|
+
line = ''
|
208
|
+
text.split.each do |word|
|
209
|
+
if (line + word).length < max
|
210
|
+
line << ' ' << word
|
211
|
+
else
|
212
|
+
ary << line
|
213
|
+
line = word
|
214
|
+
end
|
215
|
+
end
|
216
|
+
ary << line if line.length.positive?
|
217
|
+
ary
|
69
218
|
end
|
70
219
|
end
|
71
220
|
|
72
|
-
class
|
73
|
-
attr_accessor :
|
74
|
-
|
75
|
-
def
|
76
|
-
|
77
|
-
boxht: '0.5', # Object box height
|
78
|
-
boxwid: '1.3', # Object box width
|
79
|
-
awid: '0.1', # Active lifeline width
|
80
|
-
spacing: '0.25', # Spacing between messages
|
81
|
-
movewid: '0.75', # Spacing between objects
|
82
|
-
dashwid: '0.05', # Interval for dashed lines
|
83
|
-
maxpswid: '20', # Maximum width of picture
|
84
|
-
maxpsht: '20', # Maximum height of picture
|
85
|
-
underline: '0', # Underline the name of objects
|
86
|
-
}
|
87
|
-
end
|
88
|
-
|
89
|
-
def initialize(source, options = {})
|
90
|
-
self.source = source
|
221
|
+
class Diagram
|
222
|
+
attr_accessor :input, :output, :attributes, :roles, :messages, :rows
|
223
|
+
|
224
|
+
def initialize(input, options = {})
|
225
|
+
self.input = input
|
91
226
|
self.output = []
|
92
227
|
self.roles = []
|
93
228
|
self.messages = []
|
94
|
-
self.
|
229
|
+
self.rows = 0
|
230
|
+
self.attributes = DEFAULTS.dup
|
231
|
+
|
95
232
|
options.each do |key, value|
|
96
|
-
|
233
|
+
attributes.merge!(key => value)
|
97
234
|
end
|
98
235
|
end
|
99
236
|
|
100
237
|
def find(id)
|
101
|
-
id.strip
|
102
|
-
roles.detect{|role| role.id == id}
|
238
|
+
roles.detect { |role| role.id == id.strip } or raise("Non-declared role: #{id}")
|
103
239
|
end
|
104
240
|
|
105
241
|
def parse
|
106
|
-
|
242
|
+
input.split("\n").each do |line|
|
107
243
|
next if line.strip.empty?
|
108
|
-
if match = line.match(/^([a-zA-Z0-9_ \t]+) *= *([a-zA-Z0-9_ \t]+)/)
|
109
|
-
if match[2] =~ /Actor/
|
110
|
-
roles << Role.new(:actor, match[1].strip, match[1].strip)
|
111
|
-
else
|
112
|
-
roles << Role.new(:object, match[1].strip, match[2].strip)
|
113
|
-
end
|
114
|
-
elsif match = line.match(/^([a-zA-Z0-9_ \t]+) *([<\-~>]{2}) *([a-zA-Z0-9_ \t]+):([^#]+)#?(.*)/)
|
115
|
-
role1, role2, op = find(match[1]), find(match[3]), match[2]
|
116
|
-
|
117
|
-
if op.index('>')
|
118
|
-
source, dest = role1, role2
|
119
|
-
elsif op.index('<')
|
120
|
-
source, dest = role2, role1
|
121
|
-
else
|
122
|
-
raise "Message direction must be one of ->, ~>, <-, <~"
|
123
|
-
end
|
124
244
|
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
#
|
151
|
-
|
152
|
-
(
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
245
|
+
if (matches = line.match(/^(?<id>[a-zA-Z0-9_ \t]+) *= *(?<label>[a-zA-Z0-9_ \t]+)/))
|
246
|
+
# User = Actor
|
247
|
+
roles << Role.new(
|
248
|
+
id: matches[:id],
|
249
|
+
label: matches[:label],
|
250
|
+
column: roles.size,
|
251
|
+
diagram: attributes[:diagram],
|
252
|
+
ui: attributes[:role]
|
253
|
+
)
|
254
|
+
elsif (matches = line.match(/^(?<role1>[a-zA-Z0-9_ \t]+) *(?<op>[<\-~>]{2}) *(?<role2>[a-zA-Z0-9_ \t]+):(?<label>[^#]+)#?(?<comment>.*)/))
|
255
|
+
# User -> Web : Login
|
256
|
+
messages << Message.new(
|
257
|
+
role1: find(matches[:role1]),
|
258
|
+
role2: find(matches[:role2]),
|
259
|
+
row: rows,
|
260
|
+
op: matches[:op],
|
261
|
+
label: matches[:label],
|
262
|
+
comment: matches[:comment],
|
263
|
+
diagram: attributes[:diagram],
|
264
|
+
ui: attributes[:message]
|
265
|
+
)
|
266
|
+
self.rows += 1
|
267
|
+
# comment takes 1 more row
|
268
|
+
self.rows += 1 if matches[:comment].length.positive?
|
269
|
+
elsif (matches = line.match(/^(?<role>[a-zA-Z0-9_ \t]+) *:(?<label>[^#]+)#?(?<comment>.*)/))
|
270
|
+
# Web : Save the form
|
271
|
+
messages << Message.new(
|
272
|
+
role1: find(matches[:role]),
|
273
|
+
role2: find(matches[:role]),
|
274
|
+
row: rows,
|
275
|
+
op: '->',
|
276
|
+
label: matches[:label],
|
277
|
+
comment: matches[:comment],
|
278
|
+
diagram: attributes[:diagram],
|
279
|
+
ui: attributes[:message]
|
280
|
+
)
|
281
|
+
# self message takes 2 rows
|
282
|
+
self.rows += 2
|
161
283
|
end
|
162
284
|
end
|
163
285
|
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
286
|
+
prev = nil
|
287
|
+
roles.each do |succ|
|
288
|
+
succ.prev = prev
|
289
|
+
prev.succ = succ if prev
|
290
|
+
prev = succ
|
291
|
+
end
|
168
292
|
end
|
169
293
|
|
170
|
-
def
|
171
|
-
|
294
|
+
def print
|
295
|
+
format(template, width: width, height: height, content: (roles + messages).map(&:print).join("\n"))
|
172
296
|
end
|
173
297
|
|
174
|
-
def
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
headers << ''
|
180
|
-
headers << '# Variables'
|
181
|
-
# calculate height
|
182
|
-
|
183
|
-
variables[:maxpsht] = ((variables[:spacing].to_f *
|
184
|
-
messages.map(&:height).reduce(:+)) +
|
185
|
-
variables[:boxht].to_f).ceil
|
298
|
+
def height
|
299
|
+
attributes[:message][:offset] +
|
300
|
+
attributes[:message][:spacing] * rows +
|
301
|
+
attributes[:diagram][:offsety] * 2
|
302
|
+
end
|
186
303
|
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
headers << '# Actors and Objects'
|
191
|
-
roles.each do |object|
|
192
|
-
headers << %Q[#{object.type}(#{object.id},"#{object.label}");]
|
193
|
-
end
|
194
|
-
headers << 'step();'
|
195
|
-
headers << ''
|
196
|
-
self.output = headers + output
|
304
|
+
def width
|
305
|
+
(attributes[:role][:spacing] + attributes[:role][:width]) * roles.size +
|
306
|
+
attributes[:diagram][:offsetx]
|
197
307
|
end
|
198
308
|
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
output << '.PE'
|
309
|
+
private
|
310
|
+
|
311
|
+
def template
|
312
|
+
'<svg xmlns="http://www.w3.org/2000/svg" ' \
|
313
|
+
'xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" ' \
|
314
|
+
'width="%<width>s" height="%<height>s" ' \
|
315
|
+
'viewBox="0 0 %<width>s %<height>s">' \
|
316
|
+
'%<content>s</svg>'
|
208
317
|
end
|
209
318
|
end
|
210
319
|
end
|
data/lib/markdoc/version.rb
CHANGED
data/lib/markdoc.rb
CHANGED
metadata
CHANGED
@@ -1,80 +1,85 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: markdoc
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
5
|
-
prerelease:
|
4
|
+
version: 2.0.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
|
-
-
|
9
|
-
autorequire:
|
7
|
+
- Ochirkhuyag.L
|
8
|
+
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2022-06-15 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: polyglot
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
|
-
- - ~>
|
17
|
+
- - "~>"
|
20
18
|
- !ruby/object:Gem::Version
|
21
19
|
version: '0.3'
|
22
20
|
type: :runtime
|
23
21
|
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
23
|
requirements:
|
27
|
-
- - ~>
|
24
|
+
- - "~>"
|
28
25
|
- !ruby/object:Gem::Version
|
29
26
|
version: '0.3'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: pygments.rb
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '2.3'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '2.3'
|
30
41
|
- !ruby/object:Gem::Dependency
|
31
42
|
name: redcarpet
|
32
43
|
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
44
|
requirements:
|
35
|
-
- - ~>
|
45
|
+
- - "~>"
|
36
46
|
- !ruby/object:Gem::Version
|
37
|
-
version: '3.
|
47
|
+
version: '3.5'
|
38
48
|
type: :runtime
|
39
49
|
prerelease: false
|
40
50
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
51
|
requirements:
|
43
|
-
- - ~>
|
52
|
+
- - "~>"
|
44
53
|
- !ruby/object:Gem::Version
|
45
|
-
version: '3.
|
54
|
+
version: '3.5'
|
46
55
|
- !ruby/object:Gem::Dependency
|
47
56
|
name: treetop
|
48
57
|
requirement: !ruby/object:Gem::Requirement
|
49
|
-
none: false
|
50
58
|
requirements:
|
51
|
-
- - ~>
|
59
|
+
- - "~>"
|
52
60
|
- !ruby/object:Gem::Version
|
53
61
|
version: '1.6'
|
54
62
|
type: :runtime
|
55
63
|
prerelease: false
|
56
64
|
version_requirements: !ruby/object:Gem::Requirement
|
57
|
-
none: false
|
58
65
|
requirements:
|
59
|
-
- - ~>
|
66
|
+
- - "~>"
|
60
67
|
- !ruby/object:Gem::Version
|
61
68
|
version: '1.6'
|
62
69
|
- !ruby/object:Gem::Dependency
|
63
|
-
name:
|
70
|
+
name: rake
|
64
71
|
requirement: !ruby/object:Gem::Requirement
|
65
|
-
none: false
|
66
72
|
requirements:
|
67
|
-
- - ~>
|
73
|
+
- - "~>"
|
68
74
|
- !ruby/object:Gem::Version
|
69
|
-
version: '0
|
70
|
-
type: :
|
75
|
+
version: '13.0'
|
76
|
+
type: :development
|
71
77
|
prerelease: false
|
72
78
|
version_requirements: !ruby/object:Gem::Requirement
|
73
|
-
none: false
|
74
79
|
requirements:
|
75
|
-
- - ~>
|
80
|
+
- - "~>"
|
76
81
|
- !ruby/object:Gem::Version
|
77
|
-
version: '0
|
82
|
+
version: '13.0'
|
78
83
|
description: Markdown with support for pseudocode to flowchart and sequence diagram
|
79
84
|
generation
|
80
85
|
email: ochkoo@gmail.com
|
@@ -85,41 +90,38 @@ executables:
|
|
85
90
|
extensions: []
|
86
91
|
extra_rdoc_files: []
|
87
92
|
files:
|
93
|
+
- bin/markdoc
|
94
|
+
- bin/pseudo2svg
|
95
|
+
- bin/sequence2svg
|
96
|
+
- css/pygments.css
|
97
|
+
- css/style.css
|
88
98
|
- lib/markdoc.rb
|
89
99
|
- lib/markdoc/pseudocode.rb
|
90
100
|
- lib/markdoc/pseudocode.treetop
|
91
101
|
- lib/markdoc/renderer.rb
|
92
102
|
- lib/markdoc/sequence.rb
|
93
|
-
- lib/markdoc/sequence.pic
|
94
103
|
- lib/markdoc/version.rb
|
95
|
-
- css/style.css
|
96
|
-
- css/pygments.css
|
97
|
-
- bin/markdoc
|
98
|
-
- bin/pseudo2svg
|
99
|
-
- bin/sequence2svg
|
100
104
|
homepage: https://github.com/ochko/markdoc
|
101
105
|
licenses:
|
102
106
|
- MIT
|
103
|
-
|
107
|
+
metadata: {}
|
108
|
+
post_install_message:
|
104
109
|
rdoc_options: []
|
105
110
|
require_paths:
|
106
111
|
- lib
|
107
112
|
required_ruby_version: !ruby/object:Gem::Requirement
|
108
|
-
none: false
|
109
113
|
requirements:
|
110
|
-
- -
|
114
|
+
- - ">="
|
111
115
|
- !ruby/object:Gem::Version
|
112
|
-
version:
|
116
|
+
version: 2.7.6
|
113
117
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
114
|
-
none: false
|
115
118
|
requirements:
|
116
|
-
- -
|
119
|
+
- - ">="
|
117
120
|
- !ruby/object:Gem::Version
|
118
121
|
version: '0'
|
119
122
|
requirements: []
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
specification_version: 3
|
123
|
+
rubygems_version: 3.1.6
|
124
|
+
signing_key:
|
125
|
+
specification_version: 4
|
124
126
|
summary: Markdown to HTML converter with diagrams
|
125
127
|
test_files: []
|
data/lib/markdoc/sequence.pic
DELETED
@@ -1,406 +0,0 @@
|
|
1
|
-
#/usr/bin/pic2plot -Tps
|
2
|
-
#
|
3
|
-
# Pic macros for drawing UML sequence diagrams
|
4
|
-
#
|
5
|
-
# (C) Copyright 2004-2005 Diomidis Spinellis.
|
6
|
-
#
|
7
|
-
# Permission to use, copy, and distribute this software and its
|
8
|
-
# documentation for any purpose and without fee is hereby granted,
|
9
|
-
# provided that the above copyright notice appear in all copies and that
|
10
|
-
# both that copyright notice and this permission notice appear in
|
11
|
-
# supporting documentation.
|
12
|
-
#
|
13
|
-
# THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
14
|
-
# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
15
|
-
# MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
16
|
-
#
|
17
|
-
#
|
18
|
-
|
19
|
-
|
20
|
-
# Default parameters (can be redefined)
|
21
|
-
|
22
|
-
# Spacing between messages
|
23
|
-
spacing = 0.25;
|
24
|
-
# Active box width
|
25
|
-
awid = .1;
|
26
|
-
# Box height
|
27
|
-
boxht = 0.3;
|
28
|
-
# Commend folding
|
29
|
-
corner_fold=awid
|
30
|
-
# Comment distance
|
31
|
-
define comment_default_move {up 0.25 right 0.25};
|
32
|
-
# Comment height
|
33
|
-
comment_default_ht=0.5;
|
34
|
-
# Comment width
|
35
|
-
comment_default_wid=1;
|
36
|
-
# Underline object name
|
37
|
-
underline=1;
|
38
|
-
|
39
|
-
# Create a new object(name,label)
|
40
|
-
define object {
|
41
|
-
$1: box $2; move;
|
42
|
-
# Could also underline text with \mk\ul\ul\ul...\rt
|
43
|
-
if (underline) then {
|
44
|
-
line from $1.w + (.1, -.07) to $1.e + (-.1, -.07);
|
45
|
-
}
|
46
|
-
move to $1.e;
|
47
|
-
move right;
|
48
|
-
# Active is the level of activations of the object
|
49
|
-
# 0 : inactive : draw thin line swimlane
|
50
|
-
# 1 : active : draw thick swimlane
|
51
|
-
# > 1: nested : draw nested swimlane
|
52
|
-
active_$1 = 0;
|
53
|
-
lifestart_$1 = $1.s.y;
|
54
|
-
}
|
55
|
-
|
56
|
-
# Create a new external actor(name,label)
|
57
|
-
define actor {
|
58
|
-
$1: [
|
59
|
-
XSEQC: circle rad 0.06;
|
60
|
-
XSEQL: line from XSEQC.s down .12;
|
61
|
-
line from XSEQL.start - (.15,.02) to XSEQL.start + (.15,-.02);
|
62
|
-
XSEQL1: line from XSEQL.end left .08 down .15;
|
63
|
-
XSEQL2: line from XSEQL.end right .08 down .15;
|
64
|
-
line at XSEQC.n invis "" "" "" $2;
|
65
|
-
]
|
66
|
-
move to $1.e;
|
67
|
-
move right;
|
68
|
-
active_$1 = 0;
|
69
|
-
lifestart_$1 = $1.s.y - .05;
|
70
|
-
}
|
71
|
-
|
72
|
-
# Create a new placeholder object(name)
|
73
|
-
define placeholder_object {
|
74
|
-
$1: box invisible;
|
75
|
-
move;
|
76
|
-
move to $1.e;
|
77
|
-
move right;
|
78
|
-
active_$1 = 0;
|
79
|
-
lifestart_$1 = $1.s.y;
|
80
|
-
}
|
81
|
-
|
82
|
-
define pobject {
|
83
|
-
placeholder_object($1);
|
84
|
-
}
|
85
|
-
|
86
|
-
define extend_lifeline {
|
87
|
-
if (active_$1 > 0) then {
|
88
|
-
# draw the left edges of the boxes
|
89
|
-
move to ($1.x - awid/2, Here.y);
|
90
|
-
for level = 1 to active_$1 do {
|
91
|
-
line from (Here.x, lifestart_$1) to Here;
|
92
|
-
move right awid/2
|
93
|
-
}
|
94
|
-
|
95
|
-
# draw the right edge of the innermost box
|
96
|
-
move right awid/2;
|
97
|
-
line from (Here.x, lifestart_$1) to Here;
|
98
|
-
} else {
|
99
|
-
line from ($1.x, lifestart_$1) to ($1.x, Here.y) dashed;
|
100
|
-
}
|
101
|
-
lifestart_$1 = Here.y;
|
102
|
-
}
|
103
|
-
|
104
|
-
# complete(name)
|
105
|
-
# Complete the lifeline of the object with the given name
|
106
|
-
define complete {
|
107
|
-
extend_lifeline($1)
|
108
|
-
if (active_$1) then {
|
109
|
-
# draw bottom of all active boxes
|
110
|
-
line right ((active_$1 + 1) * awid/2) from ($1.x - awid/2, Here.y);
|
111
|
-
}
|
112
|
-
}
|
113
|
-
|
114
|
-
# Draw a message(from_object,to_object,label)
|
115
|
-
define message {
|
116
|
-
down;
|
117
|
-
move spacing;
|
118
|
-
# Adjust so that lines and arrows do not fall into the
|
119
|
-
# active box. Should be .5, but the arrow heads tend to
|
120
|
-
# overshoot.
|
121
|
-
if ($1.x <= $2.x) then {
|
122
|
-
off_from = awid * .6;
|
123
|
-
off_to = -awid * .6;
|
124
|
-
} else {
|
125
|
-
off_from = -awid * .6;
|
126
|
-
off_to = awid * .6;
|
127
|
-
}
|
128
|
-
|
129
|
-
# add half a box width for each level of nesting
|
130
|
-
if (active_$1 > 1) then {
|
131
|
-
off_from = off_from + (active_$1 - 1) * awid/2;
|
132
|
-
}
|
133
|
-
|
134
|
-
# add half a box width for each level of nesting
|
135
|
-
if (active_$2 > 1) then {
|
136
|
-
off_to = off_to + (active_$2 - 1) * awid/2;
|
137
|
-
}
|
138
|
-
|
139
|
-
if ($1.x == $2.x) then {
|
140
|
-
arrow from ($1.x + off_from, Here.y) right then down .25 then left $3 ljust " " " " " " ;
|
141
|
-
} else {
|
142
|
-
arrow from ($1.x + off_from, Here.y) to ($2.x + off_to, Here.y) $3 " ";
|
143
|
-
}
|
144
|
-
}
|
145
|
-
|
146
|
-
# Display a lifeline constraint(object,label)
|
147
|
-
define lifeline_constraint {
|
148
|
-
off_from = awid;
|
149
|
-
# add half a box width for each level of nesting
|
150
|
-
if (active_$1 > 1) then {
|
151
|
-
off_from = off_from + (active_$1 - 1) * awid/2;
|
152
|
-
}
|
153
|
-
|
154
|
-
box at ($1.x + off_from, Here.y) invis $2 ljust " " ;
|
155
|
-
}
|
156
|
-
|
157
|
-
define lconstraint {
|
158
|
-
lifeline_constraint($1,$2);
|
159
|
-
}
|
160
|
-
|
161
|
-
# Display an object constraint(label)
|
162
|
-
# for the last object drawn
|
163
|
-
define object_constraint {
|
164
|
-
{ box invis with .s at last box .nw $1 ljust; }
|
165
|
-
}
|
166
|
-
|
167
|
-
define oconstraint {
|
168
|
-
object_constraint($1);
|
169
|
-
}
|
170
|
-
|
171
|
-
# Draw a creation message(from_object,to_object,object_label)
|
172
|
-
define create_message {
|
173
|
-
down;
|
174
|
-
move spacing;
|
175
|
-
if ($1.x <= $2.x) then {
|
176
|
-
off_from = awid * .6;
|
177
|
-
off_to = -boxwid * .51;
|
178
|
-
} else {
|
179
|
-
off_from = -awid * .6;
|
180
|
-
off_to = boxwid * .51;
|
181
|
-
}
|
182
|
-
|
183
|
-
# add half a box width for each level of nesting
|
184
|
-
if (active_$1 > 1) then {
|
185
|
-
off_from = off_from + (active_$1 - 1) * awid/2;
|
186
|
-
}
|
187
|
-
|
188
|
-
# See comment in destroy_message
|
189
|
-
XSEQA: arrow from ($1.x + off_from, Here.y) to ($2.x + off_to, Here.y) "�create�" " ";
|
190
|
-
if ($1.x <= $2.x) then {
|
191
|
-
{ XSEQB: box $3 with .w at XSEQA.end; }
|
192
|
-
} else {
|
193
|
-
{ XSEQB: box $3 with .e at XSEQA.end; }
|
194
|
-
}
|
195
|
-
{
|
196
|
-
line from XSEQB.w + (.1, -.07) to XSEQB.e + (-.1, -.07);
|
197
|
-
}
|
198
|
-
lifestart_$2 = XSEQB.s.y;
|
199
|
-
move (spacing + boxht) / 2;
|
200
|
-
}
|
201
|
-
|
202
|
-
define cmessage {
|
203
|
-
create_message($1,$2,$3);
|
204
|
-
}
|
205
|
-
|
206
|
-
# Draw an X for a given object
|
207
|
-
define drawx {
|
208
|
-
{
|
209
|
-
line from($1.x - awid, lifestart_$1 - awid) to ($1.x + awid, lifestart_$1 + awid);
|
210
|
-
line from($1.x - awid, lifestart_$1 + awid) to ($1.x + awid, lifestart_$1 - awid);
|
211
|
-
}
|
212
|
-
}
|
213
|
-
|
214
|
-
# Draw a destroy message(from_object,to_object)
|
215
|
-
define destroy_message {
|
216
|
-
down;
|
217
|
-
move spacing;
|
218
|
-
# The troff code is \(Fo \(Fc
|
219
|
-
# The groff code is also \[Fo] \[Fc]
|
220
|
-
# The pic2plot code is \Fo \Fc
|
221
|
-
# See http://www.delorie.com/gnu/docs/plotutils/plotutils_71.html
|
222
|
-
# To stay compatible with all we have to hardcode the characters
|
223
|
-
message($1,$2,"�destroy�");
|
224
|
-
complete($2);
|
225
|
-
drawx($2);
|
226
|
-
}
|
227
|
-
|
228
|
-
define dmessage {
|
229
|
-
destroy_message($1,$2);
|
230
|
-
}
|
231
|
-
|
232
|
-
# An object deletes itself: delete(object)
|
233
|
-
define delete {
|
234
|
-
complete($1);
|
235
|
-
lifestart_$1 = lifestart_$1 - awid;
|
236
|
-
drawx($1);
|
237
|
-
}
|
238
|
-
|
239
|
-
# Draw a message return(from_object,to_object,label)
|
240
|
-
define return_message {
|
241
|
-
down;
|
242
|
-
move spacing;
|
243
|
-
# See comment in message
|
244
|
-
if ($1.x <= $2.x) then {
|
245
|
-
off_from = awid * .6;
|
246
|
-
off_to = -awid * .6;
|
247
|
-
} else {
|
248
|
-
off_from = -awid * .6;
|
249
|
-
off_to = awid * .6;
|
250
|
-
}
|
251
|
-
|
252
|
-
# add half a box width for each level of nesting
|
253
|
-
if (active_$1 > 1) then {
|
254
|
-
off_from = off_from + (active_$1 - 1) * awid/2;
|
255
|
-
}
|
256
|
-
|
257
|
-
# add half a box width for each level of nesting
|
258
|
-
if (active_$2 > 1) then {
|
259
|
-
off_to = off_to + (active_$2 - 1) * awid/2;
|
260
|
-
}
|
261
|
-
|
262
|
-
arrow from ($1.x + off_from, Here.y) to ($2.x + off_to, Here.y) dashed $3 " ";
|
263
|
-
}
|
264
|
-
|
265
|
-
define rmessage {
|
266
|
-
return_message($1,$2,$3);
|
267
|
-
}
|
268
|
-
|
269
|
-
# Object becomes active
|
270
|
-
# Can be nested to show recursion
|
271
|
-
define active {
|
272
|
-
extend_lifeline($1);
|
273
|
-
# draw top of new active box
|
274
|
-
line right awid from ($1.x + (active_$1 - 1) * awid/2, Here.y);
|
275
|
-
active_$1 = active_$1 + 1;
|
276
|
-
}
|
277
|
-
|
278
|
-
# Object becomes inactive
|
279
|
-
# Can be nested to show recursion
|
280
|
-
define inactive {
|
281
|
-
extend_lifeline($1);
|
282
|
-
active_$1 = active_$1 - 1;
|
283
|
-
# draw bottom of innermost active box
|
284
|
-
line right awid from ($1.x + (active_$1 - 1) * awid/2, Here.y);
|
285
|
-
}
|
286
|
-
|
287
|
-
# Time step
|
288
|
-
# Useful at the beginning and the end
|
289
|
-
# to show object states
|
290
|
-
define step {
|
291
|
-
down;
|
292
|
-
move spacing;
|
293
|
-
}
|
294
|
-
|
295
|
-
# Switch to asynchronous messages
|
296
|
-
define async {
|
297
|
-
arrowhead = 0;
|
298
|
-
arrowwid = arrowwid * 2;
|
299
|
-
}
|
300
|
-
|
301
|
-
# Switch to synchronous messages
|
302
|
-
define sync {
|
303
|
-
arrowhead = 1;
|
304
|
-
arrowwid = arrowwid / 2;
|
305
|
-
}
|
306
|
-
|
307
|
-
# same as lifeline_constraint, but Text and empty string are exchanged.
|
308
|
-
define lconstraint_below{
|
309
|
-
off_from = awid;
|
310
|
-
# add half a box width for each level of nesting
|
311
|
-
if (active_$1 > 1) then {
|
312
|
-
off_from = off_from + (active_$1 - 1) * awid/2;
|
313
|
-
}
|
314
|
-
|
315
|
-
box at ($1.x + off_from, Here.y) invis "" $2 ljust;
|
316
|
-
}
|
317
|
-
|
318
|
-
# begin_frame(left_object,name,label_text);
|
319
|
-
define begin_frame {
|
320
|
-
# The lifeline will be cut here
|
321
|
-
extend_lifeline($1);
|
322
|
-
# draw the frame-label
|
323
|
-
$2: box $3 invis with .n at ($1.x, Here.y);
|
324
|
-
d = $2.e.y - $2.se.y;
|
325
|
-
line from $2.ne to $2.e then down d left d then to $2.sw;
|
326
|
-
# continue the lifeline below the frame-label
|
327
|
-
move to $2.s;
|
328
|
-
lifestart_$1 = Here.y;
|
329
|
-
}
|
330
|
-
|
331
|
-
# end_frame(right_object,name);
|
332
|
-
define end_frame {
|
333
|
-
# dummy-box for the lower right corner:
|
334
|
-
box invis "" with .s at ($1.x, Here.y);
|
335
|
-
# draw the frame
|
336
|
-
frame_wid = last box.se.x - $2.nw.x
|
337
|
-
frame_ht = - last box.se.y + $2.nw.y
|
338
|
-
box with .nw at $2.nw wid frame_wid ht frame_ht;
|
339
|
-
# restore Here.y
|
340
|
-
move to last box.s;
|
341
|
-
}
|
342
|
-
|
343
|
-
# comment(object,[name],[line_movement], [box_size] text);
|
344
|
-
define comment {
|
345
|
-
old_y = Here.y
|
346
|
-
# draw the first connecting line, at which's end the box wil be positioned
|
347
|
-
move to ($1.x, Here.y)
|
348
|
-
if "$3" == "" then {
|
349
|
-
line comment_default_move() dashed;
|
350
|
-
} else {
|
351
|
-
line $3 dashed;
|
352
|
-
}
|
353
|
-
|
354
|
-
# draw the box, use comment_default_xx if no explicit
|
355
|
-
# size is given together with the text in parameter 4
|
356
|
-
old_boxht=boxht;
|
357
|
-
old_boxwid=boxwid;
|
358
|
-
boxht=comment_default_ht;
|
359
|
-
boxwid=comment_default_wid;
|
360
|
-
if "$2" == "" then {
|
361
|
-
box invis $4;
|
362
|
-
} else {
|
363
|
-
$2: box invis $4;
|
364
|
-
}
|
365
|
-
boxht=old_boxht;
|
366
|
-
boxwid=old_boxwid;
|
367
|
-
|
368
|
-
# draw the frame of the comment
|
369
|
-
line from last box.nw \
|
370
|
-
to last box.ne - (corner_fold, 0) \
|
371
|
-
then to last box.ne - (0, corner_fold) \
|
372
|
-
then to last box.se \
|
373
|
-
then to last box.sw \
|
374
|
-
then to last box.nw ;
|
375
|
-
line from last box.ne - (corner_fold, 0) \
|
376
|
-
to last box.ne - (corner_fold, corner_fold) \
|
377
|
-
then to last box.ne - (0, corner_fold) ;
|
378
|
-
|
379
|
-
# restore Here.y
|
380
|
-
move to ($1.x, old_y)
|
381
|
-
}
|
382
|
-
|
383
|
-
# connect_to_comment(object,name);
|
384
|
-
define connect_to_comment {
|
385
|
-
old_y = Here.y
|
386
|
-
# start at the object
|
387
|
-
move to ($1.x, Here.y)
|
388
|
-
# find the best connection-point of the comment to use as line-end
|
389
|
-
if $1.x < $2.w.x then {
|
390
|
-
line to $2.w dashed;
|
391
|
-
} else {
|
392
|
-
if $1.x > $2.e.x then {
|
393
|
-
line to $2.e dashed;
|
394
|
-
} else {
|
395
|
-
if Here.y < $2.s.y then {
|
396
|
-
line to $2.s dashed;
|
397
|
-
} else {
|
398
|
-
if Here.y > $2.n.y then {
|
399
|
-
line to $2.n dashed;
|
400
|
-
}
|
401
|
-
}
|
402
|
-
}
|
403
|
-
}
|
404
|
-
# restore Here.y
|
405
|
-
move to ($1.x, old_y)
|
406
|
-
}
|