diff --git a/cypress/platform/knsv2.html b/cypress/platform/knsv2.html index 26d6b31e2..185012596 100644 --- a/cypress/platform/knsv2.html +++ b/cypress/platform/knsv2.html @@ -76,7 +76,7 @@
-      %%{init: {"layout": "stress"} }%%
+      %%{init: {"layout": "elk"} }%%
 stateDiagram
   [*] --> T1
   T1 --> T2
@@ -531,7 +531,7 @@ mindmap
       mermaid.initialize({
         // theme: 'dark',
         handdrawnSeed: 12,
-        look: 'handdrawn',
+        // look: 'handdrawn',
         // layout: 'dagre',
         layout: 'elk',
         flowchart: { titleTopMargin: 10 },
diff --git a/packages/mermaid/src/diagrams/state/dataFetcher.js b/packages/mermaid/src/diagrams/state/dataFetcher.js
new file mode 100644
index 000000000..f0d1f03e7
--- /dev/null
+++ b/packages/mermaid/src/diagrams/state/dataFetcher.js
@@ -0,0 +1,392 @@
+import { log } from '../../logger.js';
+import common from '../common/common.js';
+import { getConfig } from '../../diagram-api/diagramAPI.js';
+
+import {
+  DEFAULT_DIAGRAM_DIRECTION,
+  STMT_STATE,
+  STMT_RELATION,
+  STMT_CLASSDEF,
+  STMT_APPLYCLASS,
+  DEFAULT_STATE_TYPE,
+  DIVIDER_TYPE,
+  G_EDGE_STYLE,
+  G_EDGE_ARROWHEADSTYLE,
+  G_EDGE_LABELPOS,
+  G_EDGE_LABELTYPE,
+  G_EDGE_THICKNESS,
+  CSS_EDGE,
+  DEFAULT_NESTED_DOC_DIR,
+  SHAPE_DIVIDER,
+  SHAPE_GROUP,
+  CSS_DIAGRAM_CLUSTER,
+  CSS_DIAGRAM_CLUSTER_ALT,
+  CSS_DIAGRAM_STATE,
+  SHAPE_STATE_WITH_DESC,
+  SHAPE_STATE,
+  SHAPE_START,
+  SHAPE_END,
+  SHAPE_NOTE,
+  SHAPE_NOTEGROUP,
+  CSS_DIAGRAM_NOTE,
+  DOMID_TYPE_SPACER,
+  DOMID_STATE,
+  NOTE_ID,
+  PARENT_ID,
+  NOTE,
+  PARENT,
+  CSS_EDGE_NOTE_EDGE,
+} from './stateCommon.js';
+
+// List of nodes created from the parsed diagram statement items
+let nodeDb = {};
+
+let graphItemCount = 0; // used to construct ids, etc.
+
+/**
+ * Create a standard string for the dom ID of an item.
+ * If a type is given, insert that before the counter, preceded by the type spacer
+ *
+ * @param itemId
+ * @param counter
+ * @param {string | null} type
+ * @param typeSpacer
+ * @returns {string}
+ */
+export function stateDomId(itemId = '', counter = 0, type = '', typeSpacer = DOMID_TYPE_SPACER) {
+  const typeStr = type !== null && type.length > 0 ? `${typeSpacer}${type}` : '';
+  return `${DOMID_STATE}-${itemId}${typeStr}-${counter}`;
+}
+
+const setupDoc = (parentParsedItem, doc, diagramStates, nodes, edges, altFlag, useRough) => {
+  // graphItemCount = 0;
+  log.trace('items', doc);
+  doc.forEach((item) => {
+    switch (item.stmt) {
+      case STMT_STATE:
+        dataFetcher(parentParsedItem, item, diagramStates, nodes, edges, altFlag, useRough);
+        break;
+      case DEFAULT_STATE_TYPE:
+        dataFetcher(parentParsedItem, item, diagramStates, nodes, edges, altFlag, useRough);
+        break;
+      case STMT_RELATION:
+        {
+          dataFetcher(
+            parentParsedItem,
+            item.state1,
+            diagramStates,
+            nodes,
+            edges,
+            altFlag,
+            useRough
+          );
+          dataFetcher(
+            parentParsedItem,
+            item.state2,
+            diagramStates,
+            nodes,
+            edges,
+            altFlag,
+            useRough
+          );
+          const edgeData = {
+            id: 'edge' + graphItemCount,
+            start: item.state1.id,
+            end: item.state2.id,
+            arrowhead: 'normal',
+            arrowTypeEnd: 'arrow_barb',
+            style: G_EDGE_STYLE,
+            labelStyle: '',
+            label: common.sanitizeText(item.description, getConfig()),
+            arrowheadStyle: G_EDGE_ARROWHEADSTYLE,
+            labelpos: G_EDGE_LABELPOS,
+            labelType: G_EDGE_LABELTYPE,
+            thickness: G_EDGE_THICKNESS,
+            classes: CSS_EDGE,
+            useRough,
+          };
+          edges.push(edgeData);
+          //g.setEdge(item.state1.id, item.state2.id, edgeData, graphItemCount);
+          graphItemCount++;
+        }
+        break;
+    }
+  });
+};
+
+/**
+ * Get the direction from the statement items.
+ * Look through all of the documents (docs) in the parsedItems
+ * Because is a _document_ direction, the default direction is not necessarily the same as the overall default _diagram_ direction.
+ * @param {object[]} parsedItem - the parsed statement item to look through
+ * @param [defaultDir] - the direction to use if none is found
+ * @returns {string}
+ */
+const getDir = (parsedItem, defaultDir = DEFAULT_NESTED_DOC_DIR) => {
+  let dir = defaultDir;
+  if (parsedItem.doc) {
+    for (let i = 0; i < parsedItem.doc.length; i++) {
+      const parsedItemDoc = parsedItem.doc[i];
+      if (parsedItemDoc.stmt === 'dir') {
+        dir = parsedItemDoc.value;
+      }
+    }
+  }
+  return dir;
+};
+
+/**
+ * Returns a new list of classes.
+ * In the future, this can be replaced with a class common to all diagrams.
+ * ClassDef information = { id: id, styles: [], textStyles: [] }
+ *
+ * @returns {{}}
+ */
+function newClassesList() {
+  return {};
+}
+
+// let direction = DEFAULT_DIAGRAM_DIRECTION;
+// let rootDoc = [];
+let cssClasses = newClassesList(); // style classes defined by a classDef
+
+/**
+ *
+ * @param nodes
+ * @param nodeData
+ */
+function insertOrUpdateNode(nodes, nodeData) {
+  if (!nodeData.id || nodeData.id === '' || nodeData.id === '') {
+    return;
+  }
+
+  //Populate node style attributes if nodeData has classes defined
+  if (nodeData.cssClasses) {
+    nodeData.cssClasses.split(' ').forEach((cssClass) => {
+      if (cssClasses[cssClass]) {
+        cssClasses[cssClass].styles.forEach((style) => {
+          // Populate nodeData with style attributes specifically to be used by rough.js
+          if (style && style.startsWith('fill:')) {
+            nodeData.backgroundColor = style.replace('fill:', '');
+          }
+          if (style && style.startsWith('stroke:')) {
+            nodeData.borderColor = style.replace('stroke:', '');
+          }
+          if (style && style.startsWith('stroke-width:')) {
+            nodeData.borderWidth = style.replace('stroke-width:', '');
+          }
+
+          nodeData.cssStyles += style + ';';
+        });
+        cssClasses[cssClass].textStyles.forEach((style) => {
+          nodeData.labelStyle += style + ';';
+          if (style && style.startsWith('fill:')) {
+            nodeData.labelTextColor = style.replace('fill:', '');
+          }
+        });
+      }
+    });
+  }
+  const existingNodeData = nodes.find((node) => node.id === nodeData.id);
+  if (existingNodeData) {
+    //update the existing nodeData
+    Object.assign(existingNodeData, nodeData);
+  } else {
+    nodes.push(nodeData);
+  }
+}
+/**
+ * Get classes from the db for the info item.
+ * If there aren't any or if dbInfoItem isn't defined, return an empty string.
+ * Else create 1 string from the list of classes found
+ *
+ * @param {undefined | null | object} dbInfoItem
+ * @returns {string}
+ */
+function getClassesFromDbInfo(dbInfoItem) {
+  if (dbInfoItem === undefined || dbInfoItem === null) {
+    return '';
+  } else {
+    if (dbInfoItem.cssClasses) {
+      return dbInfoItem.cssClasses.join(' ');
+    } else {
+      return '';
+    }
+  }
+}
+export const dataFetcher = (parent, parsedItem, diagramStates, nodes, edges, altFlag, useRough) => {
+  const itemId = parsedItem.id;
+  const classStr = getClassesFromDbInfo(diagramStates[itemId]);
+
+  if (itemId !== 'root') {
+    let shape = SHAPE_STATE;
+    if (parsedItem.start === true) {
+      shape = SHAPE_START;
+    }
+    if (parsedItem.start === false) {
+      shape = SHAPE_END;
+    }
+    if (parsedItem.type !== DEFAULT_STATE_TYPE) {
+      shape = parsedItem.type;
+    }
+
+    // Add the node to our list (nodeDb)
+    if (!nodeDb[itemId]) {
+      nodeDb[itemId] = {
+        id: itemId,
+        shape,
+        description: common.sanitizeText(itemId, getConfig()),
+        cssClasses: `${classStr} ${CSS_DIAGRAM_STATE}`,
+      };
+    }
+
+    const newNode = nodeDb[itemId];
+    console.log('New Node:', newNode);
+
+    // Save data for description and group so that for instance a statement without description overwrites
+    // one with description  @todo TODO What does this mean? If important, add a test for it
+
+    // Build of the array of description strings
+    if (parsedItem.description) {
+      if (Array.isArray(newNode.description)) {
+        // There already is an array of strings,add to it
+        newNode.shape = SHAPE_STATE_WITH_DESC;
+        newNode.description.push(parsedItem.description);
+      } else {
+        if (newNode.description?.length > 0) {
+          // if there is a description already transform it to an array
+          newNode.shape = SHAPE_STATE_WITH_DESC;
+          if (newNode.description === itemId) {
+            // If the previous description was this, remove it
+            newNode.description = [parsedItem.description];
+          } else {
+            newNode.description = [newNode.description, parsedItem.description];
+          }
+        } else {
+          newNode.shape = SHAPE_STATE;
+          newNode.description = parsedItem.description;
+        }
+      }
+      newNode.description = common.sanitizeTextOrArray(newNode.description, getConfig());
+    }
+
+    // If there's only 1 description entry, just use a regular state shape
+    if (newNode.description?.length === 1 && newNode.shape === SHAPE_STATE_WITH_DESC) {
+      newNode.shape = SHAPE_STATE;
+    }
+
+    // group
+    if (!newNode.type && parsedItem.doc) {
+      log.info('Setting cluster for ', itemId, getDir(parsedItem));
+      newNode.type = 'group';
+      newNode.dir = getDir(parsedItem);
+      newNode.shape = parsedItem.type === DIVIDER_TYPE ? SHAPE_DIVIDER : SHAPE_GROUP;
+      newNode.cssClasses =
+        newNode.cssClasses +
+        ' ' +
+        CSS_DIAGRAM_CLUSTER +
+        ' ' +
+        (altFlag ? CSS_DIAGRAM_CLUSTER_ALT : '');
+    }
+
+    // This is what will be added to the graph
+    const nodeData = {
+      labelStyle: '',
+      shape: newNode.shape,
+      label: newNode.description,
+      cssClasses: newNode.cssClasses,
+      cssStyles: '',
+      id: itemId,
+      dir: newNode.dir,
+      domId: stateDomId(itemId, graphItemCount),
+      type: newNode.type,
+      padding: 15,
+      rx: 10,
+      ry: 10,
+      useRough,
+    };
+
+    if (parent && parent.id !== 'root') {
+      log.trace('Setting node ', itemId, ' to be child of its parent ', parent.id);
+      nodeData.parentId = parent.id;
+    }
+
+    nodeData.centerLabel = true;
+
+    if (parsedItem.note) {
+      // Todo: set random id
+      const noteData = {
+        labelStyle: '',
+        shape: SHAPE_NOTE,
+        label: parsedItem.note.text,
+        cssClasses: CSS_DIAGRAM_NOTE,
+        // useHtmlLabels: false,
+        cssStyles: '', // styles.style,
+        id: itemId + NOTE_ID + '-' + graphItemCount,
+        domId: stateDomId(itemId, graphItemCount, NOTE),
+        type: newNode.type,
+        padding: 15, //getConfig().flowchart.padding
+        useRough,
+      };
+      const groupData = {
+        labelStyle: '',
+        shape: SHAPE_NOTEGROUP,
+        label: parsedItem.note.text,
+        cssClasses: newNode.cssClasses,
+        cssStyles: '', // styles.style,
+        id: itemId + PARENT_ID,
+        domId: stateDomId(itemId, graphItemCount, PARENT),
+        type: 'group',
+        padding: 0, //getConfig().flowchart.padding
+        useRough,
+      };
+      graphItemCount++;
+
+      const parentNodeId = itemId + PARENT_ID;
+
+      //add parent id to groupData
+      groupData.id = parentNodeId;
+      //add parent id to noteData
+      noteData.parentId = parentNodeId;
+
+      //insert groupData
+      insertOrUpdateNode(nodes, groupData);
+      //insert noteData
+      insertOrUpdateNode(nodes, noteData);
+      //insert nodeData
+      insertOrUpdateNode(nodes, nodeData);
+
+      let from = itemId;
+      let to = noteData.id;
+
+      if (parsedItem.note.position === 'left of') {
+        from = noteData.id;
+        to = itemId;
+      }
+
+      edges.push({
+        id: from + '-' + to,
+        start: from,
+        end: to,
+        arrowhead: 'none',
+        arrowTypeEnd: '',
+        style: G_EDGE_STYLE,
+        labelStyle: '',
+        classes: CSS_EDGE_NOTE_EDGE,
+        arrowheadStyle: G_EDGE_ARROWHEADSTYLE,
+        labelpos: G_EDGE_LABELPOS,
+        labelType: G_EDGE_LABELTYPE,
+        thickness: G_EDGE_THICKNESS,
+        useRough,
+      });
+    } else {
+      insertOrUpdateNode(nodes, nodeData);
+    }
+
+    console.log('Nodes:', nodes);
+  }
+  if (parsedItem.doc) {
+    log.trace('Adding nodes children ');
+    setupDoc(parsedItem, parsedItem.doc, diagramStates, nodes, edges, !altFlag, useRough);
+  }
+};
diff --git a/packages/mermaid/src/diagrams/state/stateDb.js b/packages/mermaid/src/diagrams/state/stateDb.js
index 8e2ec5b81..4c5835b68 100644
--- a/packages/mermaid/src/diagrams/state/stateDb.js
+++ b/packages/mermaid/src/diagrams/state/stateDb.js
@@ -11,6 +11,7 @@ import {
   setDiagramTitle,
   getDiagramTitle,
 } from '../common/commonDb.js';
+import { dataFetcher } from './dataFetcher.js';
 
 import {
   DEFAULT_DIAGRAM_DIRECTION,
@@ -75,10 +76,6 @@ let rootDoc = [];
 let classes = newClassesList(); // style classes defined by a classDef
 
 // --------------------------------------
-// List of nodes created from the parsed diagram statement items
-let nodeDb = {};
-
-let graphItemCount = 0; // used to construct ids, etc.
 
 const newDoc = () => {
   return {
@@ -574,300 +571,6 @@ const setDirection = (dir) => {
 
 const trimColon = (str) => (str && str[0] === ':' ? str.substr(1).trim() : str.trim());
 
-const dataFetcher = (parent, parsedItem, diagramStates, nodes, edges, altFlag, useRough) => {
-  const itemId = parsedItem.id;
-  const classStr = getClassesFromDbInfo(diagramStates[itemId]);
-
-  if (itemId !== 'root') {
-    let shape = SHAPE_STATE;
-    if (parsedItem.start === true) {
-      shape = SHAPE_START;
-    }
-    if (parsedItem.start === false) {
-      shape = SHAPE_END;
-    }
-    if (parsedItem.type !== DEFAULT_STATE_TYPE) {
-      shape = parsedItem.type;
-    }
-
-    // Add the node to our list (nodeDb)
-    if (!nodeDb[itemId]) {
-      nodeDb[itemId] = {
-        id: itemId,
-        shape,
-        description: common.sanitizeText(itemId, getConfig()),
-        classes: `${classStr} ${CSS_DIAGRAM_STATE}`,
-      };
-    }
-
-    const newNode = nodeDb[itemId];
-    console.log('New Node:', newNode);
-
-    // Save data for description and group so that for instance a statement without description overwrites
-    // one with description  @todo TODO What does this mean? If important, add a test for it
-
-    // Build of the array of description strings
-    if (parsedItem.description) {
-      if (Array.isArray(newNode.description)) {
-        // There already is an array of strings,add to it
-        newNode.shape = SHAPE_STATE_WITH_DESC;
-        newNode.description.push(parsedItem.description);
-      } else {
-        if (newNode.description?.length > 0) {
-          // if there is a description already transform it to an array
-          newNode.shape = SHAPE_STATE_WITH_DESC;
-          if (newNode.description === itemId) {
-            // If the previous description was this, remove it
-            newNode.description = [parsedItem.description];
-          } else {
-            newNode.description = [newNode.description, parsedItem.description];
-          }
-        } else {
-          newNode.shape = SHAPE_STATE;
-          newNode.description = parsedItem.description;
-        }
-      }
-      newNode.description = common.sanitizeTextOrArray(newNode.description, getConfig());
-    }
-
-    // If there's only 1 description entry, just use a regular state shape
-    if (newNode.description?.length === 1 && newNode.shape === SHAPE_STATE_WITH_DESC) {
-      newNode.shape = SHAPE_STATE;
-    }
-
-    // group
-    if (!newNode.type && parsedItem.doc) {
-      log.info('Setting cluster for ', itemId, getDir(parsedItem));
-      newNode.type = 'group';
-      newNode.dir = getDir(parsedItem);
-      newNode.shape = parsedItem.type === DIVIDER_TYPE ? SHAPE_DIVIDER : SHAPE_GROUP;
-      newNode.classes =
-        newNode.classes +
-        ' ' +
-        CSS_DIAGRAM_CLUSTER +
-        ' ' +
-        (altFlag ? CSS_DIAGRAM_CLUSTER_ALT : '');
-    }
-
-    // This is what will be added to the graph
-    const nodeData = {
-      labelStyle: '',
-      shape: newNode.shape,
-      labelText: newNode.description,
-      classes: newNode.classes,
-      style: '',
-      id: itemId,
-      dir: newNode.dir,
-      domId: stateDomId(itemId, graphItemCount),
-      type: newNode.type,
-      padding: 15,
-      rx: 10,
-      ry: 10,
-      useRough,
-    };
-
-    if (parent && parent.id !== 'root') {
-      log.trace('Setting node ', itemId, ' to be child of its parent ', parent.id);
-      nodeData.parentId = parent.id;
-    }
-
-    nodeData.centerLabel = true;
-
-    if (parsedItem.note) {
-      // Todo: set random id
-      const noteData = {
-        labelStyle: '',
-        shape: SHAPE_NOTE,
-        labelText: parsedItem.note.text,
-        classes: CSS_DIAGRAM_NOTE,
-        // useHtmlLabels: false,
-        style: '', // styles.style,
-        id: itemId + NOTE_ID + '-' + graphItemCount,
-        domId: stateDomId(itemId, graphItemCount, NOTE),
-        type: newNode.type,
-        padding: 15, //getConfig().flowchart.padding
-        useRough,
-      };
-      const groupData = {
-        labelStyle: '',
-        shape: SHAPE_NOTEGROUP,
-        labelText: parsedItem.note.text,
-        classes: newNode.classes,
-        style: '', // styles.style,
-        id: itemId + PARENT_ID,
-        domId: stateDomId(itemId, graphItemCount, PARENT),
-        type: 'group',
-        padding: 0, //getConfig().flowchart.padding
-        useRough,
-      };
-      graphItemCount++;
-
-      const parentNodeId = itemId + PARENT_ID;
-
-      //add parent id to groupData
-      groupData.id = parentNodeId;
-      //add parent id to noteData
-      noteData.parentId = parentNodeId;
-
-      //insert groupData
-      insertOrUpdateNode(nodes, groupData);
-      //insert noteData
-      insertOrUpdateNode(nodes, noteData);
-      //insert nodeData
-      insertOrUpdateNode(nodes, nodeData);
-
-      let from = itemId;
-      let to = noteData.id;
-
-      if (parsedItem.note.position === 'left of') {
-        from = noteData.id;
-        to = itemId;
-      }
-
-      edges.push({
-        id: from + '-' + to,
-        start: from,
-        end: to,
-        arrowhead: 'none',
-        arrowTypeEnd: '',
-        style: G_EDGE_STYLE,
-        labelStyle: '',
-        classes: CSS_EDGE_NOTE_EDGE,
-        arrowheadStyle: G_EDGE_ARROWHEADSTYLE,
-        labelpos: G_EDGE_LABELPOS,
-        labelType: G_EDGE_LABELTYPE,
-        thickness: G_EDGE_THICKNESS,
-        useRough,
-      });
-    } else {
-      insertOrUpdateNode(nodes, nodeData);
-    }
-
-    console.log('Nodes:', nodes);
-  }
-  if (parsedItem.doc) {
-    log.trace('Adding nodes children ');
-    setupDoc(parsedItem, parsedItem.doc, diagramStates, nodes, edges, !altFlag, useRough);
-  }
-};
-
-/**
- *
- * @param nodes
- * @param nodeData
- */
-function insertOrUpdateNode(nodes, nodeData) {
-  if (!nodeData.id || nodeData.id === '' || nodeData.id === '') {
-    return;
-  }
-
-  //Populate node style attributes if nodeData has classes defined
-  if (nodeData.classes) {
-    nodeData.classes.split(' ').forEach((cssClass) => {
-      if (classes[cssClass]) {
-        classes[cssClass].styles.forEach((style) => {
-          // Populate nodeData with style attributes specifically to be used by rough.js
-          if (style && style.startsWith('fill:')) {
-            nodeData.backgroundColor = style.replace('fill:', '');
-          }
-          if (style && style.startsWith('stroke:')) {
-            nodeData.borderColor = style.replace('stroke:', '');
-          }
-          if (style && style.startsWith('stroke-width:')) {
-            nodeData.borderWidth = style.replace('stroke-width:', '');
-          }
-
-          nodeData.style += style + ';';
-        });
-        classes[cssClass].textStyles.forEach((style) => {
-          nodeData.labelStyle += style + ';';
-          if (style && style.startsWith('fill:')) {
-            nodeData.labelTextColor = style.replace('fill:', '');
-          }
-        });
-      }
-    });
-  }
-  const existingNodeData = nodes.find((node) => node.id === nodeData.id);
-  if (existingNodeData) {
-    //update the existing nodeData
-    Object.assign(existingNodeData, nodeData);
-  } else {
-    nodes.push(nodeData);
-  }
-}
-
-/**
- * Create a standard string for the dom ID of an item.
- * If a type is given, insert that before the counter, preceded by the type spacer
- *
- * @param itemId
- * @param counter
- * @param {string | null} type
- * @param typeSpacer
- * @returns {string}
- */
-export function stateDomId(itemId = '', counter = 0, type = '', typeSpacer = DOMID_TYPE_SPACER) {
-  const typeStr = type !== null && type.length > 0 ? `${typeSpacer}${type}` : '';
-  return `${DOMID_STATE}-${itemId}${typeStr}-${counter}`;
-}
-
-const setupDoc = (parentParsedItem, doc, diagramStates, nodes, edges, altFlag, useRough) => {
-  // graphItemCount = 0;
-  log.trace('items', doc);
-  doc.forEach((item) => {
-    switch (item.stmt) {
-      case STMT_STATE:
-        dataFetcher(parentParsedItem, item, diagramStates, nodes, edges, altFlag, useRough);
-        break;
-      case DEFAULT_STATE_TYPE:
-        dataFetcher(parentParsedItem, item, diagramStates, nodes, edges, altFlag, useRough);
-        break;
-      case STMT_RELATION:
-        {
-          dataFetcher(
-            parentParsedItem,
-            item.state1,
-            diagramStates,
-            nodes,
-            edges,
-            altFlag,
-            useRough
-          );
-          dataFetcher(
-            parentParsedItem,
-            item.state2,
-            diagramStates,
-            nodes,
-            edges,
-            altFlag,
-            useRough
-          );
-          const edgeData = {
-            id: 'edge' + graphItemCount,
-            start: item.state1.id,
-            end: item.state2.id,
-            arrowhead: 'normal',
-            arrowTypeEnd: 'arrow_barb',
-            style: G_EDGE_STYLE,
-            labelStyle: '',
-            label: common.sanitizeText(item.description, getConfig()),
-            arrowheadStyle: G_EDGE_ARROWHEADSTYLE,
-            labelpos: G_EDGE_LABELPOS,
-            labelType: G_EDGE_LABELTYPE,
-            thickness: G_EDGE_THICKNESS,
-            classes: CSS_EDGE,
-            useRough,
-          };
-          edges.push(edgeData);
-          //g.setEdge(item.state1.id, item.state2.id, edgeData, graphItemCount);
-          graphItemCount++;
-        }
-        break;
-    }
-  });
-};
-
 export const getData = () => {
   const nodes = [];
   const edges = [];
@@ -886,47 +589,6 @@ export const getData = () => {
   return { nodes, edges, other: {} };
 };
 
-/**
- * Get the direction from the statement items.
- * Look through all of the documents (docs) in the parsedItems
- * Because is a _document_ direction, the default direction is not necessarily the same as the overall default _diagram_ direction.
- * @param {object[]} parsedItem - the parsed statement item to look through
- * @param [defaultDir] - the direction to use if none is found
- * @returns {string}
- */
-const getDir = (parsedItem, defaultDir = DEFAULT_NESTED_DOC_DIR) => {
-  let dir = defaultDir;
-  if (parsedItem.doc) {
-    for (let i = 0; i < parsedItem.doc.length; i++) {
-      const parsedItemDoc = parsedItem.doc[i];
-      if (parsedItemDoc.stmt === 'dir') {
-        dir = parsedItemDoc.value;
-      }
-    }
-  }
-  return dir;
-};
-
-/**
- * Get classes from the db for the info item.
- * If there aren't any or if dbInfoItem isn't defined, return an empty string.
- * Else create 1 string from the list of classes found
- *
- * @param {undefined | null | object} dbInfoItem
- * @returns {string}
- */
-function getClassesFromDbInfo(dbInfoItem) {
-  if (dbInfoItem === undefined || dbInfoItem === null) {
-    return '';
-  } else {
-    if (dbInfoItem.classes) {
-      return dbInfoItem.classes.join(' ');
-    } else {
-      return '';
-    }
-  }
-}
-
 export default {
   getConfig: () => getConfig().state,
   getData,
diff --git a/packages/mermaid/src/rendering-util/layout-algorithms/dagre/mermaid-graphlib.js b/packages/mermaid/src/rendering-util/layout-algorithms/dagre/mermaid-graphlib.js
index 005bb8f83..3744254b2 100644
--- a/packages/mermaid/src/rendering-util/layout-algorithms/dagre/mermaid-graphlib.js
+++ b/packages/mermaid/src/rendering-util/layout-algorithms/dagre/mermaid-graphlib.js
@@ -288,7 +288,7 @@ export const adjustClustersAndEdges = (graph, depth) => {
         domId: specialId,
         id: specialId,
         labelStyle: '',
-        labelText: edge.label,
+        label: edge.label,
         padding: 0,
         shape: 'labelRect',
         style: '',
@@ -416,7 +416,7 @@ export const extractor = (graph, depth) => {
         clusterNode: true,
         id: node,
         clusterData: clusterDb[node].clusterData,
-        labelText: clusterDb[node].labelText,
+        label: clusterDb[node].label,
         graph: clusterGraph,
       });
       log.warn('New graph after copy node: (', node, ')', graphlibJson.write(clusterGraph));
diff --git a/packages/mermaid/src/rendering-util/layout-algorithms/dagre/mermaid-graphlib.spec.js b/packages/mermaid/src/rendering-util/layout-algorithms/dagre/mermaid-graphlib.spec.js
index d44e54391..a10e4669d 100644
--- a/packages/mermaid/src/rendering-util/layout-algorithms/dagre/mermaid-graphlib.spec.js
+++ b/packages/mermaid/src/rendering-util/layout-algorithms/dagre/mermaid-graphlib.spec.js
@@ -386,7 +386,7 @@ flowchart TB
     */
 
     const exportedGraph = JSON.parse(
-      '{"options":{"directed":true,"multigraph":true,"compound":true},"nodes":[{"v":"A","value":{"labelStyle":"","shape":"rect","labelText":"A","rx":0,"ry":0,"class":"default","style":"","id":"A","width":500,"type":"group","padding":15}},{"v":"B","value":{"labelStyle":"","shape":"rect","labelText":"B","rx":0,"ry":0,"class":"default","style":"","id":"B","width":500,"type":"group","padding":15},"parent":"A"},{"v":"b","value":{"labelStyle":"","shape":"rect","labelText":"b","rx":0,"ry":0,"class":"default","style":"","id":"b","padding":15},"parent":"A"},{"v":"c","value":{"labelStyle":"","shape":"rect","labelText":"c","rx":0,"ry":0,"class":"default","style":"","id":"c","padding":15},"parent":"B"},{"v":"a","value":{"labelStyle":"","shape":"rect","labelText":"a","rx":0,"ry":0,"class":"default","style":"","id":"a","padding":15},"parent":"A"}],"edges":[{"v":"b","w":"B","name":"1","value":{"minlen":1,"arrowhead":"normal","arrowTypeStart":"arrow_open","arrowTypeEnd":"arrow_point","thickness":"normal","pattern":"solid","style":"fill:none","labelStyle":"","arrowheadStyle":"fill: #333","labelpos":"c","labelType":"text","label":"","id":"L-b-B","classes":"flowchart-link LS-b LE-B"}},{"v":"a","w":"c","name":"2","value":{"minlen":1,"arrowhead":"normal","arrowTypeStart":"arrow_open","arrowTypeEnd":"arrow_point","thickness":"normal","pattern":"solid","style":"fill:none","labelStyle":"","arrowheadStyle":"fill: #333","labelpos":"c","labelType":"text","label":"","id":"L-a-c","classes":"flowchart-link LS-a LE-c"}}],"value":{"rankdir":"TB","nodesep":50,"ranksep":50,"marginx":8,"marginy":8}}'
+      '{"options":{"directed":true,"multigraph":true,"compound":true},"nodes":[{"v":"A","value":{"labelStyle":"","shape":"rect","labelText":"A","rx":0,"ry":0,"cssClass":"default","style":"","id":"A","width":500,"type":"group","padding":15}},{"v":"B","value":{"labelStyle":"","shape":"rect","labelText":"B","rx":0,"ry":0,"class":"default","style":"","id":"B","width":500,"type":"group","padding":15},"parent":"A"},{"v":"b","value":{"labelStyle":"","shape":"rect","labelText":"b","rx":0,"ry":0,"class":"default","style":"","id":"b","padding":15},"parent":"A"},{"v":"c","value":{"labelStyle":"","shape":"rect","labelText":"c","rx":0,"ry":0,"class":"default","style":"","id":"c","padding":15},"parent":"B"},{"v":"a","value":{"labelStyle":"","shape":"rect","labelText":"a","rx":0,"ry":0,"class":"default","style":"","id":"a","padding":15},"parent":"A"}],"edges":[{"v":"b","w":"B","name":"1","value":{"minlen":1,"arrowhead":"normal","arrowTypeStart":"arrow_open","arrowTypeEnd":"arrow_point","thickness":"normal","pattern":"solid","style":"fill:none","labelStyle":"","arrowheadStyle":"fill: #333","labelpos":"c","labelType":"text","label":"","id":"L-b-B","cssClasses":"flowchart-link LS-b LE-B"}},{"v":"a","w":"c","name":"2","value":{"minlen":1,"arrowhead":"normal","arrowTypeStart":"arrow_open","arrowTypeEnd":"arrow_point","thickness":"normal","pattern":"solid","style":"fill:none","labelStyle":"","arrowheadStyle":"fill: #333","labelpos":"c","labelType":"text","label":"","id":"L-a-c","cssClasses":"flowchart-link LS-a LE-c"}}],"value":{"rankdir":"TB","nodesep":50,"ranksep":50,"marginx":8,"marginy":8}}'
     );
     const gr = graphlibJson.read(exportedGraph);
 
diff --git a/packages/mermaid/src/rendering-util/rendering-elements/clusters.js b/packages/mermaid/src/rendering-util/rendering-elements/clusters.js
index 8c422cee2..b807409ed 100644
--- a/packages/mermaid/src/rendering-util/rendering-elements/clusters.js
+++ b/packages/mermaid/src/rendering-util/rendering-elements/clusters.js
@@ -14,10 +14,7 @@ const rect = (parent, node) => {
   const siteConfig = getConfig();
 
   // Add outer g element
-  const shapeSvg = parent
-    .insert('g')
-    .attr('class', 'cluster' + (node.class ? ' ' + node.class : ''))
-    .attr('id', node.id);
+  const shapeSvg = parent.insert('g').attr('class', 'cluster').attr('id', node.id);
 
   // add the rect
   const rect = shapeSvg.insert('rect', ':first-child');
@@ -25,15 +22,15 @@ const rect = (parent, node) => {
   const useHtmlLabels = evaluate(siteConfig.flowchart.htmlLabels);
 
   // Create the label and insert it after the rect
-  const label = shapeSvg.insert('g').attr('class', 'cluster-label');
+  const labelEl = shapeSvg.insert('g').attr('class', 'cluster-label');
 
   // const text = label
   //   .node()
-  //   .appendChild(createLabel(node.labelText, node.labelStyle, undefined, true));
+  //   .appendChild(createLabel(node.label, node.labelStyle, undefined, true));
   const text =
     node.labelType === 'markdown'
-      ? createText(label, node.labelText, { style: node.labelStyle, useHtmlLabels })
-      : label.node().appendChild(createLabel(node.labelText, node.labelStyle, undefined, true));
+      ? createText(labelEl, node.label, { style: node.labelStyle, useHtmlLabels })
+      : labelEl.node().appendChild(createLabel(node.label, node.labelStyle, undefined, true));
 
   // Get the size of the label
   let bbox = text.getBBox();
@@ -59,7 +56,7 @@ const rect = (parent, node) => {
   log.trace('Data ', node, JSON.stringify(node));
   // center the rect around its coordinate
   rect
-    .attr('style', node.style)
+    .attr('style', node.cssStyles)
     .attr('rx', node.rx)
     .attr('ry', node.ry)
     .attr('x', node.x - width / 2)
@@ -69,13 +66,13 @@ const rect = (parent, node) => {
 
   const { subGraphTitleTopMargin } = getSubGraphTitleMargins(siteConfig);
   if (useHtmlLabels) {
-    label.attr(
+    labelEl.attr(
       'transform',
       // This puts the label on top of the box instead of inside it
       `translate(${node.x - bbox.width / 2}, ${node.y - node.height / 2 + subGraphTitleTopMargin})`
     );
   } else {
-    label.attr(
+    labelEl.attr(
       'transform',
       // This puts the label on top of the box instead of inside it
       `translate(${node.x}, ${node.y - node.height / 2 + subGraphTitleTopMargin})`
@@ -154,7 +151,7 @@ const roundedWithTitle = (parent, node) => {
     themeVariables;
 
   // Add outer g element
-  const shapeSvg = parent.insert('g').attr('class', node.classes).attr('id', node.id);
+  const shapeSvg = parent.insert('g').attr('class', node.cssClasses).attr('id', node.id);
 
   // add the rect
   const outerRectG = shapeSvg.insert('g', ':first-child');
@@ -163,9 +160,7 @@ const roundedWithTitle = (parent, node) => {
   const label = shapeSvg.insert('g').attr('class', 'cluster-label');
   let innerRect = shapeSvg.append('rect');
 
-  const text = label
-    .node()
-    .appendChild(createLabel(node.labelText, node.labelStyle, undefined, true));
+  const text = label.node().appendChild(createLabel(node.label, node.labelStyle, undefined, true));
 
   // Get the size of the label
   let bbox = text.getBBox();
@@ -197,7 +192,7 @@ const roundedWithTitle = (parent, node) => {
   // add the rect
   let rect;
   if (node.useRough) {
-    const isAlt = node.classes.includes('statediagram-cluster-alt');
+    const isAlt = node.cssClasses.includes('statediagram-cluster-alt');
     const rc = rough.svg(shapeSvg);
     const roughOuterNode =
       node.rx || node.ry
@@ -263,7 +258,7 @@ const roundedWithTitle = (parent, node) => {
 const divider = (parent, node) => {
   const { handdrawnSeed } = getConfig();
   // Add outer g element
-  const shapeSvg = parent.insert('g').attr('class', node.classes).attr('id', node.id);
+  const shapeSvg = parent.insert('g').attr('class', node.cssClasses).attr('id', node.id);
 
   // add the rect
   let rect;
@@ -318,7 +313,7 @@ export const insertCluster = (elem, node) => {
   return cluster;
 };
 export const getClusterTitleWidth = (elem, node) => {
-  const label = createLabel(node.labelText, node.labelStyle, undefined, true);
+  const label = createLabel(node.label, node.labelStyle, undefined, true);
   elem.node().appendChild(label);
   const width = label.getBBox().width;
   elem.node().removeChild(label);
diff --git a/packages/mermaid/src/rendering-util/rendering-elements/nodes.js b/packages/mermaid/src/rendering-util/rendering-elements/nodes.js
index 427476ee0..3013d2fba 100644
--- a/packages/mermaid/src/rendering-util/rendering-elements/nodes.js
+++ b/packages/mermaid/src/rendering-util/rendering-elements/nodes.js
@@ -48,9 +48,9 @@ export const insertNode = async (elem, node, dir) => {
   if (node.tooltip) {
     el.attr('title', node.tooltip);
   }
-  if (node.class) {
-    el.attr('class', 'node default ' + node.class);
-  }
+  // if (node.class) {
+  //   el.attr('class', 'node default ' + node.class);
+  // }
 
   nodeElems[node.id] = newEl;
 
diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/note.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/note.ts
index 1d78acd2f..5ba4ba451 100644
--- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/note.ts
+++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/note.ts
@@ -16,12 +16,12 @@ export const note = async (parent: SVGAElement, node: Node) => {
   const { shapeSvg, bbox, halfPadding } = await labelHelper(
     parent,
     node,
-    'node ' + node.classes,
+    'node ' + node.cssClasses,
     true
   );
 
-  log.info('Classes = ', node.classes);
-  const { style, useRough } = node;
+  log.info('Classes = ', node.cssClasses);
+  const { cssStyles, useRough } = node;
   let rect;
   const totalWidth = bbox.width + node.padding;
   const totalHeight = bbox.height + node.padding;
@@ -41,7 +41,7 @@ export const note = async (parent: SVGAElement, node: Node) => {
     });
 
     rect = shapeSvg.insert(() => roughNode, ':first-child');
-    rect.attr('class', 'basic label-container').attr('style', style);
+    rect.attr('class', 'basic label-container').attr('style', cssStyles);
   } else {
     rect = shapeSvg.insert('rect', ':first-child');
     rect
diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/rect.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/rect.ts
index 34c6a09e6..9ced7ee1f 100644
--- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/rect.ts
+++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/rect.ts
@@ -65,7 +65,7 @@ export const rect = async (parent: SVGAElement, node: Node) => {
   const { shapeSvg, bbox, halfPadding } = await labelHelper(
     parent,
     node,
-    'node ' + node.classes + ' ' + node.class,
+    'node ' + node.cssClasses, // + ' ' + node.class,
     true
   );
 
@@ -75,7 +75,7 @@ export const rect = async (parent: SVGAElement, node: Node) => {
   const y = -bbox.height / 2 - halfPadding;
 
   let rect;
-  const { rx, ry, style, useRough } = node;
+  const { rx, ry, style: cssStyles, useRough } = node;
   if (useRough) {
     const rc = rough.svg(shapeSvg);
     const options = userNodeOverrides(node, {
@@ -93,13 +93,13 @@ export const rect = async (parent: SVGAElement, node: Node) => {
         : rc.rectangle(x, y, totalWidth, totalHeight, options);
 
     rect = shapeSvg.insert(() => roughNode, ':first-child');
-    rect.attr('class', 'basic label-container').attr('style', style);
+    rect.attr('class', 'basic label-container').attr('style', cssStyles);
   } else {
     rect = shapeSvg.insert('rect', ':first-child');
 
     rect
       .attr('class', 'basic label-container')
-      .attr('style', style)
+      .attr('style', cssStyles)
       .attr('rx', rx)
       .attr('ry', ry)
       .attr('x', x)
@@ -108,16 +108,16 @@ export const rect = async (parent: SVGAElement, node: Node) => {
       .attr('height', totalHeight);
   }
 
-  if (node.props) {
-    const propKeys = new Set(Object.keys(node.props));
-    if (node.props.borders) {
-      applyNodePropertyBorders(rect, node.props.borders + '', totalWidth, totalHeight);
-      propKeys.delete('borders');
-    }
-    propKeys.forEach((propKey) => {
-      log.warn(`Unknown node property ${propKey}`);
-    });
-  }
+  // if (node.props) {
+  //   const propKeys = new Set(Object.keys(node.props));
+  //   if (node.props.borders) {
+  //     applyNodePropertyBorders(rect, node.props.borders + '', totalWidth, totalHeight);
+  //     propKeys.delete('borders');
+  //   }
+  //   propKeys.forEach((propKey) => {
+  //     log.warn(`Unknown node property ${propKey}`);
+  //   });
+  // }
 
   updateNodeBounds(node, rect);
 
@@ -131,7 +131,7 @@ export const rect = async (parent: SVGAElement, node: Node) => {
 export const labelRect = async (parent: SVGElement, node: Node) => {
   const { shapeSvg } = await labelHelper(parent, node, 'label', true);
 
-  log.trace('Classes = ', node.class);
+  // log.trace('Classes = ', node.class);
   // add the rect
   const rect = shapeSvg.insert('rect', ':first-child');
 
@@ -141,16 +141,16 @@ export const labelRect = async (parent: SVGElement, node: Node) => {
   rect.attr('width', totalWidth).attr('height', totalHeight);
   shapeSvg.attr('class', 'label edgeLabel');
 
-  if (node.props) {
-    const propKeys = new Set(Object.keys(node.props));
-    if (node.props.borders) {
-      applyNodePropertyBorders(rect, node.borders, totalWidth, totalHeight);
-      propKeys.delete('borders');
-    }
-    propKeys.forEach((propKey) => {
-      log.warn(`Unknown node property ${propKey}`);
-    });
-  }
+  // if (node.props) {
+  //   const propKeys = new Set(Object.keys(node.props));
+  //   if (node.props.borders) {
+  //     applyNodePropertyBorders(rect, node.borders, totalWidth, totalHeight);
+  //     propKeys.delete('borders');
+  //   }
+  //   propKeys.forEach((propKey) => {
+  //     log.warn(`Unknown node property ${propKey}`);
+  //   });
+  // }
 
   updateNodeBounds(node, rect);
 
diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/util.js b/packages/mermaid/src/rendering-util/rendering-elements/shapes/util.js
index d9314aacb..3ab5090a6 100644
--- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/util.js
+++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/util.js
@@ -6,48 +6,43 @@ import { evaluate, sanitizeText } from '$root/diagrams/common/common.js';
 import { decodeEntities } from '$root/utils.js';
 
 export const labelHelper = async (parent, node, _classes, isNode) => {
-  let classes;
+  let cssClasses;
   const useHtmlLabels = node.useHtmlLabels || evaluate(getConfig().flowchart.htmlLabels);
   if (!_classes) {
-    classes = 'node default';
+    cssClasses = 'node default';
   } else {
-    classes = _classes;
+    cssClasses = _classes;
   }
 
   // Add outer g element
   const shapeSvg = parent
     .insert('g')
-    .attr('class', classes)
+    .attr('class', cssClasses)
     .attr('id', node.domId || node.id);
 
   // Create the label and insert it after the rect
-  const label = shapeSvg.insert('g').attr('class', 'label').attr('style', node.labelStyle);
+  const labelEl = shapeSvg.insert('g').attr('class', 'label').attr('style', node.labelStyle);
 
-  // Replace labelText with default value if undefined
-  let labelText;
-  if (node.labelText === undefined) {
-    labelText = '';
+  // Replace label with default value if undefined
+  let label;
+  if (node.label === undefined) {
+    label = '';
   } else {
-    labelText = typeof node.labelText === 'string' ? node.labelText : node.labelText[0];
+    label = typeof node.label === 'string' ? node.label : node.label[0];
   }
 
-  const textNode = label.node();
+  const textNode = labelEl.node();
   let text;
   if (node.labelType === 'markdown') {
     // text = textNode;
-    text = createText(label, sanitizeText(decodeEntities(labelText), getConfig()), {
+    text = createText(labelEl, sanitizeText(decodeEntities(label), getConfig()), {
       useHtmlLabels,
       width: node.width || getConfig().flowchart.wrappingWidth,
-      classes: 'markdown-node-label',
+      cssClasses: 'markdown-node-label',
     });
   } else {
     text = textNode.appendChild(
-      createLabel(
-        sanitizeText(decodeEntities(labelText), getConfig()),
-        node.labelStyle,
-        false,
-        isNode
-      )
+      createLabel(sanitizeText(decodeEntities(label), getConfig()), node.labelStyle, false, isNode)
     );
   }
   // Get the size of the label
@@ -61,7 +56,7 @@ export const labelHelper = async (parent, node, _classes, isNode) => {
     // if there are images, need to wait for them to load before getting the bounding box
     const images = div.getElementsByTagName('img');
     if (images) {
-      const noImgText = labelText.replace(/]*>/g, '').trim() === '';
+      const noImgText = label.replace(/]*>/g, '').trim() === '';
 
       await Promise.all(
         [...images].map(
@@ -107,15 +102,15 @@ export const labelHelper = async (parent, node, _classes, isNode) => {
 
   // Center the label
   if (useHtmlLabels) {
-    label.attr('transform', 'translate(' + -bbox.width / 2 + ', ' + -bbox.height / 2 + ')');
+    labelEl.attr('transform', 'translate(' + -bbox.width / 2 + ', ' + -bbox.height / 2 + ')');
   } else {
-    label.attr('transform', 'translate(' + 0 + ', ' + -bbox.height / 2 + ')');
+    labelEl.attr('transform', 'translate(' + 0 + ', ' + -bbox.height / 2 + ')');
   }
   if (node.centerLabel) {
-    label.attr('transform', 'translate(' + -bbox.width / 2 + ', ' + -bbox.height / 2 + ')');
+    labelEl.attr('transform', 'translate(' + -bbox.width / 2 + ', ' + -bbox.height / 2 + ')');
   }
-  label.insert('rect', ':first-child');
-  return { shapeSvg, bbox, halfPadding, label };
+  labelEl.insert('rect', ':first-child');
+  return { shapeSvg, bbox, halfPadding, label: labelEl };
 };
 
 export const updateNodeBounds = (node, element) => {
diff --git a/packages/mermaid/src/rendering-util/types.d.ts b/packages/mermaid/src/rendering-util/types.d.ts
index 4e65ebe24..f6b56582e 100644
--- a/packages/mermaid/src/rendering-util/types.d.ts
+++ b/packages/mermaid/src/rendering-util/types.d.ts
@@ -14,25 +14,24 @@ interface Node {
   id: string;
   label?: string;
   parentId?: string;
-  position?: string; //REMOVE
+  position?: string; // Keep, this is for notes 'left of', 'right of', etc.
   cssStyles?: string; // Renamed from `styles` to `cssStyles`
-  style?: string; //REMOVE
   cssClasses?: string; // Renamed from `classes` to `cssClasses`
-  classes?: string; //REMOVE
-  class?: string; //REMOVE
+  // style?: string; //REMOVE
+  // class?: string; //REMOVE
+  // labelText?: string; //REMOVE, use `label` instead
+  // props?: Record; //REMOVE
   labelStyle?: string;
-  labelText?: string; //REMOVE, use `label` instead
 
   // Flowchart specific properties
-  labelType?: string; // REMOVE? Always use markdown string, need to check for KaTeX
+  labelType?: string; // REMOVE? Always use markdown string, need to check for KaTeX - wait with this one
   domId: string;
   // Rendering specific properties for both Flowchart and State Diagram nodes
   dir?: string; // Only relevant for isGroup true, i.e. a sub-graph or composite state.
   haveCallback?: boolean;
   link?: string;
   linkTarget?: string;
-  padding?: number; //REMOVE, use from LayoutData.config
-  props?: Record; //REMOVE
+  padding?: number; //REMOVE?, use from LayoutData.config - Keep, this could be shape specific
   shape?: string;
   tooltip?: string;
   type: string; // REMOVE, replace with isGroup: boolean, default false
@@ -137,8 +136,8 @@ export function createDomElement(node: Node): Node {
   element.id = node.domId;
 
   // Optional: Apply styles and classes to the element
-  if (node.styles) {
-    element.style.cssText = node.styles;
+  if (node.cssStyles) {
+    element.style.cssText = node.cssStyles;
   }
   if (node.classes) {
     element.className = node.classes;
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 43036f16f..08ec10c41 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -436,6 +436,9 @@ importers:
 
   packages/mermaid-layout-elk:
     dependencies:
+      d3:
+        specifier: ^7.9.0
+        version: 7.9.0
       elkjs:
         specifier: ^0.9.3
         version: 0.9.3
@@ -515,6 +518,61 @@ importers:
         specifier: ^7.0.0
         version: 7.0.0
 
+  packages/mermaid/src/vitepress:
+    dependencies:
+      '@vueuse/core':
+        specifier: ^10.1.0
+        version: 10.9.0(vue@3.4.26)
+      jiti:
+        specifier: ^1.18.2
+        version: 1.21.0
+      mermaid:
+        specifier: workspace:^
+        version: link:../..
+      vue:
+        specifier: ^3.3
+        version: 3.4.26(typescript@5.4.5)
+    devDependencies:
+      '@iconify-json/carbon':
+        specifier: ^1.1.16
+        version: 1.1.32
+      '@unocss/reset':
+        specifier: ^0.58.0
+        version: 0.58.9
+      '@vite-pwa/vitepress':
+        specifier: ^0.3.0
+        version: 0.3.1(vite-plugin-pwa@0.17.5)
+      '@vitejs/plugin-vue':
+        specifier: ^4.2.1
+        version: 4.6.2(vite@4.5.3)(vue@3.4.26)
+      fast-glob:
+        specifier: ^3.2.12
+        version: 3.3.2
+      https-localhost:
+        specifier: ^4.7.1
+        version: 4.7.1
+      pathe:
+        specifier: ^1.1.0
+        version: 1.1.2
+      unocss:
+        specifier: ^0.58.0
+        version: 0.58.9(postcss@8.4.38)(rollup@2.79.1)(vite@4.5.3)
+      unplugin-vue-components:
+        specifier: ^0.26.0
+        version: 0.26.0(rollup@2.79.1)(vue@3.4.26)
+      vite:
+        specifier: ^4.4.12
+        version: 4.5.3(@types/node@20.12.7)
+      vite-plugin-pwa:
+        specifier: ^0.17.0
+        version: 0.17.5(vite@4.5.3)(workbox-build@7.1.0)(workbox-window@7.1.0)
+      vitepress:
+        specifier: 1.0.0-rc.39
+        version: 1.0.0-rc.39(@algolia/client-search@4.23.3)(@types/node@20.12.7)(postcss@8.4.38)(search-insights@2.13.0)(typescript@5.4.5)
+      workbox-window:
+        specifier: ^7.0.0
+        version: 7.1.0
+
   packages/parser:
     dependencies:
       langium:
@@ -1118,13 +1176,13 @@ packages:
     dependencies:
       '@ampproject/remapping': 2.3.0
       '@babel/code-frame': 7.24.2
-      '@babel/generator': 7.24.4
+      '@babel/generator': 7.24.5
       '@babel/helper-compilation-targets': 7.23.6
-      '@babel/helper-module-transforms': 7.23.3(@babel/core@7.24.4)
-      '@babel/helpers': 7.24.4
+      '@babel/helper-module-transforms': 7.24.5(@babel/core@7.24.4)
+      '@babel/helpers': 7.24.5
       '@babel/parser': 7.24.5
       '@babel/template': 7.24.0
-      '@babel/traverse': 7.24.1
+      '@babel/traverse': 7.24.5
       '@babel/types': 7.24.5
       convert-source-map: 2.0.0
       debug: 4.3.4(supports-color@8.1.1)
@@ -1158,16 +1216,6 @@ packages:
       - supports-color
     dev: true
 
-  /@babel/generator@7.24.4:
-    resolution: {integrity: sha512-Xd6+v6SnjWVx/nus+y0l1sxMOTOMBkyL4+BIdbALyatQnAe/SRVjANeDPSCYaX+i1iJmuGSKf3Z+E+V/va1Hvw==}
-    engines: {node: '>=6.9.0'}
-    dependencies:
-      '@babel/types': 7.24.5
-      '@jridgewell/gen-mapping': 0.3.5
-      '@jridgewell/trace-mapping': 0.3.25
-      jsesc: 2.5.2
-    dev: true
-
   /@babel/generator@7.24.5:
     resolution: {integrity: sha512-x32i4hEXvr+iI0NEoEfDKzlemF8AmtOP8CcrRaEcpzysWuoEb1KknpcvMsHKPONoKZiDuItklgWhB18xEhr9PA==}
     engines: {node: '>=6.9.0'}
@@ -1268,13 +1316,6 @@ packages:
       '@babel/types': 7.24.5
     dev: true
 
-  /@babel/helper-member-expression-to-functions@7.23.0:
-    resolution: {integrity: sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==}
-    engines: {node: '>=6.9.0'}
-    dependencies:
-      '@babel/types': 7.24.5
-    dev: true
-
   /@babel/helper-member-expression-to-functions@7.24.5:
     resolution: {integrity: sha512-4owRteeihKWKamtqg4JmWSsEZU445xpFRXPEwp44HbgbxdWlUV1b4Agg4lkA806Lil5XM/e+FJyS0vj5T6vmcA==}
     engines: {node: '>=6.9.0'}
@@ -1289,8 +1330,8 @@ packages:
       '@babel/types': 7.24.5
     dev: true
 
-  /@babel/helper-module-transforms@7.23.3(@babel/core@7.24.4):
-    resolution: {integrity: sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==}
+  /@babel/helper-module-transforms@7.24.5(@babel/core@7.24.4):
+    resolution: {integrity: sha512-9GxeY8c2d2mdQUP1Dye0ks3VDyIMS98kt/llQ2nUId8IsWqTF0l1LkSX0/uP7l7MCDrzXS009Hyhe2gzTiGW8A==}
     engines: {node: '>=6.9.0'}
     peerDependencies:
       '@babel/core': ^7.0.0
@@ -1349,7 +1390,7 @@ packages:
     dependencies:
       '@babel/core': 7.24.5
       '@babel/helper-environment-visitor': 7.22.20
-      '@babel/helper-member-expression-to-functions': 7.23.0
+      '@babel/helper-member-expression-to-functions': 7.24.5
       '@babel/helper-optimise-call-expression': 7.22.5
     dev: true
 
@@ -1401,17 +1442,6 @@ packages:
       '@babel/types': 7.24.5
     dev: true
 
-  /@babel/helpers@7.24.4:
-    resolution: {integrity: sha512-FewdlZbSiwaVGlgT1DPANDuCHaDMiOo+D/IDYRFYjHOuv66xMSJ7fQwwODwRNAPkADIO/z1EoF/l2BCWlWABDw==}
-    engines: {node: '>=6.9.0'}
-    dependencies:
-      '@babel/template': 7.24.0
-      '@babel/traverse': 7.24.5
-      '@babel/types': 7.24.5
-    transitivePeerDependencies:
-      - supports-color
-    dev: true
-
   /@babel/helpers@7.24.5:
     resolution: {integrity: sha512-CiQmBMMpMQHwM5m01YnrM6imUG1ebgYJ+fAIW4FZe6m4qHTPaRHti+R8cggAwkdz4oXhtO4/K9JWlh+8hIfR2Q==}
     engines: {node: '>=6.9.0'}
@@ -1493,15 +1523,6 @@ packages:
       '@babel/core': 7.24.5
     dev: true
 
-  /@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.24.4):
-    resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==}
-    peerDependencies:
-      '@babel/core': ^7.0.0-0
-    dependencies:
-      '@babel/core': 7.24.4
-      '@babel/helper-plugin-utils': 7.24.5
-    dev: true
-
   /@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.24.5):
     resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==}
     peerDependencies:
@@ -1511,21 +1532,12 @@ packages:
       '@babel/helper-plugin-utils': 7.24.5
     dev: true
 
-  /@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.24.4):
+  /@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.24.5):
     resolution: {integrity: sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==}
     peerDependencies:
       '@babel/core': ^7.0.0-0
     dependencies:
-      '@babel/core': 7.24.4
-      '@babel/helper-plugin-utils': 7.24.5
-    dev: true
-
-  /@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.24.4):
-    resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==}
-    peerDependencies:
-      '@babel/core': ^7.0.0-0
-    dependencies:
-      '@babel/core': 7.24.4
+      '@babel/core': 7.24.5
       '@babel/helper-plugin-utils': 7.24.5
     dev: true
 
@@ -1586,15 +1598,6 @@ packages:
       '@babel/helper-plugin-utils': 7.24.5
     dev: true
 
-  /@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.24.4):
-    resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==}
-    peerDependencies:
-      '@babel/core': ^7.0.0-0
-    dependencies:
-      '@babel/core': 7.24.4
-      '@babel/helper-plugin-utils': 7.24.5
-    dev: true
-
   /@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.24.5):
     resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==}
     peerDependencies:
@@ -1604,15 +1607,6 @@ packages:
       '@babel/helper-plugin-utils': 7.24.5
     dev: true
 
-  /@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.24.4):
-    resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==}
-    peerDependencies:
-      '@babel/core': ^7.0.0-0
-    dependencies:
-      '@babel/core': 7.24.4
-      '@babel/helper-plugin-utils': 7.24.5
-    dev: true
-
   /@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.24.5):
     resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==}
     peerDependencies:
@@ -1622,16 +1616,6 @@ packages:
       '@babel/helper-plugin-utils': 7.24.5
     dev: true
 
-  /@babel/plugin-syntax-jsx@7.24.1(@babel/core@7.24.4):
-    resolution: {integrity: sha512-2eCtxZXf+kbkMIsXS4poTvT4Yu5rXiRa+9xGVT56raghjmBTKMpFNc9R4IDiB4emao9eO22Ox7CxuJG7BgExqA==}
-    engines: {node: '>=6.9.0'}
-    peerDependencies:
-      '@babel/core': ^7.0.0-0
-    dependencies:
-      '@babel/core': 7.24.4
-      '@babel/helper-plugin-utils': 7.24.5
-    dev: true
-
   /@babel/plugin-syntax-jsx@7.24.1(@babel/core@7.24.5):
     resolution: {integrity: sha512-2eCtxZXf+kbkMIsXS4poTvT4Yu5rXiRa+9xGVT56raghjmBTKMpFNc9R4IDiB4emao9eO22Ox7CxuJG7BgExqA==}
     engines: {node: '>=6.9.0'}
@@ -1642,15 +1626,6 @@ packages:
       '@babel/helper-plugin-utils': 7.24.5
     dev: true
 
-  /@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.24.4):
-    resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==}
-    peerDependencies:
-      '@babel/core': ^7.0.0-0
-    dependencies:
-      '@babel/core': 7.24.4
-      '@babel/helper-plugin-utils': 7.24.5
-    dev: true
-
   /@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.24.5):
     resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==}
     peerDependencies:
@@ -1660,15 +1635,6 @@ packages:
       '@babel/helper-plugin-utils': 7.24.5
     dev: true
 
-  /@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.24.4):
-    resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==}
-    peerDependencies:
-      '@babel/core': ^7.0.0-0
-    dependencies:
-      '@babel/core': 7.24.4
-      '@babel/helper-plugin-utils': 7.24.5
-    dev: true
-
   /@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.24.5):
     resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==}
     peerDependencies:
@@ -1678,15 +1644,6 @@ packages:
       '@babel/helper-plugin-utils': 7.24.5
     dev: true
 
-  /@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.24.4):
-    resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==}
-    peerDependencies:
-      '@babel/core': ^7.0.0-0
-    dependencies:
-      '@babel/core': 7.24.4
-      '@babel/helper-plugin-utils': 7.24.5
-    dev: true
-
   /@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.24.5):
     resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==}
     peerDependencies:
@@ -1696,15 +1653,6 @@ packages:
       '@babel/helper-plugin-utils': 7.24.5
     dev: true
 
-  /@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.24.4):
-    resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==}
-    peerDependencies:
-      '@babel/core': ^7.0.0-0
-    dependencies:
-      '@babel/core': 7.24.4
-      '@babel/helper-plugin-utils': 7.24.5
-    dev: true
-
   /@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.24.5):
     resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==}
     peerDependencies:
@@ -1714,15 +1662,6 @@ packages:
       '@babel/helper-plugin-utils': 7.24.5
     dev: true
 
-  /@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.24.4):
-    resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==}
-    peerDependencies:
-      '@babel/core': ^7.0.0-0
-    dependencies:
-      '@babel/core': 7.24.4
-      '@babel/helper-plugin-utils': 7.24.5
-    dev: true
-
   /@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.24.5):
     resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==}
     peerDependencies:
@@ -1732,15 +1671,6 @@ packages:
       '@babel/helper-plugin-utils': 7.24.5
     dev: true
 
-  /@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.24.4):
-    resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==}
-    peerDependencies:
-      '@babel/core': ^7.0.0-0
-    dependencies:
-      '@babel/core': 7.24.4
-      '@babel/helper-plugin-utils': 7.24.5
-    dev: true
-
   /@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.24.5):
     resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==}
     peerDependencies:
@@ -1760,16 +1690,6 @@ packages:
       '@babel/helper-plugin-utils': 7.24.5
     dev: true
 
-  /@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.24.4):
-    resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==}
-    engines: {node: '>=6.9.0'}
-    peerDependencies:
-      '@babel/core': ^7.0.0-0
-    dependencies:
-      '@babel/core': 7.24.4
-      '@babel/helper-plugin-utils': 7.24.5
-    dev: true
-
   /@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.24.5):
     resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==}
     engines: {node: '>=6.9.0'}
