UNPKG

@ndbx/runtime

Version:

The `@ndbx/runtime` package provides a runtime environment to embed NodeBox visualizations directly into React applications. NodeBox is a powerful tool for creating interactive and generative visualizations, and this runtime allows you to integrate those

129 lines (114 loc) 4.41 kB
import { expect, it } from "vitest"; import { findNodeStatements } from "../src/lexer"; function _find(s: string): string[] { const src = `export default function (node) {\n${s}\n}`; return findNodeStatements(src); } it("can find regular node statements", () => { const stmts = _find(`const xIn = node.numberIn({ name: "x" });`); expect(stmts).toEqual(['node.numberIn({ name: "x" })']); }); it("ignores node statements wrapped in a line comment", () => { const stmts = _find(`// const xIn = node.numberIn({ name: "x" });`); expect(stmts).toEqual([]); }); it("ignores node statements wrapped in a block comment", () => { const stmts1 = _find(`/* const xIn = node.numberIn({ name: "x" }); */`); expect(stmts1).toEqual([]); const stmts2 = _find(`/* const xIn = node.numberIn({ name: "x" }); */\nconst yIn = node.numberIn({ name: "y" });`); expect(stmts2).toEqual(['node.numberIn({ name: "y" })']); }); it("supports longer statements", () => { const source = ` /** * Translate, rotate and/or scale a set of shapes. * * This node takes shapes and applies a transformation to each shape. * The transformation is defined by the translation, rotation and scale parameters. */ import { Transform } from "@ndbx/g"; export default function (node) { const shapeIn = node.shapeIn({ name: "shapes" }); const txIn = node.numberIn({ name: "translate x", value: 0 }); const tyIn = node.numberIn({ name: "translate y", value: 0 }); const rotateIn = node.numberIn({ name: "rotate", value: 0 }); const sxIn = node.numberIn({ name: "scale x", value: 1, step: 0.01 }); const syIn = node.numberIn({ name: "scale y", value: 1, step: 0.01 }); const shapeOut = node.shapeOut({ name: "out" }); node.onRender = () => { const [tx, ty, r, sx, sy] = [txIn.value, tyIn.value, rotateIn.value, sxIn.value, syIn.value]; const shape = shapeIn.value; if (!shape) { shapeOut.set([]); return; } const transform = new Transform(); transform .scale(sx, sy) .rotate((r * Math.PI) / 180) .translate(tx, ty); const newShape = shape.clone(); newShape.applyTransform(transform); shapeOut.set(newShape); }; } "`; const stmts = findNodeStatements(source); expect(stmts).toEqual([ 'node.shapeIn({ name: "shapes" })', 'node.numberIn({ name: "translate x", value: 0 })', 'node.numberIn({ name: "translate y", value: 0 })', 'node.numberIn({ name: "rotate", value: 0 })', 'node.numberIn({ name: "scale x", value: 1, step: 0.01 })', 'node.numberIn({ name: "scale y", value: 1, step: 0.01 })', 'node.shapeOut({ name: "out" })', ]); }); it("supports sections", () => { const stmts1 = _find(`node.pushSection("Test");`); expect(stmts1).toEqual(['node.pushSection("Test")']); const stmts2 = _find(`node.popSection();`); expect(stmts2).toEqual(["node.popSection()"]); }); it("handles nested objects and arrays", () => { const stmts = _find( `const complexIn = node.objectIn({ name: "complex", value: { arr: [1, 2, 3], obj: { a: 1, b: 2 } } });`, ); expect(stmts).toEqual(['node.objectIn({ name: "complex", value: { arr: [1, 2, 3], obj: { a: 1, b: 2 } } })']); }); it("handles multi-line statements", () => { const source = ` const multiLineIn = node.numberIn({ name: "multi-line", value: 0, min: -10, max: 10 });`; const stmts = _find(source); expect(stmts).toEqual(['node.numberIn({\n name: "multi-line",\n value: 0,\n min: -10,\n max: 10\n })']); }); it("handles statements with no spaces", () => { const stmts = _find(`const noSpaceIn=node.booleanIn({name:"no-space"});`); expect(stmts).toEqual(['node.booleanIn({name:"no-space"})']); }); it("handles multiple statements in succession", () => { const stmts = _find(` const a = node.numberIn({ name: "a" });const b = node.numberIn({ name: "b" }); const c = node.numberIn({ name: "c" }); `); expect(stmts).toEqual([ 'node.numberIn({ name: "a" })', 'node.numberIn({ name: "b" })', 'node.numberIn({ name: "c" })', ]); }); it("ignores node.onRender statements", () => { const stmts = _find(` const x = node.numberIn({ name: "x" }); node.onRender = () => { console.log("Rendering"); }; const y = node.numberIn({ name: "y" }); `); expect(stmts).toEqual(['node.numberIn({ name: "x" })', 'node.numberIn({ name: "y" })']); });