From 6f3df30b01ac566bd7169459997362e71cb9483f Mon Sep 17 00:00:00 2001 From: Duane Nykamp Date: Wed, 30 Oct 2024 01:19:42 -0500 Subject: [PATCH] inverse definition of text will attempt to update a composite-generated list --- .../src/components/MathInput.js | 1 + .../src/components/MathList.js | 1 - .../doenetml-worker/src/components/Text.js | 39 +++++ .../src/components/TextInput.js | 1 + .../src/test/tagSpecific/boolean.test.ts | 2 +- .../src/test/tagSpecific/callAction.test.ts | 99 +++++++------ .../src/test/tagSpecific/mathlist.test.ts | 41 ++++++ .../src/test/tagSpecific/numberlist.test.ts | 135 +++++++++++++++++- .../src/test/tagSpecific/text.test.ts | 6 +- .../src/test/tagSpecific/textinput.test.ts | 10 +- .../src/test/tagSpecific/textlist.test.ts | 40 ++++++ .../src/test/tagSpecific/triggerset.test.ts | 14 +- packages/doenetml-worker/src/utils/label.js | 9 +- 13 files changed, 326 insertions(+), 72 deletions(-) diff --git a/packages/doenetml-worker/src/components/MathInput.js b/packages/doenetml-worker/src/components/MathInput.js index a7bec2a08..77e592ed0 100644 --- a/packages/doenetml-worker/src/components/MathInput.js +++ b/packages/doenetml-worker/src/components/MathInput.js @@ -147,6 +147,7 @@ export default class MathInput extends Input { sugarInstructions.push({ replacementFunction: returnWrapNonLabelsSugarFunction({ wrappingComponentType: "math", + wrapSingleIfNotWrappingComponentType: true, }), }); diff --git a/packages/doenetml-worker/src/components/MathList.js b/packages/doenetml-worker/src/components/MathList.js index b17691e2e..65ce2e8f0 100644 --- a/packages/doenetml-worker/src/components/MathList.js +++ b/packages/doenetml-worker/src/components/MathList.js @@ -277,7 +277,6 @@ export default class MathList extends CompositeComponent { }; stateVariableDefinitions.maths = { - public: true, shadowingInstructions: { createComponentOfType: "math", }, diff --git a/packages/doenetml-worker/src/components/Text.js b/packages/doenetml-worker/src/components/Text.js index 8ec308677..bc1e9908d 100644 --- a/packages/doenetml-worker/src/components/Text.js +++ b/packages/doenetml-worker/src/components/Text.js @@ -169,9 +169,48 @@ export default class Text extends InlineComponent { dependencyValues, }) { let numChildren = dependencyValues.textLikeChildren.length; + if (numChildren > 1) { + // if have multiple children, then we could still update them if + // 1. all children come from a single composite with asList set to true, and + // 2. the desired value is a comma-separated list with the number of entries + // matching the number of children. + // In that case, we will attempt to update each child to the corresponding entry + // from the desired value. + + // Check if all text children are from a composite with asList set to true + let foundAllFromListComposite = false; + for (let range of dependencyValues.textLikeChildren + .compositeReplacementRange) { + if ( + range.asList && + range.firstInd === 0 && + range.lastInd === numChildren - 1 + ) { + foundAllFromListComposite = true; + } + } + + if (foundAllFromListComposite) { + // Check if desired value is a comma-separated list with the same number of entries as children + let splitValues = desiredStateVariableValues.value + .split(",") + .map((v) => v.trim()); + + if (splitValues.length === numChildren) { + // All conditions are met, so we attempt to update the children + let instructions = splitValues.map((v, i) => ({ + setDependency: "textLikeChildren", + desiredValue: v, + childIndex: i, + variableIndex: 0, + })); + return { success: true, instructions }; + } + } return { success: false }; } + if (numChildren === 1) { return { success: true, diff --git a/packages/doenetml-worker/src/components/TextInput.js b/packages/doenetml-worker/src/components/TextInput.js index bd2c4b624..8f801059e 100644 --- a/packages/doenetml-worker/src/components/TextInput.js +++ b/packages/doenetml-worker/src/components/TextInput.js @@ -101,6 +101,7 @@ export default class Textinput extends Input { sugarInstructions.push({ replacementFunction: returnWrapNonLabelsSugarFunction({ wrappingComponentType: "text", + wrapSingleIfNotWrappingComponentType: true, }), }); diff --git a/packages/doenetml-worker/src/test/tagSpecific/boolean.test.ts b/packages/doenetml-worker/src/test/tagSpecific/boolean.test.ts index 549a14acd..26188e1e2 100644 --- a/packages/doenetml-worker/src/test/tagSpecific/boolean.test.ts +++ b/packages/doenetml-worker/src/test/tagSpecific/boolean.test.ts @@ -1009,7 +1009,7 @@ describe("Boolean tag tests", async () => { isSupersetCaseInsensitive: false, }, { - set1: "a, c", + set1: "a, c", set2: "", isSubset: true, isSubsetCaseInsensitive: true, diff --git a/packages/doenetml-worker/src/test/tagSpecific/callAction.test.ts b/packages/doenetml-worker/src/test/tagSpecific/callAction.test.ts index 924bec46a..4d6910e7d 100644 --- a/packages/doenetml-worker/src/test/tagSpecific/callAction.test.ts +++ b/packages/doenetml-worker/src/test/tagSpecific/callAction.test.ts @@ -5,7 +5,6 @@ import { updateBooleanInputValue, updateMathInputValue, } from "../utils/actions"; -import me from "math-expressions"; const Mock = vi.fn(); vi.stubGlobal("postMessage", Mock); @@ -18,7 +17,7 @@ describe("callAction tag tests", async () => { let numbers = stateVariables["/nums"].stateValues.text .split(",") .map(Number); - expect(numbers.length).eq(5); + expect(numbers.length).eq(7); for (let [ind, num] of numbers.entries()) { expect(Number.isInteger(num)).be.true; expect(num).gte(1); @@ -42,7 +41,7 @@ describe("callAction tag tests", async () => { .split(",") .map(Number); - expect(numbers2.length).eq(5); + expect(numbers2.length).eq(7); for (let num of numbers2) { expect(Number.isInteger(num)).be.true; expect(num).gte(1); @@ -54,7 +53,7 @@ describe("callAction tag tests", async () => { it("resample random numbers", async () => { let core = await createTestCore({ doenetML: ` -

+

@@ -373,7 +372,7 @@ describe("callAction tag tests", async () => { let numbers = stateVariables["/nums"].stateValues.text .split(",") .map(Number); - expect(numbers.length).eq(5); + expect(numbers.length).eq(7); for (let num of numbers) { expect(Number.isInteger(num)).be.true; expect(num).gte(1); @@ -424,7 +423,7 @@ describe("callAction tag tests", async () => { .split(",") .map(Number); - expect(numbers2.length).eq(5); + expect(numbers2.length).eq(7); for (let num of numbers2) { expect(Number.isInteger(num)).be.true; expect(num).gte(1); @@ -436,7 +435,7 @@ describe("callAction tag tests", async () => { it("chained actions", async () => { let core = await createTestCore({ doenetML: ` -

+

@@ -461,7 +460,7 @@ describe("callAction tag tests", async () => { it("chained actions, unnecessary $", async () => { let core = await createTestCore({ doenetML: ` -

+

@@ -488,7 +487,7 @@ describe("callAction tag tests", async () => { doenetML: `