@@ -1780,16 +1700,6 @@ packages:
       '@babel/helper-plugin-utils': 7.24.5
     dev: true
 
-  /@babel/plugin-syntax-typescript@7.24.1(@babel/core@7.24.4):
-    resolution: {integrity: sha512-Yhnmvy5HZEnHUty6i++gcfH1/l68AHnItFHnaCv6hn9dNh0hQvvQJsxpi4BMBFN5DLeHBuucT/0DgzXif/OyRw==}
-    engines: {node: '>=6.9.0'}
-    peerDependencies:
-      '@babel/core': ^7.0.0-0
-    dependencies:
-      '@babel/core': 7.24.4
-      '@babel/helper-plugin-utils': 7.24.5
-    dev: true
-
   /@babel/plugin-syntax-typescript@7.24.1(@babel/core@7.24.5):
     resolution: {integrity: sha512-Yhnmvy5HZEnHUty6i++gcfH1/l68AHnItFHnaCv6hn9dNh0hQvvQJsxpi4BMBFN5DLeHBuucT/0DgzXif/OyRw==}
     engines: {node: '>=6.9.0'}
@@ -2506,24 +2416,6 @@ packages:
       '@babel/types': 7.24.5
     dev: true
 
-  /@babel/traverse@7.24.1:
-    resolution: {integrity: sha512-xuU6o9m68KeqZbQuDt2TcKSxUw/mrsvavlEqQ1leZ/B+C9tk6E4sRWy97WaXgvq5E+nU3cXMxv3WKOCanVMCmQ==}
-    engines: {node: '>=6.9.0'}
-    dependencies:
-      '@babel/code-frame': 7.24.2
-      '@babel/generator': 7.24.5
-      '@babel/helper-environment-visitor': 7.22.20
-      '@babel/helper-function-name': 7.23.0
-      '@babel/helper-hoist-variables': 7.22.5
-      '@babel/helper-split-export-declaration': 7.24.5
-      '@babel/parser': 7.24.5
-      '@babel/types': 7.24.5
-      debug: 4.3.4(supports-color@8.1.1)
-      globals: 11.12.0
-    transitivePeerDependencies:
-      - supports-color
-    dev: true
-
   /@babel/traverse@7.24.5:
     resolution: {integrity: sha512-7aaBLeDQ4zYcUFDUD41lJc1fG8+5IU9DaNSJAgal866FGvmD5EbWQgnEC6kO1gGLsX0esNkfnJSndbTXA3r7UA==}
     engines: {node: '>=6.9.0'}
