sunrize 1.11.4 → 1.11.6

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.11.4",
4
+ "version": "1.11.6",
5
5
  "description": "A Multi-Platform X3D Editor",
6
6
  "main": "src/main.js",
7
7
  "bin": {
@@ -91,7 +91,7 @@
91
91
  "@vscode/codicons": "^0.0.41",
92
92
  "capitalize": "^2.0.4",
93
93
  "console": "^0.7.2",
94
- "electron": "^39.0.0",
94
+ "electron": "^39.1.1",
95
95
  "electron-prompt": "^1.7.0",
96
96
  "electron-squirrel-startup": "^1.0.1",
97
97
  "electron-tabs": "^1.0.4",
@@ -100,7 +100,7 @@
100
100
  "jquery-ui-dist": "^1.13.3",
101
101
  "jstree": "^3.3.17",
102
102
  "material-icons": "^1.13.14",
103
- "material-symbols": "^0.38.0",
103
+ "material-symbols": "^0.39.1",
104
104
  "md5": "^2.3.0",
105
105
  "mime-types": "^3.0.1",
106
106
  "monaco-editor": "^0.54.0",
@@ -110,7 +110,7 @@
110
110
  "string-similarity": "^4.0.4",
111
111
  "tweakpane": "^3.1.10",
112
112
  "update-electron-app": "^3.1.1",
113
- "x_ite": "^12.1.4",
113
+ "x_ite": "^12.1.6",
114
114
  "x3d-traverse": "^1.0.22"
115
115
  }
116
116
  }
@@ -55,8 +55,9 @@ module .exports = class Document extends Interface
55
55
  */
56
56
  async initialize ()
57
57
  {
58
- $("html") .attr ("platform", process .platform);
59
- $("body") .addClass ("modal");
58
+ $("html")
59
+ .attr ("platform", process .platform)
60
+ .addClass ("read-only");
60
61
 
61
62
  // Actions
62
63
 
@@ -192,7 +193,7 @@ module .exports = class Document extends Interface
192
193
  await this .restoreFile ();
193
194
 
194
195
  if (!this .isInitialScene)
195
- $("body") .removeClass ("modal");
196
+ $("html") .removeClass ("read-only");
196
197
  }
197
198
 
198
199
  configure ()
@@ -23,7 +23,7 @@ $.fn.exportNodePopover = function (node, oldExportedName)
23
23
 
24
24
  const nameInput = $("<input></input>")
25
25
  .attr ("placeholder", _("Enter exported name"))
26
- .val (oldExportedName ?? scene .getUniqueExportName (node .getName ()))
26
+ .val (oldExportedName || scene .getUniqueExportName (node .getName ()))
27
27
  .appendTo (content);
28
28
 
29
29
  // Create tooltip.
@@ -23,7 +23,7 @@ $.fn.importNodePopover = function (inlineNode, exportedName, oldImportedName)
23
23
 
24
24
  const nameInput = $("<input></input>")
25
25
  .attr ("placeholder", _("Enter imported name"))
26
- .val (oldImportedName ?? executionContext .getUniqueImportName (exportedName))
26
+ .val (oldImportedName || executionContext .getUniqueImportName (exportedName))
27
27
  .appendTo (content);
28
28
 
29
29
  // Create tooltip.
@@ -11,23 +11,12 @@ const
11
11
  module .exports = class Console extends Interface
