├── .github └── FUNDING.yml ├── .gitignore ├── .startproject ├── LICENSE ├── README.md ├── app.go ├── build ├── README.md ├── appicon.png ├── darwin │ ├── Info.dev.plist │ └── Info.plist └── windows │ ├── icon.ico │ ├── info.json │ ├── installer │ └── project.nsi │ └── wails.exe.manifest ├── frontend ├── README.md ├── config.codekit3 ├── dist │ └── index.html ├── index.html ├── jsconfig.json ├── package-lock.json ├── package.json ├── package.json.md5 ├── src │ ├── Main.svelte │ ├── components │ │ ├── AddComponent.svelte │ │ ├── BirthdayCounter.svelte │ │ ├── BirthdayCounterConfig.svelte │ │ ├── EditComponent.svelte │ │ ├── EditSpanField.svelte │ │ ├── FlowVariable.svelte │ │ ├── FlowVariableConfig.svelte │ │ ├── IPAddress.svelte │ │ ├── IPAddressConfig.svelte │ │ ├── Script.svelte │ │ ├── ScriptBar.svelte │ │ ├── ScriptConfig.svelte │ │ ├── Separator.svelte │ │ ├── SeparatorConfig.svelte │ │ ├── ViewComponent.svelte │ │ ├── WebLink.svelte │ │ ├── WebLinkConfig.svelte │ │ └── WebView.svelte │ ├── main.js │ ├── stores │ │ ├── config.js │ │ ├── headerPosition.js │ │ ├── preferences.js │ │ ├── resizeWindow.js │ │ ├── styles.js │ │ ├── timer.js │ │ ├── variables.js │ │ └── width.js │ ├── style.css │ └── vite-env.d.ts ├── vite.config.js └── wailsjs │ ├── go │ └── main │ │ ├── App.d.ts │ │ └── App.js │ └── runtime │ ├── package.json │ ├── runtime.d.ts │ └── runtime.js ├── go.mod ├── go.sum ├── main.go ├── maskfile.md ├── server.go └── wails.json /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [raguay] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry 13 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Wails bin directory 2 | build/bin 3 | # Wails Windows NSIS support files 4 | build/windows/installer/wails_tools.nsh 5 | build/windows/installer/tmp/ 6 | ExternalScriptTest 7 | 8 | frontend/dist 9 | # IDEs 10 | .idea 11 | .vscode 12 | 13 | # The black hole that is... 14 | node_modules 15 | package-lock.json 16 | -------------------------------------------------------------------------------- /.startproject: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raguay/ScriptBarApp/fb283cd80a97714f89e912f77b84bb603d201075/.startproject -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Richard Guay 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![ScriptBarApp](https://socialify.git.ci/raguay/scriptbarapp/image?description=1&font=Raleway&forks=1&issues=1&language=1&owner=1&pattern=Circuit%20Board&pulls=1&stargazers=1&theme=Dark) 2 | 3 | [![Richard's GitHub stats](https://github-readme-stats.vercel.app/api?username=raguay)](https://github.com/anuraghazra/github-readme-stats) 4 | 5 | # Script Bar 6 | 7 | ![Script Bar](https://github.com/raguay/ScriptBarApp/blob/main/img/ScriptBar.jpg?raw=truehttps) 8 | 9 | An application to show results from scripts and Node-Red in the menubar. It is currently in the Alpha stage, but very usable. You can display results from the Node-Red server in [EmailIt Server](https://github.com/raguay/EmailItServer), command line scripts for either [TextBar](http://richsomerfield.com/apps/textbar/) (mostly working), [xBar](https://github.com/matryer/xbar) (not working - still in development), or some of the builtin components include web sites and IP addresses both local and external. You have to have the [EmailIt Server](https://github.com/raguay/EmailItServer) running to use this program. Currently, EmailItServer is now apart of [EmailIt](https://GitHub.com/raguay/EmailIt). 10 | 11 | The program is built with a [Svelte](https://svelte.dev/) JavaScript frontend and [Wails](https://wails.app/) backend and packager. The goal is to make this project usable on Windows, macOS, and Linux. I'm currently developing it on macOS and will be working of the other versions after the macOS is stable and Wails version 2 is ready for that platform. 12 | 13 | ## Note: 14 | 15 | This program isn't a replacement for xBar. xBar puts script outputs into individual menubar items. ScriptBar places all script output into a single interface for easy viewing when activated. I have a very cluttered menubar with many application that I use. So, I wanted some scripts to show in it's own menubar using xBar, and some grouped together in a single interface for convience. Pick the program that best suites your needs or use both like I do! This program also get output from a Node-Red server in the EmailIt Server program. 16 | 17 | ## Building 18 | 19 | To build the application, first go to the `frontend` directory and build it using: 20 | 21 | ```sh 22 | npm install 23 | npm run build 24 | ``` 25 | The first line installs the libraries used to build the application. The second line compiles the Svelte front end. Next, you need to build the Wails app. First, install Wails by installing the prerequisites mentioned on their webiste and then run: 26 | 27 | ```sh 28 | go get -u github.com/wailsapp/wails/cmd/wails 29 | ``` 30 | 31 | Then build the application or your platform with: 32 | 33 | ```sh 34 | wails build 35 | ``` 36 | 37 | or, to build a macOS universal program, use this command line: 38 | 39 | ```sh 40 | wails build --platform "darwin/universal" 41 | ``` 42 | 43 | To run the program, simply run the executable in the `build/bin` directory: 44 | 45 | ```sh 46 | open ./build/bin/ScriptBar.app 47 | ``` 48 | 49 | You must have the [EmailIt Server](https://github.com/raguay/EmailItServer) running first. Currently, EmailItServer is embedded inside of [EmailIt](https://GitHub.com/raguay/EmailIt). 50 | 51 | ## Documentation 52 | 53 | The ScriptBar application is launched along with EmailIt. It relies upon the EmailIt Server for all of it's information. Just like EmailIt, it is a Wails application using Svelte for the frontend framework. 54 | 55 | ![ScriptBar Application](/img/ScriptBar.png) 56 | 57 | This shows my ScriptBar. The `+` in the upper left corner allows you to add new items to each tab. The tab with a `+` in it allows you to add a new tab. By double clicking the tab names, you can change text shown for each tab. You can have as many tabs as you want and as many items in each tab as you want. But, if you get too many, it will go past your screen edges! You can click and drag the top area to move the application around. 58 | 59 | ![Double Click Entry](/img/doubleclickentry.png) 60 | 61 | If you double click on the name of an entry, you can click `Up` to move it up the list or `Down` to move it down the list. By double clicking the entry name, you can edit it's parameters. 62 | 63 | There are seven types of entries that you can use. They are described below: 64 | 65 | #### Birthday Counter 66 | 67 | ![Birthday Counter](/img/birthdaycounter.png) 68 | 69 | The birthday counter takes the output of a birthday counter flow in Node-Red. It will show the time to the person's next birthday and their current age. The script for the birthday node in Node-Red is: 70 | 71 | ```javascript 72 | // 73 | // Get the current date and the count down 74 | // date. 75 | // 76 | var now = new Date(); 77 | 78 | 79 | var dmon = msg.payload.month - 1; 80 | var dday = msg.payload.day; 81 | var dyear = msg.payload.year; 82 | var bd = new Date(); 83 | bd.setFullYear(now.getFullYear()); 84 | bd.setMonth(dmon); 85 | bd.setDate(dday); 86 | 87 | // 88 | // Calculate the number of milliseconds until 89 | // the date. 90 | // 91 | var diff = 0; 92 | if(now.getMonth() <= dmon) { 93 | diff = bd.getTime() - now.getTime(); 94 | if((now.getMonth() === dmon)&&(now.getDate() > dday)) { 95 | diff = 0; 96 | } 97 | } 98 | 99 | if(diff === 0) { 100 | var yearEnd = new Date(); 101 | yearEnd.setMonth(11); 102 | yearEnd.setDate(31); 103 | diff = yearEnd.getTime() - now.getTime(); 104 | bd.setFullYear(now.getFullYear()+1); 105 | diff += bd.getTime() - yearEnd.getTime(); 106 | } 107 | 108 | // 109 | // Convert the difference to months, weeks, days. 110 | // 111 | ddays = Math.floor(diff / (1000*60*60*24)); 112 | dweeks = Math.floor(ddays / 7); 113 | ddays -= dweeks * 7; 114 | 115 | // 116 | // Create the answer and send it on. 117 | // 118 | var result = dweeks.toString() + ' weeks, ' + ddays.toString() + ' days'; 119 | var ans = { 120 | payload: result, 121 | topic: 'days' 122 | } 123 | return ans; 124 | ``` 125 | 126 | You put this code into a function node. Then create another function node with this code to calculate the current age: 127 | 128 | ```javascript 129 | // 130 | // Get the current date and the count down 131 | // date. 132 | // 133 | var now = new Date(); 134 | 135 | var dmon = msg.payload.month - 1; 136 | var dday = msg.payload.day; 137 | var dyear = msg.payload.year; 138 | 139 | // 140 | // Create the answer and send it on. 141 | // 142 | var result = now.getFullYear() - dyear; 143 | var ans = { 144 | payload: result, 145 | topic: 'age' 146 | } 147 | return ans; 148 | ``` 149 | 150 | You feed these two function nodes with an inject node with a payload like this: 151 | 152 | ```json 153 | {"year":1969,"month":8,"day":1} 154 | ``` 155 | 156 | You need to change the `year`, `month`, and `day` fields to match the person's birthday. Then add a join node with these properties: 157 | 158 | ![Join Node for Birthday Counter](/img/joinnode.png) 159 | 160 | The last node is a `SPVariables` node set to the name of the Node-Red variable you want to use. The full flow looks like this: 161 | 162 | ![Birthday Counter Flow](/img/birthdayflow.png) 163 | 164 | #### Flow Variable 165 | 166 | ![Flow Variable](/img/flowvariable.png) 167 | 168 | The flowvariable entry takes the text in a Node-Red flow variable and simply displays it. 169 | 170 | #### Internal IP Address 171 | 172 | ![Internal IP Address](/img/intipaddress.png) 173 | 174 | The Internal IP Address entry will display the internal IP address of your computer. That is the IP of your local network, not the IP used on the Internet. If you give a port number and check the link checkbox, you can click the IP address shown in ScriptBar and it will open a webpage to that address and port number. This entry type uses an API from the EmailItServer. 175 | 176 | #### External IP Address 177 | 178 | ![External IP Address](/img/ipaddress.png) 179 | 180 | The External IP Address is the same as the Internal IP address except that it takes a Node-Red flow variable name. You have to create a flow that fills in the external IP address of your system. There are several nodes that can supply that information, so I leave up to you. The one I use is an HTTP request node with the url set to `https://api.ipify.org?format=json`. 181 | 182 | #### Script 183 | 184 | ![Script](/img/script.png) 185 | 186 | The Script entry allows you to call an External Script from EmailIt and display it's output. The output types can be: Generic, TextBar, BitBar (which is now xBar), and HTML. The Generic setting just displays the output as plain text. The TextBar setting processes the output as a TextBar script. The BitBar setting processes the output as a BitBar script (not currently working), and the HTML setting displays the output as HTML. The `What is the command line?` isn't currently used. I plan to have it just run the command line and display the results. 187 | 188 | ![Output of a Script](/img/scriptoutput.png) 189 | 190 | The picture above shows an TextBar script output called TaskPaperTodo.rb. This is a ruby script that displays the tasks I have in the TaskPaper program. 191 | 192 | #### Separator 193 | 194 | ![Separator](/img/separator.png) 195 | 196 | This is a simple line separator to separate entry types. 197 | 198 | #### Web Link 199 | 200 | ![Web Link](/img/weblink.png) 201 | 202 | The Web Link entry type allows you to give a website address. By clicking on the glob on the ScriptBar program, it will open that web link in the default browser. I use this type a whole lot to keep up with websites that I go to often. 203 | 204 | -------------------------------------------------------------------------------- /app.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bytes" 5 | "context" 6 | "errors" 7 | "fmt" 8 | "io" 9 | "io/ioutil" 10 | "net/http" 11 | "os" 12 | "os/exec" 13 | "path/filepath" 14 | goruntime "runtime" 15 | "strings" 16 | "time" 17 | 18 | clip "github.com/atotto/clipboard" 19 | cp "github.com/otiai10/copy" 20 | rt "github.com/wailsapp/wails/v2/pkg/runtime" 21 | ) 22 | 23 | // App struct 24 | type App struct { 25 | ctx context.Context 26 | err string 27 | } 28 | 29 | // NewApp creates a new App application struct 30 | func NewApp() *App { 31 | return &App{} 32 | } 33 | 34 | // startup is called at application startup 35 | func (a *App) startup(ctx context.Context) { 36 | // Perform your setup here 37 | a.ctx = ctx 38 | } 39 | 40 | // domReady is called after front-end resources have been loaded 41 | func (a App) domReady(ctx context.Context) { 42 | // 43 | // Run the server for getting variable information. 44 | // 45 | go RunServer(&a, ctx) 46 | } 47 | 48 | // beforeClose is called when the application is about to quit, 49 | // either by clicking the window close button or calling runtime.Quit. 50 | // Returning true will cause the application to continue, false will continue shutdown as normal. 51 | func (a *App) beforeClose(ctx context.Context) (prevent bool) { 52 | return false 53 | } 54 | 55 | // shutdown is called at application termination 56 | func (a *App) shutdown(ctx context.Context) { 57 | // Perform your teardown here 58 | } 59 | 60 | func (a *App) Quit() { 61 | rt.Quit(a.ctx) 62 | } 63 | 64 | type FileParts struct { 65 | Dir string 66 | Name string 67 | Extension string 68 | } 69 | 70 | type FileInfo struct { 71 | Dir string 72 | Name string 73 | Extension string 74 | IsDir bool 75 | Size int64 76 | Modtime string 77 | } 78 | 79 | type Environment struct { 80 | Name string `json:"name" binding:"required"` 81 | EnvVar []string `json:"envVar" binding:"required"` 82 | } 83 | 84 | type ServerResponce struct { 85 | Error string `json:"error"` 86 | Result string `json:"result"` 87 | } 88 | 89 | func (a *App) SendHTTPQuery(method string, uri string, body string) string { 90 | var result string 91 | switch strings.Trim(method, " ") { 92 | case "GET": 93 | { 94 | resp, err := http.Get(uri) 95 | if err != nil { 96 | print(err) 97 | } 98 | defer resp.Body.Close() 99 | body, err := ioutil.ReadAll(resp.Body) 100 | if err != nil { 101 | print(err) 102 | } 103 | result = string(body) 104 | } 105 | 106 | case "POST": 107 | { 108 | resp, err := http.Post(uri, "application/json", bytes.NewBuffer([]byte(body+"\n"))) 109 | if err != nil { 110 | print(err) 111 | } 112 | defer resp.Body.Close() 113 | repBody, errdec := ioutil.ReadAll(resp.Body) 114 | if errdec != nil { 115 | print(errdec) 116 | } 117 | result = string(repBody) 118 | } 119 | case "PUT": 120 | { 121 | client := http.Client{} 122 | 123 | // regardless of GET or POST, we can safely add the body 124 | req, err := http.NewRequest("PUT", uri, bytes.NewBuffer([]byte(body+"\n"))) 125 | if err != nil { 126 | return err.Error() 127 | } 128 | headers := map[string]string{} 129 | headers["Method"] = "PUT" 130 | headers["Content-Type"] = "application/json" 131 | 132 | // for each header passed, add the header value to the request 133 | for k, v := range headers { 134 | req.Header.Set(k, v) 135 | } 136 | 137 | // finally, do the request 138 | res, err := client.Do(req) 139 | if err != nil { 140 | return err.Error() 141 | } 142 | 143 | if res == nil { 144 | return fmt.Sprint("error: calling %s returned empty response", uri) 145 | } 146 | 147 | responseData, err := io.ReadAll(res.Body) 148 | if err != nil { 149 | return err.Error() 150 | } 151 | 152 | defer res.Body.Close() 153 | 154 | if res.StatusCode != http.StatusOK { 155 | return fmt.Sprintf("error calling %s:\nstatus: %s\nresponseData: %s", uri, res.Status, responseData) 156 | } 157 | 158 | result = string(responseData) 159 | } 160 | } 161 | return result 162 | } 163 | 164 | func (a *App) SystemOpenFile(prog string) { 165 | if a.FileExists(prog) { 166 | var ArgsArray [2]string 167 | var sar []string 168 | ArgsArray[1] = prog 169 | a.RunCommandLine("/usr/bin/open", ArgsArray[:], sar, "") 170 | } 171 | } 172 | 173 | func (a *App) GetExecutable() string { 174 | ex, err := os.Executable() 175 | if err != nil { 176 | a.err = err.Error() 177 | } 178 | return ex 179 | } 180 | 181 | func (a *App) Getwd() string { 182 | wd, err := os.Getwd() 183 | if err != nil { 184 | a.err = err.Error() 185 | } 186 | return wd 187 | } 188 | 189 | func (a *App) ReadFile(path string) string { 190 | a.err = "" 191 | contents, err := os.ReadFile(path) 192 | if err != nil { 193 | a.err = err.Error() 194 | } 195 | return string(contents[:]) 196 | } 197 | 198 | func (a *App) GetHomeDir() string { 199 | a.err = "" 200 | hdir, err := os.UserHomeDir() 201 | if err != nil { 202 | a.err = err.Error() 203 | } 204 | return hdir 205 | } 206 | 207 | func (a *App) WriteFile(path string, data string) { 208 | err := os.WriteFile(path, []byte(data), 0666) 209 | if err != nil { 210 | a.err = err.Error() 211 | } 212 | } 213 | 214 | func (a *App) FileExists(path string) bool { 215 | a.err = "" 216 | _, err := os.Stat(path) 217 | return !errors.Is(err, os.ErrNotExist) 218 | } 219 | 220 | func (a *App) DirExists(path string) bool { 221 | a.err = "" 222 | dstat, err := os.Stat(path) 223 | if err != nil { 224 | a.err = err.Error() 225 | return false 226 | } 227 | return dstat.IsDir() 228 | } 229 | 230 | func (a *App) SplitFile(path string) FileParts { 231 | a.err = "" 232 | var parts FileParts 233 | parts.Dir, parts.Name = filepath.Split(path) 234 | parts.Extension = filepath.Ext(path) 235 | return parts 236 | } 237 | 238 | func (a *App) ReadDir(path string) []FileInfo { 239 | a.err = "" 240 | var result []FileInfo 241 | result = make([]FileInfo, 0, 0) 242 | files, err := ioutil.ReadDir(path) 243 | if err != nil { 244 | a.err = err.Error() 245 | } else { 246 | for _, file := range files { 247 | var fileInfo FileInfo 248 | fileInfo.Name = file.Name() 249 | fileInfo.Size = file.Size() 250 | fileInfo.IsDir = file.IsDir() 251 | fileInfo.Modtime = file.ModTime().Format(time.ANSIC) 252 | fileInfo.Dir = path 253 | fileInfo.Extension = filepath.Ext(file.Name()) 254 | result = append(result, fileInfo) 255 | } 256 | } 257 | return result 258 | } 259 | 260 | func (a *App) MakeDir(path string) { 261 | a.err = "" 262 | err := os.MkdirAll(path, 0755) 263 | if err != nil { 264 | a.err = err.Error() 265 | } 266 | } 267 | 268 | func (a *App) MakeFile(path string) { 269 | a.err = "" 270 | a.WriteFile(path, "") 271 | } 272 | 273 | func (a *App) MoveEntries(from string, to string) { 274 | a.err = "" 275 | err := os.Rename(from, to) 276 | if err != nil { 277 | a.err = err.Error() 278 | } 279 | } 280 | 281 | func (a *App) RenameEntry(from string, to string) { 282 | a.err = "" 283 | err := os.Rename(from, to) 284 | if err != nil { 285 | a.err = err.Error() 286 | } 287 | } 288 | 289 | func (a *App) GetError() string { 290 | return a.err 291 | } 292 | 293 | func (a *App) CopyEntries(from string, to string) { 294 | a.err = "" 295 | info, err := os.Stat(from) 296 | if os.IsNotExist(err) { 297 | a.err = err.Error() 298 | return 299 | } 300 | if info.IsDir() { 301 | // 302 | // It's a directory! Do a deap copy. 303 | // 304 | err := cp.Copy(from, to) 305 | if err != nil { 306 | a.err = err.Error() 307 | return 308 | } 309 | } else { 310 | // 311 | // It's a file. Just copy it. 312 | // 313 | source, err := os.Open(from) 314 | if err != nil { 315 | a.err = err.Error() 316 | return 317 | } 318 | defer source.Close() 319 | 320 | destination, err := os.Create(to) 321 | if err != nil { 322 | a.err = err.Error() 323 | return 324 | } 325 | defer destination.Close() 326 | _, err = io.Copy(destination, source) 327 | 328 | if err != nil { 329 | a.err = err.Error() 330 | } 331 | } 332 | } 333 | 334 | func (a *App) DeleteEntries(path string) { 335 | a.err = "" 336 | err := os.RemoveAll(path) 337 | if err != nil { 338 | a.err = err.Error() 339 | } 340 | } 341 | 342 | func (a *App) RunCommandLine(cmd string, args []string, env []string, dir string) string { 343 | a.err = "" 344 | cmdline := exec.Command(cmd) 345 | cmdline.Args = args 346 | cmdline.Env = env 347 | cmdline.Dir = dir 348 | result, err := cmdline.CombinedOutput() 349 | if err != nil { 350 | a.err = err.Error() 351 | } 352 | 353 | return string(result[:]) 354 | } 355 | 356 | func (a *App) GetClip() string { 357 | result, err := clip.ReadAll() 358 | if err != nil { 359 | a.err = err.Error() 360 | } 361 | return result 362 | } 363 | 364 | func (a *App) SetClip(msg string) { 365 | err := clip.WriteAll(msg) 366 | if err != nil { 367 | a.err = err.Error() 368 | } 369 | } 370 | 371 | func (a *App) GetEnvironment() []string { 372 | return os.Environ() 373 | } 374 | 375 | func (a *App) GetEnv(name string) string { 376 | return os.Getenv(name) 377 | } 378 | 379 | func (a *App) AppendPath(dir string, name string) string { 380 | return filepath.Join(dir, name) 381 | } 382 | 383 | func (a *App) GetOSName() string { 384 | os := goruntime.GOOS 385 | result := "" 386 | switch os { 387 | case "windows": 388 | result = "windows" 389 | break 390 | case "darwin": 391 | result = "macos" 392 | case "linux": 393 | result = "linux" 394 | default: 395 | result = fmt.Sprintf("%s", os) 396 | } 397 | return result 398 | } 399 | -------------------------------------------------------------------------------- /build/README.md: -------------------------------------------------------------------------------- 1 | # Build Directory 2 | 3 | The build directory is used to house all the build files and assets for your application. 4 | 5 | The structure is: 6 | 7 | * bin - Output directory 8 | * darwin - macOS specific files 9 | * windows - Windows specific files 10 | 11 | ## Mac 12 | 13 | The `darwin` directory holds files specific to Mac builds. 14 | These may be customised and used as part of the build. To return these files to the default state, simply delete them 15 | and 16 | build with `wails build`. 17 | 18 | The directory contains the following files: 19 | 20 | - `Info.plist` - the main plist file used for Mac builds. It is used when building using `wails build`. 21 | - `Info.dev.plist` - same as the main plist file but used when building using `wails dev`. 22 | 23 | ## Windows 24 | 25 | The `windows` directory contains the manifest and rc files used when building with `wails build`. 26 | These may be customised for your application. To return these files to the default state, simply delete them and 27 | build with `wails build`. 28 | 29 | - `icon.ico` - The icon used for the application. This is used when building using `wails build`. If you wish to 30 | use a different icon, simply replace this file with your own. If it is missing, a new `icon.ico` file 31 | will be created using the `appicon.png` file in the build directory. 32 | - `installer/*` - The files used to create the Windows installer. These are used when building using `wails build`. 33 | - `info.json` - Application details used for Windows builds. The data here will be used by the Windows installer, 34 | as well as the application itself (right click the exe -> properties -> details) 35 | - `wails.exe.manifest` - The main application manifest file. -------------------------------------------------------------------------------- /build/appicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raguay/ScriptBarApp/fb283cd80a97714f89e912f77b84bb603d201075/build/appicon.png -------------------------------------------------------------------------------- /build/darwin/Info.dev.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CFBundlePackageType 5 | APPL 6 | CFBundleName 7 | {{.Info.ProductName}} 8 | CFBundleExecutable 9 | {{.Name}} 10 | CFBundleIdentifier 11 | com.wails.{{.Name}} 12 | CFBundleVersion 13 | {{.Info.ProductVersion}} 14 | CFBundleGetInfoString 15 | {{.Info.Comments}} 16 | CFBundleShortVersionString 17 | {{.Info.ProductVersion}} 18 | CFBundleIconFile 19 | iconfile 20 | LSMinimumSystemVersion 21 | 10.13.0 22 | NSHighResolutionCapable 23 | true 24 | NSHumanReadableCopyright 25 | {{.Info.Copyright}} 26 | NSAppTransportSecurity 27 | 28 | NSAllowsLocalNetworking 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /build/darwin/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CFBundlePackageType 5 | APPL 6 | CFBundleName 7 | {{.Info.ProductName}} 8 | CFBundleExecutable 9 | {{.Name}} 10 | CFBundleIdentifier 11 | com.wails.{{.Name}} 12 | CFBundleVersion 13 | {{.Info.ProductVersion}} 14 | CFBundleGetInfoString 15 | {{.Info.Comments}} 16 | CFBundleShortVersionString 17 | {{.Info.ProductVersion}} 18 | CFBundleIconFile 19 | iconfile 20 | LSMinimumSystemVersion 21 | 10.13.0 22 | NSHighResolutionCapable 23 | true 24 | NSHumanReadableCopyright 25 | {{.Info.Copyright}} 26 | 27 | -------------------------------------------------------------------------------- /build/windows/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raguay/ScriptBarApp/fb283cd80a97714f89e912f77b84bb603d201075/build/windows/icon.ico -------------------------------------------------------------------------------- /build/windows/info.json: -------------------------------------------------------------------------------- 1 | { 2 | "fixed": { 3 | "file_version": "{{.Info.ProductVersion}}" 4 | }, 5 | "info": { 6 | "0000": { 7 | "ProductVersion": "{{.Info.ProductVersion}}", 8 | "CompanyName": "{{.Info.CompanyName}}", 9 | "FileDescription": "{{.Info.ProductName}}", 10 | "LegalCopyright": "{{.Info.Copyright}}", 11 | "ProductName": "{{.Info.ProductName}}", 12 | "Comments": "{{.Info.Comments}}" 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /build/windows/installer/project.nsi: -------------------------------------------------------------------------------- 1 | Unicode true 2 | 3 | #### 4 | ## Please note: Template replacements don't work in this file. They are provided with default defines like 5 | ## mentioned underneath. 6 | ## If the keyword is not defined, "wails_tools.nsh" will populate them with the values from ProjectInfo. 7 | ## If they are defined here, "wails_tools.nsh" will not touch them. This allows to use this project.nsi manually 8 | ## from outside of Wails for debugging and development of the installer. 9 | ## 10 | ## For development first make a wails nsis build to populate the "wails_tools.nsh": 11 | ## > wails build --target windows/amd64 --nsis 12 | ## Then you can call makensis on this file with specifying the path to your binary: 13 | ## For a AMD64 only installer: 14 | ## > makensis -DARG_WAILS_AMD64_BINARY=..\..\bin\app.exe 15 | ## For a ARM64 only installer: 16 | ## > makensis -DARG_WAILS_ARM64_BINARY=..\..\bin\app.exe 17 | ## For a installer with both architectures: 18 | ## > makensis -DARG_WAILS_AMD64_BINARY=..\..\bin\app-amd64.exe -DARG_WAILS_ARM64_BINARY=..\..\bin\app-arm64.exe 19 | #### 20 | ## The following information is taken from the ProjectInfo file, but they can be overwritten here. 21 | #### 22 | ## !define INFO_PROJECTNAME "MyProject" # Default "{{.Name}}" 23 | ## !define INFO_COMPANYNAME "MyCompany" # Default "{{.Info.CompanyName}}" 24 | ## !define INFO_PRODUCTNAME "MyProduct" # Default "{{.Info.ProductName}}" 25 | ## !define INFO_PRODUCTVERSION "1.0.0" # Default "{{.Info.ProductVersion}}" 26 | ## !define INFO_COPYRIGHT "Copyright" # Default "{{.Info.Copyright}}" 27 | ### 28 | ## !define PRODUCT_EXECUTABLE "Application.exe" # Default "${INFO_PROJECTNAME}.exe" 29 | ## !define UNINST_KEY_NAME "UninstKeyInRegistry" # Default "${INFO_COMPANYNAME}${INFO_PRODUCTNAME}" 30 | #### 31 | ## !define REQUEST_EXECUTION_LEVEL "admin" # Default "admin" see also https://nsis.sourceforge.io/Docs/Chapter4.html 32 | #### 33 | ## Include the wails tools 34 | #### 35 | !include "wails_tools.nsh" 36 | 37 | # The version information for this two must consist of 4 parts 38 | VIProductVersion "${INFO_PRODUCTVERSION}.0" 39 | VIFileVersion "${INFO_PRODUCTVERSION}.0" 40 | 41 | VIAddVersionKey "CompanyName" "${INFO_COMPANYNAME}" 42 | VIAddVersionKey "FileDescription" "${INFO_PRODUCTNAME} Installer" 43 | VIAddVersionKey "ProductVersion" "${INFO_PRODUCTVERSION}" 44 | VIAddVersionKey "FileVersion" "${INFO_PRODUCTVERSION}" 45 | VIAddVersionKey "LegalCopyright" "${INFO_COPYRIGHT}" 46 | VIAddVersionKey "ProductName" "${INFO_PRODUCTNAME}" 47 | 48 | !include "MUI.nsh" 49 | 50 | !define MUI_ICON "..\icon.ico" 51 | !define MUI_UNICON "..\icon.ico" 52 | # !define MUI_WELCOMEFINISHPAGE_BITMAP "resources\leftimage.bmp" #Include this to add a bitmap on the left side of the Welcome Page. Must be a size of 164x314 53 | !define MUI_FINISHPAGE_NOAUTOCLOSE # Wait on the INSTFILES page so the user can take a look into the details of the installation steps 54 | !define MUI_ABORTWARNING # This will warn the user if they exit from the installer. 55 | 56 | !insertmacro MUI_PAGE_WELCOME # Welcome to the installer page. 57 | # !insertmacro MUI_PAGE_LICENSE "resources\eula.txt" # Adds a EULA page to the installer 58 | !insertmacro MUI_PAGE_DIRECTORY # In which folder install page. 59 | !insertmacro MUI_PAGE_INSTFILES # Installing page. 60 | !insertmacro MUI_PAGE_FINISH # Finished installation page. 61 | 62 | !insertmacro MUI_UNPAGE_INSTFILES # Uinstalling page 63 | 64 | !insertmacro MUI_LANGUAGE "English" # Set the Language of the installer 65 | 66 | ## The following two statements can be used to sign the installer and the uninstaller. The path to the binaries are provided in %1 67 | #!uninstfinalize 'signtool --file "%1"' 68 | #!finalize 'signtool --file "%1"' 69 | 70 | Name "${INFO_PRODUCTNAME}" 71 | OutFile "..\..\bin\${INFO_PROJECTNAME}-${ARCH}-installer.exe" # Name of the installer's file. 72 | InstallDir "$PROGRAMFILES64\${INFO_COMPANYNAME}\${INFO_PRODUCTNAME}" # Default installing folder ($PROGRAMFILES is Program Files folder). 73 | ShowInstDetails show # This will always show the installation details. 74 | 75 | Function .onInit 76 | !insertmacro wails.checkArchitecture 77 | FunctionEnd 78 | 79 | Section 80 | !insertmacro wails.webview2runtime 81 | 82 | SetOutPath $INSTDIR 83 | 84 | !insertmacro wails.files 85 | 86 | CreateShortcut "$SMPROGRAMS\${INFO_PRODUCTNAME}.lnk" "$INSTDIR\${PRODUCT_EXECUTABLE}" 87 | CreateShortCut "$DESKTOP\${INFO_PRODUCTNAME}.lnk" "$INSTDIR\${PRODUCT_EXECUTABLE}" 88 | 89 | !insertmacro wails.writeUninstaller 90 | SectionEnd 91 | 92 | Section "uninstall" 93 | RMDir /r "$AppData\${PRODUCT_EXECUTABLE}" # Remove the WebView2 DataPath 94 | 95 | RMDir /r $INSTDIR 96 | 97 | Delete "$SMPROGRAMS\${INFO_PRODUCTNAME}.lnk" 98 | Delete "$DESKTOP\${INFO_PRODUCTNAME}.lnk" 99 | 100 | !insertmacro wails.deleteUninstaller 101 | SectionEnd 102 | -------------------------------------------------------------------------------- /build/windows/wails.exe.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | true/pm 12 | permonitorv2,permonitor 13 | 14 | 15 | -------------------------------------------------------------------------------- /frontend/README.md: -------------------------------------------------------------------------------- 1 | # Svelte + Vite 2 | 3 | This template should help get you started developing with Svelte in Vite. 4 | 5 | ## Recommended IDE Setup 6 | 7 | [VS Code](https://code.visualstudio.com/) 8 | 9 | + [Svelte](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode). 10 | 11 | ## Need an official Svelte framework? 12 | 13 | Check out [SvelteKit](https://github.com/sveltejs/kit#readme), which is also powered by Vite. Deploy anywhere with its 14 | serverless-first approach and adapt to various platforms, with out of the box support for TypeScript, SCSS, and Less, 15 | and easily-added support for mdsvex, GraphQL, PostCSS, Tailwind CSS, and more. 16 | 17 | ## Technical considerations 18 | 19 | **Why use this over SvelteKit?** 20 | 21 | - It brings its own routing solution which might not be preferable for some users. 22 | - It is first and foremost a framework that just happens to use Vite under the hood, not a Vite app. 23 | `vite dev` and `vite build` wouldn't work in a SvelteKit environment, for example. 24 | 25 | This template contains as little as possible to get started with Vite + Svelte, while taking into account the developer 26 | experience with regards to HMR and intellisense. It demonstrates capabilities on par with the other `create-vite` 27 | templates and is a good starting point for beginners dipping their toes into a Vite + Svelte project. 28 | 29 | Should you later need the extended capabilities and extensibility provided by SvelteKit, the template has been 30 | structured similarly to SvelteKit so that it is easy to migrate. 31 | 32 | **Why `global.d.ts` instead of `compilerOptions.types` inside `jsconfig.json` or `tsconfig.json`?** 33 | 34 | Setting `compilerOptions.types` shuts out all other types not explicitly listed in the configuration. Using triple-slash 35 | references keeps the default TypeScript setting of accepting type information from the entire workspace, while also 36 | adding `svelte` and `vite/client` type information. 37 | 38 | **Why include `.vscode/extensions.json`?** 39 | 40 | Other templates indirectly recommend extensions via the README, but this file allows VS Code to prompt the user to 41 | install the recommended extension upon opening the project. 42 | 43 | **Why enable `checkJs` in the JS template?** 44 | 45 | It is likely that most cases of changing variable types in runtime are likely to be accidental, rather than deliberate. 46 | This provides advanced typechecking out of the box. Should you like to take advantage of the dynamically-typed nature of 47 | JavaScript, it is trivial to change the configuration. 48 | 49 | **Why is HMR not preserving my local component state?** 50 | 51 | HMR state preservation comes with a number of gotchas! It has been disabled by default in both `svelte-hmr` 52 | and `@sveltejs/vite-plugin-svelte` due to its often surprising behavior. You can read the 53 | details [here](https://github.com/rixo/svelte-hmr#svelte-hmr). 54 | 55 | If you have state that's important to retain within a component, consider creating an external store which would not be 56 | replaced by HMR. 57 | 58 | ```js 59 | // store.js 60 | // An extremely simple external store 61 | import { writable } from 'svelte/store' 62 | export default writable(0) 63 | ``` 64 | -------------------------------------------------------------------------------- /frontend/dist/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ScriptBar 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /frontend/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ScriptBar 7 | 8 | 9 |
10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /frontend/jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "moduleResolution": "Node", 4 | "target": "ESNext", 5 | "module": "ESNext", 6 | /** 7 | * svelte-preprocess cannot figure out whether you have 8 | * a value or a type, so tell TypeScript to enforce using 9 | * `import type` instead of `import` for Types. 10 | */ 11 | "importsNotUsedAsValues": "error", 12 | "isolatedModules": true, 13 | "resolveJsonModule": true, 14 | /** 15 | * To have warnings / errors of the Svelte compiler at the 16 | * correct position, enable source maps by default. 17 | */ 18 | "sourceMap": true, 19 | "esModuleInterop": true, 20 | "skipLibCheck": true, 21 | "forceConsistentCasingInFileNames": true, 22 | "baseUrl": ".", 23 | /** 24 | * Typecheck JS in `.svelte` and `.js` files by default. 25 | * Disable this if you'd like to use dynamic types. 26 | */ 27 | "checkJs": true 28 | }, 29 | /** 30 | * Use global.d.ts instead of compilerOptions.types 31 | * to avoid limiting type declarations. 32 | */ 33 | "include": [ 34 | "src/**/*.d.ts", 35 | "src/**/*.js", 36 | "src/**/*.svelte" 37 | ] 38 | } 39 | -------------------------------------------------------------------------------- /frontend/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "frontend", 3 | "version": "0.0.0", 4 | "lockfileVersion": 2, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "frontend", 9 | "version": "0.0.0", 10 | "dependencies": { 11 | "ansi_up": "^5.2.1" 12 | }, 13 | "devDependencies": { 14 | "@sveltejs/vite-plugin-svelte": "^2.4.1", 15 | "svelte": "^3.59.1", 16 | "vite": "^4.3.9" 17 | } 18 | }, 19 | "node_modules/@esbuild/android-arm": { 20 | "version": "0.17.18", 21 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.18.tgz", 22 | "integrity": "sha512-EmwL+vUBZJ7mhFCs5lA4ZimpUH3WMAoqvOIYhVQwdIgSpHC8ImHdsRyhHAVxpDYUSm0lWvd63z0XH1IlImS2Qw==", 23 | "cpu": [ 24 | "arm" 25 | ], 26 | "dev": true, 27 | "optional": true, 28 | "os": [ 29 | "android" 30 | ], 31 | "engines": { 32 | "node": ">=12" 33 | } 34 | }, 35 | "node_modules/@esbuild/android-arm64": { 36 | "version": "0.17.18", 37 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.18.tgz", 38 | "integrity": "sha512-/iq0aK0eeHgSC3z55ucMAHO05OIqmQehiGay8eP5l/5l+iEr4EIbh4/MI8xD9qRFjqzgkc0JkX0LculNC9mXBw==", 39 | "cpu": [ 40 | "arm64" 41 | ], 42 | "dev": true, 43 | "optional": true, 44 | "os": [ 45 | "android" 46 | ], 47 | "engines": { 48 | "node": ">=12" 49 | } 50 | }, 51 | "node_modules/@esbuild/android-x64": { 52 | "version": "0.17.18", 53 | "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.18.tgz", 54 | "integrity": "sha512-x+0efYNBF3NPW2Xc5bFOSFW7tTXdAcpfEg2nXmxegm4mJuVeS+i109m/7HMiOQ6M12aVGGFlqJX3RhNdYM2lWg==", 55 | "cpu": [ 56 | "x64" 57 | ], 58 | "dev": true, 59 | "optional": true, 60 | "os": [ 61 | "android" 62 | ], 63 | "engines": { 64 | "node": ">=12" 65 | } 66 | }, 67 | "node_modules/@esbuild/darwin-arm64": { 68 | "version": "0.17.18", 69 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.18.tgz", 70 | "integrity": "sha512-6tY+djEAdF48M1ONWnQb1C+6LiXrKjmqjzPNPWXhu/GzOHTHX2nh8Mo2ZAmBFg0kIodHhciEgUBtcYCAIjGbjQ==", 71 | "cpu": [ 72 | "arm64" 73 | ], 74 | "dev": true, 75 | "optional": true, 76 | "os": [ 77 | "darwin" 78 | ], 79 | "engines": { 80 | "node": ">=12" 81 | } 82 | }, 83 | "node_modules/@esbuild/darwin-x64": { 84 | "version": "0.17.18", 85 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.18.tgz", 86 | "integrity": "sha512-Qq84ykvLvya3dO49wVC9FFCNUfSrQJLbxhoQk/TE1r6MjHo3sFF2tlJCwMjhkBVq3/ahUisj7+EpRSz0/+8+9A==", 87 | "cpu": [ 88 | "x64" 89 | ], 90 | "dev": true, 91 | "optional": true, 92 | "os": [ 93 | "darwin" 94 | ], 95 | "engines": { 96 | "node": ">=12" 97 | } 98 | }, 99 | "node_modules/@esbuild/freebsd-arm64": { 100 | "version": "0.17.18", 101 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.18.tgz", 102 | "integrity": "sha512-fw/ZfxfAzuHfaQeMDhbzxp9mc+mHn1Y94VDHFHjGvt2Uxl10mT4CDavHm+/L9KG441t1QdABqkVYwakMUeyLRA==", 103 | "cpu": [ 104 | "arm64" 105 | ], 106 | "dev": true, 107 | "optional": true, 108 | "os": [ 109 | "freebsd" 110 | ], 111 | "engines": { 112 | "node": ">=12" 113 | } 114 | }, 115 | "node_modules/@esbuild/freebsd-x64": { 116 | "version": "0.17.18", 117 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.18.tgz", 118 | "integrity": "sha512-FQFbRtTaEi8ZBi/A6kxOC0V0E9B/97vPdYjY9NdawyLd4Qk5VD5g2pbWN2VR1c0xhzcJm74HWpObPszWC+qTew==", 119 | "cpu": [ 120 | "x64" 121 | ], 122 | "dev": true, 123 | "optional": true, 124 | "os": [ 125 | "freebsd" 126 | ], 127 | "engines": { 128 | "node": ">=12" 129 | } 130 | }, 131 | "node_modules/@esbuild/linux-arm": { 132 | "version": "0.17.18", 133 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.18.tgz", 134 | "integrity": "sha512-jW+UCM40LzHcouIaqv3e/oRs0JM76JfhHjCavPxMUti7VAPh8CaGSlS7cmyrdpzSk7A+8f0hiedHqr/LMnfijg==", 135 | "cpu": [ 136 | "arm" 137 | ], 138 | "dev": true, 139 | "optional": true, 140 | "os": [ 141 | "linux" 142 | ], 143 | "engines": { 144 | "node": ">=12" 145 | } 146 | }, 147 | "node_modules/@esbuild/linux-arm64": { 148 | "version": "0.17.18", 149 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.18.tgz", 150 | "integrity": "sha512-R7pZvQZFOY2sxUG8P6A21eq6q+eBv7JPQYIybHVf1XkQYC+lT7nDBdC7wWKTrbvMXKRaGudp/dzZCwL/863mZQ==", 151 | "cpu": [ 152 | "arm64" 153 | ], 154 | "dev": true, 155 | "optional": true, 156 | "os": [ 157 | "linux" 158 | ], 159 | "engines": { 160 | "node": ">=12" 161 | } 162 | }, 163 | "node_modules/@esbuild/linux-ia32": { 164 | "version": "0.17.18", 165 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.18.tgz", 166 | "integrity": "sha512-ygIMc3I7wxgXIxk6j3V00VlABIjq260i967Cp9BNAk5pOOpIXmd1RFQJQX9Io7KRsthDrQYrtcx7QCof4o3ZoQ==", 167 | "cpu": [ 168 | "ia32" 169 | ], 170 | "dev": true, 171 | "optional": true, 172 | "os": [ 173 | "linux" 174 | ], 175 | "engines": { 176 | "node": ">=12" 177 | } 178 | }, 179 | "node_modules/@esbuild/linux-loong64": { 180 | "version": "0.17.18", 181 | "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.18.tgz", 182 | "integrity": "sha512-bvPG+MyFs5ZlwYclCG1D744oHk1Pv7j8psF5TfYx7otCVmcJsEXgFEhQkbhNW8otDHL1a2KDINW20cfCgnzgMQ==", 183 | "cpu": [ 184 | "loong64" 185 | ], 186 | "dev": true, 187 | "optional": true, 188 | "os": [ 189 | "linux" 190 | ], 191 | "engines": { 192 | "node": ">=12" 193 | } 194 | }, 195 | "node_modules/@esbuild/linux-mips64el": { 196 | "version": "0.17.18", 197 | "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.18.tgz", 198 | "integrity": "sha512-oVqckATOAGuiUOa6wr8TXaVPSa+6IwVJrGidmNZS1cZVx0HqkTMkqFGD2HIx9H1RvOwFeWYdaYbdY6B89KUMxA==", 199 | "cpu": [ 200 | "mips64el" 201 | ], 202 | "dev": true, 203 | "optional": true, 204 | "os": [ 205 | "linux" 206 | ], 207 | "engines": { 208 | "node": ">=12" 209 | } 210 | }, 211 | "node_modules/@esbuild/linux-ppc64": { 212 | "version": "0.17.18", 213 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.18.tgz", 214 | "integrity": "sha512-3dLlQO+b/LnQNxgH4l9rqa2/IwRJVN9u/bK63FhOPB4xqiRqlQAU0qDU3JJuf0BmaH0yytTBdoSBHrb2jqc5qQ==", 215 | "cpu": [ 216 | "ppc64" 217 | ], 218 | "dev": true, 219 | "optional": true, 220 | "os": [ 221 | "linux" 222 | ], 223 | "engines": { 224 | "node": ">=12" 225 | } 226 | }, 227 | "node_modules/@esbuild/linux-riscv64": { 228 | "version": "0.17.18", 229 | "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.18.tgz", 230 | "integrity": "sha512-/x7leOyDPjZV3TcsdfrSI107zItVnsX1q2nho7hbbQoKnmoeUWjs+08rKKt4AUXju7+3aRZSsKrJtaRmsdL1xA==", 231 | "cpu": [ 232 | "riscv64" 233 | ], 234 | "dev": true, 235 | "optional": true, 236 | "os": [ 237 | "linux" 238 | ], 239 | "engines": { 240 | "node": ">=12" 241 | } 242 | }, 243 | "node_modules/@esbuild/linux-s390x": { 244 | "version": "0.17.18", 245 | "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.18.tgz", 246 | "integrity": "sha512-cX0I8Q9xQkL/6F5zWdYmVf5JSQt+ZfZD2bJudZrWD+4mnUvoZ3TDDXtDX2mUaq6upMFv9FlfIh4Gfun0tbGzuw==", 247 | "cpu": [ 248 | "s390x" 249 | ], 250 | "dev": true, 251 | "optional": true, 252 | "os": [ 253 | "linux" 254 | ], 255 | "engines": { 256 | "node": ">=12" 257 | } 258 | }, 259 | "node_modules/@esbuild/linux-x64": { 260 | "version": "0.17.18", 261 | "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.18.tgz", 262 | "integrity": "sha512-66RmRsPlYy4jFl0vG80GcNRdirx4nVWAzJmXkevgphP1qf4dsLQCpSKGM3DUQCojwU1hnepI63gNZdrr02wHUA==", 263 | "cpu": [ 264 | "x64" 265 | ], 266 | "dev": true, 267 | "optional": true, 268 | "os": [ 269 | "linux" 270 | ], 271 | "engines": { 272 | "node": ">=12" 273 | } 274 | }, 275 | "node_modules/@esbuild/netbsd-x64": { 276 | "version": "0.17.18", 277 | "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.18.tgz", 278 | "integrity": "sha512-95IRY7mI2yrkLlTLb1gpDxdC5WLC5mZDi+kA9dmM5XAGxCME0F8i4bYH4jZreaJ6lIZ0B8hTrweqG1fUyW7jbg==", 279 | "cpu": [ 280 | "x64" 281 | ], 282 | "dev": true, 283 | "optional": true, 284 | "os": [ 285 | "netbsd" 286 | ], 287 | "engines": { 288 | "node": ">=12" 289 | } 290 | }, 291 | "node_modules/@esbuild/openbsd-x64": { 292 | "version": "0.17.18", 293 | "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.18.tgz", 294 | "integrity": "sha512-WevVOgcng+8hSZ4Q3BKL3n1xTv5H6Nb53cBrtzzEjDbbnOmucEVcZeGCsCOi9bAOcDYEeBZbD2SJNBxlfP3qiA==", 295 | "cpu": [ 296 | "x64" 297 | ], 298 | "dev": true, 299 | "optional": true, 300 | "os": [ 301 | "openbsd" 302 | ], 303 | "engines": { 304 | "node": ">=12" 305 | } 306 | }, 307 | "node_modules/@esbuild/sunos-x64": { 308 | "version": "0.17.18", 309 | "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.18.tgz", 310 | "integrity": "sha512-Rzf4QfQagnwhQXVBS3BYUlxmEbcV7MY+BH5vfDZekU5eYpcffHSyjU8T0xucKVuOcdCsMo+Ur5wmgQJH2GfNrg==", 311 | "cpu": [ 312 | "x64" 313 | ], 314 | "dev": true, 315 | "optional": true, 316 | "os": [ 317 | "sunos" 318 | ], 319 | "engines": { 320 | "node": ">=12" 321 | } 322 | }, 323 | "node_modules/@esbuild/win32-arm64": { 324 | "version": "0.17.18", 325 | "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.18.tgz", 326 | "integrity": "sha512-Kb3Ko/KKaWhjeAm2YoT/cNZaHaD1Yk/pa3FTsmqo9uFh1D1Rfco7BBLIPdDOozrObj2sahslFuAQGvWbgWldAg==", 327 | "cpu": [ 328 | "arm64" 329 | ], 330 | "dev": true, 331 | "optional": true, 332 | "os": [ 333 | "win32" 334 | ], 335 | "engines": { 336 | "node": ">=12" 337 | } 338 | }, 339 | "node_modules/@esbuild/win32-ia32": { 340 | "version": "0.17.18", 341 | "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.18.tgz", 342 | "integrity": "sha512-0/xUMIdkVHwkvxfbd5+lfG7mHOf2FRrxNbPiKWg9C4fFrB8H0guClmaM3BFiRUYrznVoyxTIyC/Ou2B7QQSwmw==", 343 | "cpu": [ 344 | "ia32" 345 | ], 346 | "dev": true, 347 | "optional": true, 348 | "os": [ 349 | "win32" 350 | ], 351 | "engines": { 352 | "node": ">=12" 353 | } 354 | }, 355 | "node_modules/@esbuild/win32-x64": { 356 | "version": "0.17.18", 357 | "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.18.tgz", 358 | "integrity": "sha512-qU25Ma1I3NqTSHJUOKi9sAH1/Mzuvlke0ioMJRthLXKm7JiSKVwFghlGbDLOO2sARECGhja4xYfRAZNPAkooYg==", 359 | "cpu": [ 360 | "x64" 361 | ], 362 | "dev": true, 363 | "optional": true, 364 | "os": [ 365 | "win32" 366 | ], 367 | "engines": { 368 | "node": ">=12" 369 | } 370 | }, 371 | "node_modules/@jridgewell/sourcemap-codec": { 372 | "version": "1.4.15", 373 | "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", 374 | "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", 375 | "dev": true 376 | }, 377 | "node_modules/@sveltejs/vite-plugin-svelte": { 378 | "version": "2.4.1", 379 | "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-2.4.1.tgz", 380 | "integrity": "sha512-bNNKvoRY89ptY7udeBSCmTdCVwkjmMcZ0j/z9J5MuedT8jPjq0zrknAo/jF1sToAza4NVaAgR9AkZoD9oJJmnA==", 381 | "dev": true, 382 | "dependencies": { 383 | "@sveltejs/vite-plugin-svelte-inspector": "^1.0.2", 384 | "debug": "^4.3.4", 385 | "deepmerge": "^4.3.1", 386 | "kleur": "^4.1.5", 387 | "magic-string": "^0.30.0", 388 | "svelte-hmr": "^0.15.1", 389 | "vitefu": "^0.2.4" 390 | }, 391 | "engines": { 392 | "node": "^14.18.0 || >= 16" 393 | }, 394 | "peerDependencies": { 395 | "svelte": "^3.54.0 || ^4.0.0-next.0", 396 | "vite": "^4.0.0" 397 | } 398 | }, 399 | "node_modules/@sveltejs/vite-plugin-svelte-inspector": { 400 | "version": "1.0.2", 401 | "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte-inspector/-/vite-plugin-svelte-inspector-1.0.2.tgz", 402 | "integrity": "sha512-Cy1dUMcYCnDVV/hPLXa43YZJ2jGKVW5rA0xuNL9dlmYhT0yoS1g7+FOFSRlgk0BXKk/Oc7grs+8BVA5Iz2fr8A==", 403 | "dev": true, 404 | "dependencies": { 405 | "debug": "^4.3.4" 406 | }, 407 | "engines": { 408 | "node": "^14.18.0 || >= 16" 409 | }, 410 | "peerDependencies": { 411 | "@sveltejs/vite-plugin-svelte": "^2.2.0", 412 | "svelte": "^3.54.0 || ^4.0.0-next.0", 413 | "vite": "^4.0.0" 414 | } 415 | }, 416 | "node_modules/ansi_up": { 417 | "version": "5.2.1", 418 | "resolved": "https://registry.npmjs.org/ansi_up/-/ansi_up-5.2.1.tgz", 419 | "integrity": "sha512-5bz5T/7FRmlxA37zDXhG6cAwlcZtfnmNLDJra66EEIT3kYlw5aPJdbkJEhm59D6kA4Wi5ict6u6IDYHJaQlH+g==", 420 | "engines": { 421 | "node": "*" 422 | } 423 | }, 424 | "node_modules/debug": { 425 | "version": "4.3.4", 426 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", 427 | "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", 428 | "dev": true, 429 | "dependencies": { 430 | "ms": "2.1.2" 431 | }, 432 | "engines": { 433 | "node": ">=6.0" 434 | }, 435 | "peerDependenciesMeta": { 436 | "supports-color": { 437 | "optional": true 438 | } 439 | } 440 | }, 441 | "node_modules/deepmerge": { 442 | "version": "4.3.1", 443 | "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", 444 | "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", 445 | "dev": true, 446 | "engines": { 447 | "node": ">=0.10.0" 448 | } 449 | }, 450 | "node_modules/esbuild": { 451 | "version": "0.17.18", 452 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.18.tgz", 453 | "integrity": "sha512-z1lix43jBs6UKjcZVKOw2xx69ffE2aG0PygLL5qJ9OS/gy0Ewd1gW/PUQIOIQGXBHWNywSc0floSKoMFF8aK2w==", 454 | "dev": true, 455 | "hasInstallScript": true, 456 | "bin": { 457 | "esbuild": "bin/esbuild" 458 | }, 459 | "engines": { 460 | "node": ">=12" 461 | }, 462 | "optionalDependencies": { 463 | "@esbuild/android-arm": "0.17.18", 464 | "@esbuild/android-arm64": "0.17.18", 465 | "@esbuild/android-x64": "0.17.18", 466 | "@esbuild/darwin-arm64": "0.17.18", 467 | "@esbuild/darwin-x64": "0.17.18", 468 | "@esbuild/freebsd-arm64": "0.17.18", 469 | "@esbuild/freebsd-x64": "0.17.18", 470 | "@esbuild/linux-arm": "0.17.18", 471 | "@esbuild/linux-arm64": "0.17.18", 472 | "@esbuild/linux-ia32": "0.17.18", 473 | "@esbuild/linux-loong64": "0.17.18", 474 | "@esbuild/linux-mips64el": "0.17.18", 475 | "@esbuild/linux-ppc64": "0.17.18", 476 | "@esbuild/linux-riscv64": "0.17.18", 477 | "@esbuild/linux-s390x": "0.17.18", 478 | "@esbuild/linux-x64": "0.17.18", 479 | "@esbuild/netbsd-x64": "0.17.18", 480 | "@esbuild/openbsd-x64": "0.17.18", 481 | "@esbuild/sunos-x64": "0.17.18", 482 | "@esbuild/win32-arm64": "0.17.18", 483 | "@esbuild/win32-ia32": "0.17.18", 484 | "@esbuild/win32-x64": "0.17.18" 485 | } 486 | }, 487 | "node_modules/fsevents": { 488 | "version": "2.3.2", 489 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", 490 | "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", 491 | "dev": true, 492 | "hasInstallScript": true, 493 | "optional": true, 494 | "os": [ 495 | "darwin" 496 | ], 497 | "engines": { 498 | "node": "^8.16.0 || ^10.6.0 || >=11.0.0" 499 | } 500 | }, 501 | "node_modules/kleur": { 502 | "version": "4.1.5", 503 | "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", 504 | "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", 505 | "dev": true, 506 | "engines": { 507 | "node": ">=6" 508 | } 509 | }, 510 | "node_modules/magic-string": { 511 | "version": "0.30.0", 512 | "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.0.tgz", 513 | "integrity": "sha512-LA+31JYDJLs82r2ScLrlz1GjSgu66ZV518eyWT+S8VhyQn/JL0u9MeBOvQMGYiPk1DBiSN9DDMOcXvigJZaViQ==", 514 | "dev": true, 515 | "dependencies": { 516 | "@jridgewell/sourcemap-codec": "^1.4.13" 517 | }, 518 | "engines": { 519 | "node": ">=12" 520 | } 521 | }, 522 | "node_modules/ms": { 523 | "version": "2.1.2", 524 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 525 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 526 | "dev": true 527 | }, 528 | "node_modules/nanoid": { 529 | "version": "3.3.6", 530 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", 531 | "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", 532 | "dev": true, 533 | "funding": [ 534 | { 535 | "type": "github", 536 | "url": "https://github.com/sponsors/ai" 537 | } 538 | ], 539 | "bin": { 540 | "nanoid": "bin/nanoid.cjs" 541 | }, 542 | "engines": { 543 | "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" 544 | } 545 | }, 546 | "node_modules/picocolors": { 547 | "version": "1.0.0", 548 | "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", 549 | "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", 550 | "dev": true 551 | }, 552 | "node_modules/postcss": { 553 | "version": "8.4.23", 554 | "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.23.tgz", 555 | "integrity": "sha512-bQ3qMcpF6A/YjR55xtoTr0jGOlnPOKAIMdOWiv0EIT6HVPEaJiJB4NLljSbiHoC2RX7DN5Uvjtpbg1NPdwv1oA==", 556 | "dev": true, 557 | "funding": [ 558 | { 559 | "type": "opencollective", 560 | "url": "https://opencollective.com/postcss/" 561 | }, 562 | { 563 | "type": "tidelift", 564 | "url": "https://tidelift.com/funding/github/npm/postcss" 565 | }, 566 | { 567 | "type": "github", 568 | "url": "https://github.com/sponsors/ai" 569 | } 570 | ], 571 | "dependencies": { 572 | "nanoid": "^3.3.6", 573 | "picocolors": "^1.0.0", 574 | "source-map-js": "^1.0.2" 575 | }, 576 | "engines": { 577 | "node": "^10 || ^12 || >=14" 578 | } 579 | }, 580 | "node_modules/rollup": { 581 | "version": "3.21.6", 582 | "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.21.6.tgz", 583 | "integrity": "sha512-SXIICxvxQxR3D4dp/3LDHZIJPC8a4anKMHd4E3Jiz2/JnY+2bEjqrOokAauc5ShGVNFHlEFjBXAXlaxkJqIqSg==", 584 | "dev": true, 585 | "bin": { 586 | "rollup": "dist/bin/rollup" 587 | }, 588 | "engines": { 589 | "node": ">=14.18.0", 590 | "npm": ">=8.0.0" 591 | }, 592 | "optionalDependencies": { 593 | "fsevents": "~2.3.2" 594 | } 595 | }, 596 | "node_modules/source-map-js": { 597 | "version": "1.0.2", 598 | "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", 599 | "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", 600 | "dev": true, 601 | "engines": { 602 | "node": ">=0.10.0" 603 | } 604 | }, 605 | "node_modules/svelte": { 606 | "version": "3.59.1", 607 | "resolved": "https://registry.npmjs.org/svelte/-/svelte-3.59.1.tgz", 608 | "integrity": "sha512-pKj8fEBmqf6mq3/NfrB9SLtcJcUvjYSWyePlfCqN9gujLB25RitWK8PvFzlwim6hD/We35KbPlRteuA6rnPGcQ==", 609 | "dev": true, 610 | "engines": { 611 | "node": ">= 8" 612 | } 613 | }, 614 | "node_modules/svelte-hmr": { 615 | "version": "0.15.1", 616 | "resolved": "https://registry.npmjs.org/svelte-hmr/-/svelte-hmr-0.15.1.tgz", 617 | "integrity": "sha512-BiKB4RZ8YSwRKCNVdNxK/GfY+r4Kjgp9jCLEy0DuqAKfmQtpL38cQK3afdpjw4sqSs4PLi3jIPJIFp259NkZtA==", 618 | "dev": true, 619 | "engines": { 620 | "node": "^12.20 || ^14.13.1 || >= 16" 621 | }, 622 | "peerDependencies": { 623 | "svelte": ">=3.19.0" 624 | } 625 | }, 626 | "node_modules/vite": { 627 | "version": "4.3.9", 628 | "resolved": "https://registry.npmjs.org/vite/-/vite-4.3.9.tgz", 629 | "integrity": "sha512-qsTNZjO9NoJNW7KnOrgYwczm0WctJ8m/yqYAMAK9Lxt4SoySUfS5S8ia9K7JHpa3KEeMfyF8LoJ3c5NeBJy6pg==", 630 | "dev": true, 631 | "dependencies": { 632 | "esbuild": "^0.17.5", 633 | "postcss": "^8.4.23", 634 | "rollup": "^3.21.0" 635 | }, 636 | "bin": { 637 | "vite": "bin/vite.js" 638 | }, 639 | "engines": { 640 | "node": "^14.18.0 || >=16.0.0" 641 | }, 642 | "optionalDependencies": { 643 | "fsevents": "~2.3.2" 644 | }, 645 | "peerDependencies": { 646 | "@types/node": ">= 14", 647 | "less": "*", 648 | "sass": "*", 649 | "stylus": "*", 650 | "sugarss": "*", 651 | "terser": "^5.4.0" 652 | }, 653 | "peerDependenciesMeta": { 654 | "@types/node": { 655 | "optional": true 656 | }, 657 | "less": { 658 | "optional": true 659 | }, 660 | "sass": { 661 | "optional": true 662 | }, 663 | "stylus": { 664 | "optional": true 665 | }, 666 | "sugarss": { 667 | "optional": true 668 | }, 669 | "terser": { 670 | "optional": true 671 | } 672 | } 673 | }, 674 | "node_modules/vitefu": { 675 | "version": "0.2.4", 676 | "resolved": "https://registry.npmjs.org/vitefu/-/vitefu-0.2.4.tgz", 677 | "integrity": "sha512-fanAXjSaf9xXtOOeno8wZXIhgia+CZury481LsDaV++lSvcU2R9Ch2bPh3PYFyoHW+w9LqAeYRISVQjUIew14g==", 678 | "dev": true, 679 | "peerDependencies": { 680 | "vite": "^3.0.0 || ^4.0.0" 681 | }, 682 | "peerDependenciesMeta": { 683 | "vite": { 684 | "optional": true 685 | } 686 | } 687 | } 688 | }, 689 | "dependencies": { 690 | "@esbuild/android-arm": { 691 | "version": "0.17.18", 692 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.18.tgz", 693 | "integrity": "sha512-EmwL+vUBZJ7mhFCs5lA4ZimpUH3WMAoqvOIYhVQwdIgSpHC8ImHdsRyhHAVxpDYUSm0lWvd63z0XH1IlImS2Qw==", 694 | "dev": true, 695 | "optional": true 696 | }, 697 | "@esbuild/android-arm64": { 698 | "version": "0.17.18", 699 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.18.tgz", 700 | "integrity": "sha512-/iq0aK0eeHgSC3z55ucMAHO05OIqmQehiGay8eP5l/5l+iEr4EIbh4/MI8xD9qRFjqzgkc0JkX0LculNC9mXBw==", 701 | "dev": true, 702 | "optional": true 703 | }, 704 | "@esbuild/android-x64": { 705 | "version": "0.17.18", 706 | "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.18.tgz", 707 | "integrity": "sha512-x+0efYNBF3NPW2Xc5bFOSFW7tTXdAcpfEg2nXmxegm4mJuVeS+i109m/7HMiOQ6M12aVGGFlqJX3RhNdYM2lWg==", 708 | "dev": true, 709 | "optional": true 710 | }, 711 | "@esbuild/darwin-arm64": { 712 | "version": "0.17.18", 713 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.18.tgz", 714 | "integrity": "sha512-6tY+djEAdF48M1ONWnQb1C+6LiXrKjmqjzPNPWXhu/GzOHTHX2nh8Mo2ZAmBFg0kIodHhciEgUBtcYCAIjGbjQ==", 715 | "dev": true, 716 | "optional": true 717 | }, 718 | "@esbuild/darwin-x64": { 719 | "version": "0.17.18", 720 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.18.tgz", 721 | "integrity": "sha512-Qq84ykvLvya3dO49wVC9FFCNUfSrQJLbxhoQk/TE1r6MjHo3sFF2tlJCwMjhkBVq3/ahUisj7+EpRSz0/+8+9A==", 722 | "dev": true, 723 | "optional": true 724 | }, 725 | "@esbuild/freebsd-arm64": { 726 | "version": "0.17.18", 727 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.18.tgz", 728 | "integrity": "sha512-fw/ZfxfAzuHfaQeMDhbzxp9mc+mHn1Y94VDHFHjGvt2Uxl10mT4CDavHm+/L9KG441t1QdABqkVYwakMUeyLRA==", 729 | "dev": true, 730 | "optional": true 731 | }, 732 | "@esbuild/freebsd-x64": { 733 | "version": "0.17.18", 734 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.18.tgz", 735 | "integrity": "sha512-FQFbRtTaEi8ZBi/A6kxOC0V0E9B/97vPdYjY9NdawyLd4Qk5VD5g2pbWN2VR1c0xhzcJm74HWpObPszWC+qTew==", 736 | "dev": true, 737 | "optional": true 738 | }, 739 | "@esbuild/linux-arm": { 740 | "version": "0.17.18", 741 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.18.tgz", 742 | "integrity": "sha512-jW+UCM40LzHcouIaqv3e/oRs0JM76JfhHjCavPxMUti7VAPh8CaGSlS7cmyrdpzSk7A+8f0hiedHqr/LMnfijg==", 743 | "dev": true, 744 | "optional": true 745 | }, 746 | "@esbuild/linux-arm64": { 747 | "version": "0.17.18", 748 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.18.tgz", 749 | "integrity": "sha512-R7pZvQZFOY2sxUG8P6A21eq6q+eBv7JPQYIybHVf1XkQYC+lT7nDBdC7wWKTrbvMXKRaGudp/dzZCwL/863mZQ==", 750 | "dev": true, 751 | "optional": true 752 | }, 753 | "@esbuild/linux-ia32": { 754 | "version": "0.17.18", 755 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.18.tgz", 756 | "integrity": "sha512-ygIMc3I7wxgXIxk6j3V00VlABIjq260i967Cp9BNAk5pOOpIXmd1RFQJQX9Io7KRsthDrQYrtcx7QCof4o3ZoQ==", 757 | "dev": true, 758 | "optional": true 759 | }, 760 | "@esbuild/linux-loong64": { 761 | "version": "0.17.18", 762 | "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.18.tgz", 763 | "integrity": "sha512-bvPG+MyFs5ZlwYclCG1D744oHk1Pv7j8psF5TfYx7otCVmcJsEXgFEhQkbhNW8otDHL1a2KDINW20cfCgnzgMQ==", 764 | "dev": true, 765 | "optional": true 766 | }, 767 | "@esbuild/linux-mips64el": { 768 | "version": "0.17.18", 769 | "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.18.tgz", 770 | "integrity": "sha512-oVqckATOAGuiUOa6wr8TXaVPSa+6IwVJrGidmNZS1cZVx0HqkTMkqFGD2HIx9H1RvOwFeWYdaYbdY6B89KUMxA==", 771 | "dev": true, 772 | "optional": true 773 | }, 774 | "@esbuild/linux-ppc64": { 775 | "version": "0.17.18", 776 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.18.tgz", 777 | "integrity": "sha512-3dLlQO+b/LnQNxgH4l9rqa2/IwRJVN9u/bK63FhOPB4xqiRqlQAU0qDU3JJuf0BmaH0yytTBdoSBHrb2jqc5qQ==", 778 | "dev": true, 779 | "optional": true 780 | }, 781 | "@esbuild/linux-riscv64": { 782 | "version": "0.17.18", 783 | "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.18.tgz", 784 | "integrity": "sha512-/x7leOyDPjZV3TcsdfrSI107zItVnsX1q2nho7hbbQoKnmoeUWjs+08rKKt4AUXju7+3aRZSsKrJtaRmsdL1xA==", 785 | "dev": true, 786 | "optional": true 787 | }, 788 | "@esbuild/linux-s390x": { 789 | "version": "0.17.18", 790 | "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.18.tgz", 791 | "integrity": "sha512-cX0I8Q9xQkL/6F5zWdYmVf5JSQt+ZfZD2bJudZrWD+4mnUvoZ3TDDXtDX2mUaq6upMFv9FlfIh4Gfun0tbGzuw==", 792 | "dev": true, 793 | "optional": true 794 | }, 795 | "@esbuild/linux-x64": { 796 | "version": "0.17.18", 797 | "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.18.tgz", 798 | "integrity": "sha512-66RmRsPlYy4jFl0vG80GcNRdirx4nVWAzJmXkevgphP1qf4dsLQCpSKGM3DUQCojwU1hnepI63gNZdrr02wHUA==", 799 | "dev": true, 800 | "optional": true 801 | }, 802 | "@esbuild/netbsd-x64": { 803 | "version": "0.17.18", 804 | "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.18.tgz", 805 | "integrity": "sha512-95IRY7mI2yrkLlTLb1gpDxdC5WLC5mZDi+kA9dmM5XAGxCME0F8i4bYH4jZreaJ6lIZ0B8hTrweqG1fUyW7jbg==", 806 | "dev": true, 807 | "optional": true 808 | }, 809 | "@esbuild/openbsd-x64": { 810 | "version": "0.17.18", 811 | "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.18.tgz", 812 | "integrity": "sha512-WevVOgcng+8hSZ4Q3BKL3n1xTv5H6Nb53cBrtzzEjDbbnOmucEVcZeGCsCOi9bAOcDYEeBZbD2SJNBxlfP3qiA==", 813 | "dev": true, 814 | "optional": true 815 | }, 816 | "@esbuild/sunos-x64": { 817 | "version": "0.17.18", 818 | "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.18.tgz", 819 | "integrity": "sha512-Rzf4QfQagnwhQXVBS3BYUlxmEbcV7MY+BH5vfDZekU5eYpcffHSyjU8T0xucKVuOcdCsMo+Ur5wmgQJH2GfNrg==", 820 | "dev": true, 821 | "optional": true 822 | }, 823 | "@esbuild/win32-arm64": { 824 | "version": "0.17.18", 825 | "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.18.tgz", 826 | "integrity": "sha512-Kb3Ko/KKaWhjeAm2YoT/cNZaHaD1Yk/pa3FTsmqo9uFh1D1Rfco7BBLIPdDOozrObj2sahslFuAQGvWbgWldAg==", 827 | "dev": true, 828 | "optional": true 829 | }, 830 | "@esbuild/win32-ia32": { 831 | "version": "0.17.18", 832 | "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.18.tgz", 833 | "integrity": "sha512-0/xUMIdkVHwkvxfbd5+lfG7mHOf2FRrxNbPiKWg9C4fFrB8H0guClmaM3BFiRUYrznVoyxTIyC/Ou2B7QQSwmw==", 834 | "dev": true, 835 | "optional": true 836 | }, 837 | "@esbuild/win32-x64": { 838 | "version": "0.17.18", 839 | "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.18.tgz", 840 | "integrity": "sha512-qU25Ma1I3NqTSHJUOKi9sAH1/Mzuvlke0ioMJRthLXKm7JiSKVwFghlGbDLOO2sARECGhja4xYfRAZNPAkooYg==", 841 | "dev": true, 842 | "optional": true 843 | }, 844 | "@jridgewell/sourcemap-codec": { 845 | "version": "1.4.15", 846 | "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", 847 | "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", 848 | "dev": true 849 | }, 850 | "@sveltejs/vite-plugin-svelte": { 851 | "version": "2.4.1", 852 | "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-2.4.1.tgz", 853 | "integrity": "sha512-bNNKvoRY89ptY7udeBSCmTdCVwkjmMcZ0j/z9J5MuedT8jPjq0zrknAo/jF1sToAza4NVaAgR9AkZoD9oJJmnA==", 854 | "dev": true, 855 | "requires": { 856 | "@sveltejs/vite-plugin-svelte-inspector": "^1.0.2", 857 | "debug": "^4.3.4", 858 | "deepmerge": "^4.3.1", 859 | "kleur": "^4.1.5", 860 | "magic-string": "^0.30.0", 861 | "svelte-hmr": "^0.15.1", 862 | "vitefu": "^0.2.4" 863 | } 864 | }, 865 | "@sveltejs/vite-plugin-svelte-inspector": { 866 | "version": "1.0.2", 867 | "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte-inspector/-/vite-plugin-svelte-inspector-1.0.2.tgz", 868 | "integrity": "sha512-Cy1dUMcYCnDVV/hPLXa43YZJ2jGKVW5rA0xuNL9dlmYhT0yoS1g7+FOFSRlgk0BXKk/Oc7grs+8BVA5Iz2fr8A==", 869 | "dev": true, 870 | "requires": { 871 | "debug": "^4.3.4" 872 | } 873 | }, 874 | "ansi_up": { 875 | "version": "5.2.1", 876 | "resolved": "https://registry.npmjs.org/ansi_up/-/ansi_up-5.2.1.tgz", 877 | "integrity": "sha512-5bz5T/7FRmlxA37zDXhG6cAwlcZtfnmNLDJra66EEIT3kYlw5aPJdbkJEhm59D6kA4Wi5ict6u6IDYHJaQlH+g==" 878 | }, 879 | "debug": { 880 | "version": "4.3.4", 881 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", 882 | "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", 883 | "dev": true, 884 | "requires": { 885 | "ms": "2.1.2" 886 | } 887 | }, 888 | "deepmerge": { 889 | "version": "4.3.1", 890 | "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", 891 | "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", 892 | "dev": true 893 | }, 894 | "esbuild": { 895 | "version": "0.17.18", 896 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.18.tgz", 897 | "integrity": "sha512-z1lix43jBs6UKjcZVKOw2xx69ffE2aG0PygLL5qJ9OS/gy0Ewd1gW/PUQIOIQGXBHWNywSc0floSKoMFF8aK2w==", 898 | "dev": true, 899 | "requires": { 900 | "@esbuild/android-arm": "0.17.18", 901 | "@esbuild/android-arm64": "0.17.18", 902 | "@esbuild/android-x64": "0.17.18", 903 | "@esbuild/darwin-arm64": "0.17.18", 904 | "@esbuild/darwin-x64": "0.17.18", 905 | "@esbuild/freebsd-arm64": "0.17.18", 906 | "@esbuild/freebsd-x64": "0.17.18", 907 | "@esbuild/linux-arm": "0.17.18", 908 | "@esbuild/linux-arm64": "0.17.18", 909 | "@esbuild/linux-ia32": "0.17.18", 910 | "@esbuild/linux-loong64": "0.17.18", 911 | "@esbuild/linux-mips64el": "0.17.18", 912 | "@esbuild/linux-ppc64": "0.17.18", 913 | "@esbuild/linux-riscv64": "0.17.18", 914 | "@esbuild/linux-s390x": "0.17.18", 915 | "@esbuild/linux-x64": "0.17.18", 916 | "@esbuild/netbsd-x64": "0.17.18", 917 | "@esbuild/openbsd-x64": "0.17.18", 918 | "@esbuild/sunos-x64": "0.17.18", 919 | "@esbuild/win32-arm64": "0.17.18", 920 | "@esbuild/win32-ia32": "0.17.18", 921 | "@esbuild/win32-x64": "0.17.18" 922 | } 923 | }, 924 | "fsevents": { 925 | "version": "2.3.2", 926 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", 927 | "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", 928 | "dev": true, 929 | "optional": true 930 | }, 931 | "kleur": { 932 | "version": "4.1.5", 933 | "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", 934 | "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", 935 | "dev": true 936 | }, 937 | "magic-string": { 938 | "version": "0.30.0", 939 | "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.0.tgz", 940 | "integrity": "sha512-LA+31JYDJLs82r2ScLrlz1GjSgu66ZV518eyWT+S8VhyQn/JL0u9MeBOvQMGYiPk1DBiSN9DDMOcXvigJZaViQ==", 941 | "dev": true, 942 | "requires": { 943 | "@jridgewell/sourcemap-codec": "^1.4.13" 944 | } 945 | }, 946 | "ms": { 947 | "version": "2.1.2", 948 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 949 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 950 | "dev": true 951 | }, 952 | "nanoid": { 953 | "version": "3.3.6", 954 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", 955 | "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", 956 | "dev": true 957 | }, 958 | "picocolors": { 959 | "version": "1.0.0", 960 | "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", 961 | "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", 962 | "dev": true 963 | }, 964 | "postcss": { 965 | "version": "8.4.23", 966 | "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.23.tgz", 967 | "integrity": "sha512-bQ3qMcpF6A/YjR55xtoTr0jGOlnPOKAIMdOWiv0EIT6HVPEaJiJB4NLljSbiHoC2RX7DN5Uvjtpbg1NPdwv1oA==", 968 | "dev": true, 969 | "requires": { 970 | "nanoid": "^3.3.6", 971 | "picocolors": "^1.0.0", 972 | "source-map-js": "^1.0.2" 973 | } 974 | }, 975 | "rollup": { 976 | "version": "3.21.6", 977 | "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.21.6.tgz", 978 | "integrity": "sha512-SXIICxvxQxR3D4dp/3LDHZIJPC8a4anKMHd4E3Jiz2/JnY+2bEjqrOokAauc5ShGVNFHlEFjBXAXlaxkJqIqSg==", 979 | "dev": true, 980 | "requires": { 981 | "fsevents": "~2.3.2" 982 | } 983 | }, 984 | "source-map-js": { 985 | "version": "1.0.2", 986 | "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", 987 | "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", 988 | "dev": true 989 | }, 990 | "svelte": { 991 | "version": "3.59.1", 992 | "resolved": "https://registry.npmjs.org/svelte/-/svelte-3.59.1.tgz", 993 | "integrity": "sha512-pKj8fEBmqf6mq3/NfrB9SLtcJcUvjYSWyePlfCqN9gujLB25RitWK8PvFzlwim6hD/We35KbPlRteuA6rnPGcQ==", 994 | "dev": true 995 | }, 996 | "svelte-hmr": { 997 | "version": "0.15.1", 998 | "resolved": "https://registry.npmjs.org/svelte-hmr/-/svelte-hmr-0.15.1.tgz", 999 | "integrity": "sha512-BiKB4RZ8YSwRKCNVdNxK/GfY+r4Kjgp9jCLEy0DuqAKfmQtpL38cQK3afdpjw4sqSs4PLi3jIPJIFp259NkZtA==", 1000 | "dev": true, 1001 | "requires": {} 1002 | }, 1003 | "vite": { 1004 | "version": "4.3.9", 1005 | "resolved": "https://registry.npmjs.org/vite/-/vite-4.3.9.tgz", 1006 | "integrity": "sha512-qsTNZjO9NoJNW7KnOrgYwczm0WctJ8m/yqYAMAK9Lxt4SoySUfS5S8ia9K7JHpa3KEeMfyF8LoJ3c5NeBJy6pg==", 1007 | "dev": true, 1008 | "requires": { 1009 | "esbuild": "^0.17.5", 1010 | "fsevents": "~2.3.2", 1011 | "postcss": "^8.4.23", 1012 | "rollup": "^3.21.0" 1013 | } 1014 | }, 1015 | "vitefu": { 1016 | "version": "0.2.4", 1017 | "resolved": "https://registry.npmjs.org/vitefu/-/vitefu-0.2.4.tgz", 1018 | "integrity": "sha512-fanAXjSaf9xXtOOeno8wZXIhgia+CZury481LsDaV++lSvcU2R9Ch2bPh3PYFyoHW+w9LqAeYRISVQjUIew14g==", 1019 | "dev": true, 1020 | "requires": {} 1021 | } 1022 | } 1023 | } 1024 | -------------------------------------------------------------------------------- /frontend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "frontend", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vite build", 9 | "preview": "vite preview" 10 | }, 11 | "devDependencies": { 12 | "@sveltejs/vite-plugin-svelte": "^2.4.1", 13 | "svelte": "^3.59.1", 14 | "vite": "^4.3.9" 15 | }, 16 | "dependencies": { 17 | "ansi_up": "^5.2.1" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /frontend/package.json.md5: -------------------------------------------------------------------------------- 1 | 26eee23757583a4a85879d0bf6fd73ff -------------------------------------------------------------------------------- /frontend/src/Main.svelte: -------------------------------------------------------------------------------- 1 | 3 | 4 | {#if view === 'scriptbar'} 5 | {viewChange(e.detail);}} 8 | /> 9 | {:else if view === 'webview'} 10 | {viewChange(e.detail);}} 13 | /> 14 | {:else} 15 |
16 |