@@ -3072,6 +2964,15 @@ packages:
     dev: true
     optional: true
 
+  /@esbuild/android-arm64@0.18.20:
+    resolution: {integrity: sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==}
+    engines: {node: '>=12'}
+    cpu: [arm64]
+    os: [android]
+    requiresBuild: true
+    dev: true
+    optional: true
+
   /@esbuild/android-arm64@0.19.12:
     resolution: {integrity: sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==}
     engines: {node: '>=12'}
@@ -3090,6 +2991,15 @@ packages:
     dev: true
     optional: true
 
+  /@esbuild/android-arm@0.18.20:
+    resolution: {integrity: sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==}
+    engines: {node: '>=12'}
+    cpu: [arm]
+    os: [android]
+    requiresBuild: true
+    dev: true
+    optional: true
+
   /@esbuild/android-arm@0.19.12:
     resolution: {integrity: sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==}
     engines: {node: '>=12'}
@@ -3108,6 +3018,15 @@ packages:
     dev: true
     optional: true
 
+  /@esbuild/android-x64@0.18.20:
+    resolution: {integrity: sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==}
+    engines: {node: '>=12'}
+    cpu: [x64]
+    os: [android]
+    requiresBuild: true
+    dev: true
+    optional: true
+
   /@esbuild/android-x64@0.19.12:
     resolution: {integrity: sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==}
     engines: {node: '>=12'}
