sunrize 1.6.1 → 1.6.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "sunrize",
3
3
  "productName": "Sunrize X3D Editor",
4
- "version": "1.6.1",
4
+ "version": "1.6.3",
5
5
  "description": "A Multi-Platform X3D Editor",
6
6
  "main": "src/main.js",
7
7
  "bin": {
@@ -93,14 +93,13 @@
93
93
  "material-symbols": "^0.16.0",
94
94
  "md5": "^2.3.0",
95
95
  "monaco-editor": "^0.47.0",
96
- "node-clipboardy": "^1.0.3",
97
96
  "node-localstorage": "^3.0.5",
98
97
  "qtip2": "^3.0.3",
99
98
  "spectrum-colorpicker2": "^2.0.10",
100
99
  "string-similarity": "^4.0.4",
101
100
  "tweakpane": "^3.1.10",
102
101
  "update-electron-app": "^3.0.0",
103
- "x_ite": "^9.3.1"
102
+ "x_ite": "^9.3.2"
104
103
  },
105
104
  "config": {
106
105
  "forge": {
@@ -3,7 +3,6 @@
3
3
  const
4
4
  electron = require ("electron"),
5
5
  prompt = require ("electron-prompt"),
6
- clipboardy = require ("node-clipboardy"),
7
6
  url = require ("url"),
8
7
  path = require ("path"),
9
8
  fs = require ("fs"),
@@ -17,11 +16,11 @@ const localStorage = new LocalStorage (path .join (electron .app .getPath ("user
17
16
 
18
17
  module .exports = class Application
19
18
  {
20
- config = new DataStorage (localStorage, "Sunrize.Application.");
21
- receivedFiles = [ ];
22
- mainMenu = [ ];
23
- openURLValue = "";
24
- exportPath = new Map ();
19
+ config = new DataStorage (localStorage, "Sunrize.Application.");
20
+ receivedFiles = [ ];
21
+ mainMenu = [ ];
22
+ openLocationValue = "";
23
+ exportPath = new Map ();
25
24
 
26
25
  static run ()
27
26
  {
@@ -63,7 +62,7 @@ module .exports = class Application
63
62
  size: [1100, 680],
64
63
  maximized: false,
65
64
  fullscreen: false,
66
- autoSave: false,
65
+ autoSave: true,
67
66
  expandExternProtoDeclarations: true,
68
67
  expandPrototypeInstances: true,
69
68
  expandInlineNodes: true,
@@ -87,7 +86,7 @@ module .exports = class Application
87
86
  electron .ipcMain .on ("title", (event, title) => this .title = title);
88
87
  electron .ipcMain .on ("current-file", (event, currentFile) => this .currentFile = currentFile);
89
88
  electron .ipcMain .on ("add-recent-document", (event, filePath) => this .addRecentDocument (filePath));
90
- electron .ipcMain .on ("update-menu", (event, object) => this .updateMenu (object));
89
+ electron .ipcMain .on ("update-menu", (event, options) => this .updateMenu (options));
91
90
  electron .ipcMain .on ("context-menu", (event, id, menu) => this .contextMenu (id, menu));
92
91
 
93
92
  electron .ipcMain .handle ("open-files", async (event, urls) => this .openFiles (urls));
@@ -153,17 +152,22 @@ module .exports = class Application
153
152
  electron .Menu .setApplicationMenu (this .mainMenu .at (-1));
154
153
  }
155
154
 
156
- updateMenu (object = { })
155
+ updateMenu (options = { })
157
156
  {
158
- Object .assign (this .menuOptions, object);
157
+ Object .assign (this .menuOptions, options);
159
158
 
160
159
  const exportPath = this .exportPath .get (this .currentFile);
161
160
 
162
161
  const menu = electron .Menu .buildFromTemplate (this .filterSeparators ([
163
- {
164
- role: "appMenu",
165
- label: electron .app .getName (),
166
- },
162
+ ... process .platform === "darwin" ?
163
+ [
164
+ {
165
+ role: "appMenu",
166
+ label: electron .app .getName (),
167
+ },
168
+ ]
169
+ :
170
+ [ ],
167
171
  {
168
172
  role: "fileMenu",
169
173
  submenu: [
@@ -194,27 +198,22 @@ module .exports = class Application
194
198
  accelerator: "Shift+CmdOrCtrl+O",
195
199
  click: async () =>
196
200
  {
197
- const clipboard = await this .clipboard ();
201
+ const clipboard = electron .clipboard .readText ();
198
202
 
199
- this .pushMenu (electron .Menu .buildFromTemplate ([
200
- {
201
- role: "appMenu",
202
- label: electron .app .getName (),
203
- },
204
- { role: "editMenu" },
205
- ]));
203
+ this .pushMenu (this .createDialogMenu ());
206
204
 
207
205
  const response = await prompt ({
208
- title: "Open URL...",
209
- label: "Enter URL for opening in new tab:",
206
+ title: _("Open Location..."),
207
+ label: _("Enter a URL to open in a new tab:"),
210
208
  type: "input",
211
- value: clipboard .match (/^(?:https?|file|ftp|smb):\/\/.+/) ? clipboard : this .openURLValue,
209
+ value: clipboard .match (/^(?:https?|file|ftp|smb):\/\/.+/) ? clipboard : this .openLocationValue,
212
210
  inputAttrs: {
213
211
  type: "url",
214
212
  placeholder: "https://example.org",
215
213
  },
216
214
  width: 500,
217
215
  customStylesheet: path .join (__dirname, "../assets/themes/prompt.css"),
216
+ showWhenReady: true,
218
217
  },
219
218
  this .mainWindow);
220
219
 
@@ -223,7 +222,7 @@ module .exports = class Application
223
222
  if (response === null)
224
223
  return;
225
224
 
226
- this .openFiles ([this .openURLValue = response]);
225
+ this .openFiles ([this .openLocationValue = response]);
227
226
  },
228
227
  },
229
228
  {
@@ -307,14 +306,14 @@ module .exports = class Application
307
306
  {
308
307
  label: util .format (_("Export As %s"), path .basename (exportPath)),
309
308
  accelerator: "CmdOrCtrl+E",
310
- click: async () =>
309
+ click: () =>
311
310
  {
312
- const exportPath = this .exportPath .get (this .currentFile);
313
-
314
311
  this .mainWindow .webContents .send ("export-as", exportPath);
315
312
  },
316
313
  }
317
- ] : [ ],
314
+ ]
315
+ :
316
+ [ ],
318
317
  {
319
318
  label: _("Export As..."),
320
319
  accelerator: "Shift+CmdOrCtrl+E",
@@ -352,9 +351,64 @@ module .exports = class Application
352
351
  this .mainWindow .webContents .send ("close");
353
352
  },
354
353
  },
354
+ ... process .platform === "darwin" ?
355
+ [ ]
356
+ :
357
+ [{ role: "quit" }],
355
358
  ],
356
359
  },
357
- this .menuOptions .defaultEditMenu ? { role: "editMenu" } :
360
+ this .menuOptions .defaultEditMenu ?
361
+ {
362
+ role: "editMenu",
363
+ submenu: [
364
+ { role: "undo" },
365
+ { role: "redo" },
366
+ { type: "separator" },
367
+ { role: "cut" },
368
+ { role: "copy" },
369
+ { role: "paste" },
370
+ ... process .platform === "darwin" ?
371
+ [
372
+ { role: "pasteAndMatchStyle" },
373
+ { role: "delete" },
374
+ { role: "selectAll" },
375
+ { type: "separator" },
376
+ {
377
+ label: _("Speech"),
378
+ submenu: [
379
+ { role: "startSpeaking" },
380
+ { role: "stopSpeaking" },
381
+ ]
382
+ },
383
+ ]
384
+ :
385
+ [
386
+ { role: "delete" },
387
+ { type: "separator" },
388
+ { role: "selectAll" },
389
+ ],
390
+ { type: "separator" },
391
+ {
392
+ label: _("Toggle Line Comment"),
393
+ accelerator: process .platform === "darwin" ? "CmdOrCtrl+Shift+7" : "CmdOrCtrl+#",
394
+ enabled: this .menuOptions .monacoEditor,
395
+ click: () =>
396
+ {
397
+ this .mainWindow .webContents .send ("script-editor", "runAction", "editor.action.commentLine");
398
+ },
399
+ },
400
+ {
401
+ label: _("Toggle Block Comment"),
402
+ accelerator: "Alt+Shift+A",
403
+ enabled: this .menuOptions .monacoEditor,
404
+ click: () =>
405
+ {
406
+ this .mainWindow .webContents .send ("script-editor", "runAction", "editor.action.blockComment");
407
+ },
408
+ },
409
+ ]
410
+ }
411
+ :
358
412
  {
359
413
  role: "editMenu",
360
414
  submenu: [
@@ -463,7 +517,7 @@ module .exports = class Application
463
517
  visible: process .env .SUNRISE_ENVIRONMENT === "DEVELOPMENT",
464
518
  },
465
519
  {
466
- label: "Reload Tab",
520
+ label: _("Reload Tab"),
467
521
  visible: process .env .SUNRISE_ENVIRONMENT === "DEVELOPMENT",
468
522
  click: () =>
469
523
  {
@@ -471,7 +525,7 @@ module .exports = class Application
471
525
  },
472
526
  },
473
527
  {
474
- label: "Toggle Tab Developer Tools",
528
+ label: _("Toggle Tab Developer Tools"),
475
529
  visible: process .env .SUNRISE_ENVIRONMENT === "DEVELOPMENT",
476
530
  click: () =>
477
531
  {
@@ -613,7 +667,7 @@ module .exports = class Application
613
667
  ],
614
668
  },
615
669
  {
616
- label: "Layout",
670
+ label: _("Layout"),
617
671
  submenu: [
618
672
  {
619
673
  label: _("Browser Frame..."),
@@ -707,22 +761,52 @@ module .exports = class Application
707
761
  ],
708
762
  },
709
763
  ... process .platform === "darwin" ?
710
- [{
711
- role: "window",
712
- submenu: [ ],
713
- }]
764
+ [
765
+ {
766
+ role: "window",
767
+ submenu: [ ],
768
+ },
769
+ ]
714
770
  :
715
- [],
771
+ [ ],
716
772
  {
717
773
  role: "help",
718
774
  submenu: [
719
775
  {
720
- label: "Learn More",
776
+ label: _("Learn More"),
721
777
  click: () =>
722
778
  {
723
779
  electron .shell .openExternal ("https://create3000.github.io/sunrize/");
724
780
  },
725
781
  },
782
+ {
783
+ label: _("A Quick Look at the User Interface"),
784
+ click: () =>
785
+ {
786
+ electron .shell .openExternal ("https://create3000.github.io/sunrize/documentation/a-quick-look-at-the-user-interface/");
787
+ },
788
+ },
789
+ {
790
+ label: _("How to Navigate in a Scene"),
791
+ click: () =>
792
+ {
793
+ electron .shell .openExternal ("https://create3000.github.io/x_ite/tutorials/how-to-navigate-in-a-scene/");
794
+ },
795
+ },
796
+ {
797
+ label: _("Using the Outline Editor"),
798
+ click: () =>
799
+ {
800
+ electron .shell .openExternal ("https://create3000.github.io/sunrize/documentation/using-the-outline-editor/");
801
+ },
802
+ },
803
+ {
804
+ label: _("Using the Script Editor"),
805
+ click: () =>
806
+ {
807
+ electron .shell .openExternal ("https://create3000.github.io/sunrize/documentation/using-the-script-editor/");
808
+ },
809
+ },
726
810
  ],
727
811
  },
728
812
  ]));
@@ -733,10 +817,29 @@ module .exports = class Application
733
817
  electron .Menu .setApplicationMenu (menu);
734
818
  }
735
819
 
736
- async createWindow ()
820
+ createDialogMenu ()
737
821
  {
738
- this .appIcon = new electron .Tray (path .join (__dirname, "../assets/images/icon.png"));
822
+ return electron .Menu .buildFromTemplate ([
823
+ ... process .platform === "darwin" ?
824
+ [
825
+ {
826
+ role: "appMenu",
827
+ label: electron .app .getName (),
828
+ },
829
+ ]
830
+ :
831
+ [
832
+ {
833
+ role: "fileMenu",
834
+ submenu: [{ role: "quit" }],
835
+ }
836
+ ],
837
+ { role: "editMenu" },
838
+ ]);
839
+ }
739
840
 
841
+ async createWindow ()
842
+ {
740
843
  const window = new electron .BrowserWindow ({
741
844
  icon: path .join (__dirname, "../assets/images/icon.png"),
742
845
  x: this .config .position [0],
@@ -787,25 +890,21 @@ module .exports = class Application
787
890
 
788
891
  contextMenu (id, menu)
789
892
  {
790
- electron .Menu .buildFromTemplate (this .createMenuTemplate (id, menu))
893
+ electron .Menu .buildFromTemplate (this .addMenuItemHandlers (id, this .filterSeparators (menu)))
791
894
  .popup ({ window: this .mainWindow });
792
895
  }
793
896
 
794
- createMenuTemplate (id, menu)
897
+ addMenuItemHandlers (id, menu)
795
898
  {
796
- const template = [ ];
797
-
798
- for (const menuItem of this .filterSeparators (menu))
899
+ for (const menuItem of menu)
799
900
  {
800
901
  if (menuItem .submenu)
801
- menuItem .submenu = this .createMenuTemplate (id, menuItem .submenu);
902
+ this .addMenuItemHandlers (id, menuItem .submenu);
802
903
  else
803
904
  menuItem .click = () => this .mainWindow .webContents .send (id, ... menuItem .args);
804
-
805
- template .push (menuItem);
806
905
  }
807
906
 
808
- return template;
907
+ return menu;
809
908
  }
810
909
 
811
910
  filterSeparators (menu)
@@ -875,13 +974,7 @@ module .exports = class Application
875
974
 
876
975
  async showOpenDialog (defaultPath, filters)
877
976
  {
878
- this .pushMenu (electron .Menu .buildFromTemplate ([
879
- {
880
- role: "appMenu",
881
- label: electron .app .getName (),
882
- },
883
- { role: "editMenu" },
884
- ]));
977
+ this .pushMenu (this .createDialogMenu ());
885
978
 
886
979
  const response = await electron .dialog .showOpenDialog ({
887
980
  defaultPath: defaultPath,
@@ -906,13 +999,7 @@ module .exports = class Application
906
999
 
907
1000
  async showSaveDialog (defaultPath)
908
1001
  {
909
- this .pushMenu (electron .Menu .buildFromTemplate ([
910
- {
911
- role: "appMenu",
912
- label: electron .app .getName (),
913
- },
914
- { role: "editMenu" },
915
- ]));
1002
+ this .pushMenu (this .createDialogMenu ());
916
1003
 
917
1004
  const response = await electron .dialog .showSaveDialog ({
918
1005
  defaultPath: defaultPath,
@@ -934,13 +1021,7 @@ module .exports = class Application
934
1021
 
935
1022
  async showExportDialog (defaultPath)
936
1023
  {
937
- this .pushMenu (electron .Menu .buildFromTemplate ([
938
- {
939
- role: "appMenu",
940
- label: electron .app .getName (),
941
- },
942
- { role: "editMenu" },
943
- ]));
1024
+ this .pushMenu (this .createDialogMenu ());
944
1025
 
945
1026
  const response = await electron .dialog .showSaveDialog ({
946
1027
  defaultPath: defaultPath,
@@ -999,18 +1080,6 @@ module .exports = class Application
999
1080
  }
1000
1081
  }
1001
1082
 
1002
- async clipboard ()
1003
- {
1004
- try
1005
- {
1006
- return await clipboardy .read ();
1007
- }
1008
- catch
1009
- {
1010
- return "";
1011
- }
1012
- }
1013
-
1014
1083
  quit ()
1015
1084
  {
1016
1085
  if (!this .applicationShouldQuitAfterLastWindowClosed)
@@ -20,6 +20,8 @@ module .exports = class Dashboard extends Interface
20
20
 
21
21
  async initialize ()
22
22
  {
23
+ this .browser .getLive () .addInterest ("updatePlay", this);
24
+
23
25
  this .handButton = $("<span></span>")
24
26
  .addClass (["image-icon", "hand"])
25
27
  .attr ("title", _("Switch to browser mode."))
@@ -75,7 +77,7 @@ module .exports = class Dashboard extends Interface
75
77
  });
76
78
 
77
79
  this [this .config .file .pointer] ();
78
- this .play (this .config .file .play);
80
+ this .play (this .config .file .play && !this .isInitialScene);
79
81
  this .straighten (this .browser .getBrowserOption ("StraightenHorizon"));
80
82
 
81
83
  if (this .config .file .panel)
@@ -113,15 +115,17 @@ module .exports = class Dashboard extends Interface
113
115
  this .config .file .play = value;
114
116
 
115
117
  if (value)
116
- {
117
- this .playButton .addClass ("active");
118
118
  this .browser .beginUpdate ();
119
- }
120
119
  else
121
- {
122
- this .playButton .removeClass ("active");
123
120
  this .browser .endUpdate ();
124
- }
121
+ }
122
+
123
+ updatePlay ()
124
+ {
125
+ if (this .browser .isLive ())
126
+ this .playButton .addClass ("active");
127
+ else
128
+ this .playButton .removeClass ("active");
125
129
  }
126
130
 
127
131
  viewAll ()
@@ -1,80 +1,79 @@
1
- // Cannot use strict.
2
- //"use strict"
1
+ "use strict";
3
2
 
4
3
  const
5
4
  storages = new WeakMap (),
6
5
  namespaces = new WeakMap (),
7
- defaults = new WeakMap ()
6
+ defaults = new WeakMap ();
8
7
 
9
8
  const handler =
10
9
  {
11
10
  get (target, key)
12
11
  {
13
- const property = target [key]
12
+ const property = target [key];
14
13
 
15
14
  if (property !== undefined)
16
- return property
15
+ return property;
17
16
 
18
17
  const
19
18
  storage = target .getStorage (),
20
19
  namespace = target .getNameSpace (),
21
- value = storage [namespace + key]
20
+ value = storage [namespace + key];
22
21
 
23
- if (value === undefined || value === "undefined" || value === null)
24
- return target .getDefaultValue (key)
22
+ if (String (value) .match (/^(?:undefined|null)$/))
23
+ return target .getDefaultValue (key);
25
24
 
26
25
  // Update timestamp.
27
- storage [namespace + key + ".#timeStamp"] = JSON .stringify (Date .now ())
26
+ storage [namespace + key + ".#timeStamp"] = JSON .stringify (Date .now ());
28
27
 
29
- return JSON .parse (value)
28
+ return JSON .parse (value);
30
29
  },
31
30
  set (target, key, value)
32
31
  {
33
32
  const
34
33
  storage = target .getStorage (),
35
- namespace = target .getNameSpace ()
34
+ namespace = target .getNameSpace ();
36
35
 
37
36
  if (value === undefined)
38
37
  {
39
- storage .removeItem (namespace + key + ".#timeStamp")
40
- storage .removeItem (namespace + key)
38
+ storage .removeItem (namespace + key + ".#timeStamp");
39
+ storage .removeItem (namespace + key);
41
40
  }
42
41
  else
43
42
  {
44
- storage [namespace + key + ".#timeStamp"] = JSON .stringify (Date .now ())
45
- storage [namespace + key] = JSON .stringify (value)
43
+ storage [namespace + key + ".#timeStamp"] = JSON .stringify (Date .now ());
44
+ storage [namespace + key] = JSON .stringify (value);
46
45
  }
47
46
 
48
- return true
47
+ return true;
49
48
  },
50
49
  has (target, key)
51
50
  {
52
- const value = target .getStorage () [target .getNameSpace () + key]
51
+ const value = target .getStorage () [target .getNameSpace () + key];
53
52
 
54
- return !(value === undefined || value === "undefined" || value === null)
53
+ return !(value === undefined || value === "undefined" || value === null);
55
54
  },
56
55
  ownKeys (target)
57
56
  {
58
57
  const
59
58
  storage = target .getStorage (),
60
59
  namespace = target .getNameSpace (),
61
- ownKeys = [ ]
60
+ ownKeys = [ ];
62
61
 
63
62
  for (const key of Object .keys (storage))
64
63
  {
65
64
  if (key .startsWith (namespace) && !key .endsWith (".#timeStamp"))
66
- ownKeys .push (key .substring (namespace .length))
65
+ ownKeys .push (key .substring (namespace .length));
67
66
  }
68
67
 
69
- return ownKeys
68
+ return ownKeys;
70
69
  },
71
70
  getOwnPropertyDescriptor (target, key)
72
71
  {
73
72
  const
74
73
  storage = target .getStorage (),
75
- namespace = target .getNameSpace ()
74
+ namespace = target .getNameSpace ();
76
75
 
77
- return Object .getOwnPropertyDescriptor (storage, namespace + key)
76
+ return Object .getOwnPropertyDescriptor (storage, namespace + key);
78
77
  },
79
78
  }
80
79
 
@@ -82,13 +81,13 @@ module .exports = class DataStorage
82
81
  {
83
82
  constructor (storage, namespace)
84
83
  {
85
- this .target = this
84
+ this .target = this;
86
85
 
87
- storages .set (this, storage)
88
- namespaces .set (this, namespace)
89
- defaults .set (this, { })
86
+ storages .set (this, storage);
87
+ namespaces .set (this, namespace);
88
+ defaults .set (this, { });
90
89
 
91
- return new Proxy (this, handler)
90
+ return new Proxy (this, handler);
92
91
  }
93
92
 
94
93
  /**
@@ -97,7 +96,7 @@ module .exports = class DataStorage
97
96
  */
98
97
  getStorage ()
99
98
  {
100
- return storages .get (this .target)
99
+ return storages .get (this .target);
101
100
  }
102
101
 
103
102
  /**
@@ -106,7 +105,7 @@ module .exports = class DataStorage
106
105
  */
107
106
  getNameSpace ()
108
107
  {
109
- return namespaces .get (this .target)
108
+ return namespaces .get (this .target);
110
109
  }
111
110
 
112
111
  /**
@@ -116,7 +115,7 @@ module .exports = class DataStorage
116
115
  */
117
116
  addNameSpace (namespace)
118
117
  {
119
- return new DataStorage (this .getStorage (), this .getNameSpace () + namespace)
118
+ return new DataStorage (this .getStorage (), this .getNameSpace () + namespace);
120
119
  }
121
120
 
122
121
  /**
@@ -125,7 +124,7 @@ module .exports = class DataStorage
125
124
  */
126
125
  setDefaultValues (object)
127
126
  {
128
- Object .assign (defaults .get (this .target), object)
127
+ Object .assign (defaults .get (this .target), object);
129
128
  }
130
129
 
131
130
  /**
@@ -134,7 +133,7 @@ module .exports = class DataStorage
134
133
  */
135
134
  getDefaultValues ()
136
135
  {
137
- return Object .assign ({ }, defaults .get (this .target))
136
+ return Object .assign ({ }, defaults .get (this .target));
138
137
  }
139
138
 
140
139
  /**
@@ -144,9 +143,9 @@ module .exports = class DataStorage
144
143
  */
145
144
  getDefaultValue (key)
146
145
  {
147
- const value = defaults .get (this .target) [key]
146
+ const value = defaults .get (this .target) [key];
148
147
 
149
- return value === undefined ? undefined : JSON .parse (JSON .stringify (value))
148
+ return value === undefined ? undefined : JSON .parse (JSON .stringify (value));
150
149
  }
151
150
 
152
151
  /**
@@ -157,18 +156,18 @@ module .exports = class DataStorage
157
156
  {
158
157
  const
159
158
  storage = this .getStorage (),
160
- namespace = this .getNameSpace ()
159
+ namespace = this .getNameSpace ();
161
160
 
162
161
  for (const key of Object .keys (storage))
163
162
  {
164
163
  if (key .startsWith (namespace) && !key .endsWith (".#timeStamp"))
165
164
  {
166
- const timeStamp = JSON .parse (storage [key + ".#timeStamp"])
165
+ const timeStamp = JSON .parse (storage [key + ".#timeStamp"]);
167
166
 
168
167
  if (timeStamp < before)
169
168
  {
170
- storage .removeItem (key + ".#timeStamp")
171
- storage .removeItem (key)
169
+ storage .removeItem (key + ".#timeStamp");
170
+ storage .removeItem (key);
172
171
  }
173
172
  }
174
173
  }
@@ -178,12 +177,12 @@ module .exports = class DataStorage
178
177
  {
179
178
  const
180
179
  storage = this .getStorage (),
181
- namespace = this .getNameSpace ()
180
+ namespace = this .getNameSpace ();
182
181
 
183
182
  for (const key of Object .keys (storage))
184
183
  {
185
184
  if (key .startsWith (namespace))
186
- storage .removeItem (key)
185
+ storage .removeItem (key);
187
186
  }
188
187
  }
189
- }
188
+ };