12
12
  {
13
13
  HISTORY_MAX = 100;
14
- CONSOLE_MAX = 1000;
15
-
16
- logLevels = [
17
- "debug",
18
- "log",
19
- "warn",
20
- "error",
21
- ];
22
-
23
- logClasses = ["", "", "filled", "filled"];
24
14
 
25
15
  constructor (element)
26
16
  {
27
17
  super (`Sunrize.Console.${element .attr ("id")}.`);
28
18
 
29
19
  this .suspendConsole = false;
30
- this .messageTime = 0;
31
20
  this .historyIndex = 0;
32
21
  this .history = [ ];
33
22
  this .addMessageCallback = this .addMessage .bind (this);
@@ -175,6 +164,8 @@ module .exports = class Console extends Interface
175
164
  this .scriptNode .setup ();
176
165
  }
177
166
 
167
+ CONSOLE_MAX = 1000;
168
+
178
169
  // Add strings to exclude here:
179
170
  excludes = [
180
171
  "The vm module of Node.js is unsupported",
@@ -184,41 +175,31 @@ module .exports = class Console extends Interface
184
175
  // "Invalid asm.js: Invalid member of stdlib",
185
176
  ];
186
177
 
178
+ messageTime = 0;
179
+
180
+ logLevels = [
181
+ "debug",
182
+ "log",
183
+ "warn",
184
+ "error",
185
+ ];
186
+
187
187
  addMessage (event, level, sourceId, line, message)
188
188
  {
189
189
  if (this .excludes .some (exclude => message .includes (exclude)))
190
190
  return;
191
191
 
192
- const
193
- classes = [this .logLevels [level] ?? "log", this .logClasses [level]],
194
- title = sourceId ? `${sourceId}:${line}`: "";
195
-
196
- const text = $(message .split ("\n")
197
- .map (line => $("<p></p>")
198
- .addClass (classes)
199
- .attr ("title", title)
200
- .text (line)
201
- .get (0)));
192
+ const text = $("<p></p>")
193
+ .addClass (this .logLevels [level] ?? "log")
194
+ .attr ("title", sourceId ? `${sourceId}:${line}`: "")
195
+ .text (message);
202
196
 
203
- if (this .messageTime && performance .now () - this .messageTime > 1000)
197
+ if (performance .now () - this .messageTime > 1000)
204
198
  this .output .append ($("<p></p>") .addClass ("splitter"));
205
199
 
206
200
  this .messageTime = performance .now ();
207
201
 
208
- const
209
- children = this .output .children (),
210
- last = children .last ();
211
-
212
- if (last .hasClass (this .logLevels [level]))
213
- {
214
- last .css ("margin-bottom", "0");
215
- text .css ("margin-top", "0");
216
- last .css ("border-bottom", "none");
217
- text .css ("border-top", "none");
218
- }
219
-
220
- children .slice (0, Math .max (children .length - this .CONSOLE_MAX, 0)) .remove ();
221
-
202
+ this .output .children (`:not(:nth-last-child(-n+${this .CONSOLE_MAX}))`) .remove ();
222
203
  this .output .append (text);
223
204
  this .output .scrollTop (this .output .prop ("scrollHeight"));
224
205
 
@@ -2154,7 +2154,7 @@ module .exports = class OutlineView extends Interface
2154
2154
  let index = 0;
2155
2155
 
2156
2156
  for (const node of field)
2157
- ul .append (this .createNodeElement ("node", parent, node .getValue (), index ++));
2157
+ ul .append (this .createNodeElement ("node", parent, node ?.getValue (), index ++));
2158
2158
 
2159
2159
  // Make jsTree.
2160
2160
 
@@ -2787,15 +2787,37 @@ module .exports = class OutlineView extends Interface
2787
2787
 
2788
2788
  nodeCloseClones (element)
2789
2789
  {
2790
- const opened = this .sceneGraph .find (`.node[node-id=${element .attr ("node-id")}],
2791
- .imported-node[node-id=${element .attr ("node-id")}],
2792
- .exported-node[node-id=${element .attr ("node-id")}]`);
2790
+ const ids = [parseInt (element .attr ("node-id"))];
2793
2791
 
2794
- opened .each (function (key, value)
2792
+ if (this .getNode (element) instanceof X3D .X3DImportedNodeProxy)
2795
2793
  {
2796
- if (value !== element .get (0))
2797
- $(value) .jstree ("close_node", value);
2798
- })
2794
+ // Close nodes.
2795
+
2796
+ ids .push ($.try (() => this .getNode (element) .getInnerNode () .getId ()));
2797
+ }
2798
+ else
2799
+ {
2800
+ // Close imported nodes.
2801
+
2802
+ const executionContext = this .getNode (element) .getScene () ?.getScene ()
2803
+ ?? this .executionContext;
2804
+
2805
+ const importedNode = executionContext .importedNodes
2806
+ .find (importedNode => $.try (() => importedNode .getExportedNode () .getInnerNode () .getId ()) === ids [0]);
2807
+
2808
+ ids .push (importedNode ?.getExportedNode () .getId ());
2809
+ }
2810
+
2811
+ for (const id of ids)
2812
+ {
2813
+ const opened = this .sceneGraph .find (`:is(.node, .imported-node, .exported-node)[node-id="${id}"]`);
2814
+
2815
+ opened .each (function (key, value)
2816
+ {
2817
+ if (value !== element .get (0))
2818
+ $(value) .jstree ("close_node", value);
2819
+ });
2820
+ }
2799
2821
  }
2800
2822
 
2801
2823
  fieldBeforeOpen (event, leaf)
@@ -2,6 +2,7 @@
2
2
 
3
3
  const
4
4
  $ = require ("jquery"),
5
+ electron = require ("electron"),
5
6
  capitalize = require ("capitalize"),
6
7
  Dialog = require ("../Controls/Dialog"),
7
8
  Tabs = require ("../Controls/Tabs"),
@@ -10,7 +11,6 @@ const
10
11
  Editor = require ("../Undo/Editor"),
11
12
  UndoManager = require ("../Undo/UndoManager"),
12
13
  _ = require ("../Application/GetText");
13
- const { height } = require("../Bits/X3DUOM");
14
14
 
15
15
  require ("../Fields");
16
16
 
@@ -472,6 +472,7 @@ module .exports = new class SceneProperties extends Dialog
472
472
  .attr ("placeholder", _("Insert meta key here."))
473
473
  .val (key) .on ("change", (event) => this .changeMetaData (event, key))))