@@ -3126,6 +3045,15 @@ packages:
     dev: true
     optional: true
 
+  /@esbuild/darwin-arm64@0.18.20:
+    resolution: {integrity: sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==}
+    engines: {node: '>=12'}
+    cpu: [arm64]
+    os: [darwin]
+    requiresBuild: true
+    dev: true
+    optional: true
+
   /@esbuild/darwin-arm64@0.19.12:
     resolution: {integrity: sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==}
     engines: {node: '>=12'}
@@ -3144,6 +3072,15 @@ packages:
     dev: true
     optional: true
 
+  /@esbuild/darwin-x64@0.18.20:
+    resolution: {integrity: sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==}
+    engines: {node: '>=12'}
+    cpu: [x64]
+    os: [darwin]
+    requiresBuild: true
+    dev: true
+    optional: true
+
   /@esbuild/darwin-x64@0.19.12:
     resolution: {integrity: sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==}
     engines: {node: '>=12'}
@@ -3162,6 +3099,15 @@ packages:
     dev: true
     optional: true
 
+  /@esbuild/freebsd-arm64@0.18.20:
+    resolution: {integrity: sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==}
+    engines: {node: '>=12'}
+    cpu: [arm64]
+    os: [freebsd]
+    requiresBuild: true
+    dev: true
+    optional: true
+
   /@esbuild/freebsd-arm64@0.19.12:
     resolution: {integrity: sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==}
     engines: {node: '>=12'}