Something went wrong

17 |

Sorry, but you somehow got to a place that isn't reachable.

18 |

Press be button below to get back to the normal page.

19 | 24 |
25 | {/if} 26 | 27 | 72 | 73 | 128 | -------------------------------------------------------------------------------- /frontend/src/components/AddComponent.svelte: -------------------------------------------------------------------------------- 1 |
3 | 7 | 12 | 16 | 27 | 31 | 36 | {#if componentConfigWidget !== null} 37 | { componentConfig = e.detail; }} 41 | /> 42 | {/if} 43 | 49 |
50 | 51 | 88 | 89 | 144 | -------------------------------------------------------------------------------- /frontend/src/components/BirthdayCounter.svelte: -------------------------------------------------------------------------------- 1 |
{ dom.style.color = $styles.highlight; }} 6 | on:mouseleave={() => { dom.style.color = $styles.textcolor; }} 7 | on:mouseout={() => { dom.style.color = $styles.textcolor; }} 8 | on:blur={() => { dom.style.color = $styles.textcolor; }} 9 | > 10 |

{ dispatch('dblclick',{});}} 11 | on:contextmenu={(e) => { e.preventDefault(); middleButton();}} 12 | class='name' style="font-size: {$styles.fontSize};" 13 | data-index="{index}" 14 | > 15 | {disName} 16 |

17 |

21 | {value} 22 |

23 |
24 | 25 | 44 | 45 | 98 | -------------------------------------------------------------------------------- /frontend/src/components/BirthdayCounterConfig.svelte: -------------------------------------------------------------------------------- 1 |
2 | 6 | { dispatch('change',{ 11 | flowVar: config.flowVar 12 | });}} 13 | /> 14 |
15 | 16 | 33 | 34 | 41 | 42 | -------------------------------------------------------------------------------- /frontend/src/components/EditComponent.svelte: -------------------------------------------------------------------------------- 1 |
2 | 6 | 11 | 15 | 20 | {#if componentConfigWidget !== null} 21 | { componentConfig = e.detail; }} 25 | /> 26 | {/if} 27 |
28 | 34 | 40 |
41 |
42 | 43 | 102 | 103 | 156 | -------------------------------------------------------------------------------- /frontend/src/components/EditSpanField.svelte: -------------------------------------------------------------------------------- 1 |
2 | {#if editH2Flag} 3 |