-
Notifications
You must be signed in to change notification settings - Fork 2
/
View2SingleHTML.ajs
213 lines (176 loc) · 7.76 KB
/
View2SingleHTML.ajs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
/*
+++++++++++++++ +++++
+++++++++++++++++ +++++
+++++ +++++ +++++
+++++ +++++ +++++
++++++++++++++++ ++++++++++++++++++
++++++++++++++++++ +++++++++++++++++
+++++ +++++ ++++++
+++++ +++++ ++++++
+++++ ++++++++++++++++++
+++++ +++++++++++++++
View2SingleHTML: Export selected view to single HTML file
Version 0.9, Feb 2024
Author : Remco Schellekens (remco.schellekens@ns.nl)
Licence: MIT https://mit-license.org/
When a view is selected, running this script will generate an HTML
file with embedded SVG (scales with browser screen size) and clickable
elements that jumps to url found in the "url" property of the element
or displays a popup window showing the documentation field of the element
(if set).
The HTML file relies on a little bit of HTML, SVG and included CSS only, and
doesn't use javascript and can therefore easily integrated in collaboration
tools like sharepoint.
If an element has a property "url" in it, it will folow the link, otherwise
it will check for an existing "documentation" property and shows a popup if
there is one.
It uses two simple template files stored in the "templates" directory
under the directory the script is stored. One for the surrounding HTML
file (v2s.html) and one for the content of the popup window (popup.html).
So you can customize it to your needs without adjusting this code
These are the template keywords that will be replaced by the code:
template_main:
{{view}} => SVG representation of view
{{name}} => name of view
{{popup}} => place to store generated HTML for popup windows
** Warning, don't delete the ".infobox" css style, it is used to
generate link in SVN up and wrapper for template_popup **
template_popup:
{{name}} => name of element
{{documentation}} => documentation of element
{{...any element property, if it is empty or doesn't exists, it will be blank ...}}
*/
/* templates to use */
template_main='v2s.html'
template_popup='v2s_popup.html'
/* global variables for creating SVG and HTML parts */
svg=""
popup=""
html_template=""
popup_template=""
/* function for reading files ....why isn't there a $.fs.readFile in jArchi ??.... */
function readFile(path) {
let Files = Java.type("java.nio.file.Files")
let Paths = Java.type("java.nio.file.Paths")
bytesObj=Files.readAllBytes(Paths.get(path))
bytes=Java.from(bytesObj)
return String.fromCharCode.apply(null,bytes)
}
function parsePopup(element) {
text=popup_template
popup+='<DIV id="'+element.id+'" class="infobox">\n'
element.prop().forEach(function(property) {
text=text.replaceAll("{{"+property+"}}",element.prop(property))
});
text=text.replaceAll("{{name}}",element.name)
text=text.replaceAll("{{documentation}}",element.documentation.replaceAll("\n","<BR/>"))
/* remove all other left over template elements */
text=text.replaceAll(/{{[^}]+}}/g,"")
popup+=text
popup+='</DIV>\n'
}
function traverseChildren(element,offx,offy) {
if (element.bounds) {
offx+=element.bounds.x
offy+=element.bounds.y
if (element.prop('url')!=null) {
/* create a box & link that uses given URL */
svg+='<a xlink:href="'+element.prop('url')+'">\n'
svg+='<path fill="white" d="M'+offx+' '+offy
svg+=' L'+String(offx+element.bounds.width)+' '+String(offy)
svg+=' L'+String(offx+element.bounds.width)+' '+String(offy+element.bounds.height)
svg+=' L'+String(offx)+' '+String(offy+element.bounds.height)
svg+='" fill-rule="evenodd" opacity="0.0" stroke="none"/>\n'
svg+='</a>\n'
} else {
if (element.documentation!=null) {
/* create a box & link that can be clicked for popup or URL */
svg+='<a xlink:href="#'+element.id+'">\n'
svg+='<path fill="white" d="M'+offx+' '+offy
svg+=' L'+String(offx+element.bounds.width)+' '+String(offy)
svg+=' L'+String(offx+element.bounds.width)+' '+String(offy+element.bounds.height)
svg+=' L'+String(offx)+' '+String(offy+element.bounds.height)
svg+='" fill-rule="evenodd" opacity="0.0" stroke="none"/>\n'
svg+='</a>\n'
/* create a div for popup window */
parsePopup(element)
}
}
}
console.log("-[ Processing ]------------------------------------------------------------------")
console.log("element id :"+element.id)
console.log("element type :"+element.type)
console.log("element name :"+element.name)
console.log("element bounds:"+element.bounds)
console.log("element x,y :"+offx+" "+offy)
console.log("element doc :"+element.documentation)
console.log("---------------------------------------------------------------------------------")
if ($(element).children()) {
$(element).children().each(function(object){
traverseChildren(object,offx,offy)
})
}
}
/* Main */
console.clear()
console.log("export View to Single HTML")
if (!$(selection).is('archimate-diagram-model')) {
window.alert("No view selected")
console.log("Select a single view first")
exit()
}
view=$(selection)[0]
console.log("Using view: "+view.name)
/* Read Templates */
html_template=readFile(__DIR__ + 'templates/'+template_main)
popup_template=readFile(__DIR__ + 'templates/'+template_popup)
/* first, create an invisible opbject in upper left corner */
/* this will prevent cropping by SVG and will determine */
/* x,y offset in coordinates between Archi and SVG */
ref=view.createObject("diagram-model-note",0,0,1,1)
ref.borderType=BORDER.NONE
ref.fillColor="#ff00ff" /* translates to "fuchsia" in svg*/
ref.opacity=0
/* if we can't find reference point, use default 10px */
Xoff=10
Yoff=10
/* create SVG with reference point in it */
svg=$.model.renderViewAsSVGString(view,true)
/* delete reference point in model (is in svg now)*/
ref.delete()
/* find reference point */
refstart=svg.lastIndexOf('<path fill="fuchsia"')
if (refstart>0) {
refline=svg.substring(refstart).split('>')[0]+'>'
/* find beginning of draw command, M="Move" */
startpath=4+refline.indexOf('d="M')
Xoff=Number(refline.substring(startpath).split(" ")[0])
Yoff=Number(refline.substring(startpath).split(" ")[1])
/* remove reference point from svg */
svg=svg.replace(refline,"")
} else {
console.log("Warning, can't find reference point, using default x&y offsets")
/* render again, without reference point */
}
/* chop end svg tag so we can add items to svg element */
start=svg.lastIndexOf('</svg')
svg=svg.substring(0,start)
/* loop through elements, find the ones with a comment and create rectangle for it, */
/* used to denote clicking area */
traverseChildren(view,Xoff,Yoff)
/* chop off xml and DOCTYPE elements, svg will be encapsuled by HTML */
start=svg.indexOf('<svg')
svg=svg.substring(start)
/* add svg tag we removed earlier */
svg+="</svg>\n"
/* combine all the stuff in a single HTML file */
html=html_template
html=html.replace("{{view}}",svg)
html=html.replace("{{popup}}",popup)
html=html.replace("{{name}}",view.name)
/* and save the thing */
filePath=window.promptSaveFile({ title: "Save HTML",fiterExtensions: [ "*.html","*.aspx"]})
if (filePath) {
$.fs.writeFile(filePath,html,"UTF8")
}
console.log("Done")