@@ -3180,6 +3126,15 @@ packages:
     dev: true
     optional: true
 
+  /@esbuild/freebsd-x64@0.18.20:
+    resolution: {integrity: sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==}
+    engines: {node: '>=12'}
+    cpu: [x64]
+    os: [freebsd]
+    requiresBuild: true
+    dev: true
+    optional: true
+
   /@esbuild/freebsd-x64@0.19.12:
     resolution: {integrity: sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==}
     engines: {node: '>=12'}
@@ -3198,6 +3153,15 @@ packages:
     dev: true
     optional: true
 
+  /@esbuild/linux-arm64@0.18.20:
+    resolution: {integrity: sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==}
+    engines: {node: '>=12'}
+    cpu: [arm64]
+    os: [linux]
+    requiresBuild: true
+    dev: true
+    optional: true
+
   /@esbuild/linux-arm64@0.19.12:
     resolution: {integrity: sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==}
     engines: {node: '>=12'}
@@ -3216,6 +3180,15 @@ packages:
     dev: true
     optional: true
 
+  /@esbuild/linux-arm@0.18.20:
+    resolution: {integrity: sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==}
+    engines: {node: '>=12'}
+    cpu: [arm]
+    os: [linux]
+    requiresBuild: true
+    dev: true
+    optional: true
+
   /@esbuild/linux-arm@0.19.12:
     resolution: {integrity: sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==}
     engines: {node: '>=12'}
@@ -3234,6 +3207,15 @@ packages:
     dev: true
     optional: true
 
+  /@esbuild/linux-ia32@0.18.20:
+    resolution: {integrity: sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==}
+    engines: {node: '>=12'}
+    cpu: [ia32]
+    os: [linux]
+    requiresBuild: true
+    dev: true
+    optional: true
+
   /@esbuild/linux-ia32@0.19.12:
     resolution: {integrity: sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==}
     engines: {node: '>=12'}
@@ -3252,6 +3234,15 @@ packages:
     dev: true
     optional: true
 
+  /@esbuild/linux-loong64@0.18.20:
+    resolution: {integrity: sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==}
+    engines: {node: '>=12'}
+    cpu: [loong64]
+    os: [linux]
+    requiresBuild: true
+    dev: true
+    optional: true
+
   /@esbuild/linux-loong64@0.19.12:
     resolution: {integrity: sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==}
     engines: {node: '>=12'}
@@ -3270,6 +3261,15 @@ packages:
     dev: true
     optional: true
 
+  /@esbuild/linux-mips64el@0.18.20:
+    resolution: {integrity: sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==}
+    engines: {node: '>=12'}
+    cpu: [mips64el]
+    os: [linux]
+    requiresBuild: true
+    dev: true
+    optional: true
+
   /@esbuild/linux-mips64el@0.19.12:
     resolution: {integrity: sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==}
     engines: {node: '>=12'}
@@ -3288,6 +3288,15 @@ packages:
     dev: true
     optional: true
 
+  /@esbuild/linux-ppc64@0.18.20:
+    resolution: {integrity: sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==}
+    engines: {node: '>=12'}
+    cpu: [ppc64]
+    os: [linux]
+    requiresBuild: true
+    dev: true
+    optional: true
+
   /@esbuild/linux-ppc64@0.19.12:
     resolution: {integrity: sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==}
     engines: {node: '>=12'}
@@ -3306,6 +3315,15 @@ packages:
     dev: true
     optional: true
 
+  /@esbuild/linux-riscv64@0.18.20:
+    resolution: {integrity: sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==}
+    engines: {node: '>=12'}
+    cpu: [riscv64]
+    os: [linux]
+    requiresBuild: true
+    dev: true
+    optional: true
+
   /@esbuild/linux-riscv64@0.19.12:
     resolution: {integrity: sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==}
     engines: {node: '>=12'}
@@ -3324,6 +3342,15 @@ packages:
     dev: true
     optional: true
 
+  /@esbuild/linux-s390x@0.18.20:
+    resolution: {integrity: sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==}
+    engines: {node: '>=12'}
+    cpu: [s390x]
+    os: [linux]
+    requiresBuild: true
+    dev: true
+    optional: true
+
   /@esbuild/linux-s390x@0.19.12:
     resolution: {integrity: sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==}
     engines: {node: '>=12'}
@@ -3342,6 +3369,15 @@ packages:
     dev: true
     optional: true
 
+  /@esbuild/linux-x64@0.18.20:
+    resolution: {integrity: sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==}
+    engines: {node: '>=12'}
+    cpu: [x64]
+    os: [linux]
+    requiresBuild: true
+    dev: true
+    optional: true
+
   /@esbuild/linux-x64@0.19.12:
     resolution: {integrity: sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==}
     engines: {node: '>=12'}
@@ -3360,6 +3396,15 @@ packages:
     dev: true
     optional: true
 
+  /@esbuild/netbsd-x64@0.18.20:
+    resolution: {integrity: sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==}
+    engines: {node: '>=12'}
+    cpu: [x64]
+    os: [netbsd]
+    requiresBuild: true
+    dev: true
+    optional: true
+
   /@esbuild/netbsd-x64@0.19.12:
     resolution: {integrity: sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==}
     engines: {node: '>=12'}
@@ -3378,6 +3423,15 @@ packages:
     dev: true
     optional: true
 
+  /@esbuild/openbsd-x64@0.18.20:
+    resolution: {integrity: sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==}
+    engines: {node: '>=12'}
+    cpu: [x64]
+    os: [openbsd]
+    requiresBuild: true
+    dev: true
+    optional: true
+
   /@esbuild/openbsd-x64@0.19.12:
     resolution: {integrity: sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==}
     engines: {node: '>=12'}
@@ -3396,6 +3450,15 @@ packages:
     dev: true
     optional: true
 
