diff --git a/.gitignore b/.gitignore index 42c698c..e32ed45 100644 --- a/.gitignore +++ b/.gitignore @@ -5,8 +5,10 @@ target/ .settings *.iml dependency-reduced-pom.xml +.ipynb_checkpoints # pip +.venv build/ dist/ .egg/ diff --git a/jjava-jupyter/src/main/java/org/dflib/jjava/jupyter/kernel/BaseKernel.java b/jjava-jupyter/src/main/java/org/dflib/jjava/jupyter/kernel/BaseKernel.java index 0b50d0b..55be0d0 100644 --- a/jjava-jupyter/src/main/java/org/dflib/jjava/jupyter/kernel/BaseKernel.java +++ b/jjava-jupyter/src/main/java/org/dflib/jjava/jupyter/kernel/BaseKernel.java @@ -7,6 +7,7 @@ import org.dflib.jjava.jupyter.kernel.display.DisplayData; import org.dflib.jjava.jupyter.kernel.display.Renderer; import org.dflib.jjava.jupyter.kernel.display.common.Image; +import org.dflib.jjava.jupyter.kernel.display.common.Swing; import org.dflib.jjava.jupyter.kernel.display.common.Text; import org.dflib.jjava.jupyter.kernel.display.common.Url; import org.dflib.jjava.jupyter.kernel.history.HistoryEntry; @@ -136,6 +137,7 @@ protected BaseKernel( this.executionCount = new AtomicInteger(1); Image.registerAll(this.renderer); + Swing.registerAll(this.renderer); Url.registerAll(this.renderer); Text.registerAll(this.renderer); } diff --git a/jjava-jupyter/src/main/java/org/dflib/jjava/jupyter/kernel/BaseNotebookStatics.java b/jjava-jupyter/src/main/java/org/dflib/jjava/jupyter/kernel/BaseNotebookStatics.java index 8acdf85..1110fe2 100644 --- a/jjava-jupyter/src/main/java/org/dflib/jjava/jupyter/kernel/BaseNotebookStatics.java +++ b/jjava-jupyter/src/main/java/org/dflib/jjava/jupyter/kernel/BaseNotebookStatics.java @@ -1,8 +1,11 @@ package org.dflib.jjava.jupyter.kernel; import org.dflib.jjava.jupyter.kernel.display.DisplayData; +import org.dflib.jjava.jupyter.kernel.display.interactive.FxBridge; +import org.dflib.jjava.jupyter.kernel.display.interactive.InteractiveSwing; import org.dflib.jjava.jupyter.kernel.magic.UndefinedMagicException; +import java.awt.Component; import java.util.List; import java.util.UUID; @@ -79,6 +82,31 @@ public static String display(Object o, String... as) { return id; } + /** + * Display an AWT/Swing component or a JavaFX node as an interactive widget: it is streamed to the browser as a live + * image and mouse/keyboard events from the browser are dispatched back into it. Requires the JJava JupyterLab + * extension for interactivity; without it the output falls back to a static image snapshot. + * + *

