@@ -5,7 +5,9 @@ package main
5
5
import (
6
6
"encoding/json"
7
7
"errors"
8
+ "io"
8
9
"io/fs"
10
+ "os"
9
11
"strings"
10
12
"syscall/js"
11
13
@@ -133,48 +135,71 @@ type jsParseResponse struct {
133
135
D2Error string `json:"d2Error"`
134
136
}
135
137
136
- type blockFS struct {}
138
+ type emptyFile struct {}
137
139
138
- func (blockFS blockFS ) Open (name string ) (fs.File , error ) {
139
- return nil , errors .New ("import statements not currently implemented" )
140
+ func (f * emptyFile ) Stat () (os.FileInfo , error ) {
141
+ return nil , nil
142
+ }
143
+
144
+ func (f * emptyFile ) Read (p []byte ) (int , error ) {
145
+ return 0 , io .EOF
146
+ }
147
+
148
+ func (f * emptyFile ) Close () error {
149
+ return nil
150
+ }
151
+
152
+ type detectFS struct {
153
+ importUsed bool
154
+ }
155
+
156
+ func (detectFS detectFS ) Open (name string ) (fs.File , error ) {
157
+ detectFS .importUsed = true
158
+ return & emptyFile {}, nil
140
159
}
141
160
142
161
func jsParse (this js.Value , args []js.Value ) interface {} {
143
162
dsl := args [0 ].String ()
144
163
themeID := args [1 ].Int ()
145
164
165
+ detectFS := detectFS {}
166
+
146
167
g , err := d2compiler .Compile ("" , strings .NewReader (dsl ), & d2compiler.CompileOptions {
147
168
UTF16 : true ,
148
- FS : blockFS {} ,
169
+ FS : detectFS ,
149
170
})
150
- var pe * d2parser.ParseError
151
- if err != nil {
152
- if errors .As (err , & pe ) {
153
- serialized , _ := json .Marshal (err )
154
- ret := jsParseResponse {ParseError : string (serialized )}
171
+ // If an import was used, client side D2 cannot reliably compile
172
+ // Defer to backend compilation
173
+ if ! detectFS .importUsed {
174
+ var pe * d2parser.ParseError
175
+ if err != nil {
176
+ if errors .As (err , & pe ) {
177
+ serialized , _ := json .Marshal (err )
178
+ ret := jsParseResponse {ParseError : string (serialized )}
179
+ str , _ := json .Marshal (ret )
180
+ return string (str )
181
+ }
182
+ ret := jsParseResponse {D2Error : err .Error ()}
155
183
str , _ := json .Marshal (ret )
156
184
return string (str )
157
185
}
158
- ret := jsParseResponse {D2Error : err .Error ()}
159
- str , _ := json .Marshal (ret )
160
- return string (str )
161
- }
162
186
163
- for _ , o := range g .Objects {
164
- if (o .Attributes .Top == nil ) != (o .Attributes .Left == nil ) {
165
- ret := jsParseResponse {UserError : `keywords "top" and "left" currently must be used together` }
187
+ for _ , o := range g .Objects {
188
+ if (o .Attributes .Top == nil ) != (o .Attributes .Left == nil ) {
189
+ ret := jsParseResponse {UserError : `keywords "top" and "left" currently must be used together` }
190
+ str , _ := json .Marshal (ret )
191
+ return string (str )
192
+ }
193
+ }
194
+
195
+ err = g .ApplyTheme (int64 (themeID ))
196
+ if err != nil {
197
+ ret := jsParseResponse {D2Error : err .Error ()}
166
198
str , _ := json .Marshal (ret )
167
199
return string (str )
168
200
}
169
201
}
170
202
171
- err = g .ApplyTheme (int64 (themeID ))
172
- if err != nil {
173
- ret := jsParseResponse {D2Error : err .Error ()}
174
- str , _ := json .Marshal (ret )
175
- return string (str )
176
- }
177
-
178
203
m , err := d2parser .Parse ("" , strings .NewReader (dsl ), nil )
179
204
if err != nil {
180
205
return err
0 commit comments