+  /@esbuild/sunos-x64@0.18.20:
+    resolution: {integrity: sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==}
+    engines: {node: '>=12'}
+    cpu: [x64]
+    os: [sunos]
+    requiresBuild: true
+    dev: true
+    optional: true
+
   /@esbuild/sunos-x64@0.19.12:
     resolution: {integrity: sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==}
     engines: {node: '>=12'}
@@ -3414,6 +3477,15 @@ packages:
     dev: true
     optional: true
 
+  /@esbuild/win32-arm64@0.18.20:
+    resolution: {integrity: sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==}
+    engines: {node: '>=12'}
+    cpu: [arm64]
+    os: [win32]
+    requiresBuild: true
+    dev: true
+    optional: true
+
   /@esbuild/win32-arm64@0.19.12:
     resolution: {integrity: sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==}
     engines: {node: '>=12'}
@@ -3432,6 +3504,15 @@ packages:
     dev: true
     optional: true
 
+  /@esbuild/win32-ia32@0.18.20:
+    resolution: {integrity: sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==}
+    engines: {node: '>=12'}
+    cpu: [ia32]
+    os: [win32]
+    requiresBuild: true
+    dev: true
+    optional: true
+
   /@esbuild/win32-ia32@0.19.12:
     resolution: {integrity: sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==}
     engines: {node: '>=12'}
@@ -3450,6 +3531,15 @@ packages:
     dev: true
     optional: true
 
+  /@esbuild/win32-x64@0.18.20:
+    resolution: {integrity: sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==}
+    engines: {node: '>=12'}
+    cpu: [x64]
+    os: [win32]
+    requiresBuild: true
+    dev: true
+    optional: true
+
   /@esbuild/win32-x64@0.19.12:
     resolution: {integrity: sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==}
     engines: {node: '>=12'}
@@ -3842,7 +3932,7 @@ packages:
     resolution: {integrity: sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==}
     engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
     dependencies:
-      '@babel/core': 7.24.4
+      '@babel/core': 7.24.5
       '@jest/types': 29.6.3
       '@jridgewell/trace-mapping': 0.3.25
       babel-plugin-istanbul: 6.1.1
@@ -5124,6 +5214,22 @@ packages:
     resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==}
     dev: true
 
+  /@unocss/astro@0.58.9(rollup@2.79.1)(vite@4.5.3):
+    resolution: {integrity: sha512-VWfHNC0EfawFxLfb3uI+QcMGBN+ju+BYtutzeZTjilLKj31X2UpqIh8fepixL6ljgZzB3fweqg2xtUMC0gMnoQ==}
+    peerDependencies:
+      vite: ^2.9.0 || ^3.0.0-0 || ^4.0.0 || ^5.0.0-0
+    peerDependenciesMeta:
+      vite:
+        optional: true
+    dependencies:
+      '@unocss/core': 0.58.9
+      '@unocss/reset': 0.58.9
+      '@unocss/vite': 0.58.9(rollup@2.79.1)(vite@4.5.3)
+      vite: 4.5.3(@types/node@20.12.7)
+    transitivePeerDependencies:
+      - rollup
+    dev: true
+
   /@unocss/astro@0.59.4(rollup@2.79.1)(vite@5.2.10):
     resolution: {integrity: sha512-DU3OR5MMR1Uvvec4/wB9EetDASHRg19Moy6z/MiIhn8JWJ0QzWYgSeJcfUX8exomMYv6WUEQJL+CyLI34Wmn8w==}
     peerDependencies:
@@ -5140,6 +5246,28 @@ packages:
       - rollup
     dev: true
 
+  /@unocss/cli@0.58.9(rollup@2.79.1):
+    resolution: {integrity: sha512-q7qlwX3V6UaqljWUQ5gMj36yTA9eLuuRywahdQWt1ioy4aPF/MEEfnMBZf/ntrqf5tIT5TO8fE11nvCco2Q/sA==}
+    engines: {node: '>=14'}
+    hasBin: true
+    dependencies:
+      '@ampproject/remapping': 2.3.0
+      '@rollup/pluginutils': 5.1.0(rollup@2.79.1)
+      '@unocss/config': 0.58.9
+      '@unocss/core': 0.58.9
+      '@unocss/preset-uno': 0.58.9
+      cac: 6.7.14
+      chokidar: 3.6.0
+      colorette: 2.0.20
+      consola: 3.2.3
+      fast-glob: 3.3.2
+      magic-string: 0.30.10
+      pathe: 1.1.2
+      perfect-debounce: 1.0.0
+    transitivePeerDependencies:
+      - rollup
+    dev: true
+
   /@unocss/cli@0.59.4(rollup@2.79.1):
     resolution: {integrity: sha512-TT+WKedSifhsRqnpoYD2LfyYipVzEbzIU4DDGIaDNeDxGXYOGpb876zzkPDcvZSpI37IJ/efkkV7PGYpPBcQBQ==}
     engines: {node: '>=14'}
@@ -5162,6 +5290,14 @@ packages:
       - rollup
     dev: true
 
+  /@unocss/config@0.58.9:
+    resolution: {integrity: sha512-90wRXIyGNI8UenWxvHUcH4l4rgq813MsTzYWsf6ZKyLLvkFjV2b2EfGXI27GPvZ7fVE1OAqx+wJNTw8CyQxwag==}
+    engines: {node: '>=14'}
+    dependencies:
+      '@unocss/core': 0.58.9
+      unconfig: 0.3.13
+    dev: true
+
   /@unocss/config@0.59.4:
     resolution: {integrity: sha512-h3yhj+D5Ygn5R7gbK4wMrtXZX6FF5DF6YD517sSSb0XB3lxHD9PhhT4HaV1hpHknvu0cMFU3460M45+TN1TI0Q==}
     engines: {node: '>=14'}
@@ -5170,16 +5306,35 @@ packages:
       unconfig: 0.3.13
     dev: true
 
+  /@unocss/core@0.58.9:
+    resolution: {integrity: sha512-wYpPIPPsOIbIoMIDuH8ihehJk5pAZmyFKXIYO/Kro98GEOFhz6lJoLsy6/PZuitlgp2/TSlubUuWGjHWvp5osw==}
+    dev: true
+
   /@unocss/core@0.59.4:
     resolution: {integrity: sha512-bBZ1sgcAtezQVZ1BST9IS3jqcsTLyqKNjiIf7FTnX3DHpfpYuMDFzSOtmkZDzBleOLO/CtcRWjT0HwTSQAmV0A==}
     dev: true
 
+  /@unocss/extractor-arbitrary-variants@0.58.9:
+    resolution: {integrity: sha512-M/BvPdbEEMdhcFQh/z2Bf9gylO1Ky/ZnpIvKWS1YJPLt4KA7UWXSUf+ZNTFxX+X58Is5qAb5hNh/XBQmL3gbXg==}
+    dependencies:
+      '@unocss/core': 0.58.9
+    dev: true
+
   /@unocss/extractor-arbitrary-variants@0.59.4:
     resolution: {integrity: sha512-RDe4FgMGJQ+tp9GLvhPHni7Cc2O0lHBRMElVlN8LoXJAdODMICdbrEPGJlEfrc+7x/QgVFoR895KpYJh3hIgGA==}
     dependencies:
       '@unocss/core': 0.59.4
     dev: true
 
+  /@unocss/inspector@0.58.9:
+    resolution: {integrity: sha512-uRzqkCNeBmEvFePXcfIFcQPMlCXd9/bLwa5OkBthiOILwQdH1uRIW3GWAa2SWspu+kZLP0Ly3SjZ9Wqi+5ZtTw==}
+    dependencies:
+      '@unocss/core': 0.58.9
+      '@unocss/rule-utils': 0.58.9
+      gzip-size: 6.0.0
+      sirv: 2.0.4
+    dev: true
+
   /@unocss/inspector@0.59.4:
     resolution: {integrity: sha512-QczJFNDiggmekkJyNcbcZIUVwlhvxz7ZwjnSf0w7K4znxfjKkZ1hNUbqLviM1HumkTKOdT27VISW7saN/ysO4w==}
     dependencies:
@@ -5189,6 +5344,21 @@ packages:
       sirv: 2.0.4
     dev: true
 
+  /@unocss/postcss@0.58.9(postcss@8.4.38):
+    resolution: {integrity: sha512-PnKmH6Qhimw35yO6u6yx9SHaX2NmvbRNPDvMDHA/1xr3M8L0o8U88tgKbWfm65NEGF3R1zJ9A8rjtZn/LPkgPA==}
+    engines: {node: '>=14'}
+    peerDependencies:
+      postcss: ^8.4.21
+    dependencies:
+      '@unocss/config': 0.58.9
+      '@unocss/core': 0.58.9
+      '@unocss/rule-utils': 0.58.9
+      css-tree: 2.3.1
+      fast-glob: 3.3.2
+      magic-string: 0.30.10
+      postcss: 8.4.38
+    dev: true
+
   /@unocss/postcss@0.59.4(postcss@8.4.38):
     resolution: {integrity: sha512-KVz+AD7McHKp7VEWHbFahhyyVEo0oP/e1vnuNSuPlHthe+1V2zfH6lps+iJcvfL2072r5J+0PvD/1kOp5ryUSg==}
     engines: {node: '>=14'}
@@ -5204,12 +5374,28 @@ packages:
       postcss: 8.4.38
     dev: true
 
+  /@unocss/preset-attributify@0.58.9:
+    resolution: {integrity: sha512-ucP+kXRFcwmBmHohUVv31bE/SejMAMo7Hjb0QcKVLyHlzRWUJsfNR+jTAIGIUSYxN7Q8MeigYsongGo3nIeJnQ==}
+    dependencies:
+      '@unocss/core': 0.58.9
+    dev: true
+
   /@unocss/preset-attributify@0.59.4:
     resolution: {integrity: sha512-BeogWuYaIakC1gmOZFFCjFVWmu/m3AqEX8UYQS6tY6lAaK2L4Qf4AstYBlT2zAMxy9LNxPDxFQrvfSfFk5Klsg==}
     dependencies:
       '@unocss/core': 0.59.4
     dev: true
 
+  /@unocss/preset-icons@0.58.9:
+    resolution: {integrity: sha512-9dS48+yAunsbS0ylOW2Wisozwpn3nGY1CqTiidkUnrMnrZK3al579A7srUX9NyPWWDjprO7eU/JkWbdDQSmFFA==}
+    dependencies:
+      '@iconify/utils': 2.1.23
+      '@unocss/core': 0.58.9
+      ofetch: 1.3.4
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
   /@unocss/preset-icons@0.59.4:
     resolution: {integrity: sha512-Afjwh5oC4KRE8TNZDUkRK6hvvV1wKLrS1e5trniE0B0AM9HK3PBolQaIU7QmzPv6WQrog+MZgIwafg1eqsPUCA==}
     dependencies:
@@ -5220,6 +5406,14 @@ packages:
       - supports-color
     dev: true
 
+  /@unocss/preset-mini@0.58.9:
+    resolution: {integrity: sha512-m4aDGYtueP8QGsU3FsyML63T/w5Mtr4htme2jXy6m50+tzC1PPHaIBstMTMQfLc6h8UOregPJyGHB5iYQZGEvQ==}
+    dependencies:
+      '@unocss/core': 0.58.9
+      '@unocss/extractor-arbitrary-variants': 0.58.9
+      '@unocss/rule-utils': 0.58.9
+    dev: true
+
   /@unocss/preset-mini@0.59.4:
     resolution: {integrity: sha512-ZLywGrXi1OCr4My5vX2rLUb5Xgx6ufR9WTQOvpQJGBdIV/jnZn/pyE5avCs476SnOq2K172lnd8mFmTK7/zArA==}
     dependencies:
@@ -5228,12 +5422,25 @@ packages:
       '@unocss/rule-utils': 0.59.4
     dev: true
 
+  /@unocss/preset-tagify@0.58.9:
+    resolution: {integrity: sha512-obh75XrRmxYwrQMflzvhQUMeHwd/R9bEDhTWUW9aBTolBy4eNypmQwOhHCKh5Xi4Dg6o0xj6GWC/jcCj1SPLog==}
+    dependencies:
+      '@unocss/core': 0.58.9
+    dev: true
+
   /@unocss/preset-tagify@0.59.4:
     resolution: {integrity: sha512-vWMdTUoghOSmTbdmZtERssffmdUdOuhh4vUdl0R8Kv6KxB0PkvEFCu2FItn97nRJdSPlZSFxxDkaOIg9w+STNQ==}
     dependencies:
       '@unocss/core': 0.59.4
     dev: true
 