A {@code javafx.scene.Node} is wrapped in a {@code JFXPanel} so it rides the same pipeline (JavaFX must be on + * the classpath — it is an optional, user-supplied dependency). + */ + public static void displayInteractive(Object component) { + BaseKernel kernel = BaseKernel.notebookKernel(); + if (component instanceof Component) { + InteractiveSwing.show(kernel, (Component) component); + } else if (FxBridge.isNode(component)) { + try { + InteractiveSwing.show(kernel, FxBridge.wrap(component)); + } catch (ReflectiveOperationException e) { + throw new RuntimeException("Failed to embed JavaFX node (is JavaFX on the classpath?)", e); + } + } else { + throw new IllegalArgumentException( + "displayInteractive expects a java.awt.Component or a javafx.scene.Node, got: " + + (component == null ? "null" : component.getClass().getName())); + } + } + public static void updateDisplay(String id, Object o) { DisplayData data = render(o); BaseKernel.notebookKernel().getIO().display.updateDisplay(id, data); diff --git a/jjava-jupyter/src/main/java/org/dflib/jjava/jupyter/kernel/comm/CommManager.java b/jjava-jupyter/src/main/java/org/dflib/jjava/jupyter/kernel/comm/CommManager.java index f39b510..aed583f 100644 --- a/jjava-jupyter/src/main/java/org/dflib/jjava/jupyter/kernel/comm/CommManager.java +++ b/jjava-jupyter/src/main/java/org/dflib/jjava/jupyter/kernel/comm/CommManager.java @@ -94,11 +94,20 @@ public Comm unregisterComm(String id) { * The latter may happen if the manager is not connected to the frontend */ public T openComm(String targetName, CommFactory factory) { + return openComm(targetName, new JsonObject(), factory); + } + + /** + * A {@link #openComm(String, CommFactory)} variant that attaches an initial {@code data} payload to the + * {@code comm_open} message. The frontend target handler receives this as the open command's data, which is useful + * for correlating the new comm with something the frontend already knows about. + */ + public T openComm(String targetName, JsonObject data, CommFactory factory) { if (this.iopub == null) return null; String id = UUID.randomUUID().toString(); - CommOpenCommand content = new CommOpenCommand(id, targetName, new JsonObject()); + CommOpenCommand content = new CommOpenCommand(id, targetName, data); Message message = new Message<>(this.context, CommOpenCommand.MESSAGE_TYPE, content); T comm = factory.produce(this, id, targetName, message); diff --git a/jjava-jupyter/src/main/java/org/dflib/jjava/jupyter/kernel/display/common/Swing.java b/jjava-jupyter/src/main/java/org/dflib/jjava/jupyter/kernel/display/common/Swing.java new file mode 100644 index 0000000..729d0c0 --- /dev/null +++ b/jjava-jupyter/src/main/java/org/dflib/jjava/jupyter/kernel/display/common/Swing.java @@ -0,0 +1,82 @@ +package org.dflib.jjava.jupyter.kernel.display.common; + +import org.dflib.jjava.jupyter.kernel.display.RenderContext; +import org.dflib.jjava.jupyter.kernel.display.Renderer; +import org.dflib.jjava.jupyter.kernel.display.mime.MIMEType; + +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.image.BufferedImage; + +/** + * Renders an {@link java.awt.Component AWT/Swing component} as an image by painting it off-screen into a + * {@link BufferedImage}, which is then encoded by {@link Image}. This works without a display (headless) since no native + * window is ever created. + */ +public class Swing { + public static final MIMEType PNG = MIMEType.IMAGE_PNG; + public static final MIMEType JPEG = MIMEType.IMAGE_JPEG; + public static final MIMEType GIF = MIMEType.IMAGE_GIF; + + public static void registerAll(Renderer renderer) { + renderer.createRegistration(Component.class) + .preferring(PNG) + .supporting(JPEG, GIF) + .register(Swing::renderComponent); + } + + public static void renderComponent(Component component, RenderContext context) { + Image.renderImage(snapshot(component), context); + } + + /** + * Paint a component using its current size, falling back to its {@link Component#getPreferredSize() preferred size} + * when it has not been laid out yet (which is the usual case for a component that was never added to a window). + */ + public static BufferedImage snapshot(Component component) { + Dimension size = component.getSize(); + if (size.width <= 0 || size.height <= 0) { + size = component.getPreferredSize(); + } + return snapshot(component, size.width, size.height); + } + + public static BufferedImage snapshot(Component component, int width, int height) { + width = Math.max(width, 1); + height = Math.max(height, 1); + + component.setSize(width, height); + layoutTree(component); + + BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); + Graphics2D g = image.createGraphics(); + try { + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); + // print() rather than paint(): it bypasses Swing's double-buffering, which is the right behaviour for + // off-screen rendering of a component that has no native peer. + component.print(g); + } finally { + g.dispose(); + } + return image; + } + + /** + * A component that was never realized in a window is not laid out, so its children have zero bounds and would not + * paint (nor hit-test). Forcing a layout pass over the whole subtree gives every child a position and size. + */ + public static void layoutTree(Component component) { + synchronized (component.getTreeLock()) { + component.doLayout(); + if (component instanceof Container) { + for (Component child : ((Container) component).getComponents()) { + layoutTree(child); + } + } + } + } +} diff --git a/jjava-jupyter/src/main/java/org/dflib/jjava/jupyter/kernel/display/interactive/FxBridge.java b/jjava-jupyter/src/main/java/org/dflib/jjava/jupyter/kernel/display/interactive/FxBridge.java new file mode 100644 index 0000000..ff83018 Binary files /dev/null and b/jjava-jupyter/src/main/java/org/dflib/jjava/jupyter/kernel/display/interactive/FxBridge.java differ diff --git a/jjava-jupyter/src/main/java/org/dflib/jjava/jupyter/kernel/display/interactive/InteractiveSwing.java b/jjava-jupyter/src/main/java/org/dflib/jjava/jupyter/kernel/display/interactive/InteractiveSwing.java new file mode 100644 index 0000000..eb8242a --- /dev/null +++ b/jjava-jupyter/src/main/java/org/dflib/jjava/jupyter/kernel/display/interactive/InteractiveSwing.java @@ -0,0 +1,91 @@ +package org.dflib.jjava.jupyter.kernel.display.interactive; + +import com.google.gson.JsonObject; +import org.dflib.jjava.jupyter.kernel.BaseKernel; +import org.dflib.jjava.jupyter.kernel.comm.CommManager; +import org.dflib.jjava.jupyter.kernel.display.DisplayData; +import org.dflib.jjava.jupyter.kernel.display.Renderer; +import org.dflib.jjava.jupyter.kernel.display.mime.MIMEType; + +import java.awt.Component; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.UUID; + +/** + * Entry point for embedding an interactive {@link Component} in a notebook. + * + *

It emits an output carrying the {@link #MIME_TYPE custom MIME type} so the JupyterLab extension can mount a canvas, + * then opens a {@value #TARGET_NAME} comm whose {@code comm_open} data carries a {@code token}. The extension matches + * that token to the canvas it just created and starts exchanging frames/events with the + * {@link InteractiveSwingSession}. + * + *

The same output also carries a static {@code image/png} snapshot, so a frontend without the extension + * (or any non-Lab frontend) degrades gracefully to a still image instead of a placeholder message. + */ +public final class InteractiveSwing { + + /** Comm target the JupyterLab extension registers a handler for. */ + public static final String TARGET_NAME = "jjava.swing.v1"; + + /** MIME type of the placeholder output the JupyterLab extension renders into a canvas. */ + public static final String MIME_TYPE = "application/vnd.jjava.swing.v1+json"; + + private InteractiveSwing() { + } + + public static InteractiveSwingSession show(BaseKernel kernel, Component component) { + // A JFXPanel needs a window ancestor (for its GraphicsConfiguration) to map input; no-op for pure Swing. + FxBridge.ensureScreened(component); + + String token = UUID.randomUUID().toString(); + InteractiveSwingSession session = new InteractiveSwingSession(token, component); + + DisplayData data = buildDisplayData( + kernel.getRenderer(), token, session.getWidth(), session.getHeight(), component); + kernel.display(data); + + CommManager commManager = kernel.getCommManager(); + JsonObject openData = new JsonObject(); + openData.addProperty("token", token); + openData.addProperty("width", session.getWidth()); + openData.addProperty("height", session.getHeight()); + + InteractiveSwingComm comm = commManager.openComm( + TARGET_NAME, openData, + (manager, id, target, message) -> new InteractiveSwingComm(manager, id, target, session)); + + if (comm != null) { + session.bind(comm); + } + + return session; + } + + /** + * Build the output bundle: the interactive {@link #MIME_TYPE} payload, plus a static {@code image/png} snapshot as a + * fallback for frontends without the extension, plus a {@code text/plain} description. + */ + static DisplayData buildDisplayData(Renderer renderer, String token, int width, int height, Component component) { + Map payload = new LinkedHashMap<>(); + payload.put("token", token); + payload.put("width", width); + payload.put("height", height); + + DisplayData data = new DisplayData(); + data.putData(MIME_TYPE, payload); + + try { + Object png = renderer.renderAs(component, MIMEType.IMAGE_PNG.toString()).getData(MIMEType.IMAGE_PNG); + if (png != null) { + data.putData(MIMEType.IMAGE_PNG, png); + } + } catch (Exception e) { + // The static snapshot is best-effort; the interactive payload is still emitted. + } + + data.putText("Interactive Swing component — install the jjava-swing JupyterLab extension for interactivity " + + "(a static snapshot is shown otherwise)."); + return data; + } +} diff --git a/jjava-jupyter/src/main/java/org/dflib/jjava/jupyter/kernel/display/interactive/InteractiveSwingComm.java b/jjava-jupyter/src/main/java/org/dflib/jjava/jupyter/kernel/display/interactive/InteractiveSwingComm.java new file mode 100644 index 0000000..0260fb4 --- /dev/null +++ b/jjava-jupyter/src/main/java/org/dflib/jjava/jupyter/kernel/display/interactive/InteractiveSwingComm.java @@ -0,0 +1,36 @@ +package org.dflib.jjava.jupyter.kernel.display.interactive; + +import org.dflib.jjava.jupyter.kernel.comm.Comm; +import org.dflib.jjava.jupyter.kernel.comm.CommManager; +import org.dflib.jjava.jupyter.messages.Message; +import org.dflib.jjava.jupyter.messages.comm.CommCloseCommand; +import org.dflib.jjava.jupyter.messages.comm.CommMsgCommand; + +/** + * The kernel side of the {@value InteractiveSwing#TARGET_NAME} comm. It is opened by the kernel (see + * {@link InteractiveSwing#show}) and forwards frontend messages to its {@link InteractiveSwingSession}, tearing the + * session down when the comm closes. + */ +class InteractiveSwingComm extends Comm { + + private final InteractiveSwingSession session; + + InteractiveSwingComm(CommManager manager, String id, String targetName, InteractiveSwingSession session) { + super(manager, id, targetName); + this.session = session; + } + + @Override + protected void onMessage(Message message) { + if (session != null) { + session.handleMessage(message.getContent().getData()); + } + } + + @Override + protected void onClose(Message closeMessage, boolean sending) { + if (session != null) { + session.dispose(); + } + } +} diff --git a/jjava-jupyter/src/main/java/org/dflib/jjava/jupyter/kernel/display/interactive/InteractiveSwingSession.java b/jjava-jupyter/src/main/java/org/dflib/jjava/jupyter/kernel/display/interactive/InteractiveSwingSession.java new file mode 100644 index 0000000..31252cb --- /dev/null +++ b/jjava-jupyter/src/main/java/org/dflib/jjava/jupyter/kernel/display/interactive/InteractiveSwingSession.java @@ -0,0 +1,430 @@ +package org.dflib.jjava.jupyter.kernel.display.interactive; + +import com.google.gson.JsonObject; +import org.dflib.jjava.jupyter.kernel.comm.Comm; +import org.dflib.jjava.jupyter.kernel.display.common.Swing; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.imageio.ImageIO; +import javax.swing.SwingUtilities; +import java.awt.AlphaComposite; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.KeyboardFocusManager; +import java.awt.Point; +import java.awt.RenderingHints; +import java.awt.event.FocusEvent; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; +import java.awt.event.MouseWheelEvent; +import java.awt.image.BufferedImage; +import java.awt.image.DataBufferInt; +import java.io.ByteArrayOutputStream; +import java.util.Collections; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; + +/** + * Hosts a single {@link Component} off-screen and bridges it to a browser canvas: it streams PNG frames of the component + * over a {@link Comm} and dispatches the mouse/keyboard events that arrive back from the frontend into the component's + * Swing event handling. No native window is ever created, so this works headless. + * + *

All component manipulation (layout, painting, event dispatch) happens on the AWT event dispatch thread (EDT). + */ +public class InteractiveSwingSession { + + private static final Logger LOGGER = LoggerFactory.getLogger(InteractiveSwingSession.class); + + /** Frames are coalesced to roughly this cadence so a burst of repaints produces one frame. */ + private static final long FRAME_INTERVAL_MS = 33; + + private static final ScheduledExecutorService SCHEDULER = Executors.newSingleThreadScheduledExecutor(runnable -> { + Thread thread = new Thread(runnable, "jjava-swing-frames"); + thread.setDaemon(true); + return thread; + }); + + private final String token; + private final Component component; + + private volatile int width; + private volatile int height; + private volatile Comm comm; + private volatile boolean disposed; + + private final AtomicBoolean framePending = new AtomicBoolean(false); + + // Reused across frames to avoid per-frame allocation; touched only on the EDT during painting. + private BufferedImage frameImage; + // Layout is expensive, so only redo it when something actually changed (resize or an invalidated component) rather + // than on every repaint. Touched only on the EDT. + private boolean needsLayout = true; + // Hash of the last frame actually streamed; lets us drop frames whose pixels are unchanged. Scheduler-thread only. + private long lastFrameHash; + + // Accessed only on the EDT. The component that should receive keyboard events, tracked from the last mouse press. + private Component focusOwner; + + InteractiveSwingSession(String token, Component component) { + this.token = token; + this.component = component; + + Dimension size = component.getSize(); + if (size.width <= 0 || size.height <= 0) { + size = component.getPreferredSize(); + } + // Fall back to a usable default when the component has neither a size nor a preferred size (e.g. a bare + // JFXPanel, which reports 0x0 until its scene drives a size). + this.width = size.width > 0 ? size.width : 400; + this.height = size.height > 0 ? size.height : 300; + + // Size and lay out eagerly so the component (and its children) have real bounds for hit-testing the very first + // events, rather than waiting for the first frame to be rendered. + component.setSize(width, height); + Swing.layoutTree(component); + + SwingRepaintManager.install(); + SwingRepaintManager.register(component, this); + } + + public String getToken() { + return token; + } + + public int getWidth() { + return width; + } + + public int getHeight() { + return height; + } + + /** Bind the comm opened by the frontend and push the first frame. */ + void bind(Comm comm) { + this.comm = comm; + requestFrame(); + } + + /** Handle a message coming from the frontend canvas. */ + void handleMessage(JsonObject data) { + if (data == null || disposed) { + return; + } + String type = optString(data, "type", ""); + switch (type) { + case "mouse": + dispatchOnEdt(() -> dispatchMouse(data)); + break; + case "key": + dispatchOnEdt(() -> dispatchKey(data)); + break; + case "resize": + dispatchOnEdt(() -> resize(data)); + break; + case "refresh": + requestFrame(); + break; + default: + break; + } + } + + /** + * Run an event-applying action on the EDT, then request a frame. A failing handler (e.g. a toolkit that can't map a + * synthetic event off-screen) is logged and swallowed so it never kills the EDT or the session. + */ + private void dispatchOnEdt(Runnable action) { + SwingUtilities.invokeLater(() -> { + try { + action.run(); + } catch (Throwable t) { + LOGGER.debug("Interactive event dispatch failed", t); + } + requestFrame(); + }); + } + + /** Schedule a (coalesced) frame to be rendered and streamed. Safe to call from any thread. */ + void requestFrame() { + if (disposed) { + return; + } + if (framePending.compareAndSet(false, true)) { + SCHEDULER.schedule(this::renderAndSend, FRAME_INTERVAL_MS, TimeUnit.MILLISECONDS); + } + } + + /** Flag that the component tree must be laid out again before the next frame (e.g. a child was invalidated). */ + void markNeedsLayout() { + needsLayout = true; + } + + void dispose() { + disposed = true; + SwingRepaintManager.unregister(component); + } + + // --- frame streaming ------------------------------------------------------------------------------------------- + + private void renderAndSend() { + framePending.set(false); + Comm target = this.comm; + if (target == null || target.isClosed() || disposed) { + return; + } + try { + BufferedImage image = paintFrame(); + long hash = framePixelHash(image); + if (hash == lastFrameHash) { + // Nothing changed since the last streamed frame (e.g. a timer called repaint() without altering + // anything) — skip the PNG encode and the send entirely. + return; + } + lastFrameHash = hash; + + ByteArrayOutputStream out = new ByteArrayOutputStream(32 * 1024); + ImageIO.write(image, "png", out); + + JsonObject message = new JsonObject(); + message.addProperty("type", "frame"); + message.addProperty("w", image.getWidth()); + message.addProperty("h", image.getHeight()); + target.send(message, null, Collections.singletonList(out.toByteArray())); + } catch (Exception e) { + LOGGER.debug("Failed to render/stream interactive Swing frame", e); + } + } + + private BufferedImage paintFrame() throws Exception { + BufferedImage[] holder = new BufferedImage[1]; + Runnable paint = () -> holder[0] = paintOnEdt(); + if (SwingUtilities.isEventDispatchThread()) { + paint.run(); + } else { + SwingUtilities.invokeAndWait(paint); + } + return holder[0]; + } + + /** Paint the component into the reused buffer, laying out only when needed. Must run on the EDT. */ + private BufferedImage paintOnEdt() { + int w = width; + int h = height; + if (frameImage == null || frameImage.getWidth() != w || frameImage.getHeight() != h) { + frameImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); + needsLayout = true; + } + if (needsLayout) { + component.setSize(w, h); + Swing.layoutTree(component); + needsLayout = false; + } + + Graphics2D g = frameImage.createGraphics(); + try { + // Clear the reused buffer to fully transparent before repainting. + g.setComposite(AlphaComposite.Clear); + g.fillRect(0, 0, w, h); + g.setComposite(AlphaComposite.SrcOver); + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); + component.print(g); + } finally { + g.dispose(); + } + return frameImage; + } + + private static long framePixelHash(BufferedImage image) { + int[] pixels = ((DataBufferInt) image.getRaster().getDataBuffer()).getData(); + long hash = 1125899906842597L; + for (int pixel : pixels) { + hash = 31 * hash + pixel; + } + return hash; + } + + // --- event dispatch (EDT) -------------------------------------------------------------------------------------- + + private void resize(JsonObject data) { + this.width = Math.max(1, optInt(data, "width", width)); + this.height = Math.max(1, optInt(data, "height", height)); + component.setSize(width, height); + needsLayout = true; + } + + private void dispatchMouse(JsonObject data) { + String action = optString(data, "action", ""); + int x = optInt(data, "x", 0); + int y = optInt(data, "y", 0); + int button = optInt(data, "button", 1); + long when = System.currentTimeMillis(); + int modifiers = mouseModifiers(data, action, button); + + Component target = componentAt(x, y); + Point p = SwingUtilities.convertPoint(component, x, y, target); + + if ("wheel".equals(action)) { + int rotation = optInt(data, "deltaY", 0) >= 0 ? 1 : -1; + MouseWheelEvent wheel = new MouseWheelEvent(target, MouseEvent.MOUSE_WHEEL, when, modifiers, + p.x, p.y, 0, false, MouseWheelEvent.WHEEL_UNIT_SCROLL, 3, rotation); + target.dispatchEvent(wheel); + return; + } + + int id; + switch (action) { + case "down": id = MouseEvent.MOUSE_PRESSED; break; + case "up": id = MouseEvent.MOUSE_RELEASED; break; + case "click": id = MouseEvent.MOUSE_CLICKED; break; + case "move": id = MouseEvent.MOUSE_MOVED; break; + case "drag": id = MouseEvent.MOUSE_DRAGGED; break; + default: return; + } + + if (id == MouseEvent.MOUSE_PRESSED) { + focusOn(target); + } + + boolean buttoned = id != MouseEvent.MOUSE_MOVED && id != MouseEvent.MOUSE_DRAGGED; + int clickCount = buttoned ? Math.max(1, optInt(data, "clickCount", 1)) : 0; + int awtButton = buttoned ? awtButton(button) : MouseEvent.NOBUTTON; + + MouseEvent event = new MouseEvent(target, id, when, modifiers, p.x, p.y, clickCount, false, awtButton); + target.dispatchEvent(event); + } + + private void dispatchKey(JsonObject data) { + Component target = focusOwner != null ? focusOwner : component; + + // JavaFX: AWT key forwarding through an off-screen JFXPanel doesn't work (no real keyboard focus), so deliver + // the key straight into the FX scene's focused node instead. + if (FxBridge.isJFXPanel(target) && FxBridge.injectKey(target, data)) { + return; + } + + String action = optString(data, "action", ""); + long when = System.currentTimeMillis(); + int modifiers = keyboardModifiers(data); + + if ("press".equals(action)) { + String text = optString(data, "char", ""); + if (text.isEmpty()) { + return; + } + KeyEvent typed = new KeyEvent(target, KeyEvent.KEY_TYPED, when, modifiers, + KeyEvent.VK_UNDEFINED, text.charAt(0)); + redispatchKey(target, typed); + return; + } + + int id; + switch (action) { + case "down": id = KeyEvent.KEY_PRESSED; break; + case "up": id = KeyEvent.KEY_RELEASED; break; + default: return; + } + int keyCode = awtKeyCode(optInt(data, "keyCode", 0)); + String text = optString(data, "char", ""); + char keyChar = text.isEmpty() ? KeyEvent.CHAR_UNDEFINED : text.charAt(0); + KeyEvent event = new KeyEvent(target, id, when, modifiers, keyCode, keyChar); + redispatchKey(target, event); + } + + /** + * Deliver a key event via {@link KeyboardFocusManager#redispatchEvent}, which bypasses the focus manager's + * type-ahead handling. A plain {@code dispatchEvent} would be swallowed here because no Java window holds focus + * (the browser does), so the key would never reach the component's key bindings. + */ + private static void redispatchKey(Component target, KeyEvent event) { + KeyboardFocusManager.getCurrentKeyboardFocusManager().redispatchEvent(target, event); + } + + /** + * Move synthetic focus to {@code target}: there is no real keyboard-focus manager off-screen, so we hand-deliver + * FOCUS_LOST/FOCUS_GAINED. This activates a Swing text caret, and — for a JFXPanel — activates the embedded JavaFX + * scene so its focused node accepts typing. + */ + private void focusOn(Component target) { + if (focusOwner == target) { + return; + } + if (focusOwner != null) { + focusOwner.dispatchEvent(new FocusEvent(focusOwner, FocusEvent.FOCUS_LOST)); + } + focusOwner = target; + target.dispatchEvent(new FocusEvent(target, FocusEvent.FOCUS_GAINED)); + } + + private Component componentAt(int x, int y) { + Component deepest = SwingUtilities.getDeepestComponentAt(component, x, y); + return deepest != null ? deepest : component; + } + + private int mouseModifiers(JsonObject data, String action, int button) { + int modifiers = keyboardModifiers(data); + boolean buttonInvolved = "down".equals(action) || "up".equals(action) + || "drag".equals(action) || "click".equals(action); + if (buttonInvolved) { + // Keep the button-down mask set even on release so SwingUtilities.isLeftMouseButton(e) and friends — which + // gate button activation — recognise the gesture. + modifiers |= buttonDownMask(button); + } + return modifiers; + } + + private static int keyboardModifiers(JsonObject data) { + int modifiers = 0; + if (optBool(data, "shift")) modifiers |= InputEvent.SHIFT_DOWN_MASK; + if (optBool(data, "ctrl")) modifiers |= InputEvent.CTRL_DOWN_MASK; + if (optBool(data, "alt")) modifiers |= InputEvent.ALT_DOWN_MASK; + if (optBool(data, "meta")) modifiers |= InputEvent.META_DOWN_MASK; + return modifiers; + } + + private static int buttonDownMask(int button) { + switch (button) { + case 2: return InputEvent.BUTTON2_DOWN_MASK; + case 3: return InputEvent.BUTTON3_DOWN_MASK; + default: return InputEvent.BUTTON1_DOWN_MASK; + } + } + + private static int awtButton(int button) { + switch (button) { + case 2: return MouseEvent.BUTTON2; + case 3: return MouseEvent.BUTTON3; + default: return MouseEvent.BUTTON1; + } + } + + /** + * Browser {@code KeyboardEvent.keyCode} values mostly coincide with AWT virtual key codes for letters, digits, + * arrows, etc. The notable exception is Enter (13 in the browser, {@link KeyEvent#VK_ENTER} 10 in AWT). + */ + private static int awtKeyCode(int browserKeyCode) { + if (browserKeyCode == 13) { + return KeyEvent.VK_ENTER; + } + return browserKeyCode; + } + + // --- json helpers ---------------------------------------------------------------------------------------------- + + private static String optString(JsonObject data, String key, String fallback) { + return data.has(key) && !data.get(key).isJsonNull() ? data.get(key).getAsString() : fallback; + } + + private static int optInt(JsonObject data, String key, int fallback) { + return data.has(key) && !data.get(key).isJsonNull() ? data.get(key).getAsInt() : fallback; + } + + private static boolean optBool(JsonObject data, String key) { + return data.has(key) && !data.get(key).isJsonNull() && data.get(key).getAsBoolean(); + } +} diff --git a/jjava-jupyter/src/main/java/org/dflib/jjava/jupyter/kernel/display/interactive/SwingRepaintManager.java b/jjava-jupyter/src/main/java/org/dflib/jjava/jupyter/kernel/display/interactive/SwingRepaintManager.java new file mode 100644 index 0000000..35bd08e --- /dev/null +++ b/jjava-jupyter/src/main/java/org/dflib/jjava/jupyter/kernel/display/interactive/SwingRepaintManager.java @@ -0,0 +1,73 @@ +package org.dflib.jjava.jupyter.kernel.display.interactive; + +import javax.swing.JComponent; +import javax.swing.RepaintManager; +import java.awt.Component; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * A {@link RepaintManager} that, in addition to the default behaviour, notices when a component belonging to an + * {@link InteractiveSwingSession} is repainted and asks that session to stream a fresh frame. This is what lets + * asynchronous changes (animation timers, model updates, etc.) reach the browser, not just the repaints that follow an + * input event. + * + *

It is installed globally (one per JVM/AppContext) but delegates to the superclass for everything, so ordinary Swing + * components that are not hosted in a session behave exactly as before. + */ +class SwingRepaintManager extends RepaintManager { + + private static volatile boolean installed = false; + + // Maps each session root component to its session. A repainted component is matched to a session by walking up its + // parent chain until a registered root is found. + private static final Map ROOTS = new ConcurrentHashMap<>(); + + static synchronized void install() { + if (!installed) { + RepaintManager.setCurrentManager(new SwingRepaintManager()); + installed = true; + } + } + + static void register(Component root, InteractiveSwingSession session) { + ROOTS.put(root, session); + } + + static void unregister(Component root) { + ROOTS.remove(root); + } + + private static InteractiveSwingSession sessionFor(Component component) { + if (ROOTS.isEmpty()) { + return null; + } + for (Component current = component; current != null; current = current.getParent()) { + InteractiveSwingSession session = ROOTS.get(current); + if (session != null) { + return session; + } + } + return null; + } + + @Override + public void addDirtyRegion(JComponent c, int x, int y, int w, int h) { + super.addDirtyRegion(c, x, y, w, h); + InteractiveSwingSession session = sessionFor(c); + if (session != null) { + session.requestFrame(); + } + } + + @Override + public void addInvalidComponent(JComponent invalidComponent) { + super.addInvalidComponent(invalidComponent); + InteractiveSwingSession session = sessionFor(invalidComponent); + if (session != null) { + // An invalidated component means the layout may have changed, so the next frame must re-lay-out. + session.markNeedsLayout(); + session.requestFrame(); + } + } +} diff --git a/jjava-jupyter/src/test/java/org/dflib/jjava/jupyter/kernel/display/common/SwingTest.java b/jjava-jupyter/src/test/java/org/dflib/jjava/jupyter/kernel/display/common/SwingTest.java new file mode 100644 index 0000000..a3fbbe3 --- /dev/null +++ b/jjava-jupyter/src/test/java/org/dflib/jjava/jupyter/kernel/display/common/SwingTest.java @@ -0,0 +1,94 @@ +package org.dflib.jjava.jupyter.kernel.display.common; + +import org.dflib.jjava.jupyter.kernel.display.DisplayData; +import org.dflib.jjava.jupyter.kernel.display.Renderer; +import org.dflib.jjava.jupyter.kernel.display.mime.MIMEType; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import javax.imageio.ImageIO; +import javax.swing.JButton; +import javax.swing.JLabel; +import javax.swing.JPanel; +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; +import java.util.Base64; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class SwingTest { + + static { + // Snapshotting works with or without a display, but force headless so the suite behaves identically on CI + // servers and developer machines. + System.setProperty("java.awt.headless", "true"); + } + + private Renderer renderer; + + @BeforeEach + public void setUp() { + this.renderer = new Renderer(); + Swing.registerAll(this.renderer); + } + + @Test + public void rendersComponentAsPng() throws Exception { + JButton button = new JButton("Click me"); + button.setSize(120, 40); + + DisplayData data = this.renderer.render(button); + + BufferedImage image = decodePng(data); + assertEquals(120, image.getWidth()); + assertEquals(40, image.getHeight()); + } + + @Test + public void fallsBackToPreferredSizeWhenNotSized() throws Exception { + JLabel label = new JLabel("hello"); + Dimension preferred = label.getPreferredSize(); + + DisplayData data = this.renderer.render(label); + + BufferedImage image = decodePng(data); + assertEquals(preferred.width, image.getWidth()); + assertEquals(preferred.height, image.getHeight()); + } + + @Test + public void snapshotHonoursRequestedSize() { + JPanel panel = new JPanel(); + + BufferedImage image = Swing.snapshot(panel, 200, 100); + + assertEquals(200, image.getWidth()); + assertEquals(100, image.getHeight()); + } + + @Test + public void laysOutChildrenBeforePainting() { + // A nested component that was never realized in a window: layout() must give the child non-zero bounds. + JPanel panel = new JPanel(new BorderLayout()); + JButton child = new JButton("child"); + panel.add(child, BorderLayout.CENTER); + + Swing.snapshot(panel, 300, 80); + + assertTrue(child.getWidth() > 0, "child should have been laid out with a non-zero width"); + assertTrue(child.getHeight() > 0, "child should have been laid out with a non-zero height"); + } + + private static BufferedImage decodePng(DisplayData data) throws Exception { + Object png = data.getData(MIMEType.IMAGE_PNG); + assertNotNull(png, "expected an image/png rendering"); + byte[] bytes = Base64.getDecoder().decode(png.toString()); + BufferedImage image = ImageIO.read(new ByteArrayInputStream(bytes)); + assertNotNull(image, "image/png payload should decode to an image"); + return image; + } +} diff --git a/jjava-jupyter/src/test/java/org/dflib/jjava/jupyter/kernel/display/interactive/InteractiveSwingSessionTest.java b/jjava-jupyter/src/test/java/org/dflib/jjava/jupyter/kernel/display/interactive/InteractiveSwingSessionTest.java new file mode 100644 index 0000000..a8ff87e --- /dev/null +++ b/jjava-jupyter/src/test/java/org/dflib/jjava/jupyter/kernel/display/interactive/InteractiveSwingSessionTest.java @@ -0,0 +1,200 @@ +package org.dflib.jjava.jupyter.kernel.display.interactive; + +import com.google.gson.JsonObject; +import org.dflib.jjava.jupyter.kernel.comm.Comm; +import org.dflib.jjava.jupyter.kernel.comm.CommManager; +import org.dflib.jjava.jupyter.kernel.display.DisplayData; +import org.dflib.jjava.jupyter.kernel.display.Renderer; +import org.dflib.jjava.jupyter.kernel.display.common.Swing; +import org.dflib.jjava.jupyter.kernel.display.mime.MIMEType; +import org.junit.jupiter.api.Test; + +import javax.swing.JButton; +import javax.swing.JLabel; +import javax.swing.JTextField; +import javax.swing.SwingUtilities; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class InteractiveSwingSessionTest { + + static { + System.setProperty("java.awt.headless", "true"); + } + + /** A {@link Comm} that records frames instead of putting them on a socket. */ + private static class RecordingComm extends Comm { + final List frames = new ArrayList<>(); + final CountDownLatch firstFrame = new CountDownLatch(1); + + RecordingComm() { + super(new CommManager(), "test-comm", InteractiveSwing.TARGET_NAME); + } + + @Override + public void send(JsonObject data, Map metadata, List blobs) { + if (blobs != null && !blobs.isEmpty()) { + frames.add(blobs.get(0)); + firstFrame.countDown(); + } + } + + @Override + protected void onMessage(org.dflib.jjava.jupyter.messages.Message message) { + } + + @Override + protected void onClose(org.dflib.jjava.jupyter.messages.Message closeMessage, boolean sending) { + } + } + + private static JsonObject key(String action, String ch) { + JsonObject o = new JsonObject(); + o.addProperty("type", "key"); + o.addProperty("action", action); + o.addProperty("char", ch); + o.addProperty("keyCode", ch.isEmpty() ? 0 : Character.toUpperCase(ch.charAt(0))); + return o; + } + + private static void typeChar(InteractiveSwingSession session, String ch) { + session.handleMessage(key("down", ch)); + session.handleMessage(key("press", ch)); + session.handleMessage(key("up", ch)); + } + + private static JsonObject mouse(String action, int x, int y) { + JsonObject o = new JsonObject(); + o.addProperty("type", "mouse"); + o.addProperty("action", action); + o.addProperty("x", x); + o.addProperty("y", y); + o.addProperty("button", 1); + return o; + } + + private static void flushEventQueue() throws Exception { + // The EDT is single-threaded and FIFO, so anything queued by handleMessage() has run once this returns. + SwingUtilities.invokeAndWait(() -> { }); + } + + @Test + public void streamsAFrameOnBind() throws Exception { + JButton button = new JButton("Hi"); + button.setSize(120, 40); + InteractiveSwingSession session = new InteractiveSwingSession("tok-1", button); + RecordingComm comm = new RecordingComm(); + + session.bind(comm); + + assertTrue(comm.firstFrame.await(2, TimeUnit.SECONDS), "expected an initial frame to be streamed"); + assertTrue(comm.frames.get(0).length > 0, "frame should be non-empty PNG bytes"); + } + + @Test + public void firesActionListenerOnClickGesture() throws Exception { + AtomicInteger clicks = new AtomicInteger(); + JButton button = new JButton("Click"); + button.addActionListener(e -> clicks.incrementAndGet()); + + InteractiveSwingSession session = new InteractiveSwingSession("tok-2", button); + session.bind(new RecordingComm()); + + // Press then release inside the button's bounds: the button fires its action on release. + session.handleMessage(mouse("down", 30, 15)); + session.handleMessage(mouse("up", 30, 15)); + flushEventQueue(); + + assertEquals(1, clicks.get(), "the button's ActionListener should have fired once"); + } + + @Test + public void skipsUnchangedFramesButStreamsChangedOnes() throws Exception { + JLabel label = new JLabel("v1"); + label.setSize(140, 30); + InteractiveSwingSession session = new InteractiveSwingSession("tok-dup", label); + RecordingComm comm = new RecordingComm(); + + session.bind(comm); + assertTrue(comm.firstFrame.await(2, TimeUnit.SECONDS)); + int afterFirst = comm.frames.size(); + + // Re-request with no change: the identical frame must be suppressed (no encode/send). + session.requestFrame(); + Thread.sleep(200); + assertEquals(afterFirst, comm.frames.size(), "an unchanged frame should be skipped"); + + // Change the visible content: a new frame must be streamed. + SwingUtilities.invokeAndWait(() -> label.setText("v2 has changed")); + session.requestFrame(); + Thread.sleep(200); + assertTrue(comm.frames.size() > afterFirst, "a changed frame should be streamed"); + } + + @Test + public void outputBundleCarriesInteractiveAndStaticFallback() { + Renderer renderer = new Renderer(); + Swing.registerAll(renderer); + JButton button = new JButton("Hi"); + button.setSize(120, 40); + + DisplayData data = InteractiveSwing.buildDisplayData(renderer, "tok", 120, 40, button); + + // Interactive payload for the extension... + assertTrue(data.hasDataForType(MIMEType.parse(InteractiveSwing.MIME_TYPE)), + "interactive MIME payload should be present"); + // ...and a static PNG fallback for frontends without it. + assertNotNull(data.getData(MIMEType.IMAGE_PNG), "static PNG fallback should be present"); + } + + @Test + public void typesIntoSwingTextField() throws Exception { + JTextField field = new JTextField(); + field.setSize(160, 24); + InteractiveSwingSession session = new InteractiveSwingSession("tok-type", field); + session.bind(new RecordingComm()); + + // Click to focus the field, then type "hi". + session.handleMessage(mouse("down", 10, 10)); + session.handleMessage(mouse("up", 10, 10)); + typeChar(session, "h"); + typeChar(session, "i"); + flushEventQueue(); + + assertEquals("hi", field.getText(), "typed characters should be inserted into the text field"); + } + + @Test + public void fxBridgeRejectsNonNodes() { + // Name-based detection must not false-positive on ordinary objects (and must not require JavaFX to be present). + assertFalse(FxBridge.isNode(null)); + assertFalse(FxBridge.isNode("not a node")); + assertFalse(FxBridge.isNode(new JButton())); + } + + @Test + public void resizeUpdatesDimensions() throws Exception { + JButton button = new JButton("Resize"); + InteractiveSwingSession session = new InteractiveSwingSession("tok-3", button); + session.bind(new RecordingComm()); + + JsonObject resize = new JsonObject(); + resize.addProperty("type", "resize"); + resize.addProperty("width", 321); + resize.addProperty("height", 123); + session.handleMessage(resize); + flushEventQueue(); + + assertEquals(321, session.getWidth()); + assertEquals(123, session.getHeight()); + } +} diff --git a/jupyterlab-extension/.gitignore b/jupyterlab-extension/.gitignore new file mode 100644 index 0000000..c2d4841 --- /dev/null +++ b/jupyterlab-extension/.gitignore @@ -0,0 +1,8 @@ +node_modules/ +lib/ +tsconfig.tsbuildinfo +jjava_swing/labextension/ +*.egg-info/ +dist/ +build/ +__pycache__/ diff --git a/jupyterlab-extension/README.md b/jupyterlab-extension/README.md new file mode 100644 index 0000000..fd4e1e8 --- /dev/null +++ b/jupyterlab-extension/README.md @@ -0,0 +1,101 @@ +# jjava-swing — interactive Swing for JupyterLab + +A JupyterLab 4 extension that makes `displayInteractive(component)` in the +[JJava](https://github.com/dflib/jjava) Java kernel render a **live, interactive** Swing/AWT +component in a notebook cell: the kernel streams PNG frames of the component and the extension +forwards mouse/keyboard events back to it. + +## How it works + +1. The kernel emits an output of MIME type `application/vnd.jjava.swing.v1+json` carrying a `token` + and the component's size. The extension's **mime renderer** mounts a `` for that token. +2. The kernel opens a `jjava.swing.v1` **comm** (carrying the same token). The extension's **notebook + plugin** has registered a handler for that comm target; it matches the comm to the canvas by token. +3. Frames arrive as comm messages with the PNG in the message buffers and are drawn to the canvas; + DOM mouse/keyboard events are serialized to JSON and sent back over the comm. + +Without this extension installed, the same cell falls back to a short text message (and, separately, +a plain `display(component)` still shows a static PNG snapshot — that needs no extension). + +## Develop / install locally + +Requires Node.js and a Python env with JupyterLab 4. + +```bash +cd jupyterlab-extension +npm install +npm run build # tsc + dev labextension build (needs `pip install jupyterlab`) +jupyter labextension develop --overwrite . +jupyter lab +``` + +Type-check only (no JupyterLab needed): + +```bash +npm install +npm run typecheck +``` + +## Build a distributable wheel + +```bash +pip install build +python -m build # produces dist/jjava_swing-*.whl (runs the npm production build) +pip install dist/jjava_swing-*.whl +``` + +## Usage (in a Java notebook) + +```java +import javax.swing.*; +import java.awt.*; + +JButton b = new JButton("Click me"); +b.addActionListener(e -> b.setText("Clicked at " + System.currentTimeMillis())); +displayInteractive(b); +``` + +### Without the extension + +`displayInteractive(...)` is safe to use even if this extension isn't installed: the same output also +carries a static `image/png` snapshot, so a plain JupyterLab/Notebook/VS Code/console frontend just shows +a still image instead of the live canvas. (And `display(component)` always renders a static snapshot with +no extension or comm at all.) Notebooks that never touch Swing are completely unaffected — AWT is not +initialized until a component is actually rendered. + +### JavaFX + +JavaFX rides the same pipeline via `javafx.embed.swing.JFXPanel` (a Swing component that embeds an FX +scene). Pass a `JFXPanel` or a bare `javafx.scene.Node` (auto-wrapped) to `displayInteractive(...)`. +JavaFX is an optional, user-supplied dependency — pull it with `%maven` (platform classifier) and build +the scene on the FX thread: + +```java +%maven org.openjfx:javafx-controls:jar:linux:21.0.2 +%maven org.openjfx:javafx-swing:jar:linux:21.0.2 + +import javafx.embed.swing.JFXPanel; +import javafx.application.Platform; +import javafx.scene.Scene; +import javafx.scene.control.Button; +import javafx.scene.layout.StackPane; + +JFXPanel fx = new JFXPanel(); // boots the FX toolkit +Platform.runLater(() -> { + Button b = new Button("FX button"); + b.setOnAction(e -> b.setText("clicked")); + fx.setScene(new Scene(new StackPane(b), 320, 200)); +}); +displayInteractive(fx); +``` + +See [examples/javafx-demo.ipynb](examples/javafx-demo.ipynb). JavaFX needs a display; on a headless +server it additionally needs Monocle (`-Dglass.platform=Monocle -Dmonocle.platform=Headless`). + +## Known limitations + +The component is hosted off-screen with no native peer, so input is dispatched synthetically. This +covers custom-painted panels, charts, buttons, text fields and tables, but **not** features that need +their own native windows or the real lightweight dispatcher: tooltips, popup menus, combo-box +dropdowns, drag-and-drop, and some focus-traversal edge cases. Mutate Swing state on the EDT +(`SwingUtilities.invokeLater`); repaints are captured and streamed regardless of which thread caused them. diff --git a/jupyterlab-extension/examples/demo1_balls.jshell b/jupyterlab-extension/examples/demo1_balls.jshell new file mode 100644 index 0000000..5361010 --- /dev/null +++ b/jupyterlab-extension/examples/demo1_balls.jshell @@ -0,0 +1,77 @@ +// Demo 1 — animation + buttons + mouse. +// Exercises: Swing Timer driving continuous repaints (async frame streaming via the custom RepaintManager), +// button clicks (Pause/Clear), and mouse clicks (click the canvas to add a ball). +import javax.swing.*; +import java.awt.*; +import java.awt.event.*; +import java.util.*; +import java.util.List; +import javax.swing.Timer; // disambiguate: java.util.Timer is auto-imported by the notebook + +class BallsPanel extends JPanel { + class Ball { double x, y, vx, vy; int r; Color c; } + final List balls = new ArrayList<>(); + final Random rnd = new Random(); + final Timer timer; + + BallsPanel() { + setPreferredSize(new Dimension(480, 300)); + setBackground(Color.WHITE); + for (int i = 0; i < 3; i++) addBall(rnd.nextInt(480), rnd.nextInt(300)); + addMouseListener(new MouseAdapter() { + public void mousePressed(MouseEvent e) { addBall(e.getX(), e.getY()); repaint(); } + }); + timer = new Timer(16, e -> { step(); repaint(); }); + timer.start(); + } + + void addBall(int x, int y) { + Ball b = new Ball(); + b.x = x; b.y = y; + b.vx = rnd.nextDouble() * 8 - 4; + b.vy = rnd.nextDouble() * 8 - 4; + b.r = 8 + rnd.nextInt(22); + b.c = Color.getHSBColor(rnd.nextFloat(), 0.7f, 0.9f); + balls.add(b); + } + + void step() { + int w = getWidth(), h = getHeight(); + for (Ball b : balls) { + b.x += b.vx; b.y += b.vy; + if (b.x - b.r < 0 || b.x + b.r > w) b.vx = -b.vx; + if (b.y - b.r < 0 || b.y + b.r > h) b.vy = -b.vy; + } + } + + protected void paintComponent(Graphics g) { + super.paintComponent(g); + Graphics2D g2 = (Graphics2D) g; + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + for (Ball b : balls) { + g2.setColor(b.c); + g2.fillOval((int) (b.x - b.r), (int) (b.y - b.r), b.r * 2, b.r * 2); + } + g2.setColor(Color.DARK_GRAY); + g2.drawString("Balls: " + balls.size() + " — click to add", 8, 16); + } +} + +BallsPanel canvas = new BallsPanel(); + +JButton toggle = new JButton("Pause"); +toggle.addActionListener(e -> { + if (canvas.timer.isRunning()) { canvas.timer.stop(); toggle.setText("Start"); } + else { canvas.timer.start(); toggle.setText("Pause"); } +}); +JButton clear = new JButton("Clear"); +clear.addActionListener(e -> { canvas.balls.clear(); canvas.repaint(); }); + +JPanel root = new JPanel(new BorderLayout()); +JPanel bar = new JPanel(); +bar.add(toggle); bar.add(clear); +root.add(bar, BorderLayout.NORTH); +root.add(canvas, BorderLayout.CENTER); +root.setPreferredSize(new Dimension(480, 340)); + +displayInteractive(root); diff --git a/jupyterlab-extension/examples/demo2_sketch.jshell b/jupyterlab-extension/examples/demo2_sketch.jshell new file mode 100644 index 0000000..de9257d --- /dev/null +++ b/jupyterlab-extension/examples/demo2_sketch.jshell @@ -0,0 +1,70 @@ +// Demo 2 — mouse drag + custom painting + a color/clear toolbar. +// Exercises: mousePressed/mouseDragged (free-hand drawing), repaint-on-drag streaming, and button clicks. +import javax.swing.*; +import java.awt.*; +import java.awt.event.*; +import java.util.*; +import java.util.List; + +class SketchPad extends JPanel { + static class Stroke { Color color; List points = new ArrayList<>(); } + final List strokes = new ArrayList<>(); + Stroke current; + Color color = new Color(0x1565C0); + + SketchPad() { + setPreferredSize(new Dimension(480, 300)); + setBackground(Color.WHITE); + MouseAdapter ma = new MouseAdapter() { + public void mousePressed(MouseEvent e) { + current = new Stroke(); + current.color = color; + current.points.add(e.getPoint()); + strokes.add(current); + repaint(); + } + public void mouseDragged(MouseEvent e) { + if (current != null) { current.points.add(e.getPoint()); repaint(); } + } + public void mouseReleased(MouseEvent e) { current = null; } + }; + addMouseListener(ma); + addMouseMotionListener(ma); + } + + protected void paintComponent(Graphics g) { + super.paintComponent(g); + Graphics2D g2 = (Graphics2D) g; + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2.setStroke(new BasicStroke(3, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); + for (Stroke s : strokes) { + g2.setColor(s.color); + for (int i = 1; i < s.points.size(); i++) { + Point a = s.points.get(i - 1), b = s.points.get(i); + g2.drawLine(a.x, a.y, b.x, b.y); + } + } + g2.setColor(Color.GRAY); + g2.drawString("Drag to draw", 8, 16); + } +} + +SketchPad pad = new SketchPad(); + +JPanel bar = new JPanel(); +for (Object[] sw : new Object[][]{{"Blue", new Color(0x1565C0)}, {"Red", new Color(0xC62828)}, {"Green", new Color(0x2E7D32)}, {"Black", Color.BLACK}}) { + JButton b = new JButton((String) sw[0]); + Color c = (Color) sw[1]; + b.addActionListener(e -> pad.color = c); + bar.add(b); +} +JButton clear = new JButton("Clear"); +clear.addActionListener(e -> { pad.strokes.clear(); pad.repaint(); }); +bar.add(clear); + +JPanel root = new JPanel(new BorderLayout()); +root.add(bar, BorderLayout.NORTH); +root.add(pad, BorderLayout.CENTER); +root.setPreferredSize(new Dimension(480, 340)); + +displayInteractive(root); diff --git a/jupyterlab-extension/examples/demo3_form.jshell b/jupyterlab-extension/examples/demo3_form.jshell new file mode 100644 index 0000000..5e7a3c2 --- /dev/null +++ b/jupyterlab-extension/examples/demo3_form.jshell @@ -0,0 +1,48 @@ +// Demo 3 — KEYBOARD + FOCUS stress test (the most fragile path). +// Click the text field, type, then click Greet. Exercises: focus tracking, KEY_TYPED into a JTextField, a slider drag. +// If typed text does not appear in the field, that is the known keyboard/focus limitation of off-screen dispatch. +import javax.swing.*; +import java.awt.*; + +// 1. We renamed the panel to 'demoPanel' to bypass any stale memory in the REPL +JPanel demoPanel = new JPanel(new GridBagLayout()); +demoPanel.setPreferredSize(new Dimension(420, 220)); + +JTextField name = new JTextField(16); +JLabel greeting = new JLabel("Type your name, then click Greet"); +JButton greet = new JButton("Greet"); +greet.addActionListener(e -> greeting.setText("Hello, " + name.getText() + "!")); + +JSlider size = new JSlider(8, 48, 16); +JLabel sizeLabel = new JLabel("Font size: 16"); +size.addChangeListener(e -> { + int v = size.getValue(); + sizeLabel.setText("Font size: " + v); + greeting.setFont(greeting.getFont().deriveFont((float) v)); +}); + +GridBagConstraints gc = new GridBagConstraints(); +gc.insets = new Insets(6, 6, 6, 6); +gc.fill = GridBagConstraints.HORIZONTAL; + +// 2. All components are now added to the newly named 'demoPanel' +gc.gridx = 0; gc.gridy = 0; +demoPanel.add(new JLabel("Name:"), gc); + +gc.gridx = 1; gc.gridy = 0; +demoPanel.add(name, gc); + +gc.gridx = 0; gc.gridy = 1; gc.gridwidth = 2; +demoPanel.add(greet, gc); + +gc.gridx = 0; gc.gridy = 2; gc.gridwidth = 1; +demoPanel.add(sizeLabel, gc); + +gc.gridx = 0; gc.gridy = 3; +demoPanel.add(size, gc); + +gc.gridx = 0; gc.gridy = 4; +demoPanel.add(greeting, gc); + +// 3. Pass the new panel to your environment's display method +displayInteractive(demoPanel); diff --git a/jupyterlab-extension/examples/javafx-demo.ipynb b/jupyterlab-extension/examples/javafx-demo.ipynb new file mode 100644 index 0000000..ed22e58 --- /dev/null +++ b/jupyterlab-extension/examples/javafx-demo.ipynb @@ -0,0 +1,255 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "309e90a6", + "metadata": {}, + "source": [ + "# JavaFX in JupyterLab (same pipeline as Swing)\n", + "\n", + "JavaFX rides the **same** interactive pipeline as Swing: a `javafx.embed.swing.JFXPanel` embeds an FX\n", + "scene and is itself a Swing `JComponent`, so `displayInteractive(...)` snapshots it and forwards\n", + "mouse/keyboard into the FX scene. You can pass a `JFXPanel` **or** a bare `javafx.scene.Node`\n", + "(it gets wrapped in a `JFXPanel` automatically).\n", + "\n", + "**Prerequisites**\n", + "- The `jjava-swing` JupyterLab extension installed + the JJava kernel reinstalled (interactivity).\n", + " Without the extension you still get a static snapshot.\n", + "- **JavaFX is an optional, user-supplied dependency.** Cell 1 pulls OpenJFX via `%maven` using the\n", + " **platform classifier** (`linux` here; use `mac`, `mac-aarch64`, or `win` as appropriate).\n", + "- A display is required (your machine has one). On a headless server, JavaFX needs Monocle\n", + " (`-Dglass.platform=Monocle -Dmonocle.platform=Headless`) — unlike Swing, which is headless-native.\n", + "\n", + "Build the FX scene graph on the **JavaFX Application Thread** (`Platform.runLater(...)`).\n", + "\n", + "> **Note:** with `%maven` you'll see `Unsupported JavaFX configuration: classes were loaded from 'unnamed module ...'`. This is a harmless JavaFX warning (OpenJFX is on the classpath, not the module path) - FX still works. To silence it, instead launch the kernel with the OpenJFX SDK on the module path: `JJAVA_JVM_OPTS=\"--module-path /path/to/javafx-sdk/lib --add-modules javafx.controls,javafx.swing\"` and skip the `%maven` cell." + ] + }, + { + "cell_type": "markdown", + "id": "bb6adb4d", + "metadata": {}, + "source": [ + "## 1. Pull OpenJFX and boot the toolkit" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "4a9858ae", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "JavaFX runtime: 21.0.2+5\n" + ] + } + ], + "source": [ + "// Pull OpenJFX (edit the classifier for your OS: linux | mac | mac-aarch64 | win)\n", + "%maven org.openjfx:javafx-base:jar:linux:21.0.2\n", + "%maven org.openjfx:javafx-graphics:jar:linux:21.0.2\n", + "%maven org.openjfx:javafx-controls:jar:linux:21.0.2\n", + "%maven org.openjfx:javafx-swing:jar:linux:21.0.2\n", + "\n", + "import javafx.embed.swing.JFXPanel;\n", + "new JFXPanel(); // boots the JavaFX toolkit\n", + "System.out.println(\"JavaFX runtime: \" + System.getProperty(\"javafx.runtime.version\"));" + ] + }, + { + "cell_type": "markdown", + "id": "3c6f7493", + "metadata": {}, + "source": [ + "## 2. A JavaFX form via JFXPanel (click Greet, type in the field)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "f9409d48", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "application/vnd.jjava.swing.v1+json": { + "height": 220, + "token": "115987be-1ef7-4947-8d29-3018f2493e6f", + "width": 360 + }, + "image/png": "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", + "text/plain": [ + "Interactive Swing component — install the jjava-swing JupyterLab extension for interactivity (a static snapshot is shown otherwise)." + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import javafx.embed.swing.JFXPanel;\n", + "import javafx.application.Platform;\n", + "import javafx.scene.Scene;\n", + "import javafx.scene.control.Button;\n", + "import javafx.scene.control.Label;\n", + "import javafx.scene.control.TextField;\n", + "import javafx.scene.layout.VBox;\n", + "import javafx.geometry.Insets;\n", + "\n", + "// A JavaFX form embedded via JFXPanel -> the existing interactive pipeline handles it.\n", + "JFXPanel fxForm = new JFXPanel();\n", + "Platform.runLater(() -> {\n", + " Label out = new Label(\"Type your name, then click Greet\");\n", + " TextField name = new TextField();\n", + " name.setPromptText(\"name\");\n", + " Button greet = new Button(\"Greet\");\n", + " greet.setOnAction(e -> out.setText(\"Hello, \" + name.getText() + \"!\"));\n", + " VBox box = new VBox(10, new Label(\"JavaFX form\"), name, greet, out);\n", + " box.setPadding(new Insets(16));\n", + " fxForm.setScene(new Scene(box, 360, 220));\n", + "});\n", + "\n", + "displayInteractive(fxForm);" + ] + }, + { + "cell_type": "markdown", + "id": "69e74f28", + "metadata": {}, + "source": [ + "## 3. Pass a bare JavaFX Node (auto-wrapped in a JFXPanel)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "51021c60", + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jjava.swing.v1+json": { + "height": 300, + "token": "c6490013-5575-49a5-a87b-8c966d103a66", + "width": 400 + }, + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAZAAAAEsCAYAAADtt+XCAAAB6ElEQVR4Xu3BMQEAAADCoPVPbQ0PoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHg3VJUAAfrjs3kAAAAASUVORK5C", + "text/plain": [ + "Interactive Swing component — install the jjava-swing JupyterLab extension for interactivity (a static snapshot is shown otherwise)." + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import javafx.application.Platform;\n", + "import javafx.scene.control.Button;\n", + "import javafx.scene.layout.StackPane;\n", + "import java.util.concurrent.CountDownLatch;\n", + "\n", + "// You can also pass a JavaFX Node directly: displayInteractive(...) wraps it in a JFXPanel for you.\n", + "StackPane[] holder = new StackPane[1];\n", + "CountDownLatch ready = new CountDownLatch(1);\n", + "Platform.runLater(() -> {\n", + " Button b = new Button(\"Click me (bare FX node)\");\n", + " b.setOnAction(e -> b.setText(\"Clicked!\"));\n", + " StackPane root = new StackPane(b);\n", + " root.setPrefSize(320, 160);\n", + " holder[0] = root;\n", + " ready.countDown();\n", + "});\n", + "ready.await();\n", + "\n", + "displayInteractive(holder[0]);" + ] + }, + { + "cell_type": "markdown", + "id": "c778189c", + "metadata": {}, + "source": [ + "## 4. An animated FX scene (streams continuously)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "f52ea674", + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jjava.swing.v1+json": { + "height": 300, + "token": "f6cac4e3-229b-4bd1-b872-9b0cd607819c", + "width": 300 + }, + "image/png": "iVBORw0KGgoAAAANSUhEUgAAASwAAAEsCAYAAAB5fY51AAABdElEQVR4Xu3BMQEAAADCoPVPbQwfoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD+Bn+3AAHkQjJKAAAAAElFTkSuQmCC", + "text/plain": [ + "Interactive Swing component — install the jjava-swing JupyterLab extension for interactivity (a static snapshot is shown otherwise)." + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import javafx.embed.swing.JFXPanel;\n", + "import javafx.application.Platform;\n", + "import javafx.scene.Scene;\n", + "import javafx.scene.layout.StackPane;\n", + "import javafx.scene.shape.Rectangle;\n", + "import javafx.scene.paint.Color;\n", + "import javafx.animation.RotateTransition;\n", + "import javafx.animation.Animation;\n", + "import javafx.util.Duration;\n", + "\n", + "// A continuously-animating FX scene -> exercises continuous frame streaming through the same pipeline.\n", + "JFXPanel fxAnim = new JFXPanel();\n", + "Platform.runLater(() -> {\n", + " Rectangle rect = new Rectangle(90, 90, Color.CORNFLOWERBLUE);\n", + " StackPane root = new StackPane(rect);\n", + " root.setPrefSize(300, 300);\n", + " RotateTransition rt = new RotateTransition(Duration.seconds(2), rect);\n", + " rt.setByAngle(360);\n", + " rt.setCycleCount(Animation.INDEFINITE);\n", + " rt.play();\n", + " fxAnim.setScene(new Scene(root, 300, 300));\n", + "});\n", + "\n", + "displayInteractive(fxAnim);" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "002704ac-8d06-4b2f-8a34-06b11c49e9c0", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Java (jjava)", + "language": "java", + "name": "java" + }, + "language_info": { + "codemirror_mode": "java", + "file_extension": ".jshell", + "mimetype": "text/x-java-source", + "name": "Java", + "pygments_lexer": "java", + "version": "21.0.11+10-1-24.04.2-Ubuntu" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/jupyterlab-extension/examples/swing-demos.ipynb b/jupyterlab-extension/examples/swing-demos.ipynb new file mode 100644 index 0000000..eb8f1f6 --- /dev/null +++ b/jupyterlab-extension/examples/swing-demos.ipynb @@ -0,0 +1,334 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "f6d8cd39", + "metadata": {}, + "source": [ + "# JJava interactive Swing demos\n", + "\n", + "Requires the `jjava-swing` JupyterLab extension. Run each cell and interact with the output.\n", + "\n", + "1. **Bouncing balls** — animation + buttons + click-to-add\n", + "2. **Sketch pad** — mouse drag + custom painting + toolbar\n", + "3. **Form** — keyboard/focus stress test (the fragile path)" + ] + }, + { + "cell_type": "markdown", + "id": "abb09aca", + "metadata": {}, + "source": [ + "## 1. Bouncing balls (animation streaming + buttons + mouse)" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "81a3aba7", + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jjava.swing.v1+json": { + "height": 340, + "token": "5251546d-21b7-4cbf-a905-e844ae5f72d7", + "width": 480 + }, + "image/png": "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", + "text/plain": [ + "Interactive Swing component — install the jjava-swing JupyterLab extension for interactivity (a static snapshot is shown otherwise)." + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "// Demo 1 — animation + buttons + mouse.\n", + "// Exercises: Swing Timer driving continuous repaints (async frame streaming via the custom RepaintManager),\n", + "// button clicks (Pause/Clear), and mouse clicks (click the canvas to add a ball).\n", + "import javax.swing.*;\n", + "import java.awt.*;\n", + "import java.awt.event.*;\n", + "import java.util.*;\n", + "import java.util.List;\n", + "import javax.swing.Timer; // disambiguate: java.util.Timer is auto-imported by the notebook\n", + "\n", + "class BallsPanel extends JPanel {\n", + " class Ball { double x, y, vx, vy; int r; Color c; }\n", + " final List balls = new ArrayList<>();\n", + " final Random rnd = new Random();\n", + " final Timer timer;\n", + "\n", + " BallsPanel() {\n", + " setPreferredSize(new Dimension(480, 300));\n", + " setBackground(Color.WHITE);\n", + " for (int i = 0; i < 3; i++) addBall(rnd.nextInt(480), rnd.nextInt(300));\n", + " addMouseListener(new MouseAdapter() {\n", + " public void mousePressed(MouseEvent e) { addBall(e.getX(), e.getY()); repaint(); }\n", + " });\n", + " timer = new Timer(16, e -> { step(); repaint(); });\n", + " timer.start();\n", + " }\n", + "\n", + " void addBall(int x, int y) {\n", + " Ball b = new Ball();\n", + " b.x = x; b.y = y;\n", + " b.vx = rnd.nextDouble() * 8 - 4;\n", + " b.vy = rnd.nextDouble() * 8 - 4;\n", + " b.r = 8 + rnd.nextInt(22);\n", + " b.c = Color.getHSBColor(rnd.nextFloat(), 0.7f, 0.9f);\n", + " balls.add(b);\n", + " }\n", + "\n", + " void step() {\n", + " int w = getWidth(), h = getHeight();\n", + " for (Ball b : balls) {\n", + " b.x += b.vx; b.y += b.vy;\n", + " if (b.x - b.r < 0 || b.x + b.r > w) b.vx = -b.vx;\n", + " if (b.y - b.r < 0 || b.y + b.r > h) b.vy = -b.vy;\n", + " }\n", + " }\n", + "\n", + " protected void paintComponent(Graphics g) {\n", + " super.paintComponent(g);\n", + " Graphics2D g2 = (Graphics2D) g;\n", + " g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);\n", + " for (Ball b : balls) {\n", + " g2.setColor(b.c);\n", + " g2.fillOval((int) (b.x - b.r), (int) (b.y - b.r), b.r * 2, b.r * 2);\n", + " }\n", + " g2.setColor(Color.DARK_GRAY);\n", + " g2.drawString(\"Balls: \" + balls.size() + \" — click to add\", 8, 16);\n", + " }\n", + "}\n", + "\n", + "BallsPanel canvas = new BallsPanel();\n", + "\n", + "JButton toggle = new JButton(\"Pause\");\n", + "toggle.addActionListener(e -> {\n", + " if (canvas.timer.isRunning()) { canvas.timer.stop(); toggle.setText(\"Start\"); }\n", + " else { canvas.timer.start(); toggle.setText(\"Pause\"); }\n", + "});\n", + "JButton clear = new JButton(\"Clear\");\n", + "clear.addActionListener(e -> { canvas.balls.clear(); canvas.repaint(); });\n", + "\n", + "JPanel root = new JPanel(new BorderLayout());\n", + "JPanel bar = new JPanel();\n", + "bar.add(toggle); bar.add(clear);\n", + "root.add(bar, BorderLayout.NORTH);\n", + "root.add(canvas, BorderLayout.CENTER);\n", + "root.setPreferredSize(new Dimension(480, 340));\n", + "\n", + "displayInteractive(root);\n" + ] + }, + { + "cell_type": "markdown", + "id": "1c70d5c6", + "metadata": {}, + "source": [ + "## 2. Sketch pad (mouse drag + custom paint + toolbar)" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "59e84cdf", + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jjava.swing.v1+json": { + "height": 340, + "token": "277d7aac-67b0-4150-8e69-6f2923abc80c", + "width": 480 + }, + "image/png": "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ddVV31jA69ata3nePffcU0pyS/l9ND9u7ty5Pdvvz3tdtWpVuuKKK8rthQsXpmeffbZcQX/xxRdp8eLFaf78+Vs+FQC2SdsFnJfzr3cbcqk1/7HUE088UZ6br1Lz1fI111xT7n/11VfLd7tbyr/O/qYC7u15jz76aLr//vu3uq+3x235HXB/3mvj1875u+989b158+ayrXw1fNddd6VFixZttR0A2BZtF/B9992Xbr/99p7l5lLLJZi/Y82FlS1btqyn1PLV57Rp03oem+Urzt4K+NJLL+0p4Py8vLyl/D3xk08+udV9+XH5tbeUC7mqgPt6r1n+zjkX7axZs8ryM888kx566KFSyFt+rw0A26rfBZyL67HHHitXv1t+99pcavl72lxi+Ve1+eoxX+FueVWZr2xffPHFspy/T676Dnj27NnppZdeKrfzd8C5KBtXnW+99Va5Ys3/t05byq+Z/ziq8cdTeftbfgfcn/ea5avj/D4eeeSRspx//Z6/C877AADt2OYCzr+Wzcnff+bvPZuv/JpLLf+BU/5jpfycfOWYS3TLUsvfA+dSy0We/73i/NjeCjg/LxddTt5mLv18tZyfl7e7fPny5qcUuXQb289/ZZ2v2KsK+Jvea95W/r47/7Mh/yCQ/7oaANqxTQW8M+Rf81aVKQAMNGEFnP+6OP/KN2v8K00ff/xx06MAYGAKK+B77723/Do7f4ebv0/NfwgFAN0irIABoJspYAAIoIABIIACBoAAChgAAihgAAiggAEggAIGgAAKGAACKGAACKCAASCAAgaAAAoYAAIoYAAIoIABIIACBoAAChgAAihgAAiggAEggAIGgAAKGAACKGAACKCAASCAAgaAAAoYAAIoYAAIoIABIIACBoAAChgAAihgAAiggAEggAIGgAAKGAACKGAACKCAASCAAgaAAAoYAAIoYAAIoIABIIACBoAAChgAAihgAAiggAEggAIGgAAKGAACKGAACKCAASCAAgaAAAoYAAIoYAAIoIABIIACBoAAChgAAihgAAiggAEggAIGgAAKGAACKGAACKCAASCAAgaAAAoYAAIoYAAIoIABIIACBoAAChgAAihgAAiggAEggAIGgAAKGAACKGAACKCAASCAAgaAAAoYAAIoYAAIoIABIIACBoAAChgAAihgAAiggAEggAIGgAAKGAACKGAACKCAASCAAgaAAAoYAAIoYAAIoIABIIACBoAAChgAAihgAAiggAEggAIGgAAKGAACKGAACKCAASCAAgaAAAoYAAIoYAAIoIABIIACBoAAChgAAihgAAiggAEggAIGgAAKGAACKGAACKCAASCAAgaAAAoYAAIoYAAIoIABIIACBoAAChgAAihgAAiggAEggAIGgAAKGAACKGAACKCAASCAAgaAAAoYAAIoYAAIoIABIIACBoAAChgAAihgAAiggAEggAIGgAAKGAACKGAACKCAASCAAgaAAAoYAAIoYAAIoIABIIACBoAAChgAAihgAAiggAEggAIGgAAKGAACKGAACKCAASCAAgaAAAoYAAIoYAAIoIABIIACBoAAChgAAihgAAiggAEggAIGgAAKGAACKGAACKCAASCAAgaAAAoYAAIoYAAIoIABIIACBoAAChgAAihgAAiggAEggAIGgAAKGAACKGAACKCAASCAAgaAAAoYAAIoYAAIoIABIIACBoAAChgAAihgAAiggAEggAIGgAAKGAACKGAACKCAASCAAgaAAAoYAAIoYAAIoIABIIACBoAAChgAAihgAAiggAEggAIGgAAKGAACKGAACKCAASCAAgaAAAoYAAIoYAAIoIABIIACBoAAChgAAihgAAiggAEggAIGgAAKGAACKGAACKCAASCAAgaAAAoYAAIoYAAIoIABIIACBoAAChgAAihgAAiggAEggAIGgAAKGAACKGAACKCAASCAAgaAAAoYAAIoYAAIoIABIIACBoAAChgAAihgAAiggAEggAIGgAAKGAACKGAACKCAASCAAgaAAAoYAAIoYAAIoIABIIACBoAAChgAAihgAAiggAEggAIGgAAKGAACKGAACKCAASCAAgaAAAoYAAIoYAAIoIABIIACBoAAChgAAihgAAiggAEggAIGgAAKGAACKGAACKCAASCAAgaAAAoYAAIoYAAIoIABIIACBoAAChgAAihgAAiggAEggAIGgAAKGAACKGAACKCAASCAAgaAAAoYAAIoYAAIoIABIIACBoAAChgAAihgAAiggAEggAIGgAAKGAACKGAACKCAASCAAgaAAAoYAAIoYAAIoIABIIACBoAAChgAAihgAAiggAEggAIGgAD/D5jRSjHl5DYAAAAAAElFTkSuQmCC", + "text/plain": [ + "Interactive Swing component — install the jjava-swing JupyterLab extension for interactivity (a static snapshot is shown otherwise)." + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "// Demo 2 — mouse drag + custom painting + a color/clear toolbar.\n", + "// Exercises: mousePressed/mouseDragged (free-hand drawing), repaint-on-drag streaming, and button clicks.\n", + "import javax.swing.*;\n", + "import java.awt.*;\n", + "import java.awt.event.*;\n", + "import java.util.*;\n", + "import java.util.List;\n", + "\n", + "class SketchPad extends JPanel {\n", + " static class Stroke { Color color; List points = new ArrayList<>(); }\n", + " final List strokes = new ArrayList<>();\n", + " Stroke current;\n", + " Color color = new Color(0x1565C0);\n", + "\n", + " SketchPad() {\n", + " setPreferredSize(new Dimension(480, 300));\n", + " setBackground(Color.WHITE);\n", + " MouseAdapter ma = new MouseAdapter() {\n", + " public void mousePressed(MouseEvent e) {\n", + " current = new Stroke();\n", + " current.color = color;\n", + " current.points.add(e.getPoint());\n", + " strokes.add(current);\n", + " repaint();\n", + " }\n", + " public void mouseDragged(MouseEvent e) {\n", + " if (current != null) { current.points.add(e.getPoint()); repaint(); }\n", + " }\n", + " public void mouseReleased(MouseEvent e) { current = null; }\n", + " };\n", + " addMouseListener(ma);\n", + " addMouseMotionListener(ma);\n", + " }\n", + "\n", + " protected void paintComponent(Graphics g) {\n", + " super.paintComponent(g);\n", + " Graphics2D g2 = (Graphics2D) g;\n", + " g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);\n", + " g2.setStroke(new BasicStroke(3, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));\n", + " for (Stroke s : strokes) {\n", + " g2.setColor(s.color);\n", + " for (int i = 1; i < s.points.size(); i++) {\n", + " Point a = s.points.get(i - 1), b = s.points.get(i);\n", + " g2.drawLine(a.x, a.y, b.x, b.y);\n", + " }\n", + " }\n", + " g2.setColor(Color.GRAY);\n", + " g2.drawString(\"Drag to draw\", 8, 16);\n", + " }\n", + "}\n", + "\n", + "SketchPad pad = new SketchPad();\n", + "\n", + "JPanel bar = new JPanel();\n", + "for (Object[] sw : new Object[][]{{\"Blue\", new Color(0x1565C0)}, {\"Red\", new Color(0xC62828)}, {\"Green\", new Color(0x2E7D32)}, {\"Black\", Color.BLACK}}) {\n", + " JButton b = new JButton((String) sw[0]);\n", + " Color c = (Color) sw[1];\n", + " b.addActionListener(e -> pad.color = c);\n", + " bar.add(b);\n", + "}\n", + "JButton clear = new JButton(\"Clear\");\n", + "clear.addActionListener(e -> { pad.strokes.clear(); pad.repaint(); });\n", + "bar.add(clear);\n", + "\n", + "JPanel root = new JPanel(new BorderLayout());\n", + "root.add(bar, BorderLayout.NORTH);\n", + "root.add(pad, BorderLayout.CENTER);\n", + "root.setPreferredSize(new Dimension(480, 340));\n", + "\n", + "displayInteractive(root);\n" + ] + }, + { + "cell_type": "markdown", + "id": "08e5d0b3", + "metadata": {}, + "source": [ + "## 3. Form (keyboard + focus + slider) — stress test" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "3a203c52", + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jjava.swing.v1+json": { + "height": 220, + "token": "3e346151-1bb9-4e53-b731-dbbb36b10bf8", + "width": 420 + }, + "image/png": "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", + "text/plain": [ + "Interactive Swing component — install the jjava-swing JupyterLab extension for interactivity (a static snapshot is shown otherwise)." + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import javax.swing.*;\n", + "import java.awt.*;\n", + "\n", + "// 1. We renamed the panel to 'demoPanel' to bypass any stale memory in the REPL\n", + "JPanel demoPanel = new JPanel(new GridBagLayout());\n", + "demoPanel.setPreferredSize(new Dimension(420, 220));\n", + "\n", + "JTextField name = new JTextField(16);\n", + "JLabel greeting = new JLabel(\"Type your name, then click Greet\");\n", + "JButton greet = new JButton(\"Greet\");\n", + "greet.addActionListener(e -> greeting.setText(\"Hello, \" + name.getText() + \"!\"));\n", + "\n", + "JSlider size = new JSlider(8, 48, 16);\n", + "JLabel sizeLabel = new JLabel(\"Font size: 16\");\n", + "size.addChangeListener(e -> {\n", + " int v = size.getValue();\n", + " sizeLabel.setText(\"Font size: \" + v);\n", + " greeting.setFont(greeting.getFont().deriveFont((float) v));\n", + "});\n", + "\n", + "GridBagConstraints gc = new GridBagConstraints();\n", + "gc.insets = new Insets(6, 6, 6, 6);\n", + "gc.fill = GridBagConstraints.HORIZONTAL;\n", + "\n", + "// 2. All components are now added to the newly named 'demoPanel'\n", + "gc.gridx = 0; gc.gridy = 0; \n", + "demoPanel.add(new JLabel(\"Name:\"), gc);\n", + "\n", + "gc.gridx = 1; gc.gridy = 0; \n", + "demoPanel.add(name, gc);\n", + "\n", + "gc.gridx = 0; gc.gridy = 1; gc.gridwidth = 2; \n", + "demoPanel.add(greet, gc);\n", + "\n", + "gc.gridx = 0; gc.gridy = 2; gc.gridwidth = 1; \n", + "demoPanel.add(sizeLabel, gc);\n", + "\n", + "gc.gridx = 0; gc.gridy = 3; \n", + "demoPanel.add(size, gc);\n", + "\n", + "gc.gridx = 0; gc.gridy = 4; \n", + "demoPanel.add(greeting, gc);\n", + "\n", + "// 3. Pass the new panel to your environment's display method\n", + "displayInteractive(demoPanel);" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "56c9bcbc-61c1-4b54-81f1-416e9a0ffa4a", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Java (jjava)", + "language": "java", + "name": "java" + }, + "language_info": { + "codemirror_mode": "java", + "file_extension": ".jshell", + "mimetype": "text/x-java-source", + "name": "Java", + "pygments_lexer": "java", + "version": "21.0.11+10-1-24.04.2-Ubuntu" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/jupyterlab-extension/install.json b/jupyterlab-extension/install.json new file mode 100644 index 0000000..6cc84e3 --- /dev/null +++ b/jupyterlab-extension/install.json @@ -0,0 +1,5 @@ +{ + "packageManager": "python", + "packageName": "jjava_swing", + "uninstallInstructions": "Use your Python package manager (pip/conda) to uninstall the package jjava_swing" +} diff --git a/jupyterlab-extension/jjava_swing/__init__.py b/jupyterlab-extension/jjava_swing/__init__.py new file mode 100644 index 0000000..f1700bd --- /dev/null +++ b/jupyterlab-extension/jjava_swing/__init__.py @@ -0,0 +1,5 @@ +"""JupyterLab prebuilt extension package for interactive JJava Swing components.""" + + +def _jupyter_labextension_paths(): + return [{"src": "labextension", "dest": "jjava-swing"}] diff --git a/jupyterlab-extension/package-lock.json b/jupyterlab-extension/package-lock.json new file mode 100644 index 0000000..109838a --- /dev/null +++ b/jupyterlab-extension/package-lock.json @@ -0,0 +1,7062 @@ +{ + "name": "jjava-swing", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "jjava-swing", + "version": "0.1.0", + "license": "Apache-2.0", + "dependencies": { + "@jupyterlab/application": "^4.0.0", + "@jupyterlab/notebook": "^4.0.0", + "@jupyterlab/rendermime-interfaces": "^3.8.0", + "@jupyterlab/services": "^7.0.0", + "@lumino/widgets": "^2.0.0" + }, + "devDependencies": { + "@jupyterlab/builder": "^4.0.0", + "rimraf": "^5.0.0", + "typescript": "~5.4.0" + } + }, + "node_modules/@antfu/install-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@antfu/install-pkg/-/install-pkg-1.1.0.tgz", + "integrity": "sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ==", + "license": "MIT", + "dependencies": { + "package-manager-detector": "^1.3.0", + "tinyexec": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", + "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==", + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.29.7", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@braintree/sanitize-url": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-7.1.2.tgz", + "integrity": "sha512-jigsZK+sMF/cuiB7sERuo9V7N9jx+dhmHHnQyDSVdpZwVutaBu7WvNYqMDLSgFgfB30n452TP3vjDAvFC973mA==", + "license": "MIT" + }, + "node_modules/@chevrotain/types": { + "version": "11.1.2", + "resolved": "https://registry.npmjs.org/@chevrotain/types/-/types-11.1.2.tgz", + "integrity": "sha512-U+HFai5+zmJCkK86QsaJtoITlboZHBqrVketcO2ROv865xfCMSFpELQoz1GkX5GzME8pTa+3kbKrZHQtI0gdbw==", + "license": "Apache-2.0" + }, + "node_modules/@codemirror/autocomplete": { + "version": "6.20.3", + "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.20.3.tgz", + "integrity": "sha512-tlosUqb+3BbxCxZdu4tKeRghPFC+QM7q4X5YhKV2eCmPG+1r2F3f4AaSz5sCrFqUtX4Jh20VFTKecl16MgiV9g==", + "license": "MIT", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.17.0", + "@lezer/common": "^1.0.0" + } + }, + "node_modules/@codemirror/commands": { + "version": "6.10.3", + "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.10.3.tgz", + "integrity": "sha512-JFRiqhKu+bvSkDLI+rUhJwSxQxYb759W5GBezE8Uc8mHLqC9aV/9aTC7yJSqCtB3F00pylrLCwnyS91Ap5ej4Q==", + "license": "MIT", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.6.0", + "@codemirror/view": "^6.27.0", + "@lezer/common": "^1.1.0" + } + }, + "node_modules/@codemirror/lang-cpp": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@codemirror/lang-cpp/-/lang-cpp-6.0.3.tgz", + "integrity": "sha512-URM26M3vunFFn9/sm6rzqrBzDgfWuDixp85uTY49wKudToc2jTHUrKIGGKs+QWND+YLofNNZpxcNGRynFJfvgA==", + "license": "MIT", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@lezer/cpp": "^1.0.0" + } + }, + "node_modules/@codemirror/lang-css": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/@codemirror/lang-css/-/lang-css-6.3.1.tgz", + "integrity": "sha512-kr5fwBGiGtmz6l0LSJIbno9QrifNMUusivHbnA1H6Dmqy4HZFte3UAICix1VuKo0lMPKQr2rqB+0BkKi/S3Ejg==", + "license": "MIT", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@lezer/common": "^1.0.2", + "@lezer/css": "^1.1.7" + } + }, + "node_modules/@codemirror/lang-html": { + "version": "6.4.11", + "resolved": "https://registry.npmjs.org/@codemirror/lang-html/-/lang-html-6.4.11.tgz", + "integrity": "sha512-9NsXp7Nwp891pQchI7gPdTwBuSuT3K65NGTHWHNJ55HjYcHLllr0rbIZNdOzas9ztc1EUVBlHou85FFZS4BNnw==", + "license": "MIT", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/lang-css": "^6.0.0", + "@codemirror/lang-javascript": "^6.0.0", + "@codemirror/language": "^6.4.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.17.0", + "@lezer/common": "^1.0.0", + "@lezer/css": "^1.1.0", + "@lezer/html": "^1.3.12" + } + }, + "node_modules/@codemirror/lang-java": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@codemirror/lang-java/-/lang-java-6.0.2.tgz", + "integrity": "sha512-m5Nt1mQ/cznJY7tMfQTJchmrjdjQ71IDs+55d1GAa8DGaB8JXWsVCkVT284C3RTASaY43YknrK2X3hPO/J3MOQ==", + "license": "MIT", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@lezer/java": "^1.0.0" + } + }, + "node_modules/@codemirror/lang-javascript": { + "version": "6.2.5", + "resolved": "https://registry.npmjs.org/@codemirror/lang-javascript/-/lang-javascript-6.2.5.tgz", + "integrity": "sha512-zD4e5mS+50htS7F+TYjBPsiIFGanfVqg4HyUz6WNFikgOPf2BgKlx+TQedI1w6n/IqRBVBbBWmGFdLB/7uxO4A==", + "license": "MIT", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/language": "^6.6.0", + "@codemirror/lint": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.17.0", + "@lezer/common": "^1.0.0", + "@lezer/javascript": "^1.0.0" + } + }, + "node_modules/@codemirror/lang-json": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@codemirror/lang-json/-/lang-json-6.0.2.tgz", + "integrity": "sha512-x2OtO+AvwEHrEwR0FyyPtfDUiloG3rnVTSZV1W8UteaLL8/MajQd8DpvUb2YVzC+/T18aSDv0H9mu+xw0EStoQ==", + "license": "MIT", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@lezer/json": "^1.0.0" + } + }, + "node_modules/@codemirror/lang-markdown": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/@codemirror/lang-markdown/-/lang-markdown-6.5.0.tgz", + "integrity": "sha512-0K40bZ35jpHya6FriukbgaleaqzBLZfOh7HuzqbMxBXkbYMJDxfF39c23xOgxFezR+3G+tR2/Mup+Xk865OMvw==", + "license": "MIT", + "dependencies": { + "@codemirror/autocomplete": "^6.7.1", + "@codemirror/lang-html": "^6.0.0", + "@codemirror/language": "^6.3.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "@lezer/common": "^1.2.1", + "@lezer/markdown": "^1.0.0" + } + }, + "node_modules/@codemirror/lang-php": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@codemirror/lang-php/-/lang-php-6.0.2.tgz", + "integrity": "sha512-ZKy2v1n8Fc8oEXj0Th0PUMXzQJ0AIR6TaZU+PbDHExFwdu+guzOA4jmCHS1Nz4vbFezwD7LyBdDnddSJeScMCA==", + "license": "MIT", + "dependencies": { + "@codemirror/lang-html": "^6.0.0", + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@lezer/common": "^1.0.0", + "@lezer/php": "^1.0.0" + } + }, + "node_modules/@codemirror/lang-python": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/@codemirror/lang-python/-/lang-python-6.2.1.tgz", + "integrity": "sha512-IRjC8RUBhn9mGR9ywecNhB51yePWCGgvHfY1lWN/Mrp3cKuHr0isDKia+9HnvhiWNnMpbGhWrkhuWOc09exRyw==", + "license": "MIT", + "dependencies": { + "@codemirror/autocomplete": "^6.3.2", + "@codemirror/language": "^6.8.0", + "@codemirror/state": "^6.0.0", + "@lezer/common": "^1.2.1", + "@lezer/python": "^1.1.4" + } + }, + "node_modules/@codemirror/lang-rust": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@codemirror/lang-rust/-/lang-rust-6.0.2.tgz", + "integrity": "sha512-EZaGjCUegtiU7kSMvOfEZpaCReowEf3yNidYu7+vfuGTm9ow4mthAparY5hisJqOHmJowVH3Upu+eJlUji6qqA==", + "license": "MIT", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@lezer/rust": "^1.0.0" + } + }, + "node_modules/@codemirror/lang-sql": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/@codemirror/lang-sql/-/lang-sql-6.10.0.tgz", + "integrity": "sha512-6ayPkEd/yRw0XKBx5uAiToSgGECo/GY2NoJIHXIIQh1EVwLuKoU8BP/qK0qH5NLXAbtJRLuT73hx7P9X34iO4w==", + "license": "MIT", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, + "node_modules/@codemirror/lang-wast": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@codemirror/lang-wast/-/lang-wast-6.0.2.tgz", + "integrity": "sha512-Imi2KTpVGm7TKuUkqyJ5NRmeFWF7aMpNiwHnLQe0x9kmrxElndyH0K6H/gXtWwY6UshMRAhpENsgfpSwsgmC6Q==", + "license": "MIT", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, + "node_modules/@codemirror/lang-xml": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@codemirror/lang-xml/-/lang-xml-6.1.0.tgz", + "integrity": "sha512-3z0blhicHLfwi2UgkZYRPioSgVTo9PV5GP5ducFH6FaHy0IAJRg+ixj5gTR1gnT/glAIC8xv4w2VL1LoZfs+Jg==", + "license": "MIT", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/language": "^6.4.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "@lezer/common": "^1.0.0", + "@lezer/xml": "^1.0.0" + } + }, + "node_modules/@codemirror/language": { + "version": "6.12.3", + "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.12.3.tgz", + "integrity": "sha512-QwCZW6Tt1siP37Jet9Tb02Zs81TQt6qQrZR2H+eGMcFsL1zMrk2/b9CLC7/9ieP1fjIUMgviLWMmgiHoJrj+ZA==", + "license": "MIT", + "dependencies": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.23.0", + "@lezer/common": "^1.5.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0", + "style-mod": "^4.0.0" + } + }, + "node_modules/@codemirror/legacy-modes": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/@codemirror/legacy-modes/-/legacy-modes-6.5.3.tgz", + "integrity": "sha512-xCsmIzH78MyWkib9jlPaaun57XNkfbMIhagfaZVd0iLTqlpw3jXaIcbZm72MTmmn64eTZpBVNjbyYh+QXnxRsg==", + "license": "MIT", + "dependencies": { + "@codemirror/language": "^6.0.0" + } + }, + "node_modules/@codemirror/lint": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.9.7.tgz", + "integrity": "sha512-28/+iWLYxKxsvGYhSYL7zaCZqLz5+FFFDq9tVsvGv9kv8RY4fFAchJ5WX9M3YrrRlTIsECjsXPqeNgnSmNP2dg==", + "license": "MIT", + "dependencies": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.42.0", + "crelt": "^1.0.5" + } + }, + "node_modules/@codemirror/search": { + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.7.1.tgz", + "integrity": "sha512-uMe5UO6PamJtSHrXhhHOzSX3ReWtiJrva6GnPMwSOrZtiExb5X5eExhr2OUZQVvdxPsKpY3Ro2mFbQadpPWmHA==", + "license": "MIT", + "dependencies": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.37.0", + "crelt": "^1.0.5" + } + }, + "node_modules/@codemirror/state": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.6.0.tgz", + "integrity": "sha512-4nbvra5R5EtiCzr9BTHiTLc+MLXK2QGiAVYMyi8PkQd3SR+6ixar/Q/01Fa21TBIDOZXgeWV4WppsQolSreAPQ==", + "license": "MIT", + "dependencies": { + "@marijn/find-cluster-break": "^1.0.0" + } + }, + "node_modules/@codemirror/view": { + "version": "6.43.1", + "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.43.1.tgz", + "integrity": "sha512-+BIjw/AG3tDQ4pJgTLPYdAW25eDE66YsvM4LKyVPgGzVgZ4a9Wj1SRX8kPVKgBDdPt8oHtZ15F0qx7p0oOHdHw==", + "license": "MIT", + "dependencies": { + "@codemirror/state": "^6.6.0", + "crelt": "^1.0.6", + "style-mod": "^4.1.0", + "w3c-keyname": "^2.2.4" + } + }, + "node_modules/@discoveryjs/json-ext": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", + "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@fortawesome/fontawesome-free": { + "version": "5.15.4", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-5.15.4.tgz", + "integrity": "sha512-eYm8vijH/hpzr/6/1CJ/V/Eb1xQFW2nnUKArb3z+yUWv7HTwj6M7SP957oMjfZjAHU6qpoNc2wQvIxBLWYa/Jg==", + "hasInstallScript": true, + "license": "(CC-BY-4.0 AND OFL-1.1 AND MIT)", + "engines": { + "node": ">=6" + } + }, + "node_modules/@iconify/types": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@iconify/types/-/types-2.0.0.tgz", + "integrity": "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==", + "license": "MIT" + }, + "node_modules/@iconify/utils": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@iconify/utils/-/utils-3.1.3.tgz", + "integrity": "sha512-LPKOXPn/zV+zis1oOfGWogaXVpqUybF3ZS6SCZIsz8vg0ivVp9+fVqyYB7xq0aiST/VhUQYGO1qo6uoYSiEJqw==", + "license": "MIT", + "dependencies": { + "@antfu/install-pkg": "^1.1.0", + "@iconify/types": "^2.0.0", + "import-meta-resolve": "^4.2.0" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "license": "MIT", + "dependencies": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/types/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/types/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/types/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@jest/types/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.11", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz", + "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jupyter/react-components": { + "version": "0.16.7", + "resolved": "https://registry.npmjs.org/@jupyter/react-components/-/react-components-0.16.7.tgz", + "integrity": "sha512-BKIPkJ9V011uhtdq1xBOu2M3up59CqsRbDS4aq8XhnHR4pwqfRV6k6irE5YBOETCoIwWZZ5RZO+cJcZ3DcsT5A==", + "license": "BSD-3-Clause", + "dependencies": { + "@jupyter/web-components": "^0.16.7", + "react": ">=17.0.0 <19.0.0" + } + }, + "node_modules/@jupyter/web-components": { + "version": "0.16.7", + "resolved": "https://registry.npmjs.org/@jupyter/web-components/-/web-components-0.16.7.tgz", + "integrity": "sha512-1a8awgvvP9J9pCV5vBRuQxdBk29764qiMJsJYEndrWH3cB/FlaO+sZIBm4OTf56Eqdgl8R3/ZSLM1+3mgXOkPg==", + "license": "BSD-3-Clause", + "dependencies": { + "@microsoft/fast-colors": "^5.3.1", + "@microsoft/fast-element": "^1.12.0", + "@microsoft/fast-foundation": "^2.49.4", + "@microsoft/fast-web-utilities": "^5.4.1" + } + }, + "node_modules/@jupyter/ydoc": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/@jupyter/ydoc/-/ydoc-3.5.0.tgz", + "integrity": "sha512-kY/p4vP4tB606AxoEUZDBDKjKLVTF2q6AJE0bMHA5l2lL0SxrjufjkXCK/EEI/vUCOpHRakysNS8644tVAvhDg==", + "license": "BSD-3-Clause", + "dependencies": { + "@jupyterlab/nbformat": "^3.0.0 || ^4.0.0-alpha.21 || ^4.0.0", + "@lumino/coreutils": "^1.11.0 || ^2.0.0", + "@lumino/disposable": "^1.10.0 || ^2.0.0", + "@lumino/signaling": "^1.10.0 || ^2.0.0", + "y-protocols": "^1.0.5", + "yjs": "^13.5.40" + } + }, + "node_modules/@jupyterlab/application": { + "version": "4.5.9", + "resolved": "https://registry.npmjs.org/@jupyterlab/application/-/application-4.5.9.tgz", + "integrity": "sha512-aTcjIkDfrOrTejzoDSitlYLuJ+tSR9KXee82hWNQRBU622IZD5+nQLo0Jw7Wxfsa+s1YoZXDQQZB9UOP4f8M6g==", + "license": "BSD-3-Clause", + "dependencies": { + "@fortawesome/fontawesome-free": "^5.12.0", + "@jupyterlab/apputils": "^4.6.9", + "@jupyterlab/coreutils": "^6.5.9", + "@jupyterlab/docregistry": "^4.5.9", + "@jupyterlab/rendermime": "^4.5.9", + "@jupyterlab/rendermime-interfaces": "^3.13.9", + "@jupyterlab/services": "^7.5.9", + "@jupyterlab/statedb": "^4.5.9", + "@jupyterlab/translation": "^4.5.9", + "@jupyterlab/ui-components": "^4.5.9", + "@lumino/algorithm": "^2.0.4", + "@lumino/application": "^2.4.8", + "@lumino/commands": "^2.3.3", + "@lumino/coreutils": "^2.2.2", + "@lumino/disposable": "^2.1.5", + "@lumino/messaging": "^2.0.4", + "@lumino/polling": "^2.1.5", + "@lumino/properties": "^2.0.4", + "@lumino/signaling": "^2.1.5", + "@lumino/widgets": "^2.7.5" + } + }, + "node_modules/@jupyterlab/apputils": { + "version": "4.6.9", + "resolved": "https://registry.npmjs.org/@jupyterlab/apputils/-/apputils-4.6.9.tgz", + "integrity": "sha512-bMPLc0mVMRWhNZ9XzuOb7bVpDcBckKEhQJ4XqBqzN53DOVbqSxjM9Z3GrrxvuKJEfqRQxCebJVIqwlpZ8T2Uxw==", + "license": "BSD-3-Clause", + "dependencies": { + "@jupyterlab/coreutils": "^6.5.9", + "@jupyterlab/observables": "^5.5.9", + "@jupyterlab/rendermime-interfaces": "^3.13.9", + "@jupyterlab/services": "^7.5.9", + "@jupyterlab/settingregistry": "^4.5.9", + "@jupyterlab/statedb": "^4.5.9", + "@jupyterlab/statusbar": "^4.5.9", + "@jupyterlab/translation": "^4.5.9", + "@jupyterlab/ui-components": "^4.5.9", + "@lumino/algorithm": "^2.0.4", + "@lumino/commands": "^2.3.3", + "@lumino/coreutils": "^2.2.2", + "@lumino/disposable": "^2.1.5", + "@lumino/domutils": "^2.0.4", + "@lumino/messaging": "^2.0.4", + "@lumino/signaling": "^2.1.5", + "@lumino/virtualdom": "^2.0.4", + "@lumino/widgets": "^2.7.5", + "@types/react": "^18.0.26", + "react": "^18.2.0", + "sanitize-html": "~2.12.1" + } + }, + "node_modules/@jupyterlab/attachments": { + "version": "4.5.9", + "resolved": "https://registry.npmjs.org/@jupyterlab/attachments/-/attachments-4.5.9.tgz", + "integrity": "sha512-TQCeVCvsf2T7UouQNQAakrMC2nzI02+fKEfUkeihitWlQTmdeixGxk8bgZiHmyHlULAmqJR4+7EkzhG+70PbjA==", + "license": "BSD-3-Clause", + "dependencies": { + "@jupyterlab/nbformat": "^4.5.9", + "@jupyterlab/observables": "^5.5.9", + "@jupyterlab/rendermime": "^4.5.9", + "@jupyterlab/rendermime-interfaces": "^3.13.9", + "@lumino/disposable": "^2.1.5", + "@lumino/signaling": "^2.1.5" + } + }, + "node_modules/@jupyterlab/builder": { + "version": "4.5.9", + "resolved": "https://registry.npmjs.org/@jupyterlab/builder/-/builder-4.5.9.tgz", + "integrity": "sha512-M2mi+TtcxSE/fiKe5RfEqrzMEms6S++W163Qc+07sj2g78t6G84Bya9dgliUmBmLN4qqYhG0NXURdCmMmWRIAg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@lumino/algorithm": "^2.0.4", + "@lumino/application": "^2.4.8", + "@lumino/commands": "^2.3.3", + "@lumino/coreutils": "^2.2.2", + "@lumino/disposable": "^2.1.5", + "@lumino/domutils": "^2.0.4", + "@lumino/dragdrop": "^2.1.8", + "@lumino/messaging": "^2.0.4", + "@lumino/properties": "^2.0.4", + "@lumino/signaling": "^2.1.5", + "@lumino/virtualdom": "^2.0.4", + "@lumino/widgets": "^2.7.5", + "ajv": "^8.12.0", + "commander": "^9.4.1", + "css-loader": "^6.7.1", + "duplicate-package-checker-webpack-plugin": "^3.0.0", + "fs-extra": "^10.1.0", + "glob": "~7.1.6", + "license-webpack-plugin": "^4.0.2", + "mini-css-extract-plugin": "^2.7.0", + "mini-svg-data-uri": "^1.4.4", + "path-browserify": "^1.0.0", + "process": "^0.11.10", + "source-map-loader": "~1.0.2", + "style-loader": "~3.3.1", + "supports-color": "^7.2.0", + "terser-webpack-plugin": "^5.3.7", + "webpack": "^5.76.1", + "webpack-cli": "^5.0.1", + "webpack-merge": "^5.8.0", + "webpack-sources": "^3.4.1", + "worker-loader": "^3.0.2" + }, + "bin": { + "build-labextension": "lib/build-labextension.js" + } + }, + "node_modules/@jupyterlab/cells": { + "version": "4.5.9", + "resolved": "https://registry.npmjs.org/@jupyterlab/cells/-/cells-4.5.9.tgz", + "integrity": "sha512-DxXNITHwTfgDYoFDH6FEC517EgBC0x6dIcoEfxyUkIDcnI/oFVHJNeTDw9EJ11lRdLJbsA4NVzsdBSU6drdWCA==", + "license": "BSD-3-Clause", + "dependencies": { + "@codemirror/state": "^6.5.4", + "@codemirror/view": "^6.39.14", + "@jupyter/ydoc": "^3.1.0", + "@jupyterlab/apputils": "^4.6.9", + "@jupyterlab/attachments": "^4.5.9", + "@jupyterlab/codeeditor": "^4.5.9", + "@jupyterlab/codemirror": "^4.5.9", + "@jupyterlab/coreutils": "^6.5.9", + "@jupyterlab/documentsearch": "^4.5.9", + "@jupyterlab/filebrowser": "^4.5.9", + "@jupyterlab/nbformat": "^4.5.9", + "@jupyterlab/observables": "^5.5.9", + "@jupyterlab/outputarea": "^4.5.9", + "@jupyterlab/rendermime": "^4.5.9", + "@jupyterlab/services": "^7.5.9", + "@jupyterlab/toc": "^6.5.9", + "@jupyterlab/translation": "^4.5.9", + "@jupyterlab/ui-components": "^4.5.9", + "@lumino/algorithm": "^2.0.4", + "@lumino/coreutils": "^2.2.2", + "@lumino/domutils": "^2.0.4", + "@lumino/dragdrop": "^2.1.8", + "@lumino/messaging": "^2.0.4", + "@lumino/polling": "^2.1.5", + "@lumino/signaling": "^2.1.5", + "@lumino/virtualdom": "^2.0.4", + "@lumino/widgets": "^2.7.5", + "react": "^18.2.0" + } + }, + "node_modules/@jupyterlab/codeeditor": { + "version": "4.5.9", + "resolved": "https://registry.npmjs.org/@jupyterlab/codeeditor/-/codeeditor-4.5.9.tgz", + "integrity": "sha512-0rFO319u6YKHgEPhkb8Yr84ZxJS6wixjWuM0yn/NesnzInJ8YOfX9uC1raCeD+HcsR6TjmEP7rsbE+FamVWDIA==", + "license": "BSD-3-Clause", + "dependencies": { + "@codemirror/state": "^6.5.4", + "@jupyter/ydoc": "^3.1.0", + "@jupyterlab/apputils": "^4.6.9", + "@jupyterlab/coreutils": "^6.5.9", + "@jupyterlab/nbformat": "^4.5.9", + "@jupyterlab/observables": "^5.5.9", + "@jupyterlab/statusbar": "^4.5.9", + "@jupyterlab/translation": "^4.5.9", + "@jupyterlab/ui-components": "^4.5.9", + "@lumino/coreutils": "^2.2.2", + "@lumino/disposable": "^2.1.5", + "@lumino/dragdrop": "^2.1.8", + "@lumino/messaging": "^2.0.4", + "@lumino/signaling": "^2.1.5", + "@lumino/widgets": "^2.7.5", + "react": "^18.2.0" + } + }, + "node_modules/@jupyterlab/codemirror": { + "version": "4.5.9", + "resolved": "https://registry.npmjs.org/@jupyterlab/codemirror/-/codemirror-4.5.9.tgz", + "integrity": "sha512-Xv2ggYS2XdnIarmnfnvNVR4CuJkVnSktW56Uma5j8F07pr4KM+JdZb7pm+vToB5FlJHpk/v+UAOADSy5j1pgIg==", + "license": "BSD-3-Clause", + "dependencies": { + "@codemirror/autocomplete": "^6.20.0", + "@codemirror/commands": "^6.10.2", + "@codemirror/lang-cpp": "^6.0.3", + "@codemirror/lang-css": "^6.3.1", + "@codemirror/lang-html": "^6.4.11", + "@codemirror/lang-java": "^6.0.2", + "@codemirror/lang-javascript": "^6.2.4", + "@codemirror/lang-json": "^6.0.2", + "@codemirror/lang-markdown": "^6.5.0", + "@codemirror/lang-php": "^6.0.2", + "@codemirror/lang-python": "^6.2.1", + "@codemirror/lang-rust": "^6.0.2", + "@codemirror/lang-sql": "^6.10.0", + "@codemirror/lang-wast": "^6.0.2", + "@codemirror/lang-xml": "^6.1.0", + "@codemirror/language": "^6.12.1", + "@codemirror/legacy-modes": "^6.5.2", + "@codemirror/search": "^6.6.0", + "@codemirror/state": "^6.5.4", + "@codemirror/view": "^6.39.14", + "@jupyter/ydoc": "^3.1.0", + "@jupyterlab/codeeditor": "^4.5.9", + "@jupyterlab/coreutils": "^6.5.9", + "@jupyterlab/documentsearch": "^4.5.9", + "@jupyterlab/nbformat": "^4.5.9", + "@jupyterlab/translation": "^4.5.9", + "@lezer/common": "^1.2.1", + "@lezer/generator": "^1.7.0", + "@lezer/highlight": "^1.2.0", + "@lezer/markdown": "^1.3.0", + "@lumino/coreutils": "^2.2.2", + "@lumino/disposable": "^2.1.5", + "@lumino/signaling": "^2.1.5", + "yjs": "^13.5.40" + } + }, + "node_modules/@jupyterlab/coreutils": { + "version": "6.5.9", + "resolved": "https://registry.npmjs.org/@jupyterlab/coreutils/-/coreutils-6.5.9.tgz", + "integrity": "sha512-5sAzdFlxO3T78sFMMkRWCBA4VZoCjtSeNNk3F9DvEh/dz9N9OVw4YuW8+lFiFkVp7m/sR6Mho+QGVc8hpG4KsQ==", + "license": "BSD-3-Clause", + "dependencies": { + "@lumino/coreutils": "^2.2.2", + "@lumino/disposable": "^2.1.5", + "@lumino/signaling": "^2.1.5", + "minimist": "~1.2.0", + "path-browserify": "^1.0.0", + "url-parse": "~1.5.4" + } + }, + "node_modules/@jupyterlab/docmanager": { + "version": "4.5.9", + "resolved": "https://registry.npmjs.org/@jupyterlab/docmanager/-/docmanager-4.5.9.tgz", + "integrity": "sha512-HyOXrqp1ZLZVmx+265KuqwR1dIbrXZkQk6hbell1gvTkNDIYzMx3W9ZOlQewsHbRts67ORKFQwotb9M+NQeHyw==", + "license": "BSD-3-Clause", + "dependencies": { + "@jupyterlab/apputils": "^4.6.9", + "@jupyterlab/coreutils": "^6.5.9", + "@jupyterlab/docregistry": "^4.5.9", + "@jupyterlab/rendermime": "^4.5.9", + "@jupyterlab/services": "^7.5.9", + "@jupyterlab/statedb": "^4.5.9", + "@jupyterlab/statusbar": "^4.5.9", + "@jupyterlab/translation": "^4.5.9", + "@jupyterlab/ui-components": "^4.5.9", + "@lumino/algorithm": "^2.0.4", + "@lumino/coreutils": "^2.2.2", + "@lumino/disposable": "^2.1.5", + "@lumino/messaging": "^2.0.4", + "@lumino/polling": "^2.1.5", + "@lumino/properties": "^2.0.4", + "@lumino/signaling": "^2.1.5", + "@lumino/widgets": "^2.7.5", + "react": "^18.2.0" + } + }, + "node_modules/@jupyterlab/docregistry": { + "version": "4.5.9", + "resolved": "https://registry.npmjs.org/@jupyterlab/docregistry/-/docregistry-4.5.9.tgz", + "integrity": "sha512-9bPGgyPejZ010SrhLo6MwYLaQwllUb+15bGvWkiRD2Oom24J06bUzhc8QmtS2hc5IIdA4T0mTHbeOq6AD7tg6A==", + "license": "BSD-3-Clause", + "dependencies": { + "@jupyter/ydoc": "^3.1.0", + "@jupyterlab/apputils": "^4.6.9", + "@jupyterlab/codeeditor": "^4.5.9", + "@jupyterlab/coreutils": "^6.5.9", + "@jupyterlab/observables": "^5.5.9", + "@jupyterlab/rendermime": "^4.5.9", + "@jupyterlab/rendermime-interfaces": "^3.13.9", + "@jupyterlab/services": "^7.5.9", + "@jupyterlab/translation": "^4.5.9", + "@jupyterlab/ui-components": "^4.5.9", + "@lumino/algorithm": "^2.0.4", + "@lumino/coreutils": "^2.2.2", + "@lumino/disposable": "^2.1.5", + "@lumino/messaging": "^2.0.4", + "@lumino/properties": "^2.0.4", + "@lumino/signaling": "^2.1.5", + "@lumino/widgets": "^2.7.5", + "react": "^18.2.0" + } + }, + "node_modules/@jupyterlab/documentsearch": { + "version": "4.5.9", + "resolved": "https://registry.npmjs.org/@jupyterlab/documentsearch/-/documentsearch-4.5.9.tgz", + "integrity": "sha512-6VQojgxMJ87Jl+SaasbBLM3dkIFPmE6ne44VBbnmntGAXaxREy7YoJCpsIexc8pdE/GClii9jiWZzm05yGdpBQ==", + "license": "BSD-3-Clause", + "dependencies": { + "@jupyterlab/apputils": "^4.6.9", + "@jupyterlab/translation": "^4.5.9", + "@jupyterlab/ui-components": "^4.5.9", + "@lumino/commands": "^2.3.3", + "@lumino/coreutils": "^2.2.2", + "@lumino/disposable": "^2.1.5", + "@lumino/messaging": "^2.0.4", + "@lumino/polling": "^2.1.5", + "@lumino/signaling": "^2.1.5", + "@lumino/widgets": "^2.7.5", + "react": "^18.2.0" + } + }, + "node_modules/@jupyterlab/filebrowser": { + "version": "4.5.9", + "resolved": "https://registry.npmjs.org/@jupyterlab/filebrowser/-/filebrowser-4.5.9.tgz", + "integrity": "sha512-KuGjrOq+Ld978/y9qv3FYtMIhnRKT3mB+lWvKiEJBN9hORplgsKEaeuZaULSGA+ZTfq1uBlzXz2C271YMCWnBA==", + "license": "BSD-3-Clause", + "dependencies": { + "@jupyterlab/apputils": "^4.6.9", + "@jupyterlab/coreutils": "^6.5.9", + "@jupyterlab/docmanager": "^4.5.9", + "@jupyterlab/docregistry": "^4.5.9", + "@jupyterlab/services": "^7.5.9", + "@jupyterlab/statedb": "^4.5.9", + "@jupyterlab/statusbar": "^4.5.9", + "@jupyterlab/translation": "^4.5.9", + "@jupyterlab/ui-components": "^4.5.9", + "@lumino/algorithm": "^2.0.4", + "@lumino/coreutils": "^2.2.2", + "@lumino/disposable": "^2.1.5", + "@lumino/domutils": "^2.0.4", + "@lumino/dragdrop": "^2.1.8", + "@lumino/messaging": "^2.0.4", + "@lumino/polling": "^2.1.5", + "@lumino/signaling": "^2.1.5", + "@lumino/virtualdom": "^2.0.4", + "@lumino/widgets": "^2.7.5", + "jest-environment-jsdom": "^29.3.0", + "react": "^18.2.0" + } + }, + "node_modules/@jupyterlab/lsp": { + "version": "4.5.9", + "resolved": "https://registry.npmjs.org/@jupyterlab/lsp/-/lsp-4.5.9.tgz", + "integrity": "sha512-PmLhhvWFYQYOki7vpbQJ4Cksw0YIajlgd6QjKJN6lue9eFQuvHCfNrBm/c7C3cIjjaF54Z3TDuUID9f5Miq0cg==", + "license": "BSD-3-Clause", + "dependencies": { + "@jupyterlab/apputils": "^4.6.9", + "@jupyterlab/codeeditor": "^4.5.9", + "@jupyterlab/codemirror": "^4.5.9", + "@jupyterlab/coreutils": "^6.5.9", + "@jupyterlab/docregistry": "^4.5.9", + "@jupyterlab/services": "^7.5.9", + "@jupyterlab/translation": "^4.5.9", + "@lumino/coreutils": "^2.2.2", + "@lumino/disposable": "^2.1.5", + "@lumino/signaling": "^2.1.5", + "@lumino/widgets": "^2.7.5", + "lodash.mergewith": "^4.6.1", + "vscode-jsonrpc": "^6.0.0", + "vscode-languageserver-protocol": "^3.17.0", + "vscode-ws-jsonrpc": "~1.0.2" + } + }, + "node_modules/@jupyterlab/markedparser-extension": { + "version": "4.5.9", + "resolved": "https://registry.npmjs.org/@jupyterlab/markedparser-extension/-/markedparser-extension-4.5.9.tgz", + "integrity": "sha512-v5WQ7wZZCaTqqLTWSDYoB630EniAKC/iUuAFzRrKHTmdCjLjqwvEjhHT1132Kib/cKzzW41xJh0IWJuwDjo35w==", + "license": "BSD-3-Clause", + "dependencies": { + "@jupyterlab/application": "^4.5.9", + "@jupyterlab/codemirror": "^4.5.9", + "@jupyterlab/coreutils": "^6.5.9", + "@jupyterlab/mermaid": "^4.5.9", + "@jupyterlab/rendermime": "^4.5.9", + "@lumino/coreutils": "^2.2.2", + "marked": "^17.0.2", + "marked-gfm-heading-id": "^4.1.3", + "marked-mangle": "^1.1.12" + } + }, + "node_modules/@jupyterlab/mermaid": { + "version": "4.5.9", + "resolved": "https://registry.npmjs.org/@jupyterlab/mermaid/-/mermaid-4.5.9.tgz", + "integrity": "sha512-tdI7zgX02vBJYhgZy8pgAK4lCbR9hCvucn6ZPcodsvcJESP8ytUYGe5fSCx4+CfxQdQHb3SiwUqfBPc9tLEd7A==", + "license": "BSD-3-Clause", + "dependencies": { + "@jupyterlab/apputils": "^4.6.9", + "@jupyterlab/coreutils": "^6.5.9", + "@jupyterlab/rendermime-interfaces": "^3.13.9", + "@lumino/coreutils": "^2.2.2", + "@lumino/widgets": "^2.7.5", + "@mermaid-js/layout-elk": "^0.2.0", + "mermaid": "^11.12.3" + } + }, + "node_modules/@jupyterlab/nbformat": { + "version": "4.5.9", + "resolved": "https://registry.npmjs.org/@jupyterlab/nbformat/-/nbformat-4.5.9.tgz", + "integrity": "sha512-P9ip05CqbMh7UjTaX8I8icLK6VxCj/8kc2VKcOnxlNfzQBpi3pQyaD/u5mQj9FJf3tnMXaDIiIed4u26tO9XhA==", + "license": "BSD-3-Clause", + "dependencies": { + "@lumino/coreutils": "^2.2.2" + } + }, + "node_modules/@jupyterlab/notebook": { + "version": "4.5.9", + "resolved": "https://registry.npmjs.org/@jupyterlab/notebook/-/notebook-4.5.9.tgz", + "integrity": "sha512-OlVRX+X80Ci9UGICvVLZ/sA8v82EcwSgXAcPb5LHUDysbAc7ad3PL4RLwn3gf4UvMwg9RnlTaSOtj5kUKTBjxQ==", + "license": "BSD-3-Clause", + "dependencies": { + "@jupyter/ydoc": "^3.1.0", + "@jupyterlab/apputils": "^4.6.9", + "@jupyterlab/cells": "^4.5.9", + "@jupyterlab/codeeditor": "^4.5.9", + "@jupyterlab/codemirror": "^4.5.9", + "@jupyterlab/coreutils": "^6.5.9", + "@jupyterlab/docregistry": "^4.5.9", + "@jupyterlab/documentsearch": "^4.5.9", + "@jupyterlab/lsp": "^4.5.9", + "@jupyterlab/markedparser-extension": "^4.5.9", + "@jupyterlab/nbformat": "^4.5.9", + "@jupyterlab/observables": "^5.5.9", + "@jupyterlab/rendermime": "^4.5.9", + "@jupyterlab/services": "^7.5.9", + "@jupyterlab/settingregistry": "^4.5.9", + "@jupyterlab/statusbar": "^4.5.9", + "@jupyterlab/toc": "^6.5.9", + "@jupyterlab/translation": "^4.5.9", + "@jupyterlab/ui-components": "^4.5.9", + "@lumino/algorithm": "^2.0.4", + "@lumino/coreutils": "^2.2.2", + "@lumino/disposable": "^2.1.5", + "@lumino/domutils": "^2.0.4", + "@lumino/dragdrop": "^2.1.8", + "@lumino/messaging": "^2.0.4", + "@lumino/polling": "^2.1.5", + "@lumino/properties": "^2.0.4", + "@lumino/signaling": "^2.1.5", + "@lumino/virtualdom": "^2.0.4", + "@lumino/widgets": "^2.7.5", + "react": "^18.2.0" + } + }, + "node_modules/@jupyterlab/observables": { + "version": "5.5.9", + "resolved": "https://registry.npmjs.org/@jupyterlab/observables/-/observables-5.5.9.tgz", + "integrity": "sha512-5VPxmjzOhwF3F1sqJa7TljftVtxP/+/CE/cPi0Z7tRcBUy8HXr3O7kLP2u+NzNl6kCiVdFxkG8ruNOCHMZYkIQ==", + "license": "BSD-3-Clause", + "dependencies": { + "@lumino/algorithm": "^2.0.4", + "@lumino/coreutils": "^2.2.2", + "@lumino/disposable": "^2.1.5", + "@lumino/messaging": "^2.0.4", + "@lumino/signaling": "^2.1.5" + } + }, + "node_modules/@jupyterlab/outputarea": { + "version": "4.5.9", + "resolved": "https://registry.npmjs.org/@jupyterlab/outputarea/-/outputarea-4.5.9.tgz", + "integrity": "sha512-utphvQ0+mW+Gp2uh1qgBMSDCylFXUvswftb1kRhoiwvBT+xrLdPMFvyoAbE5ui8xsgu2jrgxR0QVn8sAX0YRSw==", + "license": "BSD-3-Clause", + "dependencies": { + "@jupyterlab/apputils": "^4.6.9", + "@jupyterlab/nbformat": "^4.5.9", + "@jupyterlab/observables": "^5.5.9", + "@jupyterlab/rendermime": "^4.5.9", + "@jupyterlab/rendermime-interfaces": "^3.13.9", + "@jupyterlab/services": "^7.5.9", + "@jupyterlab/translation": "^4.5.9", + "@lumino/algorithm": "^2.0.4", + "@lumino/coreutils": "^2.2.2", + "@lumino/disposable": "^2.1.5", + "@lumino/messaging": "^2.0.4", + "@lumino/properties": "^2.0.4", + "@lumino/signaling": "^2.1.5", + "@lumino/widgets": "^2.7.5" + } + }, + "node_modules/@jupyterlab/rendermime": { + "version": "4.5.9", + "resolved": "https://registry.npmjs.org/@jupyterlab/rendermime/-/rendermime-4.5.9.tgz", + "integrity": "sha512-/XAyfKtnI7uKMAml7HfaIJ+zmreKd8oVKKfaVuNyxpAsT4/qQ+AYBjOhkKlDTwMjFLaN/hB7Hk2bsPzj/UajzA==", + "license": "BSD-3-Clause", + "dependencies": { + "@jupyterlab/apputils": "^4.6.9", + "@jupyterlab/coreutils": "^6.5.9", + "@jupyterlab/nbformat": "^4.5.9", + "@jupyterlab/observables": "^5.5.9", + "@jupyterlab/rendermime-interfaces": "^3.13.9", + "@jupyterlab/services": "^7.5.9", + "@jupyterlab/translation": "^4.5.9", + "@lumino/coreutils": "^2.2.2", + "@lumino/messaging": "^2.0.4", + "@lumino/signaling": "^2.1.5", + "@lumino/widgets": "^2.7.5", + "lodash.escape": "^4.0.1" + } + }, + "node_modules/@jupyterlab/rendermime-interfaces": { + "version": "3.13.9", + "resolved": "https://registry.npmjs.org/@jupyterlab/rendermime-interfaces/-/rendermime-interfaces-3.13.9.tgz", + "integrity": "sha512-XO7maJMTArs3oblMlDq3NRIOfshQjhFy9PM/HqUZPFNvh+dMXxkBdMonVF2chJrDo+SGbEq5D2Y0EiFMgZHjTg==", + "license": "BSD-3-Clause", + "dependencies": { + "@lumino/coreutils": "^1.11.0 || ^2.2.2", + "@lumino/widgets": "^1.37.2 || ^2.7.5" + } + }, + "node_modules/@jupyterlab/services": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/@jupyterlab/services/-/services-7.5.9.tgz", + "integrity": "sha512-Ctmt1xxY7EQXrP0ml7Mm8vlM8XXpUr7R+LKCK4TNjLccZTetP/swDC4zLlvY4N+ej2XpoJG9E1TFgDJLz9Euhw==", + "license": "BSD-3-Clause", + "dependencies": { + "@jupyter/ydoc": "^3.1.0", + "@jupyterlab/coreutils": "^6.5.9", + "@jupyterlab/nbformat": "^4.5.9", + "@jupyterlab/settingregistry": "^4.5.9", + "@jupyterlab/statedb": "^4.5.9", + "@lumino/coreutils": "^2.2.2", + "@lumino/disposable": "^2.1.5", + "@lumino/polling": "^2.1.5", + "@lumino/properties": "^2.0.4", + "@lumino/signaling": "^2.1.5", + "ws": "^8.11.0" + } + }, + "node_modules/@jupyterlab/settingregistry": { + "version": "4.5.9", + "resolved": "https://registry.npmjs.org/@jupyterlab/settingregistry/-/settingregistry-4.5.9.tgz", + "integrity": "sha512-qV9v9y7ZA2F3OVh4fdztqOdx0VhNoGdUnipC1QEPNWyIzIkd8VFRFyu7BHAgxE9H85GoeIeFDdcqgY8niVH44g==", + "license": "BSD-3-Clause", + "dependencies": { + "@jupyterlab/nbformat": "^4.5.9", + "@jupyterlab/statedb": "^4.5.9", + "@lumino/commands": "^2.3.3", + "@lumino/coreutils": "^2.2.2", + "@lumino/disposable": "^2.1.5", + "@lumino/signaling": "^2.1.5", + "@rjsf/utils": "^5.13.4", + "ajv": "^8.12.0", + "json5": "^2.2.3" + }, + "peerDependencies": { + "react": ">=16" + } + }, + "node_modules/@jupyterlab/statedb": { + "version": "4.5.9", + "resolved": "https://registry.npmjs.org/@jupyterlab/statedb/-/statedb-4.5.9.tgz", + "integrity": "sha512-zvgX0RarmueX/gWTMcHPxVd6DCwehydNCpRYXMS9rUsn8yWIqtOp1Bx9P0hE8Qubc/5PehvF3NTZeI4OemGZrg==", + "license": "BSD-3-Clause", + "dependencies": { + "@lumino/commands": "^2.3.3", + "@lumino/coreutils": "^2.2.2", + "@lumino/disposable": "^2.1.5", + "@lumino/properties": "^2.0.4", + "@lumino/signaling": "^2.1.5" + } + }, + "node_modules/@jupyterlab/statusbar": { + "version": "4.5.9", + "resolved": "https://registry.npmjs.org/@jupyterlab/statusbar/-/statusbar-4.5.9.tgz", + "integrity": "sha512-nb1Aq33BwCHhccPtlc3w0ls5MSvLthZZk6BCzG2uNhRXTEHOF9LQZEE0b+BU380Nu36TOAOKUReYoFYYOxxSaQ==", + "license": "BSD-3-Clause", + "dependencies": { + "@jupyterlab/ui-components": "^4.5.9", + "@lumino/algorithm": "^2.0.4", + "@lumino/coreutils": "^2.2.2", + "@lumino/disposable": "^2.1.5", + "@lumino/messaging": "^2.0.4", + "@lumino/signaling": "^2.1.5", + "@lumino/widgets": "^2.7.5", + "react": "^18.2.0" + } + }, + "node_modules/@jupyterlab/toc": { + "version": "6.5.9", + "resolved": "https://registry.npmjs.org/@jupyterlab/toc/-/toc-6.5.9.tgz", + "integrity": "sha512-lkqFtLwNNpyvgGqDkCkLgrSxCsWX16DSN8IYBMrQ7EpLvYQSUmRqpT5ro0PywBEwl203ZUDExr+XGh4Vo2nSPg==", + "license": "BSD-3-Clause", + "dependencies": { + "@jupyter/react-components": "^0.16.6", + "@jupyterlab/apputils": "^4.6.9", + "@jupyterlab/coreutils": "^6.5.9", + "@jupyterlab/docregistry": "^4.5.9", + "@jupyterlab/observables": "^5.5.9", + "@jupyterlab/rendermime": "^4.5.9", + "@jupyterlab/rendermime-interfaces": "^3.13.9", + "@jupyterlab/translation": "^4.5.9", + "@jupyterlab/ui-components": "^4.5.9", + "@lumino/coreutils": "^2.2.2", + "@lumino/disposable": "^2.1.5", + "@lumino/messaging": "^2.0.4", + "@lumino/signaling": "^2.1.5", + "@lumino/widgets": "^2.7.5", + "react": "^18.2.0" + } + }, + "node_modules/@jupyterlab/translation": { + "version": "4.5.9", + "resolved": "https://registry.npmjs.org/@jupyterlab/translation/-/translation-4.5.9.tgz", + "integrity": "sha512-Pvj9lIo+unVDfr/TumR1b0P6/yvl3Ow5pDxjbFAJE0n/cy41BcLN9h0UnSge37ioaRnDBe3z0hOzCrADh8D/Wg==", + "license": "BSD-3-Clause", + "dependencies": { + "@jupyterlab/coreutils": "^6.5.9", + "@jupyterlab/rendermime-interfaces": "^3.13.9", + "@jupyterlab/services": "^7.5.9", + "@jupyterlab/statedb": "^4.5.9", + "@lumino/coreutils": "^2.2.2" + } + }, + "node_modules/@jupyterlab/ui-components": { + "version": "4.5.9", + "resolved": "https://registry.npmjs.org/@jupyterlab/ui-components/-/ui-components-4.5.9.tgz", + "integrity": "sha512-fKU7QGvOzrjO+xMzGuNAklLWOdsdMUZg3+GYm5inkg6Qmqq9r/DYLwuc2dKAHUN3swZmm0MjhT3Z1NyZygARlg==", + "license": "BSD-3-Clause", + "dependencies": { + "@jupyter/react-components": "^0.16.6", + "@jupyter/web-components": "^0.16.6", + "@jupyterlab/coreutils": "^6.5.9", + "@jupyterlab/observables": "^5.5.9", + "@jupyterlab/rendermime-interfaces": "^3.13.9", + "@jupyterlab/translation": "^4.5.9", + "@lumino/algorithm": "^2.0.4", + "@lumino/commands": "^2.3.3", + "@lumino/coreutils": "^2.2.2", + "@lumino/disposable": "^2.1.5", + "@lumino/messaging": "^2.0.4", + "@lumino/polling": "^2.1.5", + "@lumino/properties": "^2.0.4", + "@lumino/signaling": "^2.1.5", + "@lumino/virtualdom": "^2.0.4", + "@lumino/widgets": "^2.7.5", + "@rjsf/core": "^5.13.4", + "@rjsf/utils": "^5.13.4", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "typestyle": "^2.0.4" + }, + "peerDependencies": { + "react": "^18.2.0" + } + }, + "node_modules/@lezer/common": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.5.2.tgz", + "integrity": "sha512-sxQE460fPZyU3sdc8lafxiPwJHBzZRy/udNFynGQky1SePYBdhkBl1kOagA9uT3pxR8K09bOrmTUqA9wb/PjSQ==", + "license": "MIT" + }, + "node_modules/@lezer/cpp": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@lezer/cpp/-/cpp-1.1.6.tgz", + "integrity": "sha512-vh9gWWJOXFVY8HBHK3Twzq8MgwG2iN4GSyzBP9sCGTe37P15x2R14VaBQk0VA0ezTRN1KHYBBsHhvpGZ2Xy/pA==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, + "node_modules/@lezer/css": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@lezer/css/-/css-1.3.3.tgz", + "integrity": "sha512-RzBo8r+/6QJeow7aPHIpGVIH59xTcJXp399820gZoMo9noQDRVpJLheIBUicYwKcsbOYoBRoLZlf2720dG/4Tg==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.3.0" + } + }, + "node_modules/@lezer/generator": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@lezer/generator/-/generator-1.8.0.tgz", + "integrity": "sha512-/SF4EDWowPqV1jOgoGSGTIFsE7Ezdr7ZYxyihl5eMKVO5tlnpIhFcDavgm1hHY5GEonoOAEnJ0CU0x+tvuAuUg==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.1.0", + "@lezer/lr": "^1.3.0" + }, + "bin": { + "lezer-generator": "src/lezer-generator.cjs" + } + }, + "node_modules/@lezer/highlight": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.2.3.tgz", + "integrity": "sha512-qXdH7UqTvGfdVBINrgKhDsVTJTxactNNxLk7+UMwZhU13lMHaOBlJe9Vqp907ya56Y3+ed2tlqzys7jDkTmW0g==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.3.0" + } + }, + "node_modules/@lezer/html": { + "version": "1.3.13", + "resolved": "https://registry.npmjs.org/@lezer/html/-/html-1.3.13.tgz", + "integrity": "sha512-oI7n6NJml729m7pjm9lvLvmXbdoMoi2f+1pwSDJkl9d68zGr7a9Btz8NdHTGQZtW2DA25ybeuv/SyDb9D5tseg==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, + "node_modules/@lezer/java": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@lezer/java/-/java-1.1.3.tgz", + "integrity": "sha512-yHquUfujwg6Yu4Fd1GNHCvidIvJwi/1Xu2DaKl/pfWIA2c1oXkVvawH3NyXhCaFx4OdlYBVX5wvz2f7Aoa/4Xw==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, + "node_modules/@lezer/javascript": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@lezer/javascript/-/javascript-1.5.4.tgz", + "integrity": "sha512-vvYx3MhWqeZtGPwDStM2dwgljd5smolYD2lR2UyFcHfxbBQebqx8yjmFmxtJ/E6nN6u1D9srOiVWm3Rb4tmcUA==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.1.3", + "@lezer/lr": "^1.3.0" + } + }, + "node_modules/@lezer/json": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@lezer/json/-/json-1.0.3.tgz", + "integrity": "sha512-BP9KzdF9Y35PDpv04r0VeSTKDeox5vVr3efE7eBbx3r4s3oNLfunchejZhjArmeieBH+nVOpgIiBJpEAv8ilqQ==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, + "node_modules/@lezer/lr": { + "version": "1.4.10", + "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.4.10.tgz", + "integrity": "sha512-rnCpTIBafOx4mRp43xOxDJbFipJm/c0cia/V5TiGlhmMa+wsSdoGmUN3w5Bqrks/09Q/D4tNAmWaT8p6NRi77A==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.0.0" + } + }, + "node_modules/@lezer/markdown": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/@lezer/markdown/-/markdown-1.6.4.tgz", + "integrity": "sha512-N0SxazMj4k65DBfaf1azqtMZd6u7MqluP84/NZnB/io8Td9aleFmAhz9hcbvSfsxT5tdYlJ5qgv5aMJGY4zEtA==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.5.0", + "@lezer/highlight": "^1.0.0" + } + }, + "node_modules/@lezer/php": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@lezer/php/-/php-1.0.5.tgz", + "integrity": "sha512-W7asp9DhM6q0W6DYNwIkLSKOvxlXRrif+UXBMxzsJUuqmhE7oVU+gS3THO4S/Puh7Xzgm858UNaFi6dxTP8dJA==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.1.0" + } + }, + "node_modules/@lezer/python": { + "version": "1.1.19", + "resolved": "https://registry.npmjs.org/@lezer/python/-/python-1.1.19.tgz", + "integrity": "sha512-MhQIURHRytsNzP/YXnqpYKW6la6voAH3kyplTOOiCdjyFY6cWWGFVmYVdHIPrElqSDf4iCDktQCockB9FxuhzQ==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, + "node_modules/@lezer/rust": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@lezer/rust/-/rust-1.0.2.tgz", + "integrity": "sha512-Lz5sIPBdF2FUXcWeCu1//ojFAZqzTQNRga0aYv6dYXqJqPfMdCAI0NzajWUd4Xijj1IKJLtjoXRPMvTKWBcqKg==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, + "node_modules/@lezer/xml": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@lezer/xml/-/xml-1.0.6.tgz", + "integrity": "sha512-CdDwirL0OEaStFue/66ZmFSeppuL6Dwjlk8qk153mSQwiSH/Dlri4GNymrNWnUmPl2Um7QfV1FO9KFUyX3Twww==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, + "node_modules/@lumino/algorithm": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@lumino/algorithm/-/algorithm-2.0.4.tgz", + "integrity": "sha512-gddBhESPqu25KWLeAK9Kz8tS9Ph7P45i0CNG7Ia4XMhK9PHLtTsBdJTC9jP+MqhbzC8zDT/4ekvYRV9ojRPj7Q==", + "license": "BSD-3-Clause" + }, + "node_modules/@lumino/application": { + "version": "2.4.9", + "resolved": "https://registry.npmjs.org/@lumino/application/-/application-2.4.9.tgz", + "integrity": "sha512-7TvwwgcB3+cyTAgfHA7vbLkRvwJMEcWRZAN5NirBu5Jh7itVCaNIWMtsr4wUn4lPqyANHpfzcd3hKx56JKNrVg==", + "license": "BSD-3-Clause", + "dependencies": { + "@lumino/commands": "^2.3.3", + "@lumino/coreutils": "^2.2.2", + "@lumino/widgets": "^2.8.0" + } + }, + "node_modules/@lumino/collections": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@lumino/collections/-/collections-2.0.4.tgz", + "integrity": "sha512-D/Py9L5HET6+XUYGxFqDEEth4B65X2c7B/GQVRR8q5Fl7EArVL6e98ZXw8BMkuPcTNa0zlENpCKXzlcoJZxXgQ==", + "license": "BSD-3-Clause", + "dependencies": { + "@lumino/algorithm": "^2.0.4" + } + }, + "node_modules/@lumino/commands": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/@lumino/commands/-/commands-2.3.3.tgz", + "integrity": "sha512-7Ci0QdFzt4NKFMhULr19sJPpOLHJw/oYlq6Pb0/Kq1s05+cIoLimr5wiyjkbAlNoGO/8A8SEBGHy3uctZz6G3A==", + "license": "BSD-3-Clause", + "dependencies": { + "@lumino/algorithm": "^2.0.4", + "@lumino/coreutils": "^2.2.2", + "@lumino/disposable": "^2.1.5", + "@lumino/domutils": "^2.0.4", + "@lumino/keyboard": "^2.0.4", + "@lumino/signaling": "^2.1.5", + "@lumino/virtualdom": "^2.0.4" + } + }, + "node_modules/@lumino/coreutils": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/@lumino/coreutils/-/coreutils-2.2.2.tgz", + "integrity": "sha512-zaKJaK7rawPATn2BGHkbMrR6oK3s9PxNe9KreLwWF2dB4ZBHDiEmNLRyHRorfJ7XqVOEXAsAAj0jFn+qJPC/4Q==", + "license": "BSD-3-Clause", + "dependencies": { + "@lumino/algorithm": "^2.0.4" + } + }, + "node_modules/@lumino/disposable": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@lumino/disposable/-/disposable-2.1.5.tgz", + "integrity": "sha512-hO9AkJK0oEGzxopuxI8LaZqwzSNwXJTGCdr5K4gh6al+zxpN7rOCh6Aq3zDxkIHJU4zybxv8r02ardx9XJsG3A==", + "license": "BSD-3-Clause", + "dependencies": { + "@lumino/signaling": "^2.1.5" + } + }, + "node_modules/@lumino/domutils": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@lumino/domutils/-/domutils-2.0.4.tgz", + "integrity": "sha512-naYGUQn3e0CLtz/tjKOZP8SOBg0SW7EguhkxLpNUXlVUvx7rVsfr0VI22FVL+jgI0FbxXpEkxpSMxtK73jxJAg==", + "license": "BSD-3-Clause" + }, + "node_modules/@lumino/dragdrop": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/@lumino/dragdrop/-/dragdrop-2.1.8.tgz", + "integrity": "sha512-5sBYkTka598+XsgjY2tWOC+WYCh9NEgx8RhLvQ3x+V182YhcpEXw38RWGQZyNpQ4m4vtQWKv42A26q+ae6sMwg==", + "license": "BSD-3-Clause", + "dependencies": { + "@lumino/coreutils": "^2.2.2", + "@lumino/disposable": "^2.1.5" + } + }, + "node_modules/@lumino/keyboard": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@lumino/keyboard/-/keyboard-2.0.4.tgz", + "integrity": "sha512-kIVkdSz8F5wtZr8hZp0CMX+E0eMCOnFH6XCT7j2UBQ80ERJHFy0eX+IbNo3dtRQ7+CcDhBV4hQquFNFa+/04QQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@lumino/messaging": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@lumino/messaging/-/messaging-2.0.4.tgz", + "integrity": "sha512-NbZnchAPOciSe9Qn/g6EzG0LRaw7bygFIXbCD440ZhzvugdBeAerwYhrA795jkXPNrrl3olp5AlO0cBB/XZNtg==", + "license": "BSD-3-Clause", + "dependencies": { + "@lumino/algorithm": "^2.0.4", + "@lumino/collections": "^2.0.4" + } + }, + "node_modules/@lumino/polling": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@lumino/polling/-/polling-2.1.5.tgz", + "integrity": "sha512-YhQRWTNRVSi5R5uatwh1jkxASY5JKyAGWmtnfQOZWLDUFmsIjOTsS8NaYg1BgneZjWM3fbA18dCDDT7PPs5X1g==", + "license": "BSD-3-Clause", + "dependencies": { + "@lumino/coreutils": "^2.2.2", + "@lumino/disposable": "^2.1.5", + "@lumino/signaling": "^2.1.5" + } + }, + "node_modules/@lumino/properties": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@lumino/properties/-/properties-2.0.4.tgz", + "integrity": "sha512-XsL2qLZk+1FbfuTrkyjciI8PMDw3YcaBkqVQ+iv7OOJf9bUlrmTpCMY0Hu5d3hV2W3TWlRsdbvRRLEBJSKv0iA==", + "license": "BSD-3-Clause" + }, + "node_modules/@lumino/signaling": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@lumino/signaling/-/signaling-2.1.5.tgz", + "integrity": "sha512-Wkx6WR45ynmKBlW0GBEoh4xk9+QluKr1JHuMftqcStBHSQBCnN54UKRRDbySXHGRhhx6p4neu7sGomgQSlQK8w==", + "license": "BSD-3-Clause", + "dependencies": { + "@lumino/algorithm": "^2.0.4", + "@lumino/coreutils": "^2.2.2" + } + }, + "node_modules/@lumino/virtualdom": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@lumino/virtualdom/-/virtualdom-2.0.4.tgz", + "integrity": "sha512-7MFthA9KUsqZTGm/D98FZt1QupjIGyd3XyB4SIugn6DQAqhjBiyykCZydnRq3qmuMHybQel33dNIbHpzyNyQwA==", + "license": "BSD-3-Clause", + "dependencies": { + "@lumino/algorithm": "^2.0.4" + } + }, + "node_modules/@lumino/widgets": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@lumino/widgets/-/widgets-2.8.0.tgz", + "integrity": "sha512-mgWcbxxolqC58mpN4HcPKQvZ1AzQFStonsffaIsR4Kor2vRhc7+RFc0hd5VnhgJowvoFmmREQhZW8ETR1ydCVw==", + "license": "BSD-3-Clause", + "dependencies": { + "@lumino/algorithm": "^2.0.4", + "@lumino/commands": "^2.3.3", + "@lumino/coreutils": "^2.2.2", + "@lumino/disposable": "^2.1.5", + "@lumino/domutils": "^2.0.4", + "@lumino/dragdrop": "^2.1.8", + "@lumino/keyboard": "^2.0.4", + "@lumino/messaging": "^2.0.4", + "@lumino/properties": "^2.0.4", + "@lumino/signaling": "^2.1.5", + "@lumino/virtualdom": "^2.0.4" + } + }, + "node_modules/@marijn/find-cluster-break": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@marijn/find-cluster-break/-/find-cluster-break-1.0.2.tgz", + "integrity": "sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==", + "license": "MIT" + }, + "node_modules/@mermaid-js/layout-elk": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@mermaid-js/layout-elk/-/layout-elk-0.2.1.tgz", + "integrity": "sha512-MX9jwhMyd5zDcFsYcl3duDUkKhjVRUCGEQrdCeNV5hCIR6+3FuDDbRbFmvVbAu15K1+juzsYGG+K8MDvCY1Amg==", + "license": "MIT", + "dependencies": { + "d3": "^7.9.0", + "elkjs": "^0.9.3" + }, + "peerDependencies": { + "mermaid": "^11.0.2" + } + }, + "node_modules/@mermaid-js/parser": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@mermaid-js/parser/-/parser-1.1.1.tgz", + "integrity": "sha512-VuHdsYMK1bT6X2JbcAaWAhugTRvRBRyuZgd+c22swUeI9g/ntaxF7CY7dYarhZovofCbUNO0G7JesfmNtjYOCw==", + "license": "MIT", + "dependencies": { + "@chevrotain/types": "~11.1.1" + } + }, + "node_modules/@microsoft/fast-colors": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@microsoft/fast-colors/-/fast-colors-5.3.1.tgz", + "integrity": "sha512-72RZXVfCbwQzvo5sXXkuLXLT7rMeYaSf5r/6ewQiv/trBtqpWRm4DEH2EilHw/iWTBKOXs1qZNQndgUMa5n4LA==", + "license": "MIT" + }, + "node_modules/@microsoft/fast-element": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@microsoft/fast-element/-/fast-element-1.14.0.tgz", + "integrity": "sha512-zXvuSOzvsu8zDTy9eby8ix8VqLop2rwKRgp++ZN2kTCsoB3+QJVoaGD2T/Cyso2ViZQFXNpiNCVKfnmxBvmWkQ==", + "license": "MIT" + }, + "node_modules/@microsoft/fast-foundation": { + "version": "2.50.0", + "resolved": "https://registry.npmjs.org/@microsoft/fast-foundation/-/fast-foundation-2.50.0.tgz", + "integrity": "sha512-8mFYG88Xea1jZf2TI9Lm/jzZ6RWR8x29r24mGuLojNYqIR2Bl8+hnswoV6laApKdCbGMPKnsAL/O68Q0sRxeVg==", + "license": "MIT", + "dependencies": { + "@microsoft/fast-element": "^1.14.0", + "@microsoft/fast-web-utilities": "^5.4.1", + "tabbable": "^5.2.0", + "tslib": "^1.13.0" + } + }, + "node_modules/@microsoft/fast-web-utilities": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/@microsoft/fast-web-utilities/-/fast-web-utilities-5.4.1.tgz", + "integrity": "sha512-ReWYncndjV3c8D8iq9tp7NcFNc1vbVHvcBFPME2nNFKNbS1XCesYZGlIlf3ot5EmuOXPlrzUHOWzQ2vFpIkqDg==", + "license": "MIT", + "dependencies": { + "exenv-es6": "^1.1.1" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@rjsf/core": { + "version": "5.24.13", + "resolved": "https://registry.npmjs.org/@rjsf/core/-/core-5.24.13.tgz", + "integrity": "sha512-ONTr14s7LFIjx2VRFLuOpagL76sM/HPy6/OhdBfq6UukINmTIs6+aFN0GgcR0aXQHFDXQ7f/fel0o/SO05Htdg==", + "license": "Apache-2.0", + "dependencies": { + "lodash": "^4.17.21", + "lodash-es": "^4.17.21", + "markdown-to-jsx": "^7.4.1", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@rjsf/utils": "^5.24.x", + "react": "^16.14.0 || >=17" + } + }, + "node_modules/@rjsf/utils": { + "version": "5.24.13", + "resolved": "https://registry.npmjs.org/@rjsf/utils/-/utils-5.24.13.tgz", + "integrity": "sha512-rNF8tDxIwTtXzz5O/U23QU73nlhgQNYJ+Sv5BAwQOIyhIE2Z3S5tUiSVMwZHt0julkv/Ryfwi+qsD4FiE5rOuw==", + "license": "Apache-2.0", + "dependencies": { + "json-schema-merge-allof": "^0.8.1", + "jsonpointer": "^5.0.1", + "lodash": "^4.17.21", + "lodash-es": "^4.17.21", + "react-is": "^18.2.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "react": "^16.14.0 || >=17" + } + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.10", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.10.tgz", + "integrity": "sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==", + "license": "MIT" + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "license": "BSD-3-Clause", + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, + "node_modules/@tootallnate/once": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.1.tgz", + "integrity": "sha512-HqmEUIGRJ5fSXchkVgR5F7qn48bDBzv0kWj/Kfu5e6uci4UlEeng4331LnBkWffb++Ei3FOVLxo8JJWMFBDMeQ==", + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/@types/d3": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@types/d3/-/d3-7.4.3.tgz", + "integrity": "sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww==", + "license": "MIT", + "dependencies": { + "@types/d3-array": "*", + "@types/d3-axis": "*", + "@types/d3-brush": "*", + "@types/d3-chord": "*", + "@types/d3-color": "*", + "@types/d3-contour": "*", + "@types/d3-delaunay": "*", + "@types/d3-dispatch": "*", + "@types/d3-drag": "*", + "@types/d3-dsv": "*", + "@types/d3-ease": "*", + "@types/d3-fetch": "*", + "@types/d3-force": "*", + "@types/d3-format": "*", + "@types/d3-geo": "*", + "@types/d3-hierarchy": "*", + "@types/d3-interpolate": "*", + "@types/d3-path": "*", + "@types/d3-polygon": "*", + "@types/d3-quadtree": "*", + "@types/d3-random": "*", + "@types/d3-scale": "*", + "@types/d3-scale-chromatic": "*", + "@types/d3-selection": "*", + "@types/d3-shape": "*", + "@types/d3-time": "*", + "@types/d3-time-format": "*", + "@types/d3-timer": "*", + "@types/d3-transition": "*", + "@types/d3-zoom": "*" + } + }, + "node_modules/@types/d3-array": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.2.tgz", + "integrity": "sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw==", + "license": "MIT" + }, + "node_modules/@types/d3-axis": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-axis/-/d3-axis-3.0.6.tgz", + "integrity": "sha512-pYeijfZuBd87T0hGn0FO1vQ/cgLk6E1ALJjfkC0oJ8cbwkZl3TpgS8bVBLZN+2jjGgg38epgxb2zmoGtSfvgMw==", + "license": "MIT", + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-brush": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-brush/-/d3-brush-3.0.6.tgz", + "integrity": "sha512-nH60IZNNxEcrh6L1ZSMNA28rj27ut/2ZmI3r96Zd+1jrZD++zD3LsMIjWlvg4AYrHn/Pqz4CF3veCxGjtbqt7A==", + "license": "MIT", + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-chord": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-chord/-/d3-chord-3.0.6.tgz", + "integrity": "sha512-LFYWWd8nwfwEmTZG9PfQxd17HbNPksHBiJHaKuY1XeqscXacsS2tyoo6OdRsjf+NQYeB6XrNL3a25E3gH69lcg==", + "license": "MIT" + }, + "node_modules/@types/d3-color": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz", + "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==", + "license": "MIT" + }, + "node_modules/@types/d3-contour": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-contour/-/d3-contour-3.0.6.tgz", + "integrity": "sha512-BjzLgXGnCWjUSYGfH1cpdo41/hgdWETu4YxpezoztawmqsvCeep+8QGfiY6YbDvfgHz/DkjeIkkZVJavB4a3rg==", + "license": "MIT", + "dependencies": { + "@types/d3-array": "*", + "@types/geojson": "*" + } + }, + "node_modules/@types/d3-delaunay": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-delaunay/-/d3-delaunay-6.0.4.tgz", + "integrity": "sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw==", + "license": "MIT" + }, + "node_modules/@types/d3-dispatch": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-dispatch/-/d3-dispatch-3.0.7.tgz", + "integrity": "sha512-5o9OIAdKkhN1QItV2oqaE5KMIiXAvDWBDPrD85e58Qlz1c1kI/J0NcqbEG88CoTwJrYe7ntUCVfeUl2UJKbWgA==", + "license": "MIT" + }, + "node_modules/@types/d3-drag": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-drag/-/d3-drag-3.0.7.tgz", + "integrity": "sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ==", + "license": "MIT", + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-dsv": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-dsv/-/d3-dsv-3.0.7.tgz", + "integrity": "sha512-n6QBF9/+XASqcKK6waudgL0pf/S5XHPPI8APyMLLUHd8NqouBGLsU8MgtO7NINGtPBtk9Kko/W4ea0oAspwh9g==", + "license": "MIT" + }, + "node_modules/@types/d3-ease": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz", + "integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==", + "license": "MIT" + }, + "node_modules/@types/d3-fetch": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-fetch/-/d3-fetch-3.0.7.tgz", + "integrity": "sha512-fTAfNmxSb9SOWNB9IoG5c8Hg6R+AzUHDRlsXsDZsNp6sxAEOP0tkP3gKkNSO/qmHPoBFTxNrjDprVHDQDvo5aA==", + "license": "MIT", + "dependencies": { + "@types/d3-dsv": "*" + } + }, + "node_modules/@types/d3-force": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/@types/d3-force/-/d3-force-3.0.10.tgz", + "integrity": "sha512-ZYeSaCF3p73RdOKcjj+swRlZfnYpK1EbaDiYICEEp5Q6sUiqFaFQ9qgoshp5CzIyyb/yD09kD9o2zEltCexlgw==", + "license": "MIT" + }, + "node_modules/@types/d3-format": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-format/-/d3-format-3.0.4.tgz", + "integrity": "sha512-fALi2aI6shfg7vM5KiR1wNJnZ7r6UuggVqtDA+xiEdPZQwy/trcQaHnwShLuLdta2rTymCNpxYTiMZX/e09F4g==", + "license": "MIT" + }, + "node_modules/@types/d3-geo": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@types/d3-geo/-/d3-geo-3.1.0.tgz", + "integrity": "sha512-856sckF0oP/diXtS4jNsiQw/UuK5fQG8l/a9VVLeSouf1/PPbBE1i1W852zVwKwYCBkFJJB7nCFTbk6UMEXBOQ==", + "license": "MIT", + "dependencies": { + "@types/geojson": "*" + } + }, + "node_modules/@types/d3-hierarchy": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@types/d3-hierarchy/-/d3-hierarchy-3.1.7.tgz", + "integrity": "sha512-tJFtNoYBtRtkNysX1Xq4sxtjK8YgoWUNpIiUee0/jHGRwqvzYxkq0hGVbbOGSz+JgFxxRu4K8nb3YpG3CMARtg==", + "license": "MIT" + }, + "node_modules/@types/d3-interpolate": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz", + "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==", + "license": "MIT", + "dependencies": { + "@types/d3-color": "*" + } + }, + "node_modules/@types/d3-path": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.1.tgz", + "integrity": "sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==", + "license": "MIT" + }, + "node_modules/@types/d3-polygon": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-polygon/-/d3-polygon-3.0.2.tgz", + "integrity": "sha512-ZuWOtMaHCkN9xoeEMr1ubW2nGWsp4nIql+OPQRstu4ypeZ+zk3YKqQT0CXVe/PYqrKpZAi+J9mTs05TKwjXSRA==", + "license": "MIT" + }, + "node_modules/@types/d3-quadtree": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-quadtree/-/d3-quadtree-3.0.6.tgz", + "integrity": "sha512-oUzyO1/Zm6rsxKRHA1vH0NEDG58HrT5icx/azi9MF1TWdtttWl0UIUsjEQBBh+SIkrpd21ZjEv7ptxWys1ncsg==", + "license": "MIT" + }, + "node_modules/@types/d3-random": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/d3-random/-/d3-random-3.0.3.tgz", + "integrity": "sha512-Imagg1vJ3y76Y2ea0871wpabqp613+8/r0mCLEBfdtqC7xMSfj9idOnmBYyMoULfHePJyxMAw3nWhJxzc+LFwQ==", + "license": "MIT" + }, + "node_modules/@types/d3-scale": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.9.tgz", + "integrity": "sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==", + "license": "MIT", + "dependencies": { + "@types/d3-time": "*" + } + }, + "node_modules/@types/d3-scale-chromatic": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz", + "integrity": "sha512-iWMJgwkK7yTRmWqRB5plb1kadXyQ5Sj8V/zYlFGMUBbIPKQScw+Dku9cAAMgJG+z5GYDoMjWGLVOvjghDEFnKQ==", + "license": "MIT" + }, + "node_modules/@types/d3-selection": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/@types/d3-selection/-/d3-selection-3.0.11.tgz", + "integrity": "sha512-bhAXu23DJWsrI45xafYpkQ4NtcKMwWnAC/vKrd2l+nxMFuvOT3XMYTIj2opv8vq8AO5Yh7Qac/nSeP/3zjTK0w==", + "license": "MIT" + }, + "node_modules/@types/d3-shape": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.8.tgz", + "integrity": "sha512-lae0iWfcDeR7qt7rA88BNiqdvPS5pFVPpo5OfjElwNaT2yyekbM0C9vK+yqBqEmHr6lDkRnYNoTBYlAgJa7a4w==", + "license": "MIT", + "dependencies": { + "@types/d3-path": "*" + } + }, + "node_modules/@types/d3-time": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.4.tgz", + "integrity": "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==", + "license": "MIT" + }, + "node_modules/@types/d3-time-format": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@types/d3-time-format/-/d3-time-format-4.0.3.tgz", + "integrity": "sha512-5xg9rC+wWL8kdDj153qZcsJ0FWiFt0J5RB6LYUNZjwSnesfblqrI/bJ1wBdJ8OQfncgbJG5+2F+qfqnqyzYxyg==", + "license": "MIT" + }, + "node_modules/@types/d3-timer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz", + "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==", + "license": "MIT" + }, + "node_modules/@types/d3-transition": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@types/d3-transition/-/d3-transition-3.0.9.tgz", + "integrity": "sha512-uZS5shfxzO3rGlu0cC3bjmMFKsXv+SmZZcgp0KD22ts4uGXp5EVYGzu/0YdwZeKmddhcAccYtREJKkPfXkZuCg==", + "license": "MIT", + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-zoom": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@types/d3-zoom/-/d3-zoom-3.0.8.tgz", + "integrity": "sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw==", + "license": "MIT", + "dependencies": { + "@types/d3-interpolate": "*", + "@types/d3-selection": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/geojson": { + "version": "7946.0.16", + "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.16.tgz", + "integrity": "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==", + "license": "MIT" + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "license": "MIT" + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/jsdom": { + "version": "20.0.1", + "resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-20.0.1.tgz", + "integrity": "sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/tough-cookie": "*", + "parse5": "^7.0.0" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "25.9.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.9.3.tgz", + "integrity": "sha512-603BddQMv3pUcr4U2dhujk83N2tTDVr/34wII2B6bJy6g+8WD6yUb11jszNs0gdi4PesVWl7ABt8nYMVpnLUcg==", + "license": "MIT", + "dependencies": { + "undici-types": ">=7.24.0 <7.24.7" + } + }, + "node_modules/@types/prop-types": { + "version": "15.7.15", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz", + "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==", + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "18.3.31", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.31.tgz", + "integrity": "sha512-vfEqpXTvwT91yhmwdfouStN2hSKwTvyRs8qpLfADyrq/kxDw0hZM7Wk9Ug1FELj8hIby+S/+kQCSRFF32nv2Qw==", + "license": "MIT", + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.2.2" + } + }, + "node_modules/@types/stack-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", + "license": "MIT" + }, + "node_modules/@types/tough-cookie": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", + "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==", + "license": "MIT" + }, + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", + "license": "MIT", + "optional": true + }, + "node_modules/@types/yargs": { + "version": "17.0.35", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.35.tgz", + "integrity": "sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==", + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "license": "MIT" + }, + "node_modules/@upsetjs/venn.js": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@upsetjs/venn.js/-/venn.js-2.0.0.tgz", + "integrity": "sha512-WbBhLrooyePuQ1VZxrJjtLvTc4NVfpOyKx0sKqioq9bX1C1m7Jgykkn8gLrtwumBioXIqam8DLxp88Adbue6Hw==", + "license": "MIT", + "optionalDependencies": { + "d3-selection": "^3.0.0", + "d3-transition": "^3.0.1" + } + }, + "node_modules/@webassemblyjs/ast": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", + "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/helper-numbers": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", + "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", + "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", + "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz", + "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.13.2", + "@webassemblyjs/helper-api-error": "1.13.2", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", + "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz", + "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/wasm-gen": "1.14.1" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz", + "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz", + "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", + "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz", + "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/helper-wasm-section": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-opt": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1", + "@webassemblyjs/wast-printer": "1.14.1" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz", + "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz", + "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz", + "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-api-error": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz", + "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webpack-cli/configtest": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-2.1.1.tgz", + "integrity": "sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.15.0" + }, + "peerDependencies": { + "webpack": "5.x.x", + "webpack-cli": "5.x.x" + } + }, + "node_modules/@webpack-cli/info": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-2.0.2.tgz", + "integrity": "sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.15.0" + }, + "peerDependencies": { + "webpack": "5.x.x", + "webpack-cli": "5.x.x" + } + }, + "node_modules/@webpack-cli/serve": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-2.0.5.tgz", + "integrity": "sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.15.0" + }, + "peerDependencies": { + "webpack": "5.x.x", + "webpack-cli": "5.x.x" + }, + "peerDependenciesMeta": { + "webpack-dev-server": { + "optional": true + } + } + }, + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/abab": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", + "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", + "deprecated": "Use your platform's native atob() and btoa() methods instead", + "license": "BSD-3-Clause" + }, + "node_modules/acorn": { + "version": "8.17.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.17.0.tgz", + "integrity": "sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==", + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-globals": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-7.0.1.tgz", + "integrity": "sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==", + "license": "MIT", + "dependencies": { + "acorn": "^8.1.0", + "acorn-walk": "^8.0.2" + } + }, + "node_modules/acorn-import-phases": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz", + "integrity": "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.13.0" + }, + "peerDependencies": { + "acorn": "^8.14.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.5", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.5.tgz", + "integrity": "sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==", + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/ajv": { + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/baseline-browser-mapping": { + "version": "2.10.38", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.38.tgz", + "integrity": "sha512-31/02mVB4yuQU6adKk5SlY6m+mxDwUq5KZkyYgnLrrKl7TEm1+3PyDtDBz2kOv/wxZz41GHsvV1A/u6RmiyBvw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.28.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.2.tgz", + "integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.10.12", + "caniuse-lite": "^1.0.30001782", + "electron-to-chromium": "^1.5.328", + "node-releases": "^2.0.36", + "update-browserslist-db": "^1.2.3" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001799", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001799.tgz", + "integrity": "sha512-hG1bReV+OUU+MOqK4t/ZWI0tZOyz3rqS9XuhOUz1cIcbwBKjOyJEJuw9ER5JuNyqxNk8u/JUVbGibBOL1yrjFw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/chalk/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/chalk/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/chrome-trace-event": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", + "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0" + } + }, + "node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/clone-deep/node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "license": "MIT", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true, + "license": "MIT" + }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true, + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || >=14" + } + }, + "node_modules/compute-gcd": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/compute-gcd/-/compute-gcd-1.2.1.tgz", + "integrity": "sha512-TwMbxBNz0l71+8Sc4czv13h4kEqnchV9igQZBi6QUaz09dnz13juGnnaWWJTRsP3brxOoxeB4SA2WELLw1hCtg==", + "dependencies": { + "validate.io-array": "^1.0.3", + "validate.io-function": "^1.0.2", + "validate.io-integer-array": "^1.0.0" + } + }, + "node_modules/compute-lcm": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/compute-lcm/-/compute-lcm-1.1.2.tgz", + "integrity": "sha512-OFNPdQAXnQhDSKioX8/XYT6sdUlXwpeMjfd6ApxMJfyZ4GxmLR1xvMERctlYhlHwIiz6CSpBc2+qYKjHGZw4TQ==", + "dependencies": { + "compute-gcd": "^1.2.1", + "validate.io-array": "^1.0.3", + "validate.io-function": "^1.0.2", + "validate.io-integer-array": "^1.0.0" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cose-base": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/cose-base/-/cose-base-1.0.3.tgz", + "integrity": "sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg==", + "license": "MIT", + "dependencies": { + "layout-base": "^1.0.0" + } + }, + "node_modules/crelt": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz", + "integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==", + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/css-loader": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", + "integrity": "sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==", + "dev": true, + "license": "MIT", + "dependencies": { + "icss-utils": "^5.1.0", + "postcss": "^8.4.33", + "postcss-modules-extract-imports": "^3.1.0", + "postcss-modules-local-by-default": "^4.0.5", + "postcss-modules-scope": "^3.2.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cssom": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.5.0.tgz", + "integrity": "sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==", + "license": "MIT" + }, + "node_modules/cssstyle": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", + "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", + "license": "MIT", + "dependencies": { + "cssom": "~0.3.6" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cssstyle/node_modules/cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", + "license": "MIT" + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "license": "MIT" + }, + "node_modules/cytoscape": { + "version": "3.34.0", + "resolved": "https://registry.npmjs.org/cytoscape/-/cytoscape-3.34.0.tgz", + "integrity": "sha512-62rNSrioXw93uliKFBwjukeQyeWwH2PqDrTac31r2P6464u3AUvTk0xS4LVvT251g7IgkFunrI48ZEZGjywSOg==", + "license": "MIT", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/cytoscape-cose-bilkent": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cytoscape-cose-bilkent/-/cytoscape-cose-bilkent-4.1.0.tgz", + "integrity": "sha512-wgQlVIUJF13Quxiv5e1gstZ08rnZj2XaLHGoFMYXz7SkNfCDOOteKBE6SYRfA9WxxI/iBc3ajfDoc6hb/MRAHQ==", + "license": "MIT", + "dependencies": { + "cose-base": "^1.0.0" + }, + "peerDependencies": { + "cytoscape": "^3.2.0" + } + }, + "node_modules/cytoscape-fcose": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cytoscape-fcose/-/cytoscape-fcose-2.2.0.tgz", + "integrity": "sha512-ki1/VuRIHFCzxWNrsshHYPs6L7TvLu3DL+TyIGEsRcvVERmxokbf5Gdk7mFxZnTdiGtnA4cfSmjZJMviqSuZrQ==", + "license": "MIT", + "dependencies": { + "cose-base": "^2.2.0" + }, + "peerDependencies": { + "cytoscape": "^3.2.0" + } + }, + "node_modules/cytoscape-fcose/node_modules/cose-base": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cose-base/-/cose-base-2.2.0.tgz", + "integrity": "sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g==", + "license": "MIT", + "dependencies": { + "layout-base": "^2.0.0" + } + }, + "node_modules/cytoscape-fcose/node_modules/layout-base": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/layout-base/-/layout-base-2.0.1.tgz", + "integrity": "sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg==", + "license": "MIT" + }, + "node_modules/d3": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/d3/-/d3-7.9.0.tgz", + "integrity": "sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA==", + "license": "ISC", + "dependencies": { + "d3-array": "3", + "d3-axis": "3", + "d3-brush": "3", + "d3-chord": "3", + "d3-color": "3", + "d3-contour": "4", + "d3-delaunay": "6", + "d3-dispatch": "3", + "d3-drag": "3", + "d3-dsv": "3", + "d3-ease": "3", + "d3-fetch": "3", + "d3-force": "3", + "d3-format": "3", + "d3-geo": "3", + "d3-hierarchy": "3", + "d3-interpolate": "3", + "d3-path": "3", + "d3-polygon": "3", + "d3-quadtree": "3", + "d3-random": "3", + "d3-scale": "4", + "d3-scale-chromatic": "3", + "d3-selection": "3", + "d3-shape": "3", + "d3-time": "3", + "d3-time-format": "4", + "d3-timer": "3", + "d3-transition": "3", + "d3-zoom": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-array": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", + "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", + "license": "ISC", + "dependencies": { + "internmap": "1 - 2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-axis": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-3.0.0.tgz", + "integrity": "sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-brush": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-3.0.0.tgz", + "integrity": "sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==", + "license": "ISC", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "3", + "d3-transition": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-chord": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-3.0.1.tgz", + "integrity": "sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==", + "license": "ISC", + "dependencies": { + "d3-path": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-color": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", + "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-contour": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-4.0.2.tgz", + "integrity": "sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==", + "license": "ISC", + "dependencies": { + "d3-array": "^3.2.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-delaunay": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.4.tgz", + "integrity": "sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==", + "license": "ISC", + "dependencies": { + "delaunator": "5" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dispatch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", + "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-drag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz", + "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==", + "license": "ISC", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-selection": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dsv": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-3.0.1.tgz", + "integrity": "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==", + "license": "ISC", + "dependencies": { + "commander": "7", + "iconv-lite": "0.6", + "rw": "1" + }, + "bin": { + "csv2json": "bin/dsv2json.js", + "csv2tsv": "bin/dsv2dsv.js", + "dsv2dsv": "bin/dsv2dsv.js", + "dsv2json": "bin/dsv2json.js", + "json2csv": "bin/json2dsv.js", + "json2dsv": "bin/json2dsv.js", + "json2tsv": "bin/json2dsv.js", + "tsv2csv": "bin/dsv2dsv.js", + "tsv2json": "bin/dsv2json.js" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dsv/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/d3-ease": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", + "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-fetch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-3.0.1.tgz", + "integrity": "sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==", + "license": "ISC", + "dependencies": { + "d3-dsv": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-force": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz", + "integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==", + "license": "ISC", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-quadtree": "1 - 3", + "d3-timer": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-format": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.2.tgz", + "integrity": "sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-geo": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.1.1.tgz", + "integrity": "sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==", + "license": "ISC", + "dependencies": { + "d3-array": "2.5.0 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-hierarchy": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz", + "integrity": "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-interpolate": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", + "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", + "license": "ISC", + "dependencies": { + "d3-color": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-polygon": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-3.0.1.tgz", + "integrity": "sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-quadtree": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz", + "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-random": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-3.0.1.tgz", + "integrity": "sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-sankey": { + "version": "0.12.3", + "resolved": "https://registry.npmjs.org/d3-sankey/-/d3-sankey-0.12.3.tgz", + "integrity": "sha512-nQhsBRmM19Ax5xEIPLMY9ZmJ/cDvd1BG3UVvt5h3WRxKg5zGRbvnteTyWAbzeSvlh3tW7ZEmq4VwR5mB3tutmQ==", + "license": "BSD-3-Clause", + "dependencies": { + "d3-array": "1 - 2", + "d3-shape": "^1.2.0" + } + }, + "node_modules/d3-sankey/node_modules/d3-array": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.12.1.tgz", + "integrity": "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==", + "license": "BSD-3-Clause", + "dependencies": { + "internmap": "^1.0.0" + } + }, + "node_modules/d3-sankey/node_modules/d3-path": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.9.tgz", + "integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==", + "license": "BSD-3-Clause" + }, + "node_modules/d3-sankey/node_modules/d3-shape": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.7.tgz", + "integrity": "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==", + "license": "BSD-3-Clause", + "dependencies": { + "d3-path": "1" + } + }, + "node_modules/d3-sankey/node_modules/internmap": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-1.0.1.tgz", + "integrity": "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==", + "license": "ISC" + }, + "node_modules/d3-scale": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", + "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", + "license": "ISC", + "dependencies": { + "d3-array": "2.10.0 - 3", + "d3-format": "1 - 3", + "d3-interpolate": "1.2.0 - 3", + "d3-time": "2.1.1 - 3", + "d3-time-format": "2 - 4" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-scale-chromatic": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz", + "integrity": "sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==", + "license": "ISC", + "dependencies": { + "d3-color": "1 - 3", + "d3-interpolate": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-selection": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", + "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-shape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", + "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", + "license": "ISC", + "dependencies": { + "d3-path": "^3.1.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", + "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", + "license": "ISC", + "dependencies": { + "d3-array": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time-format": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", + "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", + "license": "ISC", + "dependencies": { + "d3-time": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-timer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", + "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-transition": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz", + "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", + "license": "ISC", + "dependencies": { + "d3-color": "1 - 3", + "d3-dispatch": "1 - 3", + "d3-ease": "1 - 3", + "d3-interpolate": "1 - 3", + "d3-timer": "1 - 3" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "d3-selection": "2 - 3" + } + }, + "node_modules/d3-zoom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz", + "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==", + "license": "ISC", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "2 - 3", + "d3-transition": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/dagre-d3-es": { + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/dagre-d3-es/-/dagre-d3-es-7.0.14.tgz", + "integrity": "sha512-P4rFMVq9ESWqmOgK+dlXvOtLwYg0i7u0HBGJER0LZDJT2VHIPAMZ/riPxqJceWMStH5+E61QxFra9kIS3AqdMg==", + "license": "MIT", + "dependencies": { + "d3": "^7.9.0", + "lodash-es": "^4.17.21" + } + }, + "node_modules/data-urls": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-3.0.2.tgz", + "integrity": "sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==", + "license": "MIT", + "dependencies": { + "abab": "^2.0.6", + "whatwg-mimetype": "^3.0.0", + "whatwg-url": "^11.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/dayjs": { + "version": "1.11.21", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.21.tgz", + "integrity": "sha512-98IT+HOahAisibz/yjKbzuOBwYcjJ7BCLPzARyHiyEBmRz4fatF+KPJszEHXsGYjUG234aH/cOjW1wwTbKUZlA==", + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decimal.js": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.6.0.tgz", + "integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==", + "license": "MIT" + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/delaunator": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.1.0.tgz", + "integrity": "sha512-AGrQ4QSgssa1NGmWmLPqN5NY2KajF5MqxetNEO+o0n3ZwZZeTmt7bBnvzHWrmkZFxGgr4HdyFgelzgi06otLuQ==", + "license": "ISC", + "dependencies": { + "robust-predicates": "^3.0.2" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/dom-serializer/node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "BSD-2-Clause" + }, + "node_modules/domexception": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz", + "integrity": "sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==", + "deprecated": "Use your platform's native DOMException instead", + "license": "MIT", + "dependencies": { + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/dompurify": { + "version": "3.4.11", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.11.tgz", + "integrity": "sha512-zhlUV12GsaRzMsf9q5M254YhA4+VuF0fG+QFqu6aYpoGlKtz+w8//jBcGVYBgQkR5GHjUomejY84AV+/uPbWdw==", + "license": "(MPL-2.0 OR Apache-2.0)", + "optionalDependencies": { + "@types/trusted-types": "^2.0.7" + } + }, + "node_modules/domutils": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", + "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", + "license": "BSD-2-Clause", + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/duplicate-package-checker-webpack-plugin": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/duplicate-package-checker-webpack-plugin/-/duplicate-package-checker-webpack-plugin-3.0.0.tgz", + "integrity": "sha512-aO50/qPC7X2ChjRFniRiscxBLT/K01bALqfcDaf8Ih5OqQ1N4iT/Abx9Ofu3/ms446vHTm46FACIuJUmgUQcDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^2.3.0", + "find-root": "^1.0.0", + "lodash": "^4.17.4", + "semver": "^5.4.1" + } + }, + "node_modules/duplicate-package-checker-webpack-plugin/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true, + "license": "MIT" + }, + "node_modules/electron-to-chromium": { + "version": "1.5.375", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.375.tgz", + "integrity": "sha512-ZWP5eB4BVPW/ZYo9252hQZHZ5XavtsTgpbhcmMmRwymavC5AsLWQWBPaKMeNd2LW0KGby5HPXvj7+sr4ta5j/Q==", + "dev": true, + "license": "ISC" + }, + "node_modules/elkjs": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/elkjs/-/elkjs-0.9.3.tgz", + "integrity": "sha512-f/ZeWvW/BCXbhGEf1Ujp29EASo/lk1FDnETgNKwJrsVvGZhUWCZyg3xLJjAsxfOmt8KjswHmI5EwCQcPMpOYhQ==", + "license": "EPL-2.0" + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/enhanced-resolve": { + "version": "5.24.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.24.0.tgz", + "integrity": "sha512-SkE2t82KlkkxQRVMVLAGKxLfORGQfrkx5dkj+vlgXRVNEdPc4eZcR+J/Fvj8C+yKSFH5L0q3NFlyufOVQnCcYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.3.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/envinfo": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.21.0.tgz", + "integrity": "sha512-Lw7I8Zp5YKHFCXL7+Dz95g4CcbMEpgvqZNNq3AmlT5XAV6CgAAk6gyAMqn2zjw08K9BHfcNuKrMiCPLByGafow==", + "dev": true, + "license": "MIT", + "bin": { + "envinfo": "dist/cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-module-lexer": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.1.0.tgz", + "integrity": "sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/es-object-atoms": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-toolkit": { + "version": "1.47.1", + "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.47.1.tgz", + "integrity": "sha512-5RAqEwf4P4E17p+W75KLOWw/nOvKZzSQpxM32IpI2KZLaVonjTrZ0Ai5ghMaVI9eKC2p8eoQgcBdkEDgzFk6+Q==", + "license": "MIT", + "workspaces": [ + "docs", + "benchmarks" + ] + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/escodegen": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", + "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", + "license": "BSD-2-Clause", + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-scope/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/exenv-es6": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/exenv-es6/-/exenv-es6-1.1.1.tgz", + "integrity": "sha512-vlVu3N8d6yEMpMsEm+7sUBAI81aqYYuEvfK0jNqmdb/OPXzzH7QWDDnVjMvDSY47JdHEqx/dfC/q8WkfoTmpGQ==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "license": "MIT" + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "license": "MIT" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.2.tgz", + "integrity": "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/fastest-levenshtein": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4.9.1" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==", + "dev": true, + "license": "MIT" + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "license": "BSD-3-Clause", + "bin": { + "flat": "cli.js" + } + }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "dev": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/form-data": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz", + "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.4", + "mime-types": "^2.1.35" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/free-style": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/free-style/-/free-style-3.1.0.tgz", + "integrity": "sha512-vJujYSIyT30iDoaoeigNAxX4yB1RUrh+N2ZMhIElMr3BvCuGXOw7XNJMEEJkDUeamK2Rnb/IKFGKRKlTWIGRWA==", + "license": "MIT" + }, + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, + "license": "ISC" + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/github-slugger": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-2.0.0.tgz", + "integrity": "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==", + "license": "ISC" + }, + "node_modules/glob": { + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC" + }, + "node_modules/hachure-fill": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/hachure-fill/-/hachure-fill-0.5.2.tgz", + "integrity": "sha512-3GKBOn+m2LX9iq+JC1064cSFprJY4jL1jCXTcpnfER5HYE2l/4EfWSGzkPa/ZDBmYI0ZOEj5VHV/eKnPGkHuOg==", + "license": "MIT" + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/html-encoding-sniffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", + "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", + "license": "MIT", + "dependencies": { + "whatwg-encoding": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/htmlparser2": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", + "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1", + "entities": "^4.4.0" + } + }, + "node_modules/htmlparser2/node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "license": "MIT", + "dependencies": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/import-local": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", + "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-meta-resolve": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.2.0.tgz", + "integrity": "sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/internmap": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", + "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/interpret": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz", + "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/is-core-module": { + "version": "2.16.2", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.2.tgz", + "integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isomorphic.js": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/isomorphic.js/-/isomorphic.js-0.2.5.tgz", + "integrity": "sha512-PIeMbHqMt4DnUP3MA/Flc0HElYjMXArsw1qwJZcm9sqR8mq3l8NYizFMty0pWwE/tzIGH3EKK5+jes5mAr85yw==", + "license": "MIT", + "funding": { + "type": "GitHub Sponsors ❤", + "url": "https://github.com/sponsors/dmonad" + } + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jest-environment-jsdom": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-29.7.0.tgz", + "integrity": "sha512-k9iQbsf9OyOfdzWH8HDmrRT0gSIcX+FLNW7IQq94tFX0gynPwqDTW0Ho6iMVNjGz/nb+l/vW3dWM2bbLLpkbXA==", + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/jsdom": "^20.0.0", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0", + "jsdom": "^20.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "canvas": "^2.5.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-message-util/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-message-util/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-message-util/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-message-util/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-util/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-util/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-util/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-util/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "license": "MIT" + }, + "node_modules/jsdom": { + "version": "20.0.3", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-20.0.3.tgz", + "integrity": "sha512-SYhBvTh89tTfCD/CRdSOm13mOBa42iTaTyfyEWBdKcGdPxPtLFBXuHR8XHb33YNYaP+lLbmSvBTsnoesCNJEsQ==", + "license": "MIT", + "dependencies": { + "abab": "^2.0.6", + "acorn": "^8.8.1", + "acorn-globals": "^7.0.0", + "cssom": "^0.5.0", + "cssstyle": "^2.3.0", + "data-urls": "^3.0.2", + "decimal.js": "^10.4.2", + "domexception": "^4.0.0", + "escodegen": "^2.0.0", + "form-data": "^4.0.0", + "html-encoding-sniffer": "^3.0.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.1", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.2", + "parse5": "^7.1.1", + "saxes": "^6.0.0", + "symbol-tree": "^3.2.4", + "tough-cookie": "^4.1.2", + "w3c-xmlserializer": "^4.0.0", + "webidl-conversions": "^7.0.0", + "whatwg-encoding": "^2.0.0", + "whatwg-mimetype": "^3.0.0", + "whatwg-url": "^11.0.0", + "ws": "^8.11.0", + "xml-name-validator": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "canvas": "^2.5.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/json-schema-compare": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/json-schema-compare/-/json-schema-compare-0.2.2.tgz", + "integrity": "sha512-c4WYmDKyJXhs7WWvAWm3uIYnfyWFoIp+JEoX34rctVvEkMYCPGhXtvmFFXiffBbxfZsvQ0RNnV5H7GvDF5HCqQ==", + "license": "MIT", + "dependencies": { + "lodash": "^4.17.4" + } + }, + "node_modules/json-schema-merge-allof": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/json-schema-merge-allof/-/json-schema-merge-allof-0.8.1.tgz", + "integrity": "sha512-CTUKmIlPJbsWfzRRnOXz+0MjIqvnleIXwFTzz+t9T86HnYX/Rozria6ZVGLktAU9e+NygNljveP+yxqtQp/Q4w==", + "license": "MIT", + "dependencies": { + "compute-lcm": "^1.1.2", + "json-schema-compare": "^0.2.2", + "lodash": "^4.17.20" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonfile": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonpointer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz", + "integrity": "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/katex": { + "version": "0.16.47", + "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.47.tgz", + "integrity": "sha512-Eeo8Ys1doU1z+x8AZsPpQu+p/QcZBI5PeOo7QGQdy2x2m0MU/hYagBbGOmXwr5KVbEfVuWv9LpnQWeehogurjg==", + "funding": [ + "https://opencollective.com/katex", + "https://github.com/sponsors/katex" + ], + "license": "MIT", + "dependencies": { + "commander": "^8.3.0" + }, + "bin": { + "katex": "cli.js" + } + }, + "node_modules/katex/node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "node_modules/khroma": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/khroma/-/khroma-2.1.0.tgz", + "integrity": "sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw==" + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/layout-base": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/layout-base/-/layout-base-1.0.2.tgz", + "integrity": "sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg==", + "license": "MIT" + }, + "node_modules/lib0": { + "version": "0.2.117", + "resolved": "https://registry.npmjs.org/lib0/-/lib0-0.2.117.tgz", + "integrity": "sha512-DeXj9X5xDCjgKLU/7RR+/HQEVzuuEUiwldwOGsHK/sfAfELGWEyTcf0x+uOvCvK3O2zPmZePXWL85vtia6GyZw==", + "license": "MIT", + "dependencies": { + "isomorphic.js": "^0.2.4" + }, + "bin": { + "0ecdsa-generate-keypair": "bin/0ecdsa-generate-keypair.js", + "0gentesthtml": "bin/gentesthtml.js", + "0serve": "bin/0serve.js" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "type": "GitHub Sponsors ❤", + "url": "https://github.com/sponsors/dmonad" + } + }, + "node_modules/license-webpack-plugin": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/license-webpack-plugin/-/license-webpack-plugin-4.0.2.tgz", + "integrity": "sha512-771TFWFD70G1wLTC4oU2Cw4qvtmNrIw+wRvBtn+okgHl7slJVi7zfNcdmqDL72BojM30VNJ2UHylr1o77U37Jw==", + "dev": true, + "license": "ISC", + "dependencies": { + "webpack-sources": "^3.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + }, + "webpack-sources": { + "optional": true + } + } + }, + "node_modules/loader-runner": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.2.tgz", + "integrity": "sha512-DFEqQ3ihfS9blba08cLfYf1NRAIEm+dDjic073DRDc3/JspI/8wYmtDsHwd3+4hwvdxSK7PGaElfTmm0awWJ4w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.11.5" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/loader-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lodash": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", + "license": "MIT" + }, + "node_modules/lodash-es": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.18.1.tgz", + "integrity": "sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==", + "license": "MIT" + }, + "node_modules/lodash.escape": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-4.0.1.tgz", + "integrity": "sha512-nXEOnb/jK9g0DYMr1/Xvq6l5xMD7GDG55+GSYIYmS0G4tBk/hURD4JR9WCavs04t33WmJx9kCyp9vJ+mr4BOUw==", + "license": "MIT" + }, + "node_modules/lodash.mergewith": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz", + "integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==", + "license": "MIT" + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/markdown-to-jsx": { + "version": "7.7.17", + "resolved": "https://registry.npmjs.org/markdown-to-jsx/-/markdown-to-jsx-7.7.17.tgz", + "integrity": "sha512-7mG/1feQ0TX5I7YyMZVDgCC/y2I3CiEhIRQIhyov9nGBP5eoVrOXXHuL5ZP8GRfxVZKRiXWJgwXkb9It+nQZfQ==", + "license": "MIT", + "engines": { + "node": ">= 10" + }, + "peerDependencies": { + "react": ">= 0.14.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + } + } + }, + "node_modules/marked": { + "version": "17.0.6", + "resolved": "https://registry.npmjs.org/marked/-/marked-17.0.6.tgz", + "integrity": "sha512-gB0gkNafnonOw0obSTEGZTT86IuhILt2Wfx0mWH/1Au83kybTayroZ/V6nS25mN7u8ASy+5fMhgB3XPNrOZdmA==", + "license": "MIT", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/marked-gfm-heading-id": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/marked-gfm-heading-id/-/marked-gfm-heading-id-4.1.4.tgz", + "integrity": "sha512-CspnvVfHSkb/znqdPS4jUR8HtCjq3M/DnrsJCrfLBLvdrgbemmoINKpeWKQYkBiXAoBGejw0cV7xzqrPdup3WA==", + "license": "MIT", + "dependencies": { + "github-slugger": "^2.0.0" + }, + "peerDependencies": { + "marked": ">=13 <19" + } + }, + "node_modules/marked-mangle": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/marked-mangle/-/marked-mangle-1.1.13.tgz", + "integrity": "sha512-phz1W/nYMr1T08Q7wqH2aj+PPiK85E69WQGfId+prvryfgjY/Idibx4YUvKaYMDV9rK1qo+/yC+Quu/3gdaBeA==", + "license": "MIT", + "peerDependencies": { + "marked": ">=4 <19" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true, + "license": "MIT" + }, + "node_modules/mermaid": { + "version": "11.15.0", + "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-11.15.0.tgz", + "integrity": "sha512-pTMbcf3rWdtLiYGpmoTjHEpeY8seiy6sR+9nD7LOs8KfUbHE4lOUAprTRqRAcWSQ6MQpdX+YEsxShtGsINtPtw==", + "license": "MIT", + "dependencies": { + "@braintree/sanitize-url": "^7.1.1", + "@iconify/utils": "^3.0.2", + "@mermaid-js/parser": "^1.1.1", + "@types/d3": "^7.4.3", + "@upsetjs/venn.js": "^2.0.0", + "cytoscape": "^3.33.1", + "cytoscape-cose-bilkent": "^4.1.0", + "cytoscape-fcose": "^2.2.0", + "d3": "^7.9.0", + "d3-sankey": "^0.12.3", + "dagre-d3-es": "7.0.14", + "dayjs": "^1.11.19", + "dompurify": "^3.3.1", + "es-toolkit": "^1.45.1", + "katex": "^0.16.25", + "khroma": "^2.1.0", + "marked": "^16.3.0", + "roughjs": "^4.6.6", + "stylis": "^4.3.6", + "ts-dedent": "^2.2.0", + "uuid": "^11.1.0 || ^12 || ^13 || ^14.0.0" + } + }, + "node_modules/mermaid/node_modules/marked": { + "version": "16.4.2", + "resolved": "https://registry.npmjs.org/marked/-/marked-16.4.2.tgz", + "integrity": "sha512-TI3V8YYWvkVf3KJe1dRkpnjs68JUPyEa5vjKrp1XEEJUAOaQc+Qj+L1qWbPd0SJuAdQkFU0h73sXXqwDYxsiDA==", + "license": "MIT", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mini-css-extract-plugin": { + "version": "2.10.2", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.10.2.tgz", + "integrity": "sha512-AOSS0IdEB95ayVkxn5oGzNQwqAi2J0Jb/kKm43t7H73s8+f5873g0yuj0PNvK4dO75mu5DHg4nlgp4k6Kga8eg==", + "dev": true, + "license": "MIT", + "dependencies": { + "schema-utils": "^4.0.0", + "tapable": "^2.2.1" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/mini-svg-data-uri": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/mini-svg-data-uri/-/mini-svg-data-uri-1.4.4.tgz", + "integrity": "sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==", + "dev": true, + "license": "MIT", + "bin": { + "mini-svg-data-uri": "cli.js" + } + }, + "node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.12", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", + "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-releases": { + "version": "2.0.47", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.47.tgz", + "integrity": "sha512-Uzmd6LXpouKo8EUK68IjH4+E01w/hXyV3R3g/geCJo+rXLNfh1xucB+LOzYEOQPSiUK3h/xZf0cQGcSsmyL2Og==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/nwsapi": { + "version": "2.2.24", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.24.tgz", + "integrity": "sha512-7YRhZ3jS45LwmSCT4b2sVFHt/WuovaktDU07QrtOBY2PXskss5a9jfmR9jptyumwXST+rFjrmppMY1KT/yn35A==", + "license": "MIT" + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true, + "license": "BlueOak-1.0.0" + }, + "node_modules/package-manager-detector": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.6.0.tgz", + "integrity": "sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA==", + "license": "MIT" + }, + "node_modules/parse-srcset": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-srcset/-/parse-srcset-1.0.2.tgz", + "integrity": "sha512-/2qh0lav6CmI15FzA3i/2Bzk2zCgQhGMkvhOhKNcBVQ1ldgpbfiNTVslmooUmWJcADi1f1kIeynbDRVzNlfR6Q==", + "license": "MIT" + }, + "node_modules/parse5": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", + "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", + "license": "MIT", + "dependencies": { + "entities": "^6.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "license": "MIT" + }, + "node_modules/path-data-parser": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/path-data-parser/-/path-data-parser-0.1.0.tgz", + "integrity": "sha512-NOnmBpt5Y2RWbuv0LMzsayp3lVylAHLPUTut412ZA3l+C4uw4ZVkQbjShYCQ8TCpUMdPapr4YjUqLYD6v68j+w==", + "license": "MIT" + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/points-on-curve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/points-on-curve/-/points-on-curve-0.2.0.tgz", + "integrity": "sha512-0mYKnYYe9ZcqMCWhUjItv/oHjvgEsfKvnUTg8sAtnHr3GVy7rGkXCb6d5cSyqrWqL4k81b9CPg3urd+T7aop3A==", + "license": "MIT" + }, + "node_modules/points-on-path": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/points-on-path/-/points-on-path-0.2.1.tgz", + "integrity": "sha512-25ClnWWuw7JbWZcgqY/gJ4FQWadKxGWk+3kR/7kD0tCaDtPPMj7oHu2ToLaVhfpnHrZzYby2w6tUA0eOIuUg8g==", + "license": "MIT", + "dependencies": { + "path-data-parser": "0.1.0", + "points-on-curve": "0.2.0" + } + }, + "node_modules/postcss": { + "version": "8.5.15", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz", + "integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.12", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-modules-extract-imports": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", + "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-local-by-default": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.2.0.tgz", + "integrity": "sha512-5kcJm/zk+GJDSfw+V/42fJ5fhjL5YbFDl8nVdXkJPLLW+Vf9mTD5Xe0wqIaDnLuL2U6cDNpTr+UQ+v2HWIBhzw==", + "dev": true, + "license": "MIT", + "dependencies": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^7.0.0", + "postcss-value-parser": "^4.1.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-scope": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.1.tgz", + "integrity": "sha512-m9jZstCVaqGjTAuny8MdgE88scJnCiQSlSrOWcTQgM2t32UBe+MUmFSO5t7VMSfAf/FJKImAxBav8ooCHJXCJA==", + "dev": true, + "license": "ISC", + "dependencies": { + "postcss-selector-parser": "^7.0.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "icss-utils": "^5.0.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-selector-parser": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.4.tgz", + "integrity": "sha512-HeP7D2wyhkR+XaK6v4W8oRF62Dsz4flyuczALJp61GckGm42u1saSSJ/0auvcBqxs3jMRFEcPK34At/0JBKdOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/prop-types/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "license": "MIT" + }, + "node_modules/psl": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.15.0.tgz", + "integrity": "sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==", + "license": "MIT", + "dependencies": { + "punycode": "^2.3.1" + }, + "funding": { + "url": "https://github.com/sponsors/lupomontero" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", + "license": "MIT" + }, + "node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, + "node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "license": "MIT" + }, + "node_modules/rechoir": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", + "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve": "^1.20.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "license": "MIT" + }, + "node_modules/resolve": { + "version": "1.22.12", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz", + "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/rimraf": { + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.10.tgz", + "integrity": "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^10.3.7" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/brace-expansion": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.1.tgz", + "integrity": "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/rimraf/node_modules/glob": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/minimatch": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.2" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/robust-predicates": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.3.tgz", + "integrity": "sha512-NS3levdsRIUOmiJ8FZWCP7LG3QpJyrs/TE0Zpf1yvZu8cAJJ6QMW92H1c7kWpdIHo8RvmLxN/o2JXTKHp74lUA==", + "license": "Unlicense" + }, + "node_modules/roughjs": { + "version": "4.6.6", + "resolved": "https://registry.npmjs.org/roughjs/-/roughjs-4.6.6.tgz", + "integrity": "sha512-ZUz/69+SYpFN/g/lUlo2FXcIjRkSu3nDarreVdGGndHEBJ6cXPdKguS8JGxwj5HA5xIbVKSmLgr5b3AWxtRfvQ==", + "license": "MIT", + "dependencies": { + "hachure-fill": "^0.5.2", + "path-data-parser": "^0.1.0", + "points-on-curve": "^0.2.0", + "points-on-path": "^0.2.1" + } + }, + "node_modules/rw": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", + "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==", + "license": "BSD-3-Clause" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/sanitize-html": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-2.12.1.tgz", + "integrity": "sha512-Plh+JAn0UVDpBRP/xEjsk+xDCoOvMBwQUf/K+/cBAVuTbtX8bj2VB7S1sL1dssVpykqp0/KPSesHrqXtokVBpA==", + "license": "MIT", + "dependencies": { + "deepmerge": "^4.2.2", + "escape-string-regexp": "^4.0.0", + "htmlparser2": "^8.0.0", + "is-plain-object": "^5.0.0", + "parse-srcset": "^1.0.2", + "postcss": "^8.3.11" + } + }, + "node_modules/sanitize-html/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/saxes": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", + "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", + "license": "ISC", + "dependencies": { + "xmlchars": "^2.2.0" + }, + "engines": { + "node": ">=v12.22.7" + } + }, + "node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/schema-utils": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz", + "integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/semver": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.4.tgz", + "integrity": "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dev": true, + "license": "MIT", + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "devOptional": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-loader": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-1.0.2.tgz", + "integrity": "sha512-oX8d6ndRjN+tVyjj6PlXSyFPhDdVAPsZA30nD3/II8g4uOv8fCz0DMn5sy8KtVbDfKQxOpGwGJnK3xIW3tauDw==", + "dev": true, + "license": "MIT", + "dependencies": { + "data-urls": "^2.0.0", + "iconv-lite": "^0.6.2", + "loader-utils": "^2.0.0", + "schema-utils": "^2.7.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/source-map-loader/node_modules/ajv": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/source-map-loader/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/source-map-loader/node_modules/data-urls": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz", + "integrity": "sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "abab": "^2.0.3", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^8.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/source-map-loader/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/source-map-loader/node_modules/schema-utils": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", + "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.5", + "ajv": "^6.12.4", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 8.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/source-map-loader/node_modules/tr46": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz", + "integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==", + "dev": true, + "license": "MIT", + "dependencies": { + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/source-map-loader/node_modules/webidl-conversions": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", + "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=10.4" + } + }, + "node_modules/source-map-loader/node_modules/whatwg-mimetype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", + "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", + "dev": true, + "license": "MIT" + }, + "node_modules/source-map-loader/node_modules/whatwg-url": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz", + "integrity": "sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "lodash": "^4.7.0", + "tr46": "^2.1.0", + "webidl-conversions": "^6.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/style-loader": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.4.tgz", + "integrity": "sha512-0WqXzrsMTyb8yjZJHDqwmnwRJvhALK9LfRtRc6B4UTWe8AijYLZYZ9thuJTZc2VfQWINADW/j+LiJnfy2RoC1w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/style-mod": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.3.tgz", + "integrity": "sha512-i/n8VsZydrugj3Iuzll8+x/00GH2vnYsk1eomD8QiRrSAeW6ItbCQDtfXCeJHd0iwiNagqjQkvpvREEPtW3IoQ==", + "license": "MIT" + }, + "node_modules/stylis": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.4.0.tgz", + "integrity": "sha512-5Z9ZpRzfuH6l/UAvCPAPUo3665Nk2wLaZU3x+TLHKVzIz33+sbJqbtrYoC3KD4/uVOr2Zp+L0LySezP9OHV9yA==", + "license": "MIT" + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "license": "MIT" + }, + "node_modules/tabbable": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-5.3.3.tgz", + "integrity": "sha512-QD9qKY3StfbZqWOPLp0++pOrAVb/HbUi5xCc8cUo4XjP19808oaMiDzn0leBY5mCespIBM0CIZePzZjgzR83kA==", + "license": "MIT" + }, + "node_modules/tapable": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz", + "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/terser": { + "version": "5.48.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.48.0.tgz", + "integrity": "sha512-J/9An6vs9Us6wKRriSFXBWdRZapREHqFzdNUKk0pmu804EMR6dr6winwo7e5JDxN4xahxQsuysyYFwlwj4XN/Q==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.15.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser-webpack-plugin": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.6.1.tgz", + "integrity": "sha512-201R5j+sJpK8nFWwKVyNfZot8FaJbLZDq5evriVzbV1wDtSXDjRUDRfJzHpAaxFDMEhsZL1QkeqM61wgsS3KaQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.25", + "jest-worker": "^27.4.5", + "schema-utils": "^4.3.0", + "terser": "^5.31.1" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@minify-html/node": { + "optional": true + }, + "@swc/core": { + "optional": true + }, + "@swc/css": { + "optional": true + }, + "@swc/html": { + "optional": true + }, + "clean-css": { + "optional": true + }, + "cssnano": { + "optional": true + }, + "csso": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "html-minifier-terser": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "postcss": { + "optional": true + }, + "uglify-js": { + "optional": true + } + } + }, + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyexec": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.2.4.tgz", + "integrity": "sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/tough-cookie": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", + "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==", + "license": "BSD-3-Clause", + "dependencies": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.2.0", + "url-parse": "^1.5.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tough-cookie/node_modules/universalify": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", + "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/tr46": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", + "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", + "license": "MIT", + "dependencies": { + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/ts-dedent": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/ts-dedent/-/ts-dedent-2.3.0.tgz", + "integrity": "sha512-JfJeIHke7y2egdGGgRAvpCwYFUsHlM2gPcrVOxFkznt/4uzQ7HFmvE63iFHVLBJNDuyDOQgijDK/tXH/f6Msjg==", + "license": "MIT", + "engines": { + "node": ">=6.10" + } + }, + "node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "license": "0BSD" + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/typescript": { + "version": "5.4.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", + "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/typestyle": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/typestyle/-/typestyle-2.4.0.tgz", + "integrity": "sha512-/d1BL6Qi+YlMLEydnUEB8KL/CAjAN8cyt3/UyGnOyBrWf7bLGcR/6yhmsaUstO2IcYwZfagjE7AIzuI2vUW9mg==", + "license": "MIT", + "dependencies": { + "csstype": "3.0.10", + "free-style": "3.1.0" + } + }, + "node_modules/typestyle/node_modules/csstype": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.10.tgz", + "integrity": "sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA==", + "license": "MIT" + }, + "node_modules/undici-types": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.24.6.tgz", + "integrity": "sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==", + "license": "MIT" + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/url-parse": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "license": "MIT", + "dependencies": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/uuid": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-14.0.0.tgz", + "integrity": "sha512-Qo+uWgilfSmAhXCMav1uYFynlQO7fMFiMVZsQqZRMIXp0O7rR7qjkj+cPvBHLgBqi960QCoo/PH2/6ZtVqKvrg==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist-node/bin/uuid" + } + }, + "node_modules/validate.io-array": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/validate.io-array/-/validate.io-array-1.0.6.tgz", + "integrity": "sha512-DeOy7CnPEziggrOO5CZhVKJw6S3Yi7e9e65R1Nl/RTN1vTQKnzjfvks0/8kQ40FP/dsjRAOd4hxmJ7uLa6vxkg==", + "license": "MIT" + }, + "node_modules/validate.io-function": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/validate.io-function/-/validate.io-function-1.0.2.tgz", + "integrity": "sha512-LlFybRJEriSuBnUhQyG5bwglhh50EpTL2ul23MPIuR1odjO7XaMLFV8vHGwp7AZciFxtYOeiSCT5st+XSPONiQ==" + }, + "node_modules/validate.io-integer": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/validate.io-integer/-/validate.io-integer-1.0.5.tgz", + "integrity": "sha512-22izsYSLojN/P6bppBqhgUDjCkr5RY2jd+N2a3DCAUey8ydvrZ/OkGvFPR7qfOpwR2LC5p4Ngzxz36g5Vgr/hQ==", + "dependencies": { + "validate.io-number": "^1.0.3" + } + }, + "node_modules/validate.io-integer-array": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/validate.io-integer-array/-/validate.io-integer-array-1.0.0.tgz", + "integrity": "sha512-mTrMk/1ytQHtCY0oNO3dztafHYyGU88KL+jRxWuzfOmQb+4qqnWmI+gykvGp8usKZOM0H7keJHEbRaFiYA0VrA==", + "dependencies": { + "validate.io-array": "^1.0.3", + "validate.io-integer": "^1.0.4" + } + }, + "node_modules/validate.io-number": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/validate.io-number/-/validate.io-number-1.0.3.tgz", + "integrity": "sha512-kRAyotcbNaSYoDnXvb4MHg/0a1egJdLwS6oJ38TJY7aw9n93Fl/3blIXdyYvPOp55CNxywooG/3BcrwNrBpcSg==" + }, + "node_modules/vscode-jsonrpc": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-6.0.0.tgz", + "integrity": "sha512-wnJA4BnEjOSyFMvjZdpiOwhSq9uDoK8e/kpRJDTaMYzwlkrhG1fwDIZI94CLsLzlCK5cIbMMtFlJlfR57Lavmg==", + "license": "MIT", + "engines": { + "node": ">=8.0.0 || >=10.0.0" + } + }, + "node_modules/vscode-languageserver-protocol": { + "version": "3.18.0", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.18.0.tgz", + "integrity": "sha512-Zdz+kJ12Iz6tc11xfZyEo501bBATHXrCjmMfnaR3pMnf1CoqZBKIynba3P+/bi9VEdrMbNtAVKYpKhbODvqy+Q==", + "license": "MIT", + "dependencies": { + "vscode-jsonrpc": "9.0.0", + "vscode-languageserver-types": "3.18.0" + } + }, + "node_modules/vscode-languageserver-protocol/node_modules/vscode-jsonrpc": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-9.0.0.tgz", + "integrity": "sha512-+VvMmQPJhtvJ+8O+zu2JKIRiLxXF8NW7krWgyMGeOHrp4Cn23T5hc0v2LknNeopDOB70wghHAds7mKtcZ0I4Sg==", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/vscode-languageserver-types": { + "version": "3.18.0", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.18.0.tgz", + "integrity": "sha512-8TsGPNMIMiiBdkORgRSvLjuiEIiAFtO+KssmYWxQ+uSVvlf7RjK8YKCOjPzZ+YA04jXEV7+7LvkSmHkhpNS99g==", + "license": "MIT" + }, + "node_modules/vscode-ws-jsonrpc": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/vscode-ws-jsonrpc/-/vscode-ws-jsonrpc-1.0.2.tgz", + "integrity": "sha512-09OpRC0RcqZs4DleJRgs+R+7gQkwb4tgvsL43lzVZwW4N5NO3H/9sLNeKPBt83k7WyA8qBZjrzM6X7tKFpFrjQ==", + "license": "MIT", + "dependencies": { + "vscode-jsonrpc": "^8.0.2" + } + }, + "node_modules/vscode-ws-jsonrpc/node_modules/vscode-jsonrpc": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.1.tgz", + "integrity": "sha512-kdjOSJ2lLIn7r1rtrMbbNCHjyMPfRnowdKjBQ+mGq6NAW5QY2bEZC/khaC5OR8svbbjvLEaIXkOq45e2X9BIbQ==", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/w3c-keyname": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz", + "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==", + "license": "MIT" + }, + "node_modules/w3c-xmlserializer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz", + "integrity": "sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==", + "license": "MIT", + "dependencies": { + "xml-name-validator": "^4.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/watchpack": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.5.2.tgz", + "integrity": "sha512-6i/00NBjP4yGPs+caKSyRfpTF/8Torsu0MOW3mMzIbhgISFder8i7xbqgHlLMwJrdiN8ndBV3UA1/AfzPSr+jg==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/webpack": { + "version": "5.107.2", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.107.2.tgz", + "integrity": "sha512-v7RhXaJbpMlV0D7hC7lb2EbnxkoeUqf9qhKr6lozx3Q48pmFrqqNRmZFUEGmi7pSwm6fCQ2H1IjvCkHqdpVdjQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.8", + "@types/json-schema": "^7.0.15", + "@webassemblyjs/ast": "^1.14.1", + "@webassemblyjs/wasm-edit": "^1.14.1", + "@webassemblyjs/wasm-parser": "^1.14.1", + "acorn": "^8.16.0", + "acorn-import-phases": "^1.0.3", + "browserslist": "^4.28.1", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.22.0", + "es-module-lexer": "^2.1.0", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.11", + "loader-runner": "^4.3.2", + "mime-db": "^1.54.0", + "neo-async": "^2.6.2", + "schema-utils": "^4.3.3", + "tapable": "^2.3.0", + "terser-webpack-plugin": "^5.5.0", + "watchpack": "^2.5.1", + "webpack-sources": "^3.5.0" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-cli": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-5.1.4.tgz", + "integrity": "sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@discoveryjs/json-ext": "^0.5.0", + "@webpack-cli/configtest": "^2.1.1", + "@webpack-cli/info": "^2.0.2", + "@webpack-cli/serve": "^2.0.5", + "colorette": "^2.0.14", + "commander": "^10.0.1", + "cross-spawn": "^7.0.3", + "envinfo": "^7.7.3", + "fastest-levenshtein": "^1.0.12", + "import-local": "^3.0.2", + "interpret": "^3.1.1", + "rechoir": "^0.8.0", + "webpack-merge": "^5.7.3" + }, + "bin": { + "webpack-cli": "bin/cli.js" + }, + "engines": { + "node": ">=14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "5.x.x" + }, + "peerDependenciesMeta": { + "@webpack-cli/generators": { + "optional": true + }, + "webpack-bundle-analyzer": { + "optional": true + }, + "webpack-dev-server": { + "optional": true + } + } + }, + "node_modules/webpack-cli/node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/webpack-merge": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", + "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "clone-deep": "^4.0.1", + "flat": "^5.0.2", + "wildcard": "^2.0.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/webpack-sources": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.5.0.tgz", + "integrity": "sha512-HPuy+uuoTCaaoEoI1LQ3JN9+vrPBvEesnnX1jADHy728cHSMlq4wUc4afYqahq2B1mhQVZxCXOkNTnXltr+2vQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpack/node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/whatwg-encoding": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", + "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", + "deprecated": "Use @exodus/bytes instead for a more spec-conformant and faster implementation", + "license": "MIT", + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-mimetype": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", + "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-url": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", + "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", + "license": "MIT", + "dependencies": { + "tr46": "^3.0.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wildcard": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", + "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/worker-loader": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/worker-loader/-/worker-loader-3.0.8.tgz", + "integrity": "sha512-XQyQkIFeRVC7f7uRhFdNMe/iJOdO6zxAaR3EWbDp45v3mDhrTi+++oswKNxShUNjPC/1xUp5DB29YKLhFo129g==", + "dev": true, + "license": "MIT", + "dependencies": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/worker-loader/node_modules/ajv": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/worker-loader/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/worker-loader/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/worker-loader/node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/ws": { + "version": "8.21.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.0.tgz", + "integrity": "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xml-name-validator": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", + "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", + "license": "Apache-2.0", + "engines": { + "node": ">=12" + } + }, + "node_modules/xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "license": "MIT" + }, + "node_modules/y-protocols": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/y-protocols/-/y-protocols-1.0.7.tgz", + "integrity": "sha512-YSVsLoXxO67J6eE/nV4AtFtT3QEotZf5sK5BHxFBXso7VDUT3Tx07IfA6hsu5Q5OmBdMkQVmFZ9QOA7fikWvnw==", + "license": "MIT", + "dependencies": { + "lib0": "^0.2.85" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=8.0.0" + }, + "funding": { + "type": "GitHub Sponsors ❤", + "url": "https://github.com/sponsors/dmonad" + }, + "peerDependencies": { + "yjs": "^13.0.0" + } + }, + "node_modules/yjs": { + "version": "13.6.31", + "resolved": "https://registry.npmjs.org/yjs/-/yjs-13.6.31.tgz", + "integrity": "sha512-Eq+5BRfbeGyqGVrTJL3bEcr8gKkxPuyuoHmAwpk52fDb8kOVMrfVSTRPd6yiGgX5Fskb96qCRjzjbRjrL4YEnw==", + "license": "MIT", + "dependencies": { + "lib0": "^0.2.99" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=8.0.0" + }, + "funding": { + "type": "GitHub Sponsors ❤", + "url": "https://github.com/sponsors/dmonad" + } + } + } +} diff --git a/jupyterlab-extension/package.json b/jupyterlab-extension/package.json new file mode 100644 index 0000000..3554b1f --- /dev/null +++ b/jupyterlab-extension/package.json @@ -0,0 +1,48 @@ +{ + "name": "jjava-swing", + "version": "0.1.0", + "description": "Interactive Swing/AWT components for the JJava Jupyter kernel", + "keywords": [ + "jupyter", + "jupyterlab", + "jupyterlab-extension" + ], + "homepage": "https://github.com/dflib/jjava", + "license": "Apache-2.0", + "files": [ + "lib/**/*.{js,d.ts,js.map}", + "style/**/*.css", + "src/**/*.{ts,tsx}" + ], + "main": "lib/index.js", + "types": "lib/index.d.ts", + "style": "style/index.css", + "scripts": { + "build": "npm run build:lib && npm run build:labextension:dev", + "build:prod": "npm run clean && npm run build:lib:prod && npm run build:labextension", + "build:lib": "tsc --sourceMap", + "build:lib:prod": "tsc", + "build:labextension": "jupyter labextension build .", + "build:labextension:dev": "jupyter labextension build --development True .", + "clean": "rimraf lib tsconfig.tsbuildinfo jjava_swing/labextension", + "typecheck": "tsc --noEmit", + "watch": "tsc -w --sourceMap" + }, + "dependencies": { + "@jupyterlab/application": "^4.0.0", + "@jupyterlab/notebook": "^4.0.0", + "@jupyterlab/rendermime-interfaces": "^3.8.0", + "@jupyterlab/services": "^7.0.0", + "@lumino/widgets": "^2.0.0" + }, + "devDependencies": { + "@jupyterlab/builder": "^4.0.0", + "rimraf": "^5.0.0", + "typescript": "~5.4.0" + }, + "jupyterlab": { + "extension": "lib/plugin.js", + "mimeExtension": "lib/mimeExtension.js", + "outputDir": "jjava_swing/labextension" + } +} diff --git a/jupyterlab-extension/pyproject.toml b/jupyterlab-extension/pyproject.toml new file mode 100644 index 0000000..392c4a5 --- /dev/null +++ b/jupyterlab-extension/pyproject.toml @@ -0,0 +1,41 @@ +# Distribution as a prebuilt JupyterLab extension (a pip-installable wheel that drops the built assets under +# share/jupyter/labextensions/jjava-swing). Building the wheel requires a working JupyterLab build environment +# (Node.js + `pip install jupyterlab`), because the jupyter-builder hook runs the npm production build. +[build-system] +requires = ["hatchling>=1.5.0", "jupyterlab>=4.0.0,<5", "hatch-jupyter-builder>=0.5"] +build-backend = "hatchling.build" + +[project] +name = "jjava_swing" +version = "0.1.0" +description = "Interactive Swing/AWT components for the JJava Jupyter kernel" +readme = "README.md" +requires-python = ">=3.8" +license = "Apache-2.0" +classifiers = [ + "Framework :: Jupyter", + "Framework :: Jupyter :: JupyterLab", + "Framework :: Jupyter :: JupyterLab :: 4", + "Framework :: Jupyter :: JupyterLab :: Extensions", + "Framework :: Jupyter :: JupyterLab :: Extensions :: Prebuilt" +] +dependencies = [] + +[tool.hatch.build.targets.wheel.shared-data] +"jjava_swing/labextension" = "share/jupyter/labextensions/jjava-swing" +"install.json" = "share/jupyter/labextensions/jjava-swing/install.json" + +[tool.hatch.build.targets.wheel] +packages = ["jjava_swing"] + +[tool.hatch.build.hooks.jupyter-builder] +dependencies = ["hatch-jupyter-builder>=0.5"] +build-function = "hatch_jupyter_builder.npm_builder" +ensured-targets = [ + "jjava_swing/labextension/static/style.js", + "jjava_swing/labextension/package.json" +] + +[tool.hatch.build.hooks.jupyter-builder.build-kwargs] +build_cmd = "build:prod" +npm = ["npm"] diff --git a/jupyterlab-extension/src/canvas.ts b/jupyterlab-extension/src/canvas.ts new file mode 100644 index 0000000..0e13522 --- /dev/null +++ b/jupyterlab-extension/src/canvas.ts @@ -0,0 +1,177 @@ +import { Kernel, KernelMessage } from '@jupyterlab/services'; + +/** + * Owns the shown in a notebook output. It draws the PNG frames streamed by the kernel and forwards + * mouse/keyboard events back over the comm. + */ +export class CanvasController { + readonly element: HTMLDivElement; + + private readonly canvas: HTMLCanvasElement; + private readonly ctx: CanvasRenderingContext2D; + private comm: Kernel.IComm | null = null; + private buttonsDown = 0; + private pendingMove: MouseEvent | null = null; + + constructor(width: number, height: number) { + this.element = document.createElement('div'); + this.element.className = 'jjava-swing'; + + this.canvas = document.createElement('canvas'); + this.canvas.width = width; + this.canvas.height = height; + this.canvas.tabIndex = 0; // focusable, so it receives key events + this.canvas.className = 'jjava-swing-canvas'; + this.element.appendChild(this.canvas); + + const ctx = this.canvas.getContext('2d'); + if (!ctx) { + throw new Error('2D canvas context unavailable'); + } + this.ctx = ctx; + + this.wireEvents(); + } + + /** Bind the kernel comm and start receiving frames. */ + attachComm(comm: Kernel.IComm): void { + this.comm = comm; + comm.onMsg = (msg: KernelMessage.ICommMsgMsg) => this.onCommMsg(msg); + comm.onClose = () => { + this.comm = null; + }; + } + + dispose(): void { + if (this.comm && !this.comm.isDisposed) { + try { + this.comm.close(); + } catch { + /* ignore */ + } + } + this.comm = null; + } + + private onCommMsg(msg: KernelMessage.ICommMsgMsg): void { + const data = msg.content.data as { type?: string; w?: number; h?: number }; + if (!data || data.type !== 'frame' || !msg.buffers || msg.buffers.length === 0) { + return; + } + const buffer = msg.buffers[0]; + const bytes = buffer instanceof ArrayBuffer ? buffer : buffer.buffer; + this.drawFrame(bytes as ArrayBuffer, data.w ?? this.canvas.width, data.h ?? this.canvas.height); + } + + private drawFrame(buffer: ArrayBuffer, w: number, h: number): void { + const blob = new Blob([buffer], { type: 'image/png' }); + createImageBitmap(blob) + .then(bitmap => { + if (this.canvas.width !== w || this.canvas.height !== h) { + this.canvas.width = w; + this.canvas.height = h; + } + this.ctx.clearRect(0, 0, w, h); + this.ctx.drawImage(bitmap, 0, 0); + bitmap.close(); + }) + .catch(() => { + /* ignore decode errors */ + }); + } + + private send(payload: Record): void { + if (this.comm && !this.comm.isDisposed) { + // The comm wants a JSON value; our payloads are plain JSON objects. + this.comm.send(payload as never); + } + } + + private flushMove(): void { + const e = this.pendingMove; + this.pendingMove = null; + if (!e) { + return; + } + const p = this.point(e); + const action = this.buttonsDown > 0 ? 'drag' : 'move'; + this.send({ type: 'mouse', action, x: p.x, y: p.y, button: this.button(e), ...this.mods(e) }); + } + + private point(e: MouseEvent): { x: number; y: number } { + const rect = this.canvas.getBoundingClientRect(); + // The canvas may be displayed at a different size than its backing store (e.g. CSS max-width scaling), + // so map client coords back into the component's own pixel space. + const sx = rect.width > 0 ? this.canvas.width / rect.width : 1; + const sy = rect.height > 0 ? this.canvas.height / rect.height : 1; + return { x: Math.round((e.clientX - rect.left) * sx), y: Math.round((e.clientY - rect.top) * sy) }; + } + + private mods(e: MouseEvent | KeyboardEvent): Record { + return { shift: e.shiftKey, ctrl: e.ctrlKey, alt: e.altKey, meta: e.metaKey }; + } + + /** Map a browser mouse button (0 left, 1 middle, 2 right) to AWT's (1, 2, 3). */ + private button(e: MouseEvent): number { + return e.button === 1 ? 2 : e.button === 2 ? 3 : 1; + } + + private wireEvents(): void { + const c = this.canvas; + + c.addEventListener('mousedown', e => { + c.focus(); + this.buttonsDown++; + const p = this.point(e); + this.send({ type: 'mouse', action: 'down', x: p.x, y: p.y, button: this.button(e), clickCount: e.detail || 1, ...this.mods(e) }); + e.preventDefault(); + }); + + c.addEventListener('mouseup', e => { + this.buttonsDown = Math.max(0, this.buttonsDown - 1); + const p = this.point(e); + this.send({ type: 'mouse', action: 'up', x: p.x, y: p.y, button: this.button(e), clickCount: e.detail || 1, ...this.mods(e) }); + e.preventDefault(); + }); + + // Browsers fire mousemove 60-120x/s; coalesce to at most one message per animation frame (the latest position). + c.addEventListener('mousemove', e => { + const hadPending = this.pendingMove !== null; + this.pendingMove = e; + if (!hadPending) { + requestAnimationFrame(() => this.flushMove()); + } + }); + + c.addEventListener( + 'wheel', + e => { + const p = this.point(e); + this.send({ type: 'mouse', action: 'wheel', x: p.x, y: p.y, deltaY: e.deltaY, ...this.mods(e) }); + e.preventDefault(); + }, + { passive: false } + ); + + c.addEventListener('mouseleave', () => { + this.buttonsDown = 0; + this.flushMove(); + }); + + c.addEventListener('keydown', e => { + const printable = e.key.length === 1; + this.send({ type: 'key', action: 'down', keyCode: e.keyCode, char: printable ? e.key : '', ...this.mods(e) }); + if (printable) { + this.send({ type: 'key', action: 'press', char: e.key, ...this.mods(e) }); + } + e.preventDefault(); + }); + + c.addEventListener('keyup', e => { + this.send({ type: 'key', action: 'up', keyCode: e.keyCode, char: e.key.length === 1 ? e.key : '', ...this.mods(e) }); + e.preventDefault(); + }); + + c.addEventListener('contextmenu', e => e.preventDefault()); + } +} diff --git a/jupyterlab-extension/src/index.ts b/jupyterlab-extension/src/index.ts new file mode 100644 index 0000000..41328e6 --- /dev/null +++ b/jupyterlab-extension/src/index.ts @@ -0,0 +1,2 @@ +export { default } from './plugin'; +export { MIME_TYPE } from './mimeExtension'; diff --git a/jupyterlab-extension/src/mimeExtension.ts b/jupyterlab-extension/src/mimeExtension.ts new file mode 100644 index 0000000..39e8c59 --- /dev/null +++ b/jupyterlab-extension/src/mimeExtension.ts @@ -0,0 +1,65 @@ +import { IRenderMime } from '@jupyterlab/rendermime-interfaces'; +import { Widget } from '@lumino/widgets'; +import { CanvasController } from './canvas'; +import { registerCanvas, removeCanvas } from './registry'; + +export const MIME_TYPE = 'application/vnd.jjava.swing.v1+json'; + +interface ISwingModel { + token: string; + width?: number; + height?: number; +} + +/** The output widget: it mounts a canvas and registers it by token so the comm plugin can attach the kernel comm. */ +class SwingOutput extends Widget implements IRenderMime.IRenderer { + private token: string | null = null; + private controller: CanvasController | null = null; + + constructor() { + super(); + this.addClass('jjava-swing-output'); + } + + async renderModel(model: IRenderMime.IMimeModel): Promise { + if (this.controller) { + return; // already rendered once + } + const data = model.data[MIME_TYPE] as unknown as ISwingModel | undefined; + if (!data || !data.token) { + return; + } + this.token = String(data.token); + const width = Number(data.width) || 300; + const height = Number(data.height) || 150; + + this.controller = new CanvasController(width, height); + this.node.appendChild(this.controller.element); + registerCanvas(this.token, this.controller); + } + + dispose(): void { + if (this.token) { + removeCanvas(this.token); + } + if (this.controller) { + this.controller.dispose(); + } + super.dispose(); + } +} + +const rendererFactory: IRenderMime.IRendererFactory = { + safe: false, + mimeTypes: [MIME_TYPE], + createRenderer: () => new SwingOutput() +}; + +const extension: IRenderMime.IExtension = { + id: 'jjava-swing:mime', + rendererFactory, + rank: 0, + dataType: 'json' +}; + +export default extension; diff --git a/jupyterlab-extension/src/plugin.ts b/jupyterlab-extension/src/plugin.ts new file mode 100644 index 0000000..ec02bbe --- /dev/null +++ b/jupyterlab-extension/src/plugin.ts @@ -0,0 +1,42 @@ +import { JupyterFrontEnd, JupyterFrontEndPlugin } from '@jupyterlab/application'; +import { INotebookTracker, NotebookPanel } from '@jupyterlab/notebook'; +import { Kernel, KernelMessage } from '@jupyterlab/services'; +import { bindComm } from './registry'; + +const TARGET_NAME = 'jjava.swing.v1'; + +function registerOnKernel(kernel: Kernel.IKernelConnection | null | undefined): void { + if (!kernel) { + return; + } + kernel.registerCommTarget(TARGET_NAME, (comm, openMsg: KernelMessage.ICommOpenMsg) => { + const data = openMsg.content.data as { token?: string }; + const token = data && data.token ? String(data.token) : null; + if (token) { + bindComm(token, comm); + } + }); +} + +function wireNotebook(panel: NotebookPanel): void { + const sessionContext = panel.sessionContext; + void sessionContext.ready.then(() => registerOnKernel(sessionContext.session?.kernel)); + sessionContext.kernelChanged.connect((_, args) => registerOnKernel(args.newValue)); +} + +/** + * Registers the {@code jjava.swing.v1} comm target on every notebook kernel. The kernel opens this comm (carrying a + * token) when {@code displayInteractive(...)} runs; we hand the comm to the canvas that the mime renderer created for + * the same token. + */ +const plugin: JupyterFrontEndPlugin = { + id: 'jjava-swing:plugin', + autoStart: true, + requires: [INotebookTracker], + activate: (_app: JupyterFrontEnd, tracker: INotebookTracker) => { + tracker.forEach(wireNotebook); + tracker.widgetAdded.connect((_, panel) => wireNotebook(panel)); + } +}; + +export default plugin; diff --git a/jupyterlab-extension/src/registry.ts b/jupyterlab-extension/src/registry.ts new file mode 100644 index 0000000..611c843 --- /dev/null +++ b/jupyterlab-extension/src/registry.ts @@ -0,0 +1,34 @@ +import { Kernel } from '@jupyterlab/services'; +import { CanvasController } from './canvas'; + +/** + * Rendezvous between the mime renderer (which creates the canvas for a given token) and the comm plugin (which receives + * the kernel-opened comm for that token). The two can arrive in either order, so we hold whichever shows up first until + * its partner appears. + */ + +const canvases = new Map(); +const pendingComms = new Map(); + +export function registerCanvas(token: string, controller: CanvasController): void { + canvases.set(token, controller); + const comm = pendingComms.get(token); + if (comm) { + pendingComms.delete(token); + controller.attachComm(comm); + } +} + +export function removeCanvas(token: string): void { + canvases.delete(token); + pendingComms.delete(token); +} + +export function bindComm(token: string, comm: Kernel.IComm): void { + const controller = canvases.get(token); + if (controller) { + controller.attachComm(comm); + } else { + pendingComms.set(token, comm); + } +} diff --git a/jupyterlab-extension/style/index.css b/jupyterlab-extension/style/index.css new file mode 100644 index 0000000..d40e448 --- /dev/null +++ b/jupyterlab-extension/style/index.css @@ -0,0 +1,15 @@ +.jjava-swing-output { + padding: 2px; +} + +.jjava-swing { + display: inline-block; +} + +.jjava-swing-canvas { + display: block; + outline: none; + /* never overflow the output cell; scale down to fit if needed (click coords are scale-aware) */ + max-width: 100%; + height: auto; +} diff --git a/jupyterlab-extension/tsconfig.json b/jupyterlab-extension/tsconfig.json new file mode 100644 index 0000000..d13b376 --- /dev/null +++ b/jupyterlab-extension/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "target": "ES2018", + "module": "esnext", + "moduleResolution": "node", + "lib": ["ES2018", "DOM", "DOM.Iterable"], + "declaration": true, + "declarationMap": true, + "outDir": "lib", + "rootDir": "src", + "strict": true, + "noImplicitAny": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "skipLibCheck": true + }, + "include": ["src/*"] +}