474
474
  .append ($("<td></td>")
475
+ .addClass ("meta-value")
475
476
  .append ($("<input></input>")
476
477
  .attr ("index", 1)
477
478
  .attr ("placeholder", _("Insert meta value here."))
@@ -485,6 +486,27 @@ module .exports = new class SceneProperties extends Dialog
485
486
  .text ("delete_forever")
486
487
  .on ("click", (event) => this .removeMetaData (event, key))));
487
488
 
489
+ // Add Open Link in Browser button if it matches a link somewhere in value.
490
+ {
491
+ const
492
+ http = /(https?:\/\/(?:www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b(?:[-a-zA-Z0-9()@:%_\+.~#?&\/=]*))/,
493
+ match = value .match (http);
494
+
495
+ if (match)
496
+ {
497
+ const column = row .find ("input[index=1]") .parent ();
498
+
499
+ $("<span></span>")
500
+ .addClass ("open-link")
501
+ .attr ("title", _("Open link in web browser."))
502
+ .css ("font-size", "120%")
503
+ .addClass (["material-icons", "button"])
504
+ .text ("open_in_new")
505
+ .appendTo (column)
506
+ .on ("click", () => electron .shell .openExternal (match [1]));
507
+ }
508
+ }
509
+
488
510
  rows .push (row);
489
511
  }
490
512
 
@@ -1986,98 +1986,126 @@ ${scene .toXMLString ({ html: true, indent: " " .repeat (6) }) .trimEnd () }
1986
1986
  {
1987
1987
  node = node .valueOf ();
1988
1988
 
1989
+ undoManager .beginUndo (_("Update Field %s of Node %s"), field .getName (), node .getTypeName ());
1990
+
1991
+ if (name !== field .getName ())
1992
+ this .#renameField (executionContext, node, field, name, undoManager);
1993
+
1994
+ if (accessType !== field .getAccessType ())
1995
+ this .#changeAccessType (executionContext, node, field, accessType, undoManager);
1996
+
1997
+ undoManager .endUndo ();
1998
+ }
1999
+
2000
+ static #renameField (executionContext, node, field, name, undoManager = UndoManager .shared)
2001
+ {
2002
+ node = node .valueOf ();
2003
+
1989
2004
  const
1990
- oldAccessType = field .getAccessType (),
1991
- oldName = field .getName (),
1992
- fields = Array .from (node .getUserDefinedFields ());
2005
+ oldName = field .getName (),
2006
+ fields = Array .from (node .getUserDefinedFields ()),
2007
+ inputRoutes = Array .from (field .getInputRoutes ()),
2008
+ outputRoutes = Array .from (field .getOutputRoutes ());
1993
2009
 
1994
- undoManager .beginUndo (_("Update Fields of Node %s"), node .getTypeName ());
2010
+ undoManager .beginUndo (_("Rename Field"));
2011
+
2012
+ for (const route of inputRoutes)
2013
+ route .getExecutionContext () .deleteRoute (route);
2014
+
2015
+ for (const route of outputRoutes)
2016
+ route .getExecutionContext () .deleteRoute (route);
1995
2017
 
1996
2018
  for (const field of fields)
1997
2019
  node .removeUserDefinedField (field .getName ());
1998
2020
 
1999
- field .setAccessType (accessType);
2000
2021
  field .setName (name);
2001
2022
 
2002
2023
  for (const field of fields)
2003
2024
  node .addUserDefinedField (field .getAccessType (), field .getName (), field);
2004
2025
 
2005
- if (accessType !== oldAccessType)
2026
+ if (field .isInput ())
2006
2027
  {
2007
- if (node instanceof X3D .X3DProtoDeclaration)
2008
- {
2009
- const
2010
- proto = node,
2011
- updatedField = field;
2028
+ for (const route of inputRoutes)
2029
+ route .getExecutionContext () .addRoute (route .sourceNode, route .sourceField, route .destinationNode, name);
2030
+ }
2012
2031
 
2013
- for (const object of proto .traverse (Traverse .PROTO_DECLARATIONS | Traverse .PROTO_DECLARATION_BODY | Traverse .ROOT_NODES))
2014
- {
2015
- if (!(object instanceof X3D .SFNode))
2016
- continue;
2032
+ if (field .isOutput ())
2033
+ {
2034
+ for (const route of outputRoutes)
2035
+ route .getExecutionContext () .addRoute (route .sourceNode, name, route .destinationNode, route .destinationField);
2036
+ }
2017
2037
 
2018
- const node = object .getValue ();
2038
+ undoManager .registerUndo (() =>
2039
+ {
2040
+ this .#renameField (executionContext, node, field, oldName, undoManager);
2041
+ });
2019
2042
 
2020
- for (const field of node .getFields ())
2021
- {
2022
- // Remove references.
2043
+ this .requestUpdateInstances (node, undoManager);
2023
2044
 
2024
- if (field .getReferences () .has (updatedField))
2025
- {
2026
- if (!updatedField .isReference (field .getAccessType ()))
2027
- this .removeReference (proto, updatedField, node, field, undoManager);
2028
- }
2029
- }
2030
- }
2045
+ undoManager .endUndo ();
2046
+ }
2031
2047
 
2032
- // Remove routes.
2048
+ static #changeAccessType (executionContext, node, field, accessType, undoManager = UndoManager .shared)
2049
+ {
2050
+ node = node .valueOf ();
2033
2051
 
2034
- for (const object of executionContext .traverse (Traverse .PROTO_DECLARATIONS | Traverse .PROTO_DECLARATION_BODY | Traverse .ROOT_NODES))
2035
- {
2036
- if (!(object instanceof X3D .SFNode))
2037
- continue;
2052
+ const
2053
+ oldAccessType = field .getAccessType (),
2054
+ fields = Array .from (node .getUserDefinedFields ());
2038
2055
 
2039
- const node = object .getValue ();
2056
+ undoManager .beginUndo (_("Change AccessType"));
2040
2057
 
2041
- if (!node .getType () .includes (X3D .X3DConstants .X3DPrototypeInstance))
2042
- continue;
2058
+ for (const field of fields)
2059
+ node .removeUserDefinedField (field .getName ());
2043
2060
 
2044
- if (node .getProtoNode () !== proto)
2045
- continue;
2061
+ field .setAccessType (accessType);
2046
2062
 
2047
- const field = node .getField (oldName);
2063
+ for (const field of fields)
2064
+ node .addUserDefinedField (field .getAccessType (), field .getName (), field);
2048
2065
 
2049
- if (!updatedField .isInput ())
2050
- {
2051
- for (const route of field .getInputRoutes ())
2052
- {
2053
- this .deleteRoute (route .getExecutionContext (), route .sourceNode, route .sourceField, route .destinationNode, route .destinationField, undoManager);
2054
- }
2055
- }
2066
+ if (node instanceof X3D .X3DProtoDeclaration)
2067
+ {
2068
+ const
2069
+ proto = node,
2070
+ updatedField = field;
2056
2071
 
2057
- if (!updatedField .isOutput ())
2072
+ for (const object of proto .traverse (Traverse .PROTO_DECLARATIONS | Traverse .PROTO_DECLARATION_BODY | Traverse .ROOT_NODES))
2073
+ {
2074
+ if (!(object instanceof X3D .SFNode))
2075
+ continue;
2076
+
2077
+ const node = object .getValue ();
2078
+
2079
+ for (const field of node .getFields ())
2080
+ {
2081
+ // Remove references.
2082
+
2083
+ if (field .getReferences () .has (updatedField))
2058
2084
  {
2059
- for (const route of field .getOutputRoutes ())
2060
- {
2061
- this .deleteRoute (route .getExecutionContext (), route .sourceNode, route .sourceField, route .destinationNode, route .destinationField, undoManager);
2062
- }
2085
+ if (!updatedField .isReference (field .getAccessType ()))
2086
+ this .removeReference (proto, updatedField, node, field, undoManager);
2063
2087
  }
2064
2088
  }
2065
-
2066
- this .updateInstances (proto, undoManager);
2067
2089
  }
2068
- else
2090
+
2091
+ // Remove routes.
2092
+
2093
+ for (const object of executionContext .traverse (Traverse .PROTO_DECLARATIONS | Traverse .PROTO_DECLARATION_BODY | Traverse .ROOT_NODES))
2069
2094
  {
2070
- // Remove References.
2095
+ if (!(object instanceof X3D .SFNode))
2096
+ continue;
2071
2097
 
2072
- for (const reference of field .getReferences ())
2073
- {
2074
- if (!reference .isReference (field .getAccessType ()))
2075
- this .removeReference (proto, reference, node, field, undoManager);
2076
- }
2098
+ const node = object .getValue ();
2077
2099
 
2078
- // Remove routes.
2100
+ if (!node .getType () .includes (X3D .X3DConstants .X3DPrototypeInstance))
2101
+ continue;
2102
+
2103
+ if (node .getProtoNode () !== proto)
2104
+ continue;
2105
+
2106
+ const field = node .getField (oldName);
2079
2107
 
2080
- if (!field .isInput ())
2108
+ if (!updatedField .isInput ())
2081
2109
  {
2082
2110
  for (const route of field .getInputRoutes ())
2083
2111
  {
@@ -2085,7 +2113,7 @@ ${scene .toXMLString ({ html: true, indent: " " .repeat (6) }) .trimEnd () }
2085
2113
  }
2086
2114
  }
2087
2115
 
2088
- if (!field .isOutput ())
2116
+ if (!updatedField .isOutput ())
2089
2117
  {
2090
2118
  for (const route of field .getOutputRoutes ())
2091
2119
  {
@@ -2093,11 +2121,46 @@ ${scene .toXMLString ({ html: true, indent: " " .repeat (6) }) .trimEnd () }
2093
2121
  }
2094
2122
  }
2095
2123
  }
2124
+
2125
+ this .updateInstances (proto, undoManager);
2126
+ }
2127
+ else
2128
+ {
2129
+ const
2130
+ references = Array .from (field .getReferences ()),
2131
+ inputRoutes = Array .from (field .getInputRoutes ()),
2132
+ outputRoutes = Array .from (field .getOutputRoutes ());
2133
+
2134
+ // Remove References.
2135
+
2136
+ for (const reference of references)
2137
+ {
2138
+ if (!reference .isReference (field .getAccessType ()))
2139
+ this .removeReference (proto, reference, node, field, undoManager);
2140
+ }
2141
+
2142
+ // Remove routes.
2143
+
2144
+ if (!field .isInput ())
2145
+ {
2146
+ for (const route of inputRoutes)
2147
+ {
2148
+ this .deleteRoute (route .getExecutionContext (), route .sourceNode, route .sourceField, route .destinationNode, route .destinationField, undoManager);
2149
+ }
2150
+ }
2151
+
2152
+ if (!field .isOutput ())
2153
+ {
2154
+ for (const route of outputRoutes)
2155
+ {
2156
+ this .deleteRoute (route .getExecutionContext (), route .sourceNode, route .sourceField, route .destinationNode, route .destinationField, undoManager);
2157
+ }
2158
+ }
2096
2159
  }
2097
2160
 
2098
2161
  undoManager .registerUndo (() =>
2099
2162
  {
2100
- this .updateUserDefinedField (executionContext, node, field, oldAccessType, oldName, undoManager);
2163
+ this .#changeAccessType (executionContext, node, field, oldAccessType, undoManager);
2101
2164
  });
2102
2165
 
2103
2166
  this .requestUpdateInstances (node, undoManager);
@@ -93,7 +93,7 @@ input[type=checkbox] {
93
93
  color: var(--system-yellow);
94
94
  }
95
95
 
96
- .modal {
96
+ .read-only :is(x3d-canvas, .toolbar, .dialog, .outline-editor) {
97
97
  pointer-events: none;
98
98
  }
99
99
 
@@ -150,6 +150,7 @@ tbody th th {
150
150
  thead tr,
151
151
  tfoot tr {
152
152
  background: var(--tint-color2);
153
+ backdrop-filter: var(--tool-backdrop-filter);
153
154
  }
154
155
 
155
156
  tbody tr:nth-child(odd) {
@@ -786,6 +787,14 @@ body.dark .dialog ::placeholder {
786
787
  color: var(--system-gray2);
787
788
  }
788
789
 
790
+ .scene-properties td.meta-value {
791
+ display: flex;
792
+ }
793
+
794
+ .scene-properties .open-link {
795
+ padding-left: 4px;
796
+ }
797
+
789
798
  /* Library */
790
799
 
791
800
  .ui-widget .library-input {
@@ -1023,7 +1032,7 @@ body.dark .ui-widget .library-list .component {
1023
1032
  overflow: hidden;
1024
1033
  position: absolute;
1025
1034
  box-sizing: border-box;
1026
- left: 0;
1035
+ left: 0px;
1027
1036
  right: var(--toolbar-width);
1028
1037
  height: 100%;
1029
1038
  }
@@ -1032,7 +1041,7 @@ body.dark .ui-widget .library-list .component {
1032
1041
  position: absolute;
1033
1042
  box-sizing: border-box;
1034
1043
  overflow-y: scroll;
1035
- top: 0;
1044
+ top: 0px;
1036
1045
  border-right: 1px solid var(--border-color);
1037
1046
  border-bottom: 1px solid var(--border-color);
1038
1047
  padding: 5px;
@@ -1046,13 +1055,27 @@ body.dark .ui-widget .library-list .component {
1046
1055
  }
1047
1056
 
1048
1057
  .console-output p {
1058
+ box-sizing: border-box;
1059
+ position: relative;
1060
+ z-index: 0;
1049
1061
  margin: 0;
1062
+ padding: 1px 2px;
1063
+ white-space: pre-wrap;
1064
+ overflow-wrap: break-word;
1065
+ font-family: monospace;
1066
+ font-size: 8pt;
1050
1067
  }
1051
1068
 
1052
- .console-output p.splitter {
1053
- margin-top: 5px;
1054
- border-top: 1px solid var(--system-gray3);
1055
- margin-bottom: 5px;
1069
+ .console-output p:where(.warn, .error):before {
1070
+ content: "";
1071
+ box-sizing: border-box;
1072
+ position: absolute;
1073
+ display: block;
1074
+ z-index: -1;
1075
+ top: 0px;
1076
+ left: 0px;
1077
+ width: 100%;
1078
+ height: 100%;
1056
1079
  }
1057
1080
 
1058
1081
  .console-output p.debug {
@@ -1075,40 +1098,49 @@ body.dark .ui-widget .library-list .component {
1075
1098
  color: var(--system-red);
1076
1099
  }
1077
1100
 
1078
- .console-output p.filled {
1079
- position: relative;
1080
- z-index: 0;
1081
- margin-top: 5px;
1082
- margin-bottom: 5px;
1101
+ .console-output p.warn {
1102
+ border-top: 1px solid var(--system-yellow);
1103
+ border-bottom: 1px solid var(--system-yellow);
1083
1104
  color: black;
1084
1105
  }
1085
1106
 
1086
- .console-output p.filled:before {
1087
- content: "";
1088
- position: absolute;
1089
- display: block;
1090
- z-index: -1;
1091
- width: 100%;
1092
- height: 100%;
1093
- filter: brightness(2) opacity(60%);
1107
+ .console-output p.warn:before {
1108
+ background-color: color-mix(in srgb, color-mix(in srgb, var(--system-yellow), white 50%), transparent 30%);
1094
1109
  }
1095
1110
 
1096
- .console-output p.warn.filled {
1097
- border-top: 1px solid var(--system-yellow);
1098
- border-bottom: 1px solid var(--system-yellow);
1111
+ .console-output p.error {
1112
+ border-top: 1px solid var(--system-red);
1113
+ border-bottom: 1px solid var(--system-red);
1114
+ color: black;
1099
1115
  }
1100
1116
 
1101
- .console-output p.warn.filled:before {
1102
- background-color: var(--system-yellow);
1117
+ .console-output p.error:before {
1118
+ background-color: color-mix(in srgb, color-mix(in srgb, var(--system-red), white 50%), transparent 30%);
1103
1119
  }
1104
1120
 
1105
- .console-output p.error.filled {
1106
- border-top: 1px solid var(--system-red);
1107
- border-bottom: 1px solid var(--system-red);
1121
+ .console-output p.warn:has(+ p.warn),
1122
+ .console-output p.error:has(+ p.error) {
1123
+ border-bottom: none;
1124
+ }
1125
+
1126
+ .console-output p.warn + p.warn,
1127
+ .console-output p.error + p.error {
1128
+ border-top: none;
1129
+ }
1130
+
1131
+ .console-output p.warn:not(:has(+ p.warn)),
1132
+ .console-output p.error:not(:has(+ p.error)) {
1133
+ margin-bottom: 2px;
1108
1134
  }
1109
1135
 
1110
- .console-output p.error.filled:before {
1111
- background-color: var(--system-red);
1136
+ .console-output p.splitter {
1137
+ margin: 5px 0px;
1138
+ border-top: 1px solid var(--system-gray3);
1139
+ padding: 0px;
1140
+ }
1141
+
1142
+ .console-output p.splitter:first-child {
1143
+ display: none;
1112
1144
  }
1113
1145
 
1114
1146
  .console-input {