+  /@unocss/preset-typography@0.58.9:
+    resolution: {integrity: sha512-hrsaqKlcZni3Vh4fwXC+lP9e92FQYbqtmlZw2jpxlVwwH5aLzwk4d4MiFQGyhCfzuSDYm0Zd52putFVV02J7bA==}
+    dependencies:
+      '@unocss/core': 0.58.9
+      '@unocss/preset-mini': 0.58.9
+    dev: true
+
   /@unocss/preset-typography@0.59.4:
     resolution: {integrity: sha512-ZX9bxZUqlXK1qEDzO5lkK96ICt9itR/oNyn/7mMc1JPqwj263LumQMn5silocgzoLSUXEeq//L6GylqYjkL8GA==}
     dependencies:
@@ -5241,6 +5448,15 @@ packages:
       '@unocss/preset-mini': 0.59.4
     dev: true
 
+  /@unocss/preset-uno@0.58.9:
+    resolution: {integrity: sha512-Fze+X2Z/EegCkRdDRgwwvFBmXBenNR1AG8KxAyz8iPeWbhOBaRra2sn2ScryrfH6SbJHpw26ZyJXycAdS0Fq3A==}
+    dependencies:
+      '@unocss/core': 0.58.9
+      '@unocss/preset-mini': 0.58.9
+      '@unocss/preset-wind': 0.58.9
+      '@unocss/rule-utils': 0.58.9
+    dev: true
+
   /@unocss/preset-uno@0.59.4:
     resolution: {integrity: sha512-G1f8ZluplvXZ3bERj+sM/8zzY//XD++nNOlAQNKOANSVht3qEoJebrfEiMClNpA5qW5VWOZhEhPkh0M7GsXtnA==}
     dependencies:
@@ -5250,6 +5466,13 @@ packages:
       '@unocss/rule-utils': 0.59.4
     dev: true
 
+  /@unocss/preset-web-fonts@0.58.9:
+    resolution: {integrity: sha512-XtiO+Z+RYnNYomNkS2XxaQiY++CrQZKOfNGw5htgIrb32QtYVQSkyYQ3jDw7JmMiCWlZ4E72cV/zUb++WrZLxg==}
+    dependencies:
+      '@unocss/core': 0.58.9
+      ofetch: 1.3.4
+    dev: true
+
   /@unocss/preset-web-fonts@0.59.4:
     resolution: {integrity: sha512-ehutTjKHnf2KPmdatN42N9a8+y+glKSU3UlcBRNsVIIXVIlaBQuPVGZSPhnMtrKD17IgWylXq2K6RJK+ab0hZA==}
     dependencies:
@@ -5257,6 +5480,14 @@ packages:
       ofetch: 1.3.4
     dev: true
 
+  /@unocss/preset-wind@0.58.9:
+    resolution: {integrity: sha512-7l+7Vx5UoN80BmJKiqDXaJJ6EUqrnUQYv8NxCThFi5lYuHzxsYWZPLU3k3XlWRUQt8XL+6rYx7mMBmD7EUSHyw==}
+    dependencies:
+      '@unocss/core': 0.58.9
+      '@unocss/preset-mini': 0.58.9
+      '@unocss/rule-utils': 0.58.9
+    dev: true
+
   /@unocss/preset-wind@0.59.4:
     resolution: {integrity: sha512-CNX6w0ZpSQg/i1oF0/WKWzto8PtLqoknC5h8JmmcGb7VsyBQeV0oNnhbURxpbuMEhbv1MWVIGvk8a+P6y0rFkQ==}
     dependencies:
@@ -5265,10 +5496,22 @@ packages:
       '@unocss/rule-utils': 0.59.4
     dev: true
 
+  /@unocss/reset@0.58.9:
+    resolution: {integrity: sha512-nA2pg3tnwlquq+FDOHyKwZvs20A6iBsKPU7Yjb48JrNnzoaXqE+O9oN6782IG2yKVW4AcnsAnAnM4cxXhGzy1w==}
+    dev: true
+
   /@unocss/reset@0.59.4:
     resolution: {integrity: sha512-Upy4xzdWl4RChbLAXBq1BoR4WqxXMoIfjvtcwSZcZK2sylXCFAseSWnyzJFdSiXPqNfmMuNgPXgiSxiQB+cmNA==}
     dev: true
 
+  /@unocss/rule-utils@0.58.9:
+    resolution: {integrity: sha512-45bDa+elmlFLthhJmKr2ltKMAB0yoXnDMQ6Zp5j3OiRB7dDMBkwYRPvHLvIe+34Ey7tDt/kvvDPtWMpPl2quUQ==}
+    engines: {node: '>=14'}
+    dependencies:
+      '@unocss/core': 0.58.9
+      magic-string: 0.30.10
+    dev: true
+
   /@unocss/rule-utils@0.59.4:
     resolution: {integrity: sha512-1qoLJlBWAkS4D4sg73990S1MT7E8E5md/YhopKjTQuEC9SyeVmEg+5pR/Xd8xhPKMqbcuBPl/DS8b6l/GQO56A==}
     engines: {node: '>=14'}
@@ -5277,10 +5520,25 @@ packages:
       magic-string: 0.30.10
     dev: true
 
+  /@unocss/scope@0.58.9:
+    resolution: {integrity: sha512-BIwcpx0R3bE0rYa9JVDJTk0GX32EBvnbvufBpNkWfC5tb7g+B7nMkVq9ichanksYCCxrIQQo0mrIz5PNzu9sGA==}
+    dev: true
+
   /@unocss/scope@0.59.4:
     resolution: {integrity: sha512-wBQJ39kw4Tfj4km7AoGvSIobPKVnRZVsgc0bema5Y0PL3g1NeVQ/LopBI2zEJWdpxGXUWxSDsXm7BZo6qVlD/A==}
     dev: true
 
+  /@unocss/transformer-attributify-jsx-babel@0.58.9:
+    resolution: {integrity: sha512-UGaQoGZg+3QrsPtnGHPECmsGn4EQb2KSdZ4eGEn2YssjKv+CcQhzRvpEUgnuF/F+jGPkCkS/G/YEQBHRWBY54Q==}
+    dependencies:
+      '@babel/core': 7.24.5
+      '@babel/plugin-syntax-jsx': 7.24.1(@babel/core@7.24.5)
+      '@babel/preset-typescript': 7.24.1(@babel/core@7.24.5)
+      '@unocss/core': 0.58.9
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
   /@unocss/transformer-attributify-jsx-babel@0.59.4:
     resolution: {integrity: sha512-xtCRSgeTaDBiNJLVX7oOSFe63JiFB5nrdK23PHn3IlZM9O7Bxx4ZxI3MQJtFZFQNE+INFko+DVyY1WiFEm1p/Q==}
     dependencies:
@@ -5292,18 +5550,38 @@ packages:
       - supports-color
     dev: true
 
+  /@unocss/transformer-attributify-jsx@0.58.9:
+    resolution: {integrity: sha512-jpL3PRwf8t43v1agUdQn2EHGgfdWfvzsMxFtoybO88xzOikzAJaaouteNtojc/fQat2T9iBduDxVj5egdKmhdQ==}
+    dependencies:
+      '@unocss/core': 0.58.9
+    dev: true
+
   /@unocss/transformer-attributify-jsx@0.59.4:
     resolution: {integrity: sha512-m4b83utzKMfUQH/45V2QkjJoXd8Tu2pRP1nic91Xf7QRceyKDD+BxoTneo2JNC2K274cQu7HqqotnCm2aFfEGw==}
     dependencies:
       '@unocss/core': 0.59.4
     dev: true
 
+  /@unocss/transformer-compile-class@0.58.9:
+    resolution: {integrity: sha512-l2VpCqelJ6Tgc1kfSODxBtg7fCGPVRr2EUzTg1LrGYKa2McbKuc/wV/2DWKHGxL6+voWi7a2C9XflqGDXXutuQ==}
+    dependencies:
+      '@unocss/core': 0.58.9
+    dev: true
+
   /@unocss/transformer-compile-class@0.59.4:
     resolution: {integrity: sha512-Vgk2OCLPW0pU+Uzr1IgDtHVspSBb+gPrQFkV+5gxHk9ZdKi3oYKxLuufVWYDSwv7o9yfQGbYrMH9YLsjRsnA7Q==}
     dependencies:
       '@unocss/core': 0.59.4
     dev: true
 
+  /@unocss/transformer-directives@0.58.9:
+    resolution: {integrity: sha512-pLOUsdoY2ugVntJXg0xuGjO9XZ2xCiMxTPRtpZ4TsEzUtdEzMswR06Y8VWvNciTB/Zqxcz9ta8rD0DKePOfSuw==}
+    dependencies:
+      '@unocss/core': 0.58.9
+      '@unocss/rule-utils': 0.58.9
+      css-tree: 2.3.1
+    dev: true
+
   /@unocss/transformer-directives@0.59.4:
     resolution: {integrity: sha512-nXUTEclUbs0vQ4KfLhKt4J/5SLSEq1az2FNlJmiXMmqmn75X89OrtCu2OJu9sGXhn+YyBApxgcSSdxmtpqMi1Q==}
     dependencies:
@@ -5312,12 +5590,38 @@ packages:
       css-tree: 2.3.1
     dev: true
 
+  /@unocss/transformer-variant-group@0.58.9:
+    resolution: {integrity: sha512-3A6voHSnFcyw6xpcZT6oxE+KN4SHRnG4z862tdtWvRGcN+jGyNr20ylEZtnbk4xj0VNMeGHHQRZ0WLvmrAwvOQ==}
+    dependencies:
+      '@unocss/core': 0.58.9
+    dev: true
+
   /@unocss/transformer-variant-group@0.59.4:
     resolution: {integrity: sha512-9XLixxn1NRgP62Kj4R/NC/rpqhql5F2s6ulJ8CAMTEbd/NylVhEANluPGDVUGcLJ4cj6E02hFa8C1PLGSm7/xw==}
     dependencies:
       '@unocss/core': 0.59.4
     dev: true
 
+  /@unocss/vite@0.58.9(rollup@2.79.1)(vite@4.5.3):
+    resolution: {integrity: sha512-mmppBuulAHCal+sC0Qz36Y99t0HicAmznpj70Kzwl7g/yvXwm58/DW2OnpCWw+uA8/JBft/+z3zE+XvrI+T1HA==}
+    peerDependencies:
+      vite: ^2.9.0 || ^3.0.0-0 || ^4.0.0 || ^5.0.0-0
+    dependencies:
+      '@ampproject/remapping': 2.3.0
+      '@rollup/pluginutils': 5.1.0(rollup@2.79.1)
+      '@unocss/config': 0.58.9
+      '@unocss/core': 0.58.9
+      '@unocss/inspector': 0.58.9
+      '@unocss/scope': 0.58.9
+      '@unocss/transformer-directives': 0.58.9
+      chokidar: 3.6.0
+      fast-glob: 3.3.2
+      magic-string: 0.30.10
+      vite: 4.5.3(@types/node@20.12.7)
+    transitivePeerDependencies:
+      - rollup
+    dev: true
+
   /@unocss/vite@0.59.4(rollup@2.79.1)(vite@5.2.10):
     resolution: {integrity: sha512-q7GN7vkQYn79n7vYIUlaa7gXGwc7pk0Qo3z3ZFwWGE43/DtZnn2Hwl5UjgBAgi9McA+xqHJEHRsJnI7HJPHUYA==}
     peerDependencies:
@@ -5338,6 +5642,14 @@ packages:
       - rollup
     dev: true
 
+  /@vite-pwa/vitepress@0.3.1(vite-plugin-pwa@0.17.5):
+    resolution: {integrity: sha512-krgiYQCWXUkpQCx+IHdsanFFpAzfH5pY86MARDa6as5ZNmG18mb/gC6MEahFV67V0xfMfTaNL4B8dQNzzcikLw==}
+    peerDependencies:
+      vite-plugin-pwa: '>=0.17.2 <1'
+    dependencies:
+      vite-plugin-pwa: 0.17.5(vite@4.5.3)(workbox-build@7.1.0)(workbox-window@7.1.0)
+    dev: true
+
   /@vite-pwa/vitepress@0.4.0(vite-plugin-pwa@0.19.8):
     resolution: {integrity: sha512-MrsSCK5EBCzQAQgq5/3XHaFIjkypda58Wzy6PkDwZoRHnWexik0C2GUxMOe+RA+qdpGxB0mEkhqajeOmuYMvhw==}
     peerDependencies:
@@ -5350,6 +5662,17 @@ packages:
       vite-plugin-pwa: 0.19.8(vite@5.2.10)(workbox-build@7.1.0)(workbox-window@7.0.0)
     dev: true
 
+  /@vitejs/plugin-vue@4.6.2(vite@4.5.3)(vue@3.4.26):
+    resolution: {integrity: sha512-kqf7SGFoG+80aZG6Pf+gsZIVvGSCKE98JbiWqcCV9cThtg91Jav0yvYFC9Zb+jKetNGF6ZKeoaxgZfND21fWKw==}
+    engines: {node: ^14.18.0 || >=16.0.0}
+    peerDependencies:
+      vite: ^4.0.0 || ^5.0.0
+      vue: ^3.2.25
+    dependencies:
+      vite: 4.5.3(@types/node@20.12.7)
+      vue: 3.4.26(typescript@5.4.5)
+    dev: true
+
   /@vitejs/plugin-vue@5.0.4(vite@5.2.10)(vue@3.4.26):
     resolution: {integrity: sha512-WS3hevEszI6CEVEx28F8RjTX97k3KsrcY6kvTg7+Whm5y3oYvcqzVeGCU3hxSAn4uY2CLCkeokkGKpoctccilQ==}
     engines: {node: ^18.0.0 || >=20.0.0}
@@ -5523,7 +5846,6 @@ packages:
 
   /@vue/devtools-api@6.6.1:
     resolution: {integrity: sha512-LgPscpE3Vs0x96PzSSB4IGVSZXZBZHpfxs+ZA1d+VEPwHdOXowy/Y2CsvCAIFrf+ssVU1pD1jidj505EpUnfbA==}
-    dev: false
 
   /@vue/devtools-api@7.1.3(vue@3.4.26):
     resolution: {integrity: sha512-W8IwFJ/o5iUk78jpqhvScbgCsPiOp2uileDVC0NDtW38gCWhsnu9SeBTjcdu3lbwLdsjc+H1c5Msd/x9ApbcFA==}
@@ -6343,17 +6665,17 @@ packages:
       - debug
     dev: true
 
-  /babel-jest@29.7.0(@babel/core@7.24.4):
+  /babel-jest@29.7.0(@babel/core@7.24.5):
     resolution: {integrity: sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==}
     engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
     peerDependencies:
       '@babel/core': ^7.8.0
     dependencies:
-      '@babel/core': 7.24.4
+      '@babel/core': 7.24.5
       '@jest/transform': 29.7.0
       '@types/babel__core': 7.20.5
       babel-plugin-istanbul: 6.1.1
-      babel-preset-jest: 29.6.3(@babel/core@7.24.4)
+      babel-preset-jest: 29.6.3(@babel/core@7.24.5)
       chalk: 4.1.2
       graceful-fs: 4.2.11
       slash: 3.0.0
@@ -6433,35 +6755,35 @@ packages:
       - supports-color
     dev: true
 
-  /babel-preset-current-node-syntax@1.0.1(@babel/core@7.24.4):
+  /babel-preset-current-node-syntax@1.0.1(@babel/core@7.24.5):
     resolution: {integrity: sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==}
     peerDependencies:
       '@babel/core': ^7.0.0
     dependencies:
-      '@babel/core': 7.24.4
-      '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.24.4)
-      '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.24.4)
-      '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.24.4)
-      '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.24.4)
-      '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.24.4)
-      '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.24.4)
-      '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.24.4)
-      '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.24.4)
-      '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.24.4)
-      '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.24.4)
-      '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.24.4)
-      '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.24.4)
+      '@babel/core': 7.24.5
+      '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.24.5)
+      '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.24.5)
+      '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.24.5)
+      '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.24.5)
+      '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.24.5)
+      '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.24.5)
+      '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.24.5)
+      '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.24.5)
+      '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.24.5)
+      '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.24.5)
+      '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.24.5)
+      '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.24.5)
     dev: true
 
-  /babel-preset-jest@29.6.3(@babel/core@7.24.4):
+  /babel-preset-jest@29.6.3(@babel/core@7.24.5):
     resolution: {integrity: sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==}
     engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
     peerDependencies:
       '@babel/core': ^7.0.0
     dependencies:
-      '@babel/core': 7.24.4
+      '@babel/core': 7.24.5
       babel-plugin-jest-hoist: 29.6.3
-      babel-preset-current-node-syntax: 1.0.1(@babel/core@7.24.4)
+      babel-preset-current-node-syntax: 1.0.1(@babel/core@7.24.5)
     dev: true
 
   /bail@2.0.2:
@@ -8445,6 +8767,36 @@ packages:
       es6-symbol: 3.1.4
     dev: true
 
+  /esbuild@0.18.20:
+    resolution: {integrity: sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==}
+    engines: {node: '>=12'}
+    hasBin: true
+    requiresBuild: true
+    optionalDependencies:
+      '@esbuild/android-arm': 0.18.20
+      '@esbuild/android-arm64': 0.18.20
+      '@esbuild/android-x64': 0.18.20
+      '@esbuild/darwin-arm64': 0.18.20
+      '@esbuild/darwin-x64': 0.18.20
+      '@esbuild/freebsd-arm64': 0.18.20
+      '@esbuild/freebsd-x64': 0.18.20
+      '@esbuild/linux-arm': 0.18.20
+      '@esbuild/linux-arm64': 0.18.20
+      '@esbuild/linux-ia32': 0.18.20
+      '@esbuild/linux-loong64': 0.18.20
+      '@esbuild/linux-mips64el': 0.18.20
+      '@esbuild/linux-ppc64': 0.18.20
+      '@esbuild/linux-riscv64': 0.18.20
+      '@esbuild/linux-s390x': 0.18.20
+      '@esbuild/linux-x64': 0.18.20
+      '@esbuild/netbsd-x64': 0.18.20
+      '@esbuild/openbsd-x64': 0.18.20
+      '@esbuild/sunos-x64': 0.18.20
+      '@esbuild/win32-arm64': 0.18.20
+      '@esbuild/win32-ia32': 0.18.20
+      '@esbuild/win32-x64': 0.18.20
+    dev: true
+
   /esbuild@0.19.12:
     resolution: {integrity: sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==}
     engines: {node: '>=12'}
@@ -9687,7 +10039,7 @@ packages:
     dependencies:
       foreground-child: 3.1.1
       jackspeak: 2.3.6
-      minimatch: 9.0.3
+      minimatch: 9.0.4
       minipass: 7.0.4
       path-scurry: 1.10.1
     dev: true
@@ -10791,11 +11143,11 @@ packages:
       ts-node:
         optional: true
     dependencies:
-      '@babel/core': 7.24.4
+      '@babel/core': 7.24.5
       '@jest/test-sequencer': 29.7.0
       '@jest/types': 29.6.3
       '@types/node': 20.12.7
-      babel-jest: 29.7.0(@babel/core@7.24.4)
+      babel-jest: 29.7.0(@babel/core@7.24.5)
       chalk: 4.1.2
       ci-info: 3.9.0
       deepmerge: 4.3.1
@@ -11048,15 +11400,15 @@ packages:
     resolution: {integrity: sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==}
     engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
     dependencies:
-      '@babel/core': 7.24.4
-      '@babel/generator': 7.24.4
-      '@babel/plugin-syntax-jsx': 7.24.1(@babel/core@7.24.4)
-      '@babel/plugin-syntax-typescript': 7.24.1(@babel/core@7.24.4)
+      '@babel/core': 7.24.5
+      '@babel/generator': 7.24.5
+      '@babel/plugin-syntax-jsx': 7.24.1(@babel/core@7.24.5)
+      '@babel/plugin-syntax-typescript': 7.24.1(@babel/core@7.24.5)
       '@babel/types': 7.24.5
       '@jest/expect-utils': 29.7.0
       '@jest/transform': 29.7.0
       '@jest/types': 29.6.3
-      babel-preset-current-node-syntax: 1.0.1(@babel/core@7.24.4)
+      babel-preset-current-node-syntax: 1.0.1(@babel/core@7.24.5)
       chalk: 4.1.2
       expect: 29.7.0
       graceful-fs: 4.2.11
@@ -11705,15 +12057,9 @@ packages:
     engines: {node: '>=8'}
     dev: true
 
-  /lru-cache@10.2.0:
-    resolution: {integrity: sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==}
-    engines: {node: 14 || >=16.14}
-    dev: true
-
   /lru-cache@10.2.1:
     resolution: {integrity: sha512-tS24spDe/zXhWbNPErCHs/AGOzbKGHT+ybSBqmdLm8WZ1xXLWvH8Qn71QPAlqVhd0qUTWjy+Kl9JmISgDdEjsA==}
     engines: {node: 14 || >=16.14}
-    dev: false
 
   /lru-cache@5.1.1:
     resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
@@ -12936,7 +13282,7 @@ packages:
     resolution: {integrity: sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==}
     engines: {node: '>=16 || 14 >=14.17'}
     dependencies:
-      lru-cache: 10.2.0
+      lru-cache: 10.2.1
       minipass: 7.0.4
     dev: true
 
@@ -13472,7 +13818,7 @@ packages:
     resolution: {integrity: sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg==}
     engines: {node: '>= 0.10'}
     dependencies:
-      resolve: 1.22.4
+      resolve: 1.22.8
     dev: true
 
   /regenerate-unicode-properties@10.1.1:
@@ -13771,6 +14117,14 @@ packages:
       fsevents: 2.3.3
     dev: true
 
+  /rollup@3.29.4:
+    resolution: {integrity: sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==}
+    engines: {node: '>=14.18.0', npm: '>=8.0.0'}
+    hasBin: true
+    optionalDependencies:
+      fsevents: 2.3.3
+    dev: true
+
   /rollup@4.17.2:
     resolution: {integrity: sha512-/9ClTJPByC0U4zNLowV1tMBe8yMEAxewtR3cUNX5BoEpGH3dQEWpJLr6CLp0fPdYRF/fzVOgvDb1zXuakwF5kQ==}
     engines: {node: '>=18.0.0', npm: '>=8.0.0'}
@@ -14080,6 +14434,22 @@ packages:
       '@shikijs/core': 1.4.0
     dev: true
 
+  /shikiji-core@0.9.19:
+    resolution: {integrity: sha512-AFJu/vcNT21t0e6YrfadZ+9q86gvPum6iywRyt1OtIPjPFe25RQnYJyxHQPMLKCCWA992TPxmEmbNcOZCAJclw==}
+    dev: true
+
+  /shikiji-transformers@0.9.19:
+    resolution: {integrity: sha512-lGLI7Z8frQrIBbhZ74/eiJtxMoCQRbpaHEB+gcfvdIy+ZFaAtXncJGnc52932/UET+Y4GyKtwwC/vjWUCp+c/Q==}
+    dependencies:
+      shikiji: 0.9.19
+    dev: true
+
+  /shikiji@0.9.19:
+    resolution: {integrity: sha512-Kw2NHWktdcdypCj1GkKpXH4o6Vxz8B8TykPlPuLHOGSV8VkhoCLcFOH4k19K4LXAQYRQmxg+0X/eM+m2sLhAkg==}
+    dependencies:
+      shikiji-core: 0.9.19
+    dev: true
+
   /side-channel@1.0.6:
     resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==}
     engines: {node: '>= 0.4'}
@@ -15253,6 +15623,45 @@ packages:
     engines: {node: '>= 10.0.0'}
     dev: true
 
+  /unocss@0.58.9(postcss@8.4.38)(rollup@2.79.1)(vite@4.5.3):
+    resolution: {integrity: sha512-aqANXXP0RrtN4kSaTLn/7I6wh8o45LUdVgPzGu7Fan2DfH2+wpIs6frlnlHlOymnb+52dp6kXluQinddaUKW1A==}
+    engines: {node: '>=14'}
+    peerDependencies:
+      '@unocss/webpack': 0.58.9
+      vite: ^2.9.0 || ^3.0.0-0 || ^4.0.0 || ^5.0.0-0
+    peerDependenciesMeta:
+      '@unocss/webpack':
+        optional: true
+      vite:
+        optional: true
+    dependencies:
+      '@unocss/astro': 0.58.9(rollup@2.79.1)(vite@4.5.3)
+      '@unocss/cli': 0.58.9(rollup@2.79.1)
+      '@unocss/core': 0.58.9
+      '@unocss/extractor-arbitrary-variants': 0.58.9
+      '@unocss/postcss': 0.58.9(postcss@8.4.38)
+      '@unocss/preset-attributify': 0.58.9
+      '@unocss/preset-icons': 0.58.9
+      '@unocss/preset-mini': 0.58.9
+      '@unocss/preset-tagify': 0.58.9
+      '@unocss/preset-typography': 0.58.9
+      '@unocss/preset-uno': 0.58.9
+      '@unocss/preset-web-fonts': 0.58.9
+      '@unocss/preset-wind': 0.58.9
+      '@unocss/reset': 0.58.9
+      '@unocss/transformer-attributify-jsx': 0.58.9
+      '@unocss/transformer-attributify-jsx-babel': 0.58.9
+      '@unocss/transformer-compile-class': 0.58.9
+      '@unocss/transformer-directives': 0.58.9
+      '@unocss/transformer-variant-group': 0.58.9
+      '@unocss/vite': 0.58.9(rollup@2.79.1)(vite@4.5.3)
+      vite: 4.5.3(@types/node@20.12.7)
+    transitivePeerDependencies:
+      - postcss
+      - rollup
+      - supports-color
+    dev: true
+
   /unocss@0.59.4(postcss@8.4.38)(rollup@2.79.1)(vite@5.2.10):
     resolution: {integrity: sha512-QmCVjRObvVu/gsGrJGVt0NnrdhFFn314BUZn2WQyXV9rIvHLRmG5bIu0j5vibJkj7ZhFchTrnTM1pTFXP1xt5g==}
     engines: {node: '>=14'}
@@ -15469,6 +15878,24 @@ packages:
       - supports-color
     dev: true
 
+  /vite-plugin-pwa@0.17.5(vite@4.5.3)(workbox-build@7.1.0)(workbox-window@7.1.0):
+    resolution: {integrity: sha512-UxRNPiJBzh4tqU/vc8G2TxmrUTzT6BqvSzhszLk62uKsf+npXdvLxGDz9C675f4BJi6MbD2tPnJhi5txlMzxbQ==}
+    engines: {node: '>=16.0.0'}
+    peerDependencies:
+      vite: ^3.1.0 || ^4.0.0 || ^5.0.0
+      workbox-build: ^7.0.0
+      workbox-window: ^7.0.0
+    dependencies:
+      debug: 4.3.4(supports-color@8.1.1)
+      fast-glob: 3.3.2
+      pretty-bytes: 6.1.1
+      vite: 4.5.3(@types/node@20.12.7)
+      workbox-build: 7.1.0
+      workbox-window: 7.1.0
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
   /vite-plugin-pwa@0.19.8(vite@5.2.10)(workbox-build@7.1.0)(workbox-window@7.0.0):
     resolution: {integrity: sha512-e1oK0dfhzhDhY3VBuML6c0h8Xfx6EkOVYqolj7g+u8eRfdauZe5RLteCIA/c5gH0CBQ0CNFAuv/AFTx4Z7IXTw==}
     engines: {node: '>=16.0.0'}
@@ -15491,6 +15918,42 @@ packages:
       - supports-color
     dev: true
 
+  /vite@4.5.3(@types/node@20.12.7):
+    resolution: {integrity: sha512-kQL23kMeX92v3ph7IauVkXkikdDRsYMGTVl5KY2E9OY4ONLvkHf04MDTbnfo6NKxZiDLWzVpP5oTa8hQD8U3dg==}
+    engines: {node: ^14.18.0 || >=16.0.0}
+    hasBin: true
+    peerDependencies:
+      '@types/node': '>= 14'
+      less: '*'
+      lightningcss: ^1.21.0
+      sass: '*'
+      stylus: '*'
+      sugarss: '*'
+      terser: ^5.4.0
+    peerDependenciesMeta:
+      '@types/node':
+        optional: true
+      less:
+        optional: true
+      lightningcss:
+        optional: true
+      sass:
+        optional: true
+      stylus:
+        optional: true
+      sugarss:
+        optional: true
+      terser:
+        optional: true
+    dependencies:
+      '@types/node': 20.12.7
+      esbuild: 0.18.20
+      postcss: 8.4.38
+      rollup: 3.29.4
+    optionalDependencies:
+      fsevents: 2.3.3
+    dev: true
+
   /vite@5.2.10(@types/node@20.12.7):
     resolution: {integrity: sha512-PAzgUZbP7msvQvqdSD+ErD5qGnSFiGOoWmV5yAKUEI0kdhjbH6nMWVyZQC/hSc4aXwc0oJ9aEdIiF9Oje0JFCw==}
     engines: {node: ^18.0.0 || >=20.0.0}
@@ -15544,6 +16007,62 @@ packages:
       vue: 3.4.26(typescript@5.4.5)
     dev: true
 
+  /vitepress@1.0.0-rc.39(@algolia/client-search@4.23.3)(@types/node@20.12.7)(postcss@8.4.38)(search-insights@2.13.0)(typescript@5.4.5):
+    resolution: {integrity: sha512-EcgoRlAAp37WOxUOYv45oxyhLrcy3Upey+mKpqW3ldsg6Ol4trPndRBk2GO0QiSvEKlb9BMerk49D/bFICN6kg==}
+    hasBin: true
+    peerDependencies:
+      markdown-it-mathjax3: ^4.3.2
+      postcss: ^8.4.33
+    peerDependenciesMeta:
+      markdown-it-mathjax3:
+        optional: true
+      postcss:
+        optional: true
+    dependencies:
+      '@docsearch/css': 3.6.0
+      '@docsearch/js': 3.6.0(@algolia/client-search@4.23.3)(search-insights@2.13.0)
+      '@types/markdown-it': 13.0.8
+      '@vitejs/plugin-vue': 5.0.4(vite@5.2.10)(vue@3.4.26)
+      '@vue/devtools-api': 6.6.1
+      '@vueuse/core': 10.9.0(vue@3.4.26)
+      '@vueuse/integrations': 10.9.0(focus-trap@7.5.4)(vue@3.4.26)
+      focus-trap: 7.5.4
+      mark.js: 8.11.1
+      minisearch: 6.3.0
+      postcss: 8.4.38
+      shikiji: 0.9.19
+      shikiji-core: 0.9.19
+      shikiji-transformers: 0.9.19
+      vite: 5.2.10(@types/node@20.12.7)
+      vue: 3.4.26(typescript@5.4.5)
+    transitivePeerDependencies:
+      - '@algolia/client-search'
+      - '@types/node'
+      - '@types/react'
+      - '@vue/composition-api'
+      - async-validator
+      - axios
+      - change-case
+      - drauu
+      - fuse.js
+      - idb-keyval
+      - jwt-decode
+      - less
+      - lightningcss
+      - nprogress
+      - qrcode
+      - react
+      - react-dom
+      - sass
+      - search-insights
+      - sortablejs
+      - stylus
+      - sugarss
+      - terser
+      - typescript
+      - universal-cookie
+    dev: true
+
   /vitepress@1.1.0(@algolia/client-search@4.23.3)(@types/node@20.12.7)(postcss@8.4.38)(search-insights@2.13.0)(typescript@5.4.5):
     resolution: {integrity: sha512-G+NS5I2OETxC0SfGAMDO75JWNkrcir0UCptuhQMNoaZhhlqvYtTDQhph4qGc5dtiTtZkcFa/bCcSx+A2gSS3lA==}
     hasBin: true