1
1
package com .structurizr .cli .export ;
2
2
3
3
import com .structurizr .Workspace ;
4
+ import com .structurizr .autolayout .graphviz .GraphvizAutomaticLayout ;
4
5
import com .structurizr .cli .AbstractCommand ;
5
- import com .structurizr .dsl . StructurizrDslParser ;
6
+ import com .structurizr .documentation . Documentable ;
6
7
import com .structurizr .export .*;
7
8
import com .structurizr .export .dot .DOTExporter ;
8
9
import com .structurizr .export .ilograph .IlographExporter ;
17
18
import org .apache .commons .logging .Log ;
18
19
import org .apache .commons .logging .LogFactory ;
19
20
20
- import java .io .BufferedWriter ;
21
- import java .io .File ;
22
- import java .net .URL ;
23
- import java .net .URLClassLoader ;
21
+ import java .io .*;
24
22
import java .nio .charset .StandardCharsets ;
25
23
import java .nio .file .Files ;
24
+ import java .util .Base64 ;
26
25
import java .util .Collection ;
27
26
import java .util .HashMap ;
28
27
import java .util .Map ;
28
+ import java .util .zip .ZipEntry ;
29
+ import java .util .zip .ZipInputStream ;
29
30
30
31
public class ExportCommand extends AbstractCommand {
31
32
@@ -41,6 +42,7 @@ public class ExportCommand extends AbstractCommand {
41
42
private static final String DOT_FORMAT = "dot" ;
42
43
private static final String ILOGRAPH_FORMAT = "ilograph" ;
43
44
private static final String D2_FORMAT = "d2" ;
45
+ private static final String STATIC_FORMAT = "static" ;
44
46
private static final String CUSTOM_FORMAT = "fqcn" ;
45
47
46
48
private static final Map <String ,Exporter > EXPORTERS = new HashMap <>();
@@ -112,72 +114,130 @@ public void run(String... args) throws Exception {
112
114
113
115
workspaceId = workspace .getId ();
114
116
115
- if (!JSON_FORMAT .equalsIgnoreCase (format )) {
116
- // only inline the theme amd create default views if the user wants a diagram export
117
- ThemeUtils .loadThemes (workspace );
118
- addDefaultViewsAndStyles (workspace );
119
- }
120
-
121
117
if (outputPath == null ) {
122
118
outputPath = new File (workspacePath .getCanonicalPath ()).getParent ();
123
119
}
124
120
125
121
File outputDir = new File (outputPath );
126
122
outputDir .mkdirs ();
127
123
128
- Exporter exporter = findExporter (format , workspacePath );
129
- if (exporter == null ) {
130
- log .info (" - unknown export format: " + format );
124
+ if (STATIC_FORMAT .equals (format )) {
125
+ log .info (" - writing static site to " + outputDir .getAbsolutePath ());
126
+ unzip (getClass ().getResourceAsStream ("/static.zip" ), outputPath );
127
+
128
+ // add default views if no views exist
129
+ addDefaultViewsAndStyles (workspace );
130
+
131
+ // clear all documentation - this isn't supported by the static site
132
+ workspace .getDocumentation ().clear ();
133
+ workspace .getModel ().getElements ().stream ().filter (e -> e instanceof Documentable ).map (e -> (Documentable )e ).forEach (e -> e .getDocumentation ().clear ());
134
+
135
+ // apply Graphviz locally - the static site can't do this
136
+ File tmpdir = Files .createTempDirectory ("graphviz" ).toFile ();
137
+ tmpdir .deleteOnExit ();
138
+ log .debug ("Graphviz working directory is " + tmpdir .getAbsolutePath ());
139
+ new GraphvizAutomaticLayout (tmpdir ).apply (workspace );
140
+
141
+ String json = WorkspaceUtils .toJson (workspace , false );
142
+ String base64 = Base64 .getEncoder ().encodeToString (json .getBytes (StandardCharsets .UTF_8 ));
143
+
144
+ writeToFile (
145
+ new File (outputDir , "workspace.js" ),
146
+ String .format ("const jsonAsString = '%s';" , base64 )
147
+ );
148
+
131
149
} else {
132
- log .info (" - exporting with " + exporter .getClass ().getSimpleName ());
150
+ if (!JSON_FORMAT .equalsIgnoreCase (format )) {
151
+ // only inline the theme amd create default views if the user wants a diagram export
152
+ ThemeUtils .loadThemes (workspace );
153
+ addDefaultViewsAndStyles (workspace );
154
+ }
133
155
134
- if (exporter instanceof DiagramExporter ) {
135
- DiagramExporter diagramExporter = (DiagramExporter ) exporter ;
156
+ Exporter exporter = findExporter (format , workspacePath );
157
+ if (exporter == null ) {
158
+ log .info (" - unknown export format: " + format );
159
+ } else {
160
+ log .info (" - exporting with " + exporter .getClass ().getSimpleName ());
136
161
137
- if (workspace .getViews ().isEmpty ()) {
138
- log .info (" - the workspace contains no views" );
139
- } else {
140
- Collection <Diagram > diagrams = diagramExporter .export (workspace );
162
+ if (exporter instanceof DiagramExporter ) {
163
+ DiagramExporter diagramExporter = (DiagramExporter ) exporter ;
141
164
142
- for (Diagram diagram : diagrams ) {
143
- File file = new File (outputPath , String .format ("%s-%s.%s" , prefix (workspaceId ), diagram .getKey (), diagram .getFileExtension ()));
144
- writeToFile (file , diagram .getDefinition ());
165
+ if (workspace .getViews ().isEmpty ()) {
166
+ log .info (" - the workspace contains no views" );
167
+ } else {
168
+ Collection <Diagram > diagrams = diagramExporter .export (workspace );
145
169
146
- if (diagram .getLegend () != null ) {
147
- file = new File (outputPath , String .format ("%s-%s-key.%s" , prefix (workspaceId ), diagram .getKey (), diagram .getFileExtension ()));
148
- writeToFile (file , diagram .getLegend ().getDefinition ());
149
- }
170
+ for (Diagram diagram : diagrams ) {
171
+ File file = new File (outputPath , String .format ("%s-%s.%s" , prefix (workspaceId ), diagram .getKey (), diagram .getFileExtension ()));
172
+ writeToFile (file , diagram .getDefinition ());
173
+
174
+ if (diagram .getLegend () != null ) {
175
+ file = new File (outputPath , String .format ("%s-%s-key.%s" , prefix (workspaceId ), diagram .getKey (), diagram .getFileExtension ()));
176
+ writeToFile (file , diagram .getLegend ().getDefinition ());
177
+ }
150
178
151
- if (!diagram .getFrames ().isEmpty ()) {
152
- int index = 1 ;
153
- for (Diagram frame : diagram .getFrames ()) {
154
- file = new File (outputPath , String .format ("%s-%s-%s.%s" , prefix (workspaceId ), diagram .getKey (), index , diagram .getFileExtension ()));
155
- writeToFile (file , frame .getDefinition ());
156
- index ++;
179
+ if (!diagram .getFrames ().isEmpty ()) {
180
+ int index = 1 ;
181
+ for (Diagram frame : diagram .getFrames ()) {
182
+ file = new File (outputPath , String .format ("%s-%s-%s.%s" , prefix (workspaceId ), diagram .getKey (), index , diagram .getFileExtension ()));
183
+ writeToFile (file , frame .getDefinition ());
184
+ index ++;
185
+ }
157
186
}
158
187
}
159
188
}
160
- }
161
- } else if (exporter instanceof WorkspaceExporter ) {
162
- WorkspaceExporter workspaceExporter = (WorkspaceExporter ) exporter ;
163
- WorkspaceExport export = workspaceExporter .export (workspace );
189
+ } else if (exporter instanceof WorkspaceExporter ) {
190
+ WorkspaceExporter workspaceExporter = (WorkspaceExporter ) exporter ;
191
+ WorkspaceExport export = workspaceExporter .export (workspace );
164
192
165
- String filename ;
193
+ String filename ;
166
194
167
- if (THEME_FORMAT .equalsIgnoreCase (format )) {
168
- filename = workspacePath .getName ().substring (0 , workspacePath .getName ().lastIndexOf ('.' )) + "-theme" ;
169
- } else {
170
- filename = workspacePath .getName ().substring (0 , workspacePath .getName ().lastIndexOf ('.' ));
171
- }
195
+ if (THEME_FORMAT .equalsIgnoreCase (format )) {
196
+ filename = workspacePath .getName ().substring (0 , workspacePath .getName ().lastIndexOf ('.' )) + "-theme" ;
197
+ } else {
198
+ filename = workspacePath .getName ().substring (0 , workspacePath .getName ().lastIndexOf ('.' ));
199
+ }
172
200
173
- File file = new File (outputPath , String .format ("%s.%s" , filename , export .getFileExtension ()));
174
- writeToFile (file , export .getDefinition ());
201
+ File file = new File (outputPath , String .format ("%s.%s" , filename , export .getFileExtension ()));
202
+ writeToFile (file , export .getDefinition ());
203
+ }
175
204
}
176
205
}
177
206
178
207
log .info (" - finished" );
179
208
}
180
209
210
+ private void unzip (InputStream inputStream , String destinationDirectory ) {
211
+ byte [] buffer = new byte [1024 ];
212
+
213
+ try {
214
+ ZipInputStream zis = new ZipInputStream (inputStream );
215
+ ZipEntry ze = zis .getNextEntry ();
216
+ while (ze != null ) {
217
+ if (!ze .isDirectory ()) {
218
+ String fileName = ze .getName ();
219
+ File destinationFile = new File (destinationDirectory + File .separator + fileName );
220
+
221
+ new File (destinationFile .getParent ()).mkdirs ();
222
+ FileOutputStream fos = new FileOutputStream (destinationFile );
223
+ int len ;
224
+ while ((len = zis .read (buffer )) > 0 ) {
225
+ fos .write (buffer , 0 , len );
226
+ }
227
+ fos .close ();
228
+ }
229
+ zis .closeEntry ();
230
+ ze = zis .getNextEntry ();
231
+ }
232
+
233
+ zis .closeEntry ();
234
+ zis .close ();
235
+ inputStream .close ();
236
+ } catch (IOException e ) {
237
+ e .printStackTrace ();
238
+ }
239
+ }
240
+
181
241
private Exporter findExporter (String format , File workspacePath ) {
182
242
if (EXPORTERS .containsKey (format .toLowerCase ())) {
183
243
return EXPORTERS .get (format .toLowerCase ());
@@ -214,4 +274,4 @@ private void writeToFile(File file, String content) throws Exception {
214
274
writer .close ();
215
275
}
216
276
217
- }
277
+ }
